মিডিয়াউইকি:Gadget-Editor.js
অবয়ব
লক্ষ্য করুন: প্রকাশ করার পর, পরিবর্তনগুলো দেখতে আপনাকে আপনার ব্রাউজারের ক্যাশে পরিষ্কার করার প্রয়োজন হতে পারে।
- ফায়ারফক্স / সাফারি: পুনরায় লোড-এ ক্লিক করার সময় শিফট টিপে ধরে রাখুন, অথবা হয় Ctrl-F5 বা Ctrl-R টিপুন (ম্যাকে ⌘-R টিপুন)
- গুগল ক্রোম: Ctrl-Shift-R (ম্যাকে ⌘-Shift-R) টিপুন
- এজ: Ctrl ধরে রাখা অবস্থায় Refresh-এ ক্লিক করুন, অথবা Ctrl-F5 টিপুন।
- অপেরা: Ctrl-F5 টিপুন।
/******************************************************************
Listing Editor v1.4.1 (torty3)
********************************************************************/
( function ( mw, $ ) {
'use strict';
mw.loader.load( '/w/index.php?title=Mediawiki:Editor.css&action=raw&ctype=text/css', 'text/css' );
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-diff-ntitle1').length || $('#ca-viewsource').length ) {
return;
}
var allFields = {
'type': {size:8, right:true, newline:false, parameter:'ধরন', label:'ধরন', tip:'ধরন' },
'name': {size:50, right:false, newline:false, parameter:'নাম', label:'নাম', tip:'স্থানের নাম'},
'alt': {size:32, right:true, newline:false, parameter:'অন্য', label:'অন্য', tip:'এই নামেও পরিচিত'},
'url': {size:50, right:false, newline:false, parameter:'ইউআরএল', label:'ইউআরএল', tip:'http://www.exemplo.com'},
'email': {size:32, right:true, newline:false, parameter:'ইমেইল', label:'ইমেইল', tip:'hello@exemplo.com'},
'address': {size:50, right:false, newline:false, parameter:'ঠিকানা', label:'ঠিকানা', tip:'স্থানটির ঠিকানা'},
'lat': {size:10, right:true, newline:false, parameter:'অক্ষাংশ', label:'অক্ষাংশ', tip:'11.111111'},
'long': {size:10, right:true, newline:false, parameter:'দ্রাঘিমাংশ', label:'দ্রাঘিমাংশ', tip:'111.111111'},
'directions': {size:50, right:false, newline:false, parameter:'দিকনির্দেশ', label:'দিকনির্দেশ', tip:'কি ভাবে যাবেন'},
'phone': {size:28, right:false, newline:false, parameter:'ফোন', label:'ফোন', tip: '+৫৫ ৫৫৫ ৫৫৫-৫৫৫৫'},
'tollfree': {size:30, right:true, newline:false, parameter:'নিঃশুল্ক_ফোন_নম্বর', label:'নিঃশুল্ক_ফোন_নম্বর', tip:'+১-৮০০-১০০-১০০০'},
'fax': {size:20, right:true, newline:false, parameter:'ফ্যাক্স', label:'ফ্যাক্স', tip: '+৫৫ ৫৫৫ ৫৫৫-৫৫৫৫'},
'image': {size:20, right:true, newline:false, parameter:'চিত্র', label:'চিত্র', tip: 'স্থানের চিত্র'},
'hours': {size:28, right:false, newline:false, parameter:'সময়সূচী', label:'সময়সূচী', tip: '০৯:০০-১৭:০০'},
'checkin': {size:12, right:true, newline:false, parameter:'আগমন', label:'আগমন', tip: 'প্রবেশের সময়'},
'checkout': {size:12, right:true, newline:false, parameter:'প্রস্থান', label:'প্রস্থান', tip: 'প্রস্থানের সময়'},
'price': {size:28, right:false, newline:false, parameter:'মূল্য', label:'মূল্য', tip: 'প্রবেশমূল্য বা সেবামূল্য'},
'wikipedia': {size:30, right:true, newline:false, parameter:'উইকিপিডিয়া', label:'উইকিপিডিয়া', tip:'উইকিপিডিয়ার নিবন্ধ'},
'wikidata': {size:20, right:false, newline:false, parameter:'উইকিউপাত্ত', label:'উইকিউপাত্ত', tip:''},
'lastedit': {size:20, right:true, newline:false, parameter:'শেষ_সম্পাদনা', label:'শেষ সম্পাদনা', tip:''},
'content': {cols:34, rows:8, right:false, newline:false, parameter:'বিবরণ', label:'বিবরণ', tip: 'স্থানের বিবরণ'}
};
var currencySigns = ['\u00A3', '\u20AC', '\u00A5', '\u20A9'];
var listingTypes = {'see':'দেখুন', 'do':'করুন', 'buy':'কিনুন', 'eat':'আহার করুন', 'drink':'পান করুন', 'sleep':'রাত্রিযাপন', 'listing':'অন্যান্য'}
var sectionHeadings = {
'দেখুন': 'see',
'দর্শনীয়_স্থান': 'see',
'কী_দেখবেন': 'see',
'কি_দেখবেন': 'see',
'কী_করবেন': 'do',
'কিনুন': 'buy',
'কী_কিনবেন': 'buy',
'কি_কিনবেন': 'buy',
'খাওয়া': 'eat',
'কি_খাবেন': 'eat',
'কী_খাবেন': 'eat',
'আহার_করুন': 'eat',
'পানীয়': 'drink',
'পান_করুন': 'drink',
'রাত্রিযাপন': 'sleep',
'রাত্রি_যাপন': 'sleep',
'রাত্রীযাপন': 'sleep',
'রাত্রী_যাপন': 'sleep',
'কোথায়_থাকবেন': 'sleep',
'হোটেল': 'sleep',
'অপেক্ষা_করুন': 'see',
'দেখুন_ও_করুন': 'see',
'আহার_ও_পান_করুন': 'eat'
};
var LICENSE_TEXT = '"সংরক্ষণ করুন" ক্লিক করার মাধ্যমে, আপনি ব্যবহারের নীতিমালার সাথে সম্মত হচ্ছেন এবং একই সাথে আপনার অবদান <a class="external" target="_blank" href="http://en.wikivoyage.org/wiki/Wikivoyage:Full_text_of_the_Attribution-ShareAlike_3.0_license">সিসি বাই-এসএ ৩.০</a> লাইসেন্সের অধীনে প্রকাশের অনুমতি দিচ্ছেন।'
var translateStr = {
'add': 'তালিকাভুক্ত করুন',
'edit': 'সম্পাদনা',
'closed': 'মুছবেন?',
'saving': 'সংরক্ষিত হচ্ছে...',
'submit': 'সংরক্ষণ করুন',
'cancel': 'বাতিল',
'validationalert': 'দয়া করে একটি নাম বা ঠিকানা যোগ করুন',
'added': 'যোগ হয়েছে: ',
'updated': 'হালনাগাদ হয়েছে: ',
'removed': 'বাতিল হয়েছে: ',
'cities': 'শহর',
'destination': 'অন্যান্য গন্তব্য',
'geomap': 'মানচিত্রে অবস্থান',
'help-page': 'http://en.wikivoyage.org/wiki/Wikivoyage:Listing_editor',
'enter-captcha': 'CAPTCHA লিখুন',
'external-links': 'আপনার সম্পাদনায় নতুন বহিরাগত লিঙ্ক অন্তর্ভুক্ত রয়েছে।'
};
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" style="font-size:small;font-weight:normal;">')
.html(' [<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 () {
// css included as import stylesheet is too slow
var editButton = $('<span class="vcard-edit-button noprint"'
+ 'style="font-size:0.8em; color: rgb(150,150,150);">')
.html(' <a href="javascript:">'+translateStr['edit']+'</a>' )
.click(function() {
var listingEntry = $(this).parent();
popupForm('edit', listingEntry);
});
$('span.vcard').append( editButton );
}
/*** Functions to retrieve entry details ***/
function getIdentifier(entry) {
var id = {};
var name = entry.find('.org').text();
var address = entry.find('.label').text();
var alt = entry.find('.nickname').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');
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,' ');
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) {
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| type=$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'] && key == 'hours') node.hide();
if (key == 'checkin' || key == 'checkout' || key == 'fax' || key == 'image') node.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(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(' <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(' <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);
}
}
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, '<br>'));
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;
}
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 );
} 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']] != '') {
saveStr +='| '+parameter+ '=' + listing[parameter];
}
if (allFields[key]['newline']) {
saveStr += '\n';
}
else {
saveStr += ' ';
}
}
}
}
saveStr += '}}';
return saveStr;
}
} ( mediaWiki, jQuery ) );