Skip to content

Commit

Permalink
Add support for touch events for visible area dragging
Browse files Browse the repository at this point in the history
Closes #362
  • Loading branch information
abe33 committed Jul 15, 2015
1 parent 7d5f5b9 commit a6e0a8a
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 6 deletions.
18 changes: 13 additions & 5 deletions lib/minimap-element.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -181,11 +181,13 @@ class MinimapElement extends HTMLElement
@addEventListener 'mousewheel', elementMousewheel
@canvas.addEventListener 'mousedown', canvasMousedown
@visibleArea.addEventListener 'mousedown', visibleAreaMousedown
@visibleArea.addEventListener 'touchstart', visibleAreaMousedown

@subscriptions.add new Disposable =>
@removeEventListener 'mousewheel', elementMousewheel
@canvas.removeEventListener 'mousedown', canvasMousedown
@visibleArea.removeEventListener 'mousedown', visibleAreaMousedown
@visibleArea.removeEventListener 'touchstart', visibleAreaMousedown

# Initializes the scroll indicator div when the `minimapScrollIndicator`
# settings is enabled.
Expand Down Expand Up @@ -512,11 +514,11 @@ class MinimapElement extends HTMLElement
# area that starts the dragging gesture.
#
# event - The {Event} object.
startDrag: ({which, pageY}) ->
# if which is 2
# @middleMousePressedOverCanvas({pageY})
startDrag: (e) ->
{which, pageY} = e
return unless @minimap
return if which isnt 1 and which isnt 2
return if which isnt 1 and which isnt 2 and not e.touches?

{top} = @visibleArea.getBoundingClientRect()
{top: offsetTop} = @getBoundingClientRect()

Expand All @@ -531,11 +533,17 @@ class MinimapElement extends HTMLElement
document.body.addEventListener('mouseup', mouseupHandler)
document.body.addEventListener('mouseleave', mouseupHandler)

document.body.addEventListener('touchmove', mousemoveHandler)
document.body.addEventListener('touchend', mouseupHandler)

@dragSubscription = new Disposable ->
document.body.removeEventListener('mousemove', mousemoveHandler)
document.body.removeEventListener('mouseup', mouseupHandler)
document.body.removeEventListener('mouseleave', mouseupHandler)

document.body.removeEventListener('touchmove', mousemoveHandler)
document.body.removeEventListener('touchend', mouseupHandler)

# Internal: The method called during the drag gesture.
#
# e - The {Event} object.
Expand All @@ -546,7 +554,7 @@ class MinimapElement extends HTMLElement
# drag start.
drag: (e, initial) ->
return unless @minimap
return if e.which isnt 1 and e.which isnt 2
return if e.which isnt 1 and e.which isnt 2 and not e.touches?
y = e.pageY - initial.offsetTop - initial.dragOffset

ratio = y / (@minimap.getVisibleHeight() - @minimap.getTextEditorScaledHeight())
Expand Down
34 changes: 34 additions & 0 deletions spec/helpers/events.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,28 @@ mouseEvent = (type, properties) ->

new MouseEvent type, properties

touchEvent = (type, touches) ->
firstTouch = touches[0]

properties = {
bubbles: true
cancelable: true
view: window
ctrlKey: false
altKey: false
shiftKey: false
metaKey: false
relatedTarget: undefined
}

e = new Event(type, properties)
e.pageX = firstTouch.pageX
e.pageY = firstTouch.pageY
e.clientX = firstTouch.clientX
e.clientY = firstTouch.clientY
e.touches = e.targetTouches = e.changedTouches = touches
e

objectCenterCoordinates = (obj) ->
{top, left, width, height} = obj.getBoundingClientRect()
{x: left + width / 2, y: top + height / 2}
Expand All @@ -40,3 +62,15 @@ module.exports = {objectCenterCoordinates, mouseEvent}

module.exports.mousewheel = (obj, deltaX=0, deltaY=0) ->
obj.dispatchEvent(mouseEvent 'mousewheel', {deltaX, deltaY})

['touchstart', 'touchmove', 'touchend'].forEach (key) ->
module.exports[key] = (obj, {x, y, cx, cy} = {}) ->
{x,y} = objectCenterCoordinates(obj) unless x? and y?

unless cx? and cy?
cx = x
cy = y

obj.dispatchEvent(touchEvent key, [
{pageX: x, pageY: y, clientX: cx, clientY: cy}
])
30 changes: 29 additions & 1 deletion spec/minimap-element-spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ path = require 'path'
{TextEditor} = require 'atom'
Minimap = require '../lib/minimap'
MinimapElement = require '../lib/minimap-element'
{mousemove, mousedown, mouseup, mousewheel} = require './helpers/events'
{mousemove, mousedown, mouseup, mousewheel, touchstart, touchmove} = require './helpers/events'
stylesheetPath = path.resolve __dirname, '..', 'styles', 'minimap.less'
stylesheet = atom.themes.loadStylesheet(stylesheetPath)

Expand Down Expand Up @@ -491,6 +491,34 @@ describe 'MinimapElement', ->

expect(minimapElement.drag).not.toHaveBeenCalled()

describe 'dragging the visible area using touch events', ->
[visibleArea, originalTop] = []

beforeEach ->
visibleArea = minimapElement.visibleArea
{top: originalTop, left} = visibleArea.getBoundingClientRect()

touchstart(visibleArea, x: left + 10, y: originalTop + 10)
touchmove(visibleArea, x: left + 10, y: originalTop + 50)

nextAnimationFrame()

afterEach ->
minimapElement.endDrag()

it 'scrolls the editor so that the visible area was moved down by 40 pixels', ->
{top} = visibleArea.getBoundingClientRect()
expect(top).toBeCloseTo(originalTop + 40, -1)

it 'stops the drag gesture when the mouse is released outside the minimap', ->
{top, left} = visibleArea.getBoundingClientRect()
mouseup(jasmineContent, x: left - 10, y: top + 80)

spyOn(minimapElement, 'drag')
touchmove(visibleArea, x: left + 10, y: top + 50)

expect(minimapElement.drag).not.toHaveBeenCalled()

describe 'when the minimap cannot scroll', ->
[visibleArea, originalTop] = []

Expand Down

0 comments on commit a6e0a8a

Please sign in to comment.