mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-11-15 18:39:52 +00:00
cf7f2b141d
Let's experiment with this via our local Gruntfile. If it works fine we can install it in Jenkins (similar to node-csslint). Verify through $ npm install && npm test; Fixed all outstanding violations. Also: * Added syntaxhighight to ignore. * Added imetests (which contain unformatted JSON) to ignore. * In ve.dm.ModelRegistry#matchTypeRegExps, removed redundant !! cast from the [+!!withFunc] statement which was hitting a bug in node-jscs. All callers to this local private function pass a literal boolean true/false so no need to cast it. * Removed "/* key .. , value */" from ve.setProp, though this wasn't caught by node-jscs, found it when searching for " , ". * Made npm.devDependencies fixed instead of using tilde-ranges. This too often leads to strange bugs or sudden changes. Fixed them at the version they were currently ranging to. Bug: 54218 Change-Id: Ib2630806f3946874c8b01e58cf171df83a28da29
233 lines
5.7 KiB
JavaScript
233 lines
5.7 KiB
JavaScript
/*!
|
||
* VisualEditor UserInterface SpecialCharacterInspector class.
|
||
*
|
||
* @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
|
||
* @license The MIT License (MIT); see LICENSE.txt
|
||
*/
|
||
|
||
/**
|
||
* Special character inspector.
|
||
*
|
||
* @class
|
||
* @extends ve.ui.Inspector
|
||
*
|
||
* @constructor
|
||
* @param {ve.ui.WindowSet} windowSet Window set this inspector is part of
|
||
* @param {Object} [config] Configuration options
|
||
*/
|
||
ve.ui.SpecialCharacterInspector = function VeUiSpecialCharacterInspector( windowSet, config ) {
|
||
|
||
// Parent constructor
|
||
ve.ui.Inspector.call( this, windowSet, config );
|
||
|
||
this.characters = null;
|
||
this.$buttonDomList = null;
|
||
this.initialSelection = null;
|
||
this.addedChar = null;
|
||
this.categories = null;
|
||
|
||
// Fallback character list in case no list is found anywhere
|
||
this.minimalCharacterList =
|
||
{
|
||
'accents': {
|
||
'à': 'à',
|
||
'á': 'á',
|
||
'â': 'â',
|
||
'ä': 'ä',
|
||
'ç': 'ç',
|
||
'è': 'è',
|
||
'é': 'é',
|
||
'ê': 'ê',
|
||
'ë': 'ë',
|
||
'ì': 'ì',
|
||
'í': 'í',
|
||
'î': 'î',
|
||
'ï': 'ï',
|
||
'ò': 'ò',
|
||
'ó': 'ó',
|
||
'ô': 'ô',
|
||
'ö': 'ö',
|
||
'ø': 'ø',
|
||
'ù': 'ù',
|
||
'ú': 'ú',
|
||
'û': 'û',
|
||
'ü': 'ü'
|
||
},
|
||
'symbols': {
|
||
'−': '−',
|
||
'—': '—',
|
||
'°': '°',
|
||
'″': '″',
|
||
'′': '′',
|
||
'←': '←',
|
||
'→': '→',
|
||
'·': '·',
|
||
'§': '§'
|
||
}
|
||
};
|
||
};
|
||
|
||
/* Inheritance */
|
||
|
||
OO.inheritClass( ve.ui.SpecialCharacterInspector, ve.ui.Inspector );
|
||
|
||
/* Static properties */
|
||
|
||
ve.ui.SpecialCharacterInspector.static.name = 'specialcharacter';
|
||
|
||
ve.ui.SpecialCharacterInspector.static.icon = 'specialcharacter';
|
||
|
||
ve.ui.SpecialCharacterInspector.static.titleMessage = 'visualeditor-specialcharacterinspector-title';
|
||
|
||
ve.ui.SpecialCharacterInspector.static.removeable = false;
|
||
|
||
/* Methods */
|
||
|
||
/**
|
||
* Handle frame ready events.
|
||
*
|
||
* @method
|
||
*/
|
||
ve.ui.SpecialCharacterInspector.prototype.initialize = function () {
|
||
// Parent method
|
||
ve.ui.Inspector.prototype.initialize.call( this );
|
||
|
||
this.$spinner = this.$( '<div>' ).addClass( 've-specialchar-spinner' );
|
||
this.$form.append( this.$spinner );
|
||
};
|
||
|
||
/**
|
||
* Handle the inspector being setup.
|
||
*
|
||
* @method
|
||
* @param {Object} [data] Inspector opening data
|
||
*/
|
||
ve.ui.SpecialCharacterInspector.prototype.setup = function ( data ) {
|
||
// Parent method
|
||
ve.ui.Inspector.prototype.setup.call( this, data );
|
||
|
||
// Preserve initial selection so we can collapse cursor position
|
||
// after we're done adding
|
||
this.initialSelection = this.surface.getModel().getSelection();
|
||
|
||
this.getCharList().done( ve.bind( function () {
|
||
// Now we can rebuild our button list
|
||
// We only want to rebuild the list if we don't already have it
|
||
if ( !this.$buttonDomList ) {
|
||
// Start with the spinner showing
|
||
this.$spinner.show();
|
||
this.buildButtonList().done( ve.bind( function () {
|
||
// Append the new button list
|
||
this.$form.append( this.$buttonDomList );
|
||
// Done, hide the spinner
|
||
this.$spinner.hide();
|
||
|
||
}, this ) );
|
||
}
|
||
}, this ) );
|
||
|
||
};
|
||
|
||
/**
|
||
* Get the special character list object
|
||
* This can also be an AJAX call with default fallback
|
||
*
|
||
* @returns {jQuery.Promise}
|
||
*/
|
||
ve.ui.SpecialCharacterInspector.prototype.getCharList = function () {
|
||
var charslist, charobj,
|
||
deferred = $.Deferred();
|
||
|
||
// Don't request the character list again if we already have it
|
||
if ( !this.characters ) {
|
||
|
||
// Get the character list
|
||
charslist = ve.msg( 'visualeditor-specialcharinspector-characterlist-insert' );
|
||
try {
|
||
charobj = $.parseJSON( charslist );
|
||
} catch ( err ) {
|
||
// There was no character list found, or the character list message is
|
||
// invalid json string. Force a fallback to the minimal character list
|
||
charobj = this.minimalCharacterList;
|
||
ve.log( 've.ui.SpecialCharacterInspector: Could not parse the Special Character list; using default.');
|
||
ve.log( err.message );
|
||
} finally {
|
||
this.characters = charobj;
|
||
deferred.resolve();
|
||
}
|
||
}
|
||
|
||
return deferred.promise();
|
||
};
|
||
|
||
/**
|
||
* Builds the button DOM list based on the character list
|
||
*
|
||
* @returns {jQuery.Promise}
|
||
*/
|
||
ve.ui.SpecialCharacterInspector.prototype.buildButtonList = function () {
|
||
var category, categoryButtons,
|
||
deferred = $.Deferred(),
|
||
$widgetOutput = this.$( '<div>' ).addClass( 've-specialchar-list' );
|
||
|
||
if ( !this.characters ) {
|
||
deferred.reject();
|
||
}
|
||
|
||
for ( category in this.characters ) {
|
||
categoryButtons = new ve.ui.GroupButtonWidget( {
|
||
'groupName': category,
|
||
'group': this.characters[category],
|
||
'aggregations': { 'click': 'click' }
|
||
} );
|
||
|
||
categoryButtons.connect( this, { 'click': 'onSpecialCharAdd' } );
|
||
|
||
$widgetOutput
|
||
.append( this.$( '<h2>').text( category ) )
|
||
.append( categoryButtons.$element );
|
||
}
|
||
|
||
this.$buttonDomList = $widgetOutput;
|
||
deferred.resolve();
|
||
return deferred.promise();
|
||
};
|
||
|
||
/**
|
||
* Handle the click event on the button groups. The value of the selection will be inserted
|
||
* into the text
|
||
*
|
||
* @param {OO.ui.PushButtonWidget} button The value attached to the clicked button
|
||
*/
|
||
ve.ui.SpecialCharacterInspector.prototype.onSpecialCharAdd = function ( button ) {
|
||
var fragment = this.surface.getModel().getFragment( null, true ),
|
||
value = button.returnValue;
|
||
|
||
// Insert the character
|
||
if ( value !== undefined ) {
|
||
// get the insertion value (it could be in any category)
|
||
this.addedChar = value;
|
||
fragment.insertContent( value, false );
|
||
}
|
||
};
|
||
|
||
/**
|
||
* @inheritdoc
|
||
*/
|
||
ve.ui.SpecialCharacterInspector.prototype.teardown = function ( data ) {
|
||
var selection;
|
||
// Collapse selection after the inserted content
|
||
if ( this.addedChar ) {
|
||
selection = new ve.Range( this.initialSelection.start + this.addedChar.length );
|
||
this.surface.execute( 'content', 'select', selection );
|
||
}
|
||
// reset
|
||
this.addedChar = null;
|
||
// Parent method
|
||
ve.ui.Inspector.prototype.teardown.call( this, data );
|
||
};
|
||
|
||
/* Registration */
|
||
|
||
ve.ui.inspectorFactory.register( ve.ui.SpecialCharacterInspector );
|