class @PlasticineLine constructor: (@holder) -> @holder = $('.plasticine-line') PlasticineHelpers.setLocale() #@drawTooltip() @xScale = d3.scaleBand() @setXScaleRange() @yScale = d3.scaleLinear().range([@holder.height(),0]) @setXAxis() @setYAxis() @svg = d3.select("##{@holder.attr('id')}").append('svg').style('width', @holderWidth()).style('height', @holder.height()).append('g') d3.json(@holder.data('url')).then (data) => @build(data) build: (data) -> @xAxisFormat = data['axis_x_format'] @yAxisFormat = data['axis_y_format'] @yAxisTickCount = data['axis_y_tick_count'] @chartLayout = data['chart_layout'] @quarterStartMonth = Number(data.quarter_start_month) maxY = if @chartLayout == 'area' then data['max_y_stack'] * 1.1 else data['max_y'] data['lines'].forEach (line) => line.dots.forEach (d) => d.x = PlasticineHelpers.parseValue(d.x, @xAxisFormat) @xScale.domain data['lines'][0].dots.map( (d) -> d.x ) @yScale.domain [0, maxY] @drawYAxis() if @chartLayout == 'area' stackedDataset = [] stackedKeys = [] data['lines'].forEach (line,i) => line.dots.forEach (d,j) => stackedDataset.push { x: d.x } if i == 0 stackedKeys.push "y#{i+1}" if j == 0 stackedDataset[j]["y#{i+1}"] = d.y stack = d3.stack().keys(stackedKeys) series = stack(stackedDataset); @chartPath = d3.area().curve(d3.curveCardinal) .x( (d,i) => @xScale(stackedDataset[i].x) ) .y0( (d) => @yScale(d[0]) ) .y1( (d) => @yScale(d[1]) ) else series = data['lines'] @chartPath = d3.line().curve(d3.curveCardinal) .x( (d) => @xScale(d.x)) .y( (d) => @yScale(d.y)) @lines = @svg.append('g').attr('class', "elements #{@chartLayout}").selectAll('.element').data(series) @refreshLines() @drawXAxis() d3.select(window).on("resize." + @holder.attr("id"), () => @resizeX()) refreshLines: () -> $('g.element').remove() element = @lines.enter().append('g').attr('class', "element") element.append("path") .attr('class', 'line') .attr('d', (d) => if @chartLayout == 'area' then @chartPath(d) else @chartPath(d.dots)) drawXAxis: () -> height = @holder.height() @svg.append('g').attr('class', 'x axis') .attr('transform', 'translate(0,' + height + ')') .call @xAxis @refreshXAxis() drawYAxis: () -> group = @svg.append("g").attr("class", "y axis").call @yAxis group.selectAll("g").filter((d) -> d).classed("minor", true) @refreshYAxis() holderWidth: () -> @holder.width() refreshXAxis: () -> @setXAxis() @svg.select('.x.axis').call @xAxis refreshYAxis: () -> @setYAxis() @svg.select('.y.axis').call @yAxis resizeX: () -> d3.select(@svg.node().parentNode).style('width', @holderWidth() + 'px') @setXScaleRange() @refreshXAxis() @refreshYAxis() @refreshLines() setXAxis: () -> @xAxis = d3.axisBottom(@xScale) @xAxis.tickSize -@holder.height() switch @xAxisFormat when 'date' then @xAxis.tickFormat(d3.timeFormat('%b')) when 'quarter' then @xAxis.tickFormat (d) => PlasticineHelpers.toQuarter(d, @quarterStartMonth) when 'year' then @xAxis.tickFormat (d) => PlasticineHelpers.toYear(d, @quarterStartMonth) when 'money' then @xAxis.tickFormat (d) => PlasticineHelpers.toPrice(d) setXScaleRange: () -> linesMargin = @holder.data('lines-margin') linesLeftPadding = @holder.data('lines-left-padding') linesRightPadding = @holder.data('lines-right-padding') width = @holderWidth() @xScale = @xScale.rangeRound([linesLeftPadding, width - linesRightPadding]).padding(linesMargin); setYAxis: () -> @yAxis = d3.axisLeft(@yScale) @yAxis.tickSize -@holderWidth() @yAxis.ticks @yAxisTickCount switch @yAxisFormat when 'date' then @yAxis.tickFormat(d3.timeFormat('%b')) when 'money' then @yAxis.tickFormat (d) => PlasticineHelpers.toPrice(d)