/*! * VisualEditor UserInterface LanguageVariantInspector class. * * @copyright 2011-2018 VisualEditor Team and others; see http://ve.mit-license.org */ /** * 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' } ].concat( 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. * * @method * @return {Object} */ ve.ui.MWLanguageVariantInspector.prototype.getDefaultVariantInfo = function () { throw new Error( 'getDefaultVariantInfo must be implemented by subclass' ); }; /* eslint-disable no-unused-vars */ /** * Convert the current inspector state to new content which can be used * to update the ve.dm.SurfaceFragment backing this inspector. * * @method * @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 = function ( variantInfo ) { throw new Error( 'getContentFromInspector must be implemented by subclass' ); }; /* eslint-enable no-unused-vars */ // 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. * * @method * @param {String} [placeholder] Placeholder text for this editor. * @return {ve.ui.TargetWidget} */ ve.ui.MWLanguageVariantInspector.prototype.createTextTarget = function ( placeholder ) { return ve.init.target.createTargetWidget( { tools: ve.init.target.constructor.static.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. * * @method * @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.Document} The document model now backing the widget. */ ve.ui.MWLanguageVariantInspector.prototype.setupTextTargetDoc = function ( textTarget, htmlString ) { var doc = this.variantNode.getDocument().newFromHtml( htmlString ); textTarget.setDocument( doc ); textTarget.initialize(); 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. * * @method * @param {ve.Document} 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 ) { var surface = new ve.dm.Surface( doc ), targetHtmlDoc; // 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
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? targetHtmlDoc = ve.dm.converter.getDomFromModel( doc, false ); return ve.properInnerHtml( targetHtmlDoc.body ); }; // Inspector implementation /** * Handle frame ready events. * * @method */ 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( function () { this.close( { action: action } ); }, this ); } return ve.ui.MWLanguageVariantInspector.super.prototype.getActionProcess.call( this, action ); }; /** * Handle the inspector being setup. * * @method * @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( function () { 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(); } }, this ); }; /** * @inheritdoc */ ve.ui.MWLanguageVariantInspector.prototype.getTeardownProcess = function ( data ) { data = data || {}; return ve.ui.MWLanguageVariantInspector.super.prototype.getTeardownProcess.call( this, data ) .first( function () { var surfaceModel = this.getFragment().getSurface(), newContent; 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 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(); } }, this ); }; /* 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( function () { var variantInfo = this.variantNode.getVariantInfo(); this.textTargetDoc = this.setupTextTargetDoc( this.textTarget, variantInfo.disabled.t ); }, this ); }; ve.ui.MWLanguageVariantDisabledInspector.prototype.getContentFromInspector = function ( variantInfo ) { // TODO should allow type to depend on targetHtmlDoc, maybe switch // from inline to block. var 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( function () { this.textTarget.focus(); }, this ); }; ve.ui.MWLanguageVariantDisabledInspector.prototype.getTeardownProcess = function ( data ) { return ve.ui.MWLanguageVariantDisabledInspector.super.prototype.getTeardownProcess.call( this, data ) .next( function () { // Reset inspector this.textTarget.clear(); this.textTargetDoc = null; }, this ); }; /** * 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( function () { var variantInfo = this.variantNode.getVariantInfo(); this.languageInput.setLangAndDir( variantInfo.name.t, 'auto' ); }, this ); }; ve.ui.MWLanguageVariantNameInspector.prototype.getContentFromInspector = function ( variantInfo ) { var 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 ) { var 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( function () { var variantInfo = this.variantNode.getVariantInfo(); this.textTargetDoc = this.setupTextTargetDoc( this.textTarget, variantInfo.filter.t ); this.langWidget.setValue( variantInfo.filter.l ); }, this ); }; ve.ui.MWLanguageVariantFilterInspector.prototype.getContentFromInspector = function ( variantInfo ) { // TODO should allow type to depend on targetHtmlDoc, maybe switch // from inline to block. var 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( function () { this.textTarget.focus(); }, this ); }; ve.ui.MWLanguageVariantFilterInspector.prototype.getTeardownProcess = function ( data ) { return ve.ui.MWLanguageVariantFilterInspector.super.prototype.getTeardownProcess.call( this, data ) .next( function () { // Reset inspector this.langWidget.clearInput(); this.langWidget.clearItems(); this.textTarget.clear(); this.textTargetDoc = null; }, this ); }; /** * 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( function () { var variantInfo = this.variantNode.getVariantInfo(); this.layout.clearItems(); this.items = []; variantInfo.twoway.forEach( function ( tw, idx ) { this.items[ idx ] = this.createItem( tw.l, tw.t ); this.layout.addItems( [ this.items[ idx ].layout ] ); }, this ); }, this ); }; /** * Create widgets corresponding to a given mapping given by this rule. * @method * @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 ) { var languageInput, textTarget, clearButton, layout, item; languageInput = new ve.ui.LanguageInputWidget( { dialogManager: this.manager.getSurface().getDialogs(), dirInput: 'none' } ); textTarget = this.createTextTarget( OO.ui.msg( 'visualeditor-mwlanguagevariantinspector-twoway-text-placeholder' ) ); clearButton = new OO.ui.ButtonInputWidget( { icon: 'clear', iconTitle: OO.ui.deferMsg( 'visualeditor-mwlanguagevariantinspector-twoway-clear-button' ), framed: false } ); layout = new OO.ui.FieldLayout( new OO.ui.Widget( { content: [ new OO.ui.ActionFieldLayout( languageInput, clearButton ), textTarget ] } ), {} ); 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. var type = this.variantNode.getType(); variantInfo.twoway = this.items.map( function ( item ) { return { l: item.languageInput.getLang(), t: this.getHtmlForDoc( item.textTargetDoc ) }; }, this ); return [ { type: type, attributes: { variantInfo: variantInfo } }, { type: '/' + type } ]; }; /** * Create a new mapping item in the inspector. * @method */ ve.ui.MWLanguageVariantTwoWayInspector.prototype.onAddButtonClick = function () { var 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. * @method */ ve.ui.MWLanguageVariantTwoWayInspector.prototype.onClearButtonClick = function ( item ) { var 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( function () { var variantInfo = this.variantNode.getVariantInfo(); this.layout.clearItems(); this.items = []; variantInfo.oneway.forEach( function ( ow, idx ) { this.items[ idx ] = this.createItem( ow.f, ow.l, ow.t ); this.layout.addItems( [ this.items[ idx ].layout ] ); }, this ); }, this ); }; /** * Create widgets corresponding to a given mapping given by this rule. * @method * @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 ) { var fromTextTarget, languageInput, toTextTarget, clearButton, layout, item; fromTextTarget = this.createTextTarget( OO.ui.msg( 'visualeditor-mwlanguagevariantinspector-oneway-from-text-placeholder' ) ); languageInput = new ve.ui.LanguageInputWidget( { dialogManager: this.manager.getSurface().getDialogs(), dirInput: 'none' } ); toTextTarget = this.createTextTarget( OO.ui.msg( 'visualeditor-mwlanguagevariantinspector-oneway-to-text-placeholder' ) ); clearButton = new OO.ui.ButtonInputWidget( { icon: 'clear', iconTitle: OO.ui.deferMsg( 'visualeditor-mwlanguagevariantinspector-oneway-clear-button' ), framed: false } ); layout = new OO.ui.FieldLayout( new OO.ui.Widget( { content: [ new OO.ui.ActionFieldLayout( fromTextTarget, clearButton ), languageInput, toTextTarget ] } ), {} ); 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. var type = this.variantNode.getType(); variantInfo.oneway = this.items.map( function ( item ) { return { f: this.getHtmlForDoc( item.fromTextTargetDoc ), l: item.languageInput.getLang(), t: this.getHtmlForDoc( item.toTextTargetDoc ) }; }, this ); return [ { type: type, attributes: { variantInfo: variantInfo } }, { type: '/' + type } ]; }; /** * Create a new mapping item in the inspector. * @method */ ve.ui.MWLanguageVariantOneWayInspector.prototype.onAddButtonClick = function () { var 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. * @method */ ve.ui.MWLanguageVariantOneWayInspector.prototype.onClearButtonClick = function ( item ) { var 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 );