jenkins-bot has submitted this change and it was merged.
Change subject: Adding a MediaSizeWidget
......................................................................
Adding a MediaSizeWidget
The widget is responsible for presenting width/height values and storing
original media size values that aspect ratio is calculated from.
Change-Id: I3d0f9348a52ac39f68dd09394778369026928c9d
---
M modules/ve/i18n/en.json
M modules/ve/i18n/qqq.json
M modules/ve/ui/styles/ve.ui.Widget.css
A modules/ve/ui/widgets/ve.ui.MediaSizeWidget.js
4 files changed, 384 insertions(+), 2 deletions(-)
Approvals:
Catrope: Looks good to me, approved
jenkins-bot: Verified
diff --git a/modules/ve/i18n/en.json b/modules/ve/i18n/en.json
index d9bea05..4094ce2 100644
--- a/modules/ve/i18n/en.json
+++ b/modules/ve/i18n/en.json
@@ -60,6 +60,10 @@
"visualeditor-languageinspector-widget-label-langcode": "Language code",
"visualeditor-languageinspector-widget-label-language": "Language",
"visualeditor-linkinspector-title": "Hyperlink",
+ "visualeditor-mediasizewidget-button-originaldimensions": "Set to original
dimensions",
+ "visualeditor-mediasizewidget-label-defaulterror": "Size values are
invalid.",
+ "visualeditor-mediasizewidget-label-height": "Height",
+ "visualeditor-mediasizewidget-label-width": "Width",
"visualeditor-listbutton-bullet-tooltip": "Bullet list",
"visualeditor-listbutton-number-tooltip": "Numbered list",
"visualeditor-shortcuts-clipboard": "Clipboard",
@@ -72,4 +76,4 @@
"visualeditor-specialcharinspector-characterlist-insert":
"{\n\t\"symbols\": {\n\t\t\"−\": \"−\",\n\t\t\"—\": \"—\",\n\t\t\"°\":
\"°\",\n\t\t\"″\": \"″\",\n\t\t\"′\": \"′\",\n\t\t\"←\": \"←\",\n\t\t\"→\":
\"→\",\n\t\t\"·\": \"·\",\n\t\t\"§\": \"§\"\n\t},\n\t\"accents\": {\n\t\t\"à\":
\"à\",\n\t\t\"á\": \"á\",\n\t\t\"â\": \"â\",\n\t\t\"ä\": \"ä\",\n\t\t\"ç\":
\"ç\",\n\t\t\"è\": \"è\",\n\t\t\"é\": \"é\",\n\t\t\"ê\": \"ê\",\n\t\t\"ë\":
\"ë\",\n\t\t\"ì\": \"ì\",\n\t\t\"í\": \"í\",\n\t\t\"î\": \"î\",\n\t\t\"ï\":
\"ï\",\n\t\t\"ò\": \"ò\",\n\t\t\"ó\": \"ó\",\n\t\t\"ô\": \"ô\",\n\t\t\"ö\":
\"ö\",\n\t\t\"ø\": \"ø\",\n\t\t\"ù\": \"ù\",\n\t\t\"ú\": \"ú\",\n\t\t\"û\":
\"û\",\n\t\t\"ü\": \"ü\"\n\t},\n\t\"math\": {\n\t\t\"−\": \"−\",\n\t\t\"×\":
\"×\",\n\t\t\"÷\": \"÷\",\n\t\t\"≈\": \"≈\",\n\t\t\"≠\": \"≠\",\n\t\t\"≤\":
\"≤\",\n\t\t\"≥\": \"≥\",\n\t\t\"±\": \"±\"\n\t}\n}",
"visualeditor-toolbar-insert": "Insert",
"visualeditor-version-label": "Version"
-}
\ No newline at end of file
+}
diff --git a/modules/ve/i18n/qqq.json b/modules/ve/i18n/qqq.json
index b71c960..975a971 100644
--- a/modules/ve/i18n/qqq.json
+++ b/modules/ve/i18n/qqq.json
@@ -65,6 +65,10 @@
"visualeditor-linkinspector-title": "Title of the link inspector
dialog.\n{{Identical|Hyperlink}}",
"visualeditor-listbutton-bullet-tooltip": "Tooltip text for the bullet
list button",
"visualeditor-listbutton-number-tooltip": "Tooltip text for the numbered
list button",
+ "visualeditor-mediasizewidget-button-originaldimensions": "Label for the
button that sets media to its original dimensions.",
+ "visualeditor-mediasizewidget-label-defaulterror": "An error label
notifying the user the size inputs are invalid.",
+ "visualeditor-mediasizewidget-label-height": "Label for the height input.",
+ "visualeditor-mediasizewidget-label-width": "Label for the width input.",
"visualeditor-shortcuts-clipboard": "Heading for clipboard shortcuts",
"visualeditor-shortcuts-formatting": "Heading for paragraph formatting
shortcuts",
"visualeditor-shortcuts-history": "Heading for history shortcuts",
@@ -75,4 +79,4 @@
"visualeditor-specialcharinspector-characterlist-insert": "This is a JSON
string defining the special characters that can be inserted using the special
character insertion tool.\n{{doc-important|Please make sure it is a valid JSON
string.}}\n{{Optional}}",
"visualeditor-toolbar-insert": "Label text for insert menu in
toolbar.\n{{Identical|Insert}}",
"visualeditor-version-label": "Label text for version
number\n{{Identical|Version}}"
-}
\ No newline at end of file
+}
diff --git a/modules/ve/ui/styles/ve.ui.Widget.css
b/modules/ve/ui/styles/ve.ui.Widget.css
index e70ec20..d04cf1f 100644
--- a/modules/ve/ui/styles/ve.ui.Widget.css
+++ b/modules/ve/ui/styles/ve.ui.Widget.css
@@ -114,3 +114,8 @@
.ve-ui-groupButtonWidget {
white-space: normal;
}
+
+/* ve.ui.MediaSizeWidget */
+.ve-ui-mediaSizeWidget-input-hasError input[type="text"] {
+ background: #ffc2c2;
+}
diff --git a/modules/ve/ui/widgets/ve.ui.MediaSizeWidget.js
b/modules/ve/ui/widgets/ve.ui.MediaSizeWidget.js
new file mode 100644
index 0000000..942c814
--- /dev/null
+++ b/modules/ve/ui/widgets/ve.ui.MediaSizeWidget.js
@@ -0,0 +1,369 @@
+/*!
+ * VisualEditor UserInterface MediaSizeWidget class.
+ *
+ * @copyright 2011-2014 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/**
+ * Widget that lets the user edit dimensions (width and height),
+ * optionally with a fixed aspect ratio.
+ *
+ * The widget is designed to work in one of two ways:
+ * 1. Instantiated with size configuration already set up
+ * 2. Instantiated empty, and size details added when the
+ * data is available.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {number} [width] Initial width value
+ * @cfg {number} [height] Initial heigh value
+ * @cfg {Object} [originalDimensions] Original dimensions (width and height)
+ * @cfg {Object} [maxDimensions] Maximum dimensions the user is not allowed to
exceed
+ */
+ve.ui.MediaSizeWidget = function VeUiMediaSizeWidget( config ) {
+ var heightLabel, widthLabel;
+
+ // Parent constructor
+ OO.ui.Widget.call( this, config );
+
+ // Configuration
+ config = config || {};
+
+ this.width = config.width || '';
+ this.height = config.height || '';
+ this.originalDimensions = config.originalDimensions || {};
+ this.maxDimensions = config.maxDimensions || {};
+
+ // Cache for the aspect ratio, which is set by setOriginalDimensions()
+ this.aspectRatio = null;
+
+ // Validation
+ this.valid = false;
+
+ // Define dimension input widgets
+ this.widthInput = new OO.ui.TextInputWidget( {
+ '$': this.$
+ } );
+ this.heightInput = new OO.ui.TextInputWidget( {
+ '$': this.$
+ } );
+
+ // Define dimension labels
+ widthLabel = new OO.ui.InputLabelWidget( {
+ '$': this.$,
+ 'input': this.widthInput,
+ 'label': ve.msg( 'visualeditor-mediasizewidget-label-width' )
+ } );
+ heightLabel = new OO.ui.InputLabelWidget( {
+ '$': this.$,
+ 'input': this.heightInput,
+ 'label': ve.msg( 'visualeditor-mediasizewidget-label-height' )
+ } );
+ // Error label
+ this.errorLabel = new OO.ui.InputLabelWidget( {
+ '$': this.$,
+ 'label': ve.msg(
'visualeditor-mediasizewidget-label-defaulterror' )
+ } );
+
+ // Define buttons
+ this.originalDimensionsButton = new OO.ui.PushButtonWidget( {
+ '$': this.$,
+ 'label': ve.msg(
'visualeditor-mediasizewidget-button-originaldimensions' )
+ } );
+
+ // Build the GUI
+ this.$element.append( [
+ this.$( '<div>' )
+ .addClass( 've-ui-mediaSizeWidget-section-width' )
+ .append( [
+ widthLabel.$element,
+ this.widthInput.$element
+ ] ),
+ this.$( '<div>' )
+ .addClass( 've-ui-mediaSizeWidget-section-height' )
+ .append( [
+ heightLabel.$element,
+ this.heightInput.$element
+ ] ),
+ this.$( '<div>' )
+ .addClass( 've-ui-mediaSizeWidget-button-originalSize' )
+ .append( this.originalDimensionsButton.$element ),
+ this.$( '<div>' )
+ .addClass( 've-ui-mediaSizeWidget-label-error' )
+ .append( this.errorLabel.$element ),
+ ] );
+
+ this.originalDimensionsButton.setDisabled( true );
+
+ // Events
+ this.originalDimensionsButton.connect( this, { 'click':
'onButtonOriginalDimensionsClick' } );
+
+ this.widthInput.connect( this, { 'change': 'onWidthChange' } );
+ this.heightInput.connect( this, { 'change': 'onHeightChange' } );
+
+ // Initialization
+ this.$element.addClass( 've-ui-mediaSizeWidget' );
+ this.setOriginalDimensions( this.originalDimensions );
+ this.setMaxDimensions( this.maxDimensions );
+};
+
+/* Inheritance */
+
+OO.inheritClass( ve.ui.MediaSizeWidget, OO.ui.Widget );
+
+/* Methods */
+
+/**
+ * Get the currently set rounded dimensions.
+ *
+ * @returns {Object} Current dimensions, rounded to integer values
+ * @returns {number} return.width Width
+ * @returns {number} return.height Height
+ */
+ve.ui.MediaSizeWidget.prototype.getDimensions = function () {
+ return {
+ 'width': Number( this.widthInput.getValue() ),
+ 'height': Number( this.heightInput.getValue() )
+ };
+};
+
+/**
+ * Set the current width and height dimensions.
+ * This method accepts either both values or a single value.
+ *
+ * In general, it is expected that the original dimensions will
+ * be supplied before the current dimensions, but in case they
+ * are not, several fallback options exist.
+ *
+ * The method will accept and handle either of the following:
+ * 1. Both width/height dimensions are supplied:
+ * a. If original dimensions already set the inputs are filled
+ * in without calculation, trusting the verification method
+ * to notify the user in case there are errors.
+ * b. If original dimensions or aspectRatio are not set image
+ * will not be bound to aspect ratio.
+ * 2. Only width or only height are supplied:
+ * a. If original dimensions are already set, the corresponding
+ * input value is calculated.
+ * b. If original dimensions and aspectRatio are not set, the
+ * corresponding value will not be updated.
+ *
+ * All raw values are catched internally for accurate calculations
+ * and the values are rounded for display inside the inputs.
+ *
+ * @param {Object} dimensions Dimensions to set
+ * @param {number} [dimensions.width] Width to set
+ * @param {number} [dimensions.height] Height to set
+ */
+ve.ui.MediaSizeWidget.prototype.setDimensions = function ( dimensions ) {
+
+ // Recursion protection
+ if ( this.preventChangeRecursion ) {
+ return;
+ }
+
+ this.preventChangeRecursion = true;
+
+ if ( dimensions.width && dimensions.height ) {
+ // If both dimensions are set up, use them directly
+ this.width = dimensions.width;
+ this.height = dimensions.height;
+ } else if ( dimensions.width && !dimensions.height ) {
+ // If only width is defined
+ this.width = dimensions.width;
+ if ( this.aspectRatio !== null ) {
+ // If aspect ratio is available, calculate
+ this.height = Math.round( this.width /
this.getAspectRatio() );
+ }
+ } else if ( dimensions.height && !dimensions.width ) {
+ // If only height is defined
+ this.height = dimensions.height;
+ if ( this.aspectRatio !== null ) {
+ // If aspect ratio is available, calculate
+ this.width = Math.round( this.height *
this.getAspectRatio() );
+ }
+ }
+
+ // This will only update if the value has changed
+ this.widthInput.setValue( this.width );
+ this.heightInput.setValue( this.height );
+
+ // Check if we need to notify the user that the dimensions
+ // have a problem
+ this.validateDimensions();
+
+ this.preventChangeRecursion = false;
+};
+
+/**
+ * Get the height and width values of the maximum allowed dimensions, if set.
+ *
+ * @returns {Object} Maximum dimensions
+ * @returns {number} [return.width] Maximum width, if set
+ * @returns {number} [return.height] Maximum height, if set
+ */
+ve.ui.MediaSizeWidget.prototype.getMaxDimensions = function () {
+ return this.originalDimensions;
+};
+
+/**
+ * Set maximum width and/or height.
+ * @param {Object} dimensions Maximum dimensions
+ * @param {number} [dimensions.width] Maximum width
+ * @param {number} [dimensions.height] Maximum height
+ */
+ve.ui.MediaSizeWidget.prototype.setMaxDimensions = function ( dimensions ) {
+ this.maxDimensions = {
+ 'width': dimensions.width,
+ 'height': dimensions.height
+ };
+};
+
+/**
+ * Get the original dimensions of the image, if set.
+ * @returns {Object} Original dimensions
+ * @returns {number} [return.width] Original width, if set
+ * @returns {number} [return.height] Original height, if set
+ */
+ve.ui.MediaSizeWidget.prototype.getOriginalDimensions = function () {
+ return this.originalDimensions;
+};
+
+/**
+ * Set the original dimensions and cache the aspect ratio.
+ * @param {Object} dimensions Original dimensions
+ * @param {number} dimensions.width Original width
+ * @param {number} dimensions.height Original height
+ */
+ve.ui.MediaSizeWidget.prototype.setOriginalDimensions = function ( dimensions
) {
+ this.originalDimensions = {
+ 'width': dimensions.width,
+ 'height': dimensions.height
+ };
+ // Cache the aspect ratio
+ this.aspectRatio = this.originalDimensions.width /
this.originalDimensions.height;
+ // Enable the 'original dimensions' button
+ this.originalDimensionsButton.setDisabled( false );
+};
+
+/**
+ * Explicitly set the aspect ratio, overriding what setOriginalDimensions()
computed.
+ * @param {number} ratio Aspect ratio (width/height)
+ */
+ve.ui.MediaSizeWidget.prototype.setAspectRatio = function ( ratio ) {
+ this.aspectRatio = ratio;
+};
+
+/**
+ * Retrieve the aspect ratio. This is only known if set through
setAspectRatio() or
+ * computed by setOriginalDimensions().
+ *
+ * @returns {number|null} Aspect ratio (width/height)
+ */
+ve.ui.MediaSizeWidget.prototype.getAspectRatio = function () {
+ return this.aspectRatio;
+};
+
+/**
+ * Checks whether the input values are valid. If the inputs are
+ * not valid, an error class will be added to the inputs.
+ */
+ve.ui.MediaSizeWidget.prototype.validateDimensions = function () {
+
+ // Check for an error in the values
+ if (
+ !$.isNumeric( this.width ) ||
+ !$.isNumeric( this.height ) ||
+ Number( this.width ) <= 0 ||
+ Number( this.height ) <= 0 ||
+ // Check if the size exceeds max dimensions,
+ // but only if the maxDimensions are set
+ // TODO use a separate error message for this case,
+ // and put the max dimensions in the error message
+ (
+ $.isNumeric( this.maxDimensions.width ) &&
+ Number( this.width ) > this.maxDimensions.width
+ ) || (
+ $.isNumeric( this.maxDimensions.height ) &&
+ Number( this.height ) > this.maxDimensions.height
+ )
+ ) {
+ this.valid = false;
+ // Show error message
+ this.errorLabel.$element.show();
+ } else {
+ this.valid = true;
+ // Hide the error message
+ this.errorLabel.$element.hide();
+ }
+
+ // Add or remove the error class
+ this.$element.toggleClass( 've-ui-mediaSizeWidget-input-hasError',
!this.valid );
+};
+
+/**
+ * Respond to a change in the width input.
+ */
+ve.ui.MediaSizeWidget.prototype.onWidthChange = function () {
+ var val = this.widthInput.getValue();
+ if ( $.isNumeric( val ) ) {
+ // Calculate and update the corresponding value
+ this.setDimensions( { 'width': val } );
+ } else {
+ this.width = val;
+ // We didn't perform an actual change, but we should still
validate
+ // the input values
+ this.validateDimensions();
+ }
+};
+
+/**
+ * Respond to a change in the height input.
+ */
+ve.ui.MediaSizeWidget.prototype.onHeightChange = function () {
+ var val = this.heightInput.getValue();
+ if ( $.isNumeric( val ) ) {
+ // Calculate and update the corresponding value
+ this.setDimensions( { 'height': val } );
+ } else {
+ this.height = val;
+ // We didn't perform an actual change, but we should still
validate
+ // the input values
+ this.validateDimensions();
+ }
+};
+
+/**
+ * Set the width/height values to the original media dimensions
+ *
+ * @param {jQuery.Event} e Click event
+ */
+ve.ui.MediaSizeWidget.prototype.onButtonOriginalDimensionsClick = function () {
+ this.setDimensions( this.originalDimensions );
+};
+
+/**
+ * Checks whether there is an error with the widget
+ * @returns {boolean} Values are valid
+ */
+ve.ui.MediaSizeWidget.prototype.isValid = function () {
+ return this.valid;
+};
+
+/**
+ * Clear all values.
+ * This is useful to update the widget values between different
+ * images that have other dimensions or restrictions while the
+ * widget is already instantiated.
+ */
+ve.ui.MediaSizeWidget.prototype.clear = function () {
+ this.aspectRatio = null;
+ this.originalDimensions = {};
+ this.maxDimensions = {};
+ this.width = '';
+ this.height = '';
+};
--
To view, visit https://gerrit.wikimedia.org/r/107019
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I3d0f9348a52ac39f68dd09394778369026928c9d
Gerrit-PatchSet: 15
Gerrit-Project: VisualEditor/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Mooeypoo <[email protected]>
Gerrit-Reviewer: Catrope <[email protected]>
Gerrit-Reviewer: Esanders <[email protected]>
Gerrit-Reviewer: Mooeypoo <[email protected]>
Gerrit-Reviewer: Robmoen <[email protected]>
Gerrit-Reviewer: Trevor Parscal <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits