Замечание: Возможно, после публикации вам придётся очистить кэш своего браузера, чтобы увидеть изменения.

  • Firefox / Safari: Удерживая клавишу Shift, нажмите на панели инструментов Обновить либо нажмите Ctrl+F5 или Ctrl+R (⌘+R на Mac)
  • Google Chrome: Нажмите Ctrl+Shift+R (⌘+Shift+R на Mac)
  • Edge: Удерживая Ctrl, нажмите Обновить либо нажмите Ctrl+F5
  • Opera: Нажмите Ctrl+F5.
/****************************************************************** Listing Editor v1.4.2 (March 19, 2015‎) (torty3)                v1.3 (Russian localization) ********************************************************************/ ( function ( mw, $ ) {  'use strict';   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;  }  // **RUS** Added facebook, vkontakte, skype, format, wdid, unesco, star. Removed fax, tollfree, checkin, checkout.  var allFields = {      'type': {size:8, right:true, newline:true, parameter:'type', label:'Тип', tip:'тип объекта, определяющий значок на карте' },      'name': {size:45, right:false, newline:true, parameter:'name', label:'Название', tip:'название объекта'},      'alt': {size:45, right:false, newline:false, parameter:'alt', label:'Или', tip:'другое название или пояснение'},      'url': {size:45, right:false, newline:false, parameter:'url', label:'Веб-сайт', tip:'http://www.example.com'},      'email': {size:32, right:true, newline:true, parameter:'email', label:'E-mail', tip:'[email protected]'},      'facebook': {size:45, right:false, newline:true, parameter:'facebook', label:'Facebook', tip:'https://www.facebook.com/example'},      'vkontakte': {size:45, right:false, newline:true, parameter:'vkontakte', label:'ВКонтакте', tip:'http://vk.com/example'},      'skype': {size:45, right:false, newline:true, parameter:'skype', label:'Скайп', tip:'контакт в Скайпе'},      'address': {size:45, right:false, newline:false, parameter:'address', label:'Адрес', tip:'адрес объекта'},      'lat': {size:10, right:true, newline:false, parameter:'lat', label:'Широта', tip:'11.11111'},      'long': {size:10, right:true, newline:false, parameter:'long', label:'Долгота', tip:'111.11111'},      'directions': {size:45, right:false, newline:true, parameter:'directions', label:'Пояснения', tip:'пояснения, в том числе транспорт'},      'phone': {size:30, right:false, newline:false, parameter:'phone', label:'Телефон', tip: '+55 555 555-5555'},      //'fax': {size:30, right:true, newline:true, parameter:'fax', label:'Факс', tip: '+55 555 555-555'},      'image': {size:32, right:true, newline:true, parameter:'image', label:'Изображение', tip:'имя файла на Commons'},      'hours': {size:30, right:false, newline:false, parameter:'hours', label:'Часы работы', tip: '09:00-18: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'},      'format': {size:8, right:false, newline:true, parameter:'format', label:'Форматирование', tip:''},      'unesco': {right:true, newline:false, parameter:'unesco', label:'ЮНЕСКО?', tip:''},      'star': {right:true, newline:false, parameter:'star', label:'Важный?', tip:''},      'wdid': {size:30, right:false, newline:true, parameter:'wdid', label:'Викиданные', tip:'Qxxxxx'},      //'tollfree': {size:30, right:true, newline:false, parameter:'tollfree', label:'Tollfree', tip:'+1 800 100 1000'},      'price': {size:30, right:false, newline:true, parameter:'price', label:'Стоимость', tip: '100 руб'},      'lastedit': {size:10, right:false, newline:true, parameter:'lastedit', label:'Last Updated', tip: '2015-01-15'},      // **RUS** parameter content->description      'description': {cols:34, rows:8, right:false, newline:true, parameter:'description', label:'Описание', tip: 'описание объекта'}  };   //**RUS** added RUB sign  var currencySigns = ['\u00A3', '\u20AC', '\u00A5', '\u20A9', '\u20bd'];  //**RUS** added 'go' and 'vicinity', changed 'listing' to 'other'  var listingTypes = {'see':'see', 'do':'do', 'go':'go', 'buy':'buy', 'eat':'eat', 'drink':'drink', 'sleep':'sleep', 'other':'other', 'vicinity':'vicinity'};  //**RUS** translated keys and assigned corresponding values  var sectionHeadings = {'Как добраться':'go', 'Достопримечательности':'see', 'Чем заняться':'do', 'Покупки':'buy', 'Еда':'eat', 'Ночная жизнь':'drink', 'Где остановиться':'sleep', 'Связь':'other', 'Окрестности':'vicinity'};  var LICENSE_TEXT = 'Нажимая кнопку «Сохранить», вы соглашаетесь с <a class="external" target="_blank" href="https://wikimediafoundation.org/wiki/Terms_of_Use/ru">условиями использования</a>, а также соглашаетесь на неотзывную публикацию по лицензии <a class="external" target="_blank" href="https://en.wikipedia.org/wiki/ru:Википедия:Текст_Лицензии_Creative_Commons_Attribution-ShareAlike_3.0_Unported">CC-BY-SA 3.0</a>.'  var translateStr = {      'add': 'добавить объект',      'edit': 'edit',      'add-dialog': 'Добавить объект',      'edit-dialog': 'Редактировать объект',      'closed': 'Закрылся?',      'closed-title': 'Установите галочку, если данный объект больше не функционирует, и он будет удалён из статьи',      'verified': 'Информация актуальна на сегодняшнюю дату?',      'verified-title': 'Установите галочку, если вся информация об объекте достоверна и актуальна, и дате последнего обновления будет присвоено сегодняшнее число',      'saving': 'Сохранение',      'submit': 'Сохранить',      'cancel': 'Отмена',      'validationalert': 'Пожалуйста, укажите название или адрес',      'added': 'Добавлен объект ',      'updated': 'Обновлён объект ',      'removed': 'Удалён объект ',      'geomap': 'найти на карте',      'help-page': 'http://en.wikivoyage.org/wiki/Wikivoyage:Listing_editor',      'enter-captcha': 'Введите CAPTCHA',      'external-links': 'Введённый текст содержит внешние ссылки.',      //**RUS** added the following label      'icon-pencil-title': 'Редактировать объект'   };    var EDIT_LINK_CONTAINER = 'span.listing-metadata-items';  var LISTING_CONTAINER = 'span.vcard';   var sectionText, listingText, inlineListing;   var api = new mw.Api();    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 () { 	 //**RUS** modified the following paragraph 	 var regionArticleHeadings = ['Города', 'Областные центры', 'Курорты', 'Острова', 'Малые города', 'Другие места назначения', 'print-districts'];      for (var i=0; i < regionArticleHeadings.length; i++) {          var regionArticleHeading = encodeURIComponent(regionArticleHeadings[i]).replace(/%20/g,'_').replace(/%/g,'\\.');          if ($('#' + regionArticleHeading).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">')      	 //**RUS** added class and title parameters          .html('<a href="javascript:" class="icon-pencil" title="' + translateStr['icon-pencil-title'] + '">'+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)) {                  //**RUS** removed '|' sign                  $(this).append('&nbsp;');              }          });          // append the edit link          $(EDIT_LINK_CONTAINER).append( editButton );  }   //**RUS** modified the following method. Also retained it in use   // (i.e. skip applying https://en.wikivoyage.org/w/index.php?title=MediaWiki:Gadget-ListingEditor.js&diff=2750076&oldid=2750058)  /*** Functions to retrieve entry details ***/  function getIdentifier(entry) {      var id = {};      var name = entry.find('.listing-name').text();      var address = entry.find('.label').text();      var alt =  entry.find('.listing-alt').text();      if (name) {          id['name'] = name;      }      else if (address) {          id['address'] = address;      }      else {          id['alt'] = alt;      }      return id;  }   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');      //**RUS** added the following line      section = decodeURIComponent(section.replace(/\./g,'%').replace(/_/g,'%20'));      for (var key in sectionHeadings) {          if (section == key) return sectionHeadings[key];              }      //**RUS** changed 'listing' to 'other'      return listingTypes.other;  }   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,' ');      var id = getIdentifier(entry);      for (var key in id) break;      var search = allFields[key]['parameter'];      id[key] = replaceSpecial(id[key]);            var listingRegex = new RegExp(search+"\\s?=\\W*?"+id[key]+"\\W*?(\\||}})");      var string = sectionText.match(listingRegex)[0];      var index = sectionText.indexOf(string);       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) {  	//**RUS** added 'go', 'vicinity', changed 'listing' to 'other'      var typeRegex = new RegExp('{{('+listingTypes['go']+listingTypes['see']+'|'+listingTypes['do']                  +'|'+listingTypes['buy'] +'|'+listingTypes['eat'] + '|'+listingTypes['drink']                  +'|'+listingTypes['sleep']+'|'+listingTypes['other']+listingTypes['vicinity']+')','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 + '-dialog'],          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:360px;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];              }          }          //**RUS** added 2 following conditions          else if (key == 'unesco') {              var subnode = $('<input type="checkbox">').appendTo(node);        	           }          else if (key == 'star') {              var subnode = $('<input type="checkbox">').appendTo(node);        	           }          //**RUS** global change 'content'->'description'          else if (key != 'description') {              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]) {                //**RUS** added the following condition              if ((key == 'star' || key == 'unesco') && (listing[parameter] == 'yes')) {                  subnode.prop('checked', true);              } else {                  subnode.val(listing[parameter]);              }            }           //**RUS** commented out the next string          //if (listing[allFields['type']['parameter']] == listingTypes['sleep'] && key == 'hours') node.hide();          //**RUS** removed checkin, checkout, fax, image conditions. added format one          if (key == 'format' || 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" title="' + translateStr['closed-title'] + '">').appendTo(closedSpan)                  .attr('id', 'input-closed');              node.append(closedSpan);          }          if (key == 'phone') {              var phoneSpan = $('<span id="span_phone">');              var phoneButton = $('<span class="currency-signs">')                  .html('&#32;<u><a href="javascript:">{{phone|||}}</a></u>' )                  .click(function() {                      var caretPos = document.getElementById('input-phone').selectionStart;                      var price = $('#input-phone').val();                      $('#input-phone').val(price.substring(0, caretPos)                                  + $(this).find('a').text() + price.substring(caretPos) );                      });                  phoneSpan.append(phoneButton);                                node.append(phoneSpan);          }          if (key == 'hours') {              var hoursSpan = $('<span id="span_hours">');              var hoursButton = $('<span class="currency-signs">')                  .html('&#32;<u><a href="javascript:">{{hours|день1|день2|час1|мин1|час2|мин2}}</a></u>' )                  .click(function() {                      var caretPos = document.getElementById('input-hours').selectionStart;                      var price = $('#input-hours').val();                      $('#input-hours').val(price.substring(0, caretPos)                                  + $(this).find('a').text() + price.substring(caretPos) );                      });                  hoursSpan.append(hoursButton);                                node.append(hoursSpan);          }          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>');          }           //**RUS** global change 'content'->'description'          if (key == 'description') {              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" checked="checked" title="' + translateStr['verified-title'] + '">').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;      }      //**RUS** global change 'content'->'description'      $('#input-description').val($.trim($('#input-description').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 formToText(mode, number) {      var listing = {};      for ( var key in allFields ) {          var parameter = allFields[key]['parameter'];           //**RUS** added the following condition          if (key == 'star' || key == 'unesco') {              listing[parameter]= $("#input-"+key).is(':checked') ? 'yes' : '';          } else {              listing[parameter]= $("#input-"+key).val();          }      }       // 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);       //**RUS** added the following 7 lines      var sectionHeading = "Другое";      for (var key in sectionHeadings) {          if ($("#input-type").val() == sectionHeadings[key]) {         	 sectionHeading = key;         	 break;          }              }       //**RUS** modified the following line (removed upperCaseFirst() method)      var summary = '/* ' + sectionHeading + ' */ ';      if (mode == 'add') {          summary += translateStr['added'];          var index = sectionText.indexOf('===');          if ( index == 0 ) {              index = sectionText.indexOf('====');          }          //**RUS** prevent inserting listing after footer template          var indexFooterTemplate = sectionText.indexOf('{{footer');;          if (listing['type'] == 'vicinity' && indexFooterTemplate != -1) {         	 index = indexFooterTemplate;          }                    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) { 	  	 		//**RUS** TODO switch to an English version later 			var editPayload = { 				action: "edit", 				title: mw.config.get( "wgPageName" ), 				section: number, 				text: content, 				summary: summary, 				captchaid: cid, 				captchaword: answer 			}; 			api.postWithToken( 				"edit", 				editPayload 			).done(function(data, jqXHR) {	 	               if ( data && data.edit && data.edit.result == 'Success' ) { 	                 window.location.reload(); // reload page if edit was successful 	               } else if ( data && data.error ) { 	            	   saveFailed( 'Error: API returned error code "' + data.error.code + '": ' + data.error.info ); 	               } else if ( data && data.edit.spamblacklist ) { 	            	   saveFailed( 'Error: "'+ data.edit.spamblacklist + '" has been blacklisted' ); 	               } 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 { 	            	   saveFailed( 'Error: Unknown result from API.' ); 	               } 			}).fail(function(code, result) { 				if (code === "http") { 					alert(msg); 					saveFailed('Error: The server responded with an HTTP error while attempting to save the listing, please try again: ' + result.textStatus ); 				} else if (code === "ok-but-empty") { 					saveFailed('Error: The server returned an empty response while attempting to save the listing, please try again'); 				} else { 					saveFailed('Error: An unknown error has been encountered while attempting to save the listing, please try again: ' + code ); 				} 			}); 			savingForm();  }   	/** 	 * If an error occurs while saving the form, remove the "saving" dialog, 	 * restore the original listing editor form (with all user content), and 	 * display an alert with a failure message. 	 */ 	var saveFailed = function(msg) { 		$("#progress-dialog").dialog('destroy').remove(); 		$("#listing-editor").dialog('open'); 		alert(msg); 	};  //**RUS** almost completely reimplemeted the following method function listingToStr(listing) {     var allFields = {         'lat': {newline:false},         'long': {newline:false},         'wdid': {newline:true},         'name': {newline:false},         'alt': {newline:false},         'image': {newline:true},         'address': {newline:false},         'directions': {newline:true},         'url': {newline:false},         'facebook': {newline:false},         'vkontakte': {newline:true},         'phone': {newline:false},         'email': {newline:false},         'skype': {newline:true},         'hours': {newline:false},         'price': {newline:true},         'lastedit': {newline:true},         'description': {newline:true},         'format': {newline:true},         'unesco': {newline:true},         'star': {newline:true}     }; 	     var saveStr = '{{listing|type=' + listing['type'];	     for ( var key in allFields ) {         // if format, unesco or star parameter is empty - don't include it in the listing         if ((key == 'format' && listing['format'] == '')                 || (key == 'unesco' && listing['unesco'] == '')                 || (key == 'star' && listing['star'] == '')) {              continue;         } 			         // wdid exists only for see, do, go, vicinity         if (key == 'wdid' && listing['type'] != 'see' && listing['type'] != 'do'                 && listing['type'] != 'go' && listing['type'] != 'vicinity') {             saveStr += '\n';             continue;         } 				         saveStr +='| ' + key + '=' + listing[key];         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 ) );