1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
/*!
* VisualEditor UserInterface MWLiveExtensionInspector class.
*
* @copyright 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 ), 1000 );
};
/* 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( () => {
const 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'
} );
} );
};
/**
* @inheritdoc
*/
ve.ui.MWLiveExtensionInspector.prototype.getTeardownProcess = function ( data ) {
return ve.ui.MWLiveExtensionInspector.super.prototype.getTeardownProcess.call( this, data )
.first( () => {
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();
}
} );
};
/**
* @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 () {
if ( !this.selectedNode ) {
// Method is called debounced, so selectedNode may not still exist
return;
}
const 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;
};
|