Permalink
Find file
bd6830f Jul 31, 2012
executable file 237 lines (219 sloc) 5.78 KB
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="chrome=1" />
<title>HTML5 Server-Sent Test</title>
<style>
@-webkit-keyframes glowGreen {
from {
-webkit-box-shadow: rgba(0, 255, 0, 0) 0 0 0;
}
50% {
-webkit-box-shadow: rgba(0, 255, 0, 1) 0 0 10px;
}
to {
-webkit-box-shadow: rgba(0, 255, 0, 0) 0 0 0;
}
}
@-webkit-keyframes glowRed {
from {
-webkit-box-shadow: rgba(255, 0, 0, 0) 0 0 0;
}
50% {
-webkit-box-shadow: rgba(255, 0, 0, 1) 0 0 10px;
}
to {
-webkit-box-shadow: rgba(255, 0, 0, 0) 0 0 0;
}
}
body {
font: 12px Arial, sans-serif;
background-color: #eee;
color: #444;
}
#connection {
font: 14px Arial, sans-serif;
font-weight: bold;
vertical-align: middle;
color: black;
}
#connection div {
background-color: orange;
width: 10px;
height: 10px;
display: inline-block;
border-radius: 10px;
margin-left: 5px;
-webkit-animation-duration: 2s;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: linear;
}
#connection.connected div {
background-color: green;
-webkit-box-shadow: rgba(0, 255, 0, 0.5) 0px 0px 5px;
-webkit-animation-name: glowGreen;
}
#connection.disconnected div {
background-color: red;
-webkit-box-shadow: rgba(255, 0, 0, 0.5) 0px 0px 5px;
-webkit-animation-name: glowRed;
}
#log {
overflow: auto;
width: 300px;
height: 350px;
margin-right: 20px;
float: left;
}
#log p {
margin: 0;
padding: 0;
}
#log .info {
color: navy;
font-weight: bold;
}
#log .msg {
margin-left: 11px;
}
.border {
border: 2px solid black;
border-radius: 5px;
padding: 10px;
background-color: white;
}
#right-panel div {
text-align: left;
}
#right-panel {
height: 350px;
width: 585px;
float: left;
font-size: 14px;
text-align: center;
}
button {
background: -webkit-gradient(linear, 0% 40%, 0% 70%, from(#F9F9F9), to(#E3E3E3));
border: 1px solid #ccc;
border-radius: 3px;
margin: 0 8px 0 0;
color: black;
padding: 5px 8px;
outline: none;
white-space: nowrap;
vertical-align: middle;
-webkit-user-select:none;
user-select: none;
cursor: pointer;
}
button:not([disabled]):hover {
border: 1px solid #939393;
}
button:not([disabled]):active {
background: -webkit-gradient(linear, 0% 40%, 0% 70%, from(#E3E3E3), to(#F9F9F9));
}
button[disabled] {
color: #ccc;
}
</style>
</head>
<body>
<p>
<button onclick="logger.clear()">Clear log</button>
<button onclick="closeConnection()">Stop reconnections</button>
<span id="connection">Connecting...<div></div></span>
</p>
<div class="border" id="log"></div>
<div class="border" id="right-panel"><div>The clock before is implemented using HTML5 <code>&lt;canvas&gt;</code> and
</code><a href="http://www.html5rocks.com/tutorials/sse/basics/">Server-Sent Events</a>.
The server's time is pushed to the client every 5 seconds using a single open connection.
The server is set to break connections lasting longer than 10 seconds. However, the browser
automatically reconnects SSEs ~3 seconds after dropped connections!</div>
<canvas class="CoolClock::140:::showDigital" title="Server Sent Events are powering this clock"></canvas>
</div>
<script src="coolclock.js" type="text/javascript"></script>
<script>
if (!window.DOMTokenList) {
Element.prototype.containsClass = function(name) {
return new RegExp("(?:^|\\s+)" + name + "(?:\\s+|$)").test(this.className);
};
Element.prototype.addClass = function(name) {
if (!this.containsClass(name)) {
var c = this.className;
this.className = c ? [c, name].join(' ') : name;
}
};
Element.prototype.removeClass = function(name) {
if (this.containsClass(name)) {
var c = this.className;
this.className = c.replace(
new RegExp("(?:^|\\s+)" + name + "(?:\\s+|$)", "g"), "");
}
};
}
// sse.php sends messages with text/event-stream mimetype.
var source = new EventSource('sse.php');
function Logger(id) {
this.el = document.getElementById(id);
}
Logger.prototype.log = function(msg, opt_class) {
var fragment = document.createDocumentFragment();
var p = document.createElement('p');
p.className = opt_class || 'info';
p.textContent = msg;
fragment.appendChild(p);
this.el.appendChild(fragment);
};
Logger.prototype.clear = function() {
this.el.textContent = '';
};
var logger = new Logger('log');
function closeConnection() {
source.close();
logger.log('> Connection was closed');
updateConnectionStatus('Disconnected', false);
}
function updateConnectionStatus(msg, connected) {
var el = document.querySelector('#connection');
if (connected) {
if (el.classList) {
el.classList.add('connected');
el.classList.remove('disconnected');
} else {
el.addClass('connected');
el.removeClass('disconnected');
}
} else {
if (el.classList) {
el.classList.remove('connected');
el.classList.add('disconnected');
} else {
el.removeClass('connected');
el.addClass('disconnected');
}
}
el.innerHTML = msg + '<div></div>';
}
source.addEventListener('message', function(event) {
var data = JSON.parse(event.data);
var d = new Date(data.msg * 1e3);
var timeStr = [d.getHours(), d.getMinutes(), d.getSeconds()].join(':');
coolclock.render(d.getHours(), d.getMinutes(), d.getSeconds());
logger.log('lastEventID: ' + event.lastEventId +
', server time: ' + timeStr, 'msg');
}, false);
source.addEventListener('open', function(event) {
logger.log('> Connection was opened');
updateConnectionStatus('Connected', true);
}, false);
source.addEventListener('error', function(event) {
if (event.eventPhase == 2) { //EventSource.CLOSED
logger.log('> Connection was closed');
updateConnectionStatus('Disconnected', false);
}
}, false);
var coolclock = CoolClock.findAndCreateClocks();
</script>
</body>
</html>