Permalink
Browse files

Automatically block click events in layers wrapped in moved draggable

The most common use case here is to add a layer to a scroll and add a click handler. When you move around the scroll, you expect the click handler not to trigger. There is a small tolerance built in.
  • Loading branch information...
koenbok committed Dec 28, 2015
1 parent 59923c4 commit 643b636ef6e838cc22bf0f7489f79859eb05133d
Showing with 512 additions and 2 deletions.
  1. +26 −2 framer/Layer.coffee
  2. +37 −0 test/studio/ScrollComponentBlockClick.framer/app.coffee
  3. +12 −0 test/studio/ScrollComponentBlockClick.framer/framer/coffee-script.js
  4. +10 −0 test/studio/ScrollComponentBlockClick.framer/framer/config.json
  5. +126 −0 test/studio/ScrollComponentBlockClick.framer/framer/framer.init.js
  6. +1 −0 test/studio/ScrollComponentBlockClick.framer/framer/framer.js
  7. BIN test/studio/ScrollComponentBlockClick.framer/framer/images/background.png
  8. BIN test/studio/ScrollComponentBlockClick.framer/framer/images/cursor-active.png
  9. BIN test/studio/ScrollComponentBlockClick.framer/framer/images/cursor-active@2x.png
  10. BIN test/studio/ScrollComponentBlockClick.framer/framer/images/cursor.png
  11. BIN test/studio/ScrollComponentBlockClick.framer/framer/images/cursor@2x.png
  12. BIN test/studio/ScrollComponentBlockClick.framer/framer/images/icon-120.png
  13. BIN test/studio/ScrollComponentBlockClick.framer/framer/images/icon-152.png
  14. BIN test/studio/ScrollComponentBlockClick.framer/framer/images/icon-76.png
  15. BIN test/studio/ScrollComponentBlockClick.framer/framer/images/icon-arrow.png
  16. BIN test/studio/ScrollComponentBlockClick.framer/framer/images/icon-arrow@2x.png
  17. BIN test/studio/ScrollComponentBlockClick.framer/framer/images/icon-close.png
  18. BIN test/studio/ScrollComponentBlockClick.framer/framer/images/icon-close@2x.png
  19. BIN test/studio/ScrollComponentBlockClick.framer/framer/images/icon-framer.png
  20. BIN test/studio/ScrollComponentBlockClick.framer/framer/images/icon-framer@2x.png
  21. BIN test/studio/ScrollComponentBlockClick.framer/framer/images/icon-share.png
  22. BIN test/studio/ScrollComponentBlockClick.framer/framer/images/icon-share@2x.png
  23. +196 −0 test/studio/ScrollComponentBlockClick.framer/framer/mirror.css
  24. +44 −0 test/studio/ScrollComponentBlockClick.framer/framer/style.css
  25. +1 −0 test/studio/ScrollComponentBlockClick.framer/framer/version
  26. 0 test/studio/ScrollComponentBlockClick.framer/images/.gitkeep
  27. BIN test/studio/ScrollComponentBlockClick.framer/images/framer-icon.png
  28. +37 −0 test/studio/ScrollComponentBlockClick.framer/index.html
  29. +22 −0 test/tests/LayerTest.coffee
@@ -68,6 +68,10 @@ class exports.Layer extends BaseClass
@_prefer2d = false
@_alwaysUseImageCache = false
# Private setting for canceling of click event if wrapped in moved draggable
@_cancelClickEventInDragSession = true
@_cancelClickEventInDragSessionTolerance = 4
# We have to create the element before we set the defaults
@_createElement()
@@ -827,8 +831,23 @@ class exports.Layer extends BaseClass
@define "_domEventManager",
get: -> @_context.domEventManager.wrap(@_element)
emit: (args...) ->
super(args..., @)
emit: (eventName, args...) ->
# If this layer has a parent draggable view and its position moved
# while dragging we automatically cancel click events. This is what
# you expect when you add a button to a scroll content layer.
if @_cancelClickEventInDragSession
if eventName is Events.Click
parentDraggableLayer = @_parentDraggableLayer()
if parentDraggableLayer
offset = parentDraggableLayer.draggable.offset
return if Math.abs(0 - offset.x) > @_cancelClickEventInDragSessionTolerance
return if Math.abs(0 - offset.y) > @_cancelClickEventInDragSessionTolerance
# Always scope the event this to the layer and pass the layer as
# last argument for every event.
super(eventName, args..., @)
once: (eventName, listener) =>
super(eventName, listener)
@@ -861,6 +880,11 @@ class exports.Layer extends BaseClass
if not @listeners(eventName).length
@_domEventManager.removeAllListeners(eventName)
_parentDraggableLayer: ->
for layer in @superLayers()
return layer if layer._draggable?.enabled
return null
on: @::addListener
off: @::removeListener
@@ -0,0 +1,37 @@
scroll = new ScrollComponent
scroll.size = Screen.size
scroll.scrollHorizontal = false
scroll.backgroundColor = null
rows = 40
gutter = 8
width = scroll.width
height = 200
for rowIndex in [0..rows-1]
cellLayer = new Layer
width: width
height: height
y: rowIndex * (height + gutter)
backgroundColor: Utils.randomColor(.5)
superLayer: scroll.content
Utils.labelLayer cellLayer, rowIndex
eventKeys = [
"Move",
"ScrollStart",
"ScrollMove",
"ScrollEnd",
"ScrollAnimationDidStart",
"ScrollAnimationDidEnd",
]
_.map eventKeys, (eventKey) ->
print eventKey
scroll.on Events[eventKey], ->
print eventKey, Events[eventKey]

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -0,0 +1,10 @@
{
"device" : "iPhone 5S Space Gray",
"sharedPrototype" : 1,
"deviceOrientation" : 0,
"contentScale" : 1,
"deviceType" : "fullscreen",
"updateDelay" : 0.3,
"deviceScale" : -1,
"delay" : 0.3
}
@@ -0,0 +1,126 @@
(function() {
function isFileLoadingAllowed() {
return (window.location.protocol.indexOf("file") == -1)
}
function isHomeScreened() {
return ("standalone" in window.navigator) && window.navigator.standalone == true
}
function isCompatibleBrowser() {
return Utils.isWebKit()
}
var alertNode;
function dismissAlert() {
alertNode.parentElement.removeChild(alertNode)
loadProject()
}
function showAlert(html) {
alertNode = document.createElement("div")
alertNode.classList.add("framerAlertBackground")
alertNode.innerHTML = html
document.addEventListener("DOMContentLoaded", function(event) {
document.body.appendChild(alertNode)
})
window.dismissAlert = dismissAlert;
}
function showBrowserAlert() {
var html = ""
html += "<div class='framerAlert'>"
html += "<strong>Error: Not A WebKit Browser</strong>"
html += "Your browser is not supported. <br> Please use Safari or Chrome.<br>"
html += "<a class='btn' href='javascript:void(0)' onclick='dismissAlert();'>Try anyway</a>"
html += "</div>"
showAlert(html)
}
function showFileLoadingAlert() {
var html = ""
html += "<div class='framerAlert'>"
html += "<strong>Error: Local File Restrictions</strong>"
html += "Preview this prototype with Framer Mirror or learn more about "
html += "<a href='https://github.com/koenbok/Framer/wiki/LocalLoading'>file restrictions</a>.<br>"
html += "<a class='btn' href='javascript:void(0)' onclick='dismissAlert();'>Try anyway</a>"
html += "</div>"
showAlert(html)
}
function showHomeScreenAlert() {
link = document.createElement("link");
link.href = "framer/mirror.css"
link.type = "text/css"
link.rel = "stylesheet"
link.media = "screen"
document.addEventListener("DOMContentLoaded", function(event) {
document.getElementsByTagName("head")[0].appendChild(link)
})
var html = ""
html += "<figure class='icon-close' href='javascript:void(0)' onclick='dismissAlert();'></figure>"
html += "<section class='wrapper'>"
html += "<figure class='icon-framer'></figure><h1>Install Prototype</h1>"
html += "<p>Tap <div class='share'><figure class='icon-share'></figure> Share</div>, then choose 'Add to Home Screen'</p> "
html += "<section class='arrow'><figure class='icon-arrow'></figure></section>"
html += "</section>"
showAlert(html)
}
function loadProject() {
CoffeeScript.load("app.coffee")
}
function setDefaultPageTitle() {
// If no title was set we set it to the project folder name so
// you get a nice name on iOS if you bookmark to desktop.
document.addEventListener("DOMContentLoaded", function() {
if (document.title == "") {
if (window.FramerStudioInfo && window.FramerStudioInfo.documentTitle) {
document.title = window.FramerStudioInfo.documentTitle
} else {
document.title = window.location.pathname.replace(/\//g, "")
}
}
})
}
function init() {
if (Utils.isFramerStudio()) {
return
}
setDefaultPageTitle()
if (!isCompatibleBrowser()) {
return showBrowserAlert()
}
if (!isFileLoadingAllowed()) {
return showFileLoadingAlert()
}
// if (Utils.isMobile() && !isHomeScreened()) {
// return showHomeScreenAlert()
// }
loadProject()
}
init()
})()
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Oops, something went wrong.

0 comments on commit 643b636

Please sign in to comment.