13
13
14
14
var EventConstants = require ( 'EventConstants' ) ;
15
15
var EventPluginRegistry = require ( 'EventPluginRegistry' ) ;
16
+ var ReactEventListener = require ( 'ReactEventListener' ) ;
16
17
var ReactEventEmitterMixin = require ( 'ReactEventEmitterMixin' ) ;
17
18
var ViewportMetrics = require ( 'ViewportMetrics' ) ;
18
19
@@ -154,6 +155,22 @@ var topEventMapping = {
154
155
*/
155
156
var topListenersIDKey = '_reactListenersID' + String ( Math . random ( ) ) . slice ( 2 ) ;
156
157
158
+ /**
159
+ * Resets the document state that records registered listener tracking.
160
+ * Document is passed as a parameter allowing the react app to be loaded in a single window, and within an IFRAME that
161
+ * renders to the main window.
162
+ * @param {object } The document holding the root container.
163
+ */
164
+ ReactEventListener . setDocumentResetCallback ( function ( doc ) {
165
+ // This must be called during a document reset (@see ReactEventListener.resetDocument)
166
+ // after unmounting the last component, otherwise the next render will be visible,
167
+ // but document level event listeners will be missing, and input (clicks, typing etc)
168
+ // wont work.
169
+ reactTopListenersCounter = 0 ;
170
+ alreadyListeningTo = { } ;
171
+ delete doc [ topListenersIDKey ] ;
172
+ } ) ;
173
+
157
174
function getListeningForDocument ( mountAt ) {
158
175
// In IE8, `mountAt` is a host object and doesn't have `hasOwnProperty`
159
176
// directly.
@@ -234,13 +251,37 @@ var ReactBrowserEventEmitter = Object.assign({}, ReactEventEmitterMixin, {
234
251
*
235
252
* @param {string } registrationName Name of listener (e.g. `onClick`).
236
253
* @param {object } contentDocumentHandle Document which owns the container
254
+ * @return {function } A function that removes ALL listeners that were added.
237
255
*/
238
256
listenTo : function ( registrationName , contentDocumentHandle ) {
239
257
var mountAt = contentDocumentHandle ;
240
258
var isListening = getListeningForDocument ( mountAt ) ;
241
259
var dependencies =
242
260
EventPluginRegistry . registrationNameDependencies [ registrationName ] ;
243
261
262
+ // aggregates handler remove functions...
263
+ var listenerRemovers = [ ] ;
264
+ var trapBubbledEvent = function ( topLevelType , handlerBaseName ) {
265
+ var remover = ReactBrowserEventEmitter . ReactEventListener . trapBubbledEvent (
266
+ topLevelType ,
267
+ handlerBaseName ,
268
+ mountAt
269
+ ) ;
270
+ if ( remover && remover . remove ) {
271
+ listenerRemovers . push ( remover . remove ) ;
272
+ }
273
+ } ;
274
+ var trapCapturedEvent = function ( topLevelType , handlerBaseName , handle ) {
275
+ var remover = ReactBrowserEventEmitter . ReactEventListener . trapCapturedEvent (
276
+ topLevelType ,
277
+ handlerBaseName ,
278
+ handle
279
+ ) ;
280
+ if ( remover && remover . remove ) {
281
+ listenerRemovers . push ( remover . remove ) ;
282
+ }
283
+ } ;
284
+
244
285
var topLevelTypes = EventConstants . topLevelTypes ;
245
286
for ( var i = 0 ; i < dependencies . length ; i ++ ) {
246
287
var dependency = dependencies [ i ] ;
@@ -250,21 +291,21 @@ var ReactBrowserEventEmitter = Object.assign({}, ReactEventEmitterMixin, {
250
291
) ) {
251
292
if ( dependency === topLevelTypes . topWheel ) {
252
293
if ( isEventSupported ( 'wheel' ) ) {
253
- ReactBrowserEventEmitter . ReactEventListener . trapBubbledEvent (
294
+ trapBubbledEvent (
254
295
topLevelTypes . topWheel ,
255
296
'wheel' ,
256
297
mountAt
257
298
) ;
258
299
} else if ( isEventSupported ( 'mousewheel' ) ) {
259
- ReactBrowserEventEmitter . ReactEventListener . trapBubbledEvent (
300
+ trapBubbledEvent (
260
301
topLevelTypes . topWheel ,
261
302
'mousewheel' ,
262
303
mountAt
263
304
) ;
264
305
} else {
265
306
// Firefox needs to capture a different mouse scroll event.
266
307
// @see http://www.quirksmode.org/dom/events/tests/scroll.html
267
- ReactBrowserEventEmitter . ReactEventListener . trapBubbledEvent (
308
+ trapBubbledEvent (
268
309
topLevelTypes . topWheel ,
269
310
'DOMMouseScroll' ,
270
311
mountAt
@@ -273,13 +314,13 @@ var ReactBrowserEventEmitter = Object.assign({}, ReactEventEmitterMixin, {
273
314
} else if ( dependency === topLevelTypes . topScroll ) {
274
315
275
316
if ( isEventSupported ( 'scroll' , true ) ) {
276
- ReactBrowserEventEmitter . ReactEventListener . trapCapturedEvent (
317
+ trapCapturedEvent (
277
318
topLevelTypes . topScroll ,
278
319
'scroll' ,
279
320
mountAt
280
321
) ;
281
322
} else {
282
- ReactBrowserEventEmitter . ReactEventListener . trapBubbledEvent (
323
+ trapBubbledEvent (
283
324
topLevelTypes . topScroll ,
284
325
'scroll' ,
285
326
ReactBrowserEventEmitter . ReactEventListener . WINDOW_HANDLE
@@ -289,25 +330,25 @@ var ReactBrowserEventEmitter = Object.assign({}, ReactEventEmitterMixin, {
289
330
dependency === topLevelTypes . topBlur ) {
290
331
291
332
if ( isEventSupported ( 'focus' , true ) ) {
292
- ReactBrowserEventEmitter . ReactEventListener . trapCapturedEvent (
333
+ trapCapturedEvent (
293
334
topLevelTypes . topFocus ,
294
335
'focus' ,
295
336
mountAt
296
337
) ;
297
- ReactBrowserEventEmitter . ReactEventListener . trapCapturedEvent (
338
+ trapCapturedEvent (
298
339
topLevelTypes . topBlur ,
299
340
'blur' ,
300
341
mountAt
301
342
) ;
302
343
} else if ( isEventSupported ( 'focusin' ) ) {
303
344
// IE has `focusin` and `focusout` events which bubble.
304
345
// @see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html
305
- ReactBrowserEventEmitter . ReactEventListener . trapBubbledEvent (
346
+ trapBubbledEvent (
306
347
topLevelTypes . topFocus ,
307
348
'focusin' ,
308
349
mountAt
309
350
) ;
310
- ReactBrowserEventEmitter . ReactEventListener . trapBubbledEvent (
351
+ trapBubbledEvent (
311
352
topLevelTypes . topBlur ,
312
353
'focusout' ,
313
354
mountAt
@@ -318,7 +359,7 @@ var ReactBrowserEventEmitter = Object.assign({}, ReactEventEmitterMixin, {
318
359
isListening [ topLevelTypes . topBlur ] = true ;
319
360
isListening [ topLevelTypes . topFocus ] = true ;
320
361
} else if ( topEventMapping . hasOwnProperty ( dependency ) ) {
321
- ReactBrowserEventEmitter . ReactEventListener . trapBubbledEvent (
362
+ trapBubbledEvent (
322
363
dependency ,
323
364
topEventMapping [ dependency ] ,
324
365
mountAt
@@ -328,6 +369,14 @@ var ReactBrowserEventEmitter = Object.assign({}, ReactEventEmitterMixin, {
328
369
isListening [ dependency ] = true ;
329
370
}
330
371
}
372
+
373
+ return function ( ) {
374
+ listenerRemovers . forEach (
375
+ function ( remover ) {
376
+ remover ( ) ;
377
+ }
378
+ ) ;
379
+ } ;
331
380
} ,
332
381
333
382
trapBubbledEvent : function ( topLevelType , handlerBaseName , handle ) {
0 commit comments