jenkins-bot has submitted this change and it was merged.

Change subject: Frontend quantities
......................................................................


Frontend quantities

(requires follow-up Ic89b54e39b3fd759bad568fc412e192b237da320 to work properly)

Change-Id: Iaaa1e0ac05f025be85a95d9a99d60329e89a98db
---
M DataValues/DataValues.resources.php
M DataValues/DataValues.tests.qunit.php
A DataValues/resources/values/QuantityValue.js
M DataValues/tests/qunit/dataValues.DataValue.tests.js
M DataValuesCommon/DataValuesCommon.mw.php
M DataValuesCommon/js/ValueParsers.resources.php
A DataValuesCommon/js/src/ValueParsers/parsers/QuantityParser.js
A DataValuesCommon/js/tests/ValueParsers/parsers/QuantityParser.tests.js
A ValueView/resources/jquery.valueview/valueview.experts/experts.QuantityType.js
M ValueView/resources/jquery.valueview/valueview.experts/experts.StringValue.js
10 files changed, 319 insertions(+), 4 deletions(-)

Approvals:
  Tobias Gritschacher: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/DataValues/DataValues.resources.php 
b/DataValues/DataValues.resources.php
index 31e4d09..e67ee6a 100644
--- a/DataValues/DataValues.resources.php
+++ b/DataValues/DataValues.resources.php
@@ -46,7 +46,6 @@
                        'scripts' => array(
                                // Note: The order here is relevant, scripts 
should be places after the ones they
                                //  depend on.
-                               // TODO: Make one module per data value type.
                                'values/BoolValue.js',
                                'values/GlobeCoordinateValue.js',
                                'values/MonolingualTextValue.js',
@@ -54,6 +53,7 @@
                                'values/StringValue.js',
                                'values/NumberValue.js',
                                'values/TimeValue.js',
+                               'values/QuantityValue.js',
                                'values/UnknownValue.js',
                                'values/UnUnserializableValue.js',
                        ),
diff --git a/DataValues/DataValues.tests.qunit.php 
b/DataValues/DataValues.tests.qunit.php
index d309a18..d1e0a48 100644
--- a/DataValues/DataValues.tests.qunit.php
+++ b/DataValues/DataValues.tests.qunit.php
@@ -47,6 +47,7 @@
                                "$bp/values/StringValue.tests.js",
                                "$bp/values/NumberValue.tests.js",
                                "$bp/values/TimeValue.tests.js",
+                               "$bp/values/QuantityValue.tests.js",
                                "$bp/values/UnknownValue.tests.js",
                                "$bp/values/UnUnserializableValue.tests.js",
                        ),
diff --git a/DataValues/resources/values/QuantityValue.js 
b/DataValues/resources/values/QuantityValue.js
new file mode 100644
index 0000000..150df01
--- /dev/null
+++ b/DataValues/resources/values/QuantityValue.js
@@ -0,0 +1,203 @@
+/**
+ * @licence GNU GPL v2+
+ * @author Daniel Werner < [email protected] >
+ */
+dataValues.QuantityValue = ( function( inherit, dv, $ ) {
+       'use strict';
+
+       var PARENT = dv.DataValue;
+
+       /**
+        * Constructor for a data value representing a quantity.
+        *
+        * @since 0.1
+        *
+        * @param {string|number} amount Numeric string or a number.
+        * @param {string|null} [unit] A unit identifier, or null for unit-less 
quantities.
+        * @param {number} [significantDigits] The number of significant digits 
in the amount, counting
+        *        from the most significant digit, not counting the sign or 
decimal separator.
+        *
+        * @throws {Error}
+        */
+       var constructor = function( amount, unit, significantDigits ) {
+               if( typeof unit === 'number' ) {
+                       significantDigits = unit;
+                       unit = null;
+               }
+               var amount = processAmount( amount );
+               this._unit = processUnit( unit );
+               this._significantDigits = processSignificantDigits( 
significantDigits, amount );
+               this._amount = enforceSignificanceOnAmount( amount, 
this._significantDigits );
+       };
+
+       function processAmount( amount ) {
+               if( typeof amount === 'number' ) {
+                       amount = '' + amount;
+                       if( amount.indexOf( 'e' ) !== -1 ) {
+                               throw new Error( 'Can not cast huge numbers to 
the string format required for ' +
+                                       'representing quantity values' );
+                       }
+                       // The next check will also handle NaN and Infinity.
+               }
+
+               if( typeof amount !== 'string'
+                       || amount.match( /^[+-]?(?:[1-9]\d*|\d)(?:\.\d+)?$/ ) 
=== null
+               ) {
+                       throw new Error(
+                               'Amount has to be a number or a numeric string 
using "." as decimal separator.' );
+               }
+
+               return amount.replace( /^(\d)/, '+$1' );
+       }
+
+       function processUnit( unit ) {
+               if( unit === undefined ) {
+                       unit = null;
+               }
+               else if( unit !== null && typeof unit !== 'string' ) {
+                       throw new Error( 'The unit has to be a string or null' 
);
+               }
+               return unit;
+       }
+
+       function processSignificantDigits( significantDigits, amount ) {
+               if( significantDigits === undefined ) {
+                       var hasDecimalSeparator = amount.indexOf( '.' ) !== -1;
+                       significantDigits = amount.length - 1 - 
hasDecimalSeparator;
+               }
+               else if( typeof significantDigits !== 'number' || 
significantDigits <= 0  ) {
+                       throw new Error( '' );
+               }
+               return significantDigits;
+       }
+
+       function enforceSignificanceOnAmount( amount, significantDigits ) {
+               function padRight( string, desiredLength ) {
+                       while( string.length < desiredLength ) {
+                               string += '0';
+                       }
+                       return string;
+               }
+
+               var decimalSeparatorIndex = amount.indexOf( '.' );
+               var hasDecimalSeparator = decimalSeparatorIndex !== -1;
+               var significantChars = significantDigits + 1 + 
hasDecimalSeparator;
+               var significantPart = amount.substr( 0, significantChars );
+
+               if( significantChars > decimalSeparatorIndex ) {
+                       significantPart = significantPart.replace( /\.?$/, '.' 
);
+               }
+               significantPart = padRight( significantPart, 
decimalSeparatorIndex );
+               return significantPart.replace( /\.$/, '' );
+       }
+
+       var QuantityValue = inherit( 'DvQuantityValue', PARENT, constructor, {
+               /**
+                * @see dv.DataValue.getSortKey
+                *
+                * @since 0.1
+                *
+                * @return string
+                */
+               getSortKey: function() {
+                       return this.getAmount();
+               },
+
+               /**
+                * Returns a self-reference.
+                * @see dv.DataValue.getValue
+                *
+                * @since 0.1
+                *
+                * @return dataValues.QuantityValue
+                */
+               getValue: function() {
+                       return this;
+               },
+
+               /**
+                * Returns the amount held by this quantity, as a string in 
standard format.
+                *
+                * @since 0.1
+                *
+                * @return string
+                */
+               getAmount: function() {
+                       return this._amount;
+               },
+
+               /**
+                * Returns the unit held by this quantity. Returns null in case 
of unit-less quantities.
+                *
+                * @since 0.1
+                *
+                * @return string|null
+                */
+               getUnit: function() {
+                       return this._unit;
+               },
+
+               /**
+                * Returns the number of significant digits in the amount, 
counting from the most
+                * significant digit, not counting the sign or decimal 
separator.
+                *
+                * @since 0.1
+                *
+                * @return number
+                */
+               getSignificantDigits: function() {
+                       return this._significantDigits;
+               },
+
+               /**
+                * @see dv.DataValue.equals
+                *
+                * @since 0.1
+                */
+               equals: function( value ) {
+                       if ( !( value instanceof this.constructor ) ) {
+                               return false;
+                       }
+
+                       return this.getAmount() === value.getAmount()
+                               && this.getUnit() === value.getUnit()
+                               && this.getSignificantDigits() === 
value.getSignificantDigits();
+               },
+
+               /**
+                * @see dv.DataValue.toJSON
+                *
+                * @since 0.1
+                *
+                * @return Object
+                */
+               toJSON: function() {
+                       return {
+                               amount: this.getAmount(),
+                               unit: this.getUnit(),
+                               digits: this.getSignificantDigits()
+                       };
+               }
+       } );
+
+       /**
+        * @see dv.DataValue.newFromJSON
+        */
+       QuantityValue.newFromJSON = function( json ) {
+               return new QuantityValue(
+                       json.amount,
+                       json.unit,
+                       json.digits
+               );
+       };
+
+       /**
+        * @see dv.DataValue.TYPE
+        */
+       QuantityValue.TYPE = 'quantity';
+
+       return QuantityValue;
+
+}( dataValues.util.inherit, dataValues, jQuery ) );
+
+dataValues.registerDataValue( dataValues.StringValue );
diff --git a/DataValues/tests/qunit/dataValues.DataValue.tests.js 
b/DataValues/tests/qunit/dataValues.DataValue.tests.js
index 69f3608..ce1c809 100644
--- a/DataValues/tests/qunit/dataValues.DataValue.tests.js
+++ b/DataValues/tests/qunit/dataValues.DataValue.tests.js
@@ -116,7 +116,10 @@
                                        instance instanceof dv.DataValue,
                                        'is instance of DataValue'
                                );
-
+                               assert.ok(
+                                       instance instanceof 
this.getConstructor(),
+                                       'is instance of actual data value 
implementation\'s constructor'
+                               );
                                assert.equal(
                                        typeof( instance.getType() ),
                                        'string',
diff --git a/DataValuesCommon/DataValuesCommon.mw.php 
b/DataValuesCommon/DataValuesCommon.mw.php
index b344729..537f6b8 100644
--- a/DataValuesCommon/DataValuesCommon.mw.php
+++ b/DataValuesCommon/DataValuesCommon.mw.php
@@ -140,6 +140,7 @@
                                'parsers/IntParser.tests.js',
                                'parsers/StringParser.tests.js',
                                'parsers/TimeParser.tests.js',
+                               'parsers/QuantityParser.tests.js',
                                'parsers/NullParser.tests.js',
                        ),
                        'dependencies' => array(
diff --git a/DataValuesCommon/js/ValueParsers.resources.php 
b/DataValuesCommon/js/ValueParsers.resources.php
index 2b71b7c..4ce51df 100644
--- a/DataValuesCommon/js/ValueParsers.resources.php
+++ b/DataValuesCommon/js/ValueParsers.resources.php
@@ -56,6 +56,7 @@
                                'parsers/IntParser.js',
                                'parsers/StringParser.js',
                                'parsers/TimeParser.js',
+                               'parsers/QuantityParser.js',
                                'parsers/NullParser.js',
                        ),
                        'dependencies' => array(
diff --git a/DataValuesCommon/js/src/ValueParsers/parsers/QuantityParser.js 
b/DataValuesCommon/js/src/ValueParsers/parsers/QuantityParser.js
new file mode 100644
index 0000000..cf15c8b
--- /dev/null
+++ b/DataValuesCommon/js/src/ValueParsers/parsers/QuantityParser.js
@@ -0,0 +1,28 @@
+/**
+ * @file
+ * @ingroup ValueParsers
+ *
+ * @licence GNU GPL v2+
+ *
+ * @author Daniel Werner < [email protected] >
+ */
+( function( vp, dv ) {
+       'use strict';
+
+       var PARENT = vp.ApiBasedValueParser;
+
+       /**
+        * Constructor for globe coordinate parsers.
+        *
+        * @constructor
+        * @extends vp.ApiBasedValueParser
+        * @since 0.1
+        */
+       vp.QuantityParser = dv.util.inherit( PARENT, {
+               /**
+                * @see vp.ApiBasedValueParser.API_VALUE_PARSER_ID
+                */
+               API_VALUE_PARSER_ID: 'quantity'
+       } );
+
+}( valueParsers, dataValues ) );
diff --git 
a/DataValuesCommon/js/tests/ValueParsers/parsers/QuantityParser.tests.js 
b/DataValuesCommon/js/tests/ValueParsers/parsers/QuantityParser.tests.js
new file mode 100644
index 0000000..77f1c5a
--- /dev/null
+++ b/DataValuesCommon/js/tests/ValueParsers/parsers/QuantityParser.tests.js
@@ -0,0 +1,51 @@
+/**
+ * @licence GNU GPL v2+
+ * @author Daniel Werner < [email protected] >
+ *
+ * Constructor for creating a test object holding tests for the QuantityParser 
data value parser.
+ *
+ * @since 0.1
+ */
+valueParsers.tests.QuantityParserTest = ( function(
+       inherit, ValueParserTest, QuantityValue, QuantityParser, $
+) {
+       'use strict';
+
+       var PARENT = ValueParserTest;
+       var QuantityParserTest = inherit( PARENT, {
+               /**
+                * @see vp.tests.ValueParserTest.getObject
+                */
+               getObject: function() {
+                       return QuantityParser;
+               },
+
+               /**
+                * @see vp.tests.ValueParserTest.getParseArguments
+                */
+               getParseArguments: function() {
+                       return [
+                               [
+                                       '1.5, 1.25',
+                                       new QuantityValue( {} )
+                               ], [
+                                       '-50, -20',
+                                       new QuantityValue( {} )
+                               ]
+                       ];
+               }
+
+       } );
+
+       var test = new QuantityParserTest();
+       test.runTests( 'valueParsers.QuantityParser' );
+
+       return QuantityParserTest;
+
+}(
+       valueParsers.util.inherit,
+       valueParsers.tests.ValueParserTest,
+       dataValues.QuantityValue,
+       valueParsers.QuantityParser,
+       jQuery
+) );
diff --git 
a/ValueView/resources/jquery.valueview/valueview.experts/experts.QuantityType.js
 
b/ValueView/resources/jquery.valueview/valueview.experts/experts.QuantityType.js
new file mode 100644
index 0000000..151dd99
--- /dev/null
+++ 
b/ValueView/resources/jquery.valueview/valueview.experts/experts.QuantityType.js
@@ -0,0 +1,27 @@
+/**
+ * @licence GNU GPL v2+
+ * @author Daniel Werner < [email protected] >
+ *
+ * Valueview expert for values of quantity data type.
+ *
+ * @since 0.1
+ *
+ * @constructor
+ * @extends jQuery.valueview.experts.BifidExpert
+ */
+jQuery.valueview.experts.QuantityType = ( function( dv, vp, $, vv ) {
+       'use strict';
+
+       var PARENT = vv.StringValue;
+//     var editableExpert = vv.experts.StringValue;
+
+       return vv.expert( 'quantitytype', PARENT, {
+               /**
+                * @see Query.valueview.Expert.parser
+                */
+               parser: function() {
+                       return new vp.QuantityParser();
+               }
+       } );
+
+}( dataValues, valueParsers, jQuery, jQuery.valueview ) );
diff --git 
a/ValueView/resources/jquery.valueview/valueview.experts/experts.StringValue.js 
b/ValueView/resources/jquery.valueview/valueview.experts/experts.StringValue.js
index 39a3a33..aecd0b8 100644
--- 
a/ValueView/resources/jquery.valueview/valueview.experts/experts.StringValue.js
+++ 
b/ValueView/resources/jquery.valueview/valueview.experts/experts.StringValue.js
@@ -111,8 +111,8 @@
                        // Resize textarea to fit the value (which might be 
empty):
                        this._resizeInput();
 
-                       // We always use the textare for displaying the value, 
only in edit mode we format the
-                       // textare as an input field though.
+                       // We always use the textarea for displaying the value, 
only in edit mode we format the
+                       // textarea as an input field though.
                        if( this._viewState.isInEditMode() ) {
                                // in EDIT MODE:
                                this.$input.prop( {

-- 
To view, visit https://gerrit.wikimedia.org/r/84754
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Iaaa1e0ac05f025be85a95d9a99d60329e89a98db
Gerrit-PatchSet: 4
Gerrit-Project: mediawiki/extensions/DataValues
Gerrit-Branch: master
Gerrit-Owner: Daniel Werner <[email protected]>
Gerrit-Reviewer: Henning Snater <[email protected]>
Gerrit-Reviewer: Tobias Gritschacher <[email protected]>
Gerrit-Reviewer: jenkins-bot

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to