You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

207 lines
5.4 KiB

class TimeTable
constructor: (@element, @modal) ->
events = @element.querySelectorAll 'tbody td > ul > li'
for event in events
# JS scoping hell…
event.addEventListener 'click', ((_this, _event) ->
-> _this.modal.open _event
)(this, event)
parse_time: (time) ->
time = time.split ':'
hour = parseInt time[0]
min = parseInt time[1]
60 * hour + min
find_including: (times, time) ->
previous = null
for current in times
if previous?
if previous.time <= time < current.time
return [previous, current]
else
previous = current
null
prorate: (ref, time) ->
from = ref[0]
to = ref[1]
ratio = (time - from.time) / (to.time - from.time)
top = from.top + (to.top - from.top) * ratio
top
position: (times, element) ->
from = @parse_time(element.dataset.from)
to = @parse_time(element.dataset.to) - 5
including_from = @find_including times, from
including_to = @find_including times, to
top = @prorate including_from, from
bottom = @prorate including_to, to
root = element.parentElement
width = root.offsetWidth
element.style.top = "#{top + window.pageYOffset}px"
element.style.height = "#{bottom - top}px"
element.style.width = "#{width}px"
element.style.position = 'absolute'
init: ->
times = []
hours = @element.querySelectorAll 'tbody th > ul > li'
for hour in hours
time = @parse_time hour.dataset.time
times.push {
time: time,
top: hour.getBoundingClientRect().top
}
last = hours[hours.length - 1]
time = @parse_time last.dataset.time
rect = last.getBoundingClientRect()
times.push {
time: time + 60
top: rect.top + rect.height
}
events = @element.querySelectorAll 'tbody td > ul > li'
for event in events
@position times, event
class Modal
size: { width: 800, height: 480 }
constructor: (@modal) ->
@header = @modal.querySelector '.header'
@body = @modal.querySelector '.body'
@modal.querySelector('.close').addEventListener 'click', @close
@modal.querySelector('.cover').addEventListener 'click', @close
act: (events) ->
wrapper = =>
next = events.shift()
return unless next?
[duration, callback] = next
setTimeout (=>
callback()
wrapper()
), duration
wrapper()
start: ->
start = @event.getBoundingClientRect()
scroll = {
top: window.pageYOffset,
left: window.pageXOffset
}
@modal.style.top = "#{start.top + scroll.top}px"
@modal.style.left = "#{start.left + scroll.left}px"
@modal.style.width = "#{start.width}px"
@modal.style.height = "#{start.height}px"
@header.style.width = "#{start.width}px"
@header.style.height = "#{start.height}px"
@body.style.width = 0
@body.style.height = "#{start.height}px"
open: (@event) ->
scroll = {
top: window.pageYOffset,
left: window.pageXOffset
}
modal =
width: Math.round window.innerWidth * .8
height: Math.round window.innerHeight * .8
modal =
width: Math.min modal.width, @size.width
height: Math.min modal.height, @size.height
modal.top = Math.round (window.innerHeight - modal.height) / 2 + scroll.top
modal.left = Math.round (window.innerWidth - modal.width) / 2 + scroll.left
header_width = Math.round modal.width / 3
time = @event.querySelector('.time').textContent
@header.querySelector('.time').textContent = time
title = @event.querySelector('.title').textContent
@header.querySelector('.title').textContent = title
author = @event.querySelector('.author').textContent
@header.querySelector('.author').textContent = author
description = @event.querySelector('.description').innerHTML
@body.innerHTML = ''
@modal.classList.remove 'transition'
@act [
[20, =>
@start()
@header.classList = @event.classList
@header.classList.add 'header'
@modal.style.opacity = 1
@modal.classList.remove 'hidden'
],
[20, =>
@transition @modal, null, =>
@body.innerHTML = description
@modal.style.top = "#{modal.top}px"
@modal.style.left = "#{modal.left}px"
@modal.style.width = "#{modal.width}px"
@modal.style.height = "#{modal.height}px"
@header.style.width = "#{header_width}px"
@header.style.height = "#{modal.height}px"
@body.style.width = "#{modal.height - header_width}px"
@body.style.height = "#{modal.height}px"
]
]
close: =>
@act [
[20, =>
@transition @modal, null, =>
@modal.classList.add 'hidden'
@body.innerHTML = ''
@start()
]
]
transition: (element, events, at_end) ->
element.classList.add 'transition'
callback = ->
element.removeEventListener 'transitionend', callback
element.classList.remove 'transition'
at_end() if at_end?
element.addEventListener 'transitionend', callback
@act events if events?
class Giggity
@init: ->
giggity_logo = document.querySelector '.giggity .logo'
position = giggity_logo.getBoundingClientRect()
giggity_qrcode = document.querySelector '.giggity .qrcode'
giggity_qrcode.style.top = "#{position.bottom + 20}px"
giggity_qrcode.style.left = "#{position.right + 20}px"
giggity_logo.addEventListener 'mouseenter', ->
giggity_qrcode.classList.remove 'hidden'
giggity_logo.addEventListener 'mouseleave', ->
giggity_qrcode.classList.add 'hidden'
init = ->
modal = new Modal document.querySelector '.modal'
tables = document.querySelectorAll 'table.timetable'
for table in tables
new TimeTable(table, modal).init()
Giggity.init()
document.addEventListener 'DOMContentLoaded', init
window.addEventListener 'resize', init