WidgetUIEvents.js revision 8a864950bf1abc56d7b4c1ef7f086f1a60223b2f
98N/A/**
98N/A * Support for Widget UI Events (Custom Events fired by the widget, which wrap the underlying DOM events - e.g. widget:click, widget:mousedown)
98N/A *
98N/A * @module widget
98N/A * @submodule widget-uievents
98N/A */
98N/A
98N/Avar BOUNDING_BOX = "boundingBox",
98N/A Widget = Y.Widget,
98N/A RENDER = "render",
98N/A L = Y.Lang;
98N/A
98N/AY.mix(Widget.prototype, {
98N/A
98N/A /**
98N/A * Destructor logic for UI event infrastructure,
98N/A * invoked during Widget destruction.
98N/A *
98N/A * @method _destroyUIEvents
98N/A * @for Widget
98N/A * @private
98N/A */
98N/A _destroyUIEvents: function() {
98N/A
98N/A var widgetGuid = Y.stamp(this, true),
98N/A uievts = this._uievts;
98N/A
98N/A if (uievts) {
606N/A Y.each(uievts, function (info, key) {
606N/A if (info.instances[widgetGuid]) {
606N/A // Unregister this Widget instance as needing this delegated
705N/A // event listener.
98N/A delete info.instances[widgetGuid];
98N/A
98N/A // There are no more Widget instances using this delegated
98N/A // event listener, so detach it.
98N/A
98N/A if (Y.Object.isEmpty(info.instances)) {
98N/A info.handle.detach();
98N/A
98N/A if (uievts[key]) {
98N/A delete uievts[key];
98N/A }
98N/A }
98N/A }
98N/A });
98N/A }
98N/A },
98N/A
98N/A /**
606N/A * Map of DOM events that should be fired as Custom Events by the
98N/A * Widget instance.
98N/A *
98N/A * @property UI_EVENTS
705N/A * @for Widget
98N/A * @type Object
98N/A */
98N/A UI_EVENTS: Y.Node.DOM_EVENTS,
606N/A
98N/A /**
98N/A * Returns the node on which to bind delegate listeners.
98N/A *
98N/A * @method _getUIEventNode
98N/A * @for Widget
98N/A * @protected
98N/A */
98N/A _getUIEventNode: function () {
98N/A return this.get(BOUNDING_BOX);
98N/A },
98N/A
98N/A /**
98N/A * Binds a delegated DOM event listener of the specified type to the
98N/A * Widget's outtermost DOM element to facilitate the firing of a Custom
* Event of the same type for the Widget instance.
*
* @private
* @for Widget
* @method _createUIEvent
* @param type {String} String representing the name of the event
*/
_createUIEvent: function (type) {
var uiEvtNode = this._getUIEventNode(),
key = (Y.stamp(uiEvtNode) + type),
info,
handle;
this._uievts = this._uievts || {};
info = this._uievts[key];
// For each Node instance: Ensure that there is only one delegated
// event listener used to fire Widget UI events.
if (!info) {
Y.log("Creating delegate for the " + type + " event.", "info", "widget");
handle = uiEvtNode.delegate(type, function (evt) {
var widget = Widget.getByNode(this);
// Make the DOM event a property of the custom event
// so that developers still have access to it.
widget.fire(evt.type, { domEvent: evt });
}, "." + Y.Widget.getClassName());
this._uievts[key] = info = { instances: {}, handle: handle };
}
// Register this Widget as using this Node as a delegation container.
info.instances[Y.stamp(this)] = 1;
},
/**
* Determines if the specified event is a UI event.
*
* @private
* @method _isUIEvent
* @for Widget
* @param type {String} String representing the name of the event
* @return {String} Event Returns the name of the UI Event, otherwise
* undefined.
*/
_getUIEvent: function (type) {
if (L.isString(type)) {
var sType = this.parseType(type)[1],
returnVal;
if (this.UI_EVENTS[sType]) {
returnVal = sType;
}
return returnVal;
}
},
/**
* Sets up infastructure required to fire a UI event.
*
* @private
* @method _initUIEvent
* @for Widget
* @param type {String} String representing the name of the event
* @return {String}
*/
_initUIEvent: function (type) {
var sType = this._getUIEvent(type),
queue = this._uiEvtsInitQueue || {};
if (sType && !queue[sType]) {
Y.log("Deferring creation of " + type + " delegate until render.", "info", "widget");
this._uiEvtsInitQueue = queue[sType] = 1;
this.after(RENDER, function() {
this._createUIEvent(sType);
delete this._uiEvtsInitQueue[sType];
});
}
},
// Override of "on" from Base to facilitate the firing of Widget events
// based on DOM events of the same name/type (e.g. "click", "mouseover").
// Temporary solution until we have the ability to listen to when
// someone adds an event listener (bug 2528230)
on: function (type) {
this._initUIEvent(type);
return Widget.superclass.on.apply(this, arguments);
},
// Override of "publish" from Base to facilitate the firing of Widget events
// based on DOM events of the same name/type (e.g. "click", "mouseover").
// Temporary solution until we have the ability to listen to when
// someone publishes an event (bug 2528230)
publish: function (type, config) {
var sType = this._getUIEvent(type);
if (sType && config && config.defaultFn) {
this._initUIEvent(sType);
}
return Widget.superclass.publish.apply(this, arguments);
}
}, true); // overwrite existing EventTarget methods