This commit is contained in:
Denis Knauf 2019-11-04 12:45:00 +01:00
commit f1085ce37b
5 changed files with 215 additions and 0 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
*.css
*.html
*.js

11
Makefile Normal file
View 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
View 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
View 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
View 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 &#9654;
.if_started
%button.stop &#9632;
%button.split &#9985;
.if_stopped
%button.export &#10515;
.never
%a.exporthelper(download="schplitter.csv")
#TimeList
%table
%thead
%tbody#timelist
%footer
Denis Knauf - Zeitschplitter - Stoppuhr für <code>n</code> Teilnehmer