Henning Snater has uploaded a new change for review.

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

Change subject: snakview: Refactored drawing mechanism
......................................................................

snakview: Refactored drawing mechanism

- untangled draw() / drawProperty() relationship moving Property specific logic 
out of draw()
- drawProperty() does not (re)render when previously generated HTML is detected
- Property and Snak type are not (re)rendered when they are locked and there 
previously generated
  HTML is detected.
- Made updateVariation() public. There is no sense in being able to (re)draw 
the Variation without
  being able to update it.
- Removed parameter from updateVariation() as it is supposed to always reflect 
the current value.
- Removed parameter from drawProperty as it is supposed to always reflect the 
current value.
- 88425

Change-Id: If45c707c08ba710fe5fec456fef29c2b60586dae
---
M lib/resources/jquery.wikibase/snakview/snakview.js
M lib/resources/jquery.wikibase/snakview/snakview.variations.Value.js
2 files changed, 112 insertions(+), 61 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikibase 
refs/changes/18/189018/1

diff --git a/lib/resources/jquery.wikibase/snakview/snakview.js 
b/lib/resources/jquery.wikibase/snakview/snakview.js
index 1eb5eb9..2d7fecc 100644
--- a/lib/resources/jquery.wikibase/snakview/snakview.js
+++ b/lib/resources/jquery.wikibase/snakview/snakview.js
@@ -162,7 +162,8 @@
 
                this._cachedValues = {};
 
-               this.value( this.options.value );
+               this.updateVariation();
+               this.draw();
 
                if( this.option( 'autoStartEditing' ) && !this.snak() ) {
                        // If no Snak is represented, offer UI to build one.
@@ -197,10 +198,7 @@
                var response = PARENT.prototype._setOption.apply( this, 
arguments );
 
                if( key === 'value' ) {
-                       value = this.value();
-
-                       this._updateVariation( value );
-
+                       this.updateVariation();
                        this.draw();
                } else if( key === 'disabled' ) {
                        var propertySelector = this._getPropertySelector(),
@@ -253,7 +251,7 @@
                        // remove out-dated variations
                        if( self._variation ) {
                                self.drawSnakTypeSelector();
-                               self._updateVariation( self.value() );
+                               self.updateVariation();
                                self.drawVariation();
                                self._trigger( 'change' );
                        }
@@ -265,7 +263,7 @@
                        );
 
                        self.options.entityStore.get( entityId ).done( 
function( entity ) {
-                               self._updateVariation( self.value() );
+                               self.updateVariation();
                                self.drawSnakTypeSelector();
                                self.drawVariation();
 
@@ -640,18 +638,15 @@
        },
 
        /**
-        * Checks whether the `Snak` type has been changed by the user and will 
build a new `Variation`
-        * object for that type if necessary.
-        * @private
-        * @since 0.4
-        *
-        * @param {Object} value (In)complete `Snak` serialization.
+        * Updates the `Variation` according to the widget's current value.
+        * @since 0.5
         */
-       _updateVariation: function( value ) {
-               var variationsFactory = $.wikibase.snakview.variations,
+       updateVariation: function() {
+               var value = this.value(),
+                       propertyId = value ? value.property : null,
                        snakType = value ? value.snaktype : null,
-                       VariationConstructor = snakType ? 
variationsFactory.getVariation( snakType ) : null,
-                       propertyId = value ? value.property : null;
+                       variationsFactory = $.wikibase.snakview.variations,
+                       VariationConstructor = snakType ? 
variationsFactory.getVariation( snakType ) : null;
 
                if( this._variation
                        && ( !propertyId || this._variation.constructor !== 
VariationConstructor )
@@ -701,82 +696,134 @@
        },
 
        /**
-        * Renders the `snakview`'s current state considering edit mode, 
current value, etc..
+        * (Re)renders the widget.
         * @since 0.4
         */
        draw: function() {
-               var self = this,
-                       value = this.value(),
-                       propertyId = value ? value.property : null;
-
-               // NOTE: Order of these shouldn't matter; If for any reasons 
draw functions start changing
-               //  the outcome of the variation (or Snak type), then something 
must be incredibly wrong!
-               if( propertyId ) {
-                       this.options.entityStore.get( propertyId ).done( 
function( fetchedProperty ) {
-                               self.drawProperty(
-                                       fetchedProperty ? 
fetchedProperty.getContent() : null,
-                                       fetchedProperty ? 
fetchedProperty.getTitle() : null
-                               );
-                       } );
-               } else {
-                       this.drawProperty( null, null );
-               }
+               this.drawProperty();
                this.drawSnakTypeSelector();
                this.drawVariation();
        },
 
        /**
-        * Ensures the current `Snak`'s `Property` is displayed properly. If no 
`Snak` is set, the input
-        * form for specifying the `Snak`'s `Property` will be rendered.
-        * @since 0.4
+        * (Re)renders the Property DOM structure according to the current 
value. The `Property` DOM
+        * is not (re-)rendered if changing the `Property` is locked via the 
`locked` option and
+        * previously generated HTML is detected.
+        * @since 0.5
         *
-        * @param {wikibase.datamodel.Property|null} property
-        * @param {mediawiki.Title|null} title Only supposed to be `null` if 
`property` is `null`.
+        * @return {Object} jQuery.Promise
+        * @return {Function} return.done
+        * @return {Function} return.fail
         */
-       drawProperty: function( property, title ) {
-               var $propertyDom,
-                       value = this.value(),
-                       propertyId = value ? value.property : null;
+       drawProperty: function() {
+               var self = this,
+                       deferred = $.Deferred(),
+                       propertyId = this.value().property;
+
+               if( this.options.locked.property && 
this.$property.contents().length ) {
+                       return deferred.resolve().promise();
+               }
+
+               this._getPropertyDOM( propertyId )
+               .done( function( $property ) {
+                       self.$property.empty().append( $property );
+                       deferred.resolve();
+               } )
+               .fail( function() {
+                       self.$property.empty().text( propertyId );
+                       deferred.reject();
+               } );
+
+               return deferred.promise();
+       },
+
+       /**
+        * Retrieves the DOM structure representing the `Property` of the 
`Snak` represented by the
+        * `snakview`.
+        * @private
+        *
+        * @param {string} [propertyId]
+        * @return {Object} jQuery.Promise
+        * @return {Function} return.done
+        * @return {jQuery} return.$property
+        * @return {Function} return.fail
+        */
+       _getPropertyDOM: function( propertyId ) {
+               var self = this,
+                       deferred = $.Deferred();
+
+               if( propertyId ) {
+                       this.options.entityStore.get( propertyId )
+                       .done( function( fetchedProperty ) {
+                               deferred.resolve( self._createPropertyDOM(
+                                       fetchedProperty ? 
fetchedProperty.getContent() : undefined,
+                                       fetchedProperty ? 
fetchedProperty.getTitle() : undefined
+                               ) );
+                       } )
+                       .fail( deferred.reject );
+               } else {
+                       deferred.resolve( this._createPropertyDOM() );
+               }
+
+               return deferred.promise();
+       },
+
+       /**
+        * Creates the DOM structure specific for a `Property`-`Title` 
combination, a generic DOM
+        * structure or an input element if parameters are omitted.
+        * @private
+        *
+        * @param {wikibase.datamodel.Property|string} [property] `Property` 
object or `Property` id.
+        *        Returns generic DOM structure if omitted.
+        * @param {mediawiki.Title} [title]
+        * @return {jQuery}
+        */
+       _createPropertyDOM: function( property, title ) {
+               var $propertyDom;
 
                if( this.options.locked.property || !this.isInEditMode() ) {
-                       // property set and can't be changed afterwards, only 
display label
-                       $propertyDom = property
+                       // Property is set already and cannot be changed, 
display label only:
+                       $propertyDom = property instanceof wb.datamodel.Property
                                ? wb.utilities.ui.buildLinkToEntityPage( 
property, title )
                                // shouldn't usually happen, only in non-edit 
mode, while no Snak is set:
-                               : wb.utilities.ui.buildMissingEntityInfo( 
propertyId, wb.datamodel.Property );
+                               : wb.utilities.ui.buildMissingEntityInfo( 
property, wb.datamodel.Property );
                } else {
-                       // no property set for this Snak, serve edit view to 
specify it:
+                       // No Property set for this Snak, serve edit view to 
specify it:
                        var propertySelector = this._getPropertySelector(),
-                               propertyLabel = 
wb.utilities.ui.buildPrettyEntityLabelText( property );
+                               propertyLabel = property instanceof 
wb.datamodel.Property
+                                       ? 
wb.utilities.ui.buildPrettyEntityLabelText( property )
+                                       : property;
 
                        // TODO: use selectedEntity() or other command to set 
selected entity in both cases!
-                       if( propertySelector && property ) {
+                       if( propertySelector ) {
                                // property selector in DOM already, just 
replace current value
                                var currentValue = 
propertySelector.widget().val();
                                // Impose case-insensitivity:
                                if( propertyLabel.toLowerCase() !== 
currentValue.toLocaleLowerCase() ) {
                                        propertySelector.widget().val( 
propertyLabel );
                                }
-                               return;
-                       } else if( !propertySelector ) {
-                               // Create property selector and set value:
+                       } else {
                                $propertyDom = 
this._buildPropertySelector().val( propertyLabel );
 
                                // propagate snakview state:
                                $propertyDom.data( 'entityselector' ).option( 
'disabled', this.options.disabled );
-                       } else {
-                               return;
                        }
                }
 
-               this.$property.empty().append( $propertyDom );
+               return $propertyDom;
        },
 
        /**
-        * Updates the `snaktypeselector` for choosing the `Snak` type.
+        * Updates the `SnakTypeSelector` for choosing the `Snak` type. The 
`SnakTypeSelector` DOM
+        * is not (re-)rendered if changing the `Snak` type is locked via the 
`locked` option and
+        * previously generated HTML is detected.
         * @since 0.4
         */
        drawSnakTypeSelector: function() {
+               if( this.options.locked.snaktype && 
this.$snakTypeSelector.contents().length ) {
+                       return;
+               }
+
                var snakTypes = 
$.wikibase.snakview.variations.getCoveredSnakTypes(),
                        selector = this._getSnakTypeSelector();
 
@@ -846,7 +893,7 @@
                                // NOTE: instead of doing this here and 
checking everywhere whether this._variation
                                //  is set, we could as well use variations for 
displaying system messages like
                                //  this, e.g. having a UnsupportedSnakType 
variation which is not registered for a
-                               //  specific snak type but is known to 
_updateVariation().
+                               //  specific snak type but is known to 
updateVariation().
                        }
                }
        },
@@ -871,7 +918,7 @@
 
                // bind user interaction on selector to snakview's state:
                $anchor.on( changeEvent + '.' + this.widgetName, function( 
event ) {
-                       self._updateVariation( self.value() );
+                       self.updateVariation();
                        self.drawVariation();
                        if( self._variation ) {
                                self._variation.focus();
diff --git 
a/lib/resources/jquery.wikibase/snakview/snakview.variations.Value.js 
b/lib/resources/jquery.wikibase/snakview/snakview.variations.Value.js
index ceaff79..c1fe35a 100644
--- a/lib/resources/jquery.wikibase/snakview/snakview.variations.Value.js
+++ b/lib/resources/jquery.wikibase/snakview/snakview.variations.Value.js
@@ -20,7 +20,7 @@
        MODULE.variation( wb.datamodel.PropertyValueSnak, PARENT, {
                /**
                 * The value view widget object or null if property's data type 
isn't supported.
-                * @type jQuery.valueview.Widget
+                * @type {jQuery.valueview|null}
                 */
                _valueView: null,
 
@@ -356,14 +356,18 @@
                 * @inheritdoc
                 */
                disable: function() {
-                       this._valueView.disable();
+                       if( this._valueView ) {
+                               this._valueView.disable();
+                       }
                },
 
                /**
                 * @inheritdoc
                 */
                enable: function() {
-                       this._valueView.enable();
+                       if( this._valueView ) {
+                               this._valueView.enable();
+                       }
                },
 
                /*

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: If45c707c08ba710fe5fec456fef29c2b60586dae
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Henning Snater <[email protected]>

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

Reply via email to