4chan-x/lib/ui.coffee

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
}
)()