Merge "Add named timeouts to mw.mmv.ui.Element"

This commit is contained in:
jenkins-bot 2014-04-08 09:48:11 +00:00 committed by Gerrit Code Review
commit f163f2f30e
2 changed files with 124 additions and 1 deletions

View file

@ -37,6 +37,13 @@
* which we use to manipulate pseudo-classes and pseudo-elements.
*/
this.$inlineStyles = [];
/**
* @private
* Stores named timeouts. See setTimer().
* @property {Object.<string, {timeout: Object, handler: function(), delay: number}>}
*/
this.timers = {};
}
EP = Element.prototype;
@ -121,6 +128,60 @@
this.$inlineStyles[key].html( style || '' );
};
/**
* Sets a timer. This is a shortcut to using the native setTimout and then storing
* the reference, with some small differences for convenience:
* - setting the same timer again clears the old one
* - callbacks have the element as their context
* Timers are local to the element.
* See also clearTimer() and resetTimer().
* @param {string} name
* @param {function()} callback
* @param {number} delay delay in milliseconds
*/
EP.setTimer = function ( name, callback, delay ) {
var element = this;
this.clearTimer( name );
this.timers[name] = {
timeout: null,
handler: callback,
delay: delay
};
this.timers[name].timeout = setTimeout( function () {
delete element.timers[name];
callback.call( element );
}, delay );
};
/**
* Clears a timer. See setTimer().
* @param {string} name
*/
EP.clearTimer = function( name ) {
if ( name in this.timers ) {
clearTimeout( this.timers[name].timeout );
delete this.timers[name];
}
};
/**
* Resets a timer, so that its delay will be relative to when resetTimer() was called, not when
* the timer was created. Optionally changes the delay as well.
* Resetting a timer that does not exist or has already fired has no effect.
* See setTimer().
* @param {string} name
* @param {number} [delay] delay in milliseconds
*/
EP.resetTimer = function( name, delay ) {
if ( name in this.timers ) {
if ( delay === undefined ) {
delay = this.timers[name].delay;
}
this.setTimer( name, this.timers[name].handler, delay );
}
};
mw.mmv.ui = {};
mw.mmv.ui.reuse = {};
mw.mmv.ui.Element = Element;

View file

@ -1,5 +1,9 @@
( function ( mw, $ ) {
QUnit.module( 'mmv.ui', QUnit.newMwEnvironment() );
QUnit.module( 'mmv.ui', QUnit.newMwEnvironment( {
setup: function () {
this.clock = this.sandbox.useFakeTimers();
}
} ) );
QUnit.test( 'handleEvent()', 1, function ( assert ) {
var element = new mw.mmv.ui.Element( $( '<div>' ) );
@ -29,4 +33,62 @@
assert.ok( $testDiv.is( ':visible' ), 'Test div is visible again' );
} );
QUnit.test( 'setTimer()/clearTimer()/resetTimer()', 12, function( assert ) {
var element = new mw.mmv.ui.Element( $( '<div>' ) ),
element2 = new mw.mmv.ui.Element( $( '<div>' ) ),
spy = this.sandbox.spy(),
spy2 = this.sandbox.spy();
element.setTimer( 'foo', spy, 10 );
this.clock.tick( 100 );
assert.ok( spy.called, 'Timeout callback was called' );
assert.ok( spy.calledOnce, 'Timeout callback was called once' );
assert.ok( spy.calledOn( element ), 'Timeout callback was called on the element' );
spy = this.sandbox.spy();
element.setTimer( 'foo', spy, 10 );
element.setTimer( 'foo', spy2, 20 );
this.clock.tick( 100 );
assert.ok( !spy.called, 'Old timeout callback was not called after update' );
assert.ok( spy2.called, 'New timeout callback was called after update' );
spy = this.sandbox.spy();
spy2 = this.sandbox.spy();
element.setTimer( 'foo', spy, 10 );
element.setTimer( 'bar', spy2, 20 );
this.clock.tick( 100 );
assert.ok( spy.called && spy2.called, 'Timeouts with different names do not conflict' );
spy = this.sandbox.spy();
spy2 = this.sandbox.spy();
element.setTimer( 'foo', spy, 10 );
element2.setTimer( 'foo', spy2, 20 );
this.clock.tick( 100 );
assert.ok( spy.called && spy2.called, 'Timeouts in different elements do not conflict' );
spy = this.sandbox.spy();
element.setTimer( 'foo', spy, 10 );
element.clearTimer( 'foo' );
this.clock.tick( 100 );
assert.ok( !spy.called, 'Timeout is invalidated by clearing' );
spy = this.sandbox.spy();
element.setTimer( 'foo', spy, 100 );
this.clock.tick( 80 );
element.resetTimer( 'foo' );
this.clock.tick( 80 );
assert.ok( !spy.called, 'Timeout is reset' );
this.clock.tick( 80 );
assert.ok( spy.called, 'Timeout works after reset' );
spy = this.sandbox.spy();
element.setTimer( 'foo', spy, 100 );
this.clock.tick( 80 );
element.resetTimer( 'foo', 200 );
this.clock.tick( 180 );
assert.ok( !spy.called, 'Timeout is reset to the designated delay' );
this.clock.tick( 80 );
assert.ok( spy.called, 'Timeout works after changing the delay' );
} );
}( mediaWiki, jQuery ) );