/**
* Stores the subscriber information to be used when the event fires.
* @param {Function} fn The wrapped function to execute.
* @param {Object} context The value of the keyword 'this' in the listener.
* @param {Array} args* 0..n additional arguments to supply the listener.
*
* @class Subscriber
* @constructor
*/
Y.Subscriber = function(fn, context, args, when) {
/**
* The callback that will be execute when the event fires
* This is wrapped by Y.rbind if obj was supplied.
* @property fn
* @type Function
*/
this.fn = fn;
/**
* Optional 'this' keyword for the listener
* @property context
* @type Object
*/
this.context = context;
/**
* Unique subscriber id
* @property id
* @type String
*/
this.id = Y.guid();
/**
* Additional arguments to propagate to the subscriber
* @property args
* @type Array
*/
this.args = args;
this._when = when;
/**
* Custom events for a given fire transaction.
* @property events
* @type {EventTarget}
*/
// this.events = null;
/**
* This listener only reacts to the event once
* @property once
*/
// this.once = false;
};
Y.Subscriber.prototype = {
constructor: Y.Subscriber,
_notify: function(c, args, ce) {
if (this.deleted && !this.postponed) {
if (this.postponed) {
delete this.fn;
delete this.context;
} else {
delete this.postponed;
return null;
}
}
var a = this.args, ret;
switch (ce.signature) {
case 0:
ret = this.fn.call(c, ce.type, args, c);
break;
case 1:
ret = this.fn.call(c, args[0] || null, c);
break;
default:
if (a || args) {
args = args || [];
a = (a) ? args.concat(a) : args;
ret = this.fn.apply(c, a);
} else {
ret = this.fn.call(c);
}
}
if (this.once) {
ce._delete(this);
}
return ret;
},
/**
* Executes the subscriber.
* @method notify
* @param args {Array} Arguments array for the subscriber.
* @param ce {CustomEvent} The custom event that sent the notification.
*/
notify: function(args, ce) {
var c = this.context,
ret = true;
if (!c) {
c = (ce.contextFn) ? ce.contextFn() : ce.context;
}
// only catch errors if we will not re-throw them.
if (Y.config && Y.config.throwFail) {
ret = this._notify(c, args, ce);
} else {
try {
ret = this._notify(c, args, ce);
} catch (e) {
Y.error(this + ' failed: ' + e.message, e);
}
}
return ret;
},
/**
* Returns true if the fn and obj match this objects properties.
* Used by the unsubscribe method to match the right subscriber.
*
* @method contains
* @param {Function} fn the function to execute.
* @param {Object} context optional 'this' keyword for the listener.
* @return {boolean} true if the supplied arguments match this
* subscriber's signature.
*/
contains: function(fn, context) {
if (context) {
return ((this.fn === fn) && this.context === context);
} else {
return (this.fn === fn);
}
},
valueOf : function() {
return this.id;
}
};