# TODO: This is kind of a mess
import {$class} from './utils'
class Scroller
wrapper: undefined
trackX: undefined
handleX: undefined
track: undefined
handle: undefined
barHeight: 0
barSize: 0
mouseX: 0
mouseY: 0
clickedX: 0
clickedY: 0
pressing: null
constructor: (@el) ->
@el.classList.add 'scroller_initiated'
@wrapper = @el.querySelector '.scroller__wrapper'
@track = @el.querySelector '.scrollbar_direction_vertical'
@handle = @track.querySelector '.scrollbar__handle'
@trackX = @el.querySelector '.scrollbar_direction_horizontal'
@handleX = @trackX.querySelector '.scrollbar__handle'
@barSize = @wrapper.offsetWidth - @wrapper.clientWidth
@wrapper.style.paddingRight = "#{@barSize}px"
@wrapper.style.paddingBottom = "#{@barSize}px"
do @adjustSize
@wrapper.addEventListener 'scroll', @onScroll
self = @
# Have to wrap it in a function or else it won't recognize the "this"
do (self) ->
document.addEventListener 'mousemove', (e) ->
# Update mouse position
self.mouseX = e.clientX
self.mouseY = e.clientY
# Only need to update height when mouse is in the scroller since its is transparent when the scroller is being hovered
do self.adjustSize
return
self.handleX.addEventListener 'mousedown', (e) ->
do e.stopPropagation
# Avoid slecting everthing while dragging the handle
self.el.style.userSelect = 'none'
# Gt pressed handle
self.pressing = e.target
# Get clicked position
self.clickedX = e.clientX - self.pressing.getBoundingClientRect().left
requestAnimationFrame self.dragScrollX
false
self.handle.addEventListener 'mousedown', (e) ->
do e.stopPropagation
# Avoid slecting everthing while dragging the handle
self.el.style.userSelect = 'none'
# Gt pressed handle
self.pressing = e.target
# Get clicked position
self.clickedY = e.clientY - self.pressing.getBoundingClientRect().top
requestAnimationFrame self.dragScrollY
false
document.addEventListener 'mouseup', (e) ->
# Allow selecting again
self.el.style.userSelect = 'auto'
self.pressing = null
return
return
onScroll: =>
@handleX.style.transform = "translateX(#{@wrapper.scrollLeft / @wrapper.scrollWidth * @wrapper.clientWidth}px)"
@handle.style.transform = "translateY(#{@wrapper.scrollTop / @wrapper.scrollHeight * @wrapper.clientHeight}px)"
return
adjustSize: =>
height = @wrapper.clientHeight / @wrapper.scrollHeight * @wrapper.clientHeight
@handle.style.height = "#{height}px"
if @track.clientHeight <= height + 1
@track.classList.add 'scrollbar_maxed'
else
@track.classList.remove 'scrollbar_maxed'
width = @wrapper.clientWidth / @wrapper.scrollWidth * @wrapper.clientWidth
@handleX.style.width = "#{width}px"
if @trackX.clientWidth <= width + 1
@trackX.classList.add 'scrollbar_maxed'
else
@trackX.classList.remove 'scrollbar_maxed'
return
dragScrollX: =>
if @pressing and @pressing.classList.contains 'scrollbar__handle_direction_horizontal'
# Handle bounds
bound = do @pressing.getBoundingClientRect
# Element bounds
scbound = do @wrapper.getBoundingClientRect
x = undefined
if @mouseX < scbound.left # If exceeded the left
x = 0
else if @mouseX > scbound.right # If exceeded the right
x = @wrapper.clientwidth - @pressing.clientwidth - 1
else
x = @mouseX - @clickedX - scbound.left
if x >= 0 and x < @wrapper.clientWidth - @pressing.clientWidth # If X handle is within limits
@pressing.style.transform = "translateX(#{x}px)"
@wrapper.scrollLeft = (bound.left - scbound.left) * @wrapper.scrollWidth / @wrapper.clientWidth
requestAnimationFrame @dragScrollX
return
dragScrollY: =>
if @pressing and @pressing.classList.contains 'scrollbar__handle_direction_vertical'
# Handle bounds
bound = do @pressing.getBoundingClientRect
# Element bounds
scbound = do @wrapper.getBoundingClientRect
y = undefined
if @mouseY < scbound.top # If exceeded the top
y = 0
else if @mouseY > scbound.bottom # If exceeded the bottom
y = @wrapper.clientHeight - @pressing.clientHeight - 1
else
y = @mouseY - @clickedY - scbound.top
if y >= 0 and y < @wrapper.clientHeight - @pressing.clientHeight # If Y handle is within limits
@pressing.style.transform = "translateY(#{y}px)"
@wrapper.scrollTop = (bound.top - scbound.top) * @wrapper.scrollHeight / @wrapper.clientHeight
requestAnimationFrame @dragScrollY
return
# Helper functions
export addScrollers = ->
for el in $class 'scroller'
unless el.classList.contains 'scroller_initiated'
addScroller el
export addScroller = (el) ->
new Scroller el
# Export Scroller class
export default Scroller