Benutzer:ICON/TemplateWizard.js

< Benutzer:ICON
Version vom 14. Juni 2018, 14:54 Uhr von ICON (Diskussion | Beiträge) (Die Seite wurde neu angelegt: „( function ( mw, $ ) { // <nowiki> function defineClasses() { →‎* Messages will be moved to JSON files later on.: mw.messages.set( 'templatewizard',…“)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)

Hinweis: Leere nach dem Veröffentlichen den Browser-Cache, um die Änderungen sehen zu können.

  • Firefox/Safari: Umschalttaste drücken und gleichzeitig Aktualisieren anklicken oder entweder Strg+F5 oder Strg+R (⌘+R auf dem Mac) drücken
  • Google Chrome: Umschalttaste+Strg+R (⌘+Umschalttaste+R auf dem Mac) drücken
  • Internet Explorer/Edge: Strg+F5 drücken oder Strg drücken und gleichzeitig Aktualisieren anklicken
  • Opera: Strg+F5

( function ( mw, $ ) { // function defineClasses() { /* * Messages will be moved to JSON files later on. */ mw.messages.set( 'templatewizard', 'TemplateWizard (beta)' ); mw.messages.set( 'templatewizard-dialog-title', 'Vorlage einfügen' ); mw.messages.set( 'templatewizard-opens-in-new-tab', 'Öffnet in einem neuen Tab' ); mw.messages.set( 'templatewizard-help-page', 'Hilfeseite' ); mw.messages.set( 'templatewizard-invalid-title', 'Ungültiger Titel' ); mw.messages.set( 'templatewizard-template-not-found', '$1 kann nicht im TemplateWizard genutzt werden.' + ' Dies liegt eventuell daran, dass die Vorlage nicht existiert oder keine $2-Tags besitzt.' + ' Bitte behebe dies und versuche es erneut.' + ); mw.messages.set( 'templatewizard-default', 'Standard: $1' ); mw.messages.set( 'templatewizard-parameters-required', 'Erforderliche Parameter' ); mw.messages.set( 'templatewizard-parameters-suggested', 'Vorgeschlagene Parameter' ); mw.messages.set( 'templatewizard-parameters-optional', 'Optionale Parameter' ); mw.messages.set( 'templatewizard-insert', 'Einfügen' ); mw.messages.set( 'templatewizard-cancel', 'Abbrechen' ); mw.messages.set( 'templatewizard-use', 'Benutzen' ); mw.messages.set( 'templatewizard-select-template', 'Wähle eine Vorlage:' ); /* Extension namespace. */ mediaWiki.TemplateWizard = {}; /** * @class * @constructor * @param {Object} [config] Configuration options */ mediaWiki.TemplateWizard.TemplateForm = function mediaWikiTemplateWizardTemplateForm( config ) { // Parent constructor OO.ui.Widget.parent.call( this, config ); this.$element = $( '<div>' ).addClass( 'ext-templatewizard-templateform' ); }; OO.inheritClass( mediaWiki.TemplateWizard.TemplateForm, OO.ui.Widget ); /** * Set the template title. * @param {string} newTitle No leading 'Template:' required. */ mediaWiki.TemplateWizard.TemplateForm.prototype.setTitle = function ( newTitle ) { this.title = mw.Title.newFromText( newTitle, mw.config.get( 'wgNamespaceIds' ).template ); if ( !this.title ) { throw new Error( mw.message( 'templatewizard-invalid-title' ) ); } this.$element.append( this.getHeader() ); this.loadTemplateData(); }; mediaWiki.TemplateWizard.TemplateForm.prototype.setDialog = function ( dialog ) { this.dialog = dialog; }; mediaWiki.TemplateWizard.TemplateForm.prototype.getTitle = function () { return this.title; }; mediaWiki.TemplateWizard.TemplateForm.prototype.getFormat = function () { return this.format; }; mediaWiki.TemplateWizard.TemplateForm.prototype.getHeader = function () { var link; link = $( '<a>' ) .attr( 'target', '_blank' ) .attr( 'title', mw.message( 'templatewizard-opens-in-new-tab' ) ) .attr( 'href', this.title.getUrl() ) .text( this.title.getMainText() ); return $( '<h2>' ).html( link ); }; mediaWiki.TemplateWizard.TemplateForm.prototype.getInputWidgetForParam = function ( param, paramDefinition ) { var widget, config = { name: param }; if ( paramDefinition.autovalue ) { config.value = paramDefinition.autovalue; } if ( paramDefinition.required ) { config.required = true; } if ( paramDefinition.type === 'number' ) { widget = new OO.ui.NumberInputWidget( config ); } else if ( paramDefinition.type === 'date' ) { widget = new mw.widgets.DateInputWidget( config ); } else if ( paramDefinition.type === 'wiki-user-name' ) { widget = new mw.widgets.UserInputWidget( config ); } else if ( paramDefinition.type === 'wiki-page-name' ) { widget = new mw.widgets.TitleInputWidget( config ); } else if ( paramDefinition.type === 'wiki-file-name' ) { config.showImages = true; config.namespace = mw.config.get( 'wgNamespaceIds' ).file; widget = new mw.widgets.TitleInputWidget( config ); } else if ( paramDefinition.type === 'wiki-template-name' ) { config.namespace = mw.config.get( 'wgNamespaceIds' ).template; widget = new mw.widgets.TitleInputWidget( config ); } else { widget = new OO.ui.TextInputWidget( config ); } return widget; }; mediaWiki.TemplateWizard.TemplateForm.prototype.getParameterFieldsets = function ( groupedParams ) { var $fieldsets = $( '<div>' ), self = this; $.each( groupedParams, function ( groupName, group ) { var fieldsetLabel = mw.message( 'templatewizard-parameters-' + groupName ).text(), fieldset = new OO.ui.FieldsetLayout( { label: fieldsetLabel } ); if ( groupName === 'required' ) { fieldset.$label.css( 'color', '#e04006' ); } if ( groupName === 'suggested' ) { fieldset.$label.css( 'color', '#f99d31' ); } if ( groupName === 'optional' ) { fieldset.$label.css( 'color', '#78ab46' ); } $.each( group, function ( param, details ) { var widget, field, label, description; widget = self.getInputWidgetForParam( param, details ); description = ''; if ( details.description ) { description = details.description; } if ( details.default ) { description += ' ' + mw.message( 'templatewizard-default', details.default ); } label = param; if ( details.label ) { label = details.label; } field = new OO.ui.FieldLayout( widget, { label: label, help: description } ); fieldset.addItems( [ field ] ); } ); if ( !fieldset.isEmpty() ) { $fieldsets.append( fieldset.$element ); } } ); return $fieldsets; }; mediaWiki.TemplateWizard.TemplateForm.prototype.processTemplateData = function ( apiResponse ) { var id, templateData, description, templateLink, templateDataLink, helpLink, groupedParams; // Get the first page's template data. id = $.map( apiResponse.pages, function ( _value, key ) { return key; } ); templateData = apiResponse.pages[ id ]; // 1. Description. description = ''; if ( templateData.description ) { description = templateData.description; } else if ( templateData.missing !== undefined || templateData.params === undefined ) { // Treat non-existant and non-TemplateData templates the same. templateLink = $( '<a>' ) .attr( 'target', '_blank' ) .attr( 'title', mw.message( 'templatewizard-opens-in-new-tab' ) ) .attr( 'href', this.title.getUrl() ) .text( '{{' + this.title.getMainText() + '}}' ); templateDataLink = $( '<a>' ) .attr( 'target', '_blank' ) .attr( 'title', mw.message( 'templatewizard-opens-in-new-tab' ) ) .attr( 'href', 'https://www.mediawiki.org/wiki/Special:MyLanguage/Help:TemplateData#Structure_of_TemplateData' ) .text( 'TemplateData' ); helpLink = $( '<a>' ) .attr( 'target', '_blank' ) .attr( 'title', 'Opens in new tab' ) .attr( 'href', 'https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Extension:TemplateWizard' ) .text( mw.message( 'templatewizard-help-page' ) ); description = mw.message( 'templatewizard-template-not-found', templateLink[ 0 ].outerHTML, templateDataLink[ 0 ].outerHTML, helpLink[ 0 ].outerHTML ).plain(); } if ( description ) { this.$element.append( $( '<p>' ).addClass( 'description' ).append( description ) ); } // 2. Parameters. if ( templateData.params ) { groupedParams = this.processParameters( templateData.params ); this.$element.append( this.getParameterFieldsets( groupedParams ) ); } // 3. Format. if ( templateData.format ) { this.format = templateData.format; } else { this.format = 'inline'; } }; mediaWiki.TemplateWizard.TemplateForm.prototype.getParameters = function () { var params = {}; this.$element.find( ':input' ).each( function () { var name = $( this ).attr( 'name' ), value = $( this ).val(); if ( value ) { params[ name ] = value; } } ); return params; }; mediaWiki.TemplateWizard.TemplateForm.prototype.processParameters = function ( params ) { var groupedParams = { required: {}, suggested: {}, optional: {} }; $.each( params, function ( param, details ) { if ( details.deprecated ) { // Don't include even a mention of a deprecated parameter. return; } if ( details.required ) { groupedParams.required[ param ] = details; } else if ( details.suggested ) { groupedParams.suggested[ param ] = details; } else { groupedParams.optional[ param ] = details; } } ); return groupedParams; }; /** * */ mediaWiki.TemplateWizard.TemplateForm.prototype.loadTemplateData = function () { var templateForm = this; templateForm.dialog.pushPending(); new mw.Api().get( { action: 'templatedata', titles: this.title.getPrefixedDb(), redirects: true, doNotIgnoreMissingTitles: true, lang: mw.config.get( 'wgUserLanguage' ) } ) .done( function ( apiResponse ) { var fieldsets = templateForm.processTemplateData( apiResponse ); templateForm.$element.append( fieldsets ); } ) .always( function () { templateForm.dialog.popPending(); } ); }; /** * @class * @constructor * @param {Object} [config] Configuration options. * @param {OO.ui.ProcessDialog} [dialog] The dialog to attach the form to. */ mediaWiki.TemplateWizard.SearchForm = function mediaWikiTemplateWizardSearchForm( config, dialog ) { config.padded = true; config.expanded = true; mediaWiki.TemplateWizard.SearchForm.super.call( this, config ); this.dialog = dialog; this.titleSearchWidget = new mw.widgets.TitleInputWidget( { validate: true, namespace: mw.config.get( 'wgNamespaceIds' ).template } ); this.titleSearchWidget.connect( this, { change: 'onSearchWidgetChange', enter: 'onSearchWidgetEnter' } ); this.searchButton = new OO.ui.ButtonWidget( { label: OO.ui.deferMsg( 'templatewizard-use' ), flags: [ 'progressive' ] } ); this.searchButton.connect( this, { click: 'onSearchButtonClick' } ); this.searchField = new OO.ui.ActionFieldLayout( this.titleSearchWidget, this.searchButton, { label: OO.ui.deferMsg( 'templatewizard-select-template' ) } ); this.titleSearchWidget.emit( 'change' ); this.$element.append( this.searchField.$element ); }; OO.inheritClass( mediaWiki.TemplateWizard.SearchForm, OO.ui.PanelLayout ); mediaWiki.TemplateWizard.SearchForm.prototype.getTemplateForm = function () { return this.templateForm; }; mediaWiki.TemplateWizard.SearchForm.prototype.onSearchButtonClick = function () { this.searchField.setErrors( [] ); this.templateForm = new mw.TemplateWizard.TemplateForm(); try { this.templateForm.setDialog( this.dialog ); this.templateForm.setTitle( this.titleSearchWidget.value ); this.dialog.setResultsPanel( this.templateForm.$element ); this.dialog.actions.setMode( 'insert' ); } catch ( e ) { this.titleSearchWidget.$input.focus(); this.titleSearchWidget.$element.addClass( 'oo-ui-flaggedElement-invalid' ); this.dialog.actions.setMode( 'choose' ); this.searchField.setErrors( [ e.message ] ); } }; mediaWiki.TemplateWizard.SearchForm.prototype.onSearchWidgetChange = function () { this.titleSearchWidget.$element.removeClass( 'oo-ui-flaggedElement-invalid' ); this.searchButton.setDisabled( !this.titleSearchWidget.value ); }; mediaWiki.TemplateWizard.SearchForm.prototype.onSearchWidgetEnter = function () { this.searchButton.$button.focus(); this.searchButton.emit( 'click' ); }; /** * @class * @constructor */ mediaWiki.TemplateWizard.TemplateFormatter = function mwTemplateWizardTemplateFormatter() { this.name = ''; this.format = ''; this.params = {}; }; OO.initClass( mediaWiki.TemplateWizard.TemplateFormatter ); mediaWiki.TemplateWizard.TemplateFormatter.static.FORMATSTRING_REGEXP = /^(\n)?(\{\{ *_+)(\n? *\|\n? *_+ *= *)(_+)(\n? *\}\})(\n)?$/; mediaWiki.TemplateWizard.TemplateFormatter.prototype.setTemplateName = function ( newName ) { this.name = newName; }; mediaWiki.TemplateWizard.TemplateFormatter.prototype.setParameters = function ( params ) { this.params = params; }; mediaWiki.TemplateWizard.TemplateFormatter.prototype.setFormat = function ( format ) { var parsedFormat, inlineFormat = '{{_|_=_}}'; if ( format === 'inline' ) { format = inlineFormat; } if ( format === 'block' ) { format = '{{_\n| _ = _\n}}'; } // Check format string for validity, and fall back to 'inline' if it's not. parsedFormat = format.match( this.constructor.static.FORMATSTRING_REGEXP ); if ( !parsedFormat ) { parsedFormat = inlineFormat.match( this.constructor.static.FORMATSTRING_REGEXP ); } this.format = { startOfLine: parsedFormat[ 1 ], start: parsedFormat[ 2 ], paramName: parsedFormat[ 3 ], paramValue: parsedFormat[ 4 ], end: parsedFormat[ 5 ], endOfLine: parsedFormat[ 6 ] }; }; mediaWiki.TemplateWizard.TemplateFormatter.prototype.getFormat = function () { if ( !this.format ) { this.setFormat( 'inline' ); } return this.format; }; mediaWiki.TemplateWizard.TemplateFormatter.prototype.getTemplate = function () { var template, formatter = this, format = this.getFormat(); // Start building the template. template = ''; if ( format.startOfLine ) { template += '\n'; } template += this.constructor.static.formatStringSubst( format.start, this.name ); // Process the parameters. $.each( formatter.params, function ( key, val ) { template += formatter.constructor.static.formatStringSubst( format.paramName, key ) + formatter.constructor.static.formatStringSubst( format.paramValue, val ); } ); // End and return the template. template += format.end; if ( format.endOfLine && !template.match( /\n$/ ) ) { template += '\n'; } return template; }; /** * Format a part of the template, based on the TemplateData format string. * This method is based on that of the same name in Parsoid: * https://github.com/wikimedia/parsoid/blob/9c80dd597a8c057d43598303fd53e90cbed4ffdb/lib/html2wt/WikitextSerializer.js#L405 * @param {String} format * @param {String} value * @return {String} */ mediaWiki.TemplateWizard.TemplateFormatter.static.formatStringSubst = function ( format, value ) { value = value.trim(); return format.replace( /_+/, function ( hole ) { if ( value === '' || hole.length <= value.length ) { return value; } // Right-pad with spaces. while ( value.length < hole.length ) { value += ' '; } return value; // + ( ' '.repeat( hole.length - value.length ) ); } ); }; /** * The main dialog box for the TemplateWizard. * @class * @constructor * @extends OO.ui.ProcessDialog * @param {object} config */ mediaWiki.TemplateWizard.Dialog = function mediaWikiTemplateWizardDialog( config ) { mediaWiki.TemplateWizard.Dialog.super.call( this, config ); }; OO.inheritClass( mediaWiki.TemplateWizard.Dialog, OO.ui.ProcessDialog ); mediaWiki.TemplateWizard.Dialog.static.name = 'templateWizard'; mediaWiki.TemplateWizard.Dialog.static.title = OO.ui.deferMsg( 'templatewizard-dialog-title' ); mediaWiki.TemplateWizard.Dialog.static.actions = [ { label: OO.ui.deferMsg( 'templatewizard-insert' ), flags: [ 'primary', 'progressive' ], action: 'insert', modes: 'insert' }, { label: OO.ui.deferMsg( 'templatewizard-cancel' ), flags: 'safe', modes: [ 'choose', 'insert' ] } ]; mediaWiki.TemplateWizard.Dialog.prototype.getBodyHeight = function () { return 400; }; mediaWiki.TemplateWizard.Dialog.prototype.initialize = function () { mediaWiki.TemplateWizard.Dialog.super.prototype.initialize.apply( this, arguments ); // Set up the search form and results panel. this.searchForm = new mw.TemplateWizard.SearchForm( {}, this ); this.resultsPanel = new OO.ui.PanelLayout( { padded: true, expanded: true } ); // Put the panels together and add to the dialog body. this.stack = new OO.ui.StackLayout( { items: [ this.searchForm, this.resultsPanel ], continuous: true } ); this.$body.append( this.stack.$element ); }; mediaWiki.TemplateWizard.Dialog.prototype.setResultsPanel = function ( panelContents ) { this.resultsPanel.$element.html( panelContents ); }; mediaWiki.TemplateWizard.Dialog.prototype.getSetupProcess = function ( data ) { return mediaWiki.TemplateWizard.Dialog.super.prototype.getSetupProcess.call( this, data ) .next( function () { this.actions.setMode( 'choose' ); }, this ); }; mediaWiki.TemplateWizard.Dialog.prototype.getActionProcess = function ( action ) { var dialog = this, templateFormatter; if ( action === 'insert' ) { templateFormatter = new mw.TemplateWizard.TemplateFormatter(); templateFormatter.setTemplateName( this.searchForm.getTemplateForm().getTitle().getMainText() ); templateFormatter.setFormat( this.searchForm.getTemplateForm().getFormat() ); templateFormatter.setParameters( this.searchForm.getTemplateForm().getParameters() ); $( '#wpTextbox1' ).textSelection( 'encapsulateSelection', { post: templateFormatter.getTemplate() } ); return new OO.ui.Process( function () { dialog.close( { action: action } ); } ); } // Fallback to parent handler. return mediaWiki.TemplateWizard.Dialog.super.prototype.getActionProcess.call( this, action ); }; addButton(); } function addButton() { $( '#wpTextbox1' ).wikiEditor( 'addToToolbar', { section: 'main', group: 'insert', tools: { 'template-wizard': { labelMsg: 'templatewizard-dialog-title', type: 'button', icon: 'https://en.wikipedia.org/w/load.php?modules=oojs-ui.styles.icons-editing-advanced&image=puzzle&format=rasterized&lang=en&skin=vector&version=1vkcvi7', action: { type: 'callback', execute: function () { var templateWizard = new mw.TemplateWizard.Dialog(), windowManager = new OO.ui.WindowManager(); $( 'body' ).append( windowManager.$element ); windowManager.addWindows( [ templateWizard ] ); windowManager.openWindow( templateWizard ); } } } } } ); } function main() { // @TODO $( '#wpTextbox1' ).on( 'wikiEditor-toolbar-doneInitialSections', addButton ); var isEditing = $.inArray( mw.config.get( 'wgAction' ), [ 'edit', 'submit' ] ) !== -1; if ( !isEditing ) { return; } // Otherwise, add the toolbar button. mw.loader.using( 'user.options', function () { var dependencies; // This can be the string "0" if the user disabled the preference. if ( mw.user.options.get( 'usebetatoolbar' ) ) { dependencies = [ 'ext.wikiEditor', 'jquery.textSelection', 'oojs-ui-core', 'oojs-ui-windows', 'oojs-ui-widgets', 'mediawiki.widgets', 'mediawiki.widgets.UserInputWidget', 'mediawiki.widgets.DateInputWidget' ]; mw.loader.using( dependencies, $.ready ).then( defineClasses ); } } ); } main(); // }( mediaWiki, jQuery ) );