// Chart design based on my BulleT that was based on original bullet chart by Mike Bostock: // http://bl.ocks.org/mbostock/4061961 // with d3.chart.js (0.1.2) // http://misoproject.com/d3-chart/ d3.chart("LikertEven", { initialize: function() { var chart = this; this.xScale = d3.scale.linear(); this.tickFormat( function(d){return Math.abs(d)} ); this.x0 = chart.xScale(0); this.axisStyle(function(d) { return d.axisStyle; }); this.base.classed("LikertEven", true); // Default configuration this._margin = { top: 0, right: 0, bottom: 0, left: 0 }; this.duration(0); this.percent(function(d) { return d.percent; }); this.width(100); this.height(40); this.reverse(false); this.orient("left"); this.terjedelem(function(d) { return d.terjedelem; }); /******************************************************************************/ this.layer("rowBackgroundA", this.base.append("g").classed("rowBackgroundA", true), { dataBind: function(data) { data = data.rowStyle; return this.selectAll("rect").data(data); }, insert: function() { return this.append("g"); }, events: { enter: function(d) { this.append("rect").attr("class", function(d){return d;}) .attr("x", chart.xScale(-110)) .attr("y", 0) .attr("height", chart.height()) .attr("width", chart.xScale(250)); this.append("rect").attr("class", function(d){ var axisStyle = chart.axisStyle(); if( axisStyle === "axis" ){ return "background " + d; }else{ return "background " + "white"; } }) .attr("x", chart.xScale(100)) .attr("y", chart.height()/2) .attr("height", chart.height()/2) .attr("width", chart.xScale(40)); } } }) /******************************************************************************/ this.layer("rowBackgroundB", this.base.append("g").classed("rowBackgroundB", true), { dataBind: function() { var format = this.chart().tickFormat(); return this.selectAll("g.tickLine").data(this.chart().xScale.ticks(8), function(d) { return d; }); }, insert: function() { var tick = this.append("g").attr("class", "tickLine"); var height =chart.height(); var format = chart.tickFormat(); tick.append("line") .attr("y1", 0) .attr("y2", chart.height()) .attr("opacity", function(d) { if( d < 100 ){ return 1; }else{ return 0; } }); return tick; }, events: { enter: function(d) { var axisStyle = chart.axisStyle(); this.attr("transform", function(d) { return "translate(" + chart.xScale(d) + ",0)"; }) .attr("stroke-width", 1) .attr("stroke", "#ffffff"); }, "exit:transition": function() { this.remove(); } } }) /******************************************************************************/ this.layer("percent", this.base.append("g").classed("percent", true), { dataBind: function(data) { var data_percent = new Array(); // @CodeXmonk: a bit of hack too - ToDo later. data_percent[0] = (data.percent[0]+data.percent[1])*(-1); // [-80,-45,20,40] data_percent[1] = data.percent[1]*(-1); data_percent[2] = data.percent[2]+data.percent[3]; data_percent[3] = data.percent[2]; return this.selectAll("rect.percent").data(data_percent); }, insert: function() { return this.append("rect"); }, events: { enter: function(d, i) { this.attr("class", function(d, i) { return "percent s" + i; }) .attr("height", chart.height()) .attr("x", function(d,i) { if( d < 0 ){ return chart.xScale(d); }else{ return chart.xScale(0); } }) .attr("width", function(d, i) { return chart.xScale(Math.abs(d))-chart.xScale(0) ; }) .attr("transform", "translate(" + 0 + ",0)" ); }, "merge:transition": function(d, i) { this.duration(chart.duration()) .attr("x", function(d, i) { if( d < 0 ){ return chart.xScale(d); }else{ return chart.xScale(0); } }) .attr("width", function(d, i) { if( d < 0 ){ return chart.xScale(Math.abs(d))-chart.xScale(0) ; }else{ return chart.xScale(Math.abs(d))-chart.xScale(0) ; } }) .attr("transform", "translate(" + 0 + ",0)" ); }, exit: function() { this.remove(); } } }); /******************************************************************************/ this.layer("text", this.base.append("g").classed("text", true), { dataBind: function(data) { var data_percent = new Array(); var dimension = data.dimension; var axisStyle = chart.axisStyle(); // @CodeXmonk: a bit of hack too - ToDo later. data_percent[0] = new Array( (data.percent[0]+data.percent[1])*(-1), data.percent[0], dimension ); // [-80,-45,20,40] data_percent[1] = new Array( data.percent[1]*(-1), data.percent[1], dimension ); data_percent[2] = new Array( data.percent[2]+data.percent[3], data.percent[3], dimension ); data_percent[3] = new Array( data.percent[2], data.percent[2], dimension); return this.selectAll("text").data(data_percent); }, insert: function() { return this.append("text") }, events: { enter: function(d, i) { this.text( function(d,i) { var axisStyle = chart.axisStyle(); if( axisStyle === "axis" ){ return d[2][i+1]; }else{ switch (true) { case ( d[1] < 5 ): return ""; break; case ( 5 <= d[1] && d[1] < 8 ): return Math.abs(d[1]); break; default: return Math.abs(d[1])+"%"; break; } } }) .style("opacity", function() { var axisStyle = chart.axisStyle(); if( axisStyle === "axis" ){ return 1; }else{ return 0; } }) this.attr("class", function(d, i) { var axisStyle = chart.axisStyle(); if( axisStyle === "axis" ){ return "textResultKiem"; }else{ return "textResult"; } }) .attr("y", chart.height() - chart.height()/3) .attr("x", function(d, i) { return chart.xScale(d[0]); }) .attr("text-anchor", function(d, i) { if( d[0] < 0 ){ return "start"; }else{ return "end"; } }) .attr("transform", function(d, i) { if( d[0] < 0 ){ return "translate(" + 2 + ",0)"; }else{ return "translate(" + -2 + ",0)"; } }); }, "merge:transition": function(d, i) { this.duration(chart.duration()) .attr("x", function(d, i) { return chart.xScale(d[0]); }) .attr("text-anchor", function(d, i) { if( d[0] < 0 ){ return "start"; }else{ return "end"; } }) .attr("transform", function(d, i) { if( d[0] < 0 ){ return "translate(" + 2 + ",0)"; }else{ return "translate(" + -2 + ",0)"; } }); this.duration(chart.duration()*2) .style("opacity", function(d){return 1;}); }, exit: function() { this.remove(); } } }); /******************************************************************************/ this.layer("textLegendA", this.base.append("g").classed("textLegendA", true), { dataBind: function(data) { var data_tmp = new Array(); var dimension = data.dimension; var axisStyle = chart.axisStyle(); data_tmp[0] = new Array( dimension ); return this.selectAll("text").data(data_tmp); }, insert: function() { return this.append("text"); }, events: { enter: function(d) { this.text( function(d) {return d[0][0];}); this.attr("class", function() { var axisStyle = chart.axisStyle(); if( axisStyle === "axis" ){ return "dimTextKiem"; }else{ return "textLegendA"; } }) this.attr("y", function() { var axisStyle = chart.axisStyle(); if( axisStyle === "axis" ){ return chart.height()/1.5; }else{ return chart.height()/2.8; } }) .attr("x", function() { return chart.xScale(104);}) .attr("text-anchor", function() {return "start"; }); }, "merge:transition": function() { this.attr("x", function() { return chart.xScale(104); }) .attr("text-anchor", function() {return "start"; }); }, exit: function() { this.remove(); } } }); /******************************************************************************/ this.layer("textLegendB", this.base.append("g").classed("textLegendB", true), { dataBind: function(data) { var data_tmp = new Array(); var axisStyle = chart.axisStyle(); /* let's find the greatest value in data.percent array */ var greatest; var indexOfGreatest; var array = data.percent; for (var i = 0; i < array.length; i++) { if (!greatest || array[i] > greatest) { greatest = array[i]; indexOfGreatest = i; } } data_tmp[0] = new Array( data.percent[indexOfGreatest], indexOfGreatest, data.dimension ); return this.selectAll("text").data(data_tmp); }, insert: function() { return this.append("text"); }, events: { enter: function(d) { this.text( function(d) { var idx = d[1]; var axisStyle = chart.axisStyle(); if( axisStyle === "axis" ){ return ""; }else{ return d[0] + "% " + d[2][idx+1]; } }); this.attr("class", function(d) { var idx = d[1]; return "subtitle s" + idx; }) this.attr("y", function() { var axisStyle = chart.axisStyle(); if( axisStyle === "axis" ){ return chart.height()/1.5; }else{ return chart.height()-4; } }) .attr("x", function() { return chart.xScale(104);}) .attr("text-anchor", function() {return "start"; }); }, "merge:transition": function() { this.attr("x", function() { return chart.xScale(104); }) .attr("text-anchor", function() {return "start"; }); }, exit: function() { this.selectAll("text").remove(); } } }); /******************************************************************************/ this.layer("ticks", this.base.append("g").classed("ticks", true), { dataBind: function() { var format = this.chart().tickFormat(); return this.selectAll("g.tick").data(this.chart().xScale.ticks(8), function(d) { return d; }); }, insert: function() { var tick = this.append("g").attr("class", "tick"); var height =chart.height(); var format = chart.tickFormat(); tick.append("line") .attr("y1", chart.height()) .attr("y2", chart.height() * 7 / 6); tick.append("text") .attr("text-anchor", "middle") .attr("dy", "1em") .attr("y", chart.height() * 7 / 6) .text(format); return tick; }, events: { enter: function(d) { var axisStyle = chart.axisStyle(); this.attr("transform", function(d) { return "translate(" + chart.xScale(d) + ",0)"; }) .style("opacity", function(d){ if( axisStyle === "axis" ){ return 1; }else{ return 0; } }); }, "merge:transition": function(d) { var axisStyle = chart.axisStyle(); this.duration(chart.duration()) .attr("transform", function(d) { return "translate(" + chart.xScale(d) + ",0)"; }) .style("opacity", function(d){ if( axisStyle === "axis" ){ return 1; }else{ return 0; } }); this.select("line") .attr("y1", chart.height()) .attr("y2", chart.height() * 7 / 6); this.select("text") .attr("y", chart.height() * 7 / 6); }, "exit:transition": function() { this.duration(chart.duration()) .attr("transform", function(d) { return "translate(" + chart.xScale(d) + ",0)"; }) .style("opacity", 1e-6) .remove(); } } }); d3.timer.flush(); }, transform: function(data) { var height = this.height(); // misoproject: Copy data before sorting var newData = { rowStyle: data.rowStyle, dimension: data.dimension, randomizer: data.randomizer, terjedelem: data.terjedelem.slice(), percent: data.percent, item: data.item, }; this.xScale.domain([newData.terjedelem[0], newData.terjedelem[1]]); var axisStyle = this.axisStyle(); if( axisStyle !== "axis" ){ var select_tmp = d3.selectAll("[name=SVG]"); select_tmp.attr("height",25); } return newData; }, // misoproject: reverse or not reverse: function(x) { if (!arguments.length) return this._reverse; this._reverse = x; return this; }, // misoproject: left, right, top, bottom orient: function(x) { if (!arguments.length) return this._orient; this._orient = x; this._reverse = this._orient == "right" || this._orient == "bottom"; return this; }, axisStyle: function(x) { if (!arguments.length) return this._axisStyle; this._axisStyle = x; return this; }, // @CodeXmonk: terjedelem (20,80) terjedelem: function(x) { if (!arguments.length) return this._terjedelem; this._terjedelem = x; return this; }, percent: function(x) { if (!arguments.length) return this._percent; this._percent = x; return this; }, width: function(x) { var margin, width_tmp; if (!arguments.length) { return this._width; } margin = this.margin(); width_tmp = x[0]; width_tmp = width_tmp - (margin.left + margin.right); this._width = width_tmp; this.xScale.range(this._reverse ? [width_tmp, 0] : [0, width_tmp]); this.base.attr("width", width_tmp); return this; }, height: function(x) { var margin, height_tmp; if (!arguments.length) { return this._height; } margin = this.margin(); height_tmp = x[0]; height_tmp = height_tmp - (margin.top + margin.bottom)-10; this._height = height_tmp; this.base.attr("height", height_tmp); return this; }, margin: function(margin) { if (!margin) { return this._margin; } var margin_tmp = margin; ["top", "right", "bottom", "left"].forEach(function(dimension) { if (dimension in margin_tmp) { this._margin[dimension] = margin_tmp[dimension]; } }, this); this.base.attr("transform", "translate(" + this._margin.left + "," + this._margin.top + ")"); return this; }, tickFormat: function(x) { if (!arguments.length) return this._tickFormat; this._tickFormat = x; return this; }, orientation: function(x) { if (!arguments.length) return this._orientation; this._orientation = x; return this; }, duration: function(x) { if (!arguments.length) return this._duration; this._duration = x; return this; } });