/*
 * Create a HesitateEvent and assign it as the event to execute:
 *   $(el).on('mouseEnter', CMS.HesitateEvent( expand, 'mouseLeave').trigger);
 *   It calls the executeOnTimeOut function with the event.currentTarget after the configurable timeout IFF the cancelSelector event
 *   did not occur on the event.currentTarget. 
 *   
 *   More specifically, when trigger is called (triggered by the event you bound it to), it starts a timer 
 *   which the cancelSelector event will cancel or if the timer finished, it executes the executeOnTimeOut function
 *   passing it the original event (whose currentTarget s/b the specific ele). It never accumulates events; however, it doesn't hurt for your
 *   code to minimize invocations of trigger by binding to mouseEnter v mouseOver and such.
 *   
 *   NOTE: if something outside of this wants to cancel the event, invoke cachedhesitation.untrigger(null | anything);
 */

CMS.HesitateEvent = function(executeOnTimeOut, cancelSelector, onlyOnce) {
	this.executeOnTimeOut = executeOnTimeOut;
	this.cancelSelector = cancelSelector;
	this.timeoutEventId = null;
	this.originalEvent = null;
	this.onlyOnce = (onlyOnce === true);
};

CMS.HesitateEvent.DURATION = 800;

CMS.HesitateEvent.prototype.trigger = function(event) {
	if (event.data.timeoutEventId == null) {
		event.data.timeoutEventId = window.setTimeout(
				function() { event.data.fireEvent(event); }, 
				CMS.HesitateEvent.DURATION);
		event.data.originalEvent = event;
		$(event.data.originalEvent.delegateTarget).on(event.data.cancelSelector, event.data, event.data.untrigger);
	}
};

CMS.HesitateEvent.prototype.fireEvent = function(event) {
	event.data.timeoutEventId = null;
	$(event.data.originalEvent.delegateTarget).off(event.data.cancelSelector, event.data.untrigger);
	if (event.data.onlyOnce) $(event.data.originalEvent.delegateTarget).off(event.data.originalEvent.type, event.data.trigger);
	event.data.executeOnTimeOut(event.data.originalEvent);
};

CMS.HesitateEvent.prototype.untrigger = function(event) {
	if (event.data.timeoutEventId) {
		window.clearTimeout(event.data.timeoutEventId);
		$(event.data.originalEvent.delegateTarget).off(event.data.cancelSelector, event.data.untrigger);
	}
	event.data.timeoutEventId = null;
};