Skip to content

Instantly share code, notes, and snippets.

@ariutta
Last active October 13, 2017 21:42
Show Gist options
  • Save ariutta/1c2c8179467e16823383bbcdb1fcd108 to your computer and use it in GitHub Desktop.
Save ariutta/1c2c8179467e16823383bbcdb1fcd108 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<meta charset="utf-8">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<h1>Pretty TSV Viewer</h1>
<br>
<div id="alert-cannot-update-query-param" class="row">
<div class="alert alert-warning" role="alert">
Warning: URL in address bar is not shareable. (Viewer is inside an <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe">iframe</a>.)
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="input-group">
<input id="source-url-input-field" type="url" class="form-control" placeholder="Enter link to TSV file" aria-label="Enter link to TSV file">
<span class="input-group-btn">
<button id="source-url-input-button" class="btn btn-secondary" type="button">Go</button>
</span>
</div>
</div>
</div>
<br>
<div class="row">
<div id="comments-container" class="col-lg-6">
</div>
</div>
<div class="row">
<div class="col-lg-12">
<table class="table table-sm table-responsive table-striped table-bordered">
<tbody id="pretty-data-table-body"></tbody>
</table>
</div>
</div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var inIframe = window.location !== window.parent.location;
var url = new URL(inIframe ? document.referrer : document.location.href);
var searchParams = new URLSearchParams(url.search);
var sourceParam = searchParams.get("source");
var alertCannotUpdateQueryParam = d3.select("#alert-cannot-update-query-param");
var sourceURLInputField = d3.select("#source-url-input-field");
var sourceURLInputButton = d3.select("#source-url-input-submit");
var commentsContainer = d3.select("#comments-container");
var prettyDataTableBody = d3.select("#pretty-data-table-body");
alertCannotUpdateQueryParam.style("display", "none");
if (!!sourceParam) {
sourceURLInputField.attr("value", sourceParam);
update(sourceParam);
}
function handleSourceURLInputField(a, e) {
var sourceURL = this.value;
if (!sourceURL) {
return;
}
update(sourceURL);
if (inIframe) {
alertCannotUpdateQueryParam.style("display", "flex");
} else {
searchParams.set("source", sourceURL);
history.pushState({
sourceURL: sourceURL
}, "", "?" + searchParams.toString());
}
}
function updateField(d) {
d3.select(this)
.text(d);
}
function updateRow(d) {
var fields = d3.select(this)
.selectAll("td")
.data(d);
fields.each(updateField);
fields.exit()
.remove();
fields.enter()
.append("td")
.each(updateField)
}
function updateComment(d) {
d3.select(this).text(function(d) {return d;});
}
function update(sourceURL) {
var t = d3.transition()
.duration(750);
d3.request(sourceURL)
.mimeType("text/tab-separated-values")
.response(function(xhr) {
var responseText = xhr.responseText;
// TODO don't assume we have headers
var rawHeadersString = (responseText.match(/^#\ ?(.*$)\n^[^#]/gm) || [""])[0];
var headersString = rawHeadersString.replace(/^#\ ?/, "");
var commentsString = (responseText.replace(rawHeadersString, "").match(/^#.*$/gm) || [""]).join("\n").replace(/^#/gm, "");
var rowsString = responseText.match(/^[^#\n\r].+$/gm).join("\n");
return {
commentsString: commentsString,
headersString: headersString,
rowsString: rowsString
};
})
.get(function(parsed) {
var commentsString = parsed.commentsString;
var headersString = parsed.headersString;
var rowsString = parsed.rowsString;
var comments = commentsContainer.selectAll("p").data(commentsString.split("\n"));
comments.each(updateComment);
comments.exit().remove();
comments.enter().append("p").text(function(d) {return d;});
var trs = prettyDataTableBody
.selectAll("tr")
.data(d3.tsvParseRows(headersString + rowsString));
trs.each(updateRow);
trs.exit()
.transition(t)
.attr("y", 60)
.style("fill-opacity", 1e-6)
.remove();
trs.enter()
.append("tr")
.each(updateRow)
});
}
sourceURLInputField.on("change", handleSourceURLInputField);
sourceURLInputButton.on("click", handleSourceURLInputField);
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment