Version 3.17.2

APIs

  • Begin typing in the search box above to see results.
Show:

File: widget/js/WidgetUIEvents.js

/**
 * Support for Widget UI Events (Custom Events fired by the widget, which wrap the underlying DOM events - e.g. widget:click, widget:mousedown)
 *
 * @module widget
 * @submodule widget-uievents
 */
var BOUNDING_BOX = "boundingBox",
 Widget = Y.Widget,
 RENDER = "render",
 L = Y.Lang,
 EVENT_PREFIX_DELIMITER = ":",
 // Map of Node instances serving as a delegation containers for a specific
 // event type to Widget instances using that delegation container.
 _uievts = Y.Widget._uievts = Y.Widget._uievts || {};
Y.mix(Widget.prototype, {
 /**
 * Destructor logic for UI event infrastructure,
 * invoked during Widget destruction.
 *
 * @method _destroyUIEvents
 * @for Widget
 * @private
 */
 _destroyUIEvents: function() {
 var widgetGuid = Y.stamp(this, true);
 Y.each(_uievts, function (info, key) {
 if (info.instances[widgetGuid]) {
 // Unregister this Widget instance as needing this delegated
 // event listener.
 delete info.instances[widgetGuid];
 // There are no more Widget instances using this delegated
 // event listener, so detach it.
 if (Y.Object.isEmpty(info.instances)) {
 info.handle.detach();
 if (_uievts[key]) {
 delete _uievts[key];
 }
 }
 }
 });
 },
 /**
 * Map of DOM events that should be fired as Custom Events by the
 * Widget instance.
 *
 * @property UI_EVENTS
 * @for Widget
 * @type Object
 */
 UI_EVENTS: Y.Node.DOM_EVENTS,
 /**
 * Returns the node on which to bind delegate listeners.
 *
 * @method _getUIEventNode
 * @for Widget
 * @protected
 */
 _getUIEventNode: function () {
 return this.get(BOUNDING_BOX);
 },
 /**
 * Binds a delegated DOM event listener of the specified type to the
 * Widget's outtermost DOM element to facilitate the firing of a Custom
 * Event of the same type for the Widget instance.
 *
 * @method _createUIEvent
 * @for Widget
 * @param type {String} String representing the name of the event
 * @private
 */
 _createUIEvent: function (type) {
 var uiEvtNode = this._getUIEventNode(),
 key = (Y.stamp(uiEvtNode) + type),
 info = _uievts[key],
 handle;
 // For each Node instance: Ensure that there is only one delegated
 // event listener used to fire Widget UI events.
 if (!info) {
 handle = uiEvtNode.delegate(type, function (evt) {
 var widget = Widget.getByNode(this);
 // Widget could be null if node instance belongs to
 // another Y instance.
 if (widget) {
 if (widget._filterUIEvent(evt)) {
 widget.fire(evt.type, { domEvent: evt });
 }
 }
 }, "." + Y.Widget.getClassName());
 _uievts[key] = info = { instances: {}, handle: handle };
 }
 // Register this Widget as using this Node as a delegation container.
 info.instances[Y.stamp(this)] = 1;
 },
 /**
 * This method is used to determine if we should fire
 * the UI Event or not. The default implementation makes sure
 * that for nested delegates (nested unrelated widgets), we don't
 * fire the UI event listener more than once at each level.
 *
 * <p>For example, without the additional filter, if you have nested
 * widgets, each widget will have a delegate listener. If you
 * click on the inner widget, the inner delegate listener's
 * filter will match once, but the outer will match twice
 * (based on delegate's design) - once for the inner widget,
 * and once for the outer.</p>
 *
 * @method _filterUIEvent
 * @for Widget
 * @param {DOMEventFacade} evt
 * @return {boolean} true if it's OK to fire the custom UI event, false if not.
 * @private
 *
 */
 _filterUIEvent: function(evt) {
 // Either it's hitting this widget's delegate container (and not some other widget's),
 // or the container it's hitting is handling this widget's ui events.
 return (evt.currentTarget.compareTo(evt.container) || evt.container.compareTo(this._getUIEventNode()));
 },
 /**
 * 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],
 iDelim,
 returnVal;
 if (sType) {
 // TODO: Get delimiter from ET, or have ET support this.
 iDelim = sType.indexOf(EVENT_PREFIX_DELIMITER);
 if (iDelim > -1) {
 sType = sType.substring(iDelim + EVENT_PREFIX_DELIMITER.length);
 }
 if (this.UI_EVENTS[sType]) {
 returnVal = sType;
 }
 }
 return returnVal;
 }
 },
 /**
 * Sets up infrastructure 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
 

AltStyle によって変換されたページ (->オリジナル) /