mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-11-25 14:56:20 +00:00
43c2865f90
Make inspectors inheriting from MWLiveExtensionInspector and dialogs inheriting from MWExtensionPreviewDialog update their 'done' action every time updatePreview is called. Since both mix in ExtensionWindow, two new methods, updateActions and isModified are added there. This should make it more difficult to insert an empty node accidentally or create a transaction just by opening and closing an inspector or dialog. For more complicated dialogs, or inspectors or dialogs that don't live-update, this behaviour will have to be implemented separately. Bug: T155330 Change-Id: Iacafa01fcd419faaec9b112c96be86693a57d561
167 lines
4.7 KiB
JavaScript
167 lines
4.7 KiB
JavaScript
/*!
|
|
* VisualEditor UserInterface MWLiveExtensionInspector class.
|
|
*
|
|
* @copyright 2011-2017 VisualEditor Team and others; see AUTHORS.txt
|
|
* @license The MIT License (MIT); see LICENSE.txt
|
|
*/
|
|
|
|
/**
|
|
* Inspector for editing generic MediaWiki extensions with dynamic rendering.
|
|
*
|
|
* @class
|
|
* @abstract
|
|
* @extends ve.ui.MWExtensionInspector
|
|
*
|
|
* @constructor
|
|
* @param {Object} [config] Configuration options
|
|
*/
|
|
ve.ui.MWLiveExtensionInspector = function VeUiMWLiveExtensionInspector() {
|
|
// Parent constructor
|
|
ve.ui.MWLiveExtensionInspector.super.apply( this, arguments );
|
|
|
|
this.updatePreviewDebounced = ve.debounce( this.updatePreview.bind( this ), 250 );
|
|
};
|
|
|
|
/* Inheritance */
|
|
|
|
OO.inheritClass( ve.ui.MWLiveExtensionInspector, ve.ui.MWExtensionInspector );
|
|
|
|
/* Methods */
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
ve.ui.MWLiveExtensionInspector.prototype.initialize = function () {
|
|
// Parent method
|
|
ve.ui.MWLiveExtensionInspector.super.prototype.initialize.call( this );
|
|
|
|
this.generatedContentsError = new ve.ui.MWExpandableErrorElement();
|
|
this.form.$element.append( this.generatedContentsError.$element );
|
|
};
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
ve.ui.MWLiveExtensionInspector.prototype.getSetupProcess = function ( data ) {
|
|
return ve.ui.MWLiveExtensionInspector.super.prototype.getSetupProcess.call( this, data )
|
|
.next( function () {
|
|
var element = this.getNewElement();
|
|
// Initialization
|
|
this.getFragment().getSurface().pushStaging();
|
|
|
|
if ( !this.selectedNode ) {
|
|
// Create a new node
|
|
// collapseToEnd returns a new fragment
|
|
this.fragment = this.getFragment().collapseToEnd().insertContent( [
|
|
element,
|
|
{ type: '/' + element.type }
|
|
] );
|
|
// Check if the node was inserted at a structural offset and
|
|
// wrapped in a paragraph
|
|
if ( this.getFragment().getSelection().getRange().getLength() === 4 ) {
|
|
this.fragment = this.getFragment().adjustLinearSelection( 1, -1 );
|
|
}
|
|
this.getFragment().select();
|
|
this.selectedNode = this.getFragment().getSelectedNode();
|
|
}
|
|
this.input.on( 'change', this.onChangeHandler );
|
|
this.generatedContentsError.connect( this, {
|
|
update: 'updateSize'
|
|
} );
|
|
this.selectedNode.connect( this, {
|
|
generatedContentsError: 'showGeneratedContentsError'
|
|
} );
|
|
}, this );
|
|
};
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
ve.ui.MWLiveExtensionInspector.prototype.getTeardownProcess = function ( data ) {
|
|
return ve.ui.MWLiveExtensionInspector.super.prototype.getTeardownProcess.call( this, data )
|
|
.first( function () {
|
|
this.input.off( 'change', this.onChangeHandler );
|
|
this.generatedContentsError.clear();
|
|
this.generatedContentsError.disconnect( this );
|
|
this.selectedNode.disconnect( this );
|
|
if ( data === undefined ) { // cancel
|
|
this.getFragment().getSurface().popStaging();
|
|
}
|
|
}, this );
|
|
};
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
ve.ui.MWLiveExtensionInspector.prototype.insertOrUpdateNode = function () {
|
|
// No need to call parent method as changes have already been made
|
|
// to the model in staging, just need to apply them.
|
|
this.updatePreview();
|
|
this.getFragment().getSurface().applyStaging();
|
|
// Force the selected node to re-render after staging has finished
|
|
this.selectedNode.emit( 'update', false );
|
|
};
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
ve.ui.MWLiveExtensionInspector.prototype.removeNode = function () {
|
|
this.getFragment().getSurface().popStaging();
|
|
|
|
// Parent method
|
|
ve.ui.MWLiveExtensionInspector.super.prototype.removeNode.call( this );
|
|
};
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
ve.ui.MWLiveExtensionInspector.prototype.onChange = function () {
|
|
// Parent method
|
|
ve.ui.MWLiveExtensionInspector.super.prototype.onChange.call( this );
|
|
|
|
this.updatePreviewDebounced();
|
|
};
|
|
|
|
/**
|
|
* Update the node rendering to reflect the current content in the inspector.
|
|
*/
|
|
ve.ui.MWLiveExtensionInspector.prototype.updatePreview = function () {
|
|
var mwData = ve.copy( this.selectedNode.getAttribute( 'mw' ) );
|
|
|
|
this.updateMwData( mwData );
|
|
|
|
this.hideGeneratedContentsError();
|
|
|
|
if ( this.visible ) {
|
|
this.getFragment().changeAttributes( { mw: mwData } );
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Show the error container and set the error label to contain the error.
|
|
*
|
|
* @param {jQuery} $element Element containing the error
|
|
*/
|
|
ve.ui.MWLiveExtensionInspector.prototype.showGeneratedContentsError = function ( $element ) {
|
|
this.generatedContentsError.show( this.formatGeneratedContentsError( $element ) );
|
|
};
|
|
|
|
/**
|
|
* Hide the error and collapse the error container.
|
|
*/
|
|
ve.ui.MWLiveExtensionInspector.prototype.hideGeneratedContentsError = function () {
|
|
this.generatedContentsError.clear();
|
|
};
|
|
|
|
/**
|
|
* Format the error.
|
|
*
|
|
* Default behaviour returns the error with no modification.
|
|
*
|
|
* @param {jQuery} $element Element containing the error
|
|
* @return {jQuery} $element Element containing the error
|
|
*/
|
|
ve.ui.MWLiveExtensionInspector.prototype.formatGeneratedContentsError = function ( $element ) {
|
|
return $element;
|
|
};
|