attentive/lib/assets/javascripts/attentive.js.coffee

158 lines
3.5 KiB
CoffeeScript

class PresentationTimer
constructor: ->
@time = 0
@el = document.createElement('div')
@el.classList.add('timer')
this.render()
render: ->
@el.innerHTML = this.formattedTime()
start: ->
@_runner = this.runner()
runner: ->
setTimeout(
=>
this.render()
@time += 1
this.runner() if @_runner?
, 1000
)
stop: ->
clearTimeout(@_runner)
@_runner = null
reset: ->
this.stop()
@time = 0
this.render()
toggle: ->
if @_runner?
this.stop()
else
this.start()
toggleVisible: ->
@el.classList.toggle('hide')
isVisible: ->
!@el.classList.contains('hide')
hide: ->
@el.classList.add('hide')
formattedTime: ->
minute = "00#{Math.floor(@time / 60)}".slice(-2)
second = "00#{@time % 60}".slice(-2)
"#{minute}:#{second}"
class this.Attentive
@setup: (identifier) ->
starter = -> (new Attentive(identifier)).start()
window.addEventListener('DOMContentLoaded', starter, false)
constructor: (@identifier) ->
@length = @allSlides().length
@priorSlide = null
@initialRender = true
@timer = new PresentationTimer()
@timer.hide()
document.querySelector('body').appendChild(@timer.el)
bodyClassList: ->
@_bodyClassList ||= document.querySelector('body').classList
allSlides: ->
@_allSlides ||= @slidesViewer().querySelectorAll('.slide')
slidesViewer: ->
@_slidesViewer ||= document.querySelector(@identifier)
start: ->
@bodyClassList().add('loading')
if !this.isFile()
window.addEventListener('popstate', @handlePopState, false)
document.addEventListener('click', @handleClick, false)
document.addEventListener('keydown', @handleKeyDown, false)
window.addEventListener('resize', @calculate, false)
this.advanceTo(this.slideFromLocation())
slideFromLocation: ->
value = if this.isFile()
location.hash
else
location.pathname
Number(value.substr(1))
handlePopState: (e) =>
this.advanceTo(if e.state then e.state.index else this.slideFromLocation())
handleClick: (e) =>
this.advance() if e.target.tagName != 'A'
handleKeyDown: (e) =>
switch e.keyCode
when 72
this.advanceTo(0)
when 37
this.advance(-1)
when 39, 32
this.advance()
when 220
@timer.reset()
when 84
if e.shiftKey
@timer.toggleVisible()
else
@timer.toggle() if @timer.isVisible()
advance: (offset = 1) =>
this.advanceTo(Math.max(Math.min(@currentSlide + offset, @length - 1), 0))
isFile: => location.href.slice(0, 4) == 'file'
advanceTo: (index) =>
@priorSlide = @currentSlide
@currentSlide = index || 0
this.calculate()
if this.isFile()
location.hash = @currentSlide
else
history.pushState({ index: @currentSlide }, '', @currentSlide)
calculate: =>
for slide in @allSlides()
slide.style['width'] = "#{window.innerWidth}px"
height = (window.innerHeight - slide.querySelector('.content').clientHeight) / 2
slide.style['marginTop'] = "#{height}px"
@slidesViewer().style['width'] = "#{window.innerWidth * @allSlides().length}px"
this.align()
align: =>
@allSlides()[@priorSlide].classList.remove('active') if @priorSlide
@allSlides()[@currentSlide].classList.add('active')
@slidesViewer().style['left'] = "-#{@currentSlide * window.innerWidth}px"
if @initialRender
@bodyClassList().remove('loading')
@initialRender = false