MediaWiki:Gadget-translation-editor.js: Różnice pomiędzy wersjami
Usunięta treść Dodana treść
dodanie '#pl' do URL podczas przeladowywania strony po zapisaniu zmian; Specjalna:Diff/5361303 nie dzialalo poprawnie, gdy adres juz zawieral ow hash (Specjalna:Diff/5983121/5984970) |
HTML zwracany przez parser znajduje sie teraz wewnatrz <div class="mw-parser-output"></div> |
||
Linia 590: | Linia 590: | ||
var $parsed, $els, links; |
var $parsed, $els, links; |
||
$parsed = $( data.parse.text ).filter( 'p' ).first(); |
$parsed = $( data.parse.text ).filter( '.mw-parser-output' ).children( 'p' ).first(); |
||
$els = $parsed.find( 'a' ); |
$els = $parsed.find( 'a' ); |
||
Wersja z 23:52, 27 maj 2017
var gadget = mw.libs.translationEditor = {};
var PREFERRED_LANG_OPTION_KEY = 'userjs-translation-editor-preferred-lang';
var PREFERRED_LANG_COOKIE = 'TranslationEditorPreferredLang';
var POST_EDIT_COOKIE_KEY = 'PostEditTranslationEditor';
var EDITBOX_TOP_OFFSET = 100;
var EDITBOX_SCROLL_DURATION = 500;
var forbiddenLanguageNames = [ 'polski', 'termin obcy w języku polskim', 'użycie międzynarodowe' ];
var forbiddenLanguageCodes = [];
var errorNotifOpts = {
autoHide: false,
type: 'error'
};
var postEditCookieOpts = {
expires: 1200 // za EditPage::POST_EDIT_COOKIE_DURATION w EditPage.php
};
var pageContent, pageDraft, translations, api;
var starttimestamp, basetimestamp;
var startIndex, endIndex;
var messages = {
'transl-add-translation': '(dodaj)',
'transl-api-error': 'Błąd API. Kod: $1. Komunikat: $2.',
'transl-save-error': 'Prawdopodobnie nastąpił konflikt edycji. Przeładuj stronę i spróbuj ponownie.',
'transl-edit-error': 'Możliwość edytowania istniejących tłumaczeń zostanie wdrożona w przyszłości.',
'transl-parse-error': 'Nie udało się odczytać kodu strony. Przejdź na tryb edycji i sprawdź, czy nie ma błędów w formacie.',
'transl-load-error': 'Istnieje nowsza wersja strony. Przeładuj ją i spróbuj ponownie.',
'transl-select-lang': 'Wybierz język:',
'transl-lang-label': 'Tłumaczysz na<br><strong>$1</strong>',
'transl-lang-label-iso': 'Tłumaczysz na<br><strong>$1</strong> <small>(<a href="/wiki/Wikis%C5%82ownik:Kody_j%C4%99zyk%C3%B3w" target="_blank">$2</a>)</small>',
'transl-load-button': 'Załaduj',
'transl-save-button': 'Zapamiętaj',
'transl-forget-button': 'Zapomnij',
'transl-save-save': 'Zapisz',
'transl-save-cancel': 'Anuluj',
'transl-prompt-title': 'Ustawienia domyślnego języka',
'transl-save-prompt': 'Język o nazwie „$1” zostanie załadowany domyślnie podczas następnego uruchomienia edytora tłumaczeń.',
'transl-save-current': 'Twoje obecne ustawienie to „$1”.',
'transl-forget-prompt': 'Język o nazwie „$1” przestanie być ładowany domyślnie.',
'transl-save-success': 'Zapisano preferencje.',
'transl-save-fail': 'Wystąpił błąd podczas zapisywania preferencji.',
'transl-preview-label': 'Podgląd zmian',
'transl-apply-button': 'Pokaż zmiany',
'transl-submit-button': 'Zapisz',
'transl-watch-article': 'Obserwuj',
'transl-submitting': 'Zapisywanie',
'transl-reloading': 'Przeładowywanie',
'transl-draft-change': '(przejdź)',
'transl-draft-remove': '(usuń)',
'transl-draft-abort': '(wstrzymaj)',
'transl-keyboard': '(klawiatura ekranowa)',
'transl-keyboard-close': 'Zamknij',
'transl-report-error': '(<a href="//pl.wiktionary.org/w/index.php?title=Dyskusja_wikipedysty:Peter_Bowman&action=edit§ion=new&preloadtitle=Edytor%20t%C5%82umacze%C5%84%20%28b%C5%82%C4%85d%29&nosummary=" target="_blank">zgłoś błąd</a>)',
'transl-help-syntax': '(<a href="//upload.wikimedia.org/wiktionary/pl/1/1d/Edytor_t%C5%82umacze%C5%84_%28sk%C5%82adnia%29.png" target="_blank">składnia</a>)',
'transl-lang-suggest-code': 'Język z kodem <strong>$1</strong>',
'transl-forbidden-lang': 'Brak wsparcia dla języka: $1.',
'transl-confirm-close': 'Masz niezapisane tłumaczenia. Czy na pewno chcesz opuścić stronę?',
'transl-preview-parsing': 'poczekaj, trwa parsowanie wikikodu'
};
var config = mw.config.get( [
'wgPageName',
'wgNamespaceNumber',
'wgAction',
'wgRevisionId',
'wgCurRevisionId',
'wgArticleId'
] );
function initialize( $content ) {
var $transl, $defs, $buttonHolder;
gadget.activeLang = '';
gadget.defn = [];
gadget.langs = [];
gadget.drafts = {};
gadget.currentRequest = null;
gadget.preferredLang = !mw.user.isAnon()
? mw.user.options.get( PREFERRED_LANG_OPTION_KEY )
: mw.cookie.get( PREFERRED_LANG_COOKIE );
$transl = $content.find( 'dt.lang-pl.fldt-tlumaczenia' ).first();
$defs = $content.find( 'dd.lang-pl.fldt-znaczenia' );
if ( !$transl.length || !$defs.length ) {
return;
}
$transl
.attr( 'id', 'transl-field' )
.children( '#transl' )
.css( 'display', 'inline' );
$buttonHolder = $( '<div>' )
.attr( 'id', 'transl-buttons' )
.appendTo( $transl );
if ( !!gadget.preferredLang && typeof hideTranslations === 'function' ) {
hideTranslations( gadget.preferredLang );
}
extractDefinitions( $defs );
if ( gadget.defn.length !== $defs.length ) {
return;
}
$( '<small>' )
.text( mw.msg( 'transl-add-translation' ) )
.attr( 'id', 'transl-addbutton' )
.attr( 'accesskey', '+' )
.appendTo( $buttonHolder )
.one( 'click', $.proxy( loadEditor, null, $content, $transl ) )
.on( 'click', function () {
$content.find( '#transl-editbox' ).toggle();
$content.find( '#transl-langselector' ).trigger( 'focus' );
} );
$transl.parent().show();
}
function loadEditor( $content, $transl, evt ) {
var $spinner = $.createSpinner( {
size: 'large',
type: 'block'
} ).appendTo( $transl );
makeRequests( function () {
var $editbox = $content.find( '#transl-editbox' );
$spinner.remove();
$editbox.fadeIn();
if ( !$editbox.length ) {
$( '#transl-addbutton' ).hide();
return;
}
if ( $editbox.offset().top - $( window ).scrollTop() > EDITBOX_TOP_OFFSET ) {
$( 'html, body' ).animate( {
scrollTop: $editbox.offset().top - EDITBOX_TOP_OFFSET
}, EDITBOX_SCROLL_DURATION );
}
} );
}
function makeRequests( callback ) {
mw.loader.using( [
'mediawiki.api.edit',
'mediawiki.api.options',
'mediawiki.language.specialCharacters',
'mediawiki.RegExp',
'mediawiki.notify',
'mediawiki.confirmCloseWindow',
'jquery.suggestions',
'jquery.byteLength',
'jquery.tipsy',
'jquery.textSelection',
'jquery.ui.dialog',
'ext.gadget.langdata'
] )
.then( function () {
api = new mw.Api();
config.lang2code = mw.config.get( 'lang2code' );
config.code2lang = mw.config.get( 'code2lang' );
$.each( forbiddenLanguageNames, function ( i, lang ) {
if ( lang in config.lang2code ) {
forbiddenLanguageCodes.push( config.lang2code[ lang ] );
}
} );
return api.get( {
formatversion: 2,
prop: 'revisions',
rvprop: [ 'timestamp', 'content', 'ids' ],
titles: config.wgPageName,
curtimestamp: true
} );
} )
.done( function ( res ) {
var revision = res.query.pages[ 0 ].revisions[ 0 ];
if ( revision.revid !== config.wgCurRevisionId ) {
mw.notify( mw.msg( 'transl-load-error' ), errorNotifOpts );
} else {
pageContent = revision.content;
starttimestamp = res.curtimestamp;
basetimestamp = revision.timestamp;
if ( analyzePage() ) {
createMenu();
} else {
mw.notify( mw.msg( 'transl-parse-error' ), errorNotifOpts );
}
}
} )
.done( callback )
.fail( function ( code, details ) {
if ( typeof details === 'object' ) {
details = details.error && details.error.info || details.textStatus || '---';
}
mw.notify( mw.msg( 'transl-api-error', code, details ), errorNotifOpts );
} );
}
function extractDefinitions( $defs ) {
$defs.each( function () {
var m, text = $( this ).children( 'dfn' ).text();
if ( !text ) {
text = $( this ).text();
}
m = text.match( /^(\(.+?\)) (.+)/ );
if ( m && m[ 1 ] ) {
gadget.defn.push( {
num: m[ 1 ],
text: m[ 2 ].replace( /\[\d+\]/g, '' )
} );
} else {
return false;
}
} );
}
function analyzePage() {
var a2, a3, a4, b, langSection, langs, targetLang, targetRow;
var a = pageContent.indexOf( ' ({' + '{język polski' );
if ( a === -1 ) {
a = pageContent.indexOf( ' ({' + '{termin obcy w języku polskim' );
}
if ( a === -1 ) {
return false;
}
b = pageContent.indexOf( '\n== ', a );
b = ( b !== -1 ) ? b : pageContent.length;
langSection = pageContent.slice( 0, b );
a2 = langSection.indexOf( '{' + '{tłumaczenia}}\n', a );
b = langSection.indexOf( '{' + '{źródła}}', a2 );
if ( a2 === -1 || b === -1 ) {
return false;
}
translations = langSection.slice( 0, b );
a3 = translations.indexOf( '\n*', a2 );
if (
a3 !== -1 &&
translations.slice( a3 ).indexOf( '{{zobtłum' ) !== -1
) {
a3 = translations.lastIndexOf( '{{zobtłum' );
a3 = translations.indexOf( '\n*', a3 );
}
if ( a3 !== -1 ) {
langs = [];
$.each(
translations.slice( a3 + 1, b ).split( '\n' ),
function ( i, line ) {
var res = line.match( /^\* +([^:]+):/ );
if ( res && res[ 1 ] ) {
langs.push( res[ 1 ] );
}
} );
if ( !langs.length ) {
return false;
}
gadget.langs = langs;
startIndex = a3 + 1;
} else {
startIndex = b;
}
endIndex = b;
translations = pageContent.substring( startIndex, endIndex );
return true;
}
function getLangPos( target ) {
var n, lang, _char, p1, p2;
var abc = 'aąbcćdeęfghijklłmnńoópqrsśtuvwxyzźż';
var index = -1;
outer:
for ( n = 0; n < gadget.langs.length; n++ ) {
lang = gadget.langs[ n ];
inner:
for ( _char = 0; _char < lang.length; _char++ ) {
p1 = abc.indexOf( target[ _char ] );
p2 = abc.indexOf( lang[ _char ] );
if ( p1 > p2 ) {
index++;
continue outer;
} else if ( p1 === p2 ) {
if ( _char === lang.length - 1 ) {
if ( target.length > lang.length ) {
index++;
}
return gadget.langs[ index ];
} else {
continue inner;
}
} else {
break outer;
}
}
}
return gadget.langs[ index ];
}
function prepareDraft() {
$.each( gadget.drafts, function ( lang, draft ) {
var targetLang, targetRow, pos, translation;
if ( gadget.langs.length ) {
targetLang = getLangPos( lang );
}
if ( targetLang ) {
targetRow = mw.format( '\\* +$1:', mw.RegExp.escape( targetLang ) );
pos = translations.search( targetRow );
pos = translations.indexOf( '\n', pos ) + 1;
} else {
pos = 0;
}
translation = mw.format( '$1: $2\n', lang, serializeDraft( draft ) );
translations =
translations.slice( 0, pos ) +
'* ' + translation +
translations.slice( pos, translations.length );
gadget.langs.splice( gadget.langs.indexOf( targetLang ) + 1, 0, lang );
} );
pageDraft =
pageContent.slice( 0, startIndex ) +
translations +
pageContent.slice( endIndex, pageContent.length );
}
function resetForms( gui ) {
gadget.activeLang = null;
gui.$langLabel.html( mw.msg( 'transl-select-lang' ) ),
gui.$langSelector.val( '' ).trigger( 'focus' );
gui.$saveButton.prop( 'disabled', true );
gui.$textInputs.find( 'input' ).val( '' );
gui.$apply.prop( 'disabled', true );
gui.$textInputs.find( 'input' ).prop( 'disabled', true );
if ( $.isEmptyObject( gadget.drafts ) ) {
gui.$watch.prop( 'disabled', true );
gui.$submit.prop( 'disabled', true );
}
}
function onLoadLang( gui, targetLang, evt ) {
var lang = targetLang || gui.$langSelector.val();
var draft = gadget.drafts[ lang ];
evt && evt.preventDefault();
if ( !lang ) {
return;
}
if ( gadget.currentRequest ) {
gadget.currentRequest.abort();
}
resetForms( gui );
if ( !draft && gadget.langs.indexOf( lang ) !== -1 ) {
mw.notify( mw.msg( 'transl-edit-error' ), { type: 'warn' } );
return;
}
if ( forbiddenLanguageNames.indexOf( lang ) !== -1 ) {
mw.notify( mw.msg( 'transl-forbidden-lang', lang ), { type: 'error' } );
return;
}
gadget.activeLang = lang;
gui.$langLabel.html( lang in config.lang2code
? mw.msg( 'transl-lang-label-iso', lang, config.lang2code[ lang ] )
: mw.msg( 'transl-lang-label', lang )
);
gui.$saveButton
.prop( 'disabled', false )
.attr( 'value', gadget.preferredLang === lang
? mw.msg( 'transl-forget-button' )
: mw.msg( 'transl-save-button' )
);
gui.$textInputs.find( 'input' ).prop( 'disabled', false );
if ( draft ) {
gui.$textInputs.children().each( $.proxy( loadDrafts, null, draft ) );
}
refreshPreview( gui, lang );
gui.$apply.prop( 'disabled', false );
setTimeout( function () {
gui.$textInputs.find( 'input' ).first().trigger( 'focus' );
}, 1 );
}
function loadDrafts( draft, i, el ) {
var $el = $( el );
var defn = $el.data( 'defn' );
var $inputs = $el.children( 'input' );
var $text = $inputs.first();
var $tmpl = $inputs.last();
var text = [], tmpl = [];
if ( !draft[ defn ] ) {
return true;
}
$.each( draft[ defn ], function ( i, obj ) {
text.push( stripBrackets( obj.base ) );
tmpl.push( stripBrackets( obj.template || '' ) );
} );
$text.val( text.join( ', ' ) );
if ( tmpl.join( '' ) !== '' ) {
$tmpl.val( tmpl.join( ',' ) );
}
}
function onSaveLang( gui, evt ) {
var message, updateLang, newValue;
if ( gadget.activeLang !== gadget.preferredLang ) {
message = mw.msg( 'transl-save-prompt', gadget.activeLang );
if ( !!gadget.preferredLang ) {
message += ' ' + mw.msg( 'transl-save-current', gadget.preferredLang );
}
updateLang = true;
} else {
message = mw.msg( 'transl-forget-prompt', gadget.preferredLang );
updateLang = false;
}
newValue = updateLang ? gadget.activeLang : null;
gui.$confirmDialog.append( message ).data( {
newValue: newValue,
updateLang: updateLang
} ).dialog( 'open' );
}
function savePreferredLangRequest( gui ) {
var newValue = gui.$confirmDialog.data( 'newValue' );
var updateLang = gui.$confirmDialog.data( 'updateLang' );
if ( !mw.user.isAnon() ) {
return api.saveOption( PREFERRED_LANG_OPTION_KEY, newValue )
.done( function () {
gadget.preferredLang = newValue;
gui.$saveButton.attr( 'value', mw.msg( updateLang
? 'transl-forget-button'
: 'transl-save-button'
) );
mw.notify( mw.msg( 'transl-save-success' ) );
} );
} else {
mw.cookie.set( PREFERRED_LANG_COOKIE, newValue );
gadget.preferredLang = newValue;
gui.$saveButton.attr( 'value', mw.msg( updateLang
? 'transl-forget-button'
: 'transl-save-button'
) );
mw.notify( mw.msg( 'transl-save-success' ) );
return $().promise();
}
}
function stripBrackets( s ) {
return s.replace( /^[\[\{]{2}([^\|\[\]\{\}]+?)[\]\}]{2}$/, '$1' );
}
function onApplyChanges( gui, evt ) {
var apiPromise, draft = {};
evt && evt.preventDefault();
gui.$textInputs.children().each( $.proxy( constructDrafts, null, draft ) );
if ( $.isEmptyObject( draft ) ) {
return;
}
gui.$watch.prop( 'disabled', true );
gui.$submit.prop( 'disabled', true );
gadget.drafts[ gadget.activeLang ] = draft;
apiPromise = api.get( {
formatversion: 2,
action: 'parse',
text: serializeDraft( draft ),
contentmodel: 'wikitext',
disablelimitreport: true
} );
gadget.currentRequest = draft.request = apiPromise
.then( function ( data ) {
return parsedWikitextCallback( data, gadget.activeLang );
} )
.always( function () {
gadget.currentRequest = null;
delete draft.request;
gui.$watch.prop( 'disabled', false );
gui.$submit.prop( 'disabled', false );
} )
.promise( {
abort: apiPromise.abort
} );
refreshPreview( gui, gadget.activeLang );
}
function constructDrafts( draft, i, el ) {
var terms, tmpls, temp, arr;
var $this = $( el );
var $inputs = $this.children( 'input' );
var text = $.trim( $inputs.first().val() );
var tmpl = $.trim( $inputs.last().val() );
if ( !text ) {
return true;
}
terms = text.split( / *, */ );
tmpls = tmpl ? tmpl.split( / *, */ ) : null;
arr = [];
$.each( terms, function ( j, term ) {
var base, template;
if ( /[\[\]\(\)\{\}<>\/]/.test( term ) ) {
base = term;
} else {
base = '[' + '[' + term + ']]';
}
if ( tmpls && tmpls[ j ] ) {
template = '{' + '{' + tmpls[ j ] + '}}';
}
arr.push( {
base: base,
template: template
} );
} );
draft[ $this.data( 'defn' ) ] = arr;
}
function parsedWikitextCallback( data, lang ) {
var $parsed, $els, links;
$parsed = $( data.parse.text ).filter( '.mw-parser-output' ).children( 'p' ).first();
$els = $parsed.find( 'a' );
if ( !$els.length || !( lang in config.lang2code ) ) {
return $parsed;
}
// TODO: użycie modułu sectionLinks
$els.each( function () {
var href = $( this ).attr( 'href' );
if ( href.indexOf( '#' ) === -1 ) {
href += '#' + config.lang2code[ lang ];
$( this ).attr( 'href', href );
}
} );
if ( Number( mw.user.options.get( 'gadget-false-blue-links' ) ) ) {
links = data.parse.links.filter( function ( obj ) {
return obj.ns === 0 && obj.exists;
} ).map( function ( obj ) {
return obj.title;
} );
// TODO: sprawdzić, czy da się wstrzymać ('abort') z poziomu draft.request
gadget.currentRequest = mw.libs.falseBlueLinks.inspectTitles( links );
return gadget.currentRequest.then( function () {
mw.libs.falseBlueLinks.processElements( $parsed );
return $parsed;
} );
} else {
return $parsed;
}
}
function serializeDraft( obj ) {
// TODO: czy można tego uniknąć?
var copy = $.extend( true, {}, obj );
delete copy.parsed;
delete copy.request;
return $.map( copy, function ( data, defn ) {
return defn + ' ' + $.map( data, function ( word ) {
return ( word.template
? word.base + ' ' + word.template
: word.base
);
} ).join( ', ' );
} ).join( '; ' );
}
function refreshPreview( gui, active ) {
var $ul = $( '<ul>' );
$.each( gadget.drafts, function ( lang, draft ) {
var $li, $change, $remove, $abort, $preview, $serializedPreview;
$serializedPreview = $( '<code>' )
.addClass( 'transl-preview-entry' )
.text( serializeDraft( draft ) );
$change = $( '<small>' ).text( mw.msg( 'transl-draft-change' ) );
$remove = $( '<small>' ).text( mw.msg( 'transl-draft-remove' ) );
$abort = $( '<small>' ).text( mw.msg( 'transl-draft-abort' ) );
if ( draft.request ) {
$change.hide();
$remove.hide();
$preview = $( '<span>' )
.addClass( 'transl-parsing transl-preview-entry' )
.text( mw.msg( 'transl-preview-parsing' ) );
draft.request
.done( function ( $parsed ) {
$preview.removeClass( 'transl-parsing' ).html( $parsed.html() );
draft.parsed = $preview;
} )
.fail( function () {
$preview.replaceWith( $serializedPreview );
delete draft.parsed;
} )
.always( function () {
$change.show();
$remove.show();
$abort.hide();
} );
} else {
$abort.hide();
$preview = draft.parsed || $serializedPreview;
}
$li = $( '<li>' )
.append(
$( '<strong>' ).text( mw.format( '$1:', lang ) ),
$preview, $change, $remove, $abort
)
.appendTo( $ul );
if ( lang === active ) {
$li.addClass( 'transl-active' );
$change.addClass( 'disabled' );
} else {
$change.on( 'click', function () {
gadget.activeLang = lang;
onLoadLang( gui, lang );
$ul.children().removeClass( 'transl-active' );
$li.addClass( 'transl-active' );
} );
}
$remove.on( 'click', function () {
delete gadget.drafts[ lang ];
$li.remove();
if ( lang === active ) {
if ( gadget.currentRequest ) {
gadget.currentRequest.abort();
}
resetForms( gui );
}
} );
$abort.on( 'click', function () {
if ( gadget.currentRequest ) {
gadget.currentRequest.abort();
}
} );
} );
gui.$preview.replaceWith( $ul );
gui.$preview = $ul;
}
function makeSummary() {
var s, sortedDrafts, serializedDrafts, buildString;
buildString = function ( a, delimiter ) {
return '+tłumaczenie na ' + a.join( delimiter );
};
sortedDrafts = $.map( gadget.drafts, function ( data, lang ) {
return {
lang: lang,
data: data
};
} );
sortedDrafts.sort( function ( a, b ) {
return a.lang.localeCompare( b.lang, 'pl' );
} );
serializedDrafts = $.map( sortedDrafts, function ( obj ) {
return mw.format( '$1: $2', obj.lang, serializeDraft( obj.data ) );
} );
s = buildString( serializedDrafts, ' • ' );
if ( $.byteLength( s ) > 255 ) {
serializedDrafts = $.map( sortedDrafts, function ( obj ) {
return obj.lang;
} );
s = buildString( serializedDrafts, ', ' );
}
return s;
}
function onSubmit( gui, evt ) {
evt.preventDefault();
prepareDraft();
gui.$submit
.prop( 'disabled', true )
.attr( 'value', mw.msg( 'transl-submitting' ) );
api.postWithEditToken( {
action: 'edit',
title: config.wgPageName,
text: pageDraft,
tags: 'translation-editor',
summary: makeSummary(),
watchlist: gui.$watch.prop( 'checked' ) ? 'watch' : 'nochange',
notminor: true,
starttimestamp: starttimestamp,
basetimestamp: basetimestamp
} )
.done( function () {
var cookieKey = POST_EDIT_COOKIE_KEY + config.wgArticleId;
gui.$submit.attr( 'value', mw.msg( 'transl-reloading' ) );
mw.cookie.set( cookieKey, 'saved', postEditCookieOpts );
location.pathname = mw.util.getUrl() + '#pl';
} )
.fail( function () {
mw.notify( mw.msg( 'transl-save-error' ), errorNotifOpts );
} );
}
// [mediawiki/extensions/WikiEditor] / modules / jquery.wikiEditor.toolbar.js
function buildCharacter( character, actions ) {
if ( typeof character === 'string' ) {
character = {
label: character,
action: {
type: 'replace',
options: {
peri: character,
selectPeri: false
}
}
};
// In some cases the label for the character isn't the same as the
// character that gets inserted (e.g. Hebrew vowels)
} else if ( character && 0 in character && 1 in character ) {
character = {
label: character[ 0 ],
action: {
type: 'replace',
options: {
peri: character[ 1 ],
selectPeri: false
}
}
};
}
if ( character && 'action' in character && 'label' in character ) {
actions[ character.label ] = character.action;
if ( character.titleMsg !== undefined ) {
return mw.html.element( 'span', {
rel: character.label,
title: mw.msg( character.titleMsg )
}, character.label );
} else {
return mw.html.element( 'span', {
rel: character.label
}, character.label );
}
}
mw.log( 'A character for the toolbar was undefined. This is not supposed to happen. Double check the config.' );
// bug 31673; also an additional fix for bug 24208...
return '';
}
function unicodeToAscii( s ) {
var n, ch, index;
var out = '';
var utf = 'ąåãáćçęèłńóõüśźż';
var ascii = 'aaaacceelnoouszz';
for ( n = 0; n < s.length; n++ ) {
ch = s.charAt( n );
index = utf.indexOf( ch );
if ( index !== -1 ) {
out += ascii.charAt( index );
} else {
out += ch;
}
}
return out;
}
function createMenu() {
var gui = {}, $activeTextInput = $( [] ), charActions = {}, allowCloseWindow;
allowCloseWindow = mw.confirmCloseWindow( {
test: function () {
return !$.isEmptyObject( gadget.drafts );
},
message: mw.msg( 'transl-confirm-close' ),
namespace: 'translationeditor-editwarning'
} );
gui.$langSelector = $( '<input>' )
.attr( {
id: 'transl-langselector',
type: 'text',
size: 22
} );
gui.$textInputs = $( '<div>' )
.attr( 'id', 'transl-textinputs' );
$.each( gadget.defn, function ( i, defn ) {
var $num;
$( '<div>' )
.data( 'defn', defn.num )
.append(
$num = $( '<span>' )
.addClass( 'transl-def-label' )
.attr( 'title', defn.text )
.text( defn.num ),
$( '<input>' )
.attr( {
type: 'text',
size: 50
} ),
$( '<input>' )
.attr( {
type: 'text',
size: 1
} )
)
.appendTo( gui.$textInputs );
$num.tipsy( {
gravity: 'e'
} );
} );
gui.$loadButton = $( '<input>' )
.attr( {
type: 'button',
value: mw.msg( 'transl-load-button' )
} )
.on( 'click', $.proxy( onLoadLang, this, gui, null ) );
gui.$saveButton = $( '<input>' )
.attr( {
type: 'button',
value: mw.msg( 'transl-save-button' )
} )
.on( 'click', $.proxy( onSaveLang, this, gui ) );
gui.$apply = $( '<input>' )
.attr( {
type: 'button',
value: mw.msg( 'transl-apply-button' )
} )
.on( 'click', $.proxy( onApplyChanges, this, gui ) );
gui.$submit = $( '<input>' )
.attr( {
type: 'button',
value: mw.msg( 'transl-submit-button' )
} )
.on( 'click', allowCloseWindow.release )
.on( 'click', $.proxy( onSubmit, this, gui ) );
gui.$watch = $( '<input>' )
.attr( {
type: 'checkbox',
id: 'transl-watch'
} )
.prop( 'checked', !!Number( mw.user.options.get( 'watchdefault' ) ) );
gui.$specialCharsButton = $( '<small>' )
.html( mw.msg( 'transl-keyboard' ) )
.on( 'click', function () {
gui.$keyboard.show();
} );
gui.$previewbox = $( '<div>' )
.attr( 'id', 'transl-preview' )
.append(
$( '<div>' ).append(
gui.$specialCharsButton,
' ',
$( '<small>' ).html( mw.msg( 'transl-report-error' ) ),
' ',
$( '<small>' ).html( mw.msg( 'transl-help-syntax' ) )
),
$( '<strong>' ).text( mw.msg( 'transl-preview-label' ) ),
gui.$preview = $( '<ul>' )
);
gui.$keyboard = $( '<div>' )
.attr( 'id', 'transl-keyboard' )
.hide()
.append(
gui.$keyboardSelect = $( '<select>' ),
$( '<input>' )
.attr( {
type: 'button',
value: mw.msg( 'transl-keyboard-close' )
} )
.on( 'click', function ( evt ) {
evt.preventDefault();
gui.$keyboard.hide();
} ),
gui.$keyboardChars = $( '<div>' )
.attr( 'id', 'transl-special-chars' )
)
.appendTo( mw.util.$content );
$.each( mw.language.specialCharacters, function ( group, chars ) {
var $group = $( '<div>' )
.hide()
.attr( 'data-group', group )
.appendTo( gui.$keyboardChars );
$( '<option>' )
.attr( 'value', group )
.text( mw.msg( 'special-characters-group-' + group ) )
.appendTo( gui.$keyboardSelect );
$.each( chars, function ( i, character ) {
$( buildCharacter( character, charActions ) ).appendTo( $group );
} );
} );
gui.$keyboardSelect.on( 'change', function () {
var group = $( this ).find( ':selected' ).attr( 'value' );
gui.$keyboardChars.children().hide();
gui.$keyboardChars.find( '[data-group=' + group + ']' ).show();
mw.cookie.set( 'TranslatorKeyboardGroup', group );
} );
gui.$keyboardSelect
.find( mw.format(
'[value="$1"]',
mw.cookie.get( 'TranslatorKeyboardGroup', null, 'latin' )
) )
.prop( 'selected', true )
.end()
.trigger( 'change' );
gui.$keyboardChars.on( 'click', 'span', function () {
var label = $( this ).text();
var action = charActions[ label ];
var replace = ( action.type === 'replace' );
// jquery.wikiEditor.toolbar.js, doAction()
$activeTextInput.textSelection(
'encapsulateSelection',
$.extend( {}, action.options, {
replace: replace
} )
).trigger( 'keypress' );
} );
gui.$editbox = $( '<div>' )
.attr( 'id', 'transl-editbox' )
.hide()
.append(
$( '<div>' ).append(
gui.$langLabel = $( '<p>' )
.attr( 'id', 'transl-lang-label' ),
gui.$langSelector,
$( '<div>' )
.attr( 'id', 'transl-selector-buttons' )
.append(
gui.$loadButton, gui.$saveButton
)
),
gui.$textInputs,
$( '<div>' )
.attr( 'id', 'transl-edit-buttons' )
.append(
gui.$apply, gui.$submit, gui.$watch,
$( '<label>' )
.attr( 'for', 'transl-watch' )
.text( mw.msg( 'transl-watch-article' ) )
),
$( '<hr>' ),
gui.$previewbox
)
.appendTo( '#transl-field' );
gui.$editbox.on( 'focus', 'input[type="text"]', function () {
$activeTextInput = $( this );
} );
gui.$langSelector.suggestions( {
fetch: function ( input, response, maxRows ) {
var langs = $.map( config.lang2code, function ( code, lang ) {
return lang;
} );
input = unicodeToAscii( input.toLowerCase() );
response( $.grep( langs, function ( lang ) {
var normalized = unicodeToAscii( lang.toLowerCase() );
return (
normalized.indexOf( input ) === 0 &&
forbiddenLanguageNames.indexOf( lang ) === -1
);
} ) );
},
result: {
render: function ( suggestion, context ) {
context.data.$container.find( '.suggestions-special' ).hide();
this.text( suggestion );
},
select: function ( $input ) {
onLoadLang( gui, null );
}
},
special: {
render: function ( query, context ) {
var $label, $result;
if ( !this.children().length ) {
this.append(
$label = $( '<div>' ).addClass( 'special-label' ),
$result = $( '<div>' ).addClass( 'special-query' )
);
} else {
$label = this.find( '.special-label' );
$result = this.find( '.special-query' );
}
query = query.toLowerCase();
if (
query in config.code2lang &&
forbiddenLanguageCodes.indexOf( query ) === -1
) {
$label.html( mw.msg( 'transl-lang-suggest-code', query ) );
$result.text( config.code2lang[ query ] );
this.show();
}
},
select: function ( $input ) {
var lang = this.find( '.special-query' ).text();
$input.val( lang );
onLoadLang( gui, null );
}
},
highlightInput: true
} )
.on( 'keypress', function ( evt ) {
if ( evt.keyCode === 13 ) { // Enter
onLoadLang( gui, null );
}
} )
.on( 'paste cut drop', function ( evt ) {
$( this ).trigger( 'keypress' );
} );
gui.$confirmSpinner = $.createSpinner().css( 'margin-right', '1em' ).hide();
gui.$confirmDialog = $( '<p>' ).dialog( {
resizable: false,
minHeight: 150,
modal: true,
autoOpen: false,
draggable: false,
title: mw.msg( 'transl-prompt-title' ),
dialogClass: 'transl-dialog-no-close',
buttons: [
{
text: mw.msg( 'transl-save-save' ),
click: function () {
if ( gui.$confirmDialog.data( 'hasPendingRequest' ) ) {
return;
} else {
gui.$confirmSpinner.show();
gui.$confirmDialog.data( 'hasPendingRequest', true );
}
savePreferredLangRequest( gui )
.fail( function () {
mw.notify( mw.msg( 'transl-save-fail' ), errorNotifOpts );
} )
.always( function () {
gui.$confirmDialog.dialog( 'close' );
} );
}
},
{
text: mw.msg( 'transl-save-cancel' ),
click: function () {
if ( !gui.$confirmDialog.data( 'hasPendingRequest' ) ) {
gui.$confirmDialog.dialog( 'close' );
}
}
}
],
close: function ( event, ui ) {
gui.$confirmDialog.empty().removeData( 'hasPendingRequest' );
gui.$confirmSpinner.hide();
}
} );
gui.$textInputs.find( 'input' ).on( 'keypress', function ( evt ) {
if ( evt.keyCode === 13 ) { // Enter
onApplyChanges( gui );
}
} );
gui.$confirmSpinner.prependTo( gui.$confirmDialog.parent().find( '.ui-dialog-buttonset' ) );
resetForms( gui );
if ( !!gadget.preferredLang ) {
gadget.activeLang = gadget.preferredLang;
gui.$langSelector.val( gadget.activeLang );
onLoadLang( gui, gadget.activeLang );
}
}
if (
config.wgNamespaceNumber === 0 && config.wgAction === 'view' &&
config.wgRevisionId === config.wgCurRevisionId &&
!mw.util.getParamValue( 'printable' )
) {
if ( mw.cookie.get( POST_EDIT_COOKIE_KEY + config.wgArticleId ) === 'saved' ) {
mw.loader.using( 'mediawiki.action.view.postEdit' ).done( function () {
mw.hook( 'postEdit' ).fire();
mw.cookie.set( POST_EDIT_COOKIE_KEY + config.wgArticleId, null );
} );
}
mw.messages.set( messages );
mw.hook( Number( mw.user.options.get( 'gadget-hide-empty-fields' ) )
? 'hideEmptyFields.ready'
: 'sectionLinks.ready'
).add( initialize );
}