diff --git a/README.md b/README.md
index 99a8617..6fc068b 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,12 @@ Cubist is a Cubism graphing sandbox.
Enter Cube or Graphite expressions, get charts.
-Chart settings are chucked in local storage for later use.
+Charts are chucked in local storage for later use.
+
+## Features
+
+- server preferences and past expressions saved to local storage
+- comparison charts can be created by dragging one chart onto another ([screenshot](http://faulkner.io/t/screen2012-06-24at2.17.18AM.png))
## To install
@@ -31,6 +36,5 @@ $ export PORT=1234; cubist
- live editing for existing charts
- accept chart settings from query params
- kill data polling when charts are removed
-- support for comparison charts
- UI for removing old expressions
- change typeahead into an autocomplete based on functions and metrics available
diff --git a/css/app.css b/css/app.css
index 56db9fc..6eba7f4 100644
--- a/css/app.css
+++ b/css/app.css
@@ -1,8 +1,12 @@
-.horizon {
+.horizon, .comparison {
display:inline-block;
}
.chart-actions {
vertical-align:top;
display:inline-block;
+}
+
+.title {
+ display:block;
}
\ No newline at end of file
diff --git a/js/app.coffee b/js/app.coffee
index 83b8bb0..a0ada12 100644
--- a/js/app.coffee
+++ b/js/app.coffee
@@ -25,35 +25,59 @@ class @Store
graphite: ['carbon.agents.*.avgUpdateTime']
charts: []
+# chart data sources
+@chart_data = []
+
@context = cubism.context()
.serverDelay(0)
.clientDelay(0)
.step(config.chart.step)
.size(config.chart.size)
+chart_container = (charts, template, name='#charts') ->
+ data_id = (chart_data.push charts) - 1
+ container_id = _.uniqueId 'el'
+ container = $($(template).html())
+ .attr('id', container_id)
+ .data('chart', config.charts.length-1)
+ .data('data', data_id)
+ $(name).append(container)
+ container
+
@add_chart = (chart, name='#charts') ->
if chart.type == 'random'
data = random 'random source #'+Math.floor(Math.random()*10000)
else
data = context[chart.type](chart.dsn).metric chart.expression
- container_id = _.uniqueId 'el'
- container = $($('#chart').html())
- .attr('id', container_id)
- .data('chart', config.charts.length-1)
- $(name).append(container)
- d3.select('#' + container_id).call (div) ->
+ container = chart_container data, '#chart'
+
+ d3.select('#' + container.attr('id')).call (div) ->
div.select('.axis').call(context.axis().orient("top"))
- div.datum(data)
div.select('.horizon')
+ div.datum(data)
.call(context.horizon()
.height(config.chart.height)
.extent(config.chart.extent)
.colors(config.chart.colors))
- div.select('.rule').call(context.rule())
- # BREAK YOSELF
- $('.title', container).prepend('
')
+ container.draggable revert: true
+ container.droppable
+ drop: (event, ui) ->
+ flash '
Boom! A comparison chart is born.', 'info'
+ primary = chart_data[$(@).data('data')]
+ secondary = chart_data[$(ui.draggable).data('data')]
+ add_comparison_chart primary, secondary
+
+@add_comparison_chart = (primary, secondary, name='#charts') ->
+ container = chart_container [primary, secondary], '#comp_chart'
+
+ d3.select('#' + container.attr('id')).call (div) ->
+ div.select('.axis').call(context.axis().orient("top"))
+ div.select('.comparison')
+ .datum([primary, secondary])
+ .call(context.comparison()
+ .height(config.chart.height))
$('.create-chart').on 'click', (e) ->
form = $(e.target).parents('form')
@@ -95,6 +119,3 @@ init_form = (name) ->
init_form form for form in ['cube', 'graphite']
add_chart c for c in config.charts
-
-context.on "focus", (i, e) ->
- d3.selectAll(".value").style "right", (if not i? then null else context.size() - i + "px")
diff --git a/js/util.coffee b/js/util.coffee
index 08f5d94..d26e712 100644
--- a/js/util.coffee
+++ b/js/util.coffee
@@ -1,10 +1,16 @@
-@flash = (msg) ->
+@flash = (msg, type='error') ->
# TODO: jadify!
- $('.container-fluid:first').prepend('
+ $('.container-fluid:first').prepend('
- Oh shiii.. '+msg+'
+ '+msg+'
')
+ # auto-remove non-errors
+ if type='info'
+ window.setTimeout () ->
+ $('.alert-info').alert('close')
+ , 4000
+
# pulled from Cubism demo. Tweaked to make horrible assumptions about there being a global @context.
@random = (name) ->
value = 0
diff --git a/package.json b/package.json
index 1806c88..781ce44 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,8 @@
"d3": "2.9.4",
"cubism": "1.2.0",
"jquery": "1.7.2",
- "underscore": "1.3.3"
+ "underscore": "1.3.3",
+ "jquery-ui": "git://github.com/jquery/jquery-ui.git"
},
"bin": {"cubist": "./bin/cubist"},
"engines": {
diff --git a/views/index.jade b/views/index.jade
index aa6e9a2..17f3aeb 100644
--- a/views/index.jade
+++ b/views/index.jade
@@ -31,12 +31,20 @@ block content
#charts
script(type='text/html', id='chart')
- .chart
+ .chart(draggable="true")
.axis
.horizon
.chart-actions
a.btn.btn-mini.close-btn
i.icon-trash
+ script(type='text/html', id='comp_chart')
+ .chart
+ .axis
+ .comparison
+ .chart-actions
+ a.btn.btn-mini.close-btn
+ i.icon-trash
+
block footer
!= js('app')
diff --git a/views/layout.jade b/views/layout.jade
index 3411296..dbad260 100644
--- a/views/layout.jade
+++ b/views/layout.jade
@@ -5,6 +5,7 @@ head
meta(name="viewport", content="width=device-width, initial-scale=1.0")
link(href='css/bootstrap.css', type='text/css', rel='stylesheet')
link(href='css/app.css', type='text/css', rel='stylesheet')
+ link(href='n/jquery-ui/themes/base/jquery.ui.all.css', type='text/css', rel='stylesheet')
block header
body
@@ -16,6 +17,11 @@ body
script(src='n/d3/d3.v2.js')
script(src='n/cubism/cubism.v1.js')
script(src='js/bootstrap.js')
+ script(src="n/jquery-ui/ui/jquery.ui.core.js")
+ script(src="n/jquery-ui/ui/jquery.ui.widget.js")
+ script(src="n/jquery-ui/ui/jquery.ui.mouse.js")
+ script(src="n/jquery-ui/ui/jquery.ui.draggable.js")
+ script(src="n/jquery-ui/ui/jquery.ui.droppable.js")
!= js('util')
block footer