src/cm/media/js/lib/yui/yui_3.10.3/build/widget-uievents/widget-uievents.js
changeset 525 89ef5ed3c48b
equal deleted inserted replaced
524:322d0feea350 525:89ef5ed3c48b
       
     1 /*
       
     2 YUI 3.10.3 (build 2fb5187)
       
     3 Copyright 2013 Yahoo! Inc. All rights reserved.
       
     4 Licensed under the BSD License.
       
     5 http://yuilibrary.com/license/
       
     6 */
       
     7 
       
     8 YUI.add('widget-uievents', function (Y, NAME) {
       
     9 
       
    10 /**
       
    11  * Support for Widget UI Events (Custom Events fired by the widget, which wrap the underlying DOM events - e.g. widget:click, widget:mousedown)
       
    12  *
       
    13  * @module widget
       
    14  * @submodule widget-uievents
       
    15  */
       
    16 
       
    17 var BOUNDING_BOX = "boundingBox",
       
    18     Widget = Y.Widget,
       
    19     RENDER = "render",
       
    20     L = Y.Lang,
       
    21     EVENT_PREFIX_DELIMITER = ":",
       
    22 
       
    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 || {};
       
    26 
       
    27 Y.mix(Widget.prototype, {
       
    28 
       
    29     /**
       
    30      * Destructor logic for UI event infrastructure,
       
    31      * invoked during Widget destruction.
       
    32      *
       
    33      * @method _destroyUIEvents
       
    34      * @for Widget
       
    35      * @private
       
    36      */
       
    37     _destroyUIEvents: function() {
       
    38 
       
    39         var widgetGuid = Y.stamp(this, true);
       
    40 
       
    41         Y.each(_uievts, function (info, key) {
       
    42             if (info.instances[widgetGuid]) {
       
    43                 //  Unregister this Widget instance as needing this delegated
       
    44                 //  event listener.
       
    45                 delete info.instances[widgetGuid];
       
    46 
       
    47                 //  There are no more Widget instances using this delegated
       
    48                 //  event listener, so detach it.
       
    49 
       
    50                 if (Y.Object.isEmpty(info.instances)) {
       
    51                     info.handle.detach();
       
    52 
       
    53                     if (_uievts[key]) {
       
    54                         delete _uievts[key];
       
    55                     }
       
    56                 }
       
    57             }
       
    58         });
       
    59     },
       
    60 
       
    61     /**
       
    62      * Map of DOM events that should be fired as Custom Events by the
       
    63      * Widget instance.
       
    64      *
       
    65      * @property UI_EVENTS
       
    66      * @for Widget
       
    67      * @type Object
       
    68      */
       
    69     UI_EVENTS: Y.Node.DOM_EVENTS,
       
    70 
       
    71     /**
       
    72      * Returns the node on which to bind delegate listeners.
       
    73      *
       
    74      * @method _getUIEventNode
       
    75      * @for Widget
       
    76      * @protected
       
    77      */
       
    78     _getUIEventNode: function () {
       
    79         return this.get(BOUNDING_BOX);
       
    80     },
       
    81 
       
    82     /**
       
    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.
       
    86      *
       
    87      * @method _createUIEvent
       
    88      * @for Widget
       
    89      * @param type {String} String representing the name of the event
       
    90      * @private
       
    91      */
       
    92     _createUIEvent: function (type) {
       
    93 
       
    94         var uiEvtNode = this._getUIEventNode(),
       
    95             key = (Y.stamp(uiEvtNode) + type),
       
    96             info = _uievts[key],
       
    97             handle;
       
    98 
       
    99         //  For each Node instance: Ensure that there is only one delegated
       
   100         //  event listener used to fire Widget UI events.
       
   101 
       
   102         if (!info) {
       
   103 
       
   104             handle = uiEvtNode.delegate(type, function (evt) {
       
   105 
       
   106                 var widget = Widget.getByNode(this);
       
   107 
       
   108                 // Widget could be null if node instance belongs to
       
   109                 // another Y instance.
       
   110 
       
   111                 if (widget) {
       
   112                     if (widget._filterUIEvent(evt)) {
       
   113                         widget.fire(evt.type, { domEvent: evt });
       
   114                     }
       
   115                 }
       
   116 
       
   117             }, "." + Y.Widget.getClassName());
       
   118 
       
   119             _uievts[key] = info = { instances: {}, handle: handle };
       
   120         }
       
   121 
       
   122         //  Register this Widget as using this Node as a delegation container.
       
   123         info.instances[Y.stamp(this)] = 1;
       
   124     },
       
   125 
       
   126     /**
       
   127      * This method is used to determine if we should fire
       
   128      * the UI Event or not. The default implementation makes sure
       
   129      * that for nested delegates (nested unrelated widgets), we don't
       
   130      * fire the UI event listener more than once at each level.
       
   131      *
       
   132      * <p>For example, without the additional filter, if you have nested
       
   133      * widgets, each widget will have a delegate listener. If you
       
   134      * click on the inner widget, the inner delegate listener's
       
   135      * filter will match once, but the outer will match twice
       
   136      * (based on delegate's design) - once for the inner widget,
       
   137      * and once for the outer.</p>
       
   138      *
       
   139      * @method _filterUIEvent
       
   140      * @for Widget
       
   141      * @param {DOMEventFacade} evt
       
   142      * @return {boolean} true if it's OK to fire the custom UI event, false if not.
       
   143      * @private
       
   144      *
       
   145      */
       
   146     _filterUIEvent: function(evt) {
       
   147         // Either it's hitting this widget's delegate container (and not some other widget's),
       
   148         // or the container it's hitting is handling this widget's ui events.
       
   149         return (evt.currentTarget.compareTo(evt.container) || evt.container.compareTo(this._getUIEventNode()));
       
   150     },
       
   151 
       
   152     /**
       
   153      * Determines if the specified event is a UI event.
       
   154      *
       
   155      * @private
       
   156      * @method _isUIEvent
       
   157      * @for Widget
       
   158      * @param type {String} String representing the name of the event
       
   159      * @return {String} Event Returns the name of the UI Event, otherwise
       
   160      * undefined.
       
   161      */
       
   162     _getUIEvent: function (type) {
       
   163 
       
   164         if (L.isString(type)) {
       
   165             var sType = this.parseType(type)[1],
       
   166                 iDelim,
       
   167                 returnVal;
       
   168 
       
   169             if (sType) {
       
   170                 // TODO: Get delimiter from ET, or have ET support this.
       
   171                 iDelim = sType.indexOf(EVENT_PREFIX_DELIMITER);
       
   172                 if (iDelim > -1) {
       
   173                     sType = sType.substring(iDelim + EVENT_PREFIX_DELIMITER.length);
       
   174                 }
       
   175 
       
   176                 if (this.UI_EVENTS[sType]) {
       
   177                     returnVal = sType;
       
   178                 }
       
   179             }
       
   180 
       
   181             return returnVal;
       
   182         }
       
   183     },
       
   184 
       
   185     /**
       
   186      * Sets up infrastructure required to fire a UI event.
       
   187      *
       
   188      * @private
       
   189      * @method _initUIEvent
       
   190      * @for Widget
       
   191      * @param type {String} String representing the name of the event
       
   192      * @return {String}
       
   193      */
       
   194     _initUIEvent: function (type) {
       
   195         var sType = this._getUIEvent(type),
       
   196             queue = this._uiEvtsInitQueue || {};
       
   197 
       
   198         if (sType && !queue[sType]) {
       
   199 
       
   200             this._uiEvtsInitQueue = queue[sType] = 1;
       
   201 
       
   202             this.after(RENDER, function() {
       
   203                 this._createUIEvent(sType);
       
   204                 delete this._uiEvtsInitQueue[sType];
       
   205             });
       
   206         }
       
   207     },
       
   208 
       
   209     //  Override of "on" from Base to facilitate the firing of Widget events
       
   210     //  based on DOM events of the same name/type (e.g. "click", "mouseover").
       
   211     //  Temporary solution until we have the ability to listen to when
       
   212     //  someone adds an event listener (bug 2528230)
       
   213     on: function (type) {
       
   214         this._initUIEvent(type);
       
   215         return Widget.superclass.on.apply(this, arguments);
       
   216     },
       
   217 
       
   218     //  Override of "publish" from Base to facilitate the firing of Widget events
       
   219     //  based on DOM events of the same name/type (e.g. "click", "mouseover").
       
   220     //  Temporary solution until we have the ability to listen to when
       
   221     //  someone publishes an event (bug 2528230)
       
   222     publish: function (type, config) {
       
   223         var sType = this._getUIEvent(type);
       
   224         if (sType && config && config.defaultFn) {
       
   225             this._initUIEvent(sType);
       
   226         }
       
   227         return Widget.superclass.publish.apply(this, arguments);
       
   228     }
       
   229 
       
   230 }, true); // overwrite existing EventTarget methods
       
   231 
       
   232 
       
   233 }, '3.10.3', {"requires": ["node-event-delegate", "widget-base"]});