forked from uken/react-countdown-timer
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcountdown_timer.jsx
More file actions
123 lines (100 loc) · 3.09 KB
/
countdown_timer.jsx
File metadata and controls
123 lines (100 loc) · 3.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import React, { Component, PropTypes } from 'react'
// Generic Countdown Timer UI component
//
// props:
// - initialTimeRemaining: Number
// The time remaining for the countdown (in ms).
//
// - interval: Number (optional -- default: 1000ms)
// The time between timer ticks (in ms).
//
// - formatFunc(timeRemaining): Function (optional)
// A function that formats the timeRemaining.
//
// - tickCallback(timeRemaining): Function (optional)
// A function to call each tick.
//
export default class CountdownTimer extends Component {
static propTypes = {
initialTimeRemaining: React.PropTypes.number.isRequired,
interval: React.PropTypes.number,
formatFunc: React.PropTypes.func,
tickCallback: React.PropTypes.func,
completeCallback: React.PropTypes.func
}
defaultProps = {
interval: 1000,
formatFunc: null,
tickCallback: null,
completeCallback: null,
}
state = {
timeRemaining: this.props.initialTimeRemaining,
timeoutId: null,
prevTime: null
}
componentWillMount() {
this.isComponentMounted = false;
}
isMounted() {
return this.isComponentMounted;
}
componentDidMount() {
this.isComponentMounted = true;
this.tick = this.tick.bind(this)
this.getFormattedTime = this.getFormattedTime.bind(this)
this.tick();
}
componentWillUnmount() {
clearTimeout(this.state.timeoutId);
}
tick() {
var currentTime = Date.now();
var dt = this.state.prevTime ? (currentTime - this.state.prevTime) : 0;
var interval = this.props.interval;
// correct for small variations in actual timeout time
var timeRemainingInInterval = (interval - (dt % interval));
var timeout = timeRemainingInInterval;
if (timeRemainingInInterval < (interval / 2.0)) {
timeout += interval;
}
var timeRemaining = Math.max(this.state.timeRemaining - dt, 0);
var countdownComplete = (this.state.prevTime && timeRemaining <= 0);
if (this.isMounted()) {
if (this.state.timeoutId) { clearTimeout(this.state.timeoutId); }
this.setState({
timeoutId: countdownComplete ? null : setTimeout(this.tick, timeout),
prevTime: currentTime,
timeRemaining: timeRemaining
});
}
if (countdownComplete) {
if (this.props.completeCallback) { this.props.completeCallback(); }
return;
}
if (this.props.tickCallback) {
this.props.tickCallback(timeRemaining);
}
}
getFormattedTime = (milliseconds) => {
if (this.props.formatFunc) {
return this.props.formatFunc(milliseconds);
}
var totalSeconds = Math.round(milliseconds / 1000);
var seconds = parseInt(totalSeconds % 60);
var minutes = parseInt(totalSeconds / 60) % 60;
var hours = parseInt(totalSeconds / 3600);
seconds = seconds < 10 ? '0' + seconds : seconds;
minutes = minutes < 10 ? '0' + minutes : minutes;
hours = hours < 10 ? '0' + hours : hours;
return hours + ':' + minutes + ':' + seconds;
}
render() {
var timeRemaining = this.state.timeRemaining;
return (
<div className='timer'>
{this.getFormattedTime(timeRemaining)}
</div>
);
}
}