mediawiki-extensions-Visual.../modules/ve-mw/ui/inspectors/ve.ui.MWLanguageVariantInspector.js
Ed Sanders b9b966de6e Avoid Array.concat
See I9addf43b2857de7bcac.

Change-Id: Ic1998ab6f7dedf6946d7ae63a985a76031f8eecf
2024-05-29 21:16:25 +01:00

841 lines
25 KiB
JavaScript

/*!
* VisualEditor UserInterface LanguageVariantInspector class.
*
* @copyright See AUTHORS.txt
*/
/**
* Inspector for a ve.dm.MWLanguageVariantNode.
*
* @class
* @extends ve.ui.NodeInspector
*
* @constructor
* @param {Object} [config] Configuration options
*/
ve.ui.MWLanguageVariantInspector = function VeUiMWLanguageVariantInspector() {
// Parent constructor
ve.ui.MWLanguageVariantInspector.super.apply( this, arguments );
};
/* Inheritance */
OO.inheritClass( ve.ui.MWLanguageVariantInspector, ve.ui.NodeInspector );
/* Static properties */
ve.ui.MWLanguageVariantInspector.static.name = 'mwLanguageVariant-disabled';
ve.ui.MWLanguageVariantInspector.static.title = OO.ui.deferMsg(
'visualeditor-mwlanguagevariantinspector-title-disabled'
);
ve.ui.MWLanguageVariantInspector.static.modelClasses = [
ve.dm.MWLanguageVariantBlockNode,
ve.dm.MWLanguageVariantInlineNode,
ve.dm.MWLanguageVariantHiddenNode
];
ve.ui.MWLanguageVariantInspector.static.size = 'large';
ve.ui.MWLanguageVariantInspector.static.actions = [
{
action: 'remove',
label: OO.ui.deferMsg( 'visualeditor-inspector-remove-tooltip' ),
flags: 'destructive',
modes: 'edit'
},
...ve.ui.MWLanguageVariantInspector.super.static.actions
];
ve.ui.MWLanguageVariantInspector.static.defaultVariantType =
'mwLanguageVariantInline';
ve.ui.MWLanguageVariantInspector.static.includeCommands = null;
// This is very similar to the exclude list in ve.ui.MWMediaDialog
ve.ui.MWLanguageVariantInspector.static.excludeCommands = [
// No formatting
'paragraph',
'heading1',
'heading2',
'heading3',
'heading4',
'heading5',
'heading6',
'preformatted',
'blockquote',
// TODO: Decide if tables tools should be allowed
'tableCellHeader',
'tableCellData',
// No structure
'bullet',
'bulletWrapOnce',
'number',
'numberWrapOnce',
'indent',
'outdent'
];
/**
* Get the import rules for embedded target widgets in this inspector.
*
* @see ve.ui.MWMediaDialog#getImportRules
* @return {Object} Import rules
*/
ve.ui.MWLanguageVariantInspector.static.getImportRules = function () {
return ve.extendObject(
ve.copy( ve.init.target.constructor.static.importRules ),
{
// TODO: We might want to include some of the
// conversion/sanitization done by ve.ui.MWMediaDialog
}
);
};
/* Methods */
/**
* Return a valid `variantInfo` object which will be used when a new
* node of this subclass is inserted. For instance,
* ve.ui.MWLanguageVariantDisabledInspector will return the appropriate
* object to use when the equivalent of wikitext `-{}-` is inserted
* in the document.
*
* @return {Object}
*/
ve.ui.MWLanguageVariantInspector.prototype.getDefaultVariantInfo = null;
/**
* Convert the current inspector state to new content which can be used
* to update the ve.dm.SurfaceFragment backing this inspector.
*
* @param {Object} An existing variantInfo object for this node, which will be
* mutated to update it with the latest content from this inspector.
* @return {string|Array} New content for the ve.dm.SurfaceFragment
* being inspected/updated.
*/
ve.ui.MWLanguageVariantInspector.prototype.getContentFromInspector = null;
// Helper functions for creating sub-document editors for embedded HTML
/**
* Helper function to create a subdocument editor for HTML embedded in the
* language variant node.
*
* @param {string} [placeholder] Placeholder text for this editor.
* @return {ve.ui.TargetWidget}
*/
ve.ui.MWLanguageVariantInspector.prototype.createTextTarget = function ( placeholder ) {
return ve.init.target.createTargetWidget( {
toolbarGroups: [],
includeCommands: this.constructor.static.includeCommands,
excludeCommands: this.constructor.static.excludeCommands,
importRules: this.constructor.static.getImportRules(),
inDialog: this.constructor.static.name,
placeholder: placeholder || null
} );
};
/**
* Helper function to initialize a ve.ui.TargetWidget with a given HTML
* string extracted from the language variant node.
*
* @param {ve.ui.TargetWidget} [textTarget] A subdocument editor widget
* created by ve.ui.MWLanguageVariantInspector#createTextTarget.
* @param {string} [htmlString] The HTML string extracted from this node.
* @return {ve.dm.Document} The document model now backing the widget.
*/
ve.ui.MWLanguageVariantInspector.prototype.setupTextTargetDoc = function ( textTarget, htmlString ) {
const doc = this.variantNode.getDocument().newFromHtml( htmlString );
textTarget.setDocument( doc );
return doc;
};
/**
* Helper function to serialize the document backing a `ve.ui.TargetWidget`
* back into HTML which can be embedded into the language variant node.
* This method needs to do a bit of hackery to remove unnecessary p-wrapping
* and (TODO) determine if an inline node needs to be converted to a
* block node or vice-versa.
*
* @param {ve.dm.Document} doc The document backing an editor widget, as returned
* by ve.ui.MWLanguageVariantInspector#setupTextTargetDoc.
* @return {string} An HTML string appropriate for embedding into a
* language variant node.
*/
ve.ui.MWLanguageVariantInspector.prototype.getHtmlForDoc = function ( doc ) {
const surface = new ve.dm.Surface( doc );
// Remove outermost p-wrapping, if present
try {
surface.change(
ve.dm.TransactionBuilder.static.newFromWrap( doc, new ve.Range( 0, doc.data.countNonInternalElements() ), [], [], [ { type: 'paragraph' } ], [] )
);
} catch ( e ) {
// Sometimes there is no p-wrapping, for example: "* foo"
// Sometimes there are multiple <p> tags in the output.
// That's okay: ignore the error and use what we've got.
}
// XXX return a flag to indicate whether contents are now inline or block?
const targetHtmlDoc = ve.dm.converter.getDomFromModel( doc );
return ve.properInnerHtml( targetHtmlDoc.body );
};
// Inspector implementation
/**
* Handle frame ready events.
*/
ve.ui.MWLanguageVariantInspector.prototype.initialize = function () {
// Parent method
ve.ui.MWLanguageVariantInspector.super.prototype.initialize.call( this );
this.$content.addClass( 've-ui-mwLanguageVariantInspector-content' );
};
/**
* @inheritdoc
*/
ve.ui.MWLanguageVariantInspector.prototype.getActionProcess = function ( action ) {
if ( action === 'remove' || action === 'insert' ) {
return new OO.ui.Process( () => {
this.close( { action: action } );
} );
}
return ve.ui.MWLanguageVariantInspector.super.prototype.getActionProcess.call( this, action );
};
/**
* Handle the inspector being setup.
*
* @param {Object} [data] Inspector opening data
* @return {OO.ui.Process}
*/
ve.ui.MWLanguageVariantInspector.prototype.getSetupProcess = function ( data ) {
return ve.ui.MWLanguageVariantInspector.super.prototype.getSetupProcess.call( this, data )
.next( () => {
this.getFragment().getSurface().pushStaging();
this.variantNode = this.getSelectedNode();
if ( !this.variantNode ) {
this.getFragment().insertContent( [
{
type: this.constructor.static.defaultVariantType,
attributes: {
variantInfo: this.getDefaultVariantInfo()
}
},
{ type: '/' + this.constructor.static.defaultVariantType }
] ).select();
this.variantNode = this.getSelectedNode();
}
} );
};
/**
* @inheritdoc
*/
ve.ui.MWLanguageVariantInspector.prototype.getTeardownProcess = function ( data ) {
data = data || {};
return ve.ui.MWLanguageVariantInspector.super.prototype.getTeardownProcess.call( this, data )
.first( () => {
const surfaceModel = this.getFragment().getSurface();
if ( data.action === 'remove' ) {
surfaceModel.popStaging();
// If popStaging removed the node then this will be a no-op
this.getFragment().removeContent();
} else if ( data.action === 'done' ) {
// Edit language variant node
const newContent = this.getContentFromInspector(
ve.copy( this.variantNode.getVariantInfo() )
);
if ( newContent[ 0 ].type === this.variantNode.getType() ) {
this.getFragment().changeAttributes( {
variantInfo: newContent[ 0 ].attributes.variantInfo
} );
} else {
this.getFragment().removeContent();
this.getFragment().insertContent( newContent ).select();
this.variantNode = this.getSelectedNode();
}
surfaceModel.applyStaging();
} else {
surfaceModel.popStaging();
}
} );
};
/* Subclasses */
/**
* Editor for "disabled" rules.
*
* @class
* @extends ve.ui.MWLanguageVariantInspector
*
* @constructor
* @param {Object} [config] Configuration options
*/
ve.ui.MWLanguageVariantDisabledInspector = function VeUiMWLanguageVariantDisabledInspector() {
ve.ui.MWLanguageVariantDisabledInspector.super.apply( this, arguments );
};
/* Inheritance */
OO.inheritClass( ve.ui.MWLanguageVariantDisabledInspector, ve.ui.MWLanguageVariantInspector );
/* Static properties */
ve.ui.MWLanguageVariantDisabledInspector.static.name = 'mwLanguageVariant-disabled';
ve.ui.MWLanguageVariantDisabledInspector.static.title = OO.ui.deferMsg(
'visualeditor-mwlanguagevariantinspector-title-disabled'
);
/* Methods */
ve.ui.MWLanguageVariantDisabledInspector.prototype.initialize = function () {
ve.ui.MWLanguageVariantDisabledInspector.super.prototype.initialize.call( this );
this.textTarget = this.createTextTarget( OO.ui.msg(
'visualeditor-mwlanguagevariantinspector-disabled-placeholder'
) );
this.form.$element.append( this.textTarget.$element );
};
ve.ui.MWLanguageVariantDisabledInspector.prototype.getDefaultVariantInfo = function () {
return { disabled: { t: '' } };
};
ve.ui.MWLanguageVariantDisabledInspector.prototype.getSetupProcess = function ( data ) {
return ve.ui.MWLanguageVariantDisabledInspector.super.prototype.getSetupProcess.call( this, data ).next( () => {
const variantInfo = this.variantNode.getVariantInfo();
this.textTargetDoc = this.setupTextTargetDoc(
this.textTarget,
variantInfo.disabled.t
);
} );
};
ve.ui.MWLanguageVariantDisabledInspector.prototype.getContentFromInspector = function ( variantInfo ) {
// TODO should allow type to depend on targetHtmlDoc, maybe switch
// from inline to block.
const type = this.variantNode.getType();
variantInfo.disabled.t = this.getHtmlForDoc( this.textTargetDoc );
return [
{
type: type,
attributes: { variantInfo: variantInfo }
},
{
type: '/' + type
}
];
};
ve.ui.MWLanguageVariantDisabledInspector.prototype.getReadyProcess = function ( data ) {
return ve.ui.MWLanguageVariantDisabledInspector.super.prototype.getReadyProcess.call( this, data )
.next( () => {
this.textTarget.focus();
} );
};
ve.ui.MWLanguageVariantDisabledInspector.prototype.getTeardownProcess = function ( data ) {
return ve.ui.MWLanguageVariantDisabledInspector.super.prototype.getTeardownProcess.call( this, data )
.next( () => {
// Reset inspector
this.textTarget.clear();
this.textTargetDoc = null;
} );
};
/**
* Editor for "name" rules.
*
* @class
* @extends ve.ui.MWLanguageVariantInspector
*
* @constructor
* @param {Object} [config] Configuration options
*/
ve.ui.MWLanguageVariantNameInspector = function VeUiMWLanguageVariantNameInspector() {
ve.ui.MWLanguageVariantNameInspector.super.apply( this, arguments );
};
/* Inheritance */
OO.inheritClass( ve.ui.MWLanguageVariantNameInspector, ve.ui.MWLanguageVariantInspector );
/* Static properties */
ve.ui.MWLanguageVariantNameInspector.static.name = 'mwLanguageVariant-name';
ve.ui.MWLanguageVariantNameInspector.static.title = OO.ui.deferMsg(
'visualeditor-mwlanguagevariantinspector-title-name'
);
/* Methods */
ve.ui.MWLanguageVariantNameInspector.prototype.initialize = function () {
ve.ui.MWLanguageVariantNameInspector.super.prototype.initialize.call( this );
this.languageInput = new ve.ui.LanguageInputWidget( {
dialogManager: this.manager.getSurface().getDialogs(),
dirInput: 'none'
} );
this.form.$element.append( this.languageInput.$element );
};
ve.ui.MWLanguageVariantNameInspector.prototype.getDefaultVariantInfo = function () {
return { name: { t: mw.config.get( 'wgUserVariant' ) || 'en' } };
};
ve.ui.MWLanguageVariantNameInspector.prototype.getSetupProcess = function ( data ) {
return ve.ui.MWLanguageVariantNameInspector.super.prototype.getSetupProcess.call( this, data )
.next( () => {
const variantInfo = this.variantNode.getVariantInfo();
this.languageInput.setLangAndDir(
variantInfo.name.t,
'auto'
);
} );
};
ve.ui.MWLanguageVariantNameInspector.prototype.getContentFromInspector = function ( variantInfo ) {
const type = this.variantNode.getType();
variantInfo.name.t = this.languageInput.getLang();
return [
{
type: type,
attributes: { variantInfo: variantInfo }
},
{
type: '/' + type
}
];
};
/**
* Editor for "filter" rules.
*
* @class
* @extends ve.ui.MWLanguageVariantInspector
*
* @constructor
* @param {Object} [config] Configuration options
*/
ve.ui.MWLanguageVariantFilterInspector = function VeUiMWLanguageVariantFilterInspector() {
ve.ui.MWLanguageVariantFilterInspector.super.apply( this, arguments );
};
/* Inheritance */
OO.inheritClass( ve.ui.MWLanguageVariantFilterInspector, ve.ui.MWLanguageVariantInspector );
/* Static properties */
ve.ui.MWLanguageVariantFilterInspector.static.name = 'mwLanguageVariant-filter';
ve.ui.MWLanguageVariantFilterInspector.static.title = OO.ui.deferMsg(
'visualeditor-mwlanguagevariantinspector-title-filter'
);
/* Methods */
ve.ui.MWLanguageVariantFilterInspector.prototype.initialize = function () {
ve.ui.MWLanguageVariantFilterInspector.super.prototype.initialize.call( this );
this.textTarget = this.createTextTarget( OO.ui.msg(
'visualeditor-mwlanguagevariantinspector-filter-text-placeholder'
) );
this.langWidget = new OO.ui.TagMultiselectWidget( {
allowArbitary: false,
allowDisplayInvalidTags: true,
allowedValues: ve.init.platform.getLanguageCodes().sort(),
placeholder: OO.ui.msg(
'visualeditor-mwlanguagevariantinspector-filter-langs-placeholder'
),
icon: 'language'
} );
this.langWidget.createTagItemWidget = function ( data, label ) {
const name = ve.init.platform.getLanguageName( data.toLowerCase() );
label = label || ( name ? ( name + ' (' + data + ')' ) : data );
return OO.ui.TagMultiselectWidget.prototype.createTagItemWidget.call(
this, data, label
);
};
this.form.$element.append(
new OO.ui.FieldLayout( this.langWidget, {
align: 'top',
label: OO.ui.msg( 'visualeditor-mwlanguagevariantinspector-filter-langs-label' )
} ).$element
);
this.form.$element.append(
new OO.ui.FieldLayout( this.textTarget, {
align: 'top',
label: OO.ui.msg( 'visualeditor-mwlanguagevariantinspector-filter-text-label' )
} ).$element
);
};
ve.ui.MWLanguageVariantFilterInspector.prototype.getDefaultVariantInfo = function () {
return { filter: { l: [ mw.config.get( 'wgUserVariant' ) ], t: '' } };
};
ve.ui.MWLanguageVariantFilterInspector.prototype.getSetupProcess = function ( data ) {
return ve.ui.MWLanguageVariantFilterInspector.super.prototype.getSetupProcess.call( this, data ).next( () => {
const variantInfo = this.variantNode.getVariantInfo();
this.textTargetDoc = this.setupTextTargetDoc(
this.textTarget,
variantInfo.filter.t
);
this.langWidget.setValue( variantInfo.filter.l );
} );
};
ve.ui.MWLanguageVariantFilterInspector.prototype.getContentFromInspector = function ( variantInfo ) {
// TODO should allow type to depend on targetHtmlDoc, maybe switch
// from inline to block.
const type = this.variantNode.getType();
variantInfo.filter.t = this.getHtmlForDoc( this.textTargetDoc );
variantInfo.filter.l = this.langWidget.getValue();
return [
{
type: type,
attributes: { variantInfo: variantInfo }
},
{
type: '/' + type
}
];
};
ve.ui.MWLanguageVariantFilterInspector.prototype.getReadyProcess = function ( data ) {
return ve.ui.MWLanguageVariantFilterInspector.super.prototype.getReadyProcess.call( this, data )
.next( () => {
this.textTarget.focus();
} );
};
ve.ui.MWLanguageVariantFilterInspector.prototype.getTeardownProcess = function ( data ) {
return ve.ui.MWLanguageVariantFilterInspector.super.prototype.getTeardownProcess.call( this, data )
.next( () => {
// Reset inspector
this.langWidget.clearInput();
this.langWidget.clearItems();
this.textTarget.clear();
this.textTargetDoc = null;
} );
};
/**
* Editor for "two-way" rules.
*
* @class
* @extends ve.ui.MWLanguageVariantInspector
*
* @constructor
* @param {Object} [config] Configuration options
*/
ve.ui.MWLanguageVariantTwoWayInspector = function VeUiMWLanguageVariantTwoWayInspector() {
ve.ui.MWLanguageVariantTwoWayInspector.super.apply( this, arguments );
};
/* Inheritance */
OO.inheritClass( ve.ui.MWLanguageVariantTwoWayInspector, ve.ui.MWLanguageVariantInspector );
/* Static properties */
ve.ui.MWLanguageVariantTwoWayInspector.static.name = 'mwLanguageVariant-twoway';
ve.ui.MWLanguageVariantTwoWayInspector.static.title = OO.ui.deferMsg(
'visualeditor-mwlanguagevariantinspector-title-twoway'
);
/* Methods */
ve.ui.MWLanguageVariantTwoWayInspector.prototype.initialize = function () {
ve.ui.MWLanguageVariantTwoWayInspector.super.prototype.initialize.call( this );
this.items = [];
this.layout = new OO.ui.FieldsetLayout( { } );
this.form.$element.append( this.layout.$element );
this.addButton = new OO.ui.ButtonInputWidget( {
label: OO.ui.msg( 'visualeditor-mwlanguagevariantinspector-twoway-add-button' ),
icon: 'add'
} );
this.form.$element.append( this.addButton.$element );
// Events
this.addButton.connect( this, { click: 'onAddButtonClick' } );
};
ve.ui.MWLanguageVariantTwoWayInspector.prototype.getDefaultVariantInfo = function () {
return { twoway: [ { l: mw.config.get( 'wgUserVariant' ), t: '' } ] };
};
ve.ui.MWLanguageVariantTwoWayInspector.prototype.getSetupProcess = function ( data ) {
return ve.ui.MWLanguageVariantTwoWayInspector.super.prototype.getSetupProcess.call( this, data ).next( () => {
const variantInfo = this.variantNode.getVariantInfo();
this.layout.clearItems();
this.items = [];
variantInfo.twoway.forEach( ( tw, idx ) => {
this.items[ idx ] = this.createItem( tw.l, tw.t );
this.layout.addItems( [ this.items[ idx ].layout ] );
} );
} );
};
/**
* Create widgets corresponding to a given mapping given by this rule.
*
* @param {string} [lang] The language code for the content text.
* @param {string} [content] The HTML content text.
* @return {Object} An object containing the required widgets and backing
* documents for this mapping item.
*/
ve.ui.MWLanguageVariantTwoWayInspector.prototype.createItem = function ( lang, content ) {
const languageInput = new ve.ui.LanguageInputWidget( {
dialogManager: this.manager.getSurface().getDialogs(),
dirInput: 'none'
} );
const textTarget = this.createTextTarget( OO.ui.msg(
'visualeditor-mwlanguagevariantinspector-twoway-text-placeholder'
) );
const clearButton = new OO.ui.ButtonInputWidget( {
icon: 'clear',
title: OO.ui.deferMsg(
'visualeditor-mwlanguagevariantinspector-twoway-clear-button'
),
framed: false
} );
const layout = new OO.ui.FieldLayout(
new OO.ui.Widget( {
content: [
new OO.ui.ActionFieldLayout(
languageInput,
clearButton
),
textTarget
]
} ), {}
);
const item = {
languageInput: languageInput,
textTarget: textTarget,
clearButton: clearButton,
layout: layout
};
// Initialize
item.textTargetDoc = this.setupTextTargetDoc( textTarget, content );
languageInput.setLangAndDir( lang, 'auto' );
clearButton.connect( this, { click: [ 'onClearButtonClick', item ] } );
return item;
};
ve.ui.MWLanguageVariantTwoWayInspector.prototype.getContentFromInspector = function ( variantInfo ) {
// TODO should allow type to depend on targetHtmlDoc, maybe switch
// from inline to block.
const type = this.variantNode.getType();
variantInfo.twoway = this.items.map( ( item ) => ( {
l: item.languageInput.getLang(),
t: this.getHtmlForDoc( item.textTargetDoc )
} ) );
return [
{
type: type,
attributes: { variantInfo: variantInfo }
},
{
type: '/' + type
}
];
};
/**
* Create a new mapping item in the inspector.
*/
ve.ui.MWLanguageVariantTwoWayInspector.prototype.onAddButtonClick = function () {
const idx = this.items.length;
this.items[ idx ] = this.createItem( mw.config.get( 'wgUserVariant' ), '' );
this.layout.addItems( [ this.items[ idx ].layout ] );
};
/**
* Remove a mapping item from the inspector.
*
* @param {Object} item
*/
ve.ui.MWLanguageVariantTwoWayInspector.prototype.onClearButtonClick = function ( item ) {
const idx = this.items.indexOf( item );
this.items.splice( idx, 1 );
this.layout.removeItems( [ item.layout ] );
item.clearButton.disconnect( this );
};
/**
* Editor for "one-way" rules.
*
* @class
* @extends ve.ui.MWLanguageVariantInspector
*
* @constructor
* @param {Object} [config] Configuration options
*/
ve.ui.MWLanguageVariantOneWayInspector = function VeUiMWLanguageVariantOneWayInspector() {
ve.ui.MWLanguageVariantOneWayInspector.super.apply( this, arguments );
};
/* Inheritance */
OO.inheritClass( ve.ui.MWLanguageVariantOneWayInspector, ve.ui.MWLanguageVariantInspector );
/* Static properties */
ve.ui.MWLanguageVariantOneWayInspector.static.name = 'mwLanguageVariant-oneway';
ve.ui.MWLanguageVariantOneWayInspector.static.title = OO.ui.deferMsg(
'visualeditor-mwlanguagevariantinspector-title-oneway'
);
/* Methods */
ve.ui.MWLanguageVariantOneWayInspector.prototype.initialize = function () {
ve.ui.MWLanguageVariantOneWayInspector.super.prototype.initialize.call( this );
this.items = [];
this.layout = new OO.ui.FieldsetLayout( { } );
this.form.$element.append( this.layout.$element );
this.addButton = new OO.ui.ButtonInputWidget( {
label: OO.ui.msg( 'visualeditor-mwlanguagevariantinspector-oneway-add-button' ),
icon: 'add'
} );
this.form.$element.append( this.addButton.$element );
// Events
this.addButton.connect( this, { click: 'onAddButtonClick' } );
};
ve.ui.MWLanguageVariantOneWayInspector.prototype.getDefaultVariantInfo = function () {
return { oneway: [ { f: '', l: mw.config.get( 'wgUserVariant' ), t: '' } ] };
};
ve.ui.MWLanguageVariantOneWayInspector.prototype.getSetupProcess = function ( data ) {
return ve.ui.MWLanguageVariantOneWayInspector.super.prototype.getSetupProcess.call( this, data ).next( () => {
const variantInfo = this.variantNode.getVariantInfo();
this.layout.clearItems();
this.items = [];
variantInfo.oneway.forEach( ( ow, idx ) => {
this.items[ idx ] = this.createItem( ow.f, ow.l, ow.t );
this.layout.addItems( [ this.items[ idx ].layout ] );
} );
} );
};
/**
* Create widgets corresponding to a given mapping given by this rule.
*
* @param {string} [from] The HTML source text.
* @param {string} [lang] The language code for the destination text.
* @param {string} [to] The HTML destination text.
* @return {Object} An object containing the required widgets and backing
* documents for this mapping item.
*/
ve.ui.MWLanguageVariantOneWayInspector.prototype.createItem = function ( from, lang, to ) {
const fromTextTarget = this.createTextTarget( OO.ui.msg(
'visualeditor-mwlanguagevariantinspector-oneway-from-text-placeholder'
) );
const languageInput = new ve.ui.LanguageInputWidget( {
dialogManager: this.manager.getSurface().getDialogs(),
dirInput: 'none'
} );
const toTextTarget = this.createTextTarget( OO.ui.msg(
'visualeditor-mwlanguagevariantinspector-oneway-to-text-placeholder'
) );
const clearButton = new OO.ui.ButtonInputWidget( {
icon: 'clear',
title: OO.ui.deferMsg(
'visualeditor-mwlanguagevariantinspector-oneway-clear-button'
),
framed: false
} );
const layout = new OO.ui.FieldLayout(
new OO.ui.Widget( {
content: [
new OO.ui.ActionFieldLayout(
fromTextTarget,
clearButton
),
languageInput,
toTextTarget
]
} ), {}
);
const item = {
fromTextTarget: fromTextTarget,
languageInput: languageInput,
toTextTarget: toTextTarget,
clearButton: clearButton,
layout: layout
};
// Initialize
item.fromTextTargetDoc = this.setupTextTargetDoc( fromTextTarget, from );
item.toTextTargetDoc = this.setupTextTargetDoc( toTextTarget, to );
languageInput.setLangAndDir( lang, 'auto' );
clearButton.connect( this, { click: [ 'onClearButtonClick', item ] } );
return item;
};
ve.ui.MWLanguageVariantOneWayInspector.prototype.getContentFromInspector = function ( variantInfo ) {
// TODO should allow type to depend on targetHtmlDoc, maybe switch
// from inline to block.
const type = this.variantNode.getType();
variantInfo.oneway = this.items.map( ( item ) => ( {
f: this.getHtmlForDoc( item.fromTextTargetDoc ),
l: item.languageInput.getLang(),
t: this.getHtmlForDoc( item.toTextTargetDoc )
} ) );
return [
{
type: type,
attributes: { variantInfo: variantInfo }
},
{
type: '/' + type
}
];
};
/**
* Create a new mapping item in the inspector.
*/
ve.ui.MWLanguageVariantOneWayInspector.prototype.onAddButtonClick = function () {
const idx = this.items.length;
this.items[ idx ] = this.createItem( '', mw.config.get( 'wgUserVariant' ), '' );
this.layout.addItems( [ this.items[ idx ].layout ] );
};
/**
* Remove a mapping item from the inspector.
*
* @param {Object} item
*/
ve.ui.MWLanguageVariantOneWayInspector.prototype.onClearButtonClick = function ( item ) {
const idx = this.items.indexOf( item );
this.items.splice( idx, 1 );
this.layout.removeItems( [ item.layout ] );
item.clearButton.disconnect( this );
};
/* Registration */
ve.ui.windowFactory.register( ve.ui.MWLanguageVariantDisabledInspector );
ve.ui.windowFactory.register( ve.ui.MWLanguageVariantNameInspector );
ve.ui.windowFactory.register( ve.ui.MWLanguageVariantFilterInspector );
ve.ui.windowFactory.register( ve.ui.MWLanguageVariantTwoWayInspector );
ve.ui.windowFactory.register( ve.ui.MWLanguageVariantOneWayInspector );