init
This commit is contained in:
commit
f1085ce37b
5 changed files with 215 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
*.css
|
||||
*.html
|
||||
*.js
|
11
Makefile
Normal file
11
Makefile
Normal file
|
@ -0,0 +1,11 @@
|
|||
all: index.html app.js app.css
|
||||
.PHONY: all
|
||||
|
||||
index.html: index.html.haml
|
||||
haml $^ $@
|
||||
|
||||
app.js: app.js.coffee
|
||||
coffee -cs >$@ <$^
|
||||
|
||||
app.css: app.css.sass
|
||||
sassc $^ $@
|
68
app.css.sass
Normal file
68
app.css.sass
Normal file
|
@ -0,0 +1,68 @@
|
|||
#clock
|
||||
.duration
|
||||
font-size: 2em
|
||||
text-align: center
|
||||
|
||||
.controls
|
||||
button, a
|
||||
display: inline-block
|
||||
border: none
|
||||
background: #fff
|
||||
color: #000
|
||||
box-shadow: inset 0 0 0.7ex white, 0 0 0.7ex white
|
||||
margin: 1ex
|
||||
&:not(:first-child)
|
||||
margin-left: 2ex
|
||||
padding: 1ex
|
||||
font-size: 2em
|
||||
border-radius: 1ex
|
||||
outline: none
|
||||
&:hover, &:active
|
||||
box-shadow: inset 0 0 0.7ex white, 0 0 1ex white
|
||||
background: #ddd
|
||||
color: #000
|
||||
&:hover, &:active, &:focus, &
|
||||
outline: none
|
||||
> *
|
||||
display: none
|
||||
&[data-state=loaded] > .if_loaded,
|
||||
&[data-state=started] > .if_started,
|
||||
&[data-state=stopped] > .if_stopped
|
||||
display: initial
|
||||
|
||||
#timelist
|
||||
tr > td:first-child
|
||||
text-align: right
|
||||
width: 3em
|
||||
input
|
||||
background: black
|
||||
border: none
|
||||
color: white
|
||||
box-shadow: inset 0 0 1px white, 0 0 1px white
|
||||
&:hover, &:focus, &:active
|
||||
box-shadow: inset 0 0 0.7ex white, 0 0 1ex white
|
||||
&:hover, &:focus, &:active, &
|
||||
outline: none
|
||||
|
||||
main
|
||||
margin: 0 auto
|
||||
width: 20em
|
||||
text-align: center
|
||||
table
|
||||
text-align: initial
|
||||
min-height: 20em
|
||||
|
||||
.duration
|
||||
font-family: monospace
|
||||
|
||||
html, body
|
||||
border: none
|
||||
margin: 0
|
||||
padding: 0
|
||||
background-color: #111
|
||||
color: #fff
|
||||
|
||||
footer
|
||||
font-size: 0.5em
|
||||
color: #444
|
||||
text-align: right
|
101
app.js.coffee
Normal file
101
app.js.coffee
Normal file
|
@ -0,0 +1,101 @@
|
|||
|
||||
window.duration_to_string = (dur) ->
|
||||
pad = (x) ->
|
||||
x = Math.floor x
|
||||
if 10 > x
|
||||
"0#{x}"
|
||||
else
|
||||
x
|
||||
pad3 = (x) ->
|
||||
x = Math.floor x
|
||||
if 10 > x
|
||||
"00#{x}"
|
||||
else if 100 > x
|
||||
"0#{x}"
|
||||
else
|
||||
x
|
||||
"#{pad dur/3600000}:#{pad (dur/60000) % 60}:#{pad dur / 1000 % 60}.#{pad3 dur % 1000}"
|
||||
|
||||
class Clock
|
||||
constructor: (el) ->
|
||||
@element = el
|
||||
@controls = el.querySelector ':scope .controls'
|
||||
@startbtn = el.querySelector ':scope .start'
|
||||
@splitbtn = el.querySelector ':scope .split'
|
||||
@stopbtn = el.querySelector ':scope .stop'
|
||||
@clock = el.querySelector ':scope .duration'
|
||||
@starttime = null
|
||||
@clock_interval = null
|
||||
|
||||
new_event = (name, opts) ->
|
||||
ev = new Event name
|
||||
ev[k] = v for k, v of opts
|
||||
ev
|
||||
|
||||
activate: ->
|
||||
@startbtn.addEventListener 'click', (e) =>
|
||||
e.preventDefault()
|
||||
@starttime = new Date
|
||||
clearInterval @clock_interval if @clock_interval
|
||||
@clock_interval = setInterval( (=> @update_clock()), 47)
|
||||
@controls.setAttribute 'data-state', 'started'
|
||||
@element.dispatchEvent new_event( 'clock_started', clock: @, duration: 0, starttime: @starttime)
|
||||
false
|
||||
@stopbtn.addEventListener 'click', (e) =>
|
||||
e.preventDefault()
|
||||
dur = @duration
|
||||
@starttime = null
|
||||
clearInterval @clock_interval if @clock_interval
|
||||
@controls.setAttribute 'data-state', 'stopped'
|
||||
@element.dispatchEvent new_event( 'clock_stopped', clock: @, duration: @duration, starttime: @starttime)
|
||||
false
|
||||
@splitbtn.addEventListener 'click', (e) =>
|
||||
e.preventDefault()
|
||||
@element.dispatchEvent new_event( 'clock_splitted', clock: @, duration: @duration, starttime: @starttime)
|
||||
false
|
||||
|
||||
Object.defineProperty @::, 'duration',
|
||||
enumerable: true
|
||||
get: ->
|
||||
if @starttime?
|
||||
new Date - @starttime
|
||||
else
|
||||
null
|
||||
|
||||
update_clock: ->
|
||||
@clock.textContent = duration_to_string @duration
|
||||
|
||||
window.addEventListener 'load', ->
|
||||
window.clock = new Clock document.querySelector( '#clock')
|
||||
clock.activate()
|
||||
|
||||
window.timelist = document.querySelector( '#timelist')
|
||||
window.list = []
|
||||
counter = 0
|
||||
clock.element.addEventListener 'clock_splitted', (e) ->
|
||||
counter++
|
||||
dur = duration_to_string e.duration
|
||||
tr = document.createElement 'tr'
|
||||
td = document.createElement 'td'
|
||||
td.textContent = "#{++counter}"
|
||||
tr.appendChild td
|
||||
td = document.createElement 'td'
|
||||
td.textContent = dur
|
||||
tr.appendChild td
|
||||
td = document.createElement 'td'
|
||||
iu = document.createElement('input')
|
||||
iu.setAttribute 'type', 'text'
|
||||
td.appendChild iu
|
||||
tr.appendChild td
|
||||
window.timelist.appendChild tr
|
||||
window.list.push [counter, dur, iu]
|
||||
true
|
||||
|
||||
download = clock.element.querySelector ':scope .export'
|
||||
exporthelper = clock.element.querySelector ':scope .exporthelper'
|
||||
download.addEventListener 'click', (e) ->
|
||||
t = ''
|
||||
for en in window.list
|
||||
t += "#{en[0]}\t#{en[1]}\t#{en[2].value}\n"
|
||||
exporthelper.href = "data:text/csv;name=schplitted.csv,#{encodeURIComponent t}"
|
||||
exporthelper.click()
|
32
index.html.haml
Normal file
32
index.html.haml
Normal file
|
@ -0,0 +1,32 @@
|
|||
!!! %
|
||||
%html
|
||||
%head
|
||||
%meta(charset="utf-8")
|
||||
%meta(http-equiv="X-UA-Compatible" content="IE=edge")
|
||||
%meta(name="viewport" content="width=device-width, initial-scale=1")
|
||||
%title Zeitschplitter
|
||||
%link(rel="stylesheet" href="app.css")
|
||||
%script(type="text/javascript" src="app.js")
|
||||
|
||||
%body
|
||||
%header
|
||||
%h1 Zeitschplitter
|
||||
%main
|
||||
#clock
|
||||
.duration 00:00:00.0
|
||||
.controls(data-state="loaded")
|
||||
.if_loaded
|
||||
%button.start ▶
|
||||
.if_started
|
||||
%button.stop ■
|
||||
%button.split ✁
|
||||
.if_stopped
|
||||
%button.export ⤓
|
||||
.never
|
||||
%a.exporthelper(download="schplitter.csv")
|
||||
#TimeList
|
||||
%table
|
||||
%thead
|
||||
%tbody#timelist
|
||||
%footer
|
||||
Denis Knauf - Zeitschplitter - Stoppuhr für <code>n</code> Teilnehmer
|
Loading…
Reference in a new issue