Ver Fonte

Added docs for DOMEmitterMixin.

Aleksander Nowodzinski há 10 anos atrás
pai
commit
5c5142cc34
1 ficheiros alterados com 139 adições e 51 exclusões
  1. 139 51
      packages/ckeditor5-engine/src/ui/domemittermixin.js

+ 139 - 51
packages/ckeditor5-engine/src/ui/domemittermixin.js

@@ -8,29 +8,83 @@
 /* global Node */
 
 /**
- * Mixin that injects the DOM events API into its host.
+ * Mixin that injects the DOM events API into its host. It provides the API
+ * compatible with {@link EmitterMixin}.
+ *
+ *                               listenTo( click, ... )
+ *                 +-----------------------------------------+
+ *                 |              stopListening( ... )       |
+ *  +----------------------------+                           |             addEventListener( click, ... )
+ *  | Host                       |                           |   +---------------------------------------------+
+ *  +----------------------------+                           |   |       removeEventListener( click, ... )     |
+ *  | _listeningTo: {            |                +----------v-------------+                                   |
+ *  |   UID: {                   |                | ProxyEmitter           |                                   |
+ *  |     emitter: ProxyEmitter, |                +------------------------+                      +------------v----------+
+ *  |     callbacks: {           |                | events: {              |                      | Node (HTMLElement)    |
+ *  |       click: [ callbacks ] |                |   click: [ callbacks ] |                      +-----------------------+
+ *  |     }                      |                | },                     |                      | data-cke-expando: UID |
+ *  |   }                        |                | _domNode: Node,        |                      +-----------------------+
+ *  | }                          |                | _domListeners: {},     |                                   |
+ *  | +------------------------+ |                | _emitterId: UID        |                                   |
+ *  | | DOMEmitterMixin        | |                +--------------^---------+                                   |
+ *  | +------------------------+ |                           |   |                                             |
+ *  +--------------^-------------+                           |   +---------------------------------------------+
+ *                 |                                         |                  click (DOM Event)
+ *                 +-----------------------------------------+
+ *                             fire( click, DOM Event )
  *
  * @class DOMEmitterMixin
+ * @extends EmitterMixin
  * @singleton
  */
 
 CKEDITOR.define( [ 'emittermixin', 'utils', 'log' ], function( EmitterMixin, utils, log ) {
 	var DOMEmitterMixin = {
+		/**
+		 * Registers a callback function to be executed when an event is fired in a specific Emitter or DOM Node.
+		 * It is backwards compatible with {@link EmitterMixin#listenTo}.
+		 *
+		 * @param {Emitter|Node} emitter The object that fires the event.
+		 * @param {String} event The name of the event.
+		 * @param {Function} callback The function to be called on event.
+		 * @param {Object} [ctx] The object that represents `this` in the callback. Defaults to `emitter`.
+		 * @param {Number} [priority=10] The priority of this callback in relation to other callbacks to that same event.
+		 * Lower values are called first.
+		 */
 		listenTo() {
 			var args = Array.prototype.slice.call( arguments );
 			var emitter = args[ 0 ];
 
+			// Check if emitter is an instance of DOM Node. If so, replace the argument with
+			// corresponding ProxyEmitter (or create one if not existing).
 			if ( emitter instanceof Node ) {
 				args[ 0 ] = this._getProxyEmitter( emitter ) || this._createProxyEmitter( emitter );
 			}
 
+			// Execute parent class method with Emitter (or ProxyEmitter) instance.
 			EmitterMixin.listenTo.apply( this, args );
 		},
 
+		/**
+		 * Stops listening for events. It can be used at different levels:
+		 * It is backwards compatible with {@link EmitterMixin#listenTo}.
+		 *
+		 * * To stop listening to a specific callback.
+		 * * To stop listening to a specific event.
+		 * * To stop listening to all events fired by a specific object.
+		 * * To stop listening to all events fired by all object.
+		 *
+		 * @param {Emitter|Node} [emitter] The object to stop listening to. If omitted, stops it for all objects.
+		 * @param {String} [event] (Requires the `emitter`) The name of the event to stop listening to. If omitted, stops it
+		 * for all events from `emitter`.
+		 * @param {Function} [callback] (Requires the `event`) The function to be removed from the call list for the given
+		 * `event`.
+		 */
 		stopListening() {
 			var args = Array.prototype.slice.call( arguments );
 			var emitter = args[ 0 ];
 
+			// Check if emitter is an instance of DOM Node. If so, replace the argument with corresponding ProxyEmitter.
 			if ( emitter instanceof Node ) {
 				var proxy = this._getProxyEmitter( emitter );
 
@@ -44,56 +98,105 @@ CKEDITOR.define( [ 'emittermixin', 'utils', 'log' ], function( EmitterMixin, uti
 				}
 			}
 
+			// Execute parent class method with Emitter (or ProxyEmitter) instance.
 			EmitterMixin.stopListening.apply( this, args );
 		},
 
+		/**
+		 * Creates a ProxyEmitter instance. Such an instance is a bridge between a DOM Node firing events
+		 * and any Host listening to them. It is backwards compatible with {@link EmitterMixin#on}.
+		 *
+		 * @param {Node} node DOM Node that fires events.
+		 * @returns {Object} ProxyEmitter instance bound to the DOM Node.
+		 */
 		_createProxyEmitter( node ) {
 			var proxyEmitter = utils.extend( {}, EmitterMixin, {
-				on( event, callback, ctx, priority ) {
-					EmitterMixin.on.call( this, event, callback, ctx, priority );
-
-					if ( this._domNode ) {
-						if ( this._domListenerProxies && this._domListenerProxies[ event ] ) {
-							return;
-						}
-
-						var domListener = domEvt => this.fire( event, domEvt );
+				/**
+				 * Registers a callback function to be executed when an event is fired.
+				 *
+				 * It attaches a native DOM listener to the DOM Node. When fired,
+				 * a corresponding Emitter event will also fire with DOM Event object as an argument.
+				 *
+				 * @param {String} event The name of the event.
+				 * @param {Function} callback The function to be called on event.
+				 * @param {Object} [ctx] The object that represents `this` in the callback. Defaults to the object firing the
+				 * event.
+				 * @param {Number} [priority=10] The priority of this callback in relation to other callbacks to that same event.
+				 * Lower values are called first.
+				 */
+				on( event ) {
+					// Execute parent class method first.
+					EmitterMixin.on.apply( this, arguments );
+
+					// If the DOM Listener for given event already exist it is pointless
+					// to attach another one.
+					if ( this._domListeners && this._domListeners[ event ] ) {
+						return;
+					}
 
-						domListener.removeListener = () => {
-							this._domNode.removeEventListener( event, domListener );
-							delete this._domListenerProxies[ event ];
-						};
+					// Create a native DOM listener callback. When the native DOM event
+					// is fired it will fire corresponding event on this ProxyEmitter.
+					// Note: A native DOM Event is passed as an argument.
+					var domListener = domEvt => this.fire( event, domEvt );
 
-						this._domNode.addEventListener( event, domListener );
+					// Supply the DOM listener callback with a function that will help
+					// detach it from the DOM Node, when it is no longer necessary.
+					// See: {@link off}.
+					domListener.removeListener = () => {
+						this._domNode.removeEventListener( event, domListener );
+						delete this._domListeners[ event ];
+					};
 
-						if ( !this._domListenerProxies ) {
-							this._domListenerProxies = {};
-						}
+					// Attach the native DOM listener to DOM Node.
+					this._domNode.addEventListener( event, domListener );
 
-						this._domListenerProxies[ event ] = domListener;
+					if ( !this._domListeners ) {
+						this._domListeners = {};
 					}
-				},
-
-				off( event, callback, ctx ) {
-					EmitterMixin.off.call( this, event, callback, ctx );
 
-					if ( this._domNode ) {
-						var callbacks;
+					// Store the native DOM listener in this ProxyEmitter. It will be helpful
+					// when stopping listening to the event.
+					this._domListeners[ event ] = domListener;
+				},
 
-						if ( !( callbacks = this._events[ event ] ) || !callbacks.length ) {
-							this._domListenerProxies[ event ].removeListener();
-						}
+				/**
+				 * Stops executing the callback on the given event.
+				 *
+				 * @param {String} event The name of the event.
+				 * @param {Function} callback The function to stop being called.
+				 * @param {Object} [ctx] The context object to be removed, pared with the given callback. To handle cases where
+				 * the same callback is used several times with different contexts.
+				 */
+				off( event ) {
+					// Execute parent class method first.
+					EmitterMixin.off.apply( this, arguments );
+
+					var callbacks;
+
+					// Remove native DOM listeners which are orphans. If no callbacks
+					// are awaiting given event, detach native DOM listener from DOM Node.
+					// See: {@link on}.
+					if ( !( callbacks = this._events[ event ] ) || !callbacks.length ) {
+						this._domListeners[ event ].removeListener();
 					}
 				}
 			} );
 
-			// Set emitter ID to match DOM Node expando property.
+			// Set emitter ID to match DOM Node "expando" property.
 			proxyEmitter._emitterId = this._getNodeUID( node );
+
+			// Remember the DOM Node this ProxyEmitter is bound to.
 			proxyEmitter._domNode = node;
 
 			return proxyEmitter;
 		},
 
+		/**
+		 * Retrieves ProxyEmitter for given DOM Node residing in this Host.
+		 *
+		 * @param {Node} node DOM Node of the ProxyEmitter.
+		 * @return {Emitter} Emitter instance if found.
+		 */
 		_getProxyEmitter( node ) {
 			var proxy, emitters, emitterInfo;
 
@@ -110,33 +213,18 @@ CKEDITOR.define( [ 'emittermixin', 'utils', 'log' ], function( EmitterMixin, uti
 			return proxy;
 		},
 
+		/**
+		 * Gets an unique DOM Node identifier. The identifier will be set if not defined.
+		 *
+		 * @param {Node} node
+		 * @return {Number} UID for given DOM Node.
+		 */
 		_getNodeUID( node ) {
 			return node[ EXP_KEY_NAME ] || ( node[ EXP_KEY_NAME ] = utils.uid() );
-		},
-
-		// _setNodeCustomData( node, key, value ) {
-		// 	var uid = this._getNodeUID( node );
-		// 	var slot = this.customData[ uid ] || ( this.customData[ uid ] = {} );
-
-		// 	slot[ key ] = value;
-
-		// 	return this;
-		// },
-
-		// _getNodeCustomData( node, key ) {
-		// 	var uid = node[ EXP_KEY_NAME ];
-		// 	var slot;
-
-		// 	if ( uid ) {
-		// 		slot = this.customData[ uid ];
-		// 	}
-
-		// 	return ( slot && key in slot ) ? slot[ key ] : null;
-		// }
+		}
 	};
 
 	var EXP_KEY_NAME = 'data-ck-expando';
 
 	return DOMEmitterMixin;
 } );
-