4 var precision
= 100; // milliseconds
5 var defaultTime
= (15 * 60 + 0) * 1000; // milliseconds
6 var time
= defaultTime
;
8 this.isTicking
= false;
10 var defaultIncrement
= 0;
12 var outputTime
= function() {
13 document
.getElementById(id
).innerHTML
= timeToTimeStr(time
);
14 var flagid
= "flag-" + id
.split('-')[1];
15 var flagelem
= document
.getElementById(flagid
);
16 flagelem
.style
.visibility
= time
<= 0 ? "visible" : "hidden";
17 var incid
= "increment-" + id
.split('-')[1];
18 var incelem
= document
.getElementById(incid
);
19 incelem
.innerHTML
= "+" + (increment
/ 1000).toString();
20 incelem
.style
.visibility
= increment
> 0 ? "visible" : "hidden";
23 var startTickingUnixTime
= null;
24 var remainingTimeAtTickingStart
= null;
26 var thisTimer
= this; // workaround to use this in setInterval
27 this.tick
= function() {
28 var currentPassedTime
= new Date() - startTickingUnixTime
;
29 time
= remainingTimeAtTickingStart
- currentPassedTime
;
33 clearInterval(intervalID
);
34 thisTimer
.isTicking
= false;
38 this.start
= function() {
39 startTickingUnixTime
= new Date();
40 remainingTimeAtTickingStart
= time
;
41 intervalID
= setInterval(this.tick
, precision
);
42 this.isTicking
= true;
44 this.stop
= function(toggle
= false) {
45 clearInterval(intervalID
);
46 this.isTicking
= false;
47 if (toggle
&& this.getTime() > 0) {
48 this.setTime(this.getTime() + increment
, increment
, true);
51 this.setTime
= function(t
, inc
= 0, toggle
= false) {
56 defaultIncrement
= inc
;
60 this.getTime
= function() {
63 this.reset
= function() {
67 this.setTime(defaultTime
, defaultIncrement
);
69 this.getDefaultTime
= function() {
74 var currentTimers
= new (function() {
75 this.leftTimer
= new Timer("timer-left");
76 this.rightTimer
= new Timer("timer-right");
77 this.active
= this.leftTimer
;
78 this.passive
= this.rightTimer
;
80 this.swap
= function() {
81 var tmp
= this.passive
;
82 this.passive
= this.active
;
84 var icon
= document
.getElementById("play");
85 icon
.innerHTML
= (icon
.innerHTML
== "⏴" ? "⏵" : "⏴");
87 this.pause
= function() {
90 document
.getElementById("pause").style
.visibility
= "visible";
92 this.resume
= function() {
94 this.isPaused
= false;
95 document
.getElementById("pause").style
.visibility
= "hidden";
99 function timeStrToTime(timeStr
) {
100 var minute
= parseInt(timeStr
.substr(0, 2));
101 var second
= parseInt(timeStr
.substr(3, 2));
102 return (minute
* 60 + second
) * 1000;
105 function timeToTimeStr(time
) {
106 var minute
= Math
.floor(time
/ 1000 / 60);
107 var second
= Math
.floor(time
/ 1000) % 60;
109 minute
= '0' + minute
.toString();
112 second
= '0' + second
.toString();
114 return minute
+ ':' + second
;
117 document
.onkeydown
= function(e
) {
120 case ' ': return toggle();
122 case 's': return setTime();
124 case 'r': return reset();
126 case 'P': return pauseResume();
129 } else if(e
.keyCode
) {
131 case 32: return toggle(); // space
132 case 83: return setTime(); // S
133 case 82: return reset(); // R
134 case 80: return pauseResume(); // P
138 alert("Browser not supported");
143 if(!currentTimers
.isPaused
) {
144 currentTimers
.active
.stop(true);
145 currentTimers
.passive
.start();
147 currentTimers
.swap();
148 var lbt
= document
.getElementById('left-button-top');
149 var leftIsLong
= lbt
.getAttribute('class') == 'button-long';
150 var lbt_d
= lbt
.getAttribute('d').split(' ');
151 var lbb
= document
.getElementById('left-button-body');
152 var rbt
= document
.getElementById('right-button-top');
153 var rbt_d
= rbt
.getAttribute('d').split(' ');
154 var rbb
= document
.getElementById('right-button-body');
156 var y_diff
= 50 * (leftIsLong
? 1 : -1);
157 var classes
= ['button-short', 'button-long'];
159 lbt_d
[2] = (parseInt(lbt_d
[2]) + y_diff
).toString();
160 lbt_d
[10] = (parseInt(lbt_d
[10]) + y_diff
).toString();
161 lbb
.setAttribute('height',
162 (parseInt(lbb
.getAttribute('height')) - y_diff
).toString());
163 lbb
.setAttribute('y', (parseInt(lbb
.getAttribute('y')) + y_diff
).toString());
164 rbt_d
[2] = (parseInt(rbt_d
[2]) - y_diff
).toString();
165 rbt_d
[10] = (parseInt(rbt_d
[10]) - y_diff
).toString();
166 rbb
.setAttribute('height',
167 (parseInt(rbb
.getAttribute('height')) + y_diff
).toString());
168 rbb
.setAttribute('y', (parseInt(rbb
.getAttribute('y')) - y_diff
).toString());
169 lbt
.setAttribute('class', classes
[(leftIsLong
+ 1) % 2]);
170 lbb
.setAttribute('class', classes
[(leftIsLong
+ 1) % 2]);
171 rbt
.setAttribute('class', classes
[(leftIsLong
+ 1) % 2]);
172 rbb
.setAttribute('class', classes
[(leftIsLong
+ 1) % 2]);
173 lbt
.setAttribute('d', lbt_d
.join(' '));
174 rbt
.setAttribute('d', rbt_d
.join(' '));
176 lbt
.setAttribute('onclick', leftIsLong
? '' : 'toggle()');
177 lbb
.setAttribute('onclick', leftIsLong
? '' : 'toggle()');
178 lbt
.setAttribute('cursor', leftIsLong
? 'default' : 'pointer');
179 lbb
.setAttribute('cursor', leftIsLong
? 'default' : 'pointer');
180 rbt
.setAttribute('onclick', leftIsLong
? 'toggle()' : '');
181 rbb
.setAttribute('onclick', leftIsLong
? 'toggle()' : '');
182 rbt
.setAttribute('cursor', leftIsLong
? 'pointer' : 'default');
183 rbb
.setAttribute('cursor', leftIsLong
? 'pointer' : 'default');
186 function pauseResume() {
187 if(currentTimers
.isPaused
) {
188 currentTimers
.resume();
190 currentTimers
.pause();
195 var leftstart
, rightstart
;
196 var def
= timeToTimeStr(currentTimers
.leftTimer
.getDefaultTime());
197 var regex
= /[0-9][0-9]:[0-5][0-9](\+[0-9]+)?/;
199 leftstart
= prompt("Time for LEFT player in MM:SS or MM:SS+S", def
);
200 if(leftstart
=== null) return; // Cancel
201 while(!leftstart
.match(regex
)) {
202 leftstart
= prompt("Invalid value\nTime for LEFT player in MM:SS or MM:SS+S", def
);
203 if(leftstart
=== null) return; // Cancel
206 rightstart
= prompt("Time for RIGHT player in MM:SS or MM:SS+S", def
);
207 if(rightstart
=== null) return; // Cancel
208 while(!rightstart
.match(regex
)) {
209 rightstart
= prompt("Invalid value\nTime for RIGHT player in MM:SS or MM:SS+S", def
);
210 if(rightstart
=== null) return; // Cancel
213 if(leftstart
.indexOf('+') > 0) {
214 var baseTime
= leftstart
.split('+')[0];
215 var inc
= leftstart
.split('+')[1];
216 currentTimers
.leftTimer
.setTime(timeStrToTime(baseTime
), parseInt(inc
) * 1000);
219 currentTimers
.leftTimer
.setTime(timeStrToTime(leftstart
));
221 if(rightstart
.indexOf('+') > 0) {
222 var baseTime
= rightstart
.split('+')[0];
223 var inc
= rightstart
.split('+')[1];
224 currentTimers
.rightTimer
.setTime(timeStrToTime(baseTime
), parseInt(inc
) * 1000);
227 currentTimers
.rightTimer
.setTime(timeStrToTime(leftstart
));
232 currentTimers
.pause();
233 currentTimers
.active
.reset();
234 currentTimers
.passive
.reset();
239 setTimeout(fitscreen
, 2000); // hack to allow DOM to be redrawn with new css
242 function fitscreen() {
244 * Scale body so as to fit the screen
246 var heightRatio
= window
.innerHeight
/ document
.body
.scrollHeight
;
247 var widthRatio
= window
.innerWidth
/ document
.body
.scrollWidth
;
248 var scaleRatio
= Math
.min(heightRatio
, widthRatio
, 1);
249 document
.body
.style
.transform
= 'scale(' + scaleRatio
+ ')';
252 function insertcss() {
253 /* fix positions for browsers that don't support flex */
254 var cssfile
= document
.getElementById("style");
255 if(!('align-items' in document
.body
.style
)) {
256 cssfile
.setAttribute("href", "noflex.css");