|
|
שורה 1: |
שורה 1: |
| //Template parameters wizard
| | [[קובץ:TemplatesWizard.png|250px|ממוזער|דוגמה לשימוש באשף תבניות עם ה[[המכלול:תבנית|תבנית]] "{{תב|מדען}}". לאחר בחירת תבנית, ייפתח [[טופס]] למילוי תבנית כמוצג.]] |
| //Written by [[User:קיפודנחש]]
| | '''אשף התבניות''' (לא "אשף תבניות קישורים"), מאפשר הוספה ומילוי של [[המכלול:תבנית|תבניות]] קיימות היישר מ[[הילף:רעדאגירן א בלאט|דף העריכה]], בקלות ובמהירות. האשף הכללי עובד בצורה חלקית. אשף התבניות עובד באופן שלם, רק כאשר יש לתבנית מבוקשת templatedata (ראו בהמשך). |
| "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 the source of data is templatedata.
| |
| tdTemplate,
| |
| // boolean, indicating the source of the data is analyzing the template page itself.
| |
| rawTemplate,
| |
| isInline,
| |
| 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',
| |
| oneLineTemplate = 'oneLineTemplate',
| |
| allAliases = [];
| |
|
| |
|
| function addParam(name) {
| | ==התקנת האשף== |
| if ($.inArray(name, paramsOrder) == -1)
| | בראש הדף, תחת "העדפות" ← "[[הילף:טשאטשקעס|גאדג'טים]]" ([[באַזונדער:העדפות#mw-prefsection-gadgets]]), יש לבחור "{{מדיה ויקי:Gadget-TemplateParamWizard}}". שימו לב, שהבחירה הזו מאופשרת כ[[ברירת מחדל]]. |
| paramsOrder.push(name);
| |
| }
| |
|
| |
|
| function paramsFromSelection() {
| | אם הוספתם את השורה הבאה ל[[באַזונדער:הדף שלי/common.js]], אנא הסירו אותה: |
| var selection = $("#wpTextbox1").textSelection('getSelection').replace(/^\s*\{\{|\}\}\s*$/g, ''); //scrap the first {{ and last }}
| | <syntaxhighlight lang="javascript"> |
| var specials = [],
| | importScript('mediawiki:TemplateParamWizard.js'); |
| match;
| | </syntaxhighlight> |
| while (true) { //extract inner links, inner templates and inner params - we don't want to split those.
| |
| 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(/ *\| */);
| |
| params.shift(); // remove the template name
| |
| var ordered = 0;
| |
| for (var i in params) {
| |
| var param = params[i];
| |
| if ( ! /=/.test(param) ) {
| |
| param = ++ordered + '=' + param;
| |
| }
| |
| var paramPair = param.split("=");
| |
| var name = $.trim(paramPair.shift());
| |
| if ( ! isNaN( name ) ) {
| |
| ordered = parseInt( name ); // this still won't work as advertise when template contains explicit parameter 2 before implicit 1: {{x | 2 = hey | ho }}
| |
| }
| |
| var val = paramPair.join('=');
| |
| while (true) {
| |
| match = val.match(/\0(\d+)\0/);
| |
| if (! match || ! match.length)
| |
| break;
| |
| val = val.replace(match[0], specials[parseInt(match[1], 10)-1]);
| |
| }
| |
| if (name && paramPair.length) {
| |
| var tp = templateParams[name] =
| |
| templateParams[name] ||
| |
| ~allAliases.indexOf(name) && { param:{}, options: {isAlias: 1} } ||
| |
| {param: {}, options: { notInParamPage: 1}};
| |
| addParam(name);
| |
| $.extend( tp.options, { defval: val } );
| |
| if ( /\n/.test( val ) ) $.extend( tp.options, { multiline : 5 } );
| |
| // 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}, label: paramName, param:{} };
| |
| addParam(paramName);
| |
| }
| |
| }
| |
|
| |
| function buildParamsTd(data) {
| |
| var params = data.params,
| |
| paramOrder = data.paramOrder;
| |
|
| |
|
| function optionsOfParam(param) {
| | ===יצירת תבנית חדשה=== |
| var options = {};
| | בכדי ליצור תבנית חדשה, יש ללחוץ על הכפתור [[קובץ:Vector toolbar template button.png]] כאשר נמצאים במצב עריכה. האשף יפתח חלון, שמאפשר להזין את שם התבנית הרצויה מתוך רשימה. לאחר לחיצה על "אישור", תגיעו לאשף עצמו. |
| if (param.required) options.required = true;
| |
| if (param.suggestedvalues && param.suggestedvalues.length) options.choices = param.suggestedvalues.join(',');
| |
| return options;
| |
| }
| |
|
| |
|
| function onemore(name) {
| | ניתן גם לרשום את שם התבנית בערך באופן הבא <nowiki>{{שם תבנית}}</nowiki>, ואז לסמן את התבנית וללחוץ על הכפתור [[קובץ:Vector toolbar template button.png]]. האשף מייצר ומציג טופס עם שם הפרמטר, ותיבת הכנסת טקסט ([[שדה (אחסון נתונים)|שדה מילוי]]). |
| var param = params[name];
| |
| if (param.deprecated)
| |
| return; // ignore deprecated parameters - pretend they are not in TD.
| |
| templateParams[name] = {
| |
| desc: param.description || '',
| |
| options: optionsOfParam(param),
| |
| label: param.label || name,
| |
| param: param
| |
| };
| |
| if (param.aliases) $.merge(allAliases, param.aliases); // collect alliases if there are any
| |
| addParam(name);
| |
| }
| |
|
| |
| isInline = data.format === 'inline';
| |
|
| |
| if (paramOrder && paramOrder.length)
| |
| for (var ind in paramOrder)
| |
| onemore(paramOrder[ind]);
| |
| else // no order - take them as they come.
| |
| for (var paramname in params)
| |
| onemore(paramname);
| |
|
| |
|
| // derive placeholders for feilds derived from wikidata
| | ===עדכון תבנית קיימת=== |
| if (data.maps && data.maps.hasOwnProperty('wikidata') && mw.config.get('wgWikibaseItemId')) {
| | ניתן להשתמש באשף גם לתיקונים קטנים (או גדולים) בתבנית קיימת, שכבר מולאה באופן חלקי. לשם כך, יש לסמן את התבנית הקיימת בערך וללחוץ על כפתור [[קובץ:Vector toolbar template button.png]]. האשף יקרא את הנתונים מהערך עצמו. |
| var wikidataFormattedValues = $('<div>');
| |
| for (var k in data.maps['wikidata']) {
| |
| wikidataFormattedValues.append($('<span>', {id: k, text:'{{#property:' + k + '}}'}))
| |
| }
| |
| $.post(
| |
| mw.util.wikiScript('api'),
| |
| {action: 'parse', text: wikidataFormattedValues.html(), disablelimitreport: 1, format: 'json', prop: 'text', title: mw.config.get('wgPageName')},
| |
| function(wbd) {
| |
| if (!wbd || !wbd.parse || !wbd.parse.text) return;
| |
| for (var k in data.maps['wikidata']) {
| |
| var wikidataVal = $('#' + k, wbd.parse.text['*']).text(),
| |
| field = fieldsBypName[data.maps['wikidata'][k]];
| |
| if (field)
| |
| field.prop('placeholder', wikidataVal);
| |
| }
| |
| }
| |
| );
| |
| }
| |
| }
| |
|
| |
|
| function buildParams(data) {
| | '''שימו לב''', שיש לסמן את התבנית כולה, כולל הפרמטרים שכבר קיימים. האשף יאסוף את הערכים הללו מהדף וימלא את השדות המתאימים. |
| var
| |
| lines = data.split("\n"),
| |
| line;
| |
|
| |
|
| function extractGlobalExplanation() {
| | בזמן עריכה, אם מאופשר אצלכם ה[[הילף:טשאטשקעס|גאדג'ט]] של autocomplete, הוא יעבוד גם על השדות באשף; כלומר, כאשר תוסיפו <code><nowiki>[[</nowiki></code> לאחד השדות באשף ותתחילו להקיש שם ערך, האשף יציע ערכים מתאימים לתווים שכבר הקשתם, בדומה ל[[המכלול:ניווט|תיבת החיפוש]]. |
| 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 && lines.length) {
| | == templatedata == |
| line = lines.shift();
| | כאשר יש לתבנית tempaltedata, האשף ישתמש בה לרשימת הפרמטרים, תיאור כל פרמטר, החלטה מתי פרמטר מסוים הוא "חובה", והחלטה האם לסדר תבנית בשורה אחת או שורה לכל פרמטר. אם אין tempaltedata, האשף מנסה למצות את רשימת הפרמטרים על ידי ניתוח דף התבנית, פעולה שהצלחתה אינה מובטחת. אם רשימת הפרמטרים שהאשף מציע אינה נכונה, יש ליצור tempaltedata בתבנית, או לתקן את הקיים. |
| if (!(/^\|-/.test(line))) // look for |- this is wikitext for table row.
| |
| continue;
| |
| line = lines.shift();
| |
| if (line.indexOf('globalExplanation') + 1) {
| |
| extractGlobalExplanation();
| |
| continue;
| |
| }
| |
| if (! line || ! (/^\|/.test(line))) //wikitext for column
| |
| 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;
| | מידע נוסף על tempaltedata ניתן למצוא ב[[mw:Help:TemplateData/he]]. |
| 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',
| |
| paramValueDelim = $('#' + oneLineTemplate).prop('checked') ? '=' : ' = ',
| |
| createEmpties = $('#createEmpties').prop('checked'),
| |
| mustNumberNameless,
| |
| valuedOrdered;
| |
|
| |
| for (var i = dialogFields.length - 1; i >= 0; i--) {
| |
| var field = dialogFields[i],
| |
| val = $.trim(field[1].val());
| |
|
| |
| if (isNaN(field[0])) continue; // look only at order-based fields
| |
|
| |
| mustNumberNameless |=
| |
| /=/.test(val) // order-based value containing "="
| |
| || valuedOrdered && !val; // empty ordered w lower index than a non-empty one.
| |
| if (val) valuedOrdered = true;
| |
| }
| |
|
| |
| for (var i in dialogFields) {
| |
| var
| |
| field = dialogFields[i],
| |
| name = $.trim(field[0]),
| |
| f = field[1],
| |
| opts = f.data('options'),
| |
| param = templateParams[name],
| |
| hidden = f.parents('.tpw_hidden').length,
| |
| val = f.val().replace( /\s+$/, '' ); // leave leading newlines, for lists etc., but remove trailing.
| |
| if (param && param.param && param.param.type === 'url')
| |
| val = val.replace(/\|/g, '{{!}}');
| |
| if (f.attr('type') == 'checkbox' && ! f.prop('checked'))
| |
| val = "";
| |
| if ( ( !createEmpties || opts.notInParamPage ) && $.trim( val ) === "" )
| |
| continue;//skip parameters with no value
| |
|
| |
| var next = mustNumberNameless || isNaN(name)
| |
| ? name + paramValueDelim + $.trim( val )
| |
| : $.trim( val );
| |
| par.push(next);
| |
| }
| |
| return "{{" + par.join(delim + ($('#' + oneLineTemplate).prop('checked')? "|" : "| ")) + 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 'مفصل';
| |
| case 'button hint': 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 'd MM yy';
| |
| case 'extended labels': return 'عرض كل الوسائط';
| |
| default: return key;
| |
| }
| |
| break;
| |
| case 'he':
| |
| switch (key) {
| |
| case 'explain': return hebExplain();
| |
| case 'wizard dialog title': return 'מילוי הפרמטרים עבור ' + '<a href="' + mw.util.getUrl('תבנית:' + template) + '" target="_blank">' + 'תבנית:' + template + '</a>';
| |
| case 'ok': return 'אישור';
| |
| case 'cancel': 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 'משני';
| |
| case 'button hint': 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 'd בMM yy';
| |
| case 'extended labels': return 'הראה את כל הפרמטרים';
| |
| case 'pve-required-empty': return 'התבנית דורשת שפרמטר זה יקבל ערך';
| |
| case 'pve-deprecated': return 'שימוש בפרמטר מיושן';
| |
| case 'pve-incompatible': return 'שדה זה מצפה לערך מספרי';
| |
| case 'pve-no-such-name': return 'שדה זה לא קיים בתבנית';
| |
| case 'explain-pve': return 'שדות עם שגיאה מסומנים ברקע ורוד';
| |
| case 'pve-approve-close': return 'יש בתבנית שגיאות. אנא אשרו יציאה מהאשף';
| |
| }
| |
| break;
| |
| case 'ur':
| |
| switch (key) {
| |
| case 'explain': return 'جو خانے لازمی ہیں ان کے گرد سرخ رنگ کی لکیر کھینچ دی گئی ہے، بقیہ خانے اختیاری ہوں گے۔';
| |
| case 'wizard dialog title': return 'سانچہ: "' + template + '" میں مطلوبہ معلومات درج کریں۔';
| |
| 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 'مفصل';
| |
| case 'button hint': 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 'd MM yy';
| |
| case 'extended labels': return 'تمام پیرامیٹر دکھائیں';
| |
| }
| |
| break;
| |
| case 'ru':
| |
| switch (key) {
| |
| case 'explain': return 'поля с красной рамкой обязательны, остальные - по желанию';
| |
| case 'wizard dialog title': return 'Настройте параметры для шаблона: ' + template;
| |
| case 'ok': return 'OK';
| |
| 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 'Расширенный';
| |
| case 'button hint': return 'Мастер параметров шаблона';
| |
| case 'able templates category name': throw('Необходимо определить название категории для шаблонов с поддержкой мастера');
| |
| 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 'dateFormat': return 'ММ дд, гг';
| |
| case 'extended labels': return 'Показать все параметры';
| |
| }
| |
| 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 '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';
| |
| case 'pve-required-empty': return 'The template requires a value for this filedך';
| |
| case 'pve-deprecated': return 'deprecated parameter';
| |
| case 'pve-incompatible': return 'expaects numteric value';
| |
| case 'pve-no-such-name': return 'undercgonzed parameter';
| |
| case 'explain-pve': return 'fields with errors are marked with pink background';
| |
| case 'pve-approve-close': return 'Template contains errors. Please confim exit';
| |
| }
| |
| }
| |
| return key;
| |
| }
| |
| | |
| function hebExplain() {
| |
| var explanation;
| |
| if (rawTemplate) return 'לתבנית "' + template + '" אין דף פרמטרים, ולכן לשדות אין תיאור.';
| |
| if (anyRequiredParam()) return 'שדות חובה מסומנים במסגרת אדומה';
| |
| return '';
| |
| }
| |
|
| |
| function anyRequiredParam() {
| |
| for (name in templateParams) {
| |
| var param = templateParams[name];
| |
| if (param.options.required) return true;
| |
| }
| |
| return false;
| |
| }
| |
|
| |
| function templatePage() {
| |
| var t = $.trim(template)
| |
| return t.match(':') ? t : mw.config.get('wgFormattedNamespaces')[10] + ':' + t;
| |
| }
| |
| | |
| 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())) ? false : true;
| |
| 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'));
| |
| validate();
| |
| }
| |
|
| |
| function validate() {
| |
|
| |
| function validateField(param, input) {
| |
| function markError(msg) {
| |
| input
| |
| .addClass('tpw-paramvalidation')
| |
| .attr('title', i18n(msg));
| |
| return false;
| |
| }
| |
|
| |
| var hasVal = !! input.val();
| |
| if (param.options.notInParamPage && hasVal) return markError('pve-no-such-name');
| |
| if (param.param.required && ! hasVal) return markError('pve-required-empty');
| |
| if (param.param.deprecated && hasVal) return markError('pve-deprecated');
| |
| if (param.param.type === 'number' && isNaN( Number( input.val().replace(/,/g, '') ) ) ) return markError('pve-incompatible');
| |
| return true;
| |
| }
| |
|
| |
| var aOK = true;
| |
| for (var i in dialogFields) {
| |
| var
| |
| field = dialogFields[i],
| |
| name = $.trim(field[0]),
| |
| input = field[1].removeClass('tpw-paramvalidation'),
| |
| param = templateParams[name];
| |
|
| |
| aOK = validateField(param, input) && aOK;
| |
| }
| |
|
| |
| $('#tpw-explain').html(i18n(aOK ? 'explain' : 'explain-pve') );
| |
|
| |
| return aOK;
| |
| }
| |
| | |
| function createInputField(paramName) {
| |
| var params = templateParams[paramName],
| |
| options = params.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) {
| |
| var choice = choices[i].trim(); // first and last may carry spaces
| |
| var option = $('<option>', {text: choice, value: choice});
| |
| f.append(option);
| |
| }
| |
| }
| |
| else {
| |
| checkbox = true;
| |
| var choice = choices[0].trim();
| |
| f = $('<input>', {type: 'checkbox', value: choices[0], text: choices[0].trim()})
| |
| .css({float: rtl ? 'right' : 'left'});
| |
| f.prop('checked', options.defval && options.defval.trim() == choices[0]);
| |
| }
| |
| }
| |
| else if (options.multiline) {
| |
| var rows = options.multiline;
| |
| f = $('<textarea>', {rows: 1})
| |
| .focus(function(){this.rows = 5;})
| |
| .blur(function(){this.rows = 1});
| |
| }
| |
| else
| |
| f = $('<input>', {type: 'text'});
| |
| | |
| if (!checkbox && f.autoCompleteWikiText) // teach the controls to autocomplete.
| |
| 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 && ! checkbox)
| |
| f.val(options.defval.trim());
| |
| | |
| if (options.required)
| |
| f.addClass('tpw-required');
| |
| | |
| if (options.date)
| |
| f.datepicker({dateFormat: typeof options.date == "string" ? options.date : i18n('dateFormat')});
| |
|
| |
| return f;
| |
| }
| |
| | |
| var
| |
| timer = null,
| |
| lastVisited = $('<a>');
| |
| | |
| function enterTipsy() {
| |
| clearTimeout(timer);
| |
| $(this).attr('inside', 1);
| |
| }
| |
| | |
| function leaveTipsy() {
| |
| var $this = $(this);
| |
| if ($this.attr('master') || $this.attr('inside')) {
| |
| $this.attr('inside', '');
| |
| timer = setTimeout(function(){lastVisited.tipsy('hide');}, 500);
| |
| }
| |
| }
| |
| | |
| function tipsyContent() {
| |
| var
| |
| paramName = $(this).data('paramname'),
| |
| def = templateParams[paramName],
| |
| desc = def && def.desc || '';
| |
| if (!def) return ''; // early terminate if param name is not valid
| |
| if (def.htmlDesc)
| |
| return def.htmlDesc;
| |
| if (wikiCodeFinder.test(desc)) // does it need parsing?
| |
| $.ajax({
| |
| url: mw.util.wikiScript('api'),
| |
| async: false,
| |
| type: 'post',
| |
| data: {action: 'parse', text: desc, disablepp: 1, format: 'json'}, // parse it.
| |
| success: function(data) {
| |
| var div = $('<div>').html(data.parse.text['*']);
| |
| $('a', div).attr({target: '_blank'});
| |
| def.htmlDesc = div.html();
| |
| }
| |
| });
| |
| else
| |
| def.htmlDesc = desc;
| |
| return def.htmlDesc;
| |
| }
| |
| | |
| function addRow(paramName, table) {
| |
| var
| |
| def = templateParams[paramName],
| |
| inputField = createInputField(paramName),
| |
| nameColor = def.desc
| |
| ? 'blue'
| |
| : def.options.notInParamPage
| |
| ? 'red'
| |
| : def.options.isAlias
| |
| ? 'green'
| |
| : 'black',
| |
| tr = $('<tr>')
| |
| .append(
| |
| $('<td>', {width: 120})
| |
| .css({fontWeight: 'bold', color: nameColor})
| |
| .data({ paramname: paramName })
| |
| .text(templateParams[paramName].label || paramName)
| |
| .tipsy({html: true, trigger: 'manual', title: tipsyContent})
| |
| .mouseenter(function() {
| |
| clearTimeout(timer);
| |
| $('.tipsy').remove();
| |
| lastVisited = $(this);
| |
| lastVisited.tipsy('show');
| |
| })
| |
| .mouseleave(leaveTipsy)
| |
| .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) {
| |
| var title = $('<span>').html(i18n('wizard dialog title', template));
| |
| $('.tpw_disposable').remove();
| |
|
| |
| if (rawTemplate)
| |
| buildParamsRaw(data);
| |
| else if (tdTemplate) {
| |
| buildParamsTd(data);
| |
| if (data.description) title.find('a').attr({ title: data.description });
| |
| }
| |
|
| |
| paramsFromSelection();
| |
| var table = $('<table>');
| |
| var dialog = $('<div>', {'class': 'tpw_disposable'})
| |
| .dialog({height: 'auto',
| |
| title: title.html(),
| |
| 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>', { id: 'tpw-explain' } ).html(i18n('explain')) )
| |
| .append(anyExtended ? createExtendedCheckBox() : '')
| |
| .append(table)
| |
| .append($('<p>')
| |
| .append(i18n('oneliner'))
| |
| .append($('<input>', {type: 'checkbox', id: oneLineTemplate}).prop('checked', isInline).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'}).addClass('tpw-wikicode-preview'));
| |
|
| |
| 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() {
| |
| if (! validate() && ! confirm(i18n('pve-approve-close' ) ) ) return;
| |
| injectResults();
| |
| dialog.dialog('close');
| |
| };
| |
| buttons[i18n('cancel')] = function() {dialog.dialog('close');};
| |
| buttons[i18n('preview')] = showPreview;
| |
| dialog.dialog('option', 'buttons', buttons);
| |
| circumventRtlBug();
| |
| updateRawPreview();
| |
| $('.tipsy').hover(enterTipsy, leaveTipsy);
| |
| }
| |
| | |
| 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() {
| |
| var readRaw = function() {
| |
| rawTemplate = true;
| |
| $.ajax({
| |
| url: mw.util.wikiScript(),
| |
| data: {title: templatePage(), action: 'raw'},
| |
| dataType: 'text',
| |
| success: buildDialog,
| |
| error: reportError
| |
| });
| |
| },
| |
|
| |
| readTemplateData = function() {
| |
| $.ajax({
| |
| url: mw.util.wikiScript('api'),
| |
| data: {action: 'templatedata', titles: templatePage(), redirects: true, format: 'json', lang: mw.config.get('wgUserLanguage') },
| |
| dataType: 'json',
| |
| success: function(data) {
| |
| var found = false;
| |
| if (data && data.pages)
| |
| for (var pageid in data.pages) {
| |
| tdTemplate = true;
| |
| found = true;
| |
| buildDialog(data.pages[pageid]);
| |
| break;
| |
| }
| |
| if (! found)
| |
| readRaw();
| |
| },
| |
| error: readRaw
| |
| });
| |
| };
| |
|
| |
| rawTemplate = false;
| |
| readTemplateData();
| |
| }
| |
| | |
| function templateContext() {
| |
| var selection = $("#wpTextbox1").textSelection('getSelection'),
| |
| caretPos, beforeText, afterText, templateStart, templateEnd;
| |
| | |
| // trust the user
| |
| if ( selection.length > 0 ) {
| |
| return selection;
| |
| }
| |
| | |
| caretPos = $("#wpTextbox1").textSelection('getCaretPosition');
| |
| beforeText = $("#wpTextbox1").val().substr(0, caretPos);
| |
| afterText = $("#wpTextbox1").val().substr(caretPos);
| |
| templateStart = beforeText.lastIndexOf('{{');
| |
| templateEnd = afterText.indexOf('}}') + 2;
| |
| | |
| // only under opportunistic template context assumptions
| |
| if ( $("#wpTextbox1").val().split('{').length != $("#wpTextbox1").val().split('}').length ||
| |
| (beforeText.split('{{').length === beforeText.split('}}').length) ||
| |
| (afterText.split('{{').length === afterText.split('}}').length) )
| |
| return '';
| |
| | |
| // determine the start and the end of the template context
| |
| while (beforeText.substr(templateStart).split('{{').length <= beforeText.substr(templateStart).split('}}').length)
| |
| templateStart = beforeText.lastIndexOf('{{', templateStart - 1)
| |
|
| |
| | |
| while (afterText.substr(0, templateEnd).split('{{').length >= afterText.substr(0, templateEnd).split('}}').length)
| |
| templateEnd = afterText.indexOf('}}', templateEnd) + 2;
| |
| | |
| // extend the selection to the current template context
| |
| $("#wpTextbox1").focus().textSelection('setSelection', {
| |
| start: templateStart,
| |
| end: caretPos + templateEnd
| |
| });
| |
| return $("#wpTextbox1").textSelection('getSelection');
| |
| }
| |
| | |
| function doIt() {
| |
| mw.loader.using(['jquery.ui','jquery.tipsy','jquery.textSelection', 'mediawiki.api'], function() {
| |
| init();
| |
| var match = templateContext().match(/^\{\{([^|}]*)/);
| |
| template = match ? $.trim(match[1]) : null;
| |
| if (template)
| |
| fireDialog();
| |
| else
| |
| pickTemplate();
| |
| });
| |
| }
| |
| function addToWikiEditor(){
| |
| $('#wpTextbox1').wikiEditor('addToToolbar', {
| |
| section: 'main',
| |
| group: 'insert',
| |
| tools: {
| |
| 'templateParamsWizard': {
| |
| label: i18n('button hint'),
| |
| type: 'button',
| |
| icon: '//upload.wikimedia.org/wikipedia/commons/thumb/7/7e/Template_alt_full_black_22.svg/22px-Template_alt_full_black_22.svg.png',
| |
| action: {type: 'callback', execute: doIt}
| |
| }
| |
| }
| |
| });
| |
| }
| |
| if (mw.user.options.get('usebetatoolbar'))
| |
| mw.loader.using(['ext.wikiEditor'], function() {
| |
| if(typeof $.wikiEditor != 'undefined') {
| |
| if ($('#wikiEditor-ui-toolbar').length === 1) addToWikiEditor();//in case it loaded after toolbar initaliztion
| |
| else $( '#wpTextbox1' ).on( 'wikiEditor-toolbar-doneInitialSections', addToWikiEditor);
| |
| }
| |
| });
| |
| 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)
| |
| );
| |
| } );
| |