ميډياويکي:Gadget-TemplateParamWizard.js
يادښت: د غوره توبونو د خوندي کولو وروسته، خپل د کتنمل (بروزر) ساتل شوې حافظه تازه کړی.د نور تفصيل لپاره د غځول په تنۍ کلېک وکړئ.
- فايرفاکس/ سفري: په دې کتنمل کې د Reload د ټکوهلو په وخت د Shift تڼۍ نيولې وساتی، او يا هم Ctrl-F5 يا Ctrl-Rتڼۍ کېښکاږۍ (په Apple Mac کمپيوټر باندې ⌘-R کېښکاږۍ)
- گووگل کروم: په دې کتنمل کې د Ctrl-Shift-R تڼۍ کېښکاږۍ (د مک لپاره ⌘-Shift-R)
- انټرنټ اېکسپلورر: په دې کتنمل کې د Refresh د ټکوهلو په وخت کې د Ctrl تڼۍ کېښکاږلې ونيسۍ، او يا هم د Ctrl-F5 تڼۍ کېښکاږۍ
- اوپرا: په دې کتنمل کې د خپل براوزر ساتل شوې حافظه پدې توگه سپينولی شی Tools→Preferences
لاسوند[جوړول]
// Template parameters wizard
// Written by [[User:קיפודנחש]]
'use strict';
if ( ( $.inArray( mw.config.get( 'wgAction' ), [ 'edit', 'submit' ] ) + 1 ) && ( !$( '#wpTextbox1' ).prop( 'readonly' ) ) ) {
$( function () {
// template parameter is an object with the following fields:
// desc: desciption string
// defval: default value (optional)
// options: object with optional fields:
// multiline: number of lines
// depends: another field's name
// required: boolean
// date: use JS date widget
// choices: array of legal values for the field
// extended: this field will not show on initial screen, and will appear once the user selects "show all fields"
var
// templateParams is keyed by paramName.
templateParams,
paramsOrder,
// which template are we working on
template,
// array of pairs - [paramName, inputField]
dialogFields,
// table rows keyed by paramName
rowsBypName,
// the fields, keyed by paramName
fieldsBypName,
// boolean, indicating we did not find "Parameters" page, so the parameters are extracted from template page itself.
rawTemplate,
rtl = $( 'body' ).is( '.rtl' ),
// test to see if a string contains wikiCode and hence needs parsing, or cen be used as is.
wikiCodeFinder = /[\[\]\{\}\<\>]/,
globalExplanation = '',
extendedParamCssRule,
anyExtended = false,
localStorageKey = 'templateParamWizard',
emptiesKey = 'writeEmpties';
function addParam( name ) {
if ( $.inArray( name, paramsOrder ) === -1 ) { paramsOrder.push( name ); }
}
function paramsFromSelection() {
var selection = $( '#wpTextbox1' ).textSelection( 'getSelection' ).replace( /^\s*\{\{|\}\}\s*$/g, '' ); // scrap the first {{ and last }}
var specials = [];
while ( true ) { // extract inner links, inner templates and inner params - we don't want to sptit those.
var match = selection.match( /(\{\{[^\{\}\]\[]*\}\}|\[\[[^\{\}\]\[]*\]\]|\[[^\{\}\]\[]*\])/ );
if ( !match || !match.length ) { break; }
specials.push( match[ 0 ] );
selection = selection.replace( match[ 0 ], '\0' + specials.length + '\0' );
}
var params = selection.split( /\s*\|\s*/ );
for ( var i in params ) {
var param = params[ i ];
while ( true ) {
var match = param.match( /\0(\d+)\0/ );
if ( !match || !match.length ) { break; }
param = param.replace( match[ 0 ], specials[ parseInt( match[ 1 ], 10 ) - 1 ] );
}
var paramPair = param.split( '=' );
var name = $.trim( paramPair.shift() );
if ( name && paramPair.length ) {
var tp = templateParams[ name ] = templateParams[ name ] || { options: { notInParamPage: 1 } },
val = paramPair.join( '=' );
addParam( name );
$.extend( tp.options, { defval: val } );
// next line is for the case where there are "choices"' but current value is not one of them: add it as a new choice.
if ( typeof tp.options.choices === 'string' && tp.options.choices.indexOf( val ) < 0 ) { tp.options.choices += ( ', ' + val ); }
}
}
}
function buildParamsRaw( data ) {
var
paramExtractor = /{{3,}(.*?)[<|}]/mg,
m;
while ( ( m = paramExtractor.exec( data ) ) ) {
var paramName = $.trim( m[ 1 ] );
templateParams[ paramName ] = { desc: '', options: { multiline: 5 } };
addParam( paramName );
}
}
function buildParams( data ) {
var
lines = data.split( '\n' ),
line;
function extractGlobalExplanation() {
line = line.replace( /[!\|][^\|]*\|/, '' );
if ( wikiCodeFinder.test( line ) ) {
$.post(
mw.util.wikiScript( 'api' ),
{ action: 'parse', text: line, disablepp: 1, format: 'json' },
function ( data ) {
var html = data.parse.text[ '*' ];
globalExplanation = html;
$( '#tpw_globalExplanation' ).html( html ).find( 'a' ).attr( { target: '_blank' } );
}
);
} else { globalExplanation = line; }
}
while ( lines.length ) {
line = lines.shift();
// look for |- this is wikitext for table row.
if ( !( /^\|-/.test( line ) ) ) { continue; }
line = lines.shift();
if ( line.indexOf( 'globalExplanation' ) + 1 ) {
extractGlobalExplanation();
continue;
}
// wikitext for column
if ( !line || !( /^\|/.test( line ) ) ) { continue; }
line = line.substr( 1 ); // get rid of the leading |
var fields = line.split( '||' );
if ( fields.length < 2 ) { continue; }
var name = $.trim( fields[ 0 ] );
if ( !name ) { continue; }
var desc = $.trim( fields[ 1 ] );
var pAttribs = { desc: desc };
if ( fields.length > 2 ) { pAttribs.options = analyzeOptions( $.trim( fields[ 2 ] ) ); }
templateParams[ name ] = pAttribs;
addParam( name );
}
}
function analyzeOptions( str ) {
var res = {},
avail = [ 'multiline', 'required', 'depends', 'defval', 'choices', 'date', 'extended' ], // maybe we'll have more in the future
tavail = $.map( avail, i18n ),
options = str.split( /\s*;\s*/ );
for ( var i in options ) {
var option = options[ i ].split( /\s*=\s*/ );
var ind = $.inArray( option[ 0 ], tavail );
if ( ind + 1 ) { res[ avail[ ind ] ] = option.length > 1 ? option[ 1 ] : true; }
}
anyExtended = anyExtended || res.extended;
return res;
}
function createWikiCode() {
var par = [ template ],
delim = $( '#oneLineTemplate' ).prop( 'checked' ) ? '' : '\n',
createEmpties = $( '#createEmpties' ).prop( 'checked' );
for ( var i in dialogFields ) {
var
field = dialogFields[ i ],
name = $.trim( field[ 0 ] ),
f = field[ 1 ],
hidden = f.parents( '.tpw_hidden' ).length,
val = $.trim( f.val() );
if ( !createEmpties && val === '' && f.attr( 'type' ) != 'checkbox' ) { continue; }// skip parameters with no value
if ( f.attr( 'type' ) == 'checkbox' && !f.prop( 'checked' ) ) { val = ''; }
par.push( name + '=' + val );
}
return '{{' + par.join( delim + '|' ) + delim + '}}';
}
function showPreview() {
var temp = createWikiCode();
$.post( mw.util.wikiScript( 'api' ),
{ action: 'parse',
title: mw.config.get( 'wgPageName' ),
prop: 'text',
text: temp,
format: 'json'
},
function ( data ) {
if ( data && data.parse && data.parse.text ) {
var buttons = [ { text: i18n( 'close' ), click: function () { $( this ).dialog( 'close' ); } } ],
div = $( '<div>' ).html( data.parse.text[ '*' ] );
$( 'a', div ).attr( 'target', '_blank' ); // we don't want people to click on links in preview - they'll lose their work.
$( '<div>' )
.dialog(
{ title: i18n( 'preview' ),
modal: true,
position: [ 60, 60 ],
buttons: buttons } )
.append( div );
circumventRtlBug();
}
} );
}
function circumventRtlBug() {
if ( rtl ) { $( '.ui-dialog-buttonpane button' ).css( { 'float': 'right' } ); } // jQuery has problems with rtl dialogs + ie is braindamaged.
}
function i18n( key, param ) {
switch ( mw.config.get( 'wgUserLanguage' ) ) {
case 'ar':
switch ( key ) {
case 'explain': return rawTemplate ?
'قالب "' + template + '" ليس له صفحة وسائط فرعية، لذلك فما من وصف لمعطياته.' :
'الوسائط الضرورية محددة بالأحمر والبقية اختيارية.';
case 'wizard dialog title': return 'وسائط ' + '<a href="' + mw.util.getUrl( 'قالب:' + template ) + '" target="_blank">' + 'قالب:' + template + '</a>';
case 'ok': return 'موافقة';
case 'cancel': return 'إلغاء';
case 'params subpage': return 'وسائط';
case 'preview': return 'معاينة';
case 'options select': return 'اختر معطى';
case 'multiline': return 'عدد صفوف';
case 'close': return 'أغلق';
case 'required': return 'ضروري';
case 'depends': return 'يلزمه';
case 'defval': return 'غيابي';
case 'choices': return 'خيارات';
case 'date': return 'تاريخ';
case 'extended': return 'Extended';
case 'button hint': return 'معالج وسائط القالب';
case 'able templates category name': return 'قوالب صالحة لمعالج وسائط القالب';
case 'template selector title': return 'اكتب اسم القالب:';
case 'notInParamPage': return 'وسيط "' + param + '" ليس من وسائط القالب';
case 'editParamPage': return 'عدل صفحة الوسائط';
case 'unknown error': return 'وقع خطأ.\n' + param;
case 'please select template': return 'اسم القالب';
case 'oneliner': return 'اجعله في صف واحد';
case 'createempties': return 'Write empty parameters to page';
case 'dateFormat': return 'd MM yy';
case 'extended labels': return 'Show all parameters';
}
break;
case 'ur':
switch ( key ) {
case 'explain': return rawTemplate;
case 'wizard dialog title': return 'سانچہ: "' + template + '" کے لیے محددات داخل کریں۔';
case 'ok': return 'ٹھیک ہے';
case 'wizard dialog title': return 'מילוי הפרמטרים עבור ' + '<a href="' + mw.util.getUrl( 'תבנית:' + template ) + '" target="_blank">' + 'תבנית:' + template + '</a>';
case 'params subpage': return 'محددات';
case 'preview': return 'نمائش';
case 'options select': return 'کوئی ایک منتخب کریں:';
case 'multiline': return 'Multiline';
case 'options select': return 'منتخب کریں';
case 'multiline': return 'מספר שורות';
case 'close': return 'بند کریں';
case 'required': return 'لازمی مطلوب';
case 'depends': return 'اس پر منحصر';
case 'defval': return 'طے شدہ';
case 'choices': return 'اختیارات';
case 'date': return 'تاریخ';
case 'button hint': return 'ساحر محدداتِ سانچہ';
case 'button hint': return 'אשף מילוי תבניות';
case 'able templates category name': return 'תבניות הנתמכות על ידי אשף התבניות';
case 'template selector title': return 'براہِ کرم سانچے کا نام داخل کریں';
case 'notInParamPage': return 'השדה "' + param + '" לא מופיע ברשימת הפרמטרים של התבנית';
case 'editParamPage': return 'ترمیم صفحہ محددات';
case 'unknown error': return 'نا معلوم ایرر.\n' + param;
case 'please select template': return 'سانچہ منتخب کریں';
case 'oneliner': return 'یک سطری سانچہ';
case 'createempties': return 'רשום שדות ריקים';
case 'dateFormat': return 'MM d, yy';
case 'extended labels': return 'הראה את כל הפרמטרים';
}
break;
default:
switch ( key ) {
case 'explain': return 'fields with red border are required, the rest are optional';
case 'wizard dialog title': return 'Set up parameters for template: ' + template;
case 'ok': return 'OK';
case 'cancel': return 'Cancel';
case 'params subpage': return 'Parameters';
case 'preview': return 'Preview';
case 'options select': return 'Select one:';
case 'multiline': return 'Multiline';
case 'close': return 'Close';
case 'required': return 'Required';
case 'depends': return 'Depends on';
case 'defval': return 'Default';
case 'choices': return 'Choices';
case 'date': return 'Date';
case 'extended': return 'Extended';
case 'button hint': return 'Template parameters wizard';
case 'able templates category name': throw ( 'Must define category name for wizard-capable templates' );
case 'template selector title': return 'Please enter the template name';
case 'notInParamPage': return 'field "' + param + '" does not appear in the template\'s parameters list';
case 'editParamPage': return 'Edit paramters page';
case 'unknown error': return 'Error occured: \n' + param;
case 'please select template': return 'Please enter template name';
case 'oneliner': return 'Single-line template';
case 'createempties': return 'Write empty parameters to page';
case 'dateFormat': return 'MM d, yy';
case 'extended labels': return 'Show all parameters';
}
break;
}
return key;
}
function paramPage() { return mw.config.get( 'wgFormattedNamespaces' )[ 10 ] + ':' + $.trim( template ) + '/' + i18n( 'params subpage' ); }
function templatePage() { return mw.config.get( 'wgFormattedNamespaces' )[ 10 ] + ':' + $.trim( template ); }
function updateRawPreview() {
var canOK = 'enable';
for ( var i in dialogFields ) {
var df = dialogFields[ i ][ 1 ];
var opts = df.data( 'options' );
if ( opts && opts.required && $.trim( df.val() ).length == 0 ) { canOK = 'disable'; }
if ( opts && opts.depends ) {
var dep = fieldsBypName[ opts.depends ];
var depEmpty = !( ( dep && dep.val() && $.trim( dep.val() ) ) );
var row = rowsBypName[ df.data( 'paramName' ) ];
if ( row ) { row.toggleClass( 'tpw_hidden', depEmpty ); }
}
}
$( '.ui-dialog-buttonpane button:contains(\'' + i18n( 'ok' ) + '\')' ).button( canOK );
$( '#tpw_preview' ).text( createWikiCode() );
localStorage.setItem( localStorageKey + '.' + emptiesKey, $( '#createEmpties' ).prop( 'checked' ) );
}
function createInputField( paramName ) {
var options = templateParams[ paramName ].options || {},
f,
checkbox = false;
if ( options.choices ) {
var choices = options.choices.split( /\s*,\s*/ );
if ( choices.length > 1 ) {
f = $( '<select>' ).append( $( '<option>', { text: i18n( 'options select' ), value: '' } ) );
for ( var i in choices ) { f.append( $( '<option>', { text: choices[ i ], value: choices[ i ] } ) ); }
} else {
checkbox = true;
f = $( '<input>', { type: 'checkbox', value: choices[ 0 ], text: choices[ 0 ] } )
.css( { 'float': rtl ? 'right' : 'left' } );
f.prop( 'checked', options.defval && options.defval == choices[ 0 ] );
}
} else if ( options.multiline ) {
var rows = options.multiline;
f = $( '<textarea>', { rows: 1 } )
.data( { dispRows: isNaN( parseInt( rows ) ) ? 5 : rows } )
.focus( function () { this.rows = $( this ).data( 'dispRows' ); } )
.blur( function () { this.rows = 1; } );
} else { f = $( '<input>', { type: 'text' } ); }
// teach the controls to autocomplete.
if ( !checkbox && f.autoCompleteWikiText ) {
f.autoCompleteWikiText( { positionMy: rtl ? 'left top' : 'right top' } );
}
f.css( { width: checkbox ? '1em' : '28em' } )
.data( { paramName: paramName, options: options } )
.on( 'paste cut drop input change', updateRawPreview );
if ( options.defval ) { f.val( options.defval ); }
if ( options.required ) { f.addClass( 'tpw_required' ).css( { border: '1px red solid' } ); }
if ( options.date ) { f.datepicker( { dateFormat: typeof options.date === 'string' ? options.date : i18n( 'dateFormat' ) } ); }
return f;
}
var
timer = null,
lastVisited = $( '<a>' );
function addRow( paramName, table ) {
var
def = templateParams[ paramName ],
inputField = createInputField( paramName ),
nameColor = def.desc ? 'blue' : ( def.options.notInParamPage ? 'red' : 'black' ),
tr = $( '<tr>' )
.append(
$( '<td>', { width: 120 } )
.css( { fontWeight: 'bold', color: nameColor } )
.text( paramName )
.attr( 'master', 'true' )
)
.append( $( '<td>' ).css( { width: '30em' } ).append( inputField ) );
dialogFields.push( [ paramName, inputField ] );
if ( def.options.extended ) { tr.addClass( 'tpw_extended' ); }
table.append( tr );
rowsBypName[ paramName ] = tr;
fieldsBypName[ paramName ] = inputField;
}
function injectResults() {
$( '#wpTextbox1' ).textSelection( 'encapsulateSelection', { replace: true, peri: createWikiCode() } );
}
function createExtendedCheckBox() {
return $( '<p>' )
.text( i18n( 'extended labels' ) )
.append( $( '<input>', { type: 'checkbox' } )
.change( function () {
extendedParamCssRule.disabled = $( this ).prop( 'checked' );
} )
);
}
function buildDialog( data ) {
$( '.tpw_disposable' ).remove();
if ( rawTemplate ) { buildParamsRaw( data ); } else { buildParams( data ); }
paramsFromSelection();
var $table = $( '<table>' );
var $dialog = $( '<div>', { 'class': 'tpw_disposable' } )
.dialog( { height: 'auto',
title: i18n( 'wizard dialog title', template ),
width: 'auto',
overflow: 'auto',
position: [ $( 'body' ).width() * 0.2, $( 'body' ).height() * 0.1 ],
open: function () { $( this ).css( { 'max-height': Math.round( $( 'body' ).height() * 0.7 ) } ); }
} )
.append( $( '<div>', { id: 'tpw_globalExplanation' } ).html( globalExplanation ) )
.append( $( '<p>' ).html( i18n( 'explain' ) ) )
.append( anyExtended ? createExtendedCheckBox() : '' )
.append( $table )
.append( $( '<p>' )
.append( i18n( 'oneliner' ) )
.append( $( '<input>', { type: 'checkbox', id: 'oneLineTemplate' } ).change( updateRawPreview )
)
)
.append( $( '<p>' )
.append( i18n( 'createempties' ) )
.append( $( '<input>', { type: 'checkbox', id: 'createEmpties' } )
.change( updateRawPreview )
.prop( 'checked', localStorage.getItem( localStorageKey + '.' + emptiesKey ) === 'true' )
)
)
.append( $( '<pre>', { id: 'tpw_preview' } )
.css( { backgroundColor: 'lightGreen', maxWidth: '40em', maxHeight: '8em', overflow: 'auto' } ) );
while ( paramsOrder.length ) { addRow( paramsOrder.shift(), $table ); }
var buttons = {}; // we need to do it this way, because with literal object, the keys must be literal.
buttons[ i18n( 'ok' ) ] = function () { injectResults(); $dialog.dialog( 'close' ); };
buttons[ i18n( 'cancel' ) ] = function () { $dialog.dialog( 'close' ); };
buttons[ i18n( 'preview' ) ] = showPreview;
$dialog.dialog( 'option', 'buttons', buttons );
circumventRtlBug();
updateRawPreview();
}
function init() {
template = null;
templateParams = {};
paramsOrder = [];
dialogFields = [];
rowsBypName = {};
fieldsBypName = {};
mw.util.addCSS( '.tpw_hidden{display:none;}' );
anyExtended = false;
extendedParamCssRule = extendedParamCssRule || mw.util.addCSS( '.tpw_extended{display:none;}' );
}
function reportError( a, b, error ) {
var key;
if ( typeof console !== 'undefined' ) {
for ( key in a ) {
if ( typeof a[ key ] !== 'function' ) { console.log( key + '=>' + a[ key ] ); }
}
console.log( b );
console.log( error );
}
alert( i18n( 'unknown error', error ) );
}
function pickTemplate( item ) {
function okButtonPressed( e, ui ) {
template = ui ? ui.item.value : $selector.val();
fireDialog();
$templateSelector.dialog( 'close' );
}
var $selector = $( '<input>' )
.css( { width: '28em' } )
.autocomplete( {
source: function ( request, response ) {
$.getJSON(
mw.util.wikiScript( 'api' ),
{ action: 'opensearch', search: request.term, namespace: 10 },
function ( data ) {
if ( data[ 1 ] ) { response( $( data[ 1 ] ).map( function ( index, item ) { return item.replace( /.*:/, '' ); } ) ); }
}
);
},
select: okButtonPressed
} );
var $templateSelector = $( '<div>' ).dialog( {
title: i18n( 'template selector title' ),
height: 'auto',
width: 'auto',
modal: true,
buttons: [
{ text: i18n( 'ok' ), click: okButtonPressed },
{ text: i18n( 'cancel' ), click: function () { $templateSelector.dialog( 'close' ); } }
]
} ).append( $selector );
circumventRtlBug();
$selector.focus();
}
function fireDialog() {
rawTemplate = false;
$.ajax( {
url: mw.util.wikiScript(),
data: { title: paramPage(), action: 'raw' },
dataType: 'text',
success: buildDialog,
cache: false,
error: function () {
rawTemplate = true;
$.ajax( {
url: mw.util.wikiScript(),
data: { title: templatePage(), action: 'raw' },
dataType: 'text',
success: buildDialog,
error: reportError
} );
}
} );
}
function doIt() {
mw.loader.using( [ 'jquery.ui', 'jquery.textSelection'], function () {
init();
var match = $( '#wpTextbox1' ).textSelection( 'getSelection' ).match( /^\{\{([^|}]*)/ );
template = match ? $.trim( match[ 1 ] ) : null;
if ( template ) { fireDialog(); } else { pickTemplate(); }
} );
}
if ( mw.user.options.get( 'usebetatoolbar' ) ) {
mw.loader.using( [ 'ext.wikiEditor' ], function () {
if ( typeof $.wikiEditor !== 'undefined' ) {
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
section: 'advanced',
groups: {
wizards: {
tools: {
linkTemplatewizard: {
label: i18n( 'button hint' ),
type: 'button',
icon: '//upload.wikimedia.org/wikipedia/commons/d/dd/Vector_toolbar_template_button.png',
action: { type: 'callback', execute: doIt }
}
}
}
}
} );
}
} );
} else {
$( 'div #toolbar' ).append( // "old style"
$( '<img>', { src: '//upload.wikimedia.org/wikipedia/commons/e/eb/Button_plantilla.png', title: i18n( 'button hint' ), 'class': 'mw-toolbar-editbutton' } )
.css( { cursor: 'pointer' } )
.click( doIt )
);
}
} );
}