From d318d768fc97ff08fc4b12ef1e78b7eb75e0ccef Mon Sep 17 00:00:00 2001 From: Mark Derbecker Date: Wed, 19 Jun 2013 17:07:34 -0700 Subject: [PATCH 1/3] Fix for Rickshaw GitHub Issue #89 - Re-factored Rickshaw.Graph.Legend considerably to allow for dynamic series additions/deletions. - Removed somewhat brittle "series-reordering" code in Rickshaw.Behavior.Series.Highlight and added the concept of zOrder to the Renderer. --- ...ickshaw.Graph.Behavior.Series.Highlight.js | 22 ++-- .../Rickshaw.Graph.Behavior.Series.Toggle.js | 1 + src/js/Rickshaw.Graph.Legend.js | 114 ++++++++++++------ src/js/Rickshaw.Graph.Renderer.js | 14 ++- 4 files changed, 94 insertions(+), 57 deletions(-) diff --git a/src/js/Rickshaw.Graph.Behavior.Series.Highlight.js b/src/js/Rickshaw.Graph.Behavior.Series.Highlight.js index d38fdd5f..127d6d33 100644 --- a/src/js/Rickshaw.Graph.Behavior.Series.Highlight.js +++ b/src/js/Rickshaw.Graph.Behavior.Series.Highlight.js @@ -26,19 +26,15 @@ Rickshaw.Graph.Behavior.Series.Highlight = function(args) { if (l === line) { // if we're not in a stacked renderer bring active line to the top - if (index > 0 && self.graph.renderer.unstack && (line.series.renderer ? line.series.renderer.unstack : true)) { - - var seriesIndex = self.graph.series.length - index - 1; - line.originalIndex = seriesIndex; - - var series = self.graph.series.splice(seriesIndex, 1)[0]; - self.graph.series.push(series); + if (self.graph.renderer.unstack && (line.series.renderer ? line.series.renderer.unstack : true)) { + line.series.zOrder = 1; } return; } colorSafe[line.series.name] = colorSafe[line.series.name] || line.series.color; line.series.color = disabledColor(line.series.color); + line.series.zOrder = 0; } ); @@ -53,17 +49,11 @@ Rickshaw.Graph.Behavior.Series.Highlight = function(args) { self.legend.lines.forEach( function(line) { - // return reordered series to its original place - if (l === line && line.hasOwnProperty('originalIndex')) { - - var series = self.graph.series.pop(); - self.graph.series.splice(line.originalIndex, 0, series); - delete line.originalIndex; - } - if (colorSafe[line.series.name]) { line.series.color = colorSafe[line.series.name]; } + line.series.zOrder = 0; + } ); self.graph.update(); @@ -75,6 +65,8 @@ Rickshaw.Graph.Behavior.Series.Highlight = function(args) { this.legend.lines.forEach( function(l) { self.addHighlightEvents(l); } ); + + this.legend.highlighter = this; } }; diff --git a/src/js/Rickshaw.Graph.Behavior.Series.Toggle.js b/src/js/Rickshaw.Graph.Behavior.Series.Toggle.js index f65c8a64..17f7e248 100644 --- a/src/js/Rickshaw.Graph.Behavior.Series.Toggle.js +++ b/src/js/Rickshaw.Graph.Behavior.Series.Toggle.js @@ -119,4 +119,5 @@ Rickshaw.Graph.Behavior.Series.Toggle = function(args) { this.updateBehaviour = function () { this._addBehavior() }; + this.legend.toggler = this; }; diff --git a/src/js/Rickshaw.Graph.Legend.js b/src/js/Rickshaw.Graph.Legend.js index 3da57710..d120e5f5 100644 --- a/src/js/Rickshaw.Graph.Legend.js +++ b/src/js/Rickshaw.Graph.Legend.js @@ -9,58 +9,98 @@ Rickshaw.Graph.Legend = function(args) { element.classList.add('rickshaw_legend'); - var list = this.list = document.createElement('ul'); - element.appendChild(list); + this.list = document.createElement('ul'); + element.appendChild(this.list); - var series = graph.series - .map( function(s) { return s } ); + this.prepareSeries = function(unpreparedSeries) { + var preparedSeries = unpreparedSeries.map(function(s) { + return s; + }); - if (!args.naturalOrder) { - series = series.reverse(); - } + if (!args.naturalOrder) { + preparedSeries = preparedSeries.reverse(); + } + + return preparedSeries; + }; this.lines = []; - this.addLine = function (series) { - var line = document.createElement('li'); - line.className = 'line'; - if (series.disabled) { - line.className += ' disabled'; - } + this.addLine = function(series) { + var lineElement = document.createElement('li'); + var lineData = { + element: lineElement, + series: series + }; - var swatch = document.createElement('div'); - swatch.className = 'swatch'; - swatch.style.backgroundColor = series.color; + lineData.swatch = document.createElement('div'); + lineElement.appendChild(lineData.swatch); - line.appendChild(swatch); + lineData.label = document.createElement('span'); + lineElement.appendChild(lineData.label); - var label = document.createElement('span'); - label.className = 'label'; - label.innerHTML = series.name; + this.updateLineBehavior(lineData); - line.appendChild(label); - list.appendChild(line); + if (self.toggler) { + self.toggler.addAnchor(lineData); + self.toggler.updateBehaviour(); + } + if (self.highlighter) { + self.highlighter.addHighlightEvents(lineData); + } - line.series = series; + return lineData; + }; - if (series.noLegend) { - line.style.display = 'none'; + this.updateLineBehavior = function(lineData) { + if (lineData.series.noLegend) { + lineData.element.style.display = 'none'; } - var _line = { element: line, series: series }; - if (self.shelving) { - self.shelving.addAnchor(_line); - self.shelving.updateBehaviour(); + lineData.element.className = 'line'; + if (lineData.series.disabled) { + lineData.element.className += ' disabled'; } - if (self.highlighter) { - self.highlighter.addHighlightEvents(_line); + + lineData.swatch.className = 'swatch'; + lineData.swatch.style.backgroundColor = lineData.series.color; + + lineData.label.className = 'label'; + lineData.label.innerHTML = lineData.series.name; + }; + + this.updateLines = function() { + var newSetOfLines = []; + var seriesArray = this.prepareSeries(graph.series); + + for (var i = seriesArray.length - 1; i >= 0; i--) { + var series = seriesArray[i]; + var existingLine = null; + for (var j = self.lines.length - 1; j >= 0; j--) { + if (self.lines[j].series === series) { + existingLine = self.lines[j]; + break; + } + } + + if (existingLine !== null) { + newSetOfLines.push(existingLine); + } else { + newSetOfLines.push(self.addLine(series)); + } } - self.lines.push(_line); + + self.lines = newSetOfLines; + + self.list.innerHTML = ''; + self.lines.forEach(function (lineData) { + self.list.appendChild(lineData.element); + }); }; - series.forEach( function(s) { - self.addLine(s); - } ); + self.updateLines(); - graph.onUpdate( function() {} ); -}; + graph.onUpdate(function() { + self.updateLines(); + }); +}; \ No newline at end of file diff --git a/src/js/Rickshaw.Graph.Renderer.js b/src/js/Rickshaw.Graph.Renderer.js index 4cb8c379..459589aa 100644 --- a/src/js/Rickshaw.Graph.Renderer.js +++ b/src/js/Rickshaw.Graph.Renderer.js @@ -82,7 +82,11 @@ Rickshaw.Graph.Renderer = Rickshaw.Class.create( { var vis = args.vis || graph.vis; vis.selectAll('*').remove(); - var data = series + var orderedSeries = series + .slice(0) + .sort(function(a, b) { return a.zOrder !== undefined && b.zOrder !== undefined && a.zOrder > b.zOrder; }); + + var data = orderedSeries .filter(function(s) { return !s.disabled }) .map(function(s) { return s.stack }); @@ -92,10 +96,10 @@ Rickshaw.Graph.Renderer = Rickshaw.Class.create( { .attr("d", this.seriesPathFactory()); var i = 0; - series.forEach( function(series) { - if (series.disabled) return; - series.path = nodes[0][i++]; - this._styleSeries(series); + orderedSeries.forEach( function(s) { + if (s.disabled) return; + s.path = nodes[0][i++]; + this._styleSeries(s); }, this ); }, From 6406e848b21d28084b820a13088663a4302d38c9 Mon Sep 17 00:00:00 2001 From: Mark Derbecker Date: Thu, 20 Jun 2013 11:54:24 -0700 Subject: [PATCH 2/3] Bug fixes for previous commit: - Legend order had been reversed from previous version. Fixed. - Rickshaw.Graph.Behavior.Series.Order.js interactions with the Legend were broken. Fixed. --- src/js/Rickshaw.Graph.Legend.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/js/Rickshaw.Graph.Legend.js b/src/js/Rickshaw.Graph.Legend.js index d120e5f5..81cbc0ce 100644 --- a/src/js/Rickshaw.Graph.Legend.js +++ b/src/js/Rickshaw.Graph.Legend.js @@ -28,6 +28,8 @@ Rickshaw.Graph.Legend = function(args) { this.addLine = function(series) { var lineElement = document.createElement('li'); + lineElement.series = series; + var lineData = { element: lineElement, series: series @@ -73,7 +75,7 @@ Rickshaw.Graph.Legend = function(args) { var newSetOfLines = []; var seriesArray = this.prepareSeries(graph.series); - for (var i = seriesArray.length - 1; i >= 0; i--) { + for (var i = 0; i < seriesArray.length; i++) { var series = seriesArray[i]; var existingLine = null; for (var j = self.lines.length - 1; j >= 0; j--) { From a2e16ef0059aaa11eb54d763e467b96731b5f50d Mon Sep 17 00:00:00 2001 From: Mark Derbecker Date: Wed, 19 Jun 2013 17:30:52 -0700 Subject: [PATCH 3/3] Modified "extensions.html" example so that it builds up the graph one series at a time. This properly exercises the dynamic nature of the legend and the series behaviors. --- examples/css/extensions.css | 1 + examples/extensions.html | 38 ++++++++++++++++++++++++++----------- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/examples/css/extensions.css b/examples/css/extensions.css index dfcd90e4..207c5e42 100644 --- a/examples/css/extensions.css +++ b/examples/css/extensions.css @@ -17,6 +17,7 @@ div, span, p, td { display: inline-block; position: relative; left: 8px; + height: 150px; } #legend_container { position: absolute; diff --git a/examples/extensions.html b/examples/extensions.html index 9594a52f..16a073d8 100644 --- a/examples/extensions.html +++ b/examples/extensions.html @@ -120,16 +120,7 @@
Smoothing
var palette = new Rickshaw.Color.Palette( { scheme: 'classic9' } ); -// instantiate our graph! - -var graph = new Rickshaw.Graph( { - element: document.getElementById("chart"), - width: 900, - height: 500, - renderer: 'area', - stroke: true, - preserve: true, - series: [ +var seriesArray = [ { color: palette.color(), data: seriesData[0], @@ -159,7 +150,19 @@
Smoothing
data: seriesData[6], name: 'New York' } - ] + ]; + +// instantiate our graph! + +var graphSeries = [seriesArray[0]]; +var graph = new Rickshaw.Graph( { + element: document.getElementById("chart"), + width: 900, + height: 500, + renderer: 'area', + stroke: true, + preserve: true, + series: graphSeries } ); graph.render(); @@ -255,6 +258,19 @@
Smoothing
addAnnotation(true); setTimeout( function() { setInterval( addAnnotation, 6000 ) }, 6000 ); +function addNewSeries() { + var i = graphSeries.length; + if (i >= seriesArray.length) { + return; + } else { + graphSeries[i] = seriesArray[i]; + setTimeout(addNewSeries, 50); + } + graph.update(); +} + +addNewSeries(); +