lib/public/js/dash.js in batsd-dash-0.2.1 vs lib/public/js/dash.js in batsd-dash-0.3.0
- old
+ new
@@ -1,84 +1,105 @@
// Location Hash wrapper script
-var LocationHash=function(a){function c(){var a=location.hash.substr(1).split("&");b={};for(var c=0,d;d=a[c];c++){var e=d.split("="),f=e[1].split(",");b[e[0]]=f.length>1?f:f[0]}}function d(){var a=[];for(var c in b){var d=b[c];a.push(c+"="+(d.join?d.join(","):d))}location.hash=a.join("&")}var b;return a(window).on("hashchange",c).trigger("hashchange"),{params:function(){return a.param(b)},get:function(a){return b[a]},set:function(a){for(var c in a){var e=a[c];e==undefined?delete b[c]:b[c]=e}d()}}}(jQuery);
+// https://gist.github.com/2927857
+var LocationHash=function(e){function r(){var e=location.hash.substr(1).split("&");t={};for(var r=0,i;i=e[r];r++){var s=i.split("=");if(s.length){var o=s[1].split(",");t[s[0]]=o.length>1?o:o[0]}}for(var r=0,u;u=n[r];r++)u()}function i(e){var n=[];for(var r in t){var i=t[r],s="=";if(e=="h")n.push(r+s+(i.join?i.join(","):i));else{i.join?s="[]=":i=[i];for(var o=0,u;u=i[o];o++)n.push(r+s+u)}}return n.join("&")}var t,n=[];return e(window).on("hashchange",r),r(),{params:function(e){return i(e)},changed:function(e){n.push(e)},get:function(e){return t[e]},set:function(e){for(var n in e){var r=e[n];r==undefined?delete t[n]:t[n]=r}location.hash=i("h")}}}(d3.select);
-// set Accept header to JSON
-$.ajaxSetup({ beforeSend: function(req){ req.setRequestHeader('Accept', 'application/json'); } });
+// TODO find a d3 datetimepicker (or make one)
+// then drop jquery, jqueryui and datetimerpicker altogether
+(function(){
+ $('button').button();
-// Date.now polyfill (if needed)
-if (!Date.now) Date.now = function(){ return +new Date; };
+ var now = Date.now();
+ var defaults = [now - (1000 * 60 * 30), now];
-$(function(){
- var main = $('#main-graph');
- var graph_opts = {
- xaxis: {
- mode: 'time', timeformat: '%h:%M:%S',
- minTickSize: [10, 'second']
- },
+ $('.date-time').datetimepicker().each(function(i){
+ var input = $(this);
+ var time = LocationHash.get(input.attr('name'));
- yaxis: { min: 0, minTickSize: 1 },
- lines: { show: true }, points: { show: false },
+ input.datetimepicker('setDate', new Date(time ? time * 1000 : defaults[i]));
+ });
+}());
- grid: { borderColor:'#FFF', color:'#FFF' },
- legend: { backgroundColor:'#000' }
+
+// graphs using nv.d3
+(function(){
+ var loading = d3.select('#loading');
+ var main_el = d3.select('#main-graph');
+
+ if (main_el.empty())
+ return;
+
+ var validate = /counters|timers|gauges/;
+ var inputs = d3.selectAll('.date-time')[0];
+
+ var graph = main_el.select('svg');
+ var view = d3.select('button');
+
+ loading.toggle = function(){
+ this.style('display', this.style('display') == 'block' ? 'none' : 'block');
};
- function timestamp(str){
- return Math.round(+new Date(str) / 1000);
- }
+ function set_time_params(){
+ var map = {};
- function parse_error(xhr){
- var data;
+ for (var i = 0, elem; elem = inputs[i]; i++)
+ map[elem.name] = +new Date(elem.value) / 1000;
- try {
- data = xhr.status == 500 ? { error: 'zomg server fail :(' } : $.parseJSON(xhr.responseText);
- } catch(e) {
- data = { error: 'unknown error' };
- } finally {
- return data;
- }
+ LocationHash.set(map);
}
- function update_graph(graph){
- var req = { dataType: 'json', data: LocationHash.params() };
- var path = location.pathname;
+ function time_axis_formatter(resp){
+ var format = { 600: '%x', 60: '%X', 10: '%X' }[resp.interval];
- graph.html('<h2>Loading...</h2>');
- $.ajax(path, req).done(function(data){
- $.plot(graph, data.metrics, graph_opts);
+ return function(d){
+ return d3.time.format(format)(new Date(d));
+ };
+ }
- }).fail(function(xhr){
- var data = parse_error(xhr);
+ function render_graph(){
+ var xhr, params = LocationHash.params();
- graph.html('<h2>Error: '+ data.error +'</h2>');
- });
- }
-
+ if (!validate.test(params) && location.pathname != '/')
+ return alert('Need to supply at least one counter, timer or gauge');
- // initialize the graph itself
- $('.graph').each(function(){ update_graph($(this)); });
+ main_el.select('em').remove();
+ loading.toggle();
- // initialize date time picker
- var inputs = $('input.date-time').datetimepicker();
+ d3.json('/data?'+ params, function(resp){
+ loading.toggle();
- var start = LocationHash.get('start');
- var stop = LocationHash.get('stop');
+ if (!resp)
+ return main_el.append('em').text('An Error Occurred!');
- inputs.first().datetimepicker('setDate', start ? new Date(start * 1000) : new Date(Date.now() - (1000*60*60*2)));
- inputs.last().datetimepicker('setDate', stop ? new Date(stop * 1000) : new Date());
+ nv.addGraph(function(){
+ // initialize a new chart object
+ var chart = nv.models.lineChart()
+ .x(function(d){ return d[0]; })
+ .y(function(d){ return d[1]; })
- // style View button and bind handler
- $('button').button().on('click', function(){
- // set location hash with new values
- LocationHash.set({
- start: timestamp(inputs.first().val()),
- stop: timestamp(inputs.last().val()),
+ // set xAxis tick format based up range and interval
+ chart.xAxis.tickFormat(time_axis_formatter(resp))
+
+ // force 0 into yAxis domain
+ chart.forceY([0]);
+
+ // bind data and render graph
+ graph.datum(resp.results)
+ .transition().duration(500)
+ .call(chart);
+
+ return chart;
+ });
});
+ }
- update_graph(main);
+ // view button handler
+ view.on('click', function(){
+ set_time_params();
+ render_graph();
});
- $(window).on('hashchange', function(){
- update_graph(main);
- });
-});
+ // listen for changes to URL
+ LocationHash.changed(render_graph);
+ // initial graph render
+ render_graph();
+}());