Σημείωση: μετά την δημοσίευση, ίσως χρειαστεί να παρακάμψετε την προσωρινή μνήμη του προγράμματος περιήγησής σας για να δείτε τις αλλαγές.

  • Firefox / Safari: Κρατήστε πατημένο το Shift κάνοντας ταυτόχρονα κλικ στο κουμπί Ανανέωση ή πιέστε Ctrl-F5 ή Ctrl-R (⌘-R σε Mac)
  • Google Chrome: Πιέστε Ctrl-Shift-R (⌘-Shift-R σε Mac)
  • Edge: Κρατήστε πατημένο το Ctrl κάνοντας ταυτόχρονα κλικ στο κουμπί Ανανέωση, ή πιέστε Ctrl-F5
  • Opera: Πιέστε Ctrl-F5.
  • Opera: Πιέστε Ctrl-F5.
/******************************************************************    Listing Editor v1.4.2 (torty3)      - numerous customizations added ********************************************************************/  ( function ( mw, $ ) {     'use strict';     // only run on supported skins 	// (on mobile this breaks section collapsing) 	if ( mw.config.get( 'skin' ) === 'minerva' ) { 		return; 	}      var namespace = mw.config.get( 'wgNamespaceNumber' );     if (namespace != 0 && namespace != 2 && namespace != 4) {         return;     }      if ( mw.config.get('wgAction') != 'view' || $('#mw-revision-info').length             || mw.config.get('wgCurRevisionId') != mw.config.get('wgRevisionId')             || $('#ca-viewsource').length ) {         return;     }      var allFields = {         'type': {size:8, right:true, newline:true, parameter:'type', label:'Type', tip:'type of listing' },         'name': {size:36, right:false, newline:false, parameter:'name', label:'Name', tip:'name of place'},         'alt': {size:32, right:false, newline:false, parameter:'alt', label:'Alt', tip:'also known as'},         'url': {size:36, right:false, newline:false, parameter:'url', label:'Website', tip:'http://www.example.com'},         'email': {size:32, right:true, newline:true, parameter:'email', label:'Email', tip:'[email protected]'},         'address': {size:36, right:false, newline:false, parameter:'address', label:'Address', tip:'address of place'},         'lat': {size:10, right:true, newline:false, parameter:'lat', label:'Latitude', tip:'11.11111'},         'long': {size:10, right:true, newline:false, parameter:'long', label:'Longitude', tip:'111.11111'},         'directions': {size:36, right:false, newline:true, parameter:'directions', label:'Directions', tip:'how to get here'},         'phone': {size:24, right:false, newline:false, parameter:'phone', label:'Phone', tip: '+55 555 555-5555'},         'tollfree': {size:20, right:false, newline:false, parameter:'tollfree', label:'Tollfree', tip:'+1 800 100 1000'},         'fax': {size:20, right:true, newline:true, parameter:'fax', label:'Fax', tip: '+55 555 555-555'},         'image': {size:20, right:true, newline:true, parameter:'image', label:'Image', tip: 'image of place'},         'hours': {size:28, right:true, newline:false, parameter:'hours', label:'Hours', tip: '9AM-5PM or 09:00-17:00'},         'checkin': {size:12, right:true, newline:false, parameter:'checkin', label:'Check-in', tip: 'check in time'},         'checkout': {size:12, right:true, newline:false, parameter:'checkout', label:'Check-out', tip: 'check out time'},         'price': {size:28, right:true, newline:true, parameter:'price', label:'Price', tip: 'entry or service price'},         'lastedit': {size:10, right:false, newline:true, parameter:'lastedit', label:'Last Updated', tip: '2015-01-15'},         'content': {cols:34, rows:8, right:false, newline:true, parameter:'content', label:'Content', tip: 'description of place'}     };      var currencySigns = ['\u00A3', '\u20AC', '\u00A5', '\u20A9'];     var listingTypes = {'see':'see', 'do':'do', 'buy':'buy', 'eat':'eat', 'drink':'drink', 'sleep':'sleep', 'listing':'listing'};     var sectionHeadings = {'See':'see', 'Do':'do', 'Buy':'buy', 'Eat':'eat', 'Drink':'drink', 'Sleep':'sleep', 'Connect':'listing', 'Wait':'see', 'See_and_Do':'see', 'Eat_and_Drink':'eat'};     var LICENSE_TEXT = 'By clicking "Submit", you agree to the <a class="external" target="_blank" href="http://wikimediafoundation.org/wiki/Terms_of_use">Terms of use</a>, and you irrevocably agree to release your contribution under the <a class="external" target="_blank" href="http://en.wikivoyage.org/wiki/Wikivoyage:Full_text_of_the_Attribution-ShareAlike_3.0_license">CC-BY-SA 3.0 License</a>.'     var translateStr = {         'add': 'add listing',         'edit': 'edit',         'closed': 'Closed?',         'closed-title': 'Check the box if the business is no longer in operation, and it will be removed from this article',         'verified': 'Verified information up-to-date?',         'verified-title': 'Check the box if the information in this listing has been verified to be current and accurate, and the last updated date will be changed to the current date',         'saving': 'Saving',         'submit': 'Submit',         'cancel': 'Cancel',         'validationalert': 'Please enter either a name or an address',         'added': 'Added listing for ',         'updated': 'Updated listing for ',         'removed': 'Closed listing for ',         'cities': 'Cities',         'destination': 'Other_destinations',         'geomap': 'locate on geomap',         'help-page': 'http://en.wikivoyage.org/wiki/Wikivoyage:Listing_editor',         'enter-captcha': 'Enter CAPTCHA',         'external-links': 'Your edit includes new external links.'     };      var EDIT_LINK_CONTAINER = 'span.vcard span.listing-metadata-items';     var LISTING_CONTAINER = 'span.vcard';      var sectionText, listingText, inlineListing;      wrapContent();     addListingButtons();     addEditButtons();      // makes it easier to traverse the DOM - but potential for code incompatibility     function wrapContent() {         $('h2').each(function(){             $(this).nextUntil("h2").addBack().wrapAll('<div class="mw-h2section" />');         });     }      function addListingButtons () {         if ($('#'+translateStr['cities']).length || $('#'+translateStr['destination']).length || $('#'+'Islands').length || $('#'+'print-districts').length) {             return false;         }         var editButton = $('<span class="mw-addlisting noprint">')             .html('&nbsp;[<a href="javascript:">'+translateStr['add']+'</a>]' )             .click(function() {                 var listingEntry = $(this).parent();                 popupForm('add', listingEntry);             });          for (var key in sectionHeadings) {             key = encodeURIComponent(key).replace(/%20/g,'_').replace(/%/g,'.');             $(document.getElementById(key)).parent('h2').addClass('mw-addhere');             $(document.getElementById(key)).closest('div.mw-h2section').children('h3').addClass('mw-addhere');         }         $('.mw-addhere').append(editButton);     }      function addEditButtons () {         var editButton = $('<span class="vcard-edit-button noprint">')             .html('<a href="javascript:">'+translateStr['edit']+'</a>' )             .click(function() {                 var listingEntry = $(this).closest(LISTING_CONTAINER);                 popupForm('edit', listingEntry);             });             // if there is already metadata present add a separator             $(EDIT_LINK_CONTAINER).each(function() {                 if (!isElementEmpty(this)) {                     $(this).append('&nbsp;|&nbsp;');                 }             });             // append the edit link             $(EDIT_LINK_CONTAINER).append( editButton );     }      function isInline(entry) {         if (entry.parent('p').length == 0) return false;         return true;     }      function findSectionNumber(entry) {         var link = entry.find( '.mw-editsection a' ).attr( 'href' );         if (link === undefined) link = entry.closest('div.mw-h2section').find( '.mw-editsection a' ).attr( 'href' );         if (link != undefined) return link.split( '=' ).pop();         return 0;     }      function findSectionType(entry) {         var section = entry.closest('div.mw-h2section').children('h2').find('.mw-headline').attr('id');         for (var key in sectionHeadings) {             if (section == key) return sectionHeadings[key];         }         return listingTypes.listing;     }      function getSectionText(number) {         var wikiText = $.ajax({             url: mw.util.wikiScript(''),             data: { title:mw.config.get('wgPageName'), action:'raw', section:number },             async: false,             cache: false // required         }).responseText;         return wikiText;     }      function replaceSpecial( str ) {       return str.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");     }      function getListingWikitextBraces(entry) {         sectionText = sectionText.replace(/[^\S\n]+/g,' ');         // search the HTML to get the index of the listing being edited         var parent = $(entry.parentsUntil('.mw-h2section').parent()[0]);         var cnt = 0;         parent.find('.vcard').each( function(){             if ($(entry[0]).is($(this))) {                 return false;             }             cnt++;         });         // now find the listing wikitext that matches the same index         var regex = []         for (var key in listingTypes) {             regex.push(key);         }         var listingRegex = new RegExp("{{\\s*(" + regex.join('|') + ')','g');         var matches = sectionText.match(listingRegex);         var string = matches[cnt];         var parttxt = sectionText;         var index = 0;         for (var i = 0; i < cnt; i++) {             index += parttxt.indexOf(matches[i])+matches[i].length+1;             parttxt = parttxt.slice(parttxt.indexOf(matches[i])+matches[i].length+1);         }         index += parttxt.indexOf(matches[cnt]);         // listings may contain nested templates, so check for MATCHING closing         // braces for this listing         var curly = 2;         var str1 = '', str2 = '';          // search for open and close braces         for (var i=index; i>0; i--) {             if (sectionText[i]=='}') ++curly;             else if (sectionText[i]=='{') --curly;             if(curly == 0) {                 str1 = sectionText.substr(i,index-i);                 break;             }         }         if (string.indexOf('}}') < 0) curly = 2;         var textLength = sectionText.length;         for (var j=index+string.length; j<textLength; j++) {             if (sectionText[j]=='{') ++curly;             else if (sectionText[j]=='}') --curly;             if (curly == 0) {                 str2 = sectionText.substr(index, j-index+1);                 break;             }         }         if (str2 === '') str2 = sectionText.substr(index, textLength);         string = str1 + str2;         return $.trim(string);     }      function wikiTextToListing(string) {         var typeRegex = new RegExp('{{('+listingTypes['see']+'|'+listingTypes['do']                     +'|'+listingTypes['buy'] +'|'+listingTypes['eat'] + '|'+listingTypes['drink']                     +'|'+listingTypes['sleep']+'|'+listingTypes['listing']+')','g');         string = string.slice(0,-2);         string = string.replace(typeRegex,'{{listing| '+allFields['type']['parameter']+'=$1');         string = string.replace(/{{vCard/g,'{{listing');          var listing = {};         var lastKey;         var listParams = string.split('|');         for (var j=1;j<listParams.length;j++) {             var param = listParams[j];             var index = param.indexOf('=');             if (index > 0) {                 var key = $.trim(param.substr(0, index));                 var value = $.trim(param.substr(index+1));                 listing[key] = value;                 lastKey = key;             }             else if (listing[lastKey].length) {                 listing[lastKey] += '|' + param;             }         }         return listing;     }      function getListing (entry) {         listingText = getListingWikitextBraces(entry);         var listing = wikiTextToListing(listingText);         return listing;     }      /*** Functions to handle form creation and editing ***/     function popupForm(mode, entry) {       mw.loader.using( ['jquery.ui'], function () {         var sectionType, listing;         var sectionNumber = findSectionNumber(entry);         inlineListing = isInline(entry);         sectionText = getSectionText(sectionNumber);          if (mode == 'add') {             sectionType = findSectionType(entry);             listing = {};         }         else {             sectionType = '';             listing = getListing(entry);         }          var form = $(createForm(mode, sectionType, listing));          // modal form - must submit or cancel         form.dialog({             modal: true,             height: 'auto',             width: 'auto',             title: translateStr[mode],             buttons: [                 {   text: '?',                     id: 'listing-help',                     click: function() { window.open(translateStr['help-page']);}},                 {   text: translateStr['submit'], click: function() {                         if(validateForm()) {                             formToText(mode, sectionNumber);                             $(this).dialog('close');                         }                     }                 },                 {text: translateStr['cancel'], click: function() {$(this).dialog('destroy').remove()}}             ],             open: function() {                 $('.ui-dialog-buttonpane').append('<div style="width:320px;padding-top:0.8em;font-size:xx-small;">'+LICENSE_TEXT+'</div>');                 if ($('#input-address').val() != '') {                     $('#geomap-link').attr('href', $('#geomap-link').attr('href') + '&location='                                 + encodeURIComponent($('#input-address').val()));                 }                 else if ($('#input-name').val() != '') {                     $('#geomap-link').attr('href', $('#geomap-link').attr('href') + '&location='                                 + encodeURIComponent($('#input-name').val()));                 }                 $('#input-address').change( function () {                     var link = $('#geomap-link').attr('href');                     var index = link.indexOf('&location');                     if (index < 0) index = link.length;                     $('#geomap-link').attr('href', link.substr(0,index) + '&location='                         + encodeURIComponent($('#input-address').val()));                 });             },             close: function() { $(this).dialog('destroy').remove()}         });       });     }      function createForm(mode, type, listing) {          var form = $('<form id="listing-editor">');          var leftFields = $('<fieldset id="left-fields">').appendTo(form);         var rightFields = $('<fieldset id="right-fields">').appendTo(form);         $('<div style="clear:both">').appendTo(form);          //create form according to fields         for (var key in allFields) {             var keyvalue = allFields[key];             var node = $('<div class="input-text">')                 .attr('id', 'div_' + key);              var label = $('<label>').appendTo(node)                 .text(keyvalue['label'])                 .attr('for', 'input-' + key);              // input text for everything except content which gets textarea             var parameter = keyvalue['parameter'];              if (key == 'type') {                 var subnode = $('<select id="option-type">').appendTo(node);                 for (var n in listingTypes) {                     var option = $('<option value="'+listingTypes[n]+'">');                     option.text(listingTypes[n]).appendTo(subnode);                 }                 if (mode == 'add') {                     subnode.val(listingTypes[type]);                     listing[parameter] = listingTypes[type];                 }             }             else if (key != 'content') {                 var subnode = $('<input type="text">').appendTo(node)                     .attr('size', keyvalue['size']);             }             else {                 var subnode = $('<textarea>').appendTo(node)                     .attr('cols', keyvalue['cols'])                     .attr('rows', keyvalue['rows']);             }              subnode.attr('placeholder', keyvalue['tip'])                    .attr('id', 'input-' + key);              if (listing[parameter]) {                 subnode.val(listing[parameter]);             }              // customise hiding parameters             if (listing[allFields['type']['parameter']] == listingTypes['sleep']) {                 // sleep listings display checkin/checkout instead of hours                 if (key == 'hours') {                     node.hide();                 }             } else {                 // non-sleep listings display hours instead of checkin/checkout                 if (key == 'checkin' || key == 'checkout') {                     node.hide();                 }             }             if (key == 'fax' || key == 'image' || key == 'lastedit') node.hide();              // some special form features             if (key == 'type' && mode == 'edit') {                 var closedSpan = $('<span id="span_closed">');                 var closedLabel = $('<label for="input-closed" title="' + translateStr['closed-title'] + '">').appendTo(closedSpan)                     .text(translateStr['closed']);                 var closedInput = $('<input type="checkbox">').appendTo(closedSpan)                     .attr('id', 'input-closed');                 node.append(closedSpan);             }             if (key == 'price') {                 var currencySpan = $('<span id="span_currency">');                 for (var i=0; i < currencySigns.length; i++) {                     var currencyButton = $('<span class="currency-signs">')                         .html('&#32;<u><a href="javascript:">'+currencySigns[i]+'</a></u>' )                         .click(function() {                             var caretPos = document.getElementById('input-price').selectionStart;                             var price = $('#input-price').val();                             $('#input-price').val(price.substring(0, caretPos)                                         + $(this).find('a').text() + price.substring(caretPos) );                         });                     currencySpan.append(currencyButton);                 }                 node.append(currencySpan);             }             if (key == 'lat') {                 var latlngStr = '?';                 if ($('#geodata').length) {                     var latlng = $('#geodata').text().split('; ');                     latlngStr += 'lat='+latlng[0]+'&lon='+latlng[1]+'&zoom=15';                 }                 node.append('&nbsp;<u><a id="geomap-link" target="_blank" '                     +'href="http://maps.wikivoyage-ev.org/w/geomap.php'+latlngStr+'">'                     +translateStr['geomap']+'</a></u>');             }              if (key == 'content') {                 form.append(node);             }             else if (allFields[key]['right'] == true) {                 rightFields.append(node);             }             else {                 leftFields.append(node);             }         }         if (mode == 'edit') {             var verifiedDiv = $('<div id="div_verified">');             var verifiedLabel = $('<label for="input-verified" title="' + translateStr['verified-title'] + '">').appendTo(verifiedDiv).text(translateStr['verified']);             var verifiedInput = $('<input type="checkbox">').appendTo(verifiedDiv).attr('id', 'input-verified');             form.append(verifiedDiv);         }         return form;     }      function validateForm() {         //TODO more form validation?         if ($('#input-name').val() == '' && $('#input-address').val() == '' && $('#input-alt').val() == '') {             alert(translateStr['validationalert']);             return false;         }         $('#input-content').val($.trim($('#input-content').val()).replace(/\n+/g, ' '));         var webRegex = new RegExp('^https?://', 'i');         var url = $('#input-url').val();         if (!webRegex.test(url) && url != '') {             $('#input-url').val('http://' + url);         }         return true;     }      function upperCaseFirst(str) {         str = str.toLowerCase().replace(/\b[a-z]/g, function(letter) {             return letter.toUpperCase();         });         return str;     }      function formToText(mode, number) {         var listing = {};         for ( var key in allFields ) {             var parameter = allFields[key]['parameter'];             listing[parameter]= $("#input-"+key).val();         }          if (listing[allFields['type']['parameter']] != listingTypes.sleep) {             listing[allFields['checkin']['parameter']] = null;             listing[allFields['checkout']['parameter']] = null;         }         else {             listing[allFields['hours']['parameter']] = null;         }         // only update last edit date if this is a new listing or if the "information up-to-date" box checked         if (mode == 'add' || $('#input-verified').is(':checked')) {             listing[allFields['lastedit']['parameter']] = currentLastEditDate();         }         var text = listingToStr(listing);          var summary = '/* ' +upperCaseFirst($("#input-type").val()) + ' */ ';         if (mode == 'add') {             summary += translateStr['added'];             var index = sectionText.indexOf('===');             if ( index == 0 ) {                 index = sectionText.indexOf('====');             }              if ( index > 0 ) {                 sectionText = sectionText.substr(0, index) + '* ' + text                         + '\n' + sectionText.substr(index);             }             else {                 sectionText += '\n'+ '* ' +text;             }         }         else {             if ($('#input-closed').is(':checked')) {                 text = '';                 summary += translateStr['removed'];                 var listRegex = new RegExp('\\n\\*+\\s?'+replaceSpecial(listingText));                 sectionText = sectionText.replace(listRegex, listingText);             }             else {                 summary += translateStr['updated'];             }             sectionText = sectionText.replace(listingText, text);         }         summary += $("#input-name").val();         saveForm(summary, sectionText, number, '', '');         return;     }      function savingForm() {         var progress = $('<div id="progress-dialog">'+translateStr['saving']+'...</div>');         progress.dialog({             modal: true,             height: 100,             width: 300,             title: ''         });         $(".ui-dialog-titlebar").hide();     }      function saveForm(summary, content, number, cid, answer) {         $.ajax( {             url: mw.util.wikiScript( 'api' ),             data: {                 'format': 'json',                 'action': 'edit',                 'title': mw.config.get('wgPageName'),                 'section': number,                 'token': mw.user.tokens.get( 'csrfToken' ),                 'text': content,                 'summary': summary,                 'captchaid': cid,                 'captchaword': answer             },             type: 'POST',             datatype: 'json',             success: function( data ) {                 if ( data && data.edit && data.edit.result == 'Success' ) {                   window.location.reload(); // reload page if edit was successful                 } else if ( data && data.error ) {                     alert( 'Error: API returned error code "' + data.error.code + '": ' + data.error.info );                     $(".progress-dialog").hide();                     $(".ui-dialog-titlebar").show();                 } else if ( data && data.edit.spamblacklist ) {                     alert( 'Error: "'+ data.edit.spamblacklist + '" has been blacklisted' );                     $('#progress-dialog').dialog('destroy').remove();                 } else if ( data && data.edit.captcha ) {                     var captcha = $('<div id="captcha-dialog">').text(translateStr['external-links']);                     var image = $('<img class="fancycaptcha-image">')                         .attr('src', data.edit.captcha.url)                         .appendTo(captcha);                     var label = $('<label for="input-captcha">').text(translateStr['enter-captcha']).appendTo(captcha);                     var input = $('<input id="input-captcha" type="text">').appendTo(captcha);                     captcha.dialog({                         title: translateStr['enter-captcha'],                         buttons: [                             {   text: translateStr['submit'], click: function() {                                     saveForm(summary, content, number, data.edit.captcha.id, $('#input-captcha').val());                                     }                             },                             {   text: translateStr['cancel'], click: function() {                                     $(this).dialog('destroy').remove();                                     $('#progress-dialog').dialog('destroy').remove();                             }}                         ]                     });                 } else {                     alert( 'Error: Unknown result from API.' );                 }             },             error: function( xhr ) {                 alert( 'Error: Request failed.' );             }         } )         savingForm();     }    function listingToStr(listing) {     var saveStr = '{{'+listing[allFields['type']['parameter']];     if (!inlineListing && allFields['type']['newline']) saveStr += '\n';     for ( var key in allFields ) {         var parameter = allFields[key]['parameter'];         if (key != 'type' && listing[parameter] != null) {             if (inlineListing) {                 if (listing[parameter] != '') {                     saveStr += ' | ' + parameter + '=' +listing[parameter];                 }             }             else {                 if (key == 'image' && listing[allFields['image']['parameter']] == '') {                     // image parameter is empty, don't include in listing                     continue;                 }                 if (key == 'lastedit' && listing[allFields['lastedit']['parameter']] == '') {                     // lastedit parameter is empty, don't include in listing                     continue;                 }                 saveStr +='| '+parameter+ '=' + listing[parameter];                 if (allFields[key]['newline']) {                     saveStr += '\n';                 }                 else {                     saveStr += ' ';                 }             }         }     }     saveStr += '}}';     return saveStr;   }    function currentLastEditDate() {     // return the date as "2015-01-15"     var d = new Date();     var year = d.getFullYear();     // Date.getMonth() returns 0-11     var month = d.getMonth() + 1;     if (month < 10) month = '0' + month;     var day = d.getDate();     if (day < 10) day = '0' + day;     return year + '-' + month + '-' + day;   }    function isElementEmpty(element) {     var text = $(element).text();     if (!text.trim()) {       return true;     }     return (text.trim() == '&nbsp;');   } } ( mediaWiki, jQuery ) );