Daniel Werner has uploaded a new change for review.
https://gerrit.wikimedia.org/r/79147
Change subject: toggler & inputextender: Replaced "animationstep" events with
"animation" event
......................................................................
toggler & inputextender: Replaced "animationstep" events with "animation" event
This is done by using jQuery.fn.animateWithEvent. Should give a little
performance boost during
animation executions since only one event will be triggered and bubble up the
DOM per animation
(before, an "animationstep" event got fired for each animation step and on
completion, though
using different parameters depending on the occasion).
- Allow for greater flexibility when using the event, extensions such as
widgets can now hook into
all animation stages.
- Resolved the ugliness of jQuery.ui.toggler specific handling in
jQuery.ui.inputextender.
- Introduces another new event for inputextender, "contentanimation" which
fires on the widget in
case the new "contentAnimationEvents" option is specified with the name of an
event triggered
on the inputexter's extension node.
Change-Id: If57ee1eea13d1d016915b8e06b8e9cea05c63b5e
---
M ValueView/ValueView.resources.mw.php
M ValueView/resources/jquery.ui/jquery.ui.inputextender.js
M ValueView/resources/jquery.ui/jquery.ui.toggler.js
M
ValueView/resources/jquery.valueview/valueview.experts/experts.GlobeCoordinateInput.js
M ValueView/resources/jquery.valueview/valueview.experts/experts.TimeInput.js
M ValueView/tests/qunit/jquery.ui/jquery.ui.inputextender.tests.js
6 files changed, 83 insertions(+), 64 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/DataValues
refs/changes/47/79147/1
diff --git a/ValueView/ValueView.resources.mw.php
b/ValueView/ValueView.resources.mw.php
index f4bd0ab..0286208 100644
--- a/ValueView/ValueView.resources.mw.php
+++ b/ValueView/ValueView.resources.mw.php
@@ -135,6 +135,7 @@
'jquery.eachchange',
'jquery.ui.position',
'jquery.ui.widget',
+ 'jquery.animateWithEvent',
),
),
@@ -147,6 +148,7 @@
),
'dependencies' => array(
'jquery.ui.widget',
+ 'jquery.animateWithEvent',
),
),
diff --git a/ValueView/resources/jquery.ui/jquery.ui.inputextender.js
b/ValueView/resources/jquery.ui/jquery.ui.inputextender.js
index 1df5bc2..e897667 100644
--- a/ValueView/resources/jquery.ui/jquery.ui.inputextender.js
+++ b/ValueView/resources/jquery.ui/jquery.ui.inputextender.js
@@ -20,13 +20,19 @@
* hidden when the associated input element is empty.
* Default value: true
*
- * @event animationstep: While the input extender's extension is being
animated, this event is
- * triggered on each animation step. The event forwards the parameters
received from the
- * animation's "step" callback. However, when the animation is
finished, the event is
- * triggered without the second and third parameter.
- * (1) {jQuery.Event}
- * (2) {number|undefined} [now]
- * (3) {jQuery.Tween|undefined} [tween]
+ * @option {string} [contentAnimationEvents] One or more events (separated
with spaces) which imply
+ * that the input extenders extension's content is about to be
animated. Those events should
+ * give a jQuery.AnimationEvent object as their event object. If this
is the case and the
+ * event bubbles up to the input extender's extension node, then this
will trigger the
+ * "contentanimation" event on the widget node.
+ *
+ * @event animation: Triggered at the beginning of an animation of the input's
extension.
+ * (1) {jQuery.AnimationEvent} animationEvent
+ *
+ * @event contentanimation: Triggered at the beginning of an animation of the
extender's
+ * extension content. Depends on the "contentAnimationEvents" option.
+ * (1) {jQuery.AnimationEvent} animationEvent The animation event gets
passed on from the
+ * event within the input extender's extension causing the
"contentanimation" event.
*
* @dependency jQuery.Widget
* @dependency jQuery.eachchange
@@ -77,6 +83,7 @@
*/
options: {
content: [],
+ contentAnimationEvents: '',
initCallback: null,
hideWhenInputEmpty: true,
position: {
@@ -218,7 +225,7 @@
/**
* Shows the extension.
*
- * @param {Function} [callback] Invoked as soon as the contents
are visible.
+ * @param {Function} [callback] Invoked as soon as the
extension's show animation is done.
*/
showExtension: function( callback ) {
if( !this._isExtended ) {
@@ -230,7 +237,7 @@
/**
* Hides the extension.
*
- * @param {Function} [callback] Invoked as soon as the contents
are hidden.
+ * @param {Function} [callback] Invoked as soon as the
extension's hide animation is done.
*/
hideExtension: function( callback ) {
if( this._isExtended ) {
@@ -273,12 +280,6 @@
/**
* Draws the widget.
- *
- * @param {Function} [callback] For private usage only.
- * TODO: Get rid of "callback", introduce some sort of
"animationstart" event instead,
- * offering an object allowing to register callback that will
be given into the animation's
- * options. show/hideExtension can then do a .one() event
registration for that one and
- * register their callback there.
*/
draw: function( /* private: */ callback ) {
this.element[ this._isExtended ? 'addClass' :
'removeClass' ](
@@ -300,7 +301,6 @@
this.$extension = $extension =
this._buildExtension();
$extension.appendTo( $( 'body' ) );
- // TODO
if( $.isFunction( this.options.initCallback ) )
{
$extension.show();
this.options.initCallback.call( this,
$extension );
@@ -337,37 +337,43 @@
this.$extension.css( 'opacity', '1' );
}
- this.$extension.stop( true ).fadeIn( {
- duration: 150,
- step: function( now, tween ) {
- self._trigger( 'animationstep', null, [
now, tween ] );
- },
- complete: function() {
- if( $.isFunction( callback ) ) {
- callback();
+ this.$extension.stop( true ).animateWithEvent(
+ 'extensionexpansion',
+ 'fadeIn',
+ {
+ duration: 150,
+ complete: function() {
+ if( $.isFunction( callback ) ) {
+ callback();
+ }
}
- self._trigger( 'animationstep' );
+ },
+ function( animationEvent ) {
+ self._trigger( 'animation',
animationEvent );
}
- } );
+ );
inputExtendersWithVisibleExtension.add( this );
},
_drawExtensionRemoval: function( callback ) {
var self = this;
- this.$extension.stop( true ).fadeOut( {
- duration: 150,
- step: function( now, tween ) {
- self._trigger( 'animationstep', null, [
now, tween ] );
- },
- complete: function() {
-
inputExtendersWithVisibleExtension.remove( this );
- if( $.isFunction( callback ) ) {
- callback();
+ this.$extension.stop( true ).animateWithEvent(
+ 'extensionremoval',
+ 'fadeOut',
+ {
+ duration: 150,
+ complete: function() {
+
inputExtendersWithVisibleExtension.remove( self );
+ if( $.isFunction( callback ) ) {
+ callback();
+ }
}
- self._trigger( 'animationstep' );
+ },
+ function( animationEvent ) {
+ self._trigger( 'animation',
animationEvent );
}
- } );
+ );
},
/**
@@ -410,10 +416,8 @@
self.showExtension();
}
} )
- // TODO: move this out of here, toggler is not even
used/known to this widget:
- .on( 'toggleranimationstep.' + this.widgetName,
function( event, now, tween ) {
- self._reposition();
- self._trigger( 'animationstep', null, [ now,
tween ] );
+ .on( this.options.contentAnimationEvents, function(
animationEvent ) {
+ self._trigger( 'contentanimation',
animationEvent );
} )
.on( 'keydown.' + this.widgetName, function( event ) {
// Take care of tabbing out of the extension
again:
diff --git a/ValueView/resources/jquery.ui/jquery.ui.toggler.js
b/ValueView/resources/jquery.ui/jquery.ui.toggler.js
index a4b20f8..442a5e7 100644
--- a/ValueView/resources/jquery.ui/jquery.ui.toggler.js
+++ b/ValueView/resources/jquery.ui/jquery.ui.toggler.js
@@ -11,12 +11,8 @@
*
* @option {jQuery} $subject (REQUIRED) The node whose visibility shall be
toggled.
*
- * @event animationstep: While the toggler is being animated, this event is
triggered on each
- * animation step. The event forwards the parameters received from the
animation's "step"
- * callback.
- * (1) {jQuery.Event}
- * (2) {number} now
- * (3) {jQuery.Tween} tween
+ * @event 'animation' Triggered at the beginning of toggler animations.
+ * (1) {jQuery.AnimationEvent} event
*
* @dependency jQuery.Widget
*/
@@ -96,7 +92,8 @@
this.element
.text( '' )
- .addClass( this.widgetBaseClass + ' ' +
this.widgetBaseClass + '-toggle ' + 'ui-state-default' );
+ .addClass( this.widgetBaseClass + ' ' +
this.widgetBaseClass + '-toggle '
+ + 'ui-state-default' );
if( this.element[0].nodeName === 'A' ) {
this.element.attr( 'href',
'javascript:void(0);' );
@@ -110,11 +107,14 @@
if( !self.element.hasClass( 'ui-state-disabled'
) ) {
// Change toggle icon to reflect
current state of toggle subject visibility:
self._reflectVisibilityOnToggleIcon(
true );
- self.options.$subject.slideToggle( {
- step: function( now, tween ) {
- self._trigger(
'animationstep', null, [ now, tween ] );
+
+
self.options.$subject.stop().animateWithEvent(
+ 'togglerstatetransition',
+ 'slideToggle',
+ function( animationEvent ) {
+ self._trigger(
'animation', animationEvent );
}
- } );
+ );
}
} )
.on( 'mouseover.' + this.widgetName, function( event ) {
@@ -151,13 +151,17 @@
makeVisible = !makeVisible;
}
// Add classes displaying rotated icon. If CSS3
transform is available, use it:
- this.$toggleIcon.removeClass( CLS_TOGGLE_HIDDEN + ' ' +
this.widgetBaseClass + '-icon3dtrans ' + CLS_TOGGLE_VISIBLE );
+ this.$toggleIcon.removeClass( CLS_TOGGLE_HIDDEN + ' ' +
CLS_TOGGLE_VISIBLE + ' '
+ + this.widgetBaseClass + '-icon3dtrans' );
+
if( !browserSupportsTransform ) {
this.$toggleIcon.addClass( makeVisible ?
CLS_TOGGLE_VISIBLE : CLS_TOGGLE_HIDDEN );
} else {
- this.$toggleIcon.addClass( this.widgetBaseClass
+ '-icon3dtrans ' + CLS_TOGGLE_VISIBLE );
+ this.$toggleIcon.addClass(
+ this.widgetBaseClass + '-icon3dtrans '
+ CLS_TOGGLE_VISIBLE );
}
- this.element[ makeVisible ? 'removeClass' : 'addClass'
]( this.widgetBaseClass + '-toggle-collapsed' );
+ this.element[ makeVisible ? 'removeClass' : 'addClass'
](
+ this.widgetBaseClass + '-toggle-collapsed' );
},
/**
diff --git
a/ValueView/resources/jquery.valueview/valueview.experts/experts.GlobeCoordinateInput.js
b/ValueView/resources/jquery.valueview/valueview.experts/experts.GlobeCoordinateInput.js
index 78f2c67..13c47dd 100644
---
a/ValueView/resources/jquery.valueview/valueview.experts/experts.GlobeCoordinateInput.js
+++
b/ValueView/resources/jquery.valueview/valueview.experts/experts.GlobeCoordinateInput.js
@@ -79,12 +79,13 @@
} )
.appendTo( this.$viewPort )
.eachchange( function( event, oldValue ) {
- this._viewNotifier.notify( 'change' );
+ self._viewNotifier.notify( 'change' );
} )
.inputextender( {
initCallback: function( $extension ) {
self._initInputExtender( $extension );
- }
+ },
+ contentAnimationEvents: 'toggleranimation'
} );
},
@@ -187,6 +188,8 @@
inputExtender.destroy();
}
+ this.$input.off( 'eachchange' );
+
this.$input = null;
this.$precision = null;
this.$precisionContainer = null;
diff --git
a/ValueView/resources/jquery.valueview/valueview.experts/experts.TimeInput.js
b/ValueView/resources/jquery.valueview/valueview.experts/experts.TimeInput.js
index 0ea0e56..9f181b6 100644
---
a/ValueView/resources/jquery.valueview/valueview.experts/experts.TimeInput.js
+++
b/ValueView/resources/jquery.valueview/valueview.experts/experts.TimeInput.js
@@ -112,7 +112,8 @@
.inputextender( {
initCallback: function( $extension ) {
self._initInputExtender( $extension );
- }
+ },
+ contentAnimationEvents: 'toggleranimation'
} )
.on( 'timeinputupdate.' + this.uiBaseClass, function(
event, value ) {
self._updateCalendarHint( value );
diff --git a/ValueView/tests/qunit/jquery.ui/jquery.ui.inputextender.tests.js
b/ValueView/tests/qunit/jquery.ui/jquery.ui.inputextender.tests.js
index 717ee14..237b05a 100644
--- a/ValueView/tests/qunit/jquery.ui/jquery.ui.inputextender.tests.js
+++ b/ValueView/tests/qunit/jquery.ui/jquery.ui.inputextender.tests.js
@@ -57,7 +57,8 @@
* after the promise got resolved. If the promise gets rejected,
then the hide action
* will never be performed.
* @param {Object} callbacks
- * @return {jQuery.Promise} resolved after final hiding is done.
+ * @return {jQuery.Promise} Resolved after final hiding is done. Can be
rejected in case a
+ * hideControl has been injected and gets rejected.
*/
function showAndHideExtensionAgain( instance, hideControl, callbacks ) {
var deferred = $.Deferred();
@@ -81,6 +82,9 @@
QUnit.stop(); // wait for hideExtension()
callback *2*
} )
+ .fail( function() {
+ deferred.reject();
+ } )
.always( function() {
QUnit.start(); // *1*
} );
@@ -95,8 +99,9 @@
QUnit.module( 'jquery.ui.inputextender', {
teardown: function() {
$( '.test_inputextender' ).each( function( i, node ) {
- if( $( node ).data( 'inputextender' ) ) {
- $( node ).data( 'inputextender'
).destroy();
+ var inputextender = $( node ).data(
'inputextender' );
+ if( inputextender ) {
+ inputextender.destroy();
}
$( node ).remove();
} );
@@ -106,9 +111,8 @@
QUnit.test( 'Initialization', 2, function( assert ) {
var extender = newTestInputextender();
- assert.equal(
- $( '.test_inputextender' ).data( 'inputextender' ),
- extender,
+ assert.ok(
+ extender instanceof $.ui.inputextender,
'Initialized widget.'
);
@@ -132,6 +136,7 @@
var extender = newTestInputextender(),
widgetBaseClass = extender.widgetBaseClass;
+ extender.showExtension(); // Make sure extension is being
constructed.
extender.destroy();
assert.ok(
--
To view, visit https://gerrit.wikimedia.org/r/79147
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: If57ee1eea13d1d016915b8e06b8e9cea05c63b5e
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/DataValues
Gerrit-Branch: master
Gerrit-Owner: Daniel Werner <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits