4 var precision
= 100; // milliseconds
5 var defaultTime
= (15 * 60 + 0) * 1000; // milliseconds
6 var time
= defaultTime
;
8 this.isTicking
= false;
9 var outputTime
= function() {
10 document
.getElementById(id
).innerHTML
= timeToTimeStr(time
);
11 var flagid
= "flag-" + id
.split('-')[1];
12 var flagelem
= document
.getElementById(flagid
);
13 flagelem
.style
.visibility
= time
<= 0 ? "visible" : "hidden";
16 var startTickingUnixTime
= null;
17 var remainingTimeAtTickingStart
= null;
19 var thisTimer
= this; // workaround to use this in setInterval
20 this.tick
= function() {
21 var currentPassedTime
= new Date() - startTickingUnixTime
;
22 time
= remainingTimeAtTickingStart
- currentPassedTime
;
26 clearInterval(intervalID
);
27 thisTimer
.isTicking
= false;
31 this.start
= function() {
32 startTickingUnixTime
= new Date();
33 remainingTimeAtTickingStart
= time
;
34 intervalID
= setInterval(this.tick
, precision
);
35 this.isTicking
= true;
37 this.stop
= function() {
38 clearInterval(intervalID
);
39 this.isTicking
= false;
41 this.setTime
= function(t
) {
46 this.getTime
= function() {
49 this.reset
= function() {
53 this.setTime(defaultTime
);
55 this.getDefaultTime
= function() {
60 var currentTimers
= new (function() {
61 this.leftTimer
= new Timer("timer-left");
62 this.rightTimer
= new Timer("timer-right");
63 this.active
= this.leftTimer
;
64 this.passive
= this.rightTimer
;
66 this.swap
= function() {
67 var tmp
= this.passive
;
68 this.passive
= this.active
;
70 var icon
= document
.getElementById("play");
71 icon
.innerHTML
= (icon
.innerHTML
== "◀" ? "▶" : "◀");
73 this.pause
= function() {
76 document
.getElementById("pause").style
.visibility
= "visible";
78 this.resume
= function() {
80 this.isPaused
= false;
81 document
.getElementById("pause").style
.visibility
= "hidden";
85 function timeStrToTime(timeStr
) {
86 var minute
= parseInt(timeStr
.substr(0, 2));
87 var second
= parseInt(timeStr
.substr(3, 2));
88 return (minute
* 60 + second
) * 1000;
91 function timeToTimeStr(time
) {
92 var minute
= Math
.floor(time
/ 1000 / 60);
93 var second
= Math
.floor(time
/ 1000) % 60;
95 minute
= '0' + minute
.toString();
98 second
= '0' + second
.toString();
100 return minute
+ ':' + second
;
103 document
.onkeydown
= function(e
) {
106 case ' ': return toggle();
108 case 's': return setTime();
110 case 'r': return reset();
112 case 'P': return pauseResume();
115 } else if(e
.keyCode
) {
117 case 32: return toggle(); // space
118 case 83: return setTime(); // S
119 case 82: return reset(); // R
120 case 80: return pauseResume(); // P
124 alert("Browser not supported");
129 if(!currentTimers
.isPaused
) {
130 currentTimers
.active
.stop();
131 currentTimers
.passive
.start();
133 currentTimers
.swap();
134 var lbt
= document
.getElementById('left-button-top');
135 var leftIsLong
= lbt
.getAttribute('class') == 'button-long';
136 var lbt_d
= lbt
.getAttribute('d').split(' ');
137 var lbb
= document
.getElementById('left-button-body');
138 var rbt
= document
.getElementById('right-button-top');
139 var rbt_d
= rbt
.getAttribute('d').split(' ');
140 var rbb
= document
.getElementById('right-button-body');
142 var y_diff
= 50 * (leftIsLong
? 1 : -1);
143 var classes
= ['button-short', 'button-long'];
145 lbt_d
[2] = (parseInt(lbt_d
[2]) + y_diff
).toString();
146 lbt_d
[10] = (parseInt(lbt_d
[10]) + y_diff
).toString();
147 lbb
.setAttribute('height',
148 (parseInt(lbb
.getAttribute('height')) - y_diff
).toString());
149 lbb
.setAttribute('y', (parseInt(lbb
.getAttribute('y')) + y_diff
).toString());
150 rbt_d
[2] = (parseInt(rbt_d
[2]) - y_diff
).toString();
151 rbt_d
[10] = (parseInt(rbt_d
[10]) - y_diff
).toString();
152 rbb
.setAttribute('height',
153 (parseInt(rbb
.getAttribute('height')) + y_diff
).toString());
154 rbb
.setAttribute('y', (parseInt(rbb
.getAttribute('y')) - y_diff
).toString());
155 lbt
.setAttribute('class', classes
[(leftIsLong
+ 1) % 2]);
156 lbb
.setAttribute('class', classes
[(leftIsLong
+ 1) % 2]);
157 rbt
.setAttribute('class', classes
[(leftIsLong
+ 1) % 2]);
158 rbb
.setAttribute('class', classes
[(leftIsLong
+ 1) % 2]);
159 lbt
.setAttribute('d', lbt_d
.join(' '));
160 rbt
.setAttribute('d', rbt_d
.join(' '));
162 lbt
.setAttribute('onclick', leftIsLong
? '' : 'toggle()');
163 lbb
.setAttribute('onclick', leftIsLong
? '' : 'toggle()');
164 lbt
.setAttribute('cursor', leftIsLong
? 'default' : 'pointer');
165 lbb
.setAttribute('cursor', leftIsLong
? 'default' : 'pointer');
166 rbt
.setAttribute('onclick', leftIsLong
? 'toggle()' : '');
167 rbb
.setAttribute('onclick', leftIsLong
? 'toggle()' : '');
168 rbt
.setAttribute('cursor', leftIsLong
? 'pointer' : 'default');
169 rbb
.setAttribute('cursor', leftIsLong
? 'pointer' : 'default');
172 function pauseResume() {
173 if(currentTimers
.isPaused
) {
174 currentTimers
.resume();
176 currentTimers
.pause();
181 var leftstart
, rightstart
;
182 var def
= timeToTimeStr(currentTimers
.leftTimer
.getDefaultTime());
183 var regex
= /[0-9][0-9]:[0-5][0-9]/;
185 leftstart
= prompt("Time for LEFT player in MM:SS", def
);
186 if(leftstart
=== null) return; // Cancel
187 while(!leftstart
.match(regex
)) {
188 leftstart
= prompt("Invalid value\nTime for LEFT player in MM:SS", def
);
189 if(leftstart
=== null) return; // Cancel
192 rightstart
= prompt("Time for RIGHT player in MM:SS", def
);
193 if(rightstart
=== null) return; // Cancel
194 while(!rightstart
.match(regex
)) {
195 rightstart
= prompt("Invalid value\nTime for RIGHT player in MM:SS", def
);
196 if(rightstart
=== null) return; // Cancel
198 currentTimers
.leftTimer
.setTime(timeStrToTime(leftstart
));
199 currentTimers
.rightTimer
.setTime(timeStrToTime(rightstart
));
203 currentTimers
.pause();
204 currentTimers
.active
.reset();
205 currentTimers
.passive
.reset();
210 setTimeout(fitscreen
, 2000); // hack to allow DOM to be redrawn with new css
213 function fitscreen() {
215 * Scale body so as to fit the screen
217 var heightRatio
= window
.innerHeight
/ document
.body
.scrollHeight
;
218 var widthRatio
= window
.innerWidth
/ document
.body
.scrollWidth
;
219 var scaleRatio
= Math
.min(heightRatio
, widthRatio
, 1);
220 document
.body
.style
.transform
= 'scale(' + scaleRatio
+ ')';
223 function insertcss() {
224 /* fix positions for browsers that don't support flex */
225 var cssfile
= document
.getElementById("style");
226 if(!('align-items' in document
.body
.style
)) {
227 cssfile
.setAttribute("href", "noflex.css");