Add sparkline charts, add more help, and add a chart gallery to help.
diff --git a/edit.html b/edit.html
index 25c1ea1..78ec492 100644
--- a/edit.html
+++ b/edit.html
@@ -4,7 +4,7 @@
<style>
iframe {
width: 95%;
- height: 450px;
+ min-height: 450px;
margin-left: auto;
margin-right: auto;
margin-bottom: 2em;
@@ -29,7 +29,7 @@
<div id='viewurl'><a href=''>foo</a></div>
-<iframe id='result'></iframe>
+<iframe id='result' seamless></iframe>
<script>
function argsToForm(args) {
diff --git a/help.md b/help.md
index 5f8eaa4..41f1dd1 100644
--- a/help.md
+++ b/help.md
@@ -18,6 +18,21 @@
margin-right: auto;
margin-bottom: 2em;
}
+.gallery iframe {
+ width: 40%;
+ height: 200px;
+ margin: 1em;
+ border: 0;
+}
+.gallery iframe.spark {
+ display: block;
+ width: 100px;
+ height: 40px;
+ margin-top: 0;
+ margin-bottom: 0;
+ margin-left: auto;
+ margin-right: auto;
+}
u {
color: red;
}
@@ -85,114 +100,124 @@
Available transforms:
- - <b>&limit=<u>n</u></b>
- Discard all data after <u>n</u> rows.
+ - <b>&limit=<u>n</u></b>
+ Discard all data after <u>n</u> rows.
- - <b>&filter=<u>key</u>>=<u>value1</u>,<u>value2</u>,...</b>
- Show only rows where the column named <u>key</u> has a
- value >= <u>value1</u> or <u>value2</u> etc. The
- operator (>= in this example) can be one
- of =, <, >, <=, >=, <>, or !=. If you specify more
- than one value, they
- are combined in an OR configuration (ie. a row matches
- if any of the values match). If you provide
- more than one &filter= clause, they are combined
- successively in an AND configuration (ie. a row matches
- only if all the filters are true).
+ - <b>&filter=<u>key</u>>=<u>value1</u>,<u>value2</u>,...</b>
+ Show only rows where the column named <u>key</u> has a
+ value >= <u>value1</u> or <u>value2</u> etc. The
+ operator (>= in this example) can be one
+ of =, <, >, <=, >=, <>, or !=. If you specify more
+ than one value, they
+ are combined in an OR configuration (ie. a row matches
+ if any of the values match). If you provide
+ more than one &filter= clause, they are combined
+ successively in an AND configuration (ie. a row matches
+ only if all the filters are true).
- - <b>&q=<u>value1</u>,<u>value2</u>,...</b>
- Show only rows where any of the columns contain the
- substring <u>value1</u> or <u>value2</u> etc. If more
- than one value is specified, they are combined in an OR
- configuration. If you provide more than one &q= clause,
- they are combined successively in an AND configuration.
+ - <b>&q=<u>value1</u>,<u>value2</u>,...</b>
+ Show only rows where any of the columns contain the
+ substring <u>value1</u> or <u>value2</u> etc. If more
+ than one value is specified, they are combined in an OR
+ configuration. If you provide more than one &q= clause,
+ they are combined successively in an AND configuration.
- - <b>&order=<u>[-]key1</u>,<u>[-]key2</u></b>
- Sort the table in order of <u>key1</u> and then (if key1
- is the same) by <u>key2</u> etc. If a key starts with
- '-' that means to sort that key in descending order
- (largest to smallest).
+ - <b>&order=<u>[-]key1</u>,<u>[-]key2</u></b>
+ Sort the table in order of <u>key1</u> and then (if key1
+ is the same) by <u>key2</u> etc. If a key starts with
+ '-' that means to sort that key in descending order
+ (largest to smallest).
- - <b>&extract_regexp=<u>key</u>=<u>regexp(match)regexp</u></b>
- Search for the given regular expression in each row in
- the column named <u>key</u>. If it's found, replace the
- column with the substring in the <u>(match)</u> part of
- the regexp. For example,
- `&extract_regexp=ver=version-(.*)` would replace a
- string `version-25.4` in column `ver` with the string `25.4`.
+ - <b>&extract_regexp=<u>key</u>=<u>regexp(match)regexp</u></b>
+ Search for the given regular expression in each row in
+ the column named <u>key</u>. If it's found, replace the
+ column with the substring in the <u>(match)</u> part of
+ the regexp. For example,
+ `&extract_regexp=ver=version-(.*)` would replace a
+ string `version-25.4` in column `ver` with the string `25.4`.
- - <b>&group=<u>key1</u>,<u>key2</u>,...;<u>val1</u>,<u>val2</u>,...</b>
- Summarize the table data by summing and counting. This
- operation works like a simplified version of SQL's
- "group by" clause. In the resulting output, the order
- of the columns will be
- <u>key1</u>,<u>key2</u>,...,<u>val1</u>,<u>val2</u>...
- and there will only be at most one row with any
- particular combination of <u>key1</u>,<u>key2</u>,...
- fields. The <u>val</u> columns will be summed (if they
- were already numerical) or counted (if they were
- non-numeric).
+ - <b>&group=<u>key1</u>,<u>key2</u>,...;<u>val1</u>,<u>val2</u>,...</b>
+ Summarize the table data by summing and counting. This
+ operation works like a simplified version of SQL's
+ "group by" clause. In the resulting output, the order
+ of the columns will be
+ <u>key1</u>,<u>key2</u>,...,<u>val1</u>,<u>val2</u>...
+ and there will only be at most one row with any
+ particular combination of <u>key1</u>,<u>key2</u>,...
+ fields. The <u>val</u> columns will be summed (if they
+ were already numerical) or counted (if they were
+ non-numeric).
+
+ A clause like `&group=a,b;x,y` (if x is a string and y
+ is a number) would be equivalent to this in SQL: `select
+ a, b, count(x) x, sum(y) y from MyTable group by a, b`
- A clause like `&group=a,b;x,y` (if x is a string and y
- is a number) would be equivalent to this in SQL: `select
- a, b, count(x) x, sum(y) y from MyTable group by a, b`
+ If you apply multiple <b>&group=</b> clauses, it works like
+ using multiple nested subqueries in SQL. (That is, the
+ output of one <b>&group=</b> clause becomes the MyTable
+ of the next one.)
- If you apply multiple <b>&group=</b> clauses, it works like
- using multiple nested subqueries in SQL. (That is, the
- output of one <b>&group=</b> clause becomes the MyTable
- of the next one.)
+ If you leave out the ';' and the <u>val</u> column
+ names, the default is to automatically include all
+ columns other than the <u>key</u> columns.
- If you leave out the ';' and the <u>val</u> column
- names, the default is to automatically include all
- columns other than the <u>key</u> columns.
-
- If you include the ';' but leave out the <u>val</u>
- column names, that means you don't want any value
- columns (so only the key fields will be included, and
- nothing will be summed or counted at that step). So
- `&group=a,b;` (with a trailing semicolon) is equivalent
- to this in SQL: `select a, b from MyTable group by a,
- b`.
-
- - <b>&pivot=<u>rowkeys...</u>;<u>colkeys...</u>;<u>valkeys...</u></b>
- A <b>&pivot=</b> clause works like a <b>&group=</b>
- clause, but creates a
- [pivot table](http://en.wikipedia.org/wiki/Pivot_table).
- Pivot tables are a bit complicated; the easiest way to
- learn about them is to play with an example.
- [Here's one to start
- with](/?url=example1.json&group=date,flag,ver,serial;&pivot=date,ver;flag;serial).
-
- The simplest way to think of a pivot table is like this:
- the values originally in the columns named by <u>rowkeys</u>
- end up down the left of the output table. The values
- originally in the columns named by <u>colkeys</u> end up
- as headings across the top of the output table. The values
- originally in the columns named by <u>valkeys</u> end up
- as values in the body section of the output table. A
- pivot table is very handy when you have raw data in
- SQL-like format and you want to rearrange it to be
- suitable for charting (where each line in a line chart,
- say, is usually one column of the table).
-
- If the <u>rowkeys</u> section is empty, the output will
- have exactly one row (with all the value fields counted
- or summed into that one row). If the <u>colkeys</u>
- section is empty, the <b>&pivot=</b> operation is
- essentially equivalent to a
- <b>&group=<u>rowkeys...</u>;<u>valkeys...</u></b> operation.
- If the <u>valkeys</u> section is empty, there are no
- values used to calculate the table body, so it is
- equivalent to an <b>&group=<u>rowkeys...</u>;</b>
- operation.
+ If you include the ';' but leave out the <u>val</u>
+ column names, that means you don't want any value
+ columns (so only the key fields will be included, and
+ nothing will be summed or counted at that step). So
+ `&group=a,b;` (with a trailing semicolon) is equivalent
+ to this in SQL: `select a, b from MyTable group by a,
+ b`.
- - <b>&chart=<u>charttype</u></b>
- Instead of showing a table of values, show a chart. The
- available <u>charttypes</u> are currently: stacked (a
- stacked area chart), line, column, bar, pie.
+ - <b>&treegroup=<u>key1</u>,<u>key2</u>,...;[<u>val1</u>,[<u>val2</u>]]</b>
+ Like <b>&group=</b>, but produces an output table arranged hierarchically
+ by each <u>key1</u>..<u>keyn</u>, so you can drill down. There can be
+ zero, one, or two <u>val</u> columns; the first value is the size of
+ each box in the tree view (if omitted, they are all the same size), and
+ the second value is the colour of each box (if omitted, the colour varies
+ with the size). <b>&treegroup=</b> isn't really useful unless you also
+ use <b>&chart=tree</b>.
+
+ - <b>&pivot=<u>rowkeys...</u>;<u>colkeys...</u>;<u>valkeys...</u></b>
+ A <b>&pivot=</b> clause works like a <b>&group=</b>
+ clause, but creates a
+ [pivot table](http://en.wikipedia.org/wiki/Pivot_table).
+ Pivot tables are a bit complicated; the easiest way to
+ learn about them is to play with an example.
+ [Here's one to start
+ with](/?url=example1.json&group=date,flag,ver,serial;&pivot=date,ver;flag;serial).
+
+ The simplest way to think of a pivot table is like this:
+ the values originally in the columns named by <u>rowkeys</u>
+ end up down the left of the output table. The values
+ originally in the columns named by <u>colkeys</u> end up
+ as headings across the top of the output table. The values
+ originally in the columns named by <u>valkeys</u> end up
+ as values in the body section of the output table. A
+ pivot table is very handy when you have raw data in
+ SQL-like format and you want to rearrange it to be
+ suitable for charting (where each line in a line chart,
+ say, is usually one column of the table).
+
+ If the <u>rowkeys</u> section is empty, the output will
+ have exactly one row (with all the value fields counted
+ or summed into that one row). If the <u>colkeys</u>
+ section is empty, the <b>&pivot=</b> operation is
+ essentially equivalent to a
+ <b>&group=<u>rowkeys...</u>;<u>valkeys...</u></b> operation.
+ If the <u>valkeys</u> section is empty, there are no
+ values used to calculate the table body, so it is
+ equivalent to an <b>&group=<u>rowkeys...</u>;</b>
+ operation.
- - <b>&title=<u>title</u></b>
- Add a title to the chart.
+ - <b>&chart=<u>charttype</u></b>
+ Instead of showing a table of values, show a chart. The
+ available <u>charttypes</u> are currently: stacked (a
+ stacked area chart), line, spark, column, bar, pie,
+ tree (see <b>treegroup</b>), candle, timeline, dygraph, dygraph+errors.
+
+ - <b>&title=<u>title</u></b>
+ Add a title to the chart.
## Example 1
@@ -203,44 +228,41 @@
<iframe src="example2.json">
</iframe>
-Afterquery can render it as a table like this
-[(link)](/?url=example2.json):
+(Tip: in the tables and charts below, click the "Edit" link in the
+upper-right corner to see how the query works.)
+
+Afterquery can render it as a table like this:
<iframe src="/?url=example2.json">
</iframe>
-Or pre-sort the table for you like this
-[(link)](/?url=example2.json&order=state,-date):
+Or pre-sort the table for you like this:
<iframe src="/?url=example2.json&order=state,-date">
</iframe>
-Or filter it by date [(link)](/?url=example2.json&filter=date<2012-11-10&filter=date>=2012-11-01):
+Or filter it by date:
<iframe src="/?url=example2.json&filter=date<2012-11-10&filter=date>=2012-11-01">
</iframe>
-Or summarize the results (like a "group by" in SQL)
-[(link)](/?url=example2.json&group=date):
+Or summarize the results (like a "group by" in SQL):
<iframe src="/?url=example2.json&group=date">
</iframe>
-Or summarize and display only a subset of columns
-[(link)](/?url=example2.json&group=date;NumDevices):
+Or summarize and display only a subset of columns:
<iframe src="/?url=example2.json&group=date;NumDevices">
</iframe>
Or do a [pivot table](http://en.wikipedia.org/wiki/Pivot_table)
-(converting rows into columns)
-[(link)](/?url=example2.json&pivot=date;state;NumDevices):
+(converting rows into columns):
<iframe src="/?url=example2.json&pivot=date;state;NumDevices">
</iframe>
Or filter, then pivot, and then make a chart!
-[(link)](/?url=example2.json&order=date,state&filter=date>=2012-11-01&filter=date<2012-11-14&pivot=date;state;NumDevices&chart=stacked&title=Devices Rebooted/Upgraded by Date)
<iframe
src="/?url=example2.json&order=date,state&filter=date>=2012-11-01&filter=date<2012-11-14&pivot=date;state;NumDevices&chart=stacked&title=Devices Rebooted/Upgraded by Date">
@@ -249,7 +271,7 @@
## Example 2
-Here's another dataset [(link)](/?url=example1.json):
+Here's another dataset:
<iframe src="/?url=example1.json">
</iframe>
@@ -263,45 +285,63 @@
Hmm, those version numbers are ugly because some of them
have extra debug information after them. Let's trim it
-out using a regex <a href="/?url=/example1.json&extract_regexp=ver=(v)ersion-([^-.]*)&group=ver,serial;&group=ver;serial&order=ver">(link)</a>:
+out using a regex:
<iframe
src="/?url=example1.json&extract_regexp=ver=(v)ersion-([^-.]*)&group=ver,serial;&group=ver;serial&order=ver">
</iframe>
And make a pivot table to easily show the pattern over
-time <a href="/?url=example1.json&extract_regexp=ver=(v)ersion-([^-.]*)&group=date,ver,serial;&order=date,ver&pivot=date;ver;serial">(link)</a>:
+time:
<iframe
src="/?url=example1.json&extract_regexp=ver=(v)ersion-([^-.]*)&group=date,ver,serial;&order=date,ver&pivot=date;ver;serial">
</iframe>
-Trim out some outliers <a href="/?url=example1.json&extract_regexp=ver=(v)ersion-([^-.]*)&group=date,ver,serial;&order=date,ver&group=date,ver;serial&filter=serial>10&filter=ver>&pivot=date;ver;serial">(link)</a>:
+Trim out some outliers:
<iframe
src="/?url=example1.json&extract_regexp=ver=(v)ersion-([^-.]*)&group=date,ver,serial;&order=date,ver&group=date,ver;serial&filter=serial>10&filter=ver>&pivot=date;ver;serial">
</iframe>
-And graph it <a href="/?url=example1.json&extract_regexp=ver=(v)ersion-([^-.]*)&group=date,ver,serial;&order=date,ver&group=date,ver;serial&filter=serial>10&filter=ver>&pivot=date;ver;serial&chart=stacked">(link)</a>:
+And graph it:
<iframe
src="/?url=example1.json&extract_regexp=ver=(v)ersion-([^-.]*)&group=date,ver,serial;&order=date,ver&group=date,ver;serial&filter=serial>10&filter=ver>&pivot=date;ver;serial&chart=stacked">
</iframe>
-Or graph a subset of the data <a href="/?url=example1.json&extract_regexp=ver=(v)ersion-([^-.]*)&group=date,ver,serial;&order=date,ver&q=v35,v37,v36&pivot=date;ver;serial&chart=line">(link)</a>:
+Or graph a subset of the data:
<iframe
src="/?url=example1.json&extract_regexp=ver=(v)ersion-([^-.]*)&group=date,ver,serial;&order=date,ver&q=v35,v37,v36&pivot=date;ver;serial&chart=line">
</iframe>
-Or maybe show the top 4 versions <a
-href="/?url=example1.json&group=ver,serial;&filter=ver>&order=ver&group=ver;serial&order=-serial&limit=4&chart=pie">(link)</a>:
+Or maybe show the top 4 versions:
<iframe
src="/?url=example1.json&group=ver,serial;&filter=ver>&order=ver&group=ver;serial&order=-serial&limit=4&chart=pie">
</iframe>
+## Chart gallery
+
+<div class="gallery">
+<iframe src="/?url=example1.json&extract_regexp=ver=(v)ersion-([^-.]*)&group=date,ver,serial;&order=date,ver&group=date,ver;serial&filter=serial>10&filter=ver>&pivot=date;ver;serial&chart=stacked"></iframe>
+<iframe src="/?url=example1.json&extract_regexp=ver=(v)ersion-([^-.]*)&group=date,ver,serial;&order=date,ver&group=date,ver;serial&filter=serial>10&filter=ver>&pivot=date;ver;serial&chart=line"></iframe>
+<iframe src="/?url=example1.json&group=ver,serial;&filter=ver>&order=ver&group=ver;serial&order=-serial&limit=4&chart=column"></iframe>
+<iframe src="/?url=example1.json&group=ver,serial;&filter=ver>&order=ver&group=ver;serial&order=-serial&limit=4&chart=bar"></iframe>
+<iframe src="/?url=example1.json&group=ver,serial;&filter=ver>&order=ver&group=ver;serial&order=-serial&limit=4&chart=pie"></iframe>
+<iframe src="/?url=example1.json&group=flag,ver,serial;&treegroup=flag,ver;serial&chart=tree"></iframe>
+<iframe src="/?url=example2.json&pivot=date;state;NumDevices&group=date,upgraded,rebooted,rebooted,idle&chart=candle"></iframe>
+<iframe src="/?url=example2.json&pivot=date;state;NumDevices&chart=timeline"></iframe>
+<iframe src="/?url=example2.json&pivot=date;state;NumDevices&chart=dygraph"></iframe>
+<iframe src="/?url=example2.json&pivot=date;state;NumDevices&group=date,idle,rebooted,rebooted,upgraded&chart=dygraph+errors"></iframe>
+<iframe class='spark' src="/?url=example1.json&filter=ver=oldversion-1&group=date,ver,serial;&pivot=date;ver;serial&chart=spark"></iframe>
+<iframe class='spark' src="/?url=example1.json&filter=ver=oldversion-17&group=date,ver,serial;&pivot=date;ver;serial&chart=spark"></iframe>
+<iframe class='spark' src="/?url=example1.json&filter=ver=oldversion-19&group=date,ver,serial;&pivot=date;ver;serial&chart=spark"></iframe>
+</div>
+
+
## Where can I get a jsonp data source?
There are lots of them out on the web. If your favourite
diff --git a/render.html b/render.html
index 6f63823..669ae78 100644
--- a/render.html
+++ b/render.html
@@ -10,6 +10,10 @@
right: 0;
z-index: 5;
background: #eee;
+ visibility: hidden;
+ }
+ body:hover div#editmenu {
+ visibility: visible;
}
div#editmenu a {
text-decoration: none;
diff --git a/render.js b/render.js
index 39a13a4..196f3c0 100644
--- a/render.js
+++ b/render.js
@@ -703,7 +703,7 @@
function fillNullsWithZero(grid) {
for (var rowi in grid.data) {
- row = grid.data[rowi];
+ var row = grid.data[rowi];
for (var coli in row) {
if (grid.types[coli] === T_NUM && row[coli] == undefined) {
row[coli] = 0;
@@ -832,9 +832,10 @@
enqueue('gentable', function() {
if (chartops) {
- //TODO(apenwarr): something needed this, but I no longer remember what.
- // At least line and dygraph charts are seemingly fine without it.
- //grid = fillNullsWithZero(grid);
+ if (chartops == 'stacked' || chartops == 'stackedarea') {
+ // Some charts react badly to missing values, so fill them in.
+ grid = fillNullsWithZero(grid);
+ }
var el = document.getElementById('vizchart');
$(el).height(window.innerHeight)
.width(trace ? window.innerWidth - 40 : window.innerWidth);
@@ -850,6 +851,23 @@
t = new google.visualization.BarChart(el);
} else if (chartops == 'line') {
t = new google.visualization.LineChart(el);
+ } else if (chartops == 'spark') {
+ // sparkline chart: get rid of everything but the data series.
+ // Looks best when small.
+ options.hAxis = {};
+ options.hAxis.baselineColor = 'none';
+ options.hAxis.textPosition = 'none';
+ options.hAxis.gridlines = {};
+ options.hAxis.gridlines.color = 'none';
+ options.vAxis = {};
+ options.vAxis.baselineColor = 'none';
+ options.vAxis.textPosition = 'none';
+ options.vAxis.gridlines = {};
+ options.vAxis.gridlines.color = 'none';
+ options.theme = 'maximized';
+ options.legend = {};
+ options.legend.position = 'none';
+ t = new google.visualization.LineChart(el);
} else if (chartops == 'pie') {
t = new google.visualization.PieChart(el);
} else if (chartops == 'tree') {
@@ -939,6 +957,9 @@
try {
return func.apply(null, pre_args.concat([].slice.call(arguments)));
} catch (e) {
+ $('#vizchart').hide();
+ $('#viztable').hide();
+ $('.vizstep').show();
err(e);
err("<p><a href='/help'>here's the documentation</a>");
throw e;