$.fn.enrichedChart = function(data, inSettings) { var plot = {}; var extraDefaults = { yLabels: '', yTickFormat: '', minY: 0, dimension: {w: 850, h: 300}, padding: {t: 20, r: 20, b: 85, l: 50}, bgColor: '', barWidth: 11, xLabelsHide: false, extendedTooltip: false }; var settings = addDefaultPlotSettings(inSettings, extraDefaults); plot.settings = settings; // Inner dimension var width = plot.width = settings.dimension.w - settings.padding.l - settings.padding.r; // inner width var height = plot.height = settings.dimension.h - settings.padding.t - settings.padding.b; // inner height var xScale = plot.x = d3.scaleBand() .range([0, width]) .domain(data.map(function(d) { return d.label; })); var xAxis = d3.axisBottom(xScale) .tickSizeOuter(0); if (settings.xLabelsHide) { xAxis .tickFormat('') .tickSize(0); } var yScale; var yMin, yMax, yAxis; if (settings.yLabels) { yMin = plot.yMin = 0; yMax = plot.yMax = d3.max(d3.keys(settings.yLabels)); yScale = plot.y = d3.scaleLinear() .range([height, 0]) .domain([yMin, yMax]); yAxis = d3.axisLeft(yScale) .tickFormat(function(d) { return settings.yLabels[d]; }) .tickValues(d3.keys(settings.yLabels)); } else { yMin = plot.yMin = 0.3; yMax = plot.yMax = Math.max(d3.max(data, function(d) { return parseFloat(d.value); }), settings.minY); yScale = plot.y = d3.scaleLinear() .range([height, 0]) .domain([yMin, yMax]) .nice(5); yAxis = d3.axisLeft(yScale) .ticks(5); if (settings.yTickSize != undefined) { yAxis.tickSize(settings.yTickSize); } if (settings.yTickFormat) { yAxis.tickFormat(d3.format(settings.yTickFormat)); } } var vis = plot.vis = d3.select($(this).get(0)) .append("svg") .attr("class", "barchart") .attr("width", width + settings.padding.l + settings.padding.r) .attr("height", height + settings.padding.t + settings.padding.b) .append("g") .attr("transform", "translate(" + settings.padding.l + "," + settings.padding.t + ")") .attr("width", width) .attr("height", height); $(this).on('click', '[url]', function() { document.location.href = $(this).attr('url'); }); if (settings.bgColor) { vis.append("rect") .attr("class", "chart_field") .attr("width", width) .attr("height", height+4) .attr("transform", "translate(0,-4)") .style("fill", settings.bgColor); } var bar_g = vis.selectAll(".bar_g") .data(data) .enter() .append("g") .attr("class", function(d) { return d.class? "bar_g "+d.class : "bar_g"; }) .attr("transform", function(d) { return 'translate('+xScale(d.label)+', 0)'; }) .attr("title", function(d) { return d.tooltip; }); var link = bar_g.append("a") .each(function(d) { if (d.url) d3.select(this).attr("xlink:href", d.url); }); if (settings.extendedTooltip) { var bar_transp = link.append("rect") .attr("class","bartrans") .attr("y", 0) .attr("x", function(d) { return xScale.bandwidth()/2 - settings.barWidth/2 ; }) .attr("width", settings.barWidth) .attr("height", height) .style("fill", "transparent"); } var bar_line = link.append("line") .attr("class","bar") .style("stroke", "grey") .style("stroke-width", 0.5) .attr("y1", function(d) { return (d.na == 1 || d.value<0.3)?0:yScale(d.value); }) .attr("x1", function(d) { return xScale.bandwidth()/2 ; }) .attr("y2", function(d) { return (d.na == 1 || d.value<0.3)?0:yScale(0.3); }) .attr("x2", function(d) { return xScale.bandwidth()/2 ; }) var bar_circle = link.append("circle") .attr("class", "bar") //.attr("transform", "translate(0,0)") .attr("cy", function(d) { return (d.na == 1)?0:yScale(d.value); }) .attr("cx", function(d) { return xScale.bandwidth()/2 ; }) .attr("r", function(d) { return (d.na == 1 || d.value<0.3)?0:d.radius}) //.style("stoke","1px solid black") .style("stroke", d => d.radius>4 ? "black" : "transparent") //.attr("width", settings.barWidth) //.attr("height", function(d) { return (d.na == 1)?height:(height-yScale(d.value));}) .style("fill", function(d){ if (d.na==1) { return "#FAFAFA"; } else if (typeof d.color_group!='undefined') { return colorbrewer[d.color_group[0]][d.color_group[1]][d.color_group[2]]; } else { return d.color; } }); var bar_text = bar_g.filter(function(d){ return d.na == 1; }) .append("text") .attr("class", "na_text") .style("text-anchor", "middle") .attr("transform", "rotate(-90)") .attr("y", settings.barWidth/2+6) .attr("x", -height/2) .text("N/A"); if (settings.valueLabels) { link.append("text") .attr("class", "valueLabel") .style("text-anchor", "middle") .attr("x", function(d, i) { return xScale.bandwidth()/2; }) .attr("y", function(d) { return (d.na == 1)?0:yScale(d.value)-2; }) .text(function(d) { return (d.na == 1)?'':d.value; }); } vis.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .selectAll(".tick text") .attr("class", "barchartlabel") .attr("y", 0) .attr("x", -9) .attr("transform", "rotate(-55)") .style("text-anchor", "end") .each(function(d, i) { if (data[i].tooltip) { d3.select(this).attr('title', data[i].tooltip); } if (data[i].url) { d3.select(this).attr('url', data[i].url).style('cursor', 'pointer'); } }); $(this).on('click', '[url]', function() { document.location.href = $(this).attr('url'); }); // x axis label vis.selectAll(".x.axis") .append("text") .attr("y", 20) .attr("x", width/2) .text(settings.xAxisLabel); // y axis label vis.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("y", -8) .style("text-anchor", "middle") .text(settings.yAxisLabel); vis.selectAll(".y .tick text") .call(wrap, settings.padding.l); // Legend if (settings.legend !== '') { var legend = vis.selectAll(".legend") .data(d3.map(data, function(d){return d.legend;}).values()) .enter().append("g") .attr("class", "legend") .attr("transform", function(d, i) { return "translate(0," + i * (settings.barWidth+2) + ")"; }); legend.append("rect") .attr("x", settings.legend.x) .attr("y", settings.legend.y) .attr("width", settings.barWidth) .attr("height", settings.barWidth) .style("fill", function(d, i) {return d.color; }); legend.append("text") .attr("x", settings.legend.x+settings.barWidth+2) .attr("y", settings.legend.y+settings.barWidth/2) .attr("dy", ".35em") .style("text-anchor", settings.legend.txtAnchor) .text(function(d) { return d.legend; }); } $(this).on('sort', function(e, order) { var x0 = xScale.domain( data.sort( order==='pos'? function(a, b) { return a.pos - b.pos; } :order==='value'? function(a, b) { return a.na? 1000 : b.na? -1000 : b.value - a.value; } :order==='real_value'? function(a, b) { return a.na? 1000 : b.na? -1000 : b.real_value - a.real_value; } :order==='label'? function(a, b) { return a.label.localeCompare(b.label); } :order==='origin'? function(a, b) { return a.origin.localeCompare(b.origin); } :order==='category'? function(a, b) { return a.category.localeCompare(b.category); } : function(a,b) { return 0; } ) .map(function(d) { return d.label; }) ) .copy(); vis.selectAll(".bar_g").sort(function(a, b) { return x0(a.value) - x0(b.value); }); vis.selectAll(".x.axis.tick").sort(function(a, b) { return x0(a.value) - x0(b.value); }); var transition = vis.transition().duration(100); transition.selectAll(".bar_g") .attr("transform", function(d) { return 'translate('+x0(d.label)+', 0)'; }); transition.select(".x.axis") .call(xAxis) .selectAll(".tick text") .style("text-anchor", "end") .attr("y", 0) .attr("x", -9); }); function wrap(text, width) { text.each(function() { var text = d3.select(this), words = text.text().split(/\s+/).reverse(), word, line = [], lineNumber = 0, lineHeight = 1.1, // ems y = text.attr("y"), x = text.attr("x"), dy = parseFloat(text.attr("dy")), tspan = text.text(null).append("tspan").attr("x", x).attr("y", y).attr("dy", dy + "em"); while (word = words.pop()) { line.push(word); tspan.text(line.join(" ")); if (tspan.node().getComputedTextLength() > width) { line.pop(); tspan.text(line.join(" ")); line = [word]; tspan = text.append("tspan").attr("x", x).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word); } } }); } return plot; }; $.fn.core_panel = function(data) { var margin = {top: 0, right: 80, bottom: 95, left: 135}, width = 465 - margin.left - margin.right, height = 235 - margin.top - margin.bottom; // append the svg object to the body of the page var svg = d3.select($(this).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 + ")"); // Build X scales and axis: var x = d3.scaleBand() .range([ 0, width ]) .domain(data.map(function(d) { return d.tissue; })) .padding(0.01); var xAxis = d3.axisBottom(x); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .selectAll(".tick text") .attr("class", "barchartlabel") .attr("y", 0) .attr("x", -9) .attr("transform", "rotate(-55)") .style("text-anchor", "end") .each(function(d, i) { if (data[i].tooltip) { d3.select(this).attr('title', data[i].tooltip); } if (data[i].url) { d3.select(this).attr('url', data[i].url).style('cursor', 'pointer'); } }); var y = d3.scaleBand() .range([ height, 0 ]) .domain(data.map(function(d) { return d.cell_type; })) .padding(0.01); svg.append("g") .call(d3.axisLeft(y)); // Build color scale var myColor = d3.scaleLinear() .range(["white", "#69b3a2"]) .domain([1,100]) svg.selectAll() .data(data, function(d) {return d.tissue+':'+d.cell_type;}) .enter() .append("rect") .attr("x", function(d) { return x(d.tissue) }) .attr("y", function(d) { return y(d.cell_type) }) .attr("width", x.bandwidth()) .attr("height", y.bandwidth()) //.attr("width", x.bandwidth() ) //.attr("height", y.bandwidth() ) .style("fill", function(d) { return (d.value == -1)?'white':'white'} ) svg.selectAll() .data(data) .enter() .append("line") .style("stroke", "lightgrey") .style("stroke-width", 1) .attr("x1", function(d) { return x(d.tissue) + x.bandwidth() }) .attr("y1", function(d) { return height}) .attr("x2", function(d) { return x(d.tissue) + x.bandwidth() }) .attr("y2", function(d) { return 0 }) svg.selectAll() .data(data) .enter() .append("line") .style("stroke", "grey") .style("stroke-width", 1) .attr("x1",0) .attr("y1", function(d) { return y(d.cell_type)}) .attr("x2", width) .attr("y2", function(d) { return y(d.cell_type) }) //.attr("width", x.bandwidth() ) //.attr("height", y.bandwidth() ) svg.selectAll() .data(data, function(d) {return d.tissue+':'+d.cell_type;}) .enter() .append("circle") .attr("cx", function(d) { return x.bandwidth()/2 + x(d.tissue) }) .attr("cy", function(d) { return y.bandwidth()/2 +y(d.cell_type) }) .attr("r", function(d) { if(d.value >= 0) {return x.bandwidth()/2-3} else {return 0}}) //.attr("width", x.bandwidth() ) //.attr("height", y.bandwidth() ) .style("fill", function(d) { return ((d.value==0)?'lightgrey':d.color)} ) .each(function(d, i) { if (data[i].tooltip) { d3.select(this).attr('title', data[i].tooltip); } if (data[i].url) { d3.select(this).attr('url', data[i].url).style('cursor', 'pointer'); } }); $(this).on('click', '[url]', function() { document.location.href = $(this).attr('url'); }); }