From ab2896b51705bc79402e2f49432bfc2716bbc514 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Cha=CC=81varri?= Date: Wed, 9 Sep 2015 02:38:55 +0200 Subject: [PATCH 01/14] First steps on gesture integration --- framer/EventManager.coffee | 20 ++++++++++++++------ framer/Events.coffee | 17 +++++++++++++++++ framer/GestureManager.coffee | 32 ++++++++++++++++++++++++++++++++ package.json | 1 + 4 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 framer/GestureManager.coffee diff --git a/framer/EventManager.coffee b/framer/EventManager.coffee index 21faa4031..1ffe60bd4 100644 --- a/framer/EventManager.coffee +++ b/framer/EventManager.coffee @@ -1,4 +1,5 @@ Utils = require "./Utils" +{GestureManager} = require "./GestureManager" EventManagerIdCounter = 0 @@ -6,24 +7,31 @@ class EventManagerElement constructor: (@element) -> @_events = {} + @_gestureManager = new GestureManager(@element) addEventListener: (eventName, listener) -> - # Filter out all the events that are not dom valid - if not Utils.domValidEvent(@element, eventName) - return - + # Filter out all the events that are not dom valid or a gesture + return unless Utils.domValidEvent(@element, eventName) or Events.isGestureEvent eventName + @_events[eventName] ?= [] @_events[eventName].push(listener) - @element.addEventListener(eventName, listener) + if Events.isGestureEvent eventName + @_gestureManager.addEventListener(eventName, listener) + else + @element.addEventListener(eventName, listener) removeEventListener: (eventName, listener) -> return unless @_events return unless @_events[eventName] @_events[eventName] = _.without @_events[eventName], listener - @element.removeEventListener(eventName, listener) + + if Events.isGestureEvent eventName + @_gestureManager.removeEventListener(eventName, listener) + else + @element.removeEventListener(eventName, listener) return diff --git a/framer/Events.coffee b/framer/Events.coffee index 8328d485c..9553672fd 100644 --- a/framer/Events.coffee +++ b/framer/Events.coffee @@ -33,6 +33,20 @@ Events.AnimationDidStart = "start" Events.AnimationDidStop = "stop" Events.AnimationDidEnd = "end" +# Gesture events +_gestures = [] +_gestures.push Events.Press = "press" +_gestures.push Events.PressUp = "pressup" +_gestures.push Events.Pinch = "pinch" +_gestures.push Events.PinchStart = "pinchstart" +_gestures.push Events.PinchEnd = "pinchend" +_gestures.push Events.Pan = "pan" +_gestures.push Events.Swipe = "swipe" +_gestures.push Events.SwipeLeft = "swipeleft" +_gestures.push Events.SwipeRight = "swiperight" +_gestures.push Events.SwipeUp = "swipeup" +_gestures.push Events.SwipeDown = "swipedown" + # Scroll events Events.Scroll = "scroll" @@ -40,6 +54,9 @@ Events.Scroll = "scroll" Events.ImageLoaded = "load" Events.ImageLoadError = "error" +Events.isGestureEvent = (eventName) -> + return eventName in _gestures + # Extract touch events for any event Events.touchEvent = (event) -> touchEvent = event.touches?[0] diff --git a/framer/GestureManager.coffee b/framer/GestureManager.coffee new file mode 100644 index 000000000..1cd831c57 --- /dev/null +++ b/framer/GestureManager.coffee @@ -0,0 +1,32 @@ +Hammer = require "hammerjs" + +class exports.GestureManager + + constructor: (@element) -> + @_events = {} + @_manager = null + + addEventListener: (eventName, listener) -> + #Lazy creation + @_manager ?= new Hammer.Manager(@element) + + # Add recognizer if needed + switch eventName + when Events.Press, Events.PressUp + if not @_manager.get(Events.Press) + @_manager.add new Hammer.Press({ event: Events.Press}) + recognizer = new Hammer.Press({ event: Events.Press }) + when Events.Pinch, Events.PinchStart, Events.PinchEnd + if not @_manager.get(Events.Pinch) + @_manager.add new Hammer.Pinch({ event: Events.Pinch}) + when Events.Pan + recognizer = new Hammer.Pan({ event: Events.Pan }) + when Events.Swipe, Events.SwipeLeft, Events.SwipeRight, Events.SwipeUp, Events.SwipeDown + if not @_manager.get(Events.Swipe) + # TODO Handle different directions + @_manager.add new Hammer.Swipe({ event: Events.Swipe}) + else + + @_manager.on eventName, listener + + removeEventListener: (eventName, listener) -> diff --git a/package.json b/package.json index 300020f2a..fe7cca931 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ }, "dependencies": { "eventemitter3": "^0.1.6", + "hammerjs": "^2.0.4", "lodash": "^3.5.0" }, "devDependencies": { From ae277ea57d8ecd1a83a65b2718f8f36389777059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Cha=CC=81varri?= Date: Thu, 5 Nov 2015 01:40:40 +0100 Subject: [PATCH 02/14] Adding all Hammer gestures strings --- framer/Events.coffee | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/framer/Events.coffee b/framer/Events.coffee index 9553672fd..7546a0f6b 100644 --- a/framer/Events.coffee +++ b/framer/Events.coffee @@ -35,18 +35,50 @@ Events.AnimationDidEnd = "end" # Gesture events _gestures = [] -_gestures.push Events.Press = "press" -_gestures.push Events.PressUp = "pressup" -_gestures.push Events.Pinch = "pinch" + +# Pan +_gestures.push Events.Pan = "pan" # This event includes all the other Pan events +_gestures.push Events.PanStart = "panstart" +_gestures.push Events.PanMove = "panmove" +_gestures.push Events.PanEnd = "panend" +_gestures.push Events.PanCancel = "pancancel" +_gestures.push Events.PanLeft = "panleft" +_gestures.push Events.PanRight = "panright" +_gestures.push Events.PanUp = "panup" +_gestures.push Events.PanDown = "pandown" + +# Pinch +_gestures.push Events.Pinch = "pinch" # This event includes all the other Pinch events _gestures.push Events.PinchStart = "pinchstart" +_gestures.push Events.PinchMove = "pinchmove" _gestures.push Events.PinchEnd = "pinchend" -_gestures.push Events.Pan = "pan" +_gestures.push Events.PinchCancel = "pinchcancel" +_gestures.push Events.PinchIn = "pinchin" +_gestures.push Events.PinchOut = "pinchout" + +# Press +_gestures.push Events.Press = "press" +_gestures.push Events.PressUp = "pressup" + +# Rotate +_gestures.push Events.Rotate = "rotate" # This event includes all the other Rotate events +_gestures.push Events.RotateStart = "rotatestart" +_gestures.push Events.RotateMove = "rotatemove" +_gestures.push Events.RotateEnd = "rotateend" +_gestures.push Events.RotateCancel = "rotatecancel" + +# Swipe _gestures.push Events.Swipe = "swipe" _gestures.push Events.SwipeLeft = "swipeleft" _gestures.push Events.SwipeRight = "swiperight" _gestures.push Events.SwipeUp = "swipeup" _gestures.push Events.SwipeDown = "swipedown" +# Tap +_gestures.push Events.Tap = "tap" +_gestures.push Events.SingleTap = "singletap" # Helper. Has no event string correspondance in HammerJS +_gestures.push Events.DoubleTap = "doubletap" # Helper. Has no event string correspondance in HammerJS + # Scroll events Events.Scroll = "scroll" From 16fde454092a3856c1495b083f630e32f5c27495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Cha=CC=81varri?= Date: Sat, 21 Nov 2015 16:19:55 +0100 Subject: [PATCH 03/14] Adding recognisers for every kind of gesture event to GestureManager --- framer/GestureManager.coffee | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/framer/GestureManager.coffee b/framer/GestureManager.coffee index 1cd831c57..496fb52c9 100644 --- a/framer/GestureManager.coffee +++ b/framer/GestureManager.coffee @@ -10,23 +10,38 @@ class exports.GestureManager #Lazy creation @_manager ?= new Hammer.Manager(@element) + validEvent = true + # Add recognizer if needed switch eventName + when Events.Pan, Events.PanStart, Events.PanMove, Events.PanEnd, Events.PanCancel, Events.PanLeft, Events.PanRight, Events.PanUp, Events.PanDown + if not @_manager.get(Events.Pan) + @_manager.add new Hammer.Pan({ event: Events.Pan}) + recognizer = new Hammer.Pan({ event: Events.Pan }) + when Events.Pinch, Events.PinchStart, Events.PinchMove, Events.PinchEnd, Events.PinchCancel, Events.PinchIn, Events.PinchOut + if not @_manager.get(Events.Pinch) + @_manager.add new Hammer.Pinch({ event: Events.Pinch}) when Events.Press, Events.PressUp if not @_manager.get(Events.Press) @_manager.add new Hammer.Press({ event: Events.Press}) recognizer = new Hammer.Press({ event: Events.Press }) - when Events.Pinch, Events.PinchStart, Events.PinchEnd - if not @_manager.get(Events.Pinch) - @_manager.add new Hammer.Pinch({ event: Events.Pinch}) - when Events.Pan - recognizer = new Hammer.Pan({ event: Events.Pan }) + when Events.Rotate, Events.RotateStart, Events.RotateMove, Events.RotateEnd, Events.RotateCancel + if not @_manager.get(Events.Rotate) + @_manager.add new Hammer.Rotate({ event: Events.Rotate}) + recognizer = new Hammer.Rotate({ event: Events.Rotate }) when Events.Swipe, Events.SwipeLeft, Events.SwipeRight, Events.SwipeUp, Events.SwipeDown if not @_manager.get(Events.Swipe) - # TODO Handle different directions @_manager.add new Hammer.Swipe({ event: Events.Swipe}) + when Events.Tap, Events.SingleTap + if not @_manager.get(Events.Tap) + @_manager.add new Hammer.Tap({ event: Events.Tap}) + when Events.DoubleTap + if not @_manager.get(Events.Tap) + @_manager.add new Hammer.Tap({ event: Events.Tap, taps: 2}) else - - @_manager.on eventName, listener + validEvent = false + + if validEvent + @_manager.on eventName, listener - removeEventListener: (eventName, listener) -> + removeEventListener: (eventName, listener) -> \ No newline at end of file From 5935453f6f30eb8e3885ae825490dd4bc848aac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Cha=CC=81varri?= Date: Sat, 21 Nov 2015 16:28:19 +0100 Subject: [PATCH 04/14] Renaming GestureManager class to GestureManagerElement --- framer/EventManager.coffee | 8 ++++---- framer/GestureManager.coffee | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/framer/EventManager.coffee b/framer/EventManager.coffee index 1ffe60bd4..30780a6e5 100644 --- a/framer/EventManager.coffee +++ b/framer/EventManager.coffee @@ -1,5 +1,5 @@ Utils = require "./Utils" -{GestureManager} = require "./GestureManager" +{GestureManagerElement} = require "./GestureManager" EventManagerIdCounter = 0 @@ -7,7 +7,7 @@ class EventManagerElement constructor: (@element) -> @_events = {} - @_gestureManager = new GestureManager(@element) + @_elementGestureManager = new GestureManagerElement(@element) addEventListener: (eventName, listener) -> @@ -18,7 +18,7 @@ class EventManagerElement @_events[eventName].push(listener) if Events.isGestureEvent eventName - @_gestureManager.addEventListener(eventName, listener) + @_elementGestureManager.addEventListener(eventName, listener) else @element.addEventListener(eventName, listener) @@ -29,7 +29,7 @@ class EventManagerElement @_events[eventName] = _.without @_events[eventName], listener if Events.isGestureEvent eventName - @_gestureManager.removeEventListener(eventName, listener) + @_elementGestureManager.removeEventListener(eventName, listener) else @element.removeEventListener(eventName, listener) diff --git a/framer/GestureManager.coffee b/framer/GestureManager.coffee index 496fb52c9..08fe53d61 100644 --- a/framer/GestureManager.coffee +++ b/framer/GestureManager.coffee @@ -1,6 +1,6 @@ Hammer = require "hammerjs" -class exports.GestureManager +class exports.GestureManagerElement constructor: (@element) -> @_events = {} From 4e6ba31e4c7fef82ffa9ba972ccd2a865d772ed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Cha=CC=81varri?= Date: Sun, 22 Nov 2015 01:28:09 +0100 Subject: [PATCH 05/14] Adding getEventFamily. Allowing multiple events being tracked simultaneously --- framer/GestureManager.coffee | 122 +++++++++++++++++++++++++++++------ 1 file changed, 104 insertions(+), 18 deletions(-) diff --git a/framer/GestureManager.coffee b/framer/GestureManager.coffee index 08fe53d61..68e49711c 100644 --- a/framer/GestureManager.coffee +++ b/framer/GestureManager.coffee @@ -3,44 +3,130 @@ Hammer = require "hammerjs" class exports.GestureManagerElement constructor: (@element) -> + @_events = {} @_manager = null + _getEventFamily: (eventName) -> + + eventFamily = undefined + + switch eventName + + when Events.Pan, Events.PanStart, Events.PanMove, Events.PanEnd, Events.PanCancel, Events.PanLeft, Events.PanRight, Events.PanUp, Events.PanDown + eventFamily = Events.Pan + + when Events.Pinch, Events.PinchStart, Events.PinchMove, Events.PinchEnd, Events.PinchCancel, Events.PinchIn, Events.PinchOut + eventFamily = Events.Pinch + + when Events.Press, Events.PressUp + eventFamily = Events.Press + + when Events.Rotate, Events.RotateStart, Events.RotateMove, Events.RotateEnd, Events.RotateCancel + eventFamily = Events.Rotate + + when Events.Swipe, Events.SwipeLeft, Events.SwipeRight, Events.SwipeUp, Events.SwipeDown + eventFamily = Events.Swipe + + when Events.Tap, Events.SingleTap + eventFamily = Events.Tap + + when Events.DoubleTap # Tap and DoubleTap need different type of recognizers + eventFamily = Events.DoubleTap + + else + + return eventFamily + + + _getExistingRecognizersForEventFamily: (eventFamily) -> + + # We need to mix recognizers for some gestures to be detected together + # All these dependencies come from https://cdn.rawgit.com/hammerjs/hammer.js/master/tests/manual/visual.html + existingRecognizers = [] + + switch eventFamily + + when Events.Pan # Pan depends on Swipe, Rotate and Pinch + if swipe = @_manager.get(Events.Swipe) + existingRecognizers.push(swipe) + if rotate = @_manager.get(Events.Rotate) + existingRecognizers.push(rotate) + if pinch = @_manager.get(Events.Pinch) + existingRecognizers.push(pinch) + + when Events.Swipe # Swipe depends on Pan + if pan = @_manager.get(Events.Pan) + existingRecognizers.push(pan) + + when Events.Rotate # Rotate depends on Pan and Pinch + if pan = @_manager.get(Events.Pan) + existingRecognizers.push(pan) + if pinch = @_manager.get(Events.Pinch) + existingRecognizers.push(pinch) + + when Events.Pinch # Pinch depends on Pan and Rotate + if pan = @_manager.get(Events.Pan) + existingRecognizers.push(pan) + if rotate = @_manager.get(Events.Pinch) + existingRecognizers.push(rotate) + else + + return existingRecognizers + + addEventListener: (eventName, listener) -> #Lazy creation @_manager ?= new Hammer.Manager(@element) validEvent = true + recognizer = undefined + + # Get event family to add different recognizers + eventFamily = @_getEventFamily(eventName) # Add recognizer if needed - switch eventName - when Events.Pan, Events.PanStart, Events.PanMove, Events.PanEnd, Events.PanCancel, Events.PanLeft, Events.PanRight, Events.PanUp, Events.PanDown + switch eventFamily + + when Events.Pan if not @_manager.get(Events.Pan) - @_manager.add new Hammer.Pan({ event: Events.Pan}) - recognizer = new Hammer.Pan({ event: Events.Pan }) - when Events.Pinch, Events.PinchStart, Events.PinchMove, Events.PinchEnd, Events.PinchCancel, Events.PinchIn, Events.PinchOut + recognizer = new Hammer.Pan({ event: Events.Pan}) + + when Events.Pinch if not @_manager.get(Events.Pinch) - @_manager.add new Hammer.Pinch({ event: Events.Pinch}) - when Events.Press, Events.PressUp + recognizer = new Hammer.Pinch({ event: Events.Pinch}) + + when Events.Press if not @_manager.get(Events.Press) - @_manager.add new Hammer.Press({ event: Events.Press}) - recognizer = new Hammer.Press({ event: Events.Press }) - when Events.Rotate, Events.RotateStart, Events.RotateMove, Events.RotateEnd, Events.RotateCancel + recognizer = new Hammer.Press({ event: Events.Press}) + + when Events.Rotate if not @_manager.get(Events.Rotate) - @_manager.add new Hammer.Rotate({ event: Events.Rotate}) - recognizer = new Hammer.Rotate({ event: Events.Rotate }) - when Events.Swipe, Events.SwipeLeft, Events.SwipeRight, Events.SwipeUp, Events.SwipeDown + recognizer = new Hammer.Rotate({ event: Events.Rotate}) + + when Events.Swipe if not @_manager.get(Events.Swipe) - @_manager.add new Hammer.Swipe({ event: Events.Swipe}) - when Events.Tap, Events.SingleTap + recognizer = new Hammer.Swipe({ event: Events.Swipe}) + + when Events.Tap if not @_manager.get(Events.Tap) - @_manager.add new Hammer.Tap({ event: Events.Tap}) + recognizer = new Hammer.Tap({ event: Events.Tap}) + when Events.DoubleTap - if not @_manager.get(Events.Tap) - @_manager.add new Hammer.Tap({ event: Events.Tap, taps: 2}) + if not @_manager.get(Events.DoubleTap) + recognizer = new Hammer.Tap({ event: Events.DoubleTap, taps: 2}) + else validEvent = false + if recognizer + # Add other recognizers if they existed already + existingRecognizers = @_getExistingRecognizersForEventFamily(eventFamily) + if existingRecognizers.length > 0 + @_manager.add(recognizer).recognizeWith(existingRecognizers) + else + @_manager.add recognizer + if validEvent @_manager.on eventName, listener From ff1363f178254d740cf2c2b3de575395ad6d1fd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Cha=CC=81varri?= Date: Sun, 22 Nov 2015 02:50:31 +0100 Subject: [PATCH 06/14] Adding Tap as dependency of Tap --- framer/GestureManager.coffee | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/framer/GestureManager.coffee b/framer/GestureManager.coffee index 68e49711c..eb9db81bc 100644 --- a/framer/GestureManager.coffee +++ b/framer/GestureManager.coffee @@ -39,9 +39,10 @@ class exports.GestureManagerElement return eventFamily - _getExistingRecognizersForEventFamily: (eventFamily) -> + _getDependentRecognizersForEventFamily: (eventFamily) -> - # We need to mix recognizers for some gestures to be detected together + # We need to add simultaneous recognition for certain gestures to be detected together + # See http://hammerjs.github.io/recognize-with/ # All these dependencies come from https://cdn.rawgit.com/hammerjs/hammer.js/master/tests/manual/visual.html existingRecognizers = [] @@ -70,6 +71,11 @@ class exports.GestureManagerElement existingRecognizers.push(pan) if rotate = @_manager.get(Events.Pinch) existingRecognizers.push(rotate) + + when Events.DoubleTap # DoubleTap depends on Tap + if tap = @_manager.get(Events.Tap) + existingRecognizers.push(tap) + else return existingRecognizers @@ -121,7 +127,7 @@ class exports.GestureManagerElement if recognizer # Add other recognizers if they existed already - existingRecognizers = @_getExistingRecognizersForEventFamily(eventFamily) + existingRecognizers = @_getDependentRecognizersForEventFamily(eventFamily) if existingRecognizers.length > 0 @_manager.add(recognizer).recognizeWith(existingRecognizers) else From d7a0b00054e5a7ba849c474f8cfbf8c16a6f1486 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Cha=CC=81varri?= Date: Sun, 22 Nov 2015 18:28:53 +0100 Subject: [PATCH 07/14] Implementing removeEventListener --- framer/Events.coffee | 4 ++-- framer/GestureManager.coffee | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/framer/Events.coffee b/framer/Events.coffee index 7546a0f6b..5b07de6a7 100644 --- a/framer/Events.coffee +++ b/framer/Events.coffee @@ -76,8 +76,8 @@ _gestures.push Events.SwipeDown = "swipedown" # Tap _gestures.push Events.Tap = "tap" -_gestures.push Events.SingleTap = "singletap" # Helper. Has no event string correspondance in HammerJS -_gestures.push Events.DoubleTap = "doubletap" # Helper. Has no event string correspondance in HammerJS +_gestures.push Events.SingleTap = "singletap" +_gestures.push Events.DoubleTap = "doubletap" # Scroll events Events.Scroll = "scroll" diff --git a/framer/GestureManager.coffee b/framer/GestureManager.coffee index eb9db81bc..f7abd41f6 100644 --- a/framer/GestureManager.coffee +++ b/framer/GestureManager.coffee @@ -136,4 +136,8 @@ class exports.GestureManagerElement if validEvent @_manager.on eventName, listener - removeEventListener: (eventName, listener) -> \ No newline at end of file + removeEventListener: (eventName, listener) -> + # The EventManager already checks that the listener has been registered + # so we can remove it safely + # -- Should we remove the recognizers as well?? -- + @_manager.off eventName, listener \ No newline at end of file From d214575a417a7d766fb2b403a711acdea71c7650 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Cha=CC=81varri?= Date: Thu, 10 Dec 2015 23:41:21 +0100 Subject: [PATCH 08/14] Moving all events tests to a separate file --- test/tests.coffee | 1 + test/tests/LayerEventsTest.coffee | 141 ++++++++++++++++++++++++++++++ test/tests/LayerTest.coffee | 139 ----------------------------- 3 files changed, 142 insertions(+), 139 deletions(-) create mode 100644 test/tests/LayerEventsTest.coffee diff --git a/test/tests.coffee b/test/tests.coffee index 5f0722043..5fed8d7d4 100644 --- a/test/tests.coffee +++ b/test/tests.coffee @@ -10,6 +10,7 @@ require "./tests/EventEmitterTest" require "./tests/UtilsTest" require "./tests/BaseClassTest" require "./tests/LayerTest" +require "./tests/LayerEventsTest" require "./tests/LayerStatesTest" require "./tests/VideoLayerTest" require "./tests/ImporterTest" diff --git a/test/tests/LayerEventsTest.coffee b/test/tests/LayerEventsTest.coffee new file mode 100644 index 000000000..ee6f2c78d --- /dev/null +++ b/test/tests/LayerEventsTest.coffee @@ -0,0 +1,141 @@ +simulate = require "simulate" + +describe "LayerEvents", -> + + describe "Events", -> + + it "should set pointer events", -> + + layer = new Layer() + + layer.ignoreEvents = false + layer.style["pointerEvents"].should.equal "auto" + + layer.ignoreEvents = true + layer.style["pointerEvents"].should.equal "none" + + it "should not listen to events by default", -> + + layer = new Layer() + layer.ignoreEvents.should.equal true + layer.style["pointerEvents"].should.equal "none" + + + it "should not listen to events until a listener is added", -> + + layer = new Layer() + layer.ignoreEvents.should.equal true + + layer.on Events.Click, -> + console.log "hello" + + layer.ignoreEvents.should.equal false + + it "should modify the event scope", (callback) -> + + myLayer = new Layer() + + myLayer.on "click", (event, layer) -> + @id.should.equal myLayer.id + layer.id.should.equal myLayer.id + callback() + + simulate.click myLayer._element + + + it "should modify the event scope for once", (callback) -> + + myLayer = new Layer() + + myLayer.once "click", (event, layer) -> + @id.should.equal myLayer.id + layer.id.should.equal myLayer.id + callback() + + simulate.click myLayer._element + + it "should remove events", -> + + layer = new Layer + + clickCount = 0 + + handler = -> + clickCount++ + + layer.on "test", handler + + layer.emit "test" + clickCount.should.equal 1 + + layer.off "test", handler + + layer.emit "test" + clickCount.should.equal 1 + + + it "should only run an event once", -> + + layerA = new Layer + count = 0 + + layerA.once "hello", (layer) -> + count++ + layerA.should.equal layer + + for i in [0..10] + layerA.emit("hello") + + count.should.equal 1 + + it "should modify scope for draggable events", (callback) -> + + layerA = new Layer + layerA.draggable.enabled = true + layerA.on "test", (args...) -> + @id.should.equal(layerA.id) + callback() + + layerA.draggable.emit("test", {}) + + it "should list all events", -> + layerA = new Layer + handler = -> console.log "hello" + layerA.on("test", handler) + layerA.listeners("test").length.should.equal 1 + + it "should remove all events", -> + layerA = new Layer + handler = -> console.log "hello" + layerA.on("test", handler) + layerA.removeAllListeners("test") + layerA.listeners("test").length.should.equal 0 + + it "should add and clean up dom events", -> + layerA = new Layer + handler = -> console.log "hello" + + layerA.on(Events.Click, handler) + layerA.on(Events.Click, handler) + layerA.on(Events.Click, handler) + layerA.on(Events.Click, handler) + + # But never more then one + layerA._domEventManager.listeners(Events.Click).length.should.equal(1) + + layerA.removeAllListeners(Events.Click) + + # And on removal, we should get rid of the dom event + layerA._domEventManager.listeners(Events.Click).length.should.equal(0) + + it "should work with event helpers", (done) -> + + layer = new Layer + + layer.onMouseOver (event, aLayer) -> + aLayer.should.equal(layer) + @should.equal(layer) + done() + + simulate.mouseover(layer._element) + diff --git a/test/tests/LayerTest.coffee b/test/tests/LayerTest.coffee index 2654128f5..b70f858e5 100644 --- a/test/tests/LayerTest.coffee +++ b/test/tests/LayerTest.coffee @@ -1,7 +1,5 @@ assert = require "assert" -simulate = require "simulate" - describe "Layer", -> # afterEach -> @@ -383,143 +381,6 @@ describe "Layer", -> layer.shadowColor = null layer.style.boxShadow.should.equal "" - describe "Events", -> - - it "should set pointer events", -> - - layer = new Layer() - - layer.ignoreEvents = false - layer.style["pointerEvents"].should.equal "auto" - - layer.ignoreEvents = true - layer.style["pointerEvents"].should.equal "none" - - it "should not listen to events by default", -> - - layer = new Layer() - layer.ignoreEvents.should.equal true - layer.style["pointerEvents"].should.equal "none" - - - it "should not listen to events until a listener is added", -> - - layer = new Layer() - layer.ignoreEvents.should.equal true - - layer.on Events.Click, -> - console.log "hello" - - layer.ignoreEvents.should.equal false - - it "should modify the event scope", (callback) -> - - myLayer = new Layer() - - myLayer.on "click", (event, layer) -> - @id.should.equal myLayer.id - layer.id.should.equal myLayer.id - callback() - - simulate.click myLayer._element - - - it "should modify the event scope for once", (callback) -> - - myLayer = new Layer() - - myLayer.once "click", (event, layer) -> - @id.should.equal myLayer.id - layer.id.should.equal myLayer.id - callback() - - simulate.click myLayer._element - - it "should remove events", -> - - layer = new Layer - - clickCount = 0 - - handler = -> - clickCount++ - - layer.on "test", handler - - layer.emit "test" - clickCount.should.equal 1 - - layer.off "test", handler - - layer.emit "test" - clickCount.should.equal 1 - - - it "should only run an event once", -> - - layerA = new Layer - count = 0 - - layerA.once "hello", (layer) -> - count++ - layerA.should.equal layer - - for i in [0..10] - layerA.emit("hello") - - count.should.equal 1 - - it "should modify scope for draggable events", (callback) -> - - layerA = new Layer - layerA.draggable.enabled = true - layerA.on "test", (args...) -> - @id.should.equal(layerA.id) - callback() - - layerA.draggable.emit("test", {}) - - it "should list all events", -> - layerA = new Layer - handler = -> console.log "hello" - layerA.on("test", handler) - layerA.listeners("test").length.should.equal 1 - - it "should remove all events", -> - layerA = new Layer - handler = -> console.log "hello" - layerA.on("test", handler) - layerA.removeAllListeners("test") - layerA.listeners("test").length.should.equal 0 - - it "should add and clean up dom events", -> - layerA = new Layer - handler = -> console.log "hello" - - layerA.on(Events.Click, handler) - layerA.on(Events.Click, handler) - layerA.on(Events.Click, handler) - layerA.on(Events.Click, handler) - - # But never more then one - layerA._domEventManager.listeners(Events.Click).length.should.equal(1) - - layerA.removeAllListeners(Events.Click) - - # And on removal, we should get rid of the dom event - layerA._domEventManager.listeners(Events.Click).length.should.equal(0) - - it "should work with event helpers", (done) -> - - layer = new Layer - - layer.onMouseOver (event, aLayer) -> - aLayer.should.equal(layer) - @should.equal(layer) - done() - - simulate.mouseover(layer._element) - describe "Hierarchy", -> it "should insert in dom", -> From c4f7bdb54a060cc718f220d0eac302b86d5d1f1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Cha=CC=81varri?= Date: Fri, 11 Dec 2015 00:17:03 +0100 Subject: [PATCH 09/14] Adding some gesture events tests --- test/tests/LayerEventsTest.coffee | 70 +++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/test/tests/LayerEventsTest.coffee b/test/tests/LayerEventsTest.coffee index ee6f2c78d..3f6974778 100644 --- a/test/tests/LayerEventsTest.coffee +++ b/test/tests/LayerEventsTest.coffee @@ -139,3 +139,73 @@ describe "LayerEvents", -> simulate.mouseover(layer._element) + describe "Gesture events", -> + + it "should not be listened to until a listener is added", -> + + layer = new Layer() + layer.ignoreEvents.should.equal true + + layer.on Events.Pinch, -> + console.log "hello" + + layer.ignoreEvents.should.equal false + + it "should call the handler when added and do nothing when removed", -> + + layer = new Layer + + pinchCount = 0 + + handler = -> + pinchCount++ + + layer.on Events.Pinch, handler + + layer.emit Events.Pinch + pinchCount.should.equal 1 + + layer.off Events.Pinch, handler + + layer.emit Events.Pinch + pinchCount.should.equal 1 + + + it "should only run once when using 'once'", -> + + layerA = new Layer + count = 0 + + layerA.once Events.Pinch, (layer) -> + count++ + layerA.should.equal layer + + for i in [0..10] + layerA.emit(Events.Pinch) + + count.should.equal 1 + + it "should list all gesture events", -> + layerA = new Layer + handler = -> console.log "hello" + layerA.on(Events.Pinch, handler) + layerA.listeners(Events.Pinch).length.should.equal 1 + + it "should remove all gesture events", -> + layerA = new Layer + handler = -> console.log "hello" + layerA.on(Events.Pinch, handler) + layerA.removeAllListeners(Events.Pinch) + layerA.listeners(Events.Pinch).length.should.equal 0 + + # it "should work with event helpers", (done) -> + + # layer = new Layer + + # layer.onMouseOver (event, aLayer) -> + # aLayer.should.equal(layer) + # @should.equal(layer) + # done() + + # simulate.mouseover(layer._element) + From 783e6a509c7bb00d3e7510c2d36929b1b148baa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Cha=CC=81varri?= Date: Fri, 11 Dec 2015 00:22:17 +0100 Subject: [PATCH 10/14] Cleaning --- test/tests/LayerEventsTest.coffee | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/test/tests/LayerEventsTest.coffee b/test/tests/LayerEventsTest.coffee index 3f6974778..6b4632aec 100644 --- a/test/tests/LayerEventsTest.coffee +++ b/test/tests/LayerEventsTest.coffee @@ -196,16 +196,4 @@ describe "LayerEvents", -> handler = -> console.log "hello" layerA.on(Events.Pinch, handler) layerA.removeAllListeners(Events.Pinch) - layerA.listeners(Events.Pinch).length.should.equal 0 - - # it "should work with event helpers", (done) -> - - # layer = new Layer - - # layer.onMouseOver (event, aLayer) -> - # aLayer.should.equal(layer) - # @should.equal(layer) - # done() - - # simulate.mouseover(layer._element) - + layerA.listeners(Events.Pinch).length.should.equal 0 \ No newline at end of file From 7a2f2cf547cd4d4ab662abe9a140862085df80e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Cha=CC=81varri?= Date: Sat, 19 Dec 2015 19:27:42 +0100 Subject: [PATCH 11/14] Added gesture event helpers (onPan, onPinch, etc) --- framer/Layer.coffee | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/framer/Layer.coffee b/framer/Layer.coffee index 070720d7d..f736234f7 100644 --- a/framer/Layer.coffee +++ b/framer/Layer.coffee @@ -898,6 +898,43 @@ class exports.Layer extends BaseClass onDragAnimationDidEnd: (cb) -> @on(Events.DragAnimationDidEnd, cb) onDirectionLockDidStart: (cb) -> @on(Events.DirectionLockDidStart, cb) + onPan: (cb) -> @on(Events.Pan, cb) + onPanStart: (cb) -> @on(Events.PanStart, cb) + onPanMove: (cb) -> @on(Events.PanMove, cb) + onPanEnd: (cb) -> @on(Events.PanEnd, cb) + onPanCancel: (cb) -> @on(Events.PanCancel, cb) + onPanLeft: (cb) -> @on(Events.PanLeft, cb) + onPanRight: (cb) -> @on(Events.PanRight, cb) + onPanUp: (cb) -> @on(Events.PanUp, cb) + onPanDown: (cb) -> @on(Events.PanDown, cb) + + onPinch: (cb) -> @on(Events.Pinch, cb) + onPinchStart: (cb) -> @on(Events.PinchStart, cb) + onPinchMove: (cb) -> @on(Events.PinchMove, cb) + onPinchEnd: (cb) -> @on(Events.PinchEnd, cb) + onPinchCancel: (cb) -> @on(Events.PinchCancel, cb) + onPinchIn: (cb) -> @on(Events.PinchIn, cb) + onPinchOut: (cb) -> @on(Events.PinchOut, cb) + + onPress: (cb) -> @on(Events.Press, cb) + onPressUp: (cb) -> @on(Events.PressUp, cb) + + onRotate: (cb) -> @on(Events.Rotate, cb) + onRotateStart: (cb) -> @on(Events.RotateStart, cb) + onRotateMove: (cb) -> @on(Events.RotateMove, cb) + onRotateEnd: (cb) -> @on(Events.RotateEnd, cb) + onRotateCancel: (cb) -> @on(Events.RotateCancel, cb) + + onSwipe: (cb) -> @on(Events.Swipe, cb) + onSwipeLeft: (cb) -> @on(Events.SwipeLeft, cb) + onSwipeRight: (cb) -> @on(Events.SwipeRight, cb) + onSwipeUp: (cb) -> @on(Events.SwipeUp, cb) + onSwipeDown: (cb) -> @on(Events.SwipeDown, cb) + + onTap: (cb) -> @on(Events.Tap, cb) + onSingleTap: (cb) -> @on(Events.SingleTap, cb) + onDoubleTap: (cb) -> @on(Events.DoubleTap, cb) + ############################################################## ## DESCRIPTOR From f797a36bc5e577609e64e08610ea862a793db3b7 Mon Sep 17 00:00:00 2001 From: "J.P.P Treub" Date: Mon, 4 Jan 2016 14:39:21 +0100 Subject: [PATCH 12/14] make invalid color strings transparent conforming to css --- framer/Color.coffee | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/framer/Color.coffee b/framer/Color.coffee index 28c323fc7..f0149965f 100644 --- a/framer/Color.coffee +++ b/framer/Color.coffee @@ -333,6 +333,13 @@ inputData = (color, g, b, alpha) -> if typeof color == "string" color = stringToObject(color) + if !color + color = + r:0 + g:0 + b:0 + a:0 + if color.hasOwnProperty("type") type = color.type From 3ee6d07eaec9999da30214628c99a9582f43b8f1 Mon Sep 17 00:00:00 2001 From: Koen Bok Date: Thu, 7 Jan 2016 14:08:59 +0100 Subject: [PATCH 13/14] Throw error on ScrollComponent.wrap() with nonexisting layer --- framer/Components/ScrollComponent.coffee | 3 +++ test/tests/ScrollComponentTest.coffee | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/framer/Components/ScrollComponent.coffee b/framer/Components/ScrollComponent.coffee index 94930d0c1..129a1408e 100644 --- a/framer/Components/ScrollComponent.coffee +++ b/framer/Components/ScrollComponent.coffee @@ -391,6 +391,9 @@ class exports.ScrollComponent extends Layer wrapComponent = (instance, layer, options = {correct:true}) -> + if not (layer instanceof Layer) + throw new Error("ScrollComponent.wrap expects a layer, not #{layer}. Are you sure the layer exists?") + # This function wraps the given layer into a scroll or page component. This is # great for importing from Sketch or Photoshop. diff --git a/test/tests/ScrollComponentTest.coffee b/test/tests/ScrollComponentTest.coffee index 14cc3de71..953b48dc0 100644 --- a/test/tests/ScrollComponentTest.coffee +++ b/test/tests/ScrollComponentTest.coffee @@ -77,3 +77,7 @@ describe "ScrollComponent", -> delete layerA._properties.backgroundColor scroll = ScrollComponent.wrap(layerA) + + it "should throw a warning on no layer", -> + f = -> ScrollComponent.wrap() + f.should.throw() From 36193ac7b914fc3e414de1ce7d1c7be1ca833acf Mon Sep 17 00:00:00 2001 From: Koen Bok Date: Thu, 7 Jan 2016 17:10:37 +0100 Subject: [PATCH 14/14] Fix a bug where printing arrays would be shortened. --- framer/Print.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framer/Print.coffee b/framer/Print.coffee index d742a1ee5..a83584778 100644 --- a/framer/Print.coffee +++ b/framer/Print.coffee @@ -50,7 +50,7 @@ exports.print = (args...) -> printPrefix = "ยป " printNode = document.createElement("div") - printNode.innerHTML = _.escape(printPrefix + args.map(Utils.inspect).join(", ")) + "
" + printNode.innerHTML = _.escape(printPrefix + args.map((obj) -> Utils.inspect(obj)).join(", ")) + "
" printNode.style["-webkit-user-select"] = "text" printNode.style["cursor"] = "auto"