| 
									
										
										
										
											2015-02-19 19:10:16 -08:00
										 |  |  | import {isBlank, BaseException, isPresent, StringWrapper} from 'angular2/src/facade/lang'; | 
					
						
							| 
									
										
										
										
											2015-02-27 14:50:06 -08:00
										 |  |  | import {DOM} from 'angular2/src/dom/dom_adapter'; | 
					
						
							| 
									
										
										
										
											2015-02-09 15:11:31 +01:00
										 |  |  | import {List, ListWrapper, MapWrapper} from 'angular2/src/facade/collection'; | 
					
						
							|  |  |  | import {VmTurnZone} from 'angular2/src/core/zone/vm_turn_zone'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-19 19:10:16 -08:00
										 |  |  | var BUBBLE_SYMBOL = '^'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-09 15:11:31 +01:00
										 |  |  | export class EventManager { | 
					
						
							|  |  |  |   _plugins: List<EventManagerPlugin>; | 
					
						
							|  |  |  |   _zone: VmTurnZone; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   constructor(plugins: List<EventManagerPlugin>, zone: VmTurnZone) { | 
					
						
							|  |  |  |     this._zone = zone; | 
					
						
							|  |  |  |     this._plugins = plugins; | 
					
						
							|  |  |  |     for (var i = 0; i < plugins.length; i++) { | 
					
						
							|  |  |  |       plugins[i].manager = this; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-27 14:50:06 -08:00
										 |  |  |   addEventListener(element, eventName: string, handler: Function) { | 
					
						
							| 
									
										
										
										
											2015-04-02 15:56:58 +02:00
										 |  |  |     var withoutBubbleSymbol = this._removeBubbleSymbol(eventName); | 
					
						
							|  |  |  |     var plugin = this._findPluginFor(withoutBubbleSymbol); | 
					
						
							|  |  |  |     plugin.addEventListener(element, withoutBubbleSymbol, handler, withoutBubbleSymbol != eventName); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-02-19 19:10:16 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-02 15:56:58 +02:00
										 |  |  |   addGlobalEventListener(target: string, eventName: string, handler: Function): Function { | 
					
						
							|  |  |  |     var withoutBubbleSymbol = this._removeBubbleSymbol(eventName); | 
					
						
							|  |  |  |     var plugin = this._findPluginFor(withoutBubbleSymbol); | 
					
						
							|  |  |  |     return plugin.addGlobalEventListener(target, withoutBubbleSymbol, handler, withoutBubbleSymbol != eventName); | 
					
						
							| 
									
										
										
										
											2015-02-09 15:11:31 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   getZone(): VmTurnZone { | 
					
						
							|  |  |  |     return this._zone; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   _findPluginFor(eventName: string): EventManagerPlugin { | 
					
						
							|  |  |  |     var plugins = this._plugins; | 
					
						
							|  |  |  |     for (var i = 0; i < plugins.length; i++) { | 
					
						
							|  |  |  |       var plugin = plugins[i]; | 
					
						
							|  |  |  |       if (plugin.supports(eventName)) { | 
					
						
							|  |  |  |         return plugin; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-02-19 19:10:16 -08:00
										 |  |  |     throw new BaseException(`No event manager plugin found for event ${eventName}`); | 
					
						
							| 
									
										
										
										
											2015-02-09 15:11:31 +01:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-04-02 15:56:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   _removeBubbleSymbol(eventName: string): string { | 
					
						
							|  |  |  |     return eventName[0] == BUBBLE_SYMBOL ? StringWrapper.substring(eventName, 1) : eventName; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-02-09 15:11:31 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export class EventManagerPlugin { | 
					
						
							|  |  |  |   manager: EventManager; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-19 19:10:16 -08:00
										 |  |  |   // We are assuming here that all plugins support bubbled and non-bubbled events.
 | 
					
						
							|  |  |  |   // That is equivalent to having supporting $event.target
 | 
					
						
							| 
									
										
										
										
											2015-04-28 10:56:33 -07:00
										 |  |  |   // The bubbling flag (currently ^) is stripped before calling the supports and
 | 
					
						
							| 
									
										
										
										
											2015-02-19 19:10:16 -08:00
										 |  |  |   // addEventListener methods.
 | 
					
						
							| 
									
										
										
										
											2015-02-09 15:11:31 +01:00
										 |  |  |   supports(eventName: string): boolean { | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-02 15:56:58 +02:00
										 |  |  |   addEventListener(element, eventName: string, handler: Function, shouldSupportBubble: boolean) { | 
					
						
							|  |  |  |     throw "not implemented"; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   addGlobalEventListener(element, eventName: string, handler: Function, shouldSupportBubble: boolean): Function { | 
					
						
							| 
									
										
										
										
											2015-02-09 15:11:31 +01:00
										 |  |  |     throw "not implemented"; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-02-19 19:10:16 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | export class DomEventsPlugin extends EventManagerPlugin { | 
					
						
							|  |  |  |   manager: EventManager; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // This plugin should come last in the list of plugins, because it accepts all
 | 
					
						
							|  |  |  |   // events.
 | 
					
						
							|  |  |  |   supports(eventName: string): boolean { | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-02 15:56:58 +02:00
										 |  |  |   addEventListener(element, eventName: string, handler: Function, shouldSupportBubble: boolean) { | 
					
						
							|  |  |  |     var outsideHandler = this._getOutsideHandler(shouldSupportBubble, element, handler, this.manager._zone); | 
					
						
							| 
									
										
										
										
											2015-02-19 19:10:16 -08:00
										 |  |  |     this.manager._zone.runOutsideAngular(() => { | 
					
						
							|  |  |  |       DOM.on(element, eventName, outsideHandler); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-02 15:56:58 +02:00
										 |  |  |   addGlobalEventListener(target:string, eventName: string, handler: Function, shouldSupportBubble: boolean): Function { | 
					
						
							|  |  |  |     var element = DOM.getGlobalEventTarget(target); | 
					
						
							|  |  |  |     var outsideHandler = this._getOutsideHandler(shouldSupportBubble, element, handler, this.manager._zone); | 
					
						
							|  |  |  |     return this.manager._zone.runOutsideAngular(() => { | 
					
						
							|  |  |  |       return DOM.onAndCancel(element, eventName, outsideHandler); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   _getOutsideHandler(shouldSupportBubble: boolean, element, handler: Function, zone: VmTurnZone) { | 
					
						
							|  |  |  |     return shouldSupportBubble ? | 
					
						
							|  |  |  |       DomEventsPlugin.bubbleCallback(element, handler, zone) : | 
					
						
							|  |  |  |       DomEventsPlugin.sameElementCallback(element, handler, zone); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-19 19:10:16 -08:00
										 |  |  |   static sameElementCallback(element, handler, zone) { | 
					
						
							|  |  |  |     return (event) => { | 
					
						
							|  |  |  |         if (event.target === element) { | 
					
						
							|  |  |  |           zone.run(() => handler(event)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static bubbleCallback(element, handler, zone) { | 
					
						
							|  |  |  |     return (event) => zone.run(() => handler(event)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |