UNPKG

doevisualization

Version:

Data Visualization Library based on RequireJS and D3.js (v4+)

359 lines (304 loc) 14.7 kB
define(['jquery', 'underscore', 'jqueryuiwidget', 'handlebars', 'd3' ], function($, _, ui, Handlebars, d3) { $.widget("doe.doefootballfield", { // Options to be used as defaults options: {}, _privateData: {}, _template: function() { var arrHTML = []; arrHTML.push('<div class="doedivergedbar">'); arrHTML.push('<div class="title">'); arrHTML.push('</div>'); arrHTML.push('<div class="subTitle">'); arrHTML.push('</div>'); arrHTML.push('</div>'); return arrHTML.join(''); }, _create: function() { this._fetchAndRender(); }, _fetchAndRender: function() { this._compileTemplate(); }, _compileTemplate: function() { var compiled = Handlebars.compile(this._template()); this.element.html(compiled({})); this._compileTooltip(); this._buildVisualization(); this._bindEvents(); }, _compileTooltip: function() { this._privateData.tooltipCompiled = Handlebars.compile(this.options.TooltipTemplate); }, _bindEvents: function() { }, _buildVisualization: function() { this.element.find('div.title').html(this.options.ChartTitle); this.element.find('div.subTitle').html(this.options.ChartSubTitle); console.log("raw data:", this.options.Data); var groupeddata = _.groupBy(this.options.Data, $.proxy(function(item) { return item[this.options["Groupings"][0]]; }, this)); console.log("grouped data:", groupeddata); var groupField = this.options["Groupings"]; var tooltipData = _.chain(this.options.Data) .groupBy(function(d) { return d[groupField] }) .pairs() .map(function(currentItem) { return _.object(_.zip(["groupItem", "values"], currentItem)); }) .value(); console.log("tooltip data:", tooltipData); for (var k in groupeddata) { var uniquescope = _.uniq(groupeddata[k], $.proxy(function(x) { return x[this.options["YFields"][0]]; }, this)); uniquescope = uniquescope.map($.proxy(function(item, index) { return item[this.options["YFields"][0]]; }, this)); var uniquelabel = _.uniq(groupeddata[k], $.proxy(function(x) { return x[this.options["XFields"][1]]; }, this)); uniquelabel = uniquelabel.map($.proxy(function(item, index) { return item[this.options["XFields"][1]]; }, this)); console.log(uniquescope); var finalobject = []; var scopeMeetsReqs = []; _.each(uniquescope, $.proxy(function(item) { var filtereddata = _.filter(groupeddata[k], $.proxy(function(sitem) { return sitem[this.options["YFields"][0]] === item; }, this)); var obj = {}; obj["rows"] = item; var temp = []; _.each(filtereddata, $.proxy(function(tem) { obj[tem[this.options["XFields"][1]]] = tem[this.options["XFields"][0]]; // obj["origdata"] = tem; temp.push(tem); }, this)); // if (obj[tem[this.options["XFields"][1]]] == tem[this.options["XFields"][0]]) { // obj["origdata"] = tem; // } obj["origdata"] = temp; finalobject.push(obj); }, this)); console.log(finalobject); console.log(uniquelabel); this._privateData.finalobject = finalobject; this._privateData.uniquelabel = uniquelabel; this._privateData.uniquescope = uniquescope; this._setupD3Element(k); } }, _setupD3Element: function(year) { var margin = { top: 80, right: 20, bottom: 20, left: 50 }, width = 590 - margin.left - margin.right, height = 230 - margin.top - margin.bottom; var y = d3.scaleBand() .rangeRound([0, height]) .padding(0.3); var x = d3.scaleLinear() .rangeRound([0, width]); // var xAxis = d3.svg.axis() // .scale(x) // .tickFormat(d3.format(",%")) // .orient("top"); var xAxis = d3.axisBottom(x).tickFormat(function(d) { if (d === 0) return ''; // No label for '0' else if (d < 0) d = -d; // No nagative labels return d * 100 + '%'; }); // var yAxis = d3.svg.axis() // .scale(y) // .tickSize(0) // .orient("left"); var yAxis = d3.axisLeft(y).tickSize(0); var color = d3.scaleOrdinal() .range(this.options.ColorPalette); var svg = d3.select(this.element.find('div.doedivergedbar').get(0)).append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); var tooltipcontainer = d3.select(this.element.find('div.doedivergedbar').get(0)).append("div") .attr("class", "doedivergedbartooltip") .style("opacity", 0); this._drawDivergedChart(this._privateData.finalobject, this._privateData.uniquelabel, this._privateData.uniquescope, year, svg, x, y, color, xAxis, yAxis, height, width, tooltipcontainer); }, _drawDivergedChart: function(data, uniquelabel, uniquescope, year, svg, x, y, color, xAxis, yAxis, height, width, tooltipcontainer) { svg.append("text") .attr("x", 0) .attr("y", 0) .text(year) .attr("class", "instancetitle") var rateNames = d3.keys(data[0]).filter(function(key) { return (key !== "rows" && key !== "origdata"); }); var rowsNames = data.map(function(d) { return d.rows; }); var neutralIndex = Math.floor(rateNames.length / 2); color.domain(rateNames); data.forEach(function(row) { row.total = d3.sum(rateNames.map(function(name) { return +row[name]; })); rateNames.forEach(function(name) { row['relative' + name] = (row.total !== 0 ? +row[name] / row.total : 0); }); var x0 = -1 * d3.sum(rateNames.map(function(name, i) { return i < neutralIndex ? +row['relative' + name] : 0; })); if (rateNames.length & 1) x0 += -1 * row['relative' + rateNames[neutralIndex]] / 2; var idx = 0; row.boxes = rateNames.map(function(name) { return { name: name, x0: x0, x1: x0 += row['relative' + name], total: row.total, absolute: row[name], origdata: row.origdata }; }); }); var min = d3.min(data, function(d) { return d.boxes["0"].x0; }); var max = d3.max(data, function(d) { return d.boxes[d.boxes.length - 1].x1; }); x.domain([-1, 1]).nice(); y.domain(rowsNames); svg.append("g") .attr("class", "xaxis") .attr("transform", "translate(0," + (height + 2) + ")") .call(xAxis); svg.append("g") .attr("class", "yaxis") .call(yAxis); var rows = svg.selectAll(".row") .data(data) .enter().append("g") .attr("class", "bar") .attr("transform", function(d) { return "translate(0," + y(d.rows) + ")"; }) .on("mouseover", function(d) { svg.selectAll('.y').selectAll('text').filter(function(text) { return text === d.rows; }) .transition().duration(5).style('font', '9px'); }) .on("mouseout", function(d) { svg.selectAll('.y').selectAll('text').filter(function(text) { return text === d.rows; }) .transition().duration(5).style('font', '9px'); }); var bars = rows.selectAll("rect") .data(function(d) { return d.boxes; }) .enter().append("g"); bars.append("rect") .attr("height", y.bandwidth()) .attr("x", function(d) { return x(d.x0); }) .attr("width", function(d) { return x(d.x1) - x(d.x0); }) .style("fill", function(d) { return color(d.name); }) .on("mouseover", $.proxy(function(d, i) { d3.select(this.element.find(".doedivergedbartooltip").get(0)).transition() .duration(200) .style("opacity", .9); d3.select(this.element.find(".doedivergedbartooltip").get(0)).html(this._privateData.tooltipCompiled(d.origdata[i])) .style("left", (d3.event.pageX) + "px") .style("top", (d3.event.pageY - 28) + "px"); }, this)) .on("mouseout", $.proxy(function(d, i) { d3.select(this.element.find(".doedivergedbartooltip").get(0)).transition() .duration(500) .style("opacity", 0); }, this)); // bars.append("text") // .attr("x", function (d) { // return x(d.x0); // }) // .attr("y", y.bandwidth() / 2) // .attr("dy", "0.5em") // .attr("dx", "0.5em") // .style("text-anchor", "begin") // .attr("class", "bartext") // .text(function (d) { // return d.absolute !== 0 && (d.x1 - d.x0) > 0.04 ? d.absolute : "" // }); bars.append("text") .attr("x", function(d) { return x(d.x0); }) .attr("y", y.bandwidth() / 2) .attr("dy", "0.5em") .attr("dx", "0.5em") .style("text-anchor", "begin") .attr("class", "bartext") .attr("width", "12px") .attr("height", "12px") .text(function(d) { return d.absolute !== 0 && (d.x1 - d.x0) > 0.04 ? d.absolute : "" }); svg.append("g") .attr("class", "y axis") .append("line") .attr("x1", x(0) + 1) .attr("x2", x(0) + 1) .attr("y2", height); var legend = svg.selectAll(".legend") .data(rateNames) .enter().append("g") .attr("class", "legend") .attr("transform", function(d, i) { return "translate(" + width / rateNames.length * i + ",-55)"; }); legend.append("rect") .attr("x", 0) .attr("width", 18) .attr("height", 18) .style("fill", color); legend.append("text") .attr("x", 22) .attr("y", 9) .attr("dy", ".12em") .attr("class", "legend") .style("text-anchor", "begin") .text(function(d) { return d; }); }, destroy: function() { }, _setOption: function(key, value) { this._super(key, value); }, _setOptions: function(options) { this._super(options); } }); });