Henning Snater has uploaded a new change for review.

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


Change subject: Refactored valueview preview into its own widget
......................................................................

Refactored valueview preview into its own widget

Change-Id: Iba8882b53eebab0544c69e308c91149c99d6417c
---
M ValueView/ValueView.resources.php
M ValueView/ValueView.tests.qunit.php
A ValueView/resources/jquery.valueview/jquery.valueview.preview.css
A ValueView/resources/jquery.valueview/jquery.valueview.preview.js
M ValueView/resources/jquery.valueview/valueview.css
M ValueView/resources/jquery.valueview/valueview.experts/experts.TimeInput.js
A ValueView/tests/qunit/jquery.valueview/jquery.valueview.preview.tests.js
7 files changed, 231 insertions(+), 60 deletions(-)


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

diff --git a/ValueView/ValueView.resources.php 
b/ValueView/ValueView.resources.php
index 35f5cfd..165004e 100644
--- a/ValueView/ValueView.resources.php
+++ b/ValueView/ValueView.resources.php
@@ -210,6 +210,7 @@
                                'jquery.ui.inputextender',
                                'jquery.ui.listrotator',
                                'jquery.ui.toggler',
+                               'jquery.valueview.preview',
                        ),
                        'messages' => array(
                                'valueview-expert-advancedadjustments',
@@ -248,6 +249,20 @@
                                'jquery.ui.suggester',
                        ),
                ),
+
+               'jquery.valueview.preview' => $moduleTemplate + array(
+                       'scripts' => array(
+                               'jquery.valueview/jquery.valueview.preview.js',
+                       ),
+                       'dependencies' => array(
+                               'jquery.ui.widget',
+                       ),
+                       'messages' => array(
+                               'valueview-preview-label',
+                               'valueview-preview-novalue',
+                       ),
+               )
+
        );
 
 } );
diff --git a/ValueView/ValueView.tests.qunit.php 
b/ValueView/ValueView.tests.qunit.php
index f1c38f1..ee4fd3b 100644
--- a/ValueView/ValueView.tests.qunit.php
+++ b/ValueView/ValueView.tests.qunit.php
@@ -99,6 +99,15 @@
                        ),
                ),
 
+               'jquery.valueview.preview.tests' => array(
+                       'scripts' => array(
+                               
"$bp/jquery.valueview/jquery.valueview.preview.tests.js",
+                       ),
+                       'dependencies' => array(
+                               'jquery.valueview.preview',
+                       ),
+               ),
+
                'jquery.valueview.MockViewState.tests' => array(
                        'scripts' => array(
                                
"$bp/jquery.valueview/valueview.MockViewState.tests.js",
diff --git a/ValueView/resources/jquery.valueview/jquery.valueview.preview.css 
b/ValueView/resources/jquery.valueview/jquery.valueview.preview.css
new file mode 100644
index 0000000..e4103fc
--- /dev/null
+++ b/ValueView/resources/jquery.valueview/jquery.valueview.preview.css
@@ -0,0 +1,18 @@
+/**
+ * Styles for valueview preview widget
+ *
+ * @since 0.1
+ * @file
+ * @ingroup ValueView
+ *
+ * @license GNU GPL v2+
+ * @author H. Snater < [email protected] >
+ */
+
+.valueview-preview-value {
+       font-size: 119%; /* Reset to default 100% */
+}
+
+.valueview-preview-novalue {
+       font-style: italic;
+}
diff --git a/ValueView/resources/jquery.valueview/jquery.valueview.preview.js 
b/ValueView/resources/jquery.valueview/jquery.valueview.preview.js
new file mode 100644
index 0000000..248c8fd
--- /dev/null
+++ b/ValueView/resources/jquery.valueview/jquery.valueview.preview.js
@@ -0,0 +1,90 @@
+/**
+ * Valueview preview widget
+ *
+ * @licence GNU GPL v2+
+ * @author H. Snater < [email protected] >
+ *
+ * @option {jQuery} [$input] Input element node. If specified, the preview 
will not be updated when
+ *         the input element is cleared, e.g. if the input will be hidden, it 
is not necessary to
+ *         update the value.
+ *
+ * @dependency jQuery.Widget
+ * @dependency mediaWiki
+ */
+( function( $, mw ) {
+       'use strict';
+
+       $.widget( 'valueview.preview', {
+
+               /**
+                * Additional options.
+                * @type {Object}
+                */
+               options: {
+                       $input: null
+               },
+
+               /**
+                * The node of the previewed value.
+                * @type {jQuery}
+                */
+               $value: null,
+
+               /**
+                * @see jQuery.Widget._create
+                */
+               _create: function() {
+                       this.element
+                       .addClass( this.widgetBaseClass )
+                       .append(
+                               $( '<div/>' )
+                               .addClass( this.widgetBaseClass + '-label' )
+                               .text( mw.msg( 'valueview-preview-label' ) )
+                       );
+
+                       this.$value = $( '<div/>' )
+                       .addClass( this.widgetBaseClass + '-value' )
+                       .appendTo( this.element );
+
+                       this.update( null );
+               },
+
+               /**
+                * @see jQuery.Widget.destroy
+                */
+               destroy: function() {
+                       this.$value.remove();
+
+                       this.element
+                       .children( this.widgetBaseClass + '-label' )
+                       .removeClass( this.widgetBaseClass );
+
+                       $.Widget.prototype.destroy.call( this );
+               },
+
+               /**
+                * Updates the previewed value.
+                *
+                * @param {string|null} value
+                */
+               update: function( value ) {
+                       // No need to update the preview when the input value 
is clear(ed) since the preview
+                       // will be hidden anyway.
+                       if( this.options.$input && this.options.$input.val() 
=== '' ) {
+                               return;
+                       }
+
+                       if( value === null ) {
+                               this.$value
+                               .addClass( this.widgetBaseClass + '-novalue' )
+                               .text( mw.msg( 'valueview-preview-novalue' ) );
+                       } else {
+                               this.$value
+                               .removeClass( this.widgetBaseClass + '-novalue' 
)
+                               .text( value );
+                       }
+               }
+
+       } );
+
+} )( jQuery, mediaWiki );
diff --git a/ValueView/resources/jquery.valueview/valueview.css 
b/ValueView/resources/jquery.valueview/valueview.css
index faa1393..e778c94 100644
--- a/ValueView/resources/jquery.valueview/valueview.css
+++ b/ValueView/resources/jquery.valueview/valueview.css
@@ -44,11 +44,3 @@
        /* make sure input box which still is inside a doesn't display text as 
links */
        color: inherit;
 }
-
-.valueview-preview-value {
-       font-size: 119%; /* Reset to default 100% */
-}
-
-.valueview-preview-novalue {
-       font-style: italic;
-}
diff --git 
a/ValueView/resources/jquery.valueview/valueview.experts/experts.TimeInput.js 
b/ValueView/resources/jquery.valueview/valueview.experts/experts.TimeInput.js
index e43ce7c..5d2a36e 100644
--- 
a/ValueView/resources/jquery.valueview/valueview.experts/experts.TimeInput.js
+++ 
b/ValueView/resources/jquery.valueview/valueview.experts/experts.TimeInput.js
@@ -39,16 +39,10 @@
                _newValue: null,
 
                /**
-                * The preview section's node.
-                * @type {jQuery}
+                * The preview widget.
+                * @type {jQuery.valueview.preview}
                 */
-               $preview: null,
-
-               /**
-                * The node of the previewed input value.
-                * @type {jQuery}
-                */
-               $previewValue: null,
+               preview: null,
 
                /**
                 * Container node for precision input and label.
@@ -85,20 +79,6 @@
                 */
                _init: function() {
                        var self = this;
-
-                       // TODO: Move preview out of the specific expert to a 
more generic place
-                       this.$preview = $( '<div/>' )
-                       .addClass( 'valueview-preview' )
-                       .append(
-                               $( '<div/>' )
-                               .addClass( 'valueview-preview-label' )
-                               .text( mw.msg( 'valueview-preview-label' ) )
-                       );
-
-                       this.$previewValue = $( '<div/>' )
-                       .addClass( 'valueview-preview-value' )
-                       .text( mw.msg( 'valueview-preview-novalue' ) )
-                       .appendTo( this.$preview );
 
                        this.$precisionContainer = $( '<div/>' )
                        .addClass( this.uiBaseClass + '-precisioncontainer' )
@@ -178,11 +158,15 @@
                                type: 'text',
                                'class': this.uiBaseClass + '-input 
valueview-input'
                        } )
-                       .appendTo( this.$viewPort )
-                       .eachchange( function( event, oldValue ) {
+                       .appendTo( this.$viewPort );
+
+                       var $preview = $( '<div/>' ).preview( { $input: 
this.$input } );
+                       this.preview = $preview.data( 'preview' );
+
+                       this.$input.eachchange( function( event, oldValue ) {
                                var value = self.$input.data( 'timeinput' 
).value();
                                if( oldValue === '' && value === null || 
self.$input.val() === '' ) {
-                                       self._updatePreview( null );
+                                       self._updatePreview();
                                        self._updateCalendarHint();
                                }
                        } )
@@ -190,7 +174,7 @@
                        // TODO: Move input extender out of here to a more 
generic place since it is not
                        // TimeInput specific.
                        .inputextender( {
-                               content: [ this.$preview, this.$calendarhint, 
$toggler, this.$precisionContainer, this.$calendarContainer ],
+                               content: [ $preview, this.$calendarhint, 
$toggler, this.$precisionContainer, this.$calendarContainer ],
                                initCallback: function() {
                                        self.$precision.data( 'listrotator' 
).initWidths();
                                        self.$calendar.data( 'listrotator' 
).initWidths();
@@ -201,7 +185,6 @@
                                }
                        } )
                        .on( 'timeinputupdate.' + this.uiBaseClass, function( 
event, value ) {
-                               self._updatePreview( value );
                                self._updateCalendarHint( value );
                                if( value && value.isValid() ) {
                                        self.$precision.data( 'listrotator' 
).rotate( value.precision() );
@@ -209,6 +192,7 @@
                                }
                                self._newValue = false; // value, not yet 
handled by draw(), is outdated now
                                self._viewNotifier.notify( 'change' );
+                               self._updatePreview();
                        } );
 
                },
@@ -227,8 +211,9 @@
 
                        this.$calendarhint.remove();
 
-                       this.$previewValue.remove();
-                       this.$preview.remove();
+                       var previewElement = this.preview.element;
+                       this.preview.destroy();
+                       previewElement.remove();
 
                        this.$input.data( 'inputextender' ).destroy();
                        this.$input.data( 'timeinput' ).destroy();
@@ -267,7 +252,7 @@
                        value = new Time( this.$input.val(), options );
 
                        this._setRawValue( value );
-                       this._updatePreview( value );
+                       this._updatePreview();
                        this._updateCalendarHint( value );
                        this._viewNotifier.notify( 'change' );
 
@@ -275,27 +260,11 @@
                },
 
                /**
-                * Updates the input value's preview.
-                * @since 0.1
-                *
-                * @param {time.Time|null} value
+                * Updates the preview.
                 */
-               _updatePreview: function( value ) {
-                       // No need to update the preview when the input value 
is clear(ed) since the preview
-                       // will be hidden anyway.
-                       if( this.$input.val() === '' ) {
-                               return;
-                       }
-
-                       if( value === null ) {
-                               this.$previewValue
-                               .addClass( 'valueview-preview-novalue' )
-                               .text( mw.msg( 'valueview-preview-novalue' ) )
-                       } else {
-                               this.$previewValue
-                               .removeClass( 'valueview-preview-novalue' )
-                               .text( value.text() )
-                       }
+               _updatePreview: function() {
+                       var rawValue = this._getRawValue();
+                       this.preview.update( ( rawValue ) ? rawValue.text() : 
null );
                },
 
                /**
@@ -392,13 +361,13 @@
 
                        if( this._newValue !== false ) {
                                this.$input.data( 'timeinput' ).value( 
this._newValue );
-                               this._updatePreview( this._newValue );
                                this._updateCalendarHint( this._newValue );
                                if( this._newValue !== null ) {
                                        this.$precision.data( 'listrotator' 
).value( this._newValue.precision() );
                                        this.$calendar.data( 'listrotator' 
).value( this._newValue.calendarText() );
                                }
                                this._newValue = false;
+                               this._updatePreview();
                        }
                },
 
diff --git 
a/ValueView/tests/qunit/jquery.valueview/jquery.valueview.preview.tests.js 
b/ValueView/tests/qunit/jquery.valueview/jquery.valueview.preview.tests.js
new file mode 100644
index 0000000..2329155
--- /dev/null
+++ b/ValueView/tests/qunit/jquery.valueview/jquery.valueview.preview.tests.js
@@ -0,0 +1,78 @@
+/**
+ * @since 0.1
+ * @ingroup ValueView
+ *
+ * @licence GNU GPL v2+
+ * @author H. Snater < [email protected] >
+ */
+
+( function( $, QUnit ) {
+       'use strict';
+
+       /**
+        * Factory for creating a valueview preview widget suitable for testing.
+        *
+        * @param {Object} options
+        * @return {jQuery.valueview.preview}
+        */
+       var newTestPreview = function( options ) {
+               if( !options ) {
+                       options = $.extend( {}, options );
+               }
+
+               var $div = $( '<div/>' )
+                       .addClass( 'test_preview' )
+                       .appendTo( 'body' )
+                       .preview( options );
+
+               return $div.data( 'preview' );
+       };
+
+       QUnit.module( 'jquery.valueview.preview', QUnit.newMwEnvironment( {
+               teardown: function() {
+                       $( '.test_preview' ).each( function( i, node ) {
+                               if( $( node ).data( 'preview' ) ) {
+                                       $( node ).data( 'preview' ).destroy();
+                               }
+                               $( node ).remove();
+                       } );
+               }
+       } ) );
+
+       QUnit.test( 'Initialization and destruction', 3, function( assert ) {
+               var preview = newTestPreview(),
+                       widgetBaseClass = preview.widgetBaseClass;
+
+               assert.equal(
+                       $( '.test_preview' ).data( 'preview' ),
+                       preview,
+                       'Initialized widget.'
+               );
+
+               preview.destroy();
+
+               assert.ok(
+                       $( '.test_preview' ).data( 'preview' ) === undefined,
+                       'Destroyed widget.'
+               );
+
+               assert.equal(
+                       $( '.' + widgetBaseClass + '-value' ).length,
+                       0,
+                       'Removed extension node from DOM.'
+               );
+       } );
+
+       QUnit.test( 'Update value', 1, function( assert ) {
+               var preview = newTestPreview();
+
+               preview.update( 'test' );
+
+               assert.equal(
+                       preview.$value.text(),
+                       'test',
+                       'Updated preview.'
+               );
+       } );
+
+}( jQuery, QUnit ) );

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Iba8882b53eebab0544c69e308c91149c99d6417c
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/DataValues
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