From: David Schoonover Date: Wed, 20 Jun 2012 16:00:37 +0000 (-0700) Subject: Auto-load d3 line chart type. X-Git-Url: http://git.less.ly:3516/?a=commitdiff_plain;h=89f63c7a5c7aeecb5ffbd87d135b83dc77943128;p=kraken-ui.git Auto-load d3 line chart type. --- diff --git a/data/graphs/d3-test.json b/data/graphs/d3-test.json index f649f56..15446c4 100644 --- a/data/graphs/d3-test.json +++ b/data/graphs/d3-test.json @@ -1 +1,145 @@ -{"options":{"animatedZooms":true,"avoidMinZero":false,"axis":null,"axisLabelColor":"#666666","axisLabelFontSize":11,"axisLabelFormatter":null,"axisLabelWidth":50,"axisLineColor":"#AAAAAA","axisLineWidth":0.3,"axisTickSize":3,"colorSaturation":1,"colorValue":0.5,"colors":["#FF0097","#EF8158","#83BB32","#182B53","#4596FF","#553DC9","#AD3238","#00FFBC","#F1D950"],"connectSeparatedPoints":false,"customBars":false,"dateWindow":null,"delimiter":",","digitsAfterDecimal":2,"displayAnnotations":false,"drawPoints":true,"drawXAxis":true,"drawXGrid":true,"drawYAxis":true,"drawYGrid":true,"errorBars":false,"file":null,"fillAlpha":0.15,"fillGraph":false,"fractions":false,"gridLineColor":"#D8D8D8","gridLineWidth":0.3,"hideOverlayOnMouseOut":false,"highlightCircleSize":4,"includeZero":false,"interactionModel":null,"isZoomedIgnoreProgrammaticZoom":false,"labels":null,"labelsDiv":null,"labelsDivStyles":null,"labelsDivWidth":250,"labelsKMB":true,"labelsKMG2":false,"labelsSeparateLines":true,"labelsShowZeroValues":true,"legend":"always","logscale":true,"maxNumberWidth":30,"panEdgeFraction":null,"pixelsPerLabel":null,"pixelsPerXLabel":null,"pixelsPerYLabel":null,"pointSize":1,"rangeSelectorHeight":40,"rangeSelectorPlotFillColor":"#A7B1C4","rangeSelectorPlotStrokeColor":"#808FAB","rightGap":20,"rollPeriod":1,"showLabelsOnHighlight":true,"showRangeSelector":false,"showRoller":false,"sigFigs":null,"sigma":2,"stackedGraph":false,"stepPlot":false,"strokePattern":null,"strokeWidth":4,"ticker":null,"title":null,"titleHeight":18,"valueFormatter":null,"valueRange":null,"visibility":null,"wilsonInterval":true,"xAxisHeight":null,"xAxisLabelFormatter":null,"xAxisLabelWidth":55,"xLabelHeight":18,"xValueFormatter":null,"xValueParser":null,"xlabel":null,"y2label":null,"yAxisLabelFormatter":null,"yAxisLabelWidth":50,"yLabelWidth":18,"yValueFormatter":null,"ylabel":null},"slug":"d3-test","name":"","desc":"","notes":"","width":"auto","height":320,"parents":["root"],"data":{"palette":null,"lines":[],"metrics":[{"index":0,"label":"","type":"int","timespan":{"start":null,"end":null,"step":null},"disabled":false,"source_id":"rc_active_editors_count","source_col":1,"color":"#00b2ff","visible":true,"format_value":null,"format_axis":null,"transforms":[],"scale":1},{"index":1,"label":"","type":"int","timespan":{"start":null,"end":null,"step":null},"disabled":false,"source_id":"rc_new_article_count","source_col":1,"color":"rgb(213,62,79)","visible":true,"format_value":null,"format_axis":null,"transforms":[],"scale":1}]},"callout":{"enabled":true,"metric_idx":0,"label":""},"chartType":"dygraphs","id":"d3-test"} \ No newline at end of file +{ + "options": { + "animatedZooms": true, + "avoidMinZero": false, + "axis": null, + "axisLabelColor": "#666666", + "axisLabelFontSize": 11, + "axisLabelFormatter": null, + "axisLabelWidth": 50, + "axisLineColor": "#AAAAAA", + "axisLineWidth": 0.3, + "axisTickSize": 3, + "colorSaturation": 1, + "colorValue": 0.5, + "colors": ["#FF0097", "#EF8158", "#83BB32", "#182B53", "#4596FF", "#553DC9", "#AD3238", "#00FFBC", "#F1D950"], + "connectSeparatedPoints": false, + "customBars": false, + "dateWindow": null, + "delimiter": ",", + "digitsAfterDecimal": 2, + "displayAnnotations": false, + "drawPoints": true, + "drawXAxis": true, + "drawXGrid": true, + "drawYAxis": true, + "drawYGrid": true, + "errorBars": false, + "file": null, + "fillAlpha": 0.15, + "fillGraph": false, + "fractions": false, + "gridLineColor": "#D8D8D8", + "gridLineWidth": 0.3, + "hideOverlayOnMouseOut": false, + "highlightCircleSize": 4, + "includeZero": false, + "interactionModel": null, + "isZoomedIgnoreProgrammaticZoom": false, + "labels": null, + "labelsDiv": null, + "labelsDivStyles": null, + "labelsDivWidth": 250, + "labelsKMB": true, + "labelsKMG2": false, + "labelsSeparateLines": true, + "labelsShowZeroValues": true, + "legend": "always", + "logscale": true, + "maxNumberWidth": 30, + "panEdgeFraction": null, + "pixelsPerLabel": null, + "pixelsPerXLabel": null, + "pixelsPerYLabel": null, + "pointSize": 1, + "rangeSelectorHeight": 40, + "rangeSelectorPlotFillColor": "#A7B1C4", + "rangeSelectorPlotStrokeColor": "#808FAB", + "rightGap": 20, + "rollPeriod": 1, + "showLabelsOnHighlight": true, + "showRangeSelector": false, + "showRoller": false, + "sigFigs": null, + "sigma": 2, + "stackedGraph": false, + "stepPlot": false, + "strokePattern": null, + "strokeWidth": 4, + "ticker": null, + "title": null, + "titleHeight": 18, + "valueFormatter": null, + "valueRange": null, + "visibility": null, + "wilsonInterval": true, + "xAxisHeight": null, + "xAxisLabelFormatter": null, + "xAxisLabelWidth": 55, + "xLabelHeight": 18, + "xValueFormatter": null, + "xValueParser": null, + "xlabel": null, + "y2label": null, + "yAxisLabelFormatter": null, + "yAxisLabelWidth": 50, + "yLabelWidth": 18, + "yValueFormatter": null, + "ylabel": null + }, + "slug": "d3-test", + "name": "", + "desc": "", + "notes": "", + "width": "auto", + "height": 320, + "parents": ["root"], + "data": { + "palette": null, + "lines": [], + "metrics": [{ + "index": 0, + "label": "", + "type": "int", + "timespan": { + "start": null, + "end": null, + "step": null + }, + "disabled": false, + "source_id": "rc_active_editors_count", + "source_col": 1, + "color": "#00b2ff", + "visible": true, + "format_value": null, + "format_axis": null, + "transforms": [], + "scale": 1 + }, { + "index": 1, + "label": "", + "type": "int", + "timespan": { + "start": null, + "end": null, + "step": null + }, + "disabled": false, + "source_id": "rc_new_article_count", + "source_col": 1, + "color": "rgb(213,62,79)", + "visible": true, + "format_value": null, + "format_axis": null, + "transforms": [], + "scale": 1 + }] + }, + "callout": { + "enabled": true, + "metric_idx": 0, + "label": "" + }, + "chartType": "d3-line", + "id": "d3-test" +} diff --git a/lib/chart/chart-type.co b/lib/chart/chart-type.co index d66b435..2030a90 100644 --- a/lib/chart/chart-type.co +++ b/lib/chart/chart-type.co @@ -166,7 +166,7 @@ class exports.ChartType extends ReadyEmitter proto.options_ordered = spec proto.options = _.synthesize spec, -> [it.name, it] proto.ready = true - @emit 'ready', this + @triggerReady() error: ~> console.error "Error loading #{@typeName} spec! #it" this diff --git a/lib/chart/index.co b/lib/chart/index.co index 5a02eb2..a961cba 100644 --- a/lib/chart/index.co +++ b/lib/chart/index.co @@ -1,5 +1,7 @@ -chart_type = require 'kraken/chart/chart-type' +chart_type = require 'kraken/chart/chart-type' chart_option = require 'kraken/chart/option' -dygraphs = require 'kraken/chart/type/dygraphs' +dygraphs = require 'kraken/chart/type/dygraphs' +d3_charts = require 'kraken/chart/type/d3' -exports import chart_type import chart_option import dygraphs +exports import chart_type import chart_option \ + import dygraphs import d3_charts diff --git a/lib/chart/type/d3/d3-bar-chart-type.co b/lib/chart/type/d3/d3-bar-chart-type.co index e1fc007..347244b 100644 --- a/lib/chart/type/d3/d3-bar-chart-type.co +++ b/lib/chart/type/d3/d3-bar-chart-type.co @@ -3,8 +3,30 @@ d3 = require 'd3' { _, op, } = require 'kraken/util' { ChartType, -} = require 'kraken/chart' +} = require 'kraken/chart/chart-type' -exports.foo = 1 +class exports.BarChartType extends ChartType + __bind__ : <[ determineSize ]> + SPEC_URL : '/schema/d3/d3-bar.json' + + # NOTE: ChartType.register() must come AFTER `typeName` declaration. + typeName : 'd3-bar' + ChartType.register this + + + /** + * Hash of role-names to the selector which, when applied to the view, + * returns the correct element. + * @type Object + */ + roles : + viewport : '.viewport' + legend : '.graph-legend' + + + + -> super ... + + diff --git a/lib/chart/type/d3/d3-geo-chart-type.co b/lib/chart/type/d3/d3-geo-chart-type.co index 26d5ad9..2238b31 100644 --- a/lib/chart/type/d3/d3-geo-chart-type.co +++ b/lib/chart/type/d3/d3-geo-chart-type.co @@ -3,12 +3,12 @@ ColorBrewer = require 'colorbrewer' { _, op, } = require 'kraken/util' { ChartType, -} = require 'kraken/chart' +} = require 'kraken/chart/chart-type' -class GeoWorldChartType extends ChartType +class exports.GeoWorldChartType extends ChartType __bind__ : <[ dygNumberFormatter dygNumberFormatterHTML ]> SPEC_URL : '/schema/d3/d3-geo-world.json' diff --git a/lib/chart/type/d3/d3-line-chart-type.co b/lib/chart/type/d3/d3-line-chart-type.co index 6446686..3646aa5 100644 --- a/lib/chart/type/d3/d3-line-chart-type.co +++ b/lib/chart/type/d3/d3-line-chart-type.co @@ -4,10 +4,10 @@ ColorBrewer = require 'colorbrewer' { _, op, } = require 'kraken/util' { ChartType, -} = require 'kraken/chart' +} = require 'kraken/chart/chart-type' -class LineChartType extends ChartType +class exports.LineChartType extends ChartType __bind__ : <[ determineSize ]> SPEC_URL : '/schema/d3/d3-line.json' @@ -31,6 +31,10 @@ class LineChartType extends ChartType + getData: -> + @model.dataset.getColumns() + + transform: -> dataset = @model.dataset options = @model.getOptions() import @determineSize() @@ -39,85 +43,71 @@ class LineChartType extends ChartType options - renderChart: (rawData, viewport, options, lastChart) -> - viewport.empty() - + renderChart: (data, viewport, options, lastChart) -> ### Starting with http://bost.ocks.org/mike/chart/ - - # formatDate = d3.time.format("%b %Y") - # chart = timeSeriesChart() - # .x (d) -> formatDate.parse(d.date) - # .y (d) -> +d.price - # d3.csv("sp500.csv", (data) -> - # d3.select("#example") - # .datum(data) - # .call(chart) - margin = {top: 20, right: 20, bottom: 20, left: 20} width = 760 height = 320 - xValue = (d) -> d[0] - yValue = (d) -> d[1] xScale = d3.time.scale() yScale = d3.scale.linear() - xAxis = d3.svg.axis().scale(xScale).orient("bottom").tickSize(6, 0) - X = (d) -> xScale(d[0]) - Y = (d) -> yScale(d[1]) - line = d3.svg.line().x(X).y(Y) + dates = data[0] + cols = data.slice(1) + + # Calculate extents using all the data points (but not dates) + # allValues = d3.merge @model.dataset.getDataColumns() + allValues = d3.merge cols + + + # Update the x-scale with the extents of the dates. + xScale + .domain d3.extent dates + .range [ 0, width - margin.left - margin.right ] - chart = (selection) -> - selection.each (data) -> - - # Convert data to standard representation greedily - # this is needed for nondeterministic accessors. - data = data.map (d, i) -> - [ xValue.call(data, d, i), yValue.call(data, d, i) ] - - - # Update the x-scale. - xScale - .domain d3.extent data, xValue - .range [ 0, width - margin.left - margin.right ] - - # Update the y-scale. - yScale - .domain [ 0, d3.max data, yValue ] - .range [ height - margin.top - margin.bottom, 0 ] - - # Select the svg element, if it exists. - svg = d3.select(this).selectAll("svg").data([data]) - - # Otherwise, create the skeletal chart. - gEnter = svg.enter().append("svg").append("g") - gEnter.append("path") - .attr "class", "line" - .style "stroke", (d, i) -> options.colors[i] - gEnter.append("g").attr("class", "x axis") - - # Update the outer dimensions. - svg .attr("width", width) - .attr("height", height) - - # Update the inner dimensions. - g = svg.select("g") - .attr("transform", "translate(" + margin.left + "," + margin.top + ")") - - # Update the line path. - g.select(".line") - .attr("d", line) - - # Update the x-axis. - g.select(".x.axis") - .attr("transform", "translate(0," + yScale.range()[0] + ")") - .call(xAxis) + # Update the y-scale with the extents of the data. + yScale + .domain d3.extent allValues + .range [ height - margin.top - margin.bottom, 0 ] - d3.select viewport.0 - .datum rawData - .call chart + # Select the svg element, if it exists. + svg = d3.select viewport.0 .selectAll "svg" + .data [cols] + + # ...Otherwise, create the skeletal chart. + enterFrame = svg.enter() + .append "svg" .append "g" + .attr "class", "frame" + enterFrame.append "g" + .attr "class", "x axis time" + + # Update chart dimensions. + svg .attr "width", width + .attr "height", height + frame = svg.select "g.frame" + .attr "transform", "translate(#{margin.left},#{margin.top})" + + # Update the x-axis. + xAxis = d3.svg.axis().scale(xScale).orient("bottom").tickSize(6, 0) + frame.select ".x.axis.time" + .attr "transform", "translate(0,#{yScale.range()[0]})" + .call xAxis + + # Create/Update the line paths. + lines = frame.selectAll "path.line" + .data cols.map -> d3.zip dates, it + lines.enter().append "path" + .attr "class", "line" + lines.exit().remove() + + X = (d, i) -> xScale d[0] + Y = (d, i) -> yScale d[1] + line = d3.svg.line().x(X).y(Y) + # frame.selectAll "path.line" + lines.attr "d", line + .style "stroke", (col, i) -> options.colors[i] + + svg - -module.exports = exports = LineChartType \ No newline at end of file diff --git a/lib/chart/type/d3/index.co b/lib/chart/type/d3/index.co index 3a488eb..5651289 100644 --- a/lib/chart/type/d3/index.co +++ b/lib/chart/type/d3/index.co @@ -1,5 +1,5 @@ -bar = require 'kraken/chart/type/d3/d3-bar-chart-type' -geo = require 'kraken/chart/type/d3/d3-geo-chart-type' line = require 'kraken/chart/type/d3/d3-line-chart-type' +# geo = require 'kraken/chart/type/d3/d3-geo-chart-type' +# bar = require 'kraken/chart/type/d3/d3-bar-chart-type' -exports import bar import geo import line +exports import line # import geo import bar diff --git a/lib/util/op.co b/lib/util/op.co index 2fb5172..e434d65 100644 --- a/lib/util/op.co +++ b/lib/util/op.co @@ -24,6 +24,7 @@ module.exports = op = ok : (o) -> o? notOk : (o) -> o!? + ### manipulate function args/arity first : (a) -> a second : (_,a) -> a nth : (n) -> @@ -32,12 +33,24 @@ module.exports = op = case 1 then op.second default -> arguments[n] + # reverse the order of the first two args flip : (fn) -> (a, b) -> arguments[0] = b arguments[1] = a fn.apply this, arguments + # only pass n args + aritize : (fn, cxt, n) -> + [n, cxt] = [cxt, null] if arguments.length < 3 + -> fn.apply cxt ? this, [].slice.call(arguments, 0, n) + + # only pass the first argument + it : (fn, cxt) -> + -> fn.call cxt ? this, it + + + ### reduce-ordered values & accessors khas : (k,o) -> k in o kget : (k,o) -> o[k] diff --git a/www/css/chart.styl b/www/css/chart.styl index b9b7239..8ba548d 100644 --- a/www/css/chart.styl +++ b/www/css/chart.styl @@ -5,7 +5,13 @@ .line fill none stroke #000 - stroke-width 1.5px + stroke-width 3px + .axis + font-size 11px + color #666 + + text + fill #666 diff --git a/www/d3-test.jade b/www/d3-test.jade index b9c1123..968e48f 100644 --- a/www/d3-test.jade +++ b/www/d3-test.jade @@ -26,14 +26,13 @@ block main-scripts ChartType = require('kraken/chart').ChartType data = require('kraken/data'); DataSource = data.DataSource; DataSourceList = data.DataSourceList _graph = require('kraken/graph'); Graph = _graph.Graph; GraphList = _graph.GraphList; GraphEditView = _graph.GraphEditView - LineChartType = require('kraken/chart/type/d3/d3-line-chart-type') + //LineChartType = require('kraken/chart/type/d3/d3-line-chart-type') // run on DOM-ready jQuery(function(){ root.app = new AppView(function(){ this.model = root.graph = new Graph({ id:'d3-test' }, { parse:true }) this.view = root.view = new GraphEditView({ model:this.model }) - this.view.chartType = this.model.chartType = new LineChartType(this.model, this.view); }); }); diff --git a/www/modules.yaml b/www/modules.yaml index 4ee875a..e571f9a 100644 --- a/www/modules.yaml +++ b/www/modules.yaml @@ -113,8 +113,8 @@ dev: - type: - d3: - d3-line-chart-type - - d3-geo-chart-type - - d3-bar-chart-type + # - d3-geo-chart-type + # - d3-bar-chart-type - index - dygraphs - index