2 Copyright (c) 2010, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.com/yui/license.html
8 YUI.add('widget-uievents', function(Y) {
11 * Support for Widget UI Events (Custom Events fired by the widget, which wrap the underlying DOM events - e.g. widget:click, widget:mousedown)
14 * @submodule widget-uievents
17 var BOUNDING_BOX = "boundingBox",
21 EVENT_PREFIX_DELIMITER = ":",
23 // Map of Node instances serving as a delegation containers for a specific
24 // event type to Widget instances using that delegation container.
25 _uievts = Y.Widget._uievts = Y.Widget._uievts || {};
27 Y.mix(Widget.prototype, {
30 * Destructor logic for UI event infrastructure,
31 * invoked during Widget destruction.
33 * @method _destroyUIEvents
37 _destroyUIEvents: function() {
39 var widgetGuid = Y.stamp(this, true);
41 Y.each(_uievts, function (info, key) {
42 if (info.instances[widgetGuid]) {
43 // Unregister this Widget instance as needing this delegated
45 delete info.instances[widgetGuid];
47 // There are no more Widget instances using this delegated
48 // event listener, so detach it.
50 if (Y.Object.isEmpty(info.instances)) {
62 * Map of DOM events that should be fired as Custom Events by the
69 UI_EVENTS: Y.Node.DOM_EVENTS,
72 * Returns the node on which to bind delegate listeners.
74 * @method _getUIEventNode
78 _getUIEventNode: function () {
79 return this.get(BOUNDING_BOX);
83 * Binds a delegated DOM event listener of the specified type to the
84 * Widget's outtermost DOM element to facilitate the firing of a Custom
85 * Event of the same type for the Widget instance.
89 * @method _createUIEvent
90 * @param type {String} String representing the name of the event
92 _createUIEvent: function (type) {
94 var uiEvtNode = this._getUIEventNode(),
95 key = (Y.stamp(uiEvtNode) + type),
99 // For each Node instance: Ensure that there is only one delegated
100 // event listener used to fire Widget UI events.
104 handle = uiEvtNode.delegate(type, function (evt) {
106 var widget = Widget.getByNode(this);
107 // Make the DOM event a property of the custom event
108 // so that developers still have access to it.
109 widget.fire(evt.type, { domEvent: evt });
111 }, "." + Y.Widget.getClassName());
113 _uievts[key] = info = { instances: {}, handle: handle };
116 // Register this Widget as using this Node as a delegation container.
117 info.instances[Y.stamp(this)] = 1;
121 * Determines if the specified event is a UI event.
126 * @param type {String} String representing the name of the event
127 * @return {String} Event Returns the name of the UI Event, otherwise
130 _getUIEvent: function (type) {
132 if (L.isString(type)) {
133 var sType = this.parseType(type)[1],
138 // TODO: Get delimiter from ET, or have ET support this.
139 iDelim = sType.indexOf(EVENT_PREFIX_DELIMITER);
141 sType = sType.substring(iDelim + EVENT_PREFIX_DELIMITER.length);
144 if (this.UI_EVENTS[sType]) {
154 * Sets up infrastructure required to fire a UI event.
157 * @method _initUIEvent
159 * @param type {String} String representing the name of the event
162 _initUIEvent: function (type) {
163 var sType = this._getUIEvent(type),
164 queue = this._uiEvtsInitQueue || {};
166 if (sType && !queue[sType]) {
168 this._uiEvtsInitQueue = queue[sType] = 1;
170 this.after(RENDER, function() {
171 this._createUIEvent(sType);
172 delete this._uiEvtsInitQueue[sType];
177 // Override of "on" from Base to facilitate the firing of Widget events
178 // based on DOM events of the same name/type (e.g. "click", "mouseover").
179 // Temporary solution until we have the ability to listen to when
180 // someone adds an event listener (bug 2528230)
181 on: function (type) {
182 this._initUIEvent(type);
183 return Widget.superclass.on.apply(this, arguments);
186 // Override of "publish" from Base to facilitate the firing of Widget events
187 // based on DOM events of the same name/type (e.g. "click", "mouseover").
188 // Temporary solution until we have the ability to listen to when
189 // someone publishes an event (bug 2528230)
190 publish: function (type, config) {
191 var sType = this._getUIEvent(type);
192 if (sType && config && config.defaultFn) {
193 this._initUIEvent(sType);
195 return Widget.superclass.publish.apply(this, arguments);
198 }, true); // overwrite existing EventTarget methods
201 }, '3.3.0' ,{requires:['widget-base', 'node-event-delegate']});