mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-11-24 22:35:41 +00:00
Introduce Ace editor widget
The widget attempts to load the ext.codeEditor.ace.modes module and if it fails, will fall back to regular TextWidget behaviour. Bug: T49742 Change-Id: Ie483f6eba25e3732a396c18decc0e1844b806b23
This commit is contained in:
parent
15748bde2d
commit
60c1ee7d56
|
@ -965,6 +965,7 @@
|
|||
"modules/ve-mw/ui/ve.ui.MWExtensionWindow.js",
|
||||
"modules/ve-mw/ui/commands/ve.ui.MWWikitextWarningCommand.js",
|
||||
"modules/ve-mw/ui/datatransferhandlers/ve.ui.MWWikitextStringTransferHandler.js",
|
||||
"modules/ve-mw/ui/widgets/ve.ui.MWAceEditorWidget.js",
|
||||
"modules/ve-mw/ui/widgets/ve.ui.MWTargetWidget.js",
|
||||
"modules/ve-mw/ui/widgets/ve.ui.MWTocItemWidget.js",
|
||||
"modules/ve-mw/ui/widgets/ve.ui.MWTocWidget.js",
|
||||
|
@ -987,6 +988,7 @@
|
|||
"modules/ve-mw/ui/styles/dialogs/ve.ui.MWWelcomeDialog.css",
|
||||
"modules/ve-mw/ui/styles/dialogs/ve.ui.MWSaveDialog.css",
|
||||
"modules/ve-mw/ui/styles/tools/ve.ui.MWPopupTool.css",
|
||||
"modules/ve-mw/ui/styles/widgets/ve.ui.MWAceEditorWidget.css",
|
||||
"modules/ve-mw/ui/styles/widgets/ve.ui.MWTocWidget.css",
|
||||
"modules/ve-mw/ui/styles/tools/ve.ui.MWEducationPopupTool.css"
|
||||
],
|
||||
|
|
22
modules/ve-mw/ui/styles/widgets/ve.ui.MWAceEditorWidget.css
Normal file
22
modules/ve-mw/ui/styles/widgets/ve.ui.MWAceEditorWidget.css
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*!
|
||||
* VisualEditor MediaWiki UserInterface MWAceEditorWidget styles.
|
||||
*
|
||||
* @copyright 2011-2015 VisualEditor Team and others; see AUTHORS.txt
|
||||
* @license The MIT License (MIT); see LICENSE.txt
|
||||
*/
|
||||
|
||||
.ve-ui-mwAceEditorWidget .ace_editor {
|
||||
border: 1px solid #ccc;
|
||||
margin: 1px;
|
||||
font-family: monospace, Courier;
|
||||
font-size: inherit;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.ve-ui-mwAceEditorWidget .ace_focus {
|
||||
/* TODO: Move to mediawiki theme only */
|
||||
border-color: #347bff;
|
||||
/* HACK: Make border grow out as inset doesn't overlap absolute positioned children */
|
||||
border-width: 2px;
|
||||
margin: 0;
|
||||
}
|
|
@ -53,9 +53,9 @@ ve.ui.MWExtensionWindow.static.dir = null;
|
|||
ve.ui.MWExtensionWindow.prototype.initialize = function () {
|
||||
this.input = new ve.ui.WhitespacePreservingTextInputWidget( {
|
||||
limit: 1,
|
||||
multiline: true
|
||||
multiline: true,
|
||||
classes: [ 've-ui-mwExtensionWindow-input' ]
|
||||
} );
|
||||
this.input.$element.addClass( 've-ui-mwExtensionWindow-input' );
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
170
modules/ve-mw/ui/widgets/ve.ui.MWAceEditorWidget.js
Normal file
170
modules/ve-mw/ui/widgets/ve.ui.MWAceEditorWidget.js
Normal file
|
@ -0,0 +1,170 @@
|
|||
/*!
|
||||
* VisualEditor UserInterface MWAceEditorWidget class.
|
||||
*
|
||||
* @copyright 2011-2015 VisualEditor Team and others; see http://ve.mit-license.org
|
||||
*/
|
||||
|
||||
/* global ace, require */
|
||||
|
||||
/**
|
||||
* Text input widget which hides but preserves leading and trailing whitespace
|
||||
*
|
||||
* @class
|
||||
* @extends ve.ui.WhitespacePreservingTextInputWidget
|
||||
*
|
||||
* @constructor
|
||||
* @param {Object} [config] Configuration options
|
||||
*/
|
||||
ve.ui.MWAceEditorWidget = function VeUiMWAceEditorWidget( config ) {
|
||||
// Configuration
|
||||
config = config || {};
|
||||
|
||||
this.$ace = $( '<div dir="ltr">' );
|
||||
this.editor = null;
|
||||
// Initialise to a rejected promise for the setValue call in the parent constructor
|
||||
this.loadingPromise = $.Deferred().reject().promise();
|
||||
this.styleHeight = null;
|
||||
|
||||
// Parent constructor
|
||||
ve.ui.MWAceEditorWidget.super.call( this, config );
|
||||
|
||||
// Clear the fake loading promise and setup properly
|
||||
this.loadingPromise = null;
|
||||
this.setup();
|
||||
|
||||
this.$element
|
||||
.append( this.$ace )
|
||||
.addClass( 've-ui-mwAceEditorWidget' );
|
||||
};
|
||||
|
||||
/* Inheritance */
|
||||
|
||||
OO.inheritClass( ve.ui.MWAceEditorWidget, ve.ui.WhitespacePreservingTextInputWidget );
|
||||
|
||||
/* Events */
|
||||
|
||||
/**
|
||||
* The editor has resized
|
||||
* @event resize
|
||||
*/
|
||||
|
||||
/* Methods */
|
||||
|
||||
/**
|
||||
* Setup the Ace editor instance
|
||||
*/
|
||||
ve.ui.MWAceEditorWidget.prototype.setup = function () {
|
||||
if ( !this.loadingPromise ) {
|
||||
this.loadingPromise = mw.loader.moduleRegistry.hasOwnProperty( 'ext.codeEditor.ace.modes' ) ?
|
||||
mw.loader.using( 'ext.codeEditor.ace.modes' ).then( this.setupEditor.bind( this ) ) :
|
||||
$.Deferred().reject().promise();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Destroy the Ace editor instance
|
||||
*/
|
||||
ve.ui.MWAceEditorWidget.prototype.teardown = function () {
|
||||
var widget = this;
|
||||
this.loadingPromise.done( function () {
|
||||
widget.$input.removeClass( 'oo-ui-element-hidden' );
|
||||
widget.editor.destroy();
|
||||
widget.editor = null;
|
||||
} ).always( function () {
|
||||
widget.loadingPromise = null;
|
||||
} );
|
||||
};
|
||||
|
||||
/**
|
||||
* Setup the Ace editor
|
||||
*/
|
||||
ve.ui.MWAceEditorWidget.prototype.setupEditor = function () {
|
||||
this.$input.addClass( 'oo-ui-element-hidden' );
|
||||
this.editor = ace.edit( this.$ace[ 0 ] );
|
||||
this.editor.setOptions( {
|
||||
minLines: this.minRows || 3,
|
||||
maxLines: this.autosize ? this.maxRows : this.minRows || 3
|
||||
} );
|
||||
this.editor.getSession().on( 'change', this.onEditorChange.bind( this ) );
|
||||
this.editor.renderer.on( 'resize', this.emit.bind( this, 'resize' ) );
|
||||
this.editor.resize();
|
||||
};
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
ve.ui.MWAceEditorWidget.prototype.setValue = function ( value ) {
|
||||
var widget = this;
|
||||
this.loadingPromise.done( function () {
|
||||
widget.editor.setValue( value );
|
||||
widget.editor.selection.moveTo( 0, 0 );
|
||||
} ).fail( function () {
|
||||
ve.ui.MWAceEditorWidget.super.prototype.setValue.call( widget, value );
|
||||
} );
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle change events from the Ace editor
|
||||
*/
|
||||
ve.ui.MWAceEditorWidget.prototype.onEditorChange = function () {
|
||||
// Call setValue on the parent to keep the value property in sync with the editor
|
||||
ve.ui.MWAceEditorWidget.super.prototype.setValue.call( this, this.editor.getValue() );
|
||||
};
|
||||
|
||||
/**
|
||||
* Toggle the visibility of line numbers
|
||||
*
|
||||
* @param {boolean} visible Visible
|
||||
*/
|
||||
ve.ui.MWAceEditorWidget.prototype.toggleLineNumbers = function ( visible ) {
|
||||
var widget = this;
|
||||
this.loadingPromise.done( function () {
|
||||
widget.editor.renderer.setShowGutter( visible );
|
||||
} );
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the language mode of the editor (programming language)
|
||||
*
|
||||
* @param {string} lang Language
|
||||
*/
|
||||
ve.ui.MWAceEditorWidget.prototype.setLanguage = function ( lang ) {
|
||||
var widget = this;
|
||||
this.loadingPromise.done( function () {
|
||||
widget.editor.getSession().setMode( 'ace/mode/' + ( require( 'ace/mode/' + lang ) ? lang : 'text' ) );
|
||||
} );
|
||||
};
|
||||
|
||||
/**
|
||||
* Focus the editor
|
||||
*/
|
||||
ve.ui.MWAceEditorWidget.prototype.focus = function () {
|
||||
var widget = this;
|
||||
this.loadingPromise.done( function () {
|
||||
widget.editor.focus();
|
||||
} ).fail( function () {
|
||||
ve.ui.MWAceEditorWidget.super.prototype.focus.call( widget );
|
||||
} );
|
||||
};
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
* TODO Move this upstream to OOUI
|
||||
*/
|
||||
ve.ui.MWAceEditorWidget.prototype.adjustSize = function () {
|
||||
var styleHeight,
|
||||
widget = this;
|
||||
|
||||
// Parent method
|
||||
ve.ui.MWAceEditorWidget.super.prototype.adjustSize.call( this );
|
||||
|
||||
// Implement resize events for plain TextWidget
|
||||
this.loadingPromise.fail( function () {
|
||||
styleHeight = widget.$input[ 0 ].style.height;
|
||||
|
||||
if ( styleHeight !== widget.styleHeight ) {
|
||||
widget.styleHeight = styleHeight;
|
||||
widget.emit( 'resize' );
|
||||
}
|
||||
} );
|
||||
};
|
Loading…
Reference in a new issue