default/home/static/chart.js (377 lines of code) (raw):
var order = {};
function downloadElement(id, link) {
    var svg = document.getElementById(id);
    var serializer = new XMLSerializer();
    var source = serializer.serializeToString(svg);
    if(!source.match(/^<svg[^>]+xmlns="http\:\/\/www\.w3\.org\/2000\/svg"/)){
        source = source.replace(/^<svg/, '<svg xmlns="http://www.w3.org/2000/svg"');
    }
    if(!source.match(/^<svg[^>]+"http\:\/\/www\.w3\.org\/1999\/xlink"/)){
        source = source.replace(/^<svg/, '<svg xmlns:xlink="http://www.w3.org/1999/xlink"');
    }
    //source = source.replace('^<svg', '<svg style="font-size:22px;font-family=Arial" ');
    source = '<?xml version="1.0" standalone="no"?>\r\n' + source;
    var file = new File([source], id + '.svg', {
        type: "text/svg",
        lastModified: new Date()
    });
    link.href = URL.createObjectURL(file);
    link.download = file.name;
}
function downloadPNG(id, link) {
    var canvas = document.getElementById('canvas');
    var ctx = canvas.getContext('2d');
    var data = (new XMLSerializer()).serializeToString(document.getElementById(id));
    var DOMURL = window.URL || window.webkitURL || window;
  
    var img = new Image();
    var svgBlob = new Blob([data], {type: 'image/svg+xml;charset=utf-8'});
    var url = DOMURL.createObjectURL(svgBlob);
  
    img.onload = function () {
      ctx.drawImage(img, 0, 0);
      DOMURL.revokeObjectURL(url);
  
      var imgURI = canvas
          .toDataURL('image/png')
          .replace('image/png', 'image/octet-stream');
  
          var file = new File([source], id + '.svg', {
            type: "text/svg",
            lastModified: new Date()
        });
        link.href = imgURI;
        link.download = file.name;
    };
    img.src = url;
}
function plotCharts(container, charts) {
    d3.select(document.getElementById(container))
        .selectAll('div')
        .data(charts)
        .enter()
        .append('div')
        .attr('class', 'vis bor wht rnd shd pad')
        .html(function (d) {
            d.div = this;
            if (d.type == 'pie') {
                pieChart(d);
            } else if (d.type == 'treemap') {
                treemapSVG(d);
            } else {
                barChart(d);
            }
            return '<a class="vgi-bar" href="/home/' + encodeURI(d.ID) + '#chart" class="center icn ' + encodeURI(d.key) + '">' + (d.title ? ' ' + d.title : '')
                + '</a>'
             +'<a class="fbn vgi-download" onclick="downloadElement(\''+encodeURI(d.ID)+'\',this)">download</a>'
             //+ '<a class="fbn vgi-pic" onclick="downloadPNG(\''+encodeURI(d.ID)+'\',this)">download PNG</a>';
        });
    //delete divs if data doesn't contain them.
    d3.select(document.getElementById(container))
        .selectAll('div')
        .data(charts).exit().remove()
}
function showError(a, error) {
    d3.select(a.div)
        .append("div")
        .attr("class", "tred mid gap2")
        .text("Error loading data. Check the chart parameters, or try refreshing the page." + error);
}
function pieChart(a) {
    var w = 710;
    var h = 500;
    var radius = 250;
    if ('color' in a && 'domain' in a.color && 'range' in a.color && a.color.domain.length > 0) {
        a.color = d3.scale.ordinal()
            .domain(a.color.domain)
            .range(a.color.range);
    } else {
        a.color = d3.scale.category20();
    }
    d3.json(a.href, function (error, data) {
        if (error) {
            showError(a, error);
            return;
        }
        var arc = d3.svg.arc()
            .outerRadius(radius - 10)
            .innerRadius(76);
        var pie = d3.layout.pie()
            //.sort(a.sortX)
            .value(function (d) { return d.t; });
        var svgPie = d3.select(a.div).append("svg")
            .attr("id", a.ID)
            // .attr("width", "100%")
            //    .attr("height", "90%")
            .attr("viewBox", "0 0 710 500")
            .attr("class", "chart")
            .append("g")
            .attr("transform", "translate(" + w / 2 + "," + h / 2 + ")");
        var total = 0;
        data.forEach(function (d) { total += d.t });
        svgPie.append("a")
            .attr("xlink:href", a.list)
            .append("text")
            .text(function (d) { return total })
            .attr("y", 0).attr("x", 0)
            .attr("class", "sum")
            .attr("text-anchor", "middle")
            .attr("alignment-baseline", "central");
        var g = svgPie.selectAll(".arc")
            .data(pie(data))
            .enter().append("g")
            .attr("class", "arc");
        g.append("svg:title")
            .text(function (d) { return (d.data._id ? d.data._id : 'null') + ' = ' + d.data.t });
        g.append("a")
            .attr("xlink:href", function (d) {
                return a.list + "&" + a.key + "=" + (d.data._id ? d.data._id : 'null');
            })
            .append("path")
            .attr("d", arc)
            .attr("class", function (d) { return 'icn ' + d.data._id; })
            .style("fill", function (d) { return a.color(d.data._id); });
        g.filter(function (d) { return d.endAngle - d.startAngle > .2; })
            .append("a")
            .attr("xlink:href", function (d) {
                return a.list + "&" + a.key + "=" + (d.data._id ? d.data._id : 'null');
            })
            .append("text")
            .attr("transform", function (d) {
                arc.innerRadius(radius / 2) // Set Outer Coordinate
                return "translate(" + arc.centroid(d) + ")";
            })
            .attr("class", function (d) { return 'icn ' + d.data._id; })
            .attr("dy", "1em")
            .style("text-anchor", "middle")
            .text(function (d) {
                return d.data.t + ' ' + d.data._id;
            })
    });
};
function barChart(a) {
    'marginLeft' in a ? '' : a.marginLeft = 40;
    'marginRight' in a ? '' : a.marginRight = 20;
    'marginTop' in a ? '' : a.marginTop = 20;
    'marginBottom' in a ? '' : a.marginBottom = 20;
    width = 710 - a.marginLeft - a.marginRight,
        height = 500 - a.marginTop - a.marginBottom;
    if (!('x' in a)) {
        a.x = d3.scale.ordinal()
            .rangeRoundBands([0, width], .1);
    }
    if (!('y' in a)) {
        a.y = d3.scale.linear()
            .rangeRound([height, 0]);
    }
    if ('color' in a && 'domain' in a.color && 'range' in a.color && a.color.domain.length > 0) {
        a.color = d3.scale.ordinal()
            .domain(a.color.domain)
            .range(a.color.range);
    } else {
        a.color = d3.scale.category20();
    }
    if (!('xAxis' in a)) {
        a.xAxis = d3.svg.axis()
            .scale(a.x)
            .orient("bottom");
    }
    if (!('yAxis' in a)) {
        a.yAxis = d3.svg.axis()
            .scale(a.y)
            .orient("left")
            .tickFormat(d3.format(".2s"));
    }
    d3.json(a.href, function (error, data) {
        if (error) {
            showError(a, error);
            return;
        }
        svg = d3.select(a.div).append("svg")
            .attr("id", a.ID)
            //.attr("height", "90%")
            .attr("viewBox", "0 0 710 500")
            //.attr("preserveAspectRatio","xMidYMid meet")
            .attr("class", "chart")
            .append("g")
            .attr("transform", "translate(" + a.marginLeft + "," + a.marginTop + ")");
        var total = 0;
        data.forEach(function (d) {
            var c = d.t;
            total += c;
            var keys = [a.key];
            if (d.items) {
                keys = Object.keys(d.items);
                delete keys.t;
                var y = 0;
                var skey = Object.keys(d.items[0])[0];
                d.items.sort(function (a, b) { return a[skey] > b[skey] });
                for (item of d.items) {
                    item.y = y;
                    y = y + item.t;
                }
            }
        });
        a.x.domain(data.map(function (d) {
            return d._id;
        }));
        a.y.domain([0, d3.max(data, function (d) {
            return d.t;
        })]);
        svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height + ")")
            .call(a.xAxis);
        svg.append("g")
            .attr("class", "y axis")
            .call(a.yAxis);
        svg.append("g")
            .attr("class", "grid")
            .call(a.yAxis
                .tickSize(-width, 0, 0)
                .tickFormat(""));
        svg.append("a").attr("xlink:href", a.list).append("text").text(function (d) { return total }).attr("y", 50).attr("x", 30).attr("class", "sum");
        /* total counts above bar charts */
        svg.selectAll("total")
            .data(data)
            .enter().append("a")
            .attr("target", "_blank")
            .attr("xlink:href", (d) => a.list + '&' + a.key[0] + '=' + (d._id ? d._id : 'null')).append("text")
            .text(function (d) {
                return d.t;
            })
            .attr("y", function (d) {
                return (a.y(d.t) - 2)
            })
            .attr("x", function (d) {
                return a.x(d._id);
            })
            .attr("class", "total")
            ;
        /* x axis bars */
        var bars = svg.selectAll(".state")
            .data(data)
            .enter().append("g")
            .attr("class", "g")
            .attr("transform", function (d) {
                return "translate(" + a.x(d._id) + ",0)";
            });
        var ykey;
        if (data[0] && data[0].items && data[0].items[0] && Object.keys(data[0].items[0])[0]) {
            ykey = Object.keys(data[0].items[0])[0];
        }
        /* stacked bar charts */
        bars.selectAll("rect")
            .data(function (d) {
                if (Array.isArray(d.items)) {
                    var mm = d.items.map(function (x) { x._id = d._id; return x });
                    return mm;
                } else {
                    d.y = 0;
                    return [d];
                }
            })
            .enter().append("a")
            .attr("target", "_blank")
            .attr("xlink:href", function (i) {
                return a.list + "&" + a.key[0] + "=" + (i._id ? i._id : 'null') + (ykey ? "&" + ykey + '=' + i[ykey] : '')
            })
            .append("rect")
            .attr("width", a.x.rangeBand())
            .attr("y", function (i) {
                return a.y(i.y + i.t);
                //a.y(i.y);
            })
            .attr("height", function (i) {
                return a.y(i.y) - a.y(i.y + i.t);
            })
            //.attr("class", function(d) { return d.name;})
            .style("fill", function (i) { return a.color(i[ykey]); })
            .append("svg:title")
            .text(function (i) { return i[ykey] + ' = ' + i.t });
        /* bar label */
        bars.selectAll("text").data(function (d) {
            if (Array.isArray(d.items)) {
                var mm = d.items.map(function (x) { x._id = d._id; return x });
                return mm;
            } else {
                d.y = 0;
                return [d];
            }
        }).enter().append("a")
            .attr("target", "_blank")
            .attr("xlink:href", function (i) {
                return a.list + "&" + a.key[0] + "=" + (i._id ? i._id : 'null') + (ykey ? "&" + ykey + '=' + i[ykey] : '')
            })
            .append("text").text(function (i) {
                if (a.y(i.y) - a.y(i.y + i.t) > 10) {
                    return i.t + ' ' + (ykey ? i[ykey] : '');
                }
                return '';
            })
            .attr("y", function (i) {
                return a.y(i.y) - 2;
                //a.y(i.y)+a.y(i.t)+10;
            })
            .attr("x", 2);
    });
};
function treemapSVG(a) {
    var margin = { top: 0, right: 0, bottom: 0, left: 0 },
        width = 800,
        height = 600 - margin.top - margin.bottom;
    var x = d3.scale.linear()
        .domain([0, width])
        .range([0, width]);
    var y = d3.scale.linear()
        .domain([0, height])
        .range([0, height]);
    var color = d3.scale.category20c();
    var treemap = d3.layout.treemap()
        .mode("squarify")
        .size([width, height])
        .padding([1, 1, 1, 1])
        .value(function (d) { return d.t; });
    treemap.children(function (d, depth) {
        return d.items
    })
    d3.json(a.href, function (error, root) {
        if (error) {
            showError(a, error);
            return;
        }
        input = { "_id": "root", items: root };
        console.log('Input');
        console.log(input);
        console.log('Processed');
        process = treemap.nodes(input);
        process.shift();
        console.log(process);
        //  console.log(treemap.nodes(input));
        var svg = d3.select(a.div)
            .append("svg")
            .attr("id", a.ID)
            .attr("class", "chart")
            .attr("viewBox", "0 0 " + (width + margin.left + margin.right) + " " + (height + margin.bottom + margin.top))
        var div = svg
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
            .style("shape-rendering", "crispEdges");
        var b = div.selectAll("g")
            .data(process)
            .enter().append("g")
            .attr("transform", function (d) { return "translate(" + x(d.x) + "," + y(d.y) + ")" })
        b.append("rect")
            .attr("width", function (d) { return x(d.x + d.dx) - x(d.x); })
            .attr("height", function (d) { return y(d.y + d.dy) - y(d.y); })
            .attr("fill", function (d) { return color(d._id ? d._id : d.ack); })
            .attr("fill-opacity", ".5")
            .append("title")
            .text(function (d) { return d._id + "\n" + d.t });
        var text = b.append("text")
            .attr("x", function (d) { return x(d.dx / 2); })
            .attr("y", function (d) { return y(d.dy / 2); })
            .attr("text-anchor", "middle")
            .attr("dominant-baseline", "middle");
        text.append("tspan")
            .attr("class", "sml")
            .text(function (d) {
                if (d.dx > 10 && d.dy > 10) {
                    return d._id ? d._id : (d[a.key[d.depth - 1]])
                } else {
                    return "";
                }
            });
        text.append("tspan")
            .attr("x", function (d) { return x(d.dx / 2); })
            .attr("y", function (d) { return y(d.dy / 2) + 16; })
            .text(function (d) { return d.t });
    });
}