|
|
|
var nv = {version: "0.0.1"};
|
|
|
|
|
|
|
|
window.nv = nv;
|
|
|
|
|
|
|
|
nv.models = {}; //stores all the possible models/components
|
|
|
|
nv.charts = {}; //stores all the ready to use charts
|
|
|
|
nv.graphs = []; //stores all the graphs currently on the page
|
|
|
|
nv.log = {}; //stores some statistics and potential error messages
|
|
|
|
|
|
|
|
nv.dispatch = d3.dispatch("render_start", "render_end");
|
|
|
|
|
|
|
|
|
|
|
|
// ********************************************
|
|
|
|
// Public Helper functions, not part of NV
|
|
|
|
|
|
|
|
window.log = function(obj) {
|
|
|
|
if ((typeof(window.console) === "object")
|
|
|
|
&& (typeof(window.console.log) === "function"))
|
|
|
|
console.log.apply(console, arguments);
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ********************************************
|
|
|
|
// Public Core NV functions
|
|
|
|
|
|
|
|
nv.dispatch.on("render_start", function(e) {
|
|
|
|
nv.log.startTime = +new Date;
|
|
|
|
//log('start', nv.log.startTime);
|
|
|
|
});
|
|
|
|
|
|
|
|
nv.dispatch.on("render_end", function(e) {
|
|
|
|
nv.log.endTime = +new Date;
|
|
|
|
nv.log.totalTime = nv.log.endTime - nv.log.startTime;
|
|
|
|
//log('end', nv.log.endTime);
|
|
|
|
log('total', nv.log.totalTime); //used for development, to keep track of graph generation times
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// ********************************************
|
|
|
|
// Public Core NV functions
|
|
|
|
|
|
|
|
nv.render = function render(stepSize) {
|
|
|
|
var step = stepSize || 1; // number of graphs to generate in each timout loop
|
|
|
|
|
|
|
|
render.active = true;
|
|
|
|
nv.dispatch.render_start();
|
|
|
|
|
|
|
|
setTimeout(function(){
|
|
|
|
var chart;
|
|
|
|
|
|
|
|
for (var i = 0; i < step && (graph = render.queue[i]); i++) {
|
|
|
|
chart = graph.generate();
|
|
|
|
if (typeof graph.callback === 'function') graph.callback(chart);
|
|
|
|
nv.graphs.push(chart);
|
|
|
|
}
|
|
|
|
|
|
|
|
render.queue.splice(0, i);
|
|
|
|
|
|
|
|
if (render.queue.length > 0) setTimeout(arguments.callee, 0);
|
|
|
|
else {
|
|
|
|
nv.render.active = false;
|
|
|
|
nv.dispatch.render_end();
|
|
|
|
}
|
|
|
|
}, 0);
|
|
|
|
};
|
|
|
|
nv.render.queue = [];
|
|
|
|
|
|
|
|
|
|
|
|
nv.addGraph = function(obj) {
|
|
|
|
if (typeof arguments[0] === "function")
|
|
|
|
obj = {generate: arguments[0], callback: arguments[1]};
|
|
|
|
|
|
|
|
nv.render.queue.push(obj);
|
|
|
|
|
|
|
|
if (!nv.render.active) nv.render();
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
nv.strip = function(s) {
|
|
|
|
return s.replace(/(\s|&)/g,'');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* An ugly implementation to get month end axis dates
|
|
|
|
* Will hopefully refactor sooner than later
|
|
|
|
*/
|
|
|
|
|
|
|
|
function daysInMonth(month,year) {
|
|
|
|
var m = [31,28,31,30,31,30,31,31,30,31,30,31];
|
|
|
|
if (month != 2) return m[month - 1];
|
|
|
|
if (year%4 != 0) return m[1];
|
|
|
|
if (year%100 == 0 && year%400 != 0) return m[1];
|
|
|
|
return m[1] + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function d3_time_range(floor, step, number) {
|
|
|
|
return function(t0, t1, dt) {
|
|
|
|
var time = floor(t0), times = [];
|
|
|
|
if (time < t0) step(time);
|
|
|
|
if (dt > 1) {
|
|
|
|
while (time < t1) {
|
|
|
|
var date = new Date(+time);
|
|
|
|
if (!(number(date) % dt)) times.push(date);
|
|
|
|
step(time);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
while (time < t1) times.push(new Date(+time)), step(time);
|
|
|
|
}
|
|
|
|
return times;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
d3.time.monthEnd = function(date) {
|
|
|
|
return new Date(date.getFullYear(), date.getMonth(), 0);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
d3.time.monthEnds = d3_time_range(d3.time.monthEnd, function(date) {
|
|
|
|
date.setUTCDate(date.getUTCDate() + 1);
|
|
|
|
date.setDate(daysInMonth(date.getMonth() + 1, date.getFullYear()));
|
|
|
|
}, function(date) {
|
|
|
|
return date.getMonth();
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|