130 lines
3.9 KiB
CoffeeScript
130 lines
3.9 KiB
CoffeeScript
UI = (->
|
|
dialog = (id, position, html) ->
|
|
el = d.createElement 'div'
|
|
el.className = 'reply dialog'
|
|
el.innerHTML = html
|
|
el.id = id
|
|
el.style.cssText = localStorage.getItem("#{g.NAMESPACE}#{id}.position") or position
|
|
move = el.querySelector '.move'
|
|
move.addEventListener 'touchstart', dragstart, false
|
|
move.addEventListener 'mousedown', dragstart, false
|
|
el
|
|
|
|
dragstart = (e) ->
|
|
# prevent text selection
|
|
e.preventDefault()
|
|
el = @parentNode
|
|
if isTouching = e.type is 'touchstart'
|
|
e = e.changedTouches[e.changedTouches.length - 1]
|
|
# distance from pointer to el edge is constant; calculate it here.
|
|
rect = el.getBoundingClientRect()
|
|
screenHeight = d.documentElement.clientHeight
|
|
screenWidth = d.documentElement.clientWidth
|
|
o = {
|
|
id: el.id
|
|
style: el.style
|
|
dx: e.clientX - rect.left
|
|
dy: e.clientY - rect.top
|
|
height: screenHeight - rect.height
|
|
width: screenWidth - rect.width
|
|
screenHeight: screenHeight
|
|
screenWidth: screenWidth
|
|
isTouching: isTouching
|
|
}
|
|
if isTouching
|
|
o.identifier = e.identifier
|
|
o.move = touchmove.bind o
|
|
o.up = touchend.bind o
|
|
d.addEventListener 'touchmove', o.move, false
|
|
d.addEventListener 'touchend', o.up, false
|
|
d.addEventListener 'touchcancel', o.up, false
|
|
else # mousedown
|
|
o.move = drag.bind o
|
|
o.up = dragend.bind o
|
|
d.addEventListener 'mousemove', o.move, false
|
|
d.addEventListener 'mouseup', o.up, false
|
|
touchmove = (e) ->
|
|
for touch in e.changedTouches
|
|
if touch.identifier is @identifier
|
|
drag.call @, touch
|
|
return
|
|
drag = (e) ->
|
|
left = e.clientX - @dx
|
|
top = e.clientY - @dy
|
|
if left < 10 then left = 0
|
|
else if @width - left < 10 then left = null
|
|
if top < 10 then top = 0
|
|
else if @height - top < 10 then top = null
|
|
if left is null
|
|
@style.left = null
|
|
@style.right = '0%'
|
|
else
|
|
@style.left = left / @screenWidth * 100 + '%'
|
|
@style.right = null
|
|
if top is null
|
|
@style.top = null
|
|
@style.bottom = '0%'
|
|
else
|
|
@style.top = top / @screenHeight * 100 + '%'
|
|
@style.bottom = null
|
|
touchend = (e) ->
|
|
for touch in e.changedTouches
|
|
if touch.identifier is @identifier
|
|
dragend.call @
|
|
return
|
|
dragend = ->
|
|
if @isTouching
|
|
d.removeEventListener 'touchmove', @move, false
|
|
d.removeEventListener 'touchend', @up, false
|
|
d.removeEventListener 'touchcancel', @up, false
|
|
else # mouseup
|
|
d.removeEventListener 'mousemove', @move, false
|
|
d.removeEventListener 'mouseup', @up, false
|
|
localStorage.setItem "#{g.NAMESPACE}#{@id}.position", @style.cssText
|
|
|
|
hoverstart = (root, el, events, cb) ->
|
|
o = {
|
|
root: root
|
|
el: el
|
|
style: el.style
|
|
cb: cb
|
|
events: events.split ' '
|
|
clientHeight: d.documentElement.clientHeight
|
|
clientWidth: d.documentElement.clientWidth
|
|
}
|
|
o.hover = hover.bind o
|
|
o.hoverend = hoverend.bind o
|
|
for event in o.events
|
|
root.addEventListener event, o.hoverend, false
|
|
root.addEventListener 'mousemove', o.hover, false
|
|
hover = (e) ->
|
|
height = @el.offsetHeight
|
|
top = e.clientY - 120
|
|
@style.top =
|
|
if @clientHeight <= height or top <= 0
|
|
'0px'
|
|
else if top + height >= @clientHeight
|
|
@clientHeight - height + 'px'
|
|
else
|
|
top + 'px'
|
|
|
|
{clientX} = e
|
|
if clientX <= @clientWidth - 400
|
|
@style.left = clientX + 45 + 'px'
|
|
@style.right = null
|
|
else
|
|
@style.left = null
|
|
@style.right = @clientWidth - clientX + 45 + 'px'
|
|
hoverend = ->
|
|
@el.parentNode.removeChild @el
|
|
for event in @events
|
|
@root.removeEventListener event, @hoverend, false
|
|
@root.removeEventListener 'mousemove', @hover, false
|
|
@cb.call @ if @cb
|
|
|
|
return {
|
|
dialog: dialog
|
|
hover: hoverstart
|
|
}
|
|
)()
|