File: ve.ui.MWLiveExtensionInspector.js

package info (click to toggle)
mediawiki 1%3A1.43.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 417,464 kB
  • sloc: php: 1,062,949; javascript: 664,290; sql: 9,714; python: 5,458; xml: 3,489; sh: 1,131; makefile: 64
file content (170 lines) | stat: -rw-r--r-- 4,907 bytes parent folder | download | duplicates (2)
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;
};