Support for editing captions of block images

Bug: 38129
Change-Id: I02207e78f5c28eaccd9bc97a48baa78280192255
This commit is contained in:
Inez Korczyński 2013-06-18 15:58:10 -07:00 committed by Roan Kattouw
parent fedcf454a0
commit a886952563
7 changed files with 233 additions and 1 deletions

View file

@ -33,6 +33,7 @@ $messages['en'] = array(
'visualeditor-dialog-media-insert-button' => 'Insert media',
'visualeditor-dialog-media-insert-title' => 'Insert media',
'visualeditor-dialog-media-title' => 'Media settings',
'visualeditor-dialog-media-content-section' => 'Caption content',
'visualeditor-dialog-meta-categories-data-label' => 'Categories',
'visualeditor-dialog-meta-categories-category' => 'Category',
'visualeditor-dialog-meta-categories-defaultsort-label' => 'Sort this page by default as',
@ -198,6 +199,7 @@ See also:
{{Identical|Insert media}}',
'visualeditor-dialog-media-insert-title' => 'Media insert dialog title text.
{{Identical|Insert media}}',
'visualeditor-dialog-media-content-section' => 'Label for the image content sub-section',
'visualeditor-dialog-media-title' => 'Title for the editing dialog to set how a media item is displayed on the page',
'visualeditor-dialog-meta-categories-data-label' => 'Label for the categories sub-section.
{{Identical|Category}}',

View file

@ -437,6 +437,7 @@ $wgResourceModules += array(
've/ui/dialogs/ve.ui.PagedDialog.js',
've/ui/dialogs/ve.ui.MWMetaDialog.js',
've/ui/dialogs/ve.ui.MWMediaInsertDialog.js',
've/ui/dialogs/ve.ui.MWMediaEditDialog.js',
've/ui/dialogs/ve.ui.MWTransclusionDialog.js',
've/ui/tools/ve.ui.ButtonTool.js',
@ -453,6 +454,7 @@ $wgResourceModules += array(
've/ui/tools/buttons/ve.ui.LinkButtonTool.js',
've/ui/tools/buttons/ve.ui.MWLinkButtonTool.js',
've/ui/tools/buttons/ve.ui.MWMediaInsertButtonTool.js',
've/ui/tools/buttons/ve.ui.MWMediaEditButtonTool.js',
've/ui/tools/buttons/ve.ui.BulletButtonTool.js',
've/ui/tools/buttons/ve.ui.NumberButtonTool.js',
've/ui/tools/buttons/ve.ui.IndentButtonTool.js',
@ -618,6 +620,7 @@ $wgResourceModules += array(
'visualeditor-dialog-reference-options-section',
'visualeditor-dialog-reference-title',
'visualeditor-dialogbutton-reference-tooltip',
'visualeditor-dialog-media-content-section'
),
),
'ext.visualEditor.icons-raster' => $wgVisualEditorResourceTemplate + array(

View file

@ -152,6 +152,19 @@ ve.dm.MWBlockImageNode.static.toDomElements = function ( data, doc, converter )
return [ figure ];
};
/* Methods */
/**
* Get the caption node of the image.
*
* @method
* @return {ve.dm.MWImageCaptionNode|null} Caption node, if present
*/
ve.dm.MWBlockImageNode.prototype.getCaptionNode = function() {
var node = this.children[0];
return node instanceof ve.dm.MWImageCaptionNode ? node : null;
};
/* Registration */
ve.dm.modelRegistry.register( ve.dm.MWBlockImageNode );

View file

@ -0,0 +1,157 @@
/*!
* VisualEditor user interface MWMediaEditDialog class.
*
* @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
/**
* Document dialog.
*
* @class
* @extends ve.ui.Dialog
*
* @constructor
* @param {ve.ui.Surface} surface
* @param {Object} [config] Config options
*/
ve.ui.MWMediaEditDialog = function VeUiMWMediaEditDialog( surface, config ) {
// Parent constructor
ve.ui.Dialog.call( this, surface, config );
// Properties
this.captionNode = null;
};
/* Inheritance */
ve.inheritClass( ve.ui.MWMediaEditDialog, ve.ui.Dialog );
/* Static Properties */
ve.ui.MWMediaEditDialog.static.titleMessage = 'visualeditor-dialog-media-title';
ve.ui.MWMediaEditDialog.static.icon = 'picture';
ve.ui.MWMediaEditDialog.static.modelClasses = [ ve.dm.MWBlockImageNode ];
ve.ui.MWMediaEditDialog.static.toolbarTools = [
{ 'items': ['undo', 'redo'] },
{ 'items': ['bold', 'italic', 'mwLink', 'clear'] }
];
ve.ui.MWMediaEditDialog.static.surfaceCommands = [
'bold', 'italic', 'mwLink', 'undo', 'redo'
];
/* Static Initialization */
ve.ui.MWMediaEditDialog.static.addLocalStylesheets( [
've.ce.Node.css',
've.ce.Surface.css',
've.ui.Surface.css',
've.ui.Context.css',
've.ui.Tool.css',
've.ui.Toolbar.css'
] );
/* Methods */
/**
* Handle frame ready events.
*
* @method
*/
ve.ui.MWMediaEditDialog.prototype.initialize = function () {
// Call parent method
ve.ui.Dialog.prototype.initialize.call( this );
// Properties
this.contentFieldset = new ve.ui.FieldsetLayout( {
'$$': this.frame.$$,
'label': ve.msg( 'visualeditor-dialog-media-content-section' ),
'icon': 'parameter'
} );
// Initialization
this.$body.addClass( 've-ui-mwMediaEditDialog-body' );
this.$body.append( this.contentFieldset.$ );
};
/**
* Handle frame ready events.
*
* @method
*/
ve.ui.MWMediaEditDialog.prototype.onOpen = function () {
var data, doc = this.surface.getModel().getDocument();
// Parent method
ve.ui.Dialog.prototype.onOpen.call( this );
// Get caption content
this.captionNode = this.surface.getView().getFocusedNode().getModel().getCaptionNode();
if ( this.captionNode && this.captionNode.getLength() > 0 ) {
data = doc.getData( this.captionNode.getRange(), true );
} else {
data = [
{ 'type': 'paragraph', 'internal': { 'generated': 'wrapper' } },
{ 'type': '/paragraph' }
];
}
this.captionSurface = new ve.ui.Surface(
new ve.dm.ElementLinearData( doc.getStore(), data ), { '$$': this.frame.$$ }
);
this.captionToolbar = new ve.ui.Toolbar( this.captionSurface, { '$$': this.frame.$$ } );
this.captionToolbar.$.addClass( 've-ui-mwMediaEditDialog-toolbar' );
this.contentFieldset.$.append( this.captionToolbar.$, this.captionSurface.$ );
this.captionToolbar.addTools( this.constructor.static.toolbarTools );
this.captionSurface.addCommands( this.constructor.static.surfaceCommands );
this.captionSurface.initialize();
this.captionSurface.view.documentView.documentNode.$.focus();
};
/**
* Handle frame ready events.
*
* @method
* @param {string} action Action that caused the window to be closed
*/
ve.ui.MWMediaEditDialog.prototype.onClose = function ( action ) {
var data, doc, surfaceModel = this.surface.getModel();
// Parent method
ve.ui.Dialog.prototype.onClose.call( this );
if ( action === 'apply' ) {
data = this.captionSurface.getModel().getDocument().getData();
doc = surfaceModel.getDocument();
if ( this.captionNode ) {
// Replace the contents of the caption
surfaceModel.getFragment( this.captionNode.getRange(), true ).insertContent( data );
} else {
// Insert a new caption at the beginning of the image node
surfaceModel.getFragment()
.adjustRange( 1 )
.collapseRangeToStart()
.insertContent(
[ { 'type': 'mwImageCaption' } ]
.concat( data )
.concat( [ { 'type': '/mwImageCaption' } ] )
);
}
}
// Cleanup
this.captionNode = null;
this.captionSurface.destroy();
this.captionToolbar.destroy();
};
/* Registration */
ve.ui.dialogFactory.register( 'mwMediaEdit', ve.ui.MWMediaEditDialog );
ve.ui.viewRegistry.register( 'mwMediaEdit', ve.ui.MWMediaEditDialog );

View file

@ -237,3 +237,22 @@
left: 0;
right: 0;
}
/* ve.ui.MWMediaEditDialog */
.ve-ui-mwMediaEditDialog-body {
padding: 2em;
overflow-y: auto;
}
.ve-ui-mwMediaEditDialog-toolbar {
font-size: 1.25em;
}
.ve-ui-mwMediaEditDialog-toolbar .ve-ui-toolbar-bar {
border: solid 1px #ddd;
border-radius: 0.25em;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
border-bottom-width: 0;
}

View file

@ -0,0 +1,38 @@
/*!
* VisualEditor UserInterface MWMediaEditButtonTool class.
*
* @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
/**
* MediaEdit button tool.
*
* @class
* @extends ve.ui.DialogButtonTool
* @constructor
* @param {ve.ui.Toolbar} toolbar
* @param {Object} [config] Config options
*/
ve.ui.MWMediaEditButtonTool = function VeUiMWMediaEditButtonTool( toolbar, config ) {
// Parent constructor
ve.ui.DialogButtonTool.call( this, toolbar, config );
};
/* Inheritance */
ve.inheritClass( ve.ui.MWMediaEditButtonTool, ve.ui.DialogButtonTool );
/* Static Properties */
ve.ui.MWMediaEditButtonTool.static.name = 'mwMediaEdit';
ve.ui.MWMediaEditButtonTool.static.icon = 'picture';
ve.ui.MWMediaEditButtonTool.static.titleMessage = 'visualeditor-dialogbutton-media-tooltip';
ve.ui.MWMediaEditButtonTool.static.dialog = 'mwMediaEdit';
/* Registration */
ve.ui.toolFactory.register( 'mwMediaEdit', ve.ui.MWMediaEditButtonTool );

View file

@ -209,7 +209,7 @@ ve.ui.Context.prototype.update = function () {
} else {
// No inspector is open, or the selection has changed, show a menu of available inspectors
views = ve.ui.viewRegistry.getViewsForAnnotations( fragment.getAnnotations() );
nodes = fragment.getLeafNodes();
nodes = fragment.getCoveredNodes();
for ( i = 0; i < nodes.length; i++ ) {
if ( nodes[i].range && nodes[i].range.isCollapsed() ) {
nodes.splice( i, 1 );