Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master'
Browse files Browse the repository at this point in the history
Conflicts:
	test/yasa_rra_file_tests.erl
  • Loading branch information
rramsden committed Jul 8, 2012
2 parents 0a843cb + f94d1a9 commit 6f6b267
Show file tree
Hide file tree
Showing 11 changed files with 457 additions and 11 deletions.
247 changes: 247 additions & 0 deletions priv/www/assets/bullet.js
@@ -0,0 +1,247 @@
/*
Copyright (c) 2011-2012, Loïc Hoguin <essen@ninenines.eu>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

/**
Bullet is a client-side javascript library AND server-side Cowboy handler
to manage continuous streaming. It selects the proper transport in a fully
automated way and makes sure to always reconnect to the server on any
disconnect. You only need to handle sending messages, receiving them,
and managing the heartbeat of the stream.
Usage: $.bullet(url);
Then you can register one of the 4 event handlers:
onopen, onmessage, onclose, onheartbeat.
onopen is called once right after starting the bullet stream.
onmessage is called once for each message receveid.
onclose is called once right after you voluntarily close the socket.
onheartbeat is called once every few seconds to allow you to easily setup
a ping/pong mechanism.
*/
(function($){$.extend({bullet: function(url){
var CONNECTING = 0;
var OPEN = 1;
var CLOSING = 2;
var CLOSED = 3;

var transports = {
/**
The websocket transport is disabled for Firefox 6.0 because it
causes a crash to happen when the connection is closed.
@see https://bugzilla.mozilla.org/show_bug.cgi?id=662554
*/
websocket: function(){
var ret = false;

if (window.WebSocket){
ret = window.WebSocket;
}

if (window.MozWebSocket
&& navigator.userAgent.indexOf("Firefox/6.0") == -1){
ret = window.MozWebSocket;
}

if (ret){
return {'heart': true, 'transport': ret};
}

return false;
},

xhrPolling: function(){
var timeout;
var xhr;

var fake = {
readyState: CONNECTING,
send: function(data){
if (this.readyState != CONNECTING && this.readyState != OPEN){
return false;
}

var fakeurl = url.replace('ws:', 'http:').replace('wss:', 'https:');

$.ajax({
async: false,
cache: false,
type: 'POST',
url: fakeurl,
data: data,
dataType: 'text',
contentType:
'application/x-www-form-urlencoded; charset=utf-8',
headers: {'X-Socket-Transport': 'xhrPolling'},
success: function(data){
if (data.length != 0){
fake.onmessage({'data': data});
}
}
});

return true;
},
close: function(){
this.readyState = CLOSED;
xhr.abort();
clearTimeout(timeout);
fake.onclose();
},
onopen: function(){},
onmessage: function(){},
onerror: function(){},
onclose: function(){}
};

function poll(){
var fakeurl = url.replace('ws:', 'http:').replace('wss:', 'https:');

xhr = $.ajax({
type: 'GET',
cache: false,
url: fakeurl,
dataType: 'text',
data: {},
headers: {'X-Socket-Transport': 'xhrPolling'},
success: function(data){
if (fake.readyState == CONNECTING){
fake.readyState = OPEN;
fake.onopen(fake);
}
// Connection might have closed without a response body
if (data.length != 0){
fake.onmessage({'data': data});
}
if (fake.readyState == OPEN){
nextPoll();
}
},
error: function(xhr){
fake.onerror();
}
});
}

function nextPoll(){
timeout = setTimeout(function(){poll();}, 100);
}

nextPoll();

return {'heart': false, 'transport': function(){ return fake; }};
}
};

var tn = 0;
function next(){
var c = 0;

for (var f in transports){
if (tn == c){
var t = transports[f]();
if (t){
var ret = new t.transport(url);
ret.heart = t.heart;
return ret;
}

tn++;
}

c++;
}

return false;
}

var stream = new function(){
var readyState = CLOSED;
var heartbeat;
var delay = delayDefault = 80;

var transport = next();
function init(){
readyState = CONNECTING;

if (!transport){
// No transport, give up
// @todo Trigger a disconnect error
return false;
}

transport.onopen = function(){
// We got a connection, reset the poll delay
delay = delayDefault;

if (transport.heart){
heartbeat = setInterval(function(){stream.onheartbeat();}, 20000);
}

if (readyState != OPEN){
readyState = OPEN;
stream.onopen();
}
};
transport.onclose = function(){
clearInterval(heartbeat);

if (readyState == CLOSING){
readyState = CLOSED;
stream.onclose();
} else{
// Close happened on connect, select next transport
if (readyState == CONNECTING){
tn++;
}

delay *= 2;
if (delay > 10000){
delay = 10000;
}

setTimeout(function(){
transport = next();
init();
}, delay);
}
};
transport.onerror = transport.onclose;
transport.onmessage = function(e){
stream.onmessage(e);
};
}
init();

this.onopen = function(){};
this.onmessage = function(){};
this.onclose = function(){};
this.onheartbeat = function(){};

this.setURL = function(newURL){
url = newURL;
};
this.send = function(data){
return transport.send(data);
};
this.close = function(){
readyState = CLOSING;
transport.close();
};
};

return stream;
}})})(jQuery);
7 changes: 3 additions & 4 deletions priv/www/assets/dashboard.jquery.js
Expand Up @@ -10,14 +10,13 @@
});

$.getJSON("/api/keys", function(data) {
$('#keys').jqxTree({ source: data, height: '600px', width: '300px' })
//$("#keys").append("<li data-name='"+key+"'><a href='#'>" + key + "</a></li>");
console.log(data);
$('#tree').jqxTree({ source: data, height: '600px', width: '300px' })
});

$('#keys .keyname').click(function() {
$('#tree .keyname').click(function() {
$('#timeframe').show();
$.dashboard.graph( $(this).data('name') );
return false;
});
},

Expand Down
66 changes: 66 additions & 0 deletions priv/www/assets/dashboardws.jquery.js
@@ -0,0 +1,66 @@
(function($) {
var bullet = $.bullet('ws://localhost:8080/wsapi');
bullet.onopen = function(){
console.log('WebSocket: opened');
};
bullet.onclose = function(){
console.log('WebSocket: closed');
};
bullet.onmessage = function(e){
if(e.data !== 'pong'){
//alert(e.data);
}
};
bullet.onheartbeat = function(){
bullet.send('ping');
};
$.dashboard = {

init : function() {
$.ajaxSetup({
async: false
});

$.getJSON("/api/keys", function(data) {
$('#keys').jqxTree({ source: data, height: '600px', width: '300px' })
//$("#keys").append("<li data-name='"+key+"'><a href='#'>" + key + "</a></li>");
});

$('#keys .keyname').click(function() {
if($(this).data('clicked') === true){
bullet.send(JSON.stringify({type: 'unregister', key: $(this).data('name')}));
$(this).data('clicked', false);
} else {
bullet.send(JSON.stringify({type: 'register', key: $(this).data('name'), range: '-5min'}))
//$.dashboard.graph( $(this).data('name'));
$(this).data('clicked', true);
}
return false;
});
},

graph : function(key) {
var options = {
chart: {
renderTo: 'graph',
type: 'area'
},
title: {
text: key
},
xAxis: {
type: 'datetime'
}
};


$.getJSON("/api/get?range=-5min&key="+key, function(data) {
data = $.map(data, function(arr) { return [[arr[0] * 1000, arr[1]]] });
console.log(data);

options.series = [{name: key, data: data}];
new Highcharts.Chart(options);
});
}
}
})(jQuery);
4 changes: 1 addition & 3 deletions priv/www/dashboard.html
Expand Up @@ -27,9 +27,7 @@
<div class="container">
<div class="row">
<div class="span4">
<div class="well" id="keys">

</div>
<div id="tree"></div>
</div>
<div class="span8">
<ul id="timeframe" style="display: none" class="nav nav-pills">
Expand Down
51 changes: 51 additions & 0 deletions priv/www/dashboardws.html
@@ -0,0 +1,51 @@
<!DOCTYPE html>
<html>
<head>
<title>YASA Dashboard</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="/assets/bullet.js"></script>
<script src="/assets/dashboardws.jquery.js"></script>
<script src="/assets/jqwidgets/jqxcore.js"></script>
<script src="/assets/jqwidgets/jqxbuttons.js"></script>
<script src="/assets/jqwidgets/jqxscrollbar.js"></script>
<script src="/assets/jqwidgets/jqxpanel.js"></script>
<script src="/assets/jqwidgets/jqxtree.js"></script>
<script src="http://current.bootstrapcdn.com/bootstrap-v204/js/bootstrap.min.js"></script>
<link href="http://current.bootstrapcdn.com/bootstrap-v204/css/bootstrap-combined.min.css" rel="stylesheet">
<link rel="stylesheet" href="/assets/jqwidgets/jqx.base.css" type="text/css" />
</head>
<body onload="$.dashboard.init()" style="padding-top: 80px;">

<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="brand" href="#">YASA Dashboard</a>
</div>
</div>
</div>

<div class="container">
<div class="row">
<div class="span4">
<div class="well" id="keys">

</div>
</div>
<div class="span8">
<ul class="nav nav-pills">
<li><a href="#">One Week</a></li>
<li><a href="#">One Day</a></li>
<li><a href="#">Last Hour</a></li>
<li><a href="#">Last 10 Minutes</a></li>
<li class="active"><a href="#">Last Minute</a></li>
</ul>

<div id="graph" style="width: 100%; height: 400px; margin: 0 auto"></div>
</div>
</div>
</div>
</body>
</html>


0 comments on commit 6f6b267

Please sign in to comment.