diff --git a/apps/tests/gestures-tests.ts b/apps/tests/gestures-tests.ts index a4e594924..47ccd6be0 100644 --- a/apps/tests/gestures-tests.ts +++ b/apps/tests/gestures-tests.ts @@ -13,7 +13,19 @@ export var test_DummyTestForSnippetOnly0 = function () { // ### Double Tap // ``` JavaScript var label = new labelModule.Label(); - var observer = label.observe(gestures.GestureTypes.doubleTap, function (args: gestures.GestureEventData) { + var observer = label.on(gestures.GestureTypes.doubleTap, function (args: gestures.GestureEventData) { + console.log("Double Tap"); + }); + // ``` + // +} + +export var test_DummyTestForSnippetOnly01 = function () { + // + // ### Double Tap + // ``` JavaScript + var label = new labelModule.Label(); + var observer = label.on("doubleTap", function (args: gestures.GestureEventData) { console.log("Double Tap"); }); // ``` @@ -25,7 +37,19 @@ export var test_DummyTestForSnippetOnly1 = function () { // ### Long Press // ``` JavaScript var label = new labelModule.Label(); - var observer = label.observe(gestures.GestureTypes.longPress, function (args: gestures.GestureEventData) { + var observer = label.on(gestures.GestureTypes.longPress, function (args: gestures.GestureEventData) { + console.log("Long Press"); + }); + // ``` + // +} + +export var test_DummyTestForSnippetOnly11 = function () { + // + // ### Long Press + // ``` JavaScript + var label = new labelModule.Label(); + var observer = label.on("longPress", function (args: gestures.GestureEventData) { console.log("Long Press"); }); // ``` @@ -37,7 +61,19 @@ export var test_DummyTestForSnippetOnly2 = function () { // ### Pan // ``` JavaScript var label = new labelModule.Label(); - var observer = label.observe(gestures.GestureTypes.pan, function (args: gestures.PanGestureEventData) { + var observer = label.on(gestures.GestureTypes.pan, function (args: gestures.PanGestureEventData) { + console.log("Pan deltaX:" + args.deltaX + "; deltaY:" + args.deltaY + ";"); + }); + // ``` + // +} + +export var test_DummyTestForSnippetOnly22 = function () { + // + // ### Pan + // ``` JavaScript + var label = new labelModule.Label(); + var observer = label.on("pan", function (args: gestures.PanGestureEventData) { console.log("Pan deltaX:" + args.deltaX + "; deltaY:" + args.deltaY + ";"); }); // ``` @@ -49,7 +85,19 @@ export var test_DummyTestForSnippetOnly3 = function () { // ### Pinch // ``` JavaScript var label = new labelModule.Label(); - var observer = label.observe(gestures.GestureTypes.pinch, function (args: gestures.PinchGestureEventData) { + var observer = label.on(gestures.GestureTypes.pinch, function (args: gestures.PinchGestureEventData) { + console.log("Pinch scale: " + args.scale); + }); + // ``` + // +} + +export var test_DummyTestForSnippetOnly33 = function () { + // + // ### Pinch + // ``` JavaScript + var label = new labelModule.Label(); + var observer = label.on("pinch", function (args: gestures.PinchGestureEventData) { console.log("Pinch scale: " + args.scale); }); // ``` @@ -61,7 +109,19 @@ export var test_DummyTestForSnippetOnly4 = function () { // ### Rotation // ``` JavaScript var label = new labelModule.Label(); - var observer = label.observe(gestures.GestureTypes.rotation, function (args: gestures.RotationGestureEventData) { + var observer = label.on(gestures.GestureTypes.rotation, function (args: gestures.RotationGestureEventData) { + console.log("Rotation: " + args.rotation); + }); + // ``` + // +} + +export var test_DummyTestForSnippetOnly44 = function () { + // + // ### Rotation + // ``` JavaScript + var label = new labelModule.Label(); + var observer = label.on("rotation", function (args: gestures.RotationGestureEventData) { console.log("Rotation: " + args.rotation); }); // ``` @@ -73,7 +133,19 @@ export var test_DummyTestForSnippetOnly5 = function () { // ### Swipe // ``` JavaScript var label = new labelModule.Label(); - var observer = label.observe(gestures.GestureTypes.swipe, function (args: gestures.SwipeGestureEventData) { + var observer = label.on(gestures.GestureTypes.swipe, function (args: gestures.SwipeGestureEventData) { + console.log("Swipe direction: " + args.direction); + }); + // ``` + // +} + +export var test_DummyTestForSnippetOnly55 = function () { + // + // ### Swipe + // ``` JavaScript + var label = new labelModule.Label(); + var observer = label.on("swipe", function (args: gestures.SwipeGestureEventData) { console.log("Swipe direction: " + args.direction); }); // ``` @@ -85,7 +157,19 @@ export var test_DummyTestForSnippetOnly6 = function () { // ### Tap // ``` JavaScript var label = new labelModule.Label(); - var observer = label.observe(gestures.GestureTypes.tap, function (args: gestures.GestureEventData) { + var observer = label.on(gestures.GestureTypes.tap, function (args: gestures.GestureEventData) { + console.log("Tap"); + }); + // ``` + // +} + +export var test_DummyTestForSnippetOnly66 = function () { + // + // ### Tap + // ``` JavaScript + var label = new labelModule.Label(); + var observer = label.on("tap", function (args: gestures.GestureEventData) { console.log("Tap"); }); // ``` @@ -97,10 +181,46 @@ export var test_DummyTestForSnippetOnly7 = function () { // ### Stop observing // ``` JavaScript var label = new labelModule.Label(); - var observer = label.observe(gestures.GestureTypes.tap, function (args: gestures.GestureEventData) { + var observer = label.on(gestures.GestureTypes.tap, function (args: gestures.GestureEventData) { console.log("Tap"); }); observer.disconnect(); // ``` // +} + +export var test_DummyTestForSnippetOnly8 = function () { + // + // ### Multiple gestures + // ``` JavaScript + var label = new labelModule.Label(); + var observer = label.on(gestures.GestureTypes.tap | gestures.GestureTypes.doubleTap | gestures.GestureTypes.longPress, function (args: gestures.GestureEventData) { + console.log("Event: " + args.eventName); + }); + // ``` + // +} + +export var test_DummyTestForSnippetOnly88 = function () { + // + // ### Multiple gestures as comma separated string + // ``` JavaScript + var label = new labelModule.Label(); + var observer = label.on("tap, doubleTap, longPress", function (args: gestures.GestureEventData) { + console.log("Event: " + args.eventName); + }); + // ``` + // +} + +export var test_DummyTestForSnippetOnly9 = function () { + // + // ### Events combined with gestures as comma separated string + // ``` JavaScript + var label = new labelModule.Label(); + var observer = label.on("loaded, tap, longPress", function (args: gestures.GestureEventData) { + console.log("Event: " + args.eventName); + }); + // ``` + // } \ No newline at end of file diff --git a/apps/ui-tests-app/pages/gestures.ts b/apps/ui-tests-app/pages/gestures.ts index d72851431..09190c02f 100644 --- a/apps/ui-tests-app/pages/gestures.ts +++ b/apps/ui-tests-app/pages/gestures.ts @@ -62,43 +62,43 @@ export function createPage() { rotaionLabel.text = "Gestures detection disabled"; }); - tapLabel.observe(gestures.GestureTypes.tap, function (args: gestures.GestureEventData) { + tapLabel.on(gestures.GestureTypes.tap, function (args: gestures.GestureEventData) { tapLabel.text = "Tap gesture detected"; }); var observer1 = tapLabel.getGestureObservers(gestures.GestureTypes.tap)[0]; - doubletapLabel.observe(gestures.GestureTypes.doubleTap, function (args: gestures.GestureEventData) { + doubletapLabel.on(gestures.GestureTypes.doubleTap, function (args: gestures.GestureEventData) { doubletapLabel.text = "Double Tap gesture detected"; }); var observer2 = doubletapLabel.getGestureObservers(gestures.GestureTypes.doubleTap)[0]; - longpressLabel.observe(gestures.GestureTypes.longPress, function (args: gestures.GestureEventData) { + longpressLabel.on(gestures.GestureTypes.longPress, function (args: gestures.GestureEventData) { longpressLabel.text = "Long Press gesture detected"; }); var observer3 = longpressLabel.getGestureObservers(gestures.GestureTypes.longPress)[0]; - swipeLabel.observe(gestures.GestureTypes.swipe, function (args: gestures.SwipeGestureEventData) { + swipeLabel.on(gestures.GestureTypes.swipe, function (args: gestures.SwipeGestureEventData) { swipeLabel.text = "Swipe Direction: " + args.direction; }); var observer4 = swipeLabel.getGestureObservers(gestures.GestureTypes.swipe)[0]; - panLabel.observe(gestures.GestureTypes.pan, function (args: gestures.PanGestureEventData) { + panLabel.on(gestures.GestureTypes.pan, function (args: gestures.PanGestureEventData) { panLabel.text = "Pan deltaX:" + args.deltaX + "; deltaY:" + args.deltaY + ";"; }); var observer5 = panLabel.getGestureObservers(gestures.GestureTypes.pan)[0]; - pinchLabel.observe(gestures.GestureTypes.pinch, function (args: gestures.PinchGestureEventData) { + pinchLabel.on(gestures.GestureTypes.pinch, function (args: gestures.PinchGestureEventData) { pinchLabel.text = "Pinch Scale: " + args.scale; }); var observer6 = pinchLabel.getGestureObservers(gestures.GestureTypes.pinch)[0]; - rotaionLabel.observe(gestures.GestureTypes.rotation, function (args: gestures.RotationGestureEventData) { + rotaionLabel.on(gestures.GestureTypes.rotation, function (args: gestures.RotationGestureEventData) { rotaionLabel.text = "Rotation: " + args.rotation; }); diff --git a/ui/builder/component-builder.ts b/ui/builder/component-builder.ts index 9274fd903..5c7be9671 100644 --- a/ui/builder/component-builder.ts +++ b/ui/builder/component-builder.ts @@ -11,7 +11,6 @@ import gestures = require("ui/gestures"); import bindingBuilder = require("ui/builder/binding-builder"); import platform = require("platform"); -var EVENT = "Event"; var UI_PATH = "ui/"; var MODULES = { "TabViewItem": "ui/tab-view", @@ -30,8 +29,7 @@ var DOCK = "dock"; var LEFT = "left"; var TOP = "top"; -var eventHandlers = {}, - gestureHandlers = {}; +var eventHandlers = {}; export function getComponentModule(elementName: string, namespace: string, attributes: Object, exports: Object): definition.ComponentModule { var instance: view.View; @@ -106,7 +104,7 @@ export function getComponentModule(elementName: string, namespace: string, attri } } - eventHandlers, gestureHandlers = {}; + eventHandlers = {}; componentModule = { component: instance, exports: instanceModule, bindings: bindings }; } @@ -116,13 +114,11 @@ export function getComponentModule(elementName: string, namespace: string, attri export function setPropertyValue(instance: view.View, instanceModule: Object, exports: Object, propertyName: string, propertyValue: string) { // Note: instanceModule can be null if we are loading custom compnenet with no code-behind. - var isEvent: boolean = instanceModule && isKnownEvent(propertyName, instanceModule[instance.typeName]); + var isEventOrGesture: boolean = isKnownEventOrGesture(propertyName, instance); if (isBinding(propertyValue) && instance.bind) { - if (isEvent) { + if (isEventOrGesture) { attachEventBinding(instance, propertyName, propertyValue); - } else if (isGesture(propertyName, instance)) { - attachGestureBinding(instance, propertyName, propertyValue); } else { var bindOptions = bindingBuilder.getBindingOptions(propertyName, getBindingExpressionFromAttribute(propertyValue)); instance.bind({ @@ -132,7 +128,7 @@ export function setPropertyValue(instance: view.View, instanceModule: Object, ex twoWay: bindOptions[bindingBuilder.bindingConstants.twoWay] }, bindOptions[bindingBuilder.bindingConstants.source]); } - } else if (isEvent) { + } else if (isEventOrGesture) { // Get the event handler from page module exports. var handler = exports && exports[propertyValue]; @@ -140,14 +136,6 @@ export function setPropertyValue(instance: view.View, instanceModule: Object, ex if (types.isFunction(handler)) { instance.on(propertyName, handler); } - } else if (isGesture(propertyName, instance)) { - // Get the event handler from page module exports. - var gestureHandler = exports && exports[propertyValue]; - - // Check if the handler is function and add it to the instance for specified gesture. - if (types.isFunction(gestureHandler)) { - instance.observe(gestures.fromString(propertyName.toLowerCase()), gestureHandler); - } } else if (propertyName === ROW) { gridLayoutModule.GridLayout.setRow(instance, !isNaN(+propertyValue) && +propertyValue); } else if (propertyName === COL) { @@ -199,30 +187,15 @@ function attachEventBinding(instance: view.View, eventName: string, value: strin instance.on(observable.Observable.propertyChangeEvent, eventHandlers[eventName]); } -function attachGestureBinding(instance: view.View, gestureName: string, value: string) { - // Get the event handler from instance.bindingContext. - gestureHandlers[gestureName] = (args: observable.PropertyChangeData) => { - if (args.propertyName === "bindingContext") { - var handler = instance.bindingContext && instance.bindingContext[getBindingExpressionFromAttribute(value)]; - // Check if the handler is function and add it to the instance for specified event name. - if (types.isFunction(handler)) { - instance.observe(gestures.fromString(gestureName.toLowerCase()), handler, instance.bindingContext); - } - instance.off(observable.Observable.propertyChangeEvent, gestureHandlers[gestureName]); - } - }; +function isKnownEventOrGesture(name: string, instance: any): boolean { + if (types.isString(name)) { + var evt = `${name}Event`; - instance.on(observable.Observable.propertyChangeEvent, gestureHandlers[gestureName]); -} + return instance.constructor && evt in instance.constructor || + gestures.fromString(name.toLowerCase()) !== undefined; + } -function isGesture(name: string, instance: any): boolean { - return gestures.fromString(name.toLowerCase()) !== undefined; -} - -function isKnownEvent(name: string, exports: any): boolean { - var nameEvent = name + EVENT; - var result = !types.isNullOrUndefined(exports) ? nameEvent in exports : false; - return result; + return false; } function getBindingExpressionFromAttribute(value: string): string { diff --git a/ui/core/view-common.ts b/ui/core/view-common.ts index 0306dc9c9..21fcfc732 100644 --- a/ui/core/view-common.ts +++ b/ui/core/view-common.ts @@ -13,6 +13,7 @@ import enums = require("ui/enums"); import utils = require("utils/utils"); import color = require("color"); import animationModule = require("ui/animation"); +import observable = require("data/observable"); export function getViewById(view: View, id: string): View { if (!view) { @@ -191,6 +192,70 @@ export class View extends proxy.ProxyObject implements definition.View { return list; } + public addEventListener(arg: string | gestures.GestureTypes, callback: (data: observable.EventData) => void, thisArg?: any) { + if (types.isString(arg)) { + var gesture = gestures.fromString(arg); + if (gesture && !this._isEvent(arg)) { + this.observe(gesture, callback, thisArg); + } else { + var events = (arg).split(","); + if (events.length > 0) { + for (let i = 0; i < events.length; i++) { + let evt = events[i].trim(); + let gst = gestures.fromString(evt); + if (gst && !this._isEvent(arg)) { + this.observe(gst, callback, thisArg); + } else { + super.addEventListener(evt, callback, thisArg); + } + } + } else { + super.addEventListener(arg, callback, thisArg); + } + } + } else if (types.isNumber(arg)) { + this.observe(arg, callback, thisArg); + } + } + + public removeEventListener(arg: string | gestures.GestureTypes, callback?: any, thisArg?: any) { + if (types.isString(arg)) { + var gesture = gestures.fromString(arg); + if (gesture && !this._isEvent(arg)) { + this._disconnectGestureObservers(gesture); + } else { + var events = (arg).split(","); + if (events.length > 0) { + for (let i = 0; i < events.length; i++) { + let evt = events[i].trim(); + let gst = gestures.fromString(evt); + if (gst && !this._isEvent(arg)) { + this._disconnectGestureObservers(gst); + } else { + super.removeEventListener(evt, callback, thisArg); + } + } + } else { + super.removeEventListener(arg, callback, thisArg); + } + + } + } else if (types.isNumber(arg)) { + this._disconnectGestureObservers(arg); + } + } + + private _isEvent(name: string): boolean { + return this.constructor && `${name}Event` in this.constructor; + } + + private _disconnectGestureObservers(type: gestures.GestureTypes): void { + var observers = this.getGestureObservers(type); + for (let i = 0; i < observers.length; i++) { + observers[i].disconnect(); + } + } + getViewById(id: string): T { return getViewById(this, id); } diff --git a/ui/core/view.d.ts b/ui/core/view.d.ts index b2eab2809..e635d499d 100644 --- a/ui/core/view.d.ts +++ b/ui/core/view.d.ts @@ -365,7 +365,7 @@ declare module "ui/core/view" { public getGestureObservers(type: gestures.GestureTypes): Array; /** - * Adds a gesture observer. + * [Deprecated. Please use the on() instead.] Adds a gesture observer. * @param type - Type of the gesture. * @param callback - A function that will be executed when gesture is received. * @param thisArg - An optional parameter which will be used as `this` context for callback execution. @@ -374,11 +374,19 @@ declare module "ui/core/view" { /** * A basic method signature to hook an event listener (shortcut alias to the addEventListener method). - * @param eventNames - String corresponding to events (e.g. "propertyChange"). Optionally could be used more events separated by `,` (e.g. "propertyChange", "change"). + * @param eventNames - String corresponding to events (e.g. "propertyChange"). Optionally could be used more events separated by `,` (e.g. "propertyChange", "change") or you can use gesture types. * @param callback - Callback function which will be executed when event is raised. * @param thisArg - An optional parameter which will be used as `this` context for callback execution. */ - on(eventNames: string, callback: (data: observable.EventData) => void, thisArg?: any); + on(eventNames: string | gestures.GestureTypes, callback: (data: observable.EventData) => void, thisArg?: any); + + /** + * Removes listener(s) for the specified event name. + * @param eventNames Comma delimited names of the events or gesture types the specified listener is associated with. + * @param callback An optional parameter pointing to a specific listener. If not defined, all listeners for the event names will be removed. + * @param thisArg An optional parameter which when set will be used to refine search of the correct callback which will be removed as event listener. + */ + off(eventNames: string | gestures.GestureTypes, callback?: any, thisArg?: any); /** * Raised when a loaded event occurs. diff --git a/ui/gestures/gestures.android.ts b/ui/gestures/gestures.android.ts index 489f01dee..0bfc1f52c 100644 --- a/ui/gestures/gestures.android.ts +++ b/ui/gestures/gestures.android.ts @@ -130,7 +130,10 @@ function _getArgs(type: definition.GestureTypes, view: view.View, e: android.vie return { type: type, view: view, - android: e + android: e, + ios: undefined, + object: view, + eventName: definition.toString(type), }; } @@ -140,7 +143,10 @@ function _getSwipeArgs(direction: definition.SwipeDirection, view: view.View, type: definition.GestureTypes.swipe, view: view, android: { initial: initialEvent, current: currentEvent }, - direction: direction + direction: direction, + ios: undefined, + object: view, + eventName: definition.toString(definition.GestureTypes.swipe), }; } @@ -151,7 +157,10 @@ function _getPanArgs(deltaX: number, deltaY: number, view: view.View, view: view, android: { initial: initialEvent, current: currentEvent }, deltaX: deltaX, - deltaY: deltaY + deltaY: deltaY, + ios: undefined, + object: view, + eventName: definition.toString(definition.GestureTypes.pan), }; } diff --git a/ui/gestures/gestures.d.ts b/ui/gestures/gestures.d.ts index 297a7c960..8075edeb2 100644 --- a/ui/gestures/gestures.d.ts +++ b/ui/gestures/gestures.d.ts @@ -3,6 +3,7 @@ */ declare module "ui/gestures" { import view = require("ui/core/view"); + import observable = require("data/observable"); /** * Defines an enum with supported gesture types. @@ -63,7 +64,7 @@ declare module "ui/gestures" { /** * Provides gesture event data. */ - export interface GestureEventData { + export interface GestureEventData extends observable.EventData { /** * Gets the type of the gesture. */ diff --git a/ui/gestures/gestures.ios.ts b/ui/gestures/gestures.ios.ts index 36ae6b6cc..260eb6055 100644 --- a/ui/gestures/gestures.ios.ts +++ b/ui/gestures/gestures.ios.ts @@ -44,7 +44,9 @@ class UIGestureRecognizerImpl extends NSObject { type: type, view: target, ios: recognizer, - android: undefined + android: undefined, + object: view, + eventName: definition.toString(type), }; if (callback) { @@ -257,6 +259,8 @@ function _getPinchData(args: definition.GestureEventData): definition.PinchGestu ios: args.ios, android: undefined, scale: recognizer.scale, + object: args.view, + eventName: definition.toString(args.type) }; } @@ -268,6 +272,8 @@ function _getSwipeData(args: definition.GestureEventData): definition.SwipeGestu ios: args.ios, android: undefined, direction: _getSwipeDirection(recognizer.direction), + object: args.view, + eventName: definition.toString(args.type) }; } @@ -279,7 +285,9 @@ function _getPanData(args: definition.GestureEventData, view: UIView): definitio ios: args.ios, android: undefined, deltaX: recognizer.translationInView(view).x, - deltaY: recognizer.translationInView(view).y + deltaY: recognizer.translationInView(view).y, + object: args.view, + eventName: definition.toString(args.type) }; } @@ -291,5 +299,7 @@ function _getRotationData(args: definition.GestureEventData): definition.Rotatio ios: args.ios, android: undefined, rotation: recognizer.rotation * (180.0 / Math.PI), + object: args.view, + eventName: definition.toString(args.type) }; }