Skip to content

Instantly share code, notes, and snippets.

@jackslocum
Last active December 15, 2015 17:48
Show Gist options
  • Save jackslocum/5298557 to your computer and use it in GitHub Desktop.
Save jackslocum/5298557 to your computer and use it in GitHub Desktop.
Tooltip timer class for Ext JS
/**
* @author Jack Slocum
* MIT License
*
* @class xui.util.DelayTimer
* Provides a convenient method for timing delayed show and hide of tooltips, callouts, etc
* @constructor
* @param {Object} config (optional)
*/
Ext.define('xui.util.DelayTimer', {
constructor: function(o){
Ext.apply(this, o);
this.timerFn = Ext.Function.bind(this.callFn, this);
this.timeoutFn = Ext.Function.bind(this.handleTimeout, this);
},
/**
* @cfg {Function} fn
* The function to call
*/
fn: undefined,
/**
* @cfg {Object} scope
* The "this" object for fn
*/
scope: undefined,
/**
* @cfg {Array} args
* The arguments to pass to fn when called. Generally these are passed to "start".
*/
args: undefined,
/**
* @cfg {Number} timeout
* The amount of time for the "active" state to timeout
*/
timeout: 1000,
/**
* @cfg {Number} 500
* The amount of time to delay/buffer the execution of fn
*/
delay: 500,
/**
* @cfg {Function} onEnd
* Function to be called any time end() occurs. Passed this DelayTimer.
*/
onEnd: undefined,
/**
* @cfg {Function} onTimeout
* Function to be called any time a timeout occurs (See isActive). Passed this DelayTimer.
*/
onTimeout: undefined,
/**
* @cfg {Function} test
* Function to be called right before starting the timer in start(). It is called with the same arguments that
* start() was called with. Return false to cancel the start().
* This is particularly useful for filtering calls to start() made by events bound with listen().
*/
test: undefined,
// private
active: false,
/**
* Returns true if this DelayTimer is "active" (fn will execute immediately when start is called), false if delayed
* @returns {boolean}
*/
isActive: function(){
return this.active;
},
/**
* Start the delay or will call immediately with passed arguments if "active"
* @param {Mixed} arg1 (optional)
* @param {Mixed} arg2 (optional)
* @param {mixed} etc (optional)
*/
start: function(){
this.cancel();
var args = Array.prototype.slice.call(arguments, 0);
if(args.length > 0){
this.args = args;
}
if(this.test && this.test.apply(this.scope, args) === false){
return;
}
if(this.active){
this.callFn();
}else{
this.callId = setTimeout(this.timerFn, this.delay);
}
},
/**
* Cancels the timer from the last call to start()
*/
cancel: function(){
if(this.callId){
clearTimeout(this.callId);
delete this.callId;
}
},
/**
* Starts the timeout duration. (For example, after a tooltip is hidden.)
*/
end: function(){
this.cancelTimeout();
this.timeoutId = setTimeout(this.timeoutFn, this.timeout);
if(this.onEnd){
this.onEnd.call(this.scope || this, this);
}
},
/**
* Attaches listeners to "obj" to manage calling start / cancel based on events (e.g. mouseenter / mouseleave)
* @param {Object} obj This object to listen on
* @param {String} startEvent
* @param {String} cancelEvent
*/
listen: function(obj, startEvent, cancelEvent){
if(startEvent){
obj.on(startEvent, this.start, this);
}
if(cancelEvent){
obj.on(cancelEvent, this.cancel, this);
}
},
/**
* @param {Object} obj This object previously passed to listen
* @param {String} startEvent
* @param {String} cancelEvent
*/
unlisten: function(obj, startEvent, cancelEvent){
if(startEvent){
obj.un(startEvent, this.start, this);
}
if(cancelEvent){
obj.un(cancelEvent, this.cancel, this);
}
},
/**
* Resets all timers and exits "active" mode
*/
reset: function(){
this.cancel();
this.cancelTimeout();
this.active = false;
},
// private
callFn: function(){
this.reset();
this.active = true;
this.fn.apply(this.scope || this, this.args || []);
},
// private
handleTimeout: function(){
this.active = false;
delete this.timeoutId;
if(this.onTimeout){
this.onTimeout.call(this.scope || this, this);
}
},
// private
cancelTimeout: function(){
if(this.timeoutId){
clearTimeout(this.timeoutId);
delete this.timeoutId;
}
}
});
@jackslocum
Copy link
Author

I added undefined properties on the prototype to make it easier to discover config options. You can safely delete them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment