مدیاویکی:Gadget-ListingEditor.js
نکته: پس از انتشار ممکن است برای دیدن تغییرات نیاز باشد که حافظهٔ نهانی مرورگر خود را پاک کنید.
- فایرفاکس / سافاری: کلید Shift را نگه دارید و روی دکمهٔ Reload کلیک کنید، یا کلیدهای Ctrl-F5 یا Ctrl-R را با هم فشار دهید (در رایانههای اپل مکینتاش کلیدهای ⌘-R)
- گوگل کروم: کلیدهای Ctrl+Shift+R را با هم فشار دهید (در رایانههای اپل مکینتاش کلیدهای ⌘-Shift-R)
- اینترنت اکسپلورر/ Edge: کلید Ctrl را نگهدارید و روی دکمهٔ Refresh کلیک کنید، یا کلیدهای Ctrl-F5 را با هم فشار دهید
- اپرا: Ctrl-F5 را بفشارید.
// <pre>
// This will break toggling if run on mobile skin so exit early.
if ( mw.config.get( 'skin' ) === 'minerva' ) {
return;
}
window.ListingEditor = {};
ListingEditor.allFields = {
'type': {right:true, newline:true, parameter:'نوع', label:'نوع', tip:'نوع فهرست', regx:'(نوع فهرست|type)' },
'name': {right:false, newline:false, parameter:'نام', label:'نام', tip:'نام مکان', regx:'(نام|name)'},
'alt': {right:true, newline:false, parameter:'نام دیگر', label:'نام دیگر', tip:'همچنین با این نام نیز شناخته می\u200cشود', regx:'(نام دیگر|alt)'},
'url': {right:false, newline:false, parameter:'نشانی اینترنتی', label:'وب\u200cسایت', tip:'http://www.example.com', regx:'(نشانی اینترنتی|url)'},
'email': {right:true, newline:true, parameter:'پست الکترونیکی', label:'پست الکترونیکی', tip:'hello@example.com', regx:'(پست الکترونیکی|email|رایانامه)'},
'address': {right:false, newline:false, parameter:'نشانی', label:'نشانی', tip:'نشانی مکان', regx:'(نشانی|address)'},
'lat': {right:true, newline:false, parameter:'عرض جغرافیایی', label:'عرض جغرافیایی', tip:'11.11111', regx:'(عرض جغرافیایی|lat)'},
'long': {right:true, newline:false, parameter:'طول جغرافیایی', label:'طول جغرافیایی', tip:'111.11111', regx:'(طول جغرافیایی|long)'},
'directions': {right:false, newline:true, parameter:'مسیرها', label:'مسیرها', tip:'چه طوری به آنجا می\u200cرسید', regx:'(مسیرها|directions)'},
'phone': {right:false, newline:false, parameter:'تلفن', label:'تلفن', tip: '+۹۸ ۲۱ ۸۸۸۸۸۸۸۸', regx:'(تلفن|phone)'},
'tollfree': {right:true, newline:false, parameter:'تماس رایگان', label:'تماس رایگان', tip:'شماره تلفنی که تماس با آن خرج ندارد', regx:'(تماس رایگان|tollfree)'},
'fax': {right:true, newline:false, parameter:'دورنگار', label:'دورنگار', tip: '+۹۸ ۲۱ ۸۸۸۸۸۸۸۸', regx:'(دورنگار|fax)'},
'image': {right:true, newline:true, parameter:'تصویر', label:'تصویر', tip: 'تصویر مکان', regx:'(تصویر مکان|image)'},
'hours': {right:false, newline:false, parameter:'ساعت\u200cها', label:'ساعت\u200cها', tip: 'ساعت\u200cهای کاری', regx:'(ساعت\u200cهای کاری|hours)'},
'checkin': {right:true, newline:false, parameter:'زمان پذیرش', label:'زمان پذیرش', tip: 'زمان پذیرش', regx:'(زمان پذیرش|checkin)'},
'checkout': {right:true, newline:false, parameter:'زمان اتمام پذیرش', label:'زمان اتمام پذیرش', tip: 'زمان اتمام پذیرش', regx:'(زمان اتمام پذیرش|checkout)'},
'price': {right:false, newline:true, parameter:'بها', label:'بها', tip: 'بهای خدمات', regx:'(بها|price)'},
'content': {rows:8, right:false, newline:true, parameter:'متن', label:'متن', tip: 'توضیح درباره مکان', regx:'(متن|content)'}
};
ListingEditor.currencySigns = ['\ufdfc','\u062f\u002e\u0625\u002e','\u0024','\u00A3', '\u20AC', '\u00A5', '\u20A9'];
ListingEditor.listingTypes = {'see':'دیدن', 'do':'انجام\u200cدادن', 'buy':'خریدن', 'eat':'خوردن', 'drink':'نوشیدن', 'sleep':'خوابیدن', 'listing':'فهرست\u200cبندی'};
ListingEditor.listingTypesLabels = {'see':'دیدن', 'do':'انجام\u200cدادن', 'buy':'خریدن', 'eat':'خوردن', 'drink':'نوشیدن', 'sleep':'خوابیدن', 'listing':'عمومی'};
ListingEditor.listingTypesRegex = {'see':'(دیدن|see)', 'do':'(انجام دادن|do|انجام\u200cدادن)', 'buy':'(خریدن|buy)', 'eat':'(خوردن|eat)', 'drink':'(نوشیدن|drink|آشامیدن)', 'sleep':'(خوابیدن|sleep|خواب)', 'listing':'(listing|فهرست\u200cنویسی|فهرست\u200cبندی|فهرست بندی|فهرست)'};
ListingEditor.addListingSections = {'see':'(دیدن|دیدنی ها|دیدنی\u200cها|جاذبه های گردشگری|جاذبه\u200cهای گردشگری|جاذبه ها|جاذبه\u200cها)','do':'(انجام\u200cدادن|انجام دادن|باید انجام داد|انجام دادنی\u200cها)','buy':'(خریدن|خرید کردن|خرید)','eat':'(خوردن|رستوران ها|رستوران\u200cها)','drink':'(نوشیدن|آشامیدن|نوشیدن و کافی شاپ|نوشیدن و کافی\u200cشاپ)','sleep':'(خوابیدن|خواب|هتل\u200cها|هتل ها)','listing':'(ارتباطات|آموزش|سفارت خانه\u200cها|سفارت خانه ها|سفارت\u200cخانه\u200cها|سفارت\u200cخانه ها)'};
ListingEditor.LICENSE_TEXT = 'با کلیک بر روی «ثبت»، شما با <a class="external" target="_blank" href="http://wikimediafoundation.org/wiki/Terms_of_use">شرایط استفاده</a> موافقت می\u200cکنید، و همچنین مشارکت شما برای مدت نامحدود تحت <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</a> منتشر خواهد شد.';
ListingEditor.translateStr = {
'add': 'افزودن به فهرست',
'edit': 'ویرایش',
'preview': 'پیش\u200cنمایش',
'closed': 'بسته شده؟',
'saving': 'در حال ذخیره',
'submit': 'ثبت',
'cancel': 'لغو',
'validationalert': 'خواهش می\u200cکنم نام و یا نشانی را وارد کنید',
'added': 'افزودن: ',
'updated': 'به روز رسانی: ',
'removed': 'بسته شده: ',
'cities': 'Cities',
'destination': 'Other_destinations',
'geomap': 'مشاهده موقعیت روی نقشه',
'help-page': '//fa.wikivoyage.org/wiki/%D9%88%DB%8C%DA%A9%DB%8C%E2%80%8C%D8%B3%D9%81%D8%B1:%D9%88%DB%8C%D8%B1%D8%A7%DB%8C%D8%B4%DA%AF%D8%B1_%D9%81%D9%87%D8%B1%D8%B3%D8%AA%E2%80%8C%D8%A8%D9%86%D8%AF%DB%8C%E2%80%8C%D9%87%D8%A7',
'enter-captcha': 'حروف به هم ریخته را وارد کنید',
'external-links': 'ویرایش شما شامل پیوندهای خارجی تازه می\u200cباشد.'
};
ListingEditor.loadingIcon = 'data:image/gif;base64,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';
ListingEditor.ToolIcon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAMAAAC6V+0/AAAAzFBMVEUAAAAAoP+A0P9VwP9OnetVpO5aqfBVqfFSpfVVp/ZYqfZTo/FTpPJXqvRYq/VVpvVXpvFWpvJVpfNWqfVWp/JVpfJXqfNWp/NXqPNWpvRXqPNWp/NVp/RXqPRWp/JXqfRXqvRWpfJWpvJXqPNXqfNXqPRVpfNWpvRVpvRWqfRWpvJVpfJWp/NWpvNVpfNWp/RWp/NVpfNWqPNVpfNWpvNWp/NWp/NWp/NWp/NWp/NWp/NWqPNWp/NWp/NWp/NWp/NWp/NWp/NWp/NWp/Ox28KLAAAAQ3RSTlMAAQIGDQ8REhkbHSUoLzEzODtCSk1RUlZYXGdub3B5h4qLjpOZnLCys7S1trrDxcnMzs/R2ebn6Orr7u/x8/X5+v3+w2zu5gAAAJJJREFUeAFlyNW2gkAABdDD5drdIgYqdmC3InP+/5980DWLGfbjRljrvGtA0xH0K9pZgqxBsyAff3r2SDqA0a+HMkeSg5TLKSSjdOXXUp454c89L29Okl5A3grq+YmkPcyqJ2xI8trKzSKXcTaRK77eF/2wOqbR1Q7PERCnC8X28A+LTTWr4rQO9iZU5bHnxNT6AAC2HLAUiyuPAAAAAElFTkSuQmCC';
ListingEditor.wrapContent = function () {
$('h2').each(function(){
$(this).nextUntil("h2").addBack().wrapAll('<div class="mw-h2section" />');
});
};
ListingEditor.addListingButtons = function () {
if ($('#'+ListingEditor.translateStr['cities']).length || $('#'+ListingEditor.translateStr['destination']).length || $('#'+'Islands').length || $('#'+'print-districts').length) {
return false;
}
var editButton = $('<span class="mw-addlisting noprint">')
.css('cursor','pointer')
.click(function() {
var listingEntry = $(this).parent();
ListingEditor.popupForm('add', listingEntry);
}).append(' [').append($('<a/>').text(ListingEditor.translateStr['add']).click( function(e) {
e.preventDefault();
})).append(']');
$('.mw-h2section h2 span').each( function() {
for (var key in ListingEditor.addListingSections) {
var value = ListingEditor.addListingSections[key];
var rgx = new RegExp('^'+value+'$','g');
if($(this).text().match(rgx)!=null)
{
$(this).parent('h2').addClass('mw-addhere');
$(this).closest('div.mw-h2section').children('h3').addClass('mw-addhere');
}
}
});
$('.mw-addhere').append(editButton);
};
ListingEditor.addEditButtons = function () {
var editButton = $('<span class="vcard-edit-button noprint">')
.css('cursor','pointer')
.click(function() {
var listingEntry = $(this).parent();
ListingEditor.popupForm('edit', listingEntry);
}).append(' ').append($('<a/>').text(ListingEditor.translateStr['edit']).click( function(e) {
e.preventDefault();
}));
$('.listing-item').append( editButton );
};
ListingEditor.isInline = function (entry) {
if (entry.parent('p').length == 0) return false;
return true;
};
ListingEditor.findSectionNumber = function (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;
};
ListingEditor.findSectionType = function (entry) {
var section = entry.closest('div.mw-h2section').children('h2').find('.mw-headline').text();
for (var key in ListingEditor.addListingSections) {
var value = ListingEditor.addListingSections[key];
var rgx = new RegExp('^'+value+'$','g');
if(section.match(rgx)) return key;
}
return ListingEditor.listingTypes.listing;
};
ListingEditor.replacements = {};
ListingEditor.getSectionText = function (number, entry) {
var wikiText = $.ajax({
url: mw.util.wikiScript(''),
data: { title:mw.config.get('wgPageName'), action:'raw', section:number },
async: false,
cache: false, // required
beforeSend: function () {
var loading = $('<span/>');
loading.attr('class','listing_loading');
var img = $('<img/>');
img.attr('src',ListingEditor.loadingIcon);
loading.append(img);
loading.prepend(' ');
loading.insertAfter(entry);
},
complete: function() {
$('.listing_loading').remove();
},
}).responseText;
var comments = wikiText.match(/<!--[\s\S]*?-->/mig);
if ( comments !== null ) {
for(var i = 0; i < comments.length; i++ )
{
var comment = comments[i];
var rep = '<<<COMMENT' + i + '>>>';
wikiText = wikiText.replace(comment, rep);
ListingEditor.replacements[rep] = comment;
}
}
return wikiText;
};
ListingEditor.replaceSpecial = function ( str ) {
return str.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
};
ListingEditor.getListingWikitextBraces = function (entry) {
ListingEditor.sectionText = ListingEditor.sectionText.replace(/[^\S\n]+/g,' ');
var parent = $(entry.parentsUntil('.mw-h2section').parent()[0]);
var cnt = 0;
parent.find('.listing-item').each( function(){
if($(entry[0]).is($(this)))
{
return false;
}
cnt += 1;
});
var regex = []
for(var key in ListingEditor.listingTypesRegex)
{
regex.push(ListingEditor.listingTypesRegex[key]);
}
var listingRegex = new RegExp("{{\\s*("+regex.join('|')+')','g');
var matches = ListingEditor.sectionText.match(listingRegex);
var string = matches[cnt];
var parttxt = ListingEditor.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]);
var curly = 2;
var str1 = '', str2 = '';
// search for open and close braces
for (var i=index; i>0; i--) {
if (ListingEditor.sectionText[i]=='}') ++curly;
else if (ListingEditor.sectionText[i]=='{') --curly;
if(curly == 0) {
str1 = ListingEditor.sectionText.substr(i,index-i);
break;
}
}
if (string.indexOf('}}') < 0) curly = 2;
var textLength = ListingEditor.sectionText.length;
for (var j=index+string.length; j<textLength; j++) {
if (ListingEditor.sectionText[j]=='{') ++curly;
else if (ListingEditor.sectionText[j]=='}') --curly;
if (curly == 0) {
str2 = ListingEditor.sectionText.substr(index, j-index+1);
break;
}
}
if (str2 === '') str2 = ListingEditor.sectionText.substr(index, textLength);
string = str1 + str2;
return $.trim(string);
};
ListingEditor.wikiTextToListing = function (string) {
string = string.slice(0,-2);
var type = 'listing';
for(key in ListingEditor.listingTypesRegex)
{
var typeRegex = new RegExp('{{\\s*'+ListingEditor.listingTypesRegex[key],'g');
var match = typeRegex.exec(string);
if(match != null)
{
type = key;
}
}
if(typeof ListingEditor.listingTypes[type.toLowerCase()] != "undefined") type = ListingEditor.listingTypes[type.toLowerCase()];
var regex = []
for(var key in ListingEditor.listingTypesRegex)
{
regex.push(ListingEditor.listingTypesRegex[key]);
}
var listingRegex = new RegExp("{{\\s*("+regex.join('|')+')','g');
string = string.replace(listingRegex,'{{فهرست\u200cبندی| type=' + type);
var listing = {};
var lastKey;
var OpenBracket = 0;
var OpenSquareBrackets = 0;
var listParams = [];
var buff = '';
for ( var i = 0; i < string.length; i++ )
{
var chr = string.charAt(i);
if ( chr == '{' ) {
OpenBracket++;
} else if ( chr == '}' ) {
OpenBracket--;
} else if ( chr == '[' ) {
OpenSquareBrackets++;
} else if ( chr == ']' ) {
OpenSquareBrackets--;
}
if ( chr == '|' && OpenBracket == 2 && OpenSquareBrackets === 0 ) {
listParams.push(buff);
buff = '';
} else {
buff += chr;
}
}
if ( buff !== '' ) {
listParams.push(buff);
buff = '';
}
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));
for(var key2 in ListingEditor.allFields)
{
var regx = new RegExp("^"+ListingEditor.allFields[key2]['regx']+"$")
if(key.match(regx))
{
key = key2;
break;
}
}
listing[key] = value;
lastKey = key;
}
else if (listing[lastKey].length) {
listing[lastKey] += '|' + param;
}
}
return listing;
};
ListingEditor.getListing = function (entry) {
ListingEditor.listingText = ListingEditor.getListingWikitextBraces(entry);
var listing = ListingEditor.wikiTextToListing(ListingEditor.listingText);
return listing;
};
/*** Functions to handle form creation and editing ***/
ListingEditor.popupForm = function (mode, entry) {
mw.loader.using( ['jquery.ui'], function () {
var sectionType, listing;
var sectionNumber = ListingEditor.findSectionNumber(entry);
ListingEditor.inlineListing = ListingEditor.isInline(entry);
ListingEditor.sectionText = ListingEditor.getSectionText(sectionNumber,entry);
if (mode == 'add') {
sectionType = ListingEditor.findSectionType(entry);
listing = {};
ListingEditor.sectionTitle = $($(entry.parent()[0]).find('h2 span')[0]).text();
}
else {
sectionType = '';
listing = ListingEditor.getListing(entry);
ListingEditor.sectionTitle = $($(entry.parentsUntil('.mw-h2section').parent()[0]).find('h2 span')[0]).text();
}
var form = $(ListingEditor.createForm(mode, sectionType, listing));
// modal form - must submit or cancel
form.dialog({
// IE different behavior
drag: function(event, ui) {
$(this).parent().css('right',
(
$(window).innerWidth() - parseInt($(this).parent().css('left')) - $(this).parent().width()
)+'px'
);
$(this).parent().css('left','');
},
modal: true,
height: 'auto',
width: '800px',
title: ListingEditor.translateStr[mode],
buttons: [
{ text: '؟',
id: 'listing-help',
click: function() { window.open(ListingEditor.translateStr['help-page']);}},
{text: ListingEditor.translateStr['cancel'], click: function() {$(this).dialog('destroy').remove()}},
{ text: ListingEditor.translateStr['preview'], click: function() {
if(ListingEditor.validateForm()) {
ListingEditor.preview();
}
}
},
{ text: ListingEditor.translateStr['submit'], click: function() {
if(ListingEditor.validateForm()) {
ListingEditor.formToText(mode, sectionNumber);
$(this).dialog('close');
}
}
},
],
open: function() {
$('.ui-dialog-buttonpane').append('<div style="width:320px;padding-top:0.8em;font-size:xx-small;">'+ListingEditor.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()));
});
// IE different behavior
$(this).parent().css('right',
(
$(window).innerWidth() - parseInt($(this).parent().css('left')) - $(this).parent().width()
)+'px'
);
$(this).parent().css('left','');
},
close: function() { $(this).dialog('destroy').remove()}
});
});
};
ListingEditor.buttonGenerator = function (callback, summaryText, replaceSummary, image, title, alt, idSuffix) {
var button = $('<span>', { style: 'padding-right: 2px; cursor: pointer;' }).click(callback).append(
$('<img>').attr({
src: image,
title: title,
alt: alt
}).on("error", function () {
button.replaceWith($('<button>', { text: alt }).click(callback));
})
);
return button;
};
ListingEditor.createForm = function (mode, type, listing) {
var form = $('<form id="listing-editor">');
var leftFields = $('<table id="left-fields" style="display: inline-flex;">').appendTo(form);
var rightFields = $('<table id="right-fields" style="display: inline-flex;">').appendTo(form);
$('<div style="clear:both">').appendTo(form);
//create form according to fields
for (var key in ListingEditor.allFields) {
var keyvalue = ListingEditor.allFields[key];
var row = $('<tr class="input-text">')
.attr('id', 'div_' + key);
var cell = $('<td/>').appendTo(row);
var label = $('<label>').appendTo(cell)
.text(keyvalue['label'])
.attr('for', 'input-' + key);
var cell = $('<td/>').appendTo(row);
// input text for everything except content which gets textarea
var parameter = key;
if (key == 'type') {
var subnode = $('<select id="option-type">').appendTo(cell);
for (var n in ListingEditor.listingTypes) {
var option = $('<option value="'+ListingEditor.listingTypes[n]+'">');
option.text(ListingEditor.listingTypesLabels[n]).appendTo(subnode);
}
if (mode == 'add') {
subnode.val(ListingEditor.listingTypes[type]);
listing[parameter] = ListingEditor.listingTypes[type];
}
}
else if (key != 'content') {
var subnode = $('<input type="text" style="width: 100%;">').appendTo(cell);
}
else {
var subnode = $('<textarea style="width: 100%;">').appendTo(cell)
.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[ListingEditor.allFields['type']['parameter']] == ListingEditor.listingTypes['sleep'] && key == 'hours') row.hide();
if (key == 'checkin' || key == 'checkout' || key == 'fax' || key == 'image') row.hide();
// some special form features
if (key == 'type' && mode == 'edit') {
var closedSpan = $('<span id="span_closed">');
var closedLabel = $('<label for="input-closed">').appendTo(closedSpan)
.text(ListingEditor.translateStr['closed']);
var closedInput = $('<input type="checkbox">').appendTo(closedSpan)
.attr('id', 'input-closed');
cell.append(closedSpan);
}
if (key == 'price') {
var currencySpan = $('<span id="span_currency">');
for (var i=0; i < ListingEditor.currencySigns.length; i++) {
var currencyButton = $('<span class="currency-signs">')
.html(' <u><a href="javascript:">'+ListingEditor.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);
}
cell.append(currencySpan);
}
if (key == 'lat') {
var latlngStr = '?';
if ($('#geodata').length) {
var latlng = $('#geodata').text().split('; ');
latlngStr += 'lat='+latlng[0]+'&lon='+latlng[1]+'&zoom=15';
}
cell.append(' <u><a id="geomap-link" target="_blank" '
+'href="http://maps.wikivoyage-ev.org/w/geomap.php'+latlngStr+'">'
+ListingEditor.translateStr['geomap']+'</a></u>');
}
if (key == 'content') {
var tb = $('<table/>').css('width','100%');
$(row.children()[0]).css('width','1px');
tb.append(row);
form.append(tb);
}
else if (ListingEditor.allFields[key]['right'] == true) {
rightFields.append(row);
}
else {
leftFields.append(row);
}
}
if(typeof persianWikiTools != 'undefined' && typeof persianWikiTools.superToolMove != 'undefined')
{
form.find('input[type=text]').each(function(){
var me = $(this);
me.css('width','88%');
var btn = ListingEditor.buttonGenerator(
function () {
var me = $(this);
var target = $(me.parent().children()[0]);
target.val(persianWikiTools.superToolMove(target.val()));
},
'تصحیح خودکار',
false,
ListingEditor.ToolIcon,
'تصحیح خودکار',
'تصحیح خودکار',
'super-tool'
);
btn.insertAfter(me);
});
form.find('textarea').each(function(){
var me = $(this);
me.parent().parent().append($('<td/>').css('width','1px'));
var btn = ListingEditor.buttonGenerator(
function () {
var me = $(this);
var target = $($(me.parent().parent().children()[1]).children()[0]);
target.val(persianWikiTools.superToolMove(target.val()));
},
'تصحیح خودکار',
false,
ListingEditor.ToolIcon,
'تصحیح خودکار',
'تصحیح خودکار',
'super-tool'
);
$(me.parent().parent().children()[2]).append(btn);
});
}
//form.append($('<div style="text-align: center; font-size: 120%; padding: 10px; margin: 10px; color: rgb(255, 20, 28); border: 1px solid rgb(255, 254, 41); background-color: rgb(249, 254, 201); border-radius: 10px; -webkit-border-radius: 10px; -moz-border-radius: 10px;">قبل از ذخیره کردن، بر روی دکمهٔ <img alt="تصحیح خودکار" title="تصحیح خودکار" src="' + ListingEditor.ToolIcon + '"> در هر بخش کلیک کنید تا تصحیحات لازم انجام شود.</div>'));
if (mw.config.get('wgUserName') == null)
form.append($('<div style="background-color: rgb(255, 228, 225); color: rgb(0, 0, 0); border: 1px solid rgb(234, 164, 215); border-radius: 10px; -webkit-border-radius: 10px; -moz-border-radius: 10px; padding: 10px; margin: 10px;"><span style="color: #FF0000;">توجه:</span> شما با نام کاربری وارد نشده\u200cاید، ویرایش شما با آی\u200cپی شما ثبت می\u200cشود، می\u200cتوانید ابتدا <a href="//fa.wikivoyage.org/wiki/Special:Login/signup" target="_blank">ثبت نام کنید</a>، اگر در حال حاضر در ویکی\u200cسفر و یا در دیگر پروژه\u200cهای بنیاد ویکی\u200cمدیا حساب کاربری دارید می\u200cتوانید به سیستم <a href="//fa.wikivoyage.org/wiki/Special:Login" target="_blank">وارد شوید</a>، برای اطلاعات بیشتر <a href="//fa.wikivoyage.org/wiki/%D9%88%DB%8C%DA%A9%DB%8C%E2%80%8C%D8%B3%D9%81%D8%B1:%D9%88%D8%B1%D9%88%D8%AF_%DB%8C%DA%A9%D9%BE%D8%A7%D8%B1%DA%86%D9%87" target="_blank">ویکی\u200cسفر:ورود یکپارچه</a> را بخوانید.</div>'));
return form;
};
ListingEditor.validateForm = function () {
//TODO more form validation?
if ($('#input-name').val() == '' && $('#input-address').val() == '' && $('#input-alt').val() == '') {
alert(ListingEditor.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;
};
ListingEditor.upperCaseFirst = function (str) {
str = str.toLowerCase().replace(/\b[a-z]/g, function(letter) {
return letter.toUpperCase();
});
return str;
};
ListingEditor.preview = function () {
var listing = {};
for ( var key in ListingEditor.allFields ) {
var parameter = ListingEditor.allFields[key]['parameter'];
listing[parameter]= $("#input-"+key).val();
}
if (listing[ListingEditor.allFields['type']['parameter']] != ListingEditor.listingTypes.sleep) {
listing[ListingEditor.allFields['checkin']['parameter']] = null;
listing[ListingEditor.allFields['checkout']['parameter']] = null;
}
else {
listing[ListingEditor.allFields['hours']['parameter']] = null;
}
var text = ListingEditor.listingToStr(listing);
$.ajax({
url: mw.config.get('wgScriptPath') + '/api.php?' + $.param({
action: 'parse',
prop: 'text',
contentmodel: 'wikitext',
format: 'json',
'text': text,
}),
beforeSend: function (xhr) {
if($('#listing-editor .preview-section').length == 0)
{
$('#listing-editor').append($('<hr/>'));
$('#listing-editor').append($('<h5/>').text(ListingEditor.translateStr['preview']));
$('#listing-editor').append($('<div/>')
.attr('class','preview-section')
.append($('<div/>')
.attr('class','preview-content')
)
.css('background-color','#fff')
.css('border-radius','10px')
.css('-moz-border-radius','10px')
.css('-webkit-border-radius','10px')
.css('padding','10px')
);
}
var loading = $('<span/>');
loading.attr('class','listing_previewing');
var img = $('<img/>');
img.attr('src',ListingEditor.loadingIcon);
loading.append(img);
loading.prepend(' ');
$('#listing-editor .preview-section').prepend(loading);
},
error: function(jqXHR, txt){
$('#listing-editor .preview-section .listing_previewing').remove();
},
success: function (data) {
$('#listing-editor .preview-section .listing_previewing').remove();
$('#listing-editor .preview-section .preview-content').html(data.parse.text['*']);
},
});
};
ListingEditor.formToText = function (mode, number) {
var listing = {};
for ( var key in ListingEditor.allFields ) {
var parameter = ListingEditor.allFields[key]['parameter'];
listing[parameter]= $("#input-"+key).val();
}
if (listing[ListingEditor.allFields['type']['parameter']] != ListingEditor.listingTypes.sleep) {
listing[ListingEditor.allFields['checkin']['parameter']] = null;
listing[ListingEditor.allFields['checkout']['parameter']] = null;
}
else {
listing[ListingEditor.allFields['hours']['parameter']] = null;
}
var text = ListingEditor.listingToStr(listing);
var summary = '/* ' + ListingEditor.sectionTitle + ' */ ';
if (mode == 'add') {
summary += ListingEditor.translateStr['added'];
var index = ListingEditor.sectionText.indexOf('===');
if ( index == 0 ) {
index = ListingEditor.sectionText.indexOf('====');
}
if ( index > 0 ) {
ListingEditor.sectionText = ListingEditor.sectionText.substr(0, index) + '* ' + text
+ '\n' + ListingEditor.sectionText.substr(index);
}
else {
ListingEditor.sectionText += '\n'+ '* ' +text;
}
}
else {
if ($('#input-closed').is(':checked')) {
text = '';
summary += ListingEditor.translateStr['removed'];
var listRegex = new RegExp('\\n\\*+\\s?'+ListingEditor.replaceSpecial(ListingEditor.listingText));
ListingEditor.sectionText = ListingEditor.sectionText.replace(listRegex, ListingEditor.listingText);
}
else {
summary += ListingEditor.translateStr['updated'];
}
ListingEditor.sectionText = ListingEditor.sectionText.replace(ListingEditor.listingText, text);
}
summary += $("#input-name").val();
ListingEditor.saveForm(summary, ListingEditor.sectionText, number, '', '');
return;
};
ListingEditor.savingForm = function () {
var progress = $('<div id="progress-dialog">'+ListingEditor.translateStr['saving']+'...</div>');
progress.dialog({
modal: true,
height: 100,
width: 300,
title: ''
});
$(".ui-dialog-titlebar").hide();
};
ListingEditor.saveForm = function (summary, content, number, cid, answer) {
for (var key in ListingEditor.replacements) {
var val = ListingEditor.replacements[key];
content = content.replace(key, val);
}
ListingEditor.replacements = {};
$.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( 'خطا: API کد مقابل را برگرداند "' + data.error.code + '": ' + data.error.info );
} else if ( data && data.edit.spamblacklist ) {
alert( 'خطا: "'+ data.edit.spamblacklist + '" در فهرست سیاه قرار دارد' );
$('#progress-dialog').dialog('destroy').remove();
} else if ( data && data.edit.captcha ) {
var captcha = $('<div id="captcha-dialog">').text(ListingEditor.translateStr['external-links']);
var image = $('<img class="fancycaptcha-image">')
.attr('src', data.edit.captcha.url)
.appendTo(captcha);
var label = $('<label for="input-captcha">').text(ListingEditor.translateStr['enter-captcha']).appendTo(captcha);
var input = $('<input id="input-captcha" type="text">').appendTo(captcha);
captcha.dialog({
title: ListingEditor.translateStr['enter-captcha'],
buttons: [
{ text: ListingEditor.translateStr['submit'], click: function() {
ListingEditor.saveForm(summary, content, number, data.edit.captcha.id, $('#input-captcha').val());
}
},
{ text: ListingEditor.translateStr['cancel'], click: function() {
$(this).dialog('destroy').remove();
$('#progress-dialog').dialog('destroy').remove();
}}
]
});
} else {
alert( 'خطا: نتیجه نامعلوم از API دریافت شد.' );
}
},
error: function( xhr ) {
alert( 'خطا: درخواست ناموفق بود.' );
}
} )
ListingEditor.savingForm();
};
ListingEditor.listingToStr = function (listing) {
var saveStr = '{{'+listing[ListingEditor.allFields['type']['parameter']];
if (!ListingEditor.inlineListing && ListingEditor.allFields['type']['newline']) saveStr += '\n';
for ( var key in ListingEditor.allFields ) {
var parameter = ListingEditor.allFields[key]['parameter'];
if (key != 'type' && listing[parameter] != null) {
if (ListingEditor.inlineListing) {
if (listing[parameter] != '') {
saveStr += ' | ' + parameter + '=' +listing[parameter];
}
}
else {
if (key != 'image' || listing[ListingEditor.allFields['image']['parameter']] != '') {
saveStr +='| '+parameter+ '=' + listing[parameter];
}
if (ListingEditor.allFields[key]['newline']) {
saveStr += '\n';
}
else {
saveStr += ' ';
}
}
}
}
saveStr += '}}';
return saveStr;
};
ListingEditor.init = function() {
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;
}
ListingEditor.wrapContent();
ListingEditor.addListingButtons();
ListingEditor.addEditButtons();
};
// only run on supported skins
// (on mobile this breaks section collapsing)
if ( mw.config.get( 'skin' ) !== 'minerva' ) {
$(ListingEditor.init);
}