git.fiddlerwoaroof.com
src/App.vue
4437840d
 <template>
     <div id="app">
 	<header>
 	    <h1>
 		Timer
 	    </h1>
 	    <div>
 		<button @click="mark">Go</button>
d77a13db
 		<button @click="reset">Reset</button>
4437840d
 	    </div>
 	</header>
 	<ol>
 	    <li class=header>
 		<div>Time</div><div>Lap Time</div><div>Cumulative</div>
 	    </li>
d77a13db
 
4437840d
 	    <li v-for="[time,diff,cum,new_annotation] in times">
 		<div class="time">{{formatTime(time.time)}}</div>
 		<div class="diff"><div class="time">{{formatDiff(diff)[0]}}</div><div class="mills">.{{formatDiff(diff)[1]}}</div></div>
 		<div class="cum"><div class="time">{{formatDiff(cum)[0]}}</div><div class="mills">.{{formatDiff(cum)[1]}}</div></div>
 		<div class="actions">
 		    <form @submit.prevent="annotate(time.id, new_annotation)">
 		    <input type=text v-model="new_annotation">
 		    <button type="submit">+</button>
 		    </form>
 		</div>
 		<ul v-show="time.annotations.length > 0">
 		    <li class="annotation" v-for="annotation in time.annotations">
 			<div>
 			    {{annotation.text}}
 			</div>
 			<time datetime="annotation.time">{{formatTime(annotation.time)}}</time>
 		    </li>
 		</ul>
 		
 	    </li>
 	</ol>
     </div>
   </template>
 
 <script>
 
 import {mapGetters} from 'vuex';
 
 export default {
     name: 'app',
     data () {
 	return {
 	    msg: 'Welcome to Your Vue.js App',
d77a13db
 	    curTime: Date.now(),
4437840d
 	}
     },
 
d77a13db
     beforeMount() {
 	// this.$data.curTime = new Date();
 	// console.log('foo');
 	// window.setInterval( () => {
 	//     console.log(this.$data);
 	//     this.$data.curTime = new Date();
 	// }, 100);
     },
 
4437840d
     computed: {
 	times() {
 	    let result = [];
 	    for (let cur of this.$store.state.times) {
8320b1e7
 		if ((typeof cur.time) === "string") {
 		    cur = Object.assign(
 			Object.create(cur),
 			{time: new Date(cur.time)}
 		    );
 		}
 		
4437840d
 		let diff = 0, cum = 0;
 		if (cur.id > 0) {
 		    cum = cur.time - result[cur.id-1][0].time;
 		    diff = cur.time-result[0][0].time
 		}
 
 		result.unshift([cur, diff, cum, '']);
 	    }
 	    return result;
 	},
     },
 
     methods: {
d77a13db
 	reset() {
 	    this.$store.commit('reset');
 	},
 	
4437840d
 	annotate(idx, annotation) {
 	    this.$store.commit('annotate', {idx, annotation});
 	},
 	mark() {
 	    this.$store.commit('add');
 	},
 
 	formatTime: function (time) {
 	    return (new Intl.DateTimeFormat('en-US', {
 		year:'numeric', month:'numeric', day:'numeric', hour:'2-digit', minute: '2-digit', second:'2-digit'
d77a13db
 	    })).format(time.time);
4437840d
 	},
 
 	formatDiff(diff) {
 	    let secs = Math.floor(diff/1000),
 		mills = diff % 1000,
 		mins = Math.floor(secs/60);
 	    secs = secs % 60;
 	    mins = `${mins}`;
 	    if (mills.length < 3) {
 		let pad = '0'*(3-mills.length);
 		mills = pad + mills;
 	    }
 	    let result = `${secs}`
 	    if (mins > 0) {
 		result = `${mins}:${result.padStart(2,'0')}`;
 	    }
 	    return [result,mills];
 	}
     },
 }
     </script>
 
 <style lang="scss">
   * { box-sizing: border-box; }
     #app {
 	font-family: 'Lato', Helvetica, Arial, sans-serif;
 	-webkit-font-smoothing: antialiased;
 	-moz-osx-font-smoothing: grayscale;
 	text-align: right;
 	color: #2c3e50;
     }
 
     header {
 	display: grid;
 	grid-template-columns: 75fr 25fr;
 	height: 3em;
 	line-height: 3em;
 	padding: 0;
     }
     
     h1, h2 {
 	text-align: center;
 	font-size: 1.25em;
 	padding: 0;
 	margin: 0;
     }
 
     ul {
 	list-style-type: none;
 	padding: 0;
     }
 
     a {
 	color: #42b983;
     }
 
     ol {
 	position: absolute;
 	width: 100%;
 	top: 4em;
 	bottom: 0;
 	left: 0;
 	margin: 0;
 	padding: 0 1em;
 	padding-top: 3.25em;
 	overflow-y: scroll;
 	overflow-x: auto;
     }
 
     ol > li {
 	display: grid;
 	grid-template-columns: 25fr 12.5fr 12.5fr 25fr 25fr;
 	padding: 0.5em;
 	margin-bottom: 0.25em;
     }
 
     li.header {
 	position: fixed;
 	top: 4em;
 	left: 1em;
 	right: 1em;
 	background: #eee;
     }
 
     ul {
 	/* grid-column-start: 2; */
 	/* grid-column-end: span 2; */
 	padding: 0.25em;
 	margin: 0.25em;
 	padding-right: 0;
 	margin-right: 0;
     }
     ul > li {
 	padding: 0.2em 1em;
 	background: #ffb;
 	font-style: italic;
     }
     ul > li+li {
 	border-top: 0.25em double #eee;
     }
 
     .diff, .cum {
 	text-align: right;
     }
     
     .diff div, .cum div {
 	display: inline-block;
     }
 
     .diff .time, .cum .time {
 	max-width: 80%;
 	text-align: right;
     }
 
     .diff .mills, .cum .mills {
 	width: 20%;
 	text-align: left;
     }
 
     button {
 	height: 100%;
     }
 
     .annotation {
 	color: #888;
 	}
     .annotation time::before {
 	content: "— "
     }
     .annotation time {
 	font-size: 60%;
 
     }
 </style>