Add edit support.
diff --git a/app.yaml b/app.yaml
index c6d3e07..0063637 100644
--- a/app.yaml
+++ b/app.yaml
@@ -8,6 +8,9 @@
- url: /
static_files: render.html
upload: render.html
+- url: /edit
+ static_files: edit.html
+ upload: edit.html
- url: /help
static_files: help.html
upload: help.html
diff --git a/edit.html b/edit.html
new file mode 100644
index 0000000..c58fd97
--- /dev/null
+++ b/edit.html
@@ -0,0 +1,103 @@
+<!doctype html>
+<html>
+<head>
+ <style>
+ iframe {
+ width: 95%;
+ height: 450px;
+ margin-left: auto;
+ margin-right: auto;
+ margin-bottom: 2em;
+ }
+ input, textarea {
+ display: block;
+ width: 95%;
+ }
+ textarea {
+ height: 8em;
+ }
+ </style>
+ <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
+ <script src="render.js"></script>
+</head>
+
+<body>
+
+<form>
+<input id='url' oninput='updateUrl()'>
+<textarea id='editor' wrap='off' oninput='updateUrl();'></textarea>
+</form>
+
+<div id='viewurl'><a href=''>foo</a></div>
+
+<iframe id='result'></iframe>
+
+<script>
+function argsToForm(args) {
+ var t = '';
+ for (var argi in args.all) {
+ var arg = args.all[argi];
+ var key = arg[0], value = arg[1];
+ if (key && key != 'url') {
+ t += key + '=' + value + '\n';
+ }
+ }
+ $('#editor').text(t);
+}
+
+
+function niceEncode(s) {
+ // we could use encodeURIComponent() here, but it's too fancy. Let's
+ // *only* encode & characters so the resulting URL looks as nice as
+ // possible.
+ return s.replace('&', '%26');
+}
+
+
+function formToUrl() {
+ var dataurl = $('#url').attr('value');
+ var urlbase = window.location.protocol + '//' + window.location.host;
+ var out = ['url=' + niceEncode(dataurl)];
+ var parts = $('#editor').attr('value').trim().split('\n');
+ for (var parti in parts) {
+ var part = parts[parti];
+ if (part) {
+ var bits = trySplitOne(part, '=');
+ if (bits) {
+ out.push(niceEncode(bits[0]) + '=' + niceEncode(bits[1]));
+ } else {
+ out.push(niceEncode(part));
+ }
+ }
+ }
+ return urlbase + '?' + out.join('&');
+}
+
+
+function updateUrl() {
+ var url = formToUrl();
+ console.debug('url is', url);
+ $('#viewurl a').attr('href', url).text(url);
+ if (tmo) {
+ clearTimeout(tmo);
+ }
+ tmo = setTimeout(function() {
+ if (lastloaded != url) {
+ $('iframe#result').attr('src', url + '&editlink=0');
+ lastloaded = url;
+ }
+ }, 1000);
+}
+
+tmo = null;
+lastloaded = null;
+args = parseArgs(window.location.search);
+var exampleurl = (window.location.protocol + '//' + window.location.host +
+ '/example1.json');
+$('#url').attr('value', args.get('url') || exampleurl);
+argsToForm(args);
+updateUrl();
+</script>
+
+</body>
+</html>
diff --git a/render.html b/render.html
index 04e8d64..73dcd89 100644
--- a/render.html
+++ b/render.html
@@ -1,6 +1,16 @@
<!doctype html>
<html>
<head>
+ <style>
+ body {
+ margin: 0px;
+ }
+ div#editmenu {
+ position: absolute;
+ right: 0;
+ z-index: 5;
+ }
+ </style>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script>
@@ -13,10 +23,12 @@
<body>
+<div id='editmenu'><a id='editlink' href='' target='_top'>edit</a></div>
<div id='vizchart'></div>
<div id='viztable'></div>
<script>
+$('#editlink').attr('href', '/edit' + window.location.search);
afterquery.render(window.location.search);
</script>
diff --git a/render.js b/render.js
index 1332974..5abc885 100644
--- a/render.js
+++ b/render.js
@@ -377,7 +377,7 @@
for (var wordi in words) {
for (var coli in row) {
var cell = row[coli];
- if (cell.indexOf(words[wordi]) >= 0) {
+ if (cell.indexOf && cell.indexOf(words[wordi]) >= 0) {
found = 1;
break;
}
@@ -491,12 +491,24 @@
gotdata.table.cols[headeri].id);
}
data = [];
+ var re = /^Date\((\d+),(\d+),(\d+),(\d+),(\d+),(\d+)\)$/;
for (var rowi in gotdata.table.rows) {
var row = gotdata.table.rows[rowi];
var orow = [];
for (var coli in row.c) {
var col = row.c[coli];
- orow.push(col.v);
+ var g;
+ if (!col) {
+ orow.push(null);
+ } else if ((g = re.exec(col.v))) {
+ //TODO(apenwarr): deal with date vs. time columns properly throughout
+ var d = new Date(g[1],g[2],g[3],g[4],g[5],g[6]);
+ orow.push((d.getYear() + 1900) + '-' +
+ (d.getMonth() + 1) + '-' +
+ d.getDate());
+ } else {
+ orow.push(col.v);
+ }
}
data.push(orow);
}
@@ -549,7 +561,7 @@
grid = fillNullsWithZero(grid);
var datatable = dataToGvizTable(grid);
var el = document.getElementById('vizchart');
- var options = {height:400};
+ var options = { height: 400 };
if (args.get('title')) {
options.title = args.get('title');
}
@@ -564,6 +576,8 @@
t = new google.visualization.BarChart(el);
} else if (chartops == 'pie') {
t = new google.visualization.PieChart(el);
+ } else if (chartops == 'candle' || chartops == 'candlestick') {
+ t = new google.visualization.CandlestickChart(el);
} else {
// default to a line chart if unrecognized type
t = new google.visualization.LineChart(el);
@@ -606,6 +620,10 @@
success: function(data, status) { return wrap(gotData, data, status); },
error: function(data, status) { return wrap(gotError, data, status); }
});
+ var editlink = args.get('editlink');
+ if (editlink == 0) {
+ $('#editmenu').hide();
+ }
}