Daniel Werner has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/57738


Change subject: (bug 45002) additional experts for jQuery.valueview
......................................................................

(bug 45002) additional experts for jQuery.valueview

* Introduction of a "BifidExpert" which is an abstract valueview expert 
definition which requires
  two other expert constructors in an implementation. The bifid expert will 
choose one of the two
  other experts depending on the valueview's current mode. This allows greater 
flexibility when
  defining new experts and allows for sharing code more efficiently.
* SuggestedStringValue expert which is basically a StringValue expert plus 
suggester jQuery
  widget on top. Also see the TODOs in the documentation.
* Introduces a "StaticDom" expert which can be used together with the 
"BifidExpert".
* Reintroduction of special handling for string data values that should match 
the CommonsMedia
  data type definition. This is done with a CommonsMediaType expert. This 
expert is combining the
  three experts described above.
* Added the commons media support to MediaWiki's default expert factory.

Change-Id: Ibf778f2ab544ec51f8f9574eb32aea82a5707caf
---
M ValueView/ValueView.resources.mw.php
M ValueView/ValueView.resources.php
A ValueView/resources/jquery.valueview/valueview.BifidExpert.js
A 
ValueView/resources/jquery.valueview/valueview.experts/experts.CommonsMediaType.js
A ValueView/resources/jquery.valueview/valueview.experts/experts.StaticDom.js
A 
ValueView/resources/jquery.valueview/valueview.experts/experts.SuggestedStringValue.js
M ValueView/resources/mw.ext.valueView.js
7 files changed, 424 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/DataValues 
refs/changes/38/57738/1

diff --git a/ValueView/ValueView.resources.mw.php 
b/ValueView/ValueView.resources.mw.php
index 55227f3..8af3193 100644
--- a/ValueView/ValueView.resources.mw.php
+++ b/ValueView/ValueView.resources.mw.php
@@ -49,6 +49,7 @@
                        'dependencies' => array(
                                'jquery.valueview',
                                'jquery.valueview.experts.stringvalue',
+                               'jquery.valueview.experts.commonsmediatype'
                        ),
                ),
 
diff --git a/ValueView/ValueView.resources.php 
b/ValueView/ValueView.resources.php
index 9964c8c..f8c6032 100644
--- a/ValueView/ValueView.resources.php
+++ b/ValueView/ValueView.resources.php
@@ -143,6 +143,19 @@
                                'jquery.inputAutoExpand',
                        ),
                ),
+
+               'jquery.valueview.experts.commonsmediatype' => $moduleTemplate 
+ array(
+                       'scripts' => array(
+                               'jquery.valueview/valueview.BifidExpert.js', // 
todo: define separate modules
+                               
'jquery.valueview/valueview.experts/experts.StaticDom.js',
+                               
'jquery.valueview/valueview.experts/experts.SuggestedStringValue.js',
+                               
'jquery.valueview/valueview.experts/experts.CommonsMediaType.js',
+                       ),
+                       'dependencies' => array(
+                               'jquery.valueview.experts.stringvalue',
+                               'jquery.ui.suggester',
+                       ),
+               ),
        );
 
 } );
diff --git a/ValueView/resources/jquery.valueview/valueview.BifidExpert.js 
b/ValueView/resources/jquery.valueview/valueview.BifidExpert.js
new file mode 100644
index 0000000..04c0007
--- /dev/null
+++ b/ValueView/resources/jquery.valueview/valueview.BifidExpert.js
@@ -0,0 +1,167 @@
+/**
+ * @file
+ * @ingroup ValueView
+ * @licence GNU GPL v2+
+ * @author Daniel Werner < daniel.wer...@wikimedia.de >
+ */
+( function( dv, vp, $, vv ) {
+       'use strict';
+
+       var PARENT = vv.Expert;
+
+       /**
+        * Abstract definition of a Valueview expert whose responsibilities are 
shared by two valueview
+        * experts; one taking over during edit mode, one being responsible 
while in static mode.
+        *
+        * @since 0.1
+        *
+        * @abstract
+        * @constructor
+        * @extends jQuery.valueview.Expert
+        */
+       vv.BifidExpert = dv.util.inherit( PARENT, {
+               /**
+                * Constructor for the valueview expert responsible during 
static mode.
+                * @type Function
+                */
+               _staticExpert: null,
+
+               /**
+                * Options map, the constructor of "_staticExpert" will be 
initialized with.
+                */
+               _staticExpertOptions: null,
+
+               /**
+                * Constructor for the valueview expert responsible during edit 
mode.
+                * @type Function
+                */
+               _editableExpert: null,
+
+               /**
+                * Options map, the constructor of "_editableExpert" will be 
initialized with.
+                */
+               _editableExpertOptions: null,
+
+               /**
+                * The expert currently used internally. Either an instance of 
the constructor given in the
+                * "_editableExpert" or "_staticExpert" field.
+                * @type jQuery.valueview.Expert
+                */
+               _currentExpert: null,
+
+               /**
+                * @see jQuery.valueview.Expert._init
+                */
+               _init: function() {
+                       this._updateExpert();
+               },
+
+               /**
+                * Will check whether the current expert is the right one for 
the related view's current
+                * mode. If not, the expert will be changed. Returns whether or 
not the expert has been
+                * updated.
+                *
+                * @since 0.1
+                *
+                * @return boolean
+                */
+               _updateExpert: function() {
+                       var NewExpertConstructor, newExpertOptions;
+
+                       if( this._viewState.isInEditMode() ) {
+                               NewExpertConstructor = this._editableExpert;
+                               newExpertOptions = this._editableExpertOptions 
|| {};
+                       } else {
+                               NewExpertConstructor = this._staticExpert;
+                               newExpertOptions = this._staticExpertOptions || 
{};
+                       }
+
+                       if( !this._currentExpert // first call
+                               || this._currentExpert.constructor !== 
NewExpertConstructor
+                       ) {
+                               var rawValue = null;
+
+                               if( this._currentExpert ) {
+                                       rawValue = 
this._currentExpert.rawValue();
+
+                                       // Destroy old expert which was 
responsible during previous state:
+                                       this._currentExpert.destroy();
+                                       this.$viewPort.empty();
+                               }
+
+                               // Instantiate new expert, responsible during 
current state:
+                               this._currentExpert = new NewExpertConstructor(
+                                       this.$viewPort,
+                                       this._viewState,
+                                       this._viewNotifier,
+                                       newExpertOptions
+                               );
+                               this._currentExpert.rawValue( rawValue );
+
+                               return true;
+                       }
+                       return false;
+               },
+
+               /**
+                * @see jQuery.valueview.Expert.destroy
+                */
+               destroy: function() {
+                       this.$viewPort = null;
+                       this._viewState = null;
+               },
+
+               /**
+                * @see jQuery.valueview.Expert.parser
+                */
+               parser: function() {
+                       return this._currentExpert.parser();
+               },
+
+               /**
+                * @see jQuery.valueview.Expert._getRawValue
+                */
+               _getRawValue: function() {
+                       return this._currentExpert.rawValue();
+               },
+
+               /**
+                * @see jQuery.valueview.Expert._setRawValue
+                */
+               _setRawValue: function( rawValue ) {
+                       return this._currentExpert.rawValue( rawValue );
+               },
+
+               /**
+                * @see jQuery.valueview.Expert.rawValueCompare
+                */
+               rawValueCompare: function( rawValue ) {
+                       return this._currentExpert.rawValueCompare( rawValue );
+               },
+
+               /**
+                * @see jQuery.valueview.Expert.rawValueCompare
+                */
+               draw: function() {
+                       if( !this._updateExpert() ) {
+                               // Current expert still the right one, no 
update, re-draw current expert.
+                               this._currentExpert.draw();
+                       }
+               },
+
+               /**
+                * @see jQuery.valueview.Expert.focus
+                */
+               focus: function() {
+                       this._currentExpert.focus();
+               },
+
+               /**
+                * @see jQuery.valueview.Expert.blur
+                */
+               blur: function() {
+                       this._currentExpert.blur();
+               }
+       } );
+
+}( dataValues, valueParsers, jQuery, jQuery.valueview ) );
diff --git 
a/ValueView/resources/jquery.valueview/valueview.experts/experts.CommonsMediaType.js
 
b/ValueView/resources/jquery.valueview/valueview.experts/experts.CommonsMediaType.js
new file mode 100644
index 0000000..7c70e3d
--- /dev/null
+++ 
b/ValueView/resources/jquery.valueview/valueview.experts/experts.CommonsMediaType.js
@@ -0,0 +1,76 @@
+/**
+ * @file
+ * @ingroup ValueView
+ * @licence GNU GPL v2+
+ * @author Daniel Werner < daniel.wer...@wikimedia.de >
+ */
+( function( dv, vp, $, vv, wikiUrlencode ) {
+       'use strict';
+
+       /**
+        * Returns an url to a certain file on commons.
+        *
+        * @param {string} file
+        * @returns string
+        */
+       function commonsUrl( file ) {
+               return location.protocol + '//commons.wikimedia.org/wiki/File:' 
+ wikiUrlencode( file );
+       }
+
+       var PARENT = vv.BifidExpert,
+               editableExpert = vv.experts.SuggestedStringValue;
+
+       /**
+        * Valueview expert for adding specialized handling for CommonsMedia 
data type. Without this
+        * more specialized expert, the StringValue expert would be used since 
the CommonsMedia data
+        * type is using the String data value type.
+        * This expert is based on the StringValue expert but will add a 
dropdown for choosing commons
+        * media sources. It will also display the value as a link to commons.
+        *
+        * @since 0.1
+        *
+        * @constructor
+        * @extends jQuery.valueview.experts.StringValue
+        */
+       vv.experts.CommonsMediaType = vv.expert( 'commonsmediatype', PARENT, {
+               /**
+                * @see jQuery.valueview.BifidExpert._editableExpert
+                */
+               _editableExpert: editableExpert,
+
+               /**
+                * @see jQuery.valueview.BifidExpert._editableExpertOptions
+                */
+               _editableExpertOptions: {
+                       suggesterOptions: {
+                               ajax: {
+                                       url: location.protocol + 
'//commons.wikimedia.org/w/api.php',
+                                       params: {
+                                               action: 'opensearch',
+                                               namespace: 6
+                                       }
+                               },
+                               replace: [/^File:/, '']
+                       }
+               },
+
+               /**
+                * @see jQuery.valueview.BifidExpert._staticExpert
+                */
+               _staticExpert: vv.experts.StaticDom,
+
+               /**
+                * @see jQuery.valueview.BifidExpert._staticExpertOptions
+                */
+               _staticExpertOptions: {
+                       domBuilder: function( currentRawValue, viewState ) {
+                               return $( '<a/>', {
+                                       text: currentRawValue,
+                                       href: commonsUrl( currentRawValue )
+                               } );
+                       },
+                       baseExpert: editableExpert
+               }
+       } );
+
+}( dataValues, valueParsers, jQuery, jQuery.valueview, mw.util.wikiUrlencode ) 
);
diff --git 
a/ValueView/resources/jquery.valueview/valueview.experts/experts.StaticDom.js 
b/ValueView/resources/jquery.valueview/valueview.experts/experts.StaticDom.js
new file mode 100644
index 0000000..14e6399
--- /dev/null
+++ 
b/ValueView/resources/jquery.valueview/valueview.experts/experts.StaticDom.js
@@ -0,0 +1,96 @@
+/**
+ * @file
+ * @ingroup ValueView
+ * @licence GNU GPL v2+
+ * @author Daniel Werner < daniel.wer...@wikimedia.de >
+ */
+( function( $, vv ) {
+       'use strict'
+
+       var PARENT = vv.Expert;
+
+       /**
+        * Valueview expert which will display its current value based on an 
injected callback which
+        * is responsible for returning the DOM to be drawed. The DOM should be 
static since this
+        * expert has no further logic required for handling interactive values.
+        *
+        * NOTE: This expert is useful when used as the static part of a 
BifidExpert. It can be used to
+        *  display the value in some specialized form, e.g. as a link or 
formatted text or both mixed.
+        *
+        * @since 0.1
+        *
+        * @constructor
+        * @extends jQuery.valueview.Expert
+        *
+        * @option domBuilder {Function} A callback function called whenever 
the DOM for displaying the
+        *         current raw value is required. First parameter of the 
callback is the current raw
+        *         value of the expert, second parameter is the expert's 
related ViewState object.
+        *
+        * @option baseExpert {Function} Constructor of an expert whose 
"parser" and "rawValueCompare"
+        *         functions will be borrowed. This is required because this 
expert doesn't need to
+        *         know what kind of values it handles.
+        *
+        * TODO: the "baseExpert" function is conceptually not that nice. It is 
required because the
+        *  a static DOM expert doesn't need to know what kind of values it 
handles.
+        */
+       vv.experts.StaticDom = vv.expert( 'staticdom', PARENT, {
+               /**
+                * Current value.
+                * @type {*}
+                */
+               value: null,
+
+               /**
+                * @see jQuery.valueview.Expert.destroy
+                */
+               destroy: function() {
+                       this._value = null;
+                       PARENT.prototype.destroy.call( this );
+               },
+
+               /**
+                * Returns a parser suitable for parsing the raw value returned 
by rawValue().
+                *
+                * @since 0.1
+                * @abstract
+                *
+                * @return valueParsers.Parser
+                */
+               parser: function() {
+                       return this._options.baseExpert.prototype.parser.call( 
this );
+               },
+
+               /**
+                * @see jQuery.valueview.Expert.destroy
+                */
+               _getRawValue: function() {
+                       return this._value;
+               },
+
+               /**
+                * @see jQuery.valueview.Expert.destroy
+                */
+               _setRawValue: function( rawValue ) {
+                       // TODO: this should probably also make use of the 
"baseExpert" since there is no
+                       //  handling of the value at all here.
+                       this._value = rawValue;
+               },
+
+               /**
+                * @see jQuery.valueview.Expert.rawValueCompare
+                */
+               rawValueCompare: function( value1, value2 ) {
+                       return 
this._options.baseExpert.prototype.rawValueCompare.apply( this, arguments );
+               },
+
+               /**
+                * @see jQuery.valueview.Expert.draw
+                */
+               draw: function() {
+                       // Build DOM as specified by callback:
+                       var $customDom = this._options.domBuilder( 
this.rawValue(), this._viewState );
+                       this.$viewPort.empty().append( $customDom );
+               }
+       } );
+
+}( jQuery, jQuery.valueview ) );
diff --git 
a/ValueView/resources/jquery.valueview/valueview.experts/experts.SuggestedStringValue.js
 
b/ValueView/resources/jquery.valueview/valueview.experts/experts.SuggestedStringValue.js
new file mode 100644
index 0000000..d77604a
--- /dev/null
+++ 
b/ValueView/resources/jquery.valueview/valueview.experts/experts.SuggestedStringValue.js
@@ -0,0 +1,66 @@
+/**
+ * @file
+ * @ingroup ValueView
+ * @licence GNU GPL v2+
+ * @author Daniel Werner < daniel.wer...@wikimedia.de >
+ */
+( function( dv, vp, $, vv ) {
+       'use strict';
+
+       var PARENT = vv.experts.StringValue;
+
+       /**
+        * Valueview expert based on StringValue expert but with a jQuery 
suggester loaded for offering
+        * the user auto compleation features.
+        *
+        * @since 0.1
+        *
+        * @constructor
+        * @extends jQuery.valueview.experts.StringValue
+        *
+        * TODO: Implement this as an "extension" for the StringValue expert. 
This could be done by
+        *  adding a system for extensions which get initialized in addition to 
a specific expert.
+        *  Those extensions would also require registration, this should 
probably be done by introducing
+        *  a more complex format for registering an expert plus extensions to 
an expert factory.
+        */
+       vv.experts.SuggestedStringValue = vv.expert( 'suggestedstringvalue', 
PARENT, {
+               /**
+                * @see Query.valueview.experts.StringValue._init
+                */
+               _init: function() {
+                       PARENT.prototype._init.call( this );
+
+                       var notifier = this._viewNotifier,
+                               $input = this.$input;
+
+                       // Initialize Commons Media suggestion dropdown on top 
of string input field:
+                       $input.suggester( this._options.suggesterOptions );
+
+                       // Since we're using the input auto expand, we have to 
update the position of the
+                       // dropdown whenever the input box expands vertically:
+                       $input.eachchange( function( event, oldValue ) {
+                               // TODO/OPTIMIZE: only reposition when 
necessary, i.e. when expanding vertically
+                               $input.data( 'suggester' ).repositionMenu();
+                       } );
+
+                       $input.on( 'suggesterresponse suggesterclose', 
function( event, response ) {
+                               notifier.notify( 'change' ); // here in 
addition to 'eachchange' from StringValue expert
+                               $input.data( 'AutoExpandInput' ).expand();
+
+                       } );
+               },
+
+               /**
+                * @see Query.valueview.experts.StringValue.draw
+                */
+               draw: function() {
+                       PARENT.prototype.draw.call( this );
+
+                       // Make sure suggester is closed in non-edit mode:
+                       if( !this._viewState.isInEditMode() ) {
+                               this.$input.data( 'suggester' ).close();
+                       }
+               }
+       } );
+
+}( dataValues, valueParsers, jQuery, jQuery.valueview ) );
diff --git a/ValueView/resources/mw.ext.valueView.js 
b/ValueView/resources/mw.ext.valueView.js
index b223d0d..6153977 100644
--- a/ValueView/resources/mw.ext.valueView.js
+++ b/ValueView/resources/mw.ext.valueView.js
@@ -20,6 +20,11 @@
                vv.experts.StringValue
        );
 
+       expertProvider.registerExpert(
+               dt.getDataType( 'commonsMedia' ),
+               vv.experts.CommonsMediaType
+       );
+
        /**
         * Object representing the MeidaWiki "ValueView" extension.
         *

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ibf778f2ab544ec51f8f9574eb32aea82a5707caf
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/DataValues
Gerrit-Branch: master
Gerrit-Owner: Daniel Werner <daniel.wer...@wikimedia.de>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to