Mooeypoo has uploaded a new change for review. https://gerrit.wikimedia.org/r/103193
Change subject: [WIP] Changing image size in MWMediaEditDialog ...................................................................... [WIP] Changing image size in MWMediaEditDialog Adding the ability to edit image size in the media edit dialog. Size is kept in aspect ratio at all times. If value is invalid the user will see visual cue through error class, and the size will not be updated. Some remaining issues: * Initial size: Figure out how to preserve the initial size of the image from the beginning of the session, so the user can cancel their edit if needed. * Original size: Figure out if it is possible to get the original size of the image so we can test that the manual size isn't bigger than the original image size. Change-Id: I2946fb21c46ce05583b219f665ef68928188899e --- M VisualEditor.i18n.php M VisualEditor.php M modules/ve-mw/ce/nodes/ve.ce.MWBlockImageNode.js M modules/ve-mw/ui/dialogs/ve.ui.MWMediaEditDialog.js M modules/ve-mw/ui/styles/ve.ui.MWDialog.css 5 files changed, 201 insertions(+), 5 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor refs/changes/93/103193/1 diff --git a/VisualEditor.i18n.php b/VisualEditor.i18n.php index 8e89840..2e0137f 100644 --- a/VisualEditor.i18n.php +++ b/VisualEditor.i18n.php @@ -135,6 +135,10 @@ 'visualeditor-dialog-beta-welcome-content' => 'This is our new, easier way to edit. It\'s still in beta, which means you might find parts of the page you can\'t edit, or encounter issues that need to be fixed. We encourage you to review your changes, and we welcome reports about any issues you might encounter in using VisualEditor (click the "{{int:visualeditor-help-tool}}" button to submit feedback). You can keep using the wikitext editor by clicking the "$1" tab instead – unsaved changes will be lost.', 'visualeditor-dialog-beta-welcome-title' => '{{GENDER:$1|Welcome}} to VisualEditor', 'visualeditor-dialog-media-content-section' => 'Caption', + 'visualeditor-dialog-media-size-section' => 'Image size', + 'visualeditor-dialog-media-size-width' => 'Width', + 'visualeditor-dialog-media-size-height' => 'Height', + 'visualeditor-dialog-media-button-size-default' => 'Set to original size', 'visualeditor-dialog-media-insert-button' => 'Insert media', 'visualeditor-dialog-media-insert-title' => 'Insert media', 'visualeditor-dialog-media-title' => 'Media settings', @@ -456,6 +460,10 @@ * $1 - username or empty string, for GENDER support', 'visualeditor-dialog-media-content-section' => 'Label for the image content sub-section. {{Identical|Caption}}', + 'visualeditor-dialog-media-size-section' => 'Label for the image size sub-section.', + 'visualeditor-dialog-media-size-width' => 'Label for the image width.', + 'visualeditor-dialog-media-size-height' => 'Label for the image height.', + 'visualeditor-dialog-media-button-size-default' => 'Label for the button to reset image size to original values.', 'visualeditor-dialog-media-insert-button' => 'Used as label for the button. {{Identical|Insert media}}', 'visualeditor-dialog-media-insert-title' => 'Media insert dialog title text. diff --git a/VisualEditor.php b/VisualEditor.php index ca2a946..9b1a0b1 100644 --- a/VisualEditor.php +++ b/VisualEditor.php @@ -616,6 +616,10 @@ 'visualeditor-dialog-beta-welcome-content', 'visualeditor-dialog-beta-welcome-title', 'visualeditor-dialog-media-content-section', + 'visualeditor-dialog-media-size-section', + 'visualeditor-dialog-media-size-width', + 'visualeditor-dialog-media-size-height', + 'visualeditor-dialog-media-button-size-default', 'visualeditor-dialog-media-insert-button', 'visualeditor-dialog-media-insert-title', 'visualeditor-dialog-media-title', diff --git a/modules/ve-mw/ce/nodes/ve.ce.MWBlockImageNode.js b/modules/ve-mw/ce/nodes/ve.ce.MWBlockImageNode.js index 78d424e..81ca27a 100644 --- a/modules/ve-mw/ce/nodes/ve.ce.MWBlockImageNode.js +++ b/modules/ve-mw/ce/nodes/ve.ce.MWBlockImageNode.js @@ -253,8 +253,16 @@ this.$image.attr( 'src', this.getResolvedAttribute( 'src' ) ); break; case 'width': + this.updateSize( { + 'width': to, + 'height': this.model.getAttribute( 'height' ) + } ); + break; case 'height': - this.updateSize(); + this.updateSize( { + 'width': this.model.getAttribute( 'width' ), + 'height': to + } ); break; case 'type': this.$figure diff --git a/modules/ve-mw/ui/dialogs/ve.ui.MWMediaEditDialog.js b/modules/ve-mw/ui/dialogs/ve.ui.MWMediaEditDialog.js index 7dc7a12..7ca2ffe 100644 --- a/modules/ve-mw/ui/dialogs/ve.ui.MWMediaEditDialog.js +++ b/modules/ve-mw/ui/dialogs/ve.ui.MWMediaEditDialog.js @@ -89,8 +89,13 @@ * @inheritdoc */ ve.ui.MWMediaEditDialog.prototype.initialize = function () { + var widthDiv, heightDiv; // Parent method ve.ui.MWDialog.prototype.initialize.call( this ); + + this.hasError = false; + this.sizeLabel = {}; + this.sizeInput = {}; // Properties this.editPanel = new OO.ui.PanelLayout( { @@ -103,6 +108,54 @@ 'label': ve.msg( 'visualeditor-dialog-media-content-section' ), 'icon': 'parameter' } ); + + // Size + this.sizeFieldset = new OO.ui.FieldsetLayout( { + '$': this.$, + 'label': ve.msg( 'visualeditor-dialog-media-size-section' ), + 'icon': 'parameter' + } ); + + widthDiv = $( '<div>' ); + heightDiv = $( '<div>' ); + + this.sizeInput.width = new OO.ui.TextInputWidget( { + '$': this.$ + } ); + this.sizeInput.height = new OO.ui.TextInputWidget( { + '$': this.$ + } ); + + this.sizeDefaultButton = new OO.ui.PushButtonWidget( { + '$': this.$, + 'label': ve.msg( 'visualeditor-dialog-media-button-size-default' ) + } ); + + // Set up id's so we can bind the labels to the input + this.sizeInput.width.$element.prop( 'id', 'visualeditor-mediadialog-size-width' ); + this.sizeInput.height.$element.prop( 'id', 'visualeditor-mediadialog-size-height' ); + + // Labels + this.sizeLabel.width = $( '<label>' ) + .text( ve.msg( 'visualeditor-dialog-media-size-width' ) ) + .attr( 'for', 'visualeditor-mediadialog-size-width' ); + this.sizeLabel.height = $( '<label>' ) + .text( ve.msg( 'visualeditor-dialog-media-size-height' ) ) + .attr( 'for', 'visualeditor-mediadialog-size-height' ); + + widthDiv + .append( this.sizeLabel.width ) + .append( this.sizeInput.width.$element ); + heightDiv + .append( this.sizeLabel.height ) + .append( this.sizeInput.height.$element ); + + // Build sizeFieldset + this.sizeFieldset.$element + .append( widthDiv ) + .append( heightDiv ) + .append( this.sizeDefaultButton.$element ); + this.applyButton = new OO.ui.PushButtonWidget( { '$': this.$, 'label': ve.msg( 'visualeditor-dialog-action-apply' ), @@ -111,21 +164,114 @@ // Events this.applyButton.connect( this, { 'click': [ 'close', { 'action': 'apply' } ] } ); + this.sizeDefaultButton.connect( this, { 'click': 'onSetDefaultSize' } ); + + this.sizeInput.width.$input.on( 'keyup', { 'dir': 'width' }, OO.ui.bind( this.onSizeKeydown, this ) ); + this.sizeInput.height.$input.on( 'keyup', { 'dir': 'height' }, OO.ui.bind( this.onSizeKeydown, this ) ); // Initialization - this.editPanel.$element.append( this.captionFieldset.$element ); + this.editPanel.$element.append( [ + this.captionFieldset.$element, + this.sizeFieldset.$element + ] ); + this.$body.append( this.editPanel.$element ); this.$foot.append( this.applyButton.$element ); +}; + +/** + * Set the values of 'height' and 'width' inputs to the original size + * of the image before it was edited. + * + * @param {jQuery.event} e Click event parameters + */ +ve.ui.MWMediaEditDialog.prototype.onSetDefaultSize = function ( e ) { + this.sizeInput.width.setValue( this.originalSize.width ); + this.sizeInput.height.setValue( this.originalSize.height ); + this.validateSize(); +}; + +/** + * Handle change in width or height values to make sure they match each + * other based on the aspect ratio. + * + * @param {jQuery.event} e Keyup event parameters + */ +ve.ui.MWMediaEditDialog.prototype.onSizeKeydown = function ( e ) { + var tval, + height = this.sizeInput.height.$input.val(), + width = this.sizeInput.width.$input.val(), + curr = e.data.dir; + + this.hasError = false; + + // Make sure aspect ratio is preserved + if ( curr === 'height' ) { + // Calculate width to fit aspect ratio + tval = Math.round( ( height / this.originalSize.height ) * this.originalSize.width ); + this.sizeInput.width.setValue( tval ); + } else { + // Calculate height to fit aspect ratio + tval = Math.round( ( width / this.originalSize.width ) * this.originalSize.height ); + this.sizeInput.height.setValue( tval ); + } + + this.validateSize(); +}; + +/** + * Validate that the size/height values make sense. Otherwise, + * attach an error class to the relevant inputs. + */ +ve.ui.MWMediaEditDialog.prototype.validateSize = function () { + var height = this.sizeInput.height.$input.val(), + width = this.sizeInput.width.$input.val(); + + this.hasError = false; + + // Verify size is numerical + this.showError( + this.sizeInput.height.$element, + !( $.isNumeric( height ) ) ); + + this.showError( + this.sizeInput.width.$element, + !( $.isNumeric( width ) ) ); + + // Verify size makes sense + this.showError( + this.sizeInput.height.$element, + ( height <= 0 ) ); + + this.showError( + this.sizeInput.width.$element, + ( width <= 0 ) ); + +}; + +/** + * Set or unset an error class for the element + * @param {jQuery} el The relevant element + * @param {Boolean} isErr Whether the element is erroneous or not + */ +ve.ui.MWMediaEditDialog.prototype.showError = function ( el, isErr ) { + if ( isErr ) { + el.addClass( 've-ui-mwMediaEditDialog-size-error' ); + this.hasError = true; + } else { + el.removeClass( 've-ui-mwMediaEditDialog-size-error' ); + } }; /** * @inheritdoc */ ve.ui.MWMediaEditDialog.prototype.setup = function ( data ) { + var attrs, newDoc, + doc = this.surface.getModel().getDocument(); + // Parent method ve.ui.MWDialog.prototype.setup.call( this, data ); - - var newDoc, doc = this.surface.getModel().getDocument(); // Properties this.mediaNode = this.surface.getView().getFocusedNode().getModel(); @@ -150,6 +296,16 @@ } ); + // Save original size for later calculations + attrs = this.mediaNode.getAttributes(); + this.originalSize = { + height: attrs.height, + width: attrs.width + }; + // Set initial size in inputs + this.sizeInput.width.setValue( attrs.width ); + this.sizeInput.height.setValue( attrs.height ); + // Initialization this.captionFieldset.$element.append( this.captionSurface.$element ); this.captionSurface.initialize(); @@ -159,7 +315,8 @@ * @inheritdoc */ ve.ui.MWMediaEditDialog.prototype.teardown = function ( data ) { - var newDoc, doc, + var newDoc, doc, attr, + attrs = {}, surfaceModel = this.surface.getModel(); // Data initialization @@ -183,6 +340,18 @@ surfaceModel.change( ve.dm.Transaction.newFromDocumentInsertion( doc, this.captionNode.getRange().start, newDoc ) ); + // Change attributes + attr = this.sizeInput.height.getValue(); + if ( attr ) { + attrs.height = attr; + } + attr = this.sizeInput.width.getValue(); + if ( attr ) { + attrs.width = attr; + } + surfaceModel.change( + ve.dm.Transaction.newFromAttributeChanges( doc, this.mediaNode.getOffset(), attrs ) + ); } // Cleanup diff --git a/modules/ve-mw/ui/styles/ve.ui.MWDialog.css b/modules/ve-mw/ui/styles/ve.ui.MWDialog.css index e7dac87..381d9a6 100644 --- a/modules/ve-mw/ui/styles/ve.ui.MWDialog.css +++ b/modules/ve-mw/ui/styles/ve.ui.MWDialog.css @@ -105,6 +105,13 @@ right: 0; } +/* ve.ui.MWMediaEditDialog */ +.ve-ui-mwMediaEditDialog-size-error input[type='text'] { + background: #ffc2c2; + border: 2px solid #c90000; +} + + /* ve.ui.MWSaveDialog */ .ve-ui-mwSaveDialog-panel { -- To view, visit https://gerrit.wikimedia.org/r/103193 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I2946fb21c46ce05583b219f665ef68928188899e Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/VisualEditor Gerrit-Branch: master Gerrit-Owner: Mooeypoo <mor...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits