Last active
October 13, 2017 21:42
-
-
Save ariutta/1c2c8179467e16823383bbcdb1fcd108 to your computer and use it in GitHub Desktop.
Pretty viewer for TSV files -- view live demo at https://cdn.rawgit.com/ariutta/1c2c8179467e16823383bbcdb1fcd108/raw/9cb860d90bab61de8d6ae45a926df53ee1525956/pretty-tsv-viewer.html?source=https%3A%2F%2Frawgit.com%2Fbridgedb%2FBridgeDb%2Fmaster%2Forg.bridgedb.bio%2Fresources%2Forg%2Fbridgedb%2Fbio%2Fdatasources_headers.txt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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