Hedger Wang 73b80773ba supports event capturing and bubbling phases in Navigation context.
Summary: Adds the API that enables the navigation events capturing and bubbling which is the feature
that is enabled if the nested navigation contexts is created by the navigator.

This would allow developer to observe or reconcile navigation events within the navigation tree.

public

./Libraries/FBReactKit/jest

Reviewed By: zjj010104

Differential Revision: D2546451

fb-gh-sync-id: dfc9d16defaa563b9e80fd751a20570f6e524b74
2015-10-19 10:06:22 -07:00

196 lines
5.9 KiB
JavaScript

/**
* Copyright (c) 2015, Facebook, Inc. All rights reserved.
*
* Facebook, Inc. ("Facebook") owns all right, title and interest, including
* all intellectual property and other proprietary rights, in and to the React
* Native CustomComponents software (the "Software"). Subject to your
* compliance with these terms, you are hereby granted a non-exclusive,
* worldwide, royalty-free copyright license to (1) use and copy the Software;
* and (2) reproduce and distribute the Software as part of your own software
* ("Your Software"). Facebook reserves all rights not expressly granted to
* you in this license agreement.
*
* THE SOFTWARE AND DOCUMENTATION, IF ANY, ARE PROVIDED "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES (INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE) ARE DISCLAIMED.
* IN NO EVENT SHALL FACEBOOK OR ITS AFFILIATES, OFFICERS, DIRECTORS OR
* EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @providesModule NavigationEvent
* @flow
*/
'use strict';
var invariant = require('invariant');
class NavigationEventPool {
_list: Array<any>;
constructor() {
this._list = [];
}
get(type: string, currentTarget: Object, data: any): NavigationEvent {
var event;
if (this._list.length > 0) {
event = this._list.pop();
event.constructor.call(event, type, currentTarget, data);
} else {
event = new NavigationEvent(type, currentTarget, data);
}
return event;
}
put(event: NavigationEvent) {
this._list.push(event);
}
}
var _navigationEventPool = new NavigationEventPool();
/**
* The NavigationEvent interface represents any event of the navigation.
* It contains common properties and methods to any event.
*
* == Important Properties ==
*
* - target:
* A reference to the navigation context that dispatched the event. It is
* different from event.currentTarget when the event handler is called during
* the bubbling or capturing phase of the event.
*
* - currentTarget:
* Identifies the current target for the event, as the event traverses the
* navigation context tree. It always refers to the navigation context the
* event handler has been attached to as opposed to event.target which
* identifies the navigation context on which the event occurred.
*
* - eventPhase:
* Returns an integer value which specifies the current evaluation phase of
* the event flow; possible values are listed in NavigationEvent phase
* constants below.
*/
class NavigationEvent {
static AT_TARGET: number;
static BUBBLING_PHASE: number;
static CAPTURING_PHASE: number;
static NONE: number;
_currentTarget: ?Object;
_data: any;
_defaultPrevented: boolean;
_disposed: boolean;
_propagationStopped: boolean;
_type: ?string;
target: ?Object;
// Returns an integer value which specifies the current evaluation phase of
// the event flow.
eventPhase: number;
static pool(type: string, currentTarget: Object, data: any): NavigationEvent {
return _navigationEventPool.get(type, currentTarget, data);
}
constructor(type: string, currentTarget: Object, data: any) {
this.target = currentTarget;
this.eventPhase = NavigationEvent.NONE;
this._type = type;
this._currentTarget = currentTarget;
this._data = data;
this._defaultPrevented = false;
this._disposed = false;
this._propagationStopped = false;
}
/* $FlowFixMe - get/set properties not yet supported */
get type(): string {
return this._type;
}
/* $FlowFixMe - get/set properties not yet supported */
get currentTarget(): Object {
return this._currentTarget;
}
/* $FlowFixMe - get/set properties not yet supported */
get data(): any {
return this._data;
}
/* $FlowFixMe - get/set properties not yet supported */
get defaultPrevented(): boolean {
return this._defaultPrevented;
}
preventDefault(): void {
this._defaultPrevented = true;
}
stopPropagation(): void {
this._propagationStopped = true;
}
stop(): void {
this.preventDefault();
this.stopPropagation();
}
isPropagationStopped(): boolean {
return this._propagationStopped;
}
/**
* Dispose the event.
* NavigationEvent shall be disposed after being emitted by
* `NavigationEventEmitter`.
*/
dispose(): void {
invariant(!this._disposed, 'NavigationEvent is already disposed');
this._disposed = true;
// Clean up.
this.target = null;
this.eventPhase = NavigationEvent.NONE;
this._type = null;
this._currentTarget = null;
this._data = null;
this._defaultPrevented = false;
// Put this back to the pool to reuse the instance.
_navigationEventPool.put(this);
}
}
/**
* Event phase constants.
* These values describe which phase the event flow is currently being
* evaluated.
*/
// No event is being processed at this time.
NavigationEvent.NONE = 0;
// The event is being propagated through the currentTarget's ancestor objects.
NavigationEvent.CAPTURING_PHASE = 1;
// The event has arrived at the event's currentTarget. Event listeners registered for
// this phase are called at this time.
NavigationEvent.AT_TARGET = 2;
// The event is propagating back up through the currentTarget's ancestors in reverse
// order, starting with the parent. This is known as bubbling, and occurs only
// if event propagation isn't prevented. Event listeners registered for this
// phase are triggered during this process.
NavigationEvent.BUBBLING_PHASE = 3;
module.exports = NavigationEvent;