@@ -3,6 +3,8 @@ var EventBinding = require('./EventBinding');
33var EventDispatcher = function ( )
44{
55 this . bindings = { } ;
6+ this . filters = [ ] ;
7+ this . hasFilters = false ;
68} ;
79
810EventDispatcher . prototype . constructor = EventDispatcher ;
@@ -55,6 +57,29 @@ EventDispatcher.prototype = {
5557 return this ;
5658 } ,
5759
60+ // Add a callback that is notified every time this EventDispatcher dispatches an event
61+ // no matter what the event type is. Filters are invoked first, before any bindings,
62+ // and can stop events if they wish (in which case they'll never reach the bindings)
63+ filter : function ( callback )
64+ {
65+ var i = this . filters . indexOf ( callback ) ;
66+
67+ if ( i === - 1 )
68+ {
69+ // Add the filter
70+ this . filters . push ( callback ) ;
71+ }
72+ else
73+ {
74+ // Remove the filter
75+ this . filters . splice ( i , 1 ) ;
76+ }
77+
78+ this . hasFilters = ( this . filters . length > 0 ) ;
79+
80+ return this ;
81+ } ,
82+
5883 has : function ( type , listener )
5984 {
6085 var binding = this . getBinding ( type ) ;
@@ -93,31 +118,47 @@ EventDispatcher.prototype = {
93118 return this ;
94119 } ,
95120
96- dispatch : function ( event )
121+ _dispatchHandler : function ( event )
97122 {
98- var binding ;
123+ event . reset ( this ) ;
99124
100- if ( Array . isArray ( event ) )
125+ // Pass the event through the filters first
126+
127+ if ( this . hasFilters )
101128 {
102- for ( var i = 0 ; i < event . length ; i ++ )
129+ for ( var i = 0 ; i < this . filters . length ; i ++ )
103130 {
104- binding = this . getBinding ( event [ i ] . type ) ;
131+ this . filters [ i ] . call ( this , event ) ;
105132
106- if ( binding )
133+ // Did the filter kill the event? If so, we can abort now
134+ if ( ! event . _propagate )
107135 {
108- return binding . dispatch ( event [ i ] ) ;
136+ return ;
109137 }
110138 }
111139 }
112- else
140+
141+ var binding = this . getBinding ( event . type ) ;
142+
143+ if ( binding )
113144 {
114- binding = this . getBinding ( event . type ) ;
145+ binding . dispatch ( event ) ;
146+ }
147+ } ,
115148
116- if ( binding )
149+ dispatch : function ( event )
150+ {
151+ if ( Array . isArray ( event ) )
152+ {
153+ for ( var i = 0 ; i < event . length ; i ++ )
117154 {
118- return binding . dispatch ( event ) ;
155+ this . _dispatchHandler ( event [ i ] ) ;
119156 }
120157 }
158+ else
159+ {
160+ this . _dispatchHandler ( event ) ;
161+ }
121162 } ,
122163
123164 // Removes all listeners, but retains the event type entries
@@ -133,6 +174,15 @@ EventDispatcher.prototype = {
133174 return this ;
134175 } ,
135176
177+ removeAllFilters : function ( )
178+ {
179+ this . filters . length = 0 ;
180+
181+ this . hasFilters = false ;
182+
183+ return this ;
184+ } ,
185+
136186 delete : function ( type )
137187 {
138188 var binding = this . getBinding ( type ) ;
@@ -159,7 +209,8 @@ EventDispatcher.prototype = {
159209
160210 destroy : function ( )
161211 {
162- // What would it do any differently to deleteAll?
212+ this . deleteAll ( ) ;
213+ this . removeAllFilters ( ) ;
163214 }
164215
165216} ;
0 commit comments