Skip to content

Instantly share code, notes, and snippets.

@dhoboy
Last active August 29, 2015 14:20
Show Gist options
  • Save dhoboy/1ac430a7ca883e7a8c09 to your computer and use it in GitHub Desktop.
Save dhoboy/1ac430a7ca883e7a8c09 to your computer and use it in GitHub Desktop.
Sortable, Filterable Table

Sortable, Filterable table made with D3.js See the React.js version here

Note: This D3 version of the table doesn't clear the search text onBlur. This allows you to sort the search results.

[
{
"thumb_url_default":"https://yt3.ggpht.com/-T0H7xR-9iA8/AAAAAAAAAAI/AAAAAAAAAAA/VA9CSBc5Q8A/s88-c-k-no/photo.jpg",
"views":"105689500",
"created_on":"2011-02-17T13:38:27Z",
"title":"psychicpebbles",
"id":"UC--BMyA2X4a9PGAo3lTuopg"
},
{
"thumb_url_default":"https://yt3.ggpht.com/-Aqz_Yc964cU/AAAAAAAAAAI/AAAAAAAAAAA/0SkTB3eIHL8/s88-c-k-no/photo.jpg",
"views":"229121344",
"created_on":"2007-08-18T14:57:17Z",
"title":"JustKiddingFilms",
"id":"UC-A4oZF4AlOEdlyZWBCI0cQ"
},
{
"thumb_url_default":"https://yt3.ggpht.com/-0b9t8DHdd-8/AAAAAAAAAAI/AAAAAAAAAAA/5xlL-R1Id1M/s88-c-k-no/photo.jpg",
"views":"25690295",
"created_on":"2006-07-05T08:01:16Z",
"title":"Blue Table Painting",
"id":"UC-aSLyvFLGEmNFcGomzL47w"
},
{
"thumb_url_default":"https://yt3.ggpht.com/-_9beDwBjMJ4/AAAAAAAAAAI/AAAAAAAAAAA/Jv6rGoAyoz0/s88-c-k-no/photo.jpg",
"views":18483830,
"created_on":"2012-03-02T15:51:06Z",
"title":"dillongoo",
"id":"UC-B06UJxJ20HYv15lzrm9mA"
},
{
"thumb_url_default":"https://yt3.ggpht.com/-JqTiqHU5_Hs/AAAAAAAAAAI/AAAAAAAAAAA/oGryI3Ig5U4/s88-c-k-no/photo.jpg",
"views":197190215,
"created_on":"2008-06-18T06:44:13Z",
"title":"MoneySavingVideos",
"id":"UC-dch3BP4gKHC4cec0PU1PA"
},
{
"thumb_url_default":"https://yt3.ggpht.com/-o3Zx-Zz8bwA/AAAAAAAAAAI/AAAAAAAAAAA/ZHRS7TqQd8U/s88-c-k-no/photo.jpg",
"views":430715,
"created_on":"2006-08-03T11:22:11Z",
"title":"SPLURT TV",
"id":"UC-eeciTxV2kfY6teG3Hu_dQ"
},
{
"thumb_url_default":"https://yt3.ggpht.com/-q03QTYLnRmM/AAAAAAAAAAI/AAAAAAAAAAA/6m7QYo0gRwA/s88-c-k-no/photo.jpg",
"views":790458,
"created_on":"2009-08-06T12:45:13Z",
"title":"Adozie",
"id":"UC-jDxvNUzbuFqDzRpAPbFYw"
},
{
"thumb_url_default":"https://yt3.ggpht.com/-HozDGGP43lY/AAAAAAAAAAI/AAAAAAAAAAA/IKNqSHJZ4fw/s88-c-k-no/photo.jpg",
"views":16371,
"created_on":"2011-09-11T12:04:08Z",
"title":"TheNoahHunt",
"id":"UC-m0-lV8U6imr5zC-9RMlAA"
},
{
"thumb_url_default":"https://yt3.ggpht.com/-nheWDZWkuaY/AAAAAAAAAAI/AAAAAAAAAAA/UUarZMj10wk/s88-c-k-no/photo.jpg",
"views":7561518,
"created_on":"2008-01-22T01:00:40Z",
"title":"Karliene",
"id":"UC-QCyIGEY6DzNyQOnyxIaEg"
},
{
"thumb_url_default":"https://yt3.ggpht.com/-QgxITA1sSog/AAAAAAAAAAI/AAAAAAAAAAA/-fpVz4fdImg/s88-c-k-no/photo.jpg",
"views":216964959,
"created_on":"2013-08-13T02:42:23Z",
"title":"RomanAtwoodVlogs",
"id":"UC-SV8-bUJfXjrRMnp7F8Wzw"
},
{
"thumb_url_default":"https://yt3.ggpht.com/-qaWKaxiiuDc/AAAAAAAAAAI/AAAAAAAAAAA/0EoZzkJEUMc/s88-c-k-no/photo.jpg",
"views":460971,
"created_on":"2011-05-09T03:43:36Z",
"title":"Donovan Dustin",
"id":"UC-uzRXWfXKZWHDvTCAQRfWA"
},
{
"thumb_url_default":"https://yt3.ggpht.com/-xSoc6icoyM0/AAAAAAAAAAI/AAAAAAAAAAA/WzMp9TXtYek/s88-c-k-no/photo.jpg",
"views":55921,
"created_on":"2013-11-27T03:22:11Z",
"title":"Tab's Gaming Pad",
"id":"UC-vkS8J9ovJFA7krXkbA90w"
},
{
"thumb_url_default":"https://yt3.ggpht.com/-qrD04Q_Asr0/AAAAAAAAAAI/AAAAAAAAAAA/IQmGgs75q7o/s88-c-k-no/photo.jpg",
"views":290726,
"created_on":"2011-10-12T03:13:19Z",
"title":"planethumanofficial",
"id":"UC-WMky94nwO2V0j3yWzJJ5g"
},
{
"thumb_url_default":"https://yt3.ggpht.com/-X_LNAKWmetg/AAAAAAAAAAI/AAAAAAAAAAA/dPPK1tgp6H8/s88-c-k-no/photo.jpg",
"views":1786129,
"created_on":"2010-01-24T19:43:24Z",
"title":"vedrim",
"id":"UC-zKPn4jKeg_sEYjoOFe13w"
},
{
"thumb_url_default":"https://yt3.ggpht.com/-Xjk-VC5VItM/AAAAAAAAAAI/AAAAAAAAAAA/rrBWC34Z7iA/s88-c-k-no/photo.jpg",
"views":7086046,
"created_on":"2008-06-19T03:52:00Z",
"title":"ABCD123toast",
"id":"UC04ytXliFP2zZpyFiZYvLQA"
},
{
"thumb_url_default":"https://yt3.ggpht.com/-i65yDNbvKjk/AAAAAAAAAAI/AAAAAAAAAAA/typlIFS918Q/s88-c-k-no/photo.jpg",
"views":23180487,
"created_on":"2009-09-12T11:04:24Z",
"title":"MattKeck",
"id":"UC04ZW2FS8RfUmJEa39_-JoA"
},
{
"thumb_url_default":"https://yt3.ggpht.com/-aXujGP8Dyzs/AAAAAAAAAAI/AAAAAAAAAAA/dSDxODBTGfI/s88-c-k-no/photo.jpg",
"views":666872,
"created_on":"2012-02-28T00:49:50Z",
"title":"Jesse Royal",
"id":"UC0CohPJt1XAP0sAKazrsxIQ"
},
{
"thumb_url_default":"https://yt3.ggpht.com/-dQFcuLsbK20/AAAAAAAAAAI/AAAAAAAAAAA/r9hmz7DWVSg/s88-c-k-no/photo.jpg",
"views":294623,
"created_on":"2011-05-03T05:07:35Z",
"title":"Corrie Hegwood",
"id":"UC0cuBvfn-k0mFkPI9ZeF5vA"
},
{
"thumb_url_default":"https://yt3.ggpht.com/-A_J7gPmZf-Q/AAAAAAAAAAI/AAAAAAAAAAA/n8yz1SmTU_k/s88-c-k-no/photo.jpg",
"views":643218,
"created_on":"2011-02-04T03:04:04Z",
"title":"laughspin",
"id":"UC0D3tWXruCZrBZqw0ojzqJQ"
},
{
"thumb_url_default":"https://yt3.ggpht.com/-MdLmmFh3qjo/AAAAAAAAAAI/AAAAAAAAAAA/lcGE1l_gam4/s88-c-k-no/photo.jpg",
"views":3106606,
"created_on":"2009-06-11T04:06:53Z",
"title":"Felicia Ricci",
"id":"UC0KJrVR7lOqDTkH2S2tjo5Q"
}
]
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
background-color: #d1e5f0;
font: 14px sans-serif;
}
#container {
width: 100%;
height: 100%;
position: relative;
}
#title {
font: 26px sans-serif;
position: absolute;
top: -40px;
left: 450px;
}
#FilterableTable {
width: 100%;
height: 100%;
position: absolute;
top: 40px;
left: 20px;
}
.SearchBar {
display: inline;
position: relative;
left: 1%;
}
.SearchBar input {
position: relative;
left: 2%;
}
table {
position: absolute;
top: 40px;
left: 20px;
border-collapse: collapse;
margin-bottom: 20px;
}
table a:link, a:visited { text-decoration: none; }
table a:hover, a:active { text-decoration: underline; }
table, th, td { border: 1px solid black; }
td, th {
padding: 5px;
text-align: center;
height: 20px;
}
th {
background-color: #4393c3;
color: #d9f0a3;
}
td { background-color: #92c5de; }
tr:hover td { background-color: #edf8b1; }
</style>
<body>
<script src="http://d3js.org/d3.v3.js"></script>
<script>
var column_names = ["Title","Views","Created On","URL"];
var clicks = {title: 0, views: 0, created_on: 0, url: 0};
// draw the table
d3.select("body").append("div")
.attr("id", "container")
d3.select("#container").append("div")
.attr("id", "FilterableTable");
d3.select("#FilterableTable").append("h1")
.attr("id", "title")
.text("My Youtube Channels")
d3.select("#FilterableTable").append("div")
.attr("class", "SearchBar")
.append("p")
.attr("class", "SearchBar")
.text("Search By Title:");
d3.select(".SearchBar")
.append("input")
.attr("class", "SearchBar")
.attr("id", "search")
.attr("type", "text")
.attr("placeholder", "Search...");
var table = d3.select("#FilterableTable").append("table");
table.append("thead").append("tr");
var headers = table.select("tr").selectAll("th")
.data(column_names)
.enter()
.append("th")
.text(function(d) { return d; });
var rows, row_entries, row_entries_no_anchor, row_entries_with_anchor;
d3.json("data.json", function(data) { // loading data from server
// draw table body with rows
table.append("tbody")
// data bind
rows = table.select("tbody").selectAll("tr")
.data(data, function(d){ return d.id; });
// enter the rows
rows.enter()
.append("tr")
// enter td's in each row
row_entries = rows.selectAll("td")
.data(function(d) {
var arr = [];
for (var k in d) {
if (d.hasOwnProperty(k)) {
arr.push(d[k]);
}
}
return [arr[3],arr[1],arr[2],arr[0]];
})
.enter()
.append("td")
// draw row entries with no anchor
row_entries_no_anchor = row_entries.filter(function(d) {
return (/https?:\/\//.test(d) == false)
})
row_entries_no_anchor.text(function(d) { return d; })
// draw row entries with anchor
row_entries_with_anchor = row_entries.filter(function(d) {
return (/https?:\/\//.test(d) == true)
})
row_entries_with_anchor
.append("a")
.attr("href", function(d) { return d; })
.attr("target", "_blank")
.text(function(d) { return d; })
/** search functionality **/
d3.select("#search")
.on("keyup", function() { // filter according to key pressed
var searched_data = data,
text = this.value.trim();
var searchResults = searched_data.map(function(r) {
var regex = new RegExp("^" + text + ".*", "i");
if (regex.test(r.title)) { // if there are any results
return regex.exec(r.title)[0]; // return them to searchResults
}
})
// filter blank entries from searchResults
searchResults = searchResults.filter(function(r){
return r != undefined;
})
// filter dataset with searchResults
searched_data = searchResults.map(function(r) {
return data.filter(function(p) {
return p.title.indexOf(r) != -1;
})
})
// flatten array
searched_data = [].concat.apply([], searched_data)
// data bind with new data
rows = table.select("tbody").selectAll("tr")
.data(searched_data, function(d){ return d.id; })
// enter the rows
rows.enter()
.append("tr");
// enter td's in each row
row_entries = rows.selectAll("td")
.data(function(d) {
var arr = [];
for (var k in d) {
if (d.hasOwnProperty(k)) {
arr.push(d[k]);
}
}
return [arr[3],arr[1],arr[2],arr[0]];
})
.enter()
.append("td")
// draw row entries with no anchor
row_entries_no_anchor = row_entries.filter(function(d) {
return (/https?:\/\//.test(d) == false)
})
row_entries_no_anchor.text(function(d) { return d; })
// draw row entries with anchor
row_entries_with_anchor = row_entries.filter(function(d) {
return (/https?:\/\//.test(d) == true)
})
row_entries_with_anchor
.append("a")
.attr("href", function(d) { return d; })
.attr("target", "_blank")
.text(function(d) { return d; })
// exit
rows.exit().remove();
})
/** sort functionality **/
headers
.on("click", function(d) {
if (d == "Title") {
clicks.title++;
// even number of clicks
if (clicks.title % 2 == 0) {
// sort ascending: alphabetically
rows.sort(function(a,b) {
if (a.title.toUpperCase() < b.title.toUpperCase()) {
return -1;
} else if (a.title.toUpperCase() > b.title.toUpperCase()) {
return 1;
} else {
return 0;
}
});
// odd number of clicks
} else if (clicks.title % 2 != 0) {
// sort descending: alphabetically
rows.sort(function(a,b) {
if (a.title.toUpperCase() < b.title.toUpperCase()) {
return 1;
} else if (a.title.toUpperCase() > b.title.toUpperCase()) {
return -1;
} else {
return 0;
}
});
}
}
if (d == "Views") {
clicks.views++;
// even number of clicks
if (clicks.views % 2 == 0) {
// sort ascending: numerically
rows.sort(function(a,b) {
if (+a.views < +b.views) {
return -1;
} else if (+a.views > +b.views) {
return 1;
} else {
return 0;
}
});
// odd number of clicks
} else if (clicks.views % 2 != 0) {
// sort descending: numerically
rows.sort(function(a,b) {
if (+a.views < +b.views) {
return 1;
} else if (+a.views > +b.views) {
return -1;
} else {
return 0;
}
});
}
}
if (d == "Created On") {
clicks.created_on++;
if (clicks.created_on % 2 == 0) {
// sort ascending: by date
rows.sort(function(a,b) {
// grep date and time, split them apart, make Date objects for comparing
var date = /[\d]{4}-[\d]{2}-[\d]{2}/.exec(a.created_on);
date = date[0].split("-");
var time = /[\d]{2}:[\d]{2}:[\d]{2}/.exec(a.created_on);
time = time[0].split(":");
var a_date_obj = new Date(+date[0],(+date[1]-1),+date[2],+time[0],+time[1],+time[2]);
date = /[\d]{4}-[\d]{2}-[\d]{2}/.exec(b.created_on);
date = date[0].split("-");
time = /[\d]{2}:[\d]{2}:[\d]{2}/.exec(b.created_on);
time = time[0].split(":");
var b_date_obj = new Date(+date[0],(+date[1]-1),+date[2],+time[0],+time[1],+time[2]);
if (a_date_obj < b_date_obj) {
return -1;
} else if (a_date_obj > b_date_obj) {
return 1;
} else {
return 0;
}
});
// odd number of clicks
} else if (clicks.created_on % 2 != 0) {
// sort descending: by date
rows.sort(function(a,b) {
// grep date and time, split them apart, make Date objects for comparing
var date = /[\d]{4}-[\d]{2}-[\d]{2}/.exec(a.created_on);
date = date[0].split("-");
var time = /[\d]{2}:[\d]{2}:[\d]{2}/.exec(a.created_on);
time = time[0].split(":");
var a_date_obj = new Date(+date[0],(+date[1]-1),+date[2],+time[0],+time[1],+time[2]);
date = /[\d]{4}-[\d]{2}-[\d]{2}/.exec(b.created_on);
date = date[0].split("-");
time = /[\d]{2}:[\d]{2}:[\d]{2}/.exec(b.created_on);
time = time[0].split(":");
var b_date_obj = new Date(+date[0],(+date[1]-1),+date[2],+time[0],+time[1],+time[2]);
if (a_date_obj < b_date_obj) {
return 1;
} else if (a_date_obj > b_date_obj) {
return -1;
} else {
return 0;
}
});
}
}
if (d == "URL") {
clicks.url++;
// even number of clicks
if (clicks.url % 2 == 0) {
// sort ascending: alphabetically
rows.sort(function(a,b) {
if (a.thumb_url_default.toUpperCase() < b.thumb_url_default.toUpperCase()) {
return -1;
} else if (a.thumb_url_default.toUpperCase() > b.thumb_url_default.toUpperCase()) {
return 1;
} else {
return 0;
}
});
// odd number of clicks
} else if (clicks.url % 2 != 0) {
// sort descending: alphabetically
rows.sort(function(a,b) {
if (a.thumb_url_default.toUpperCase() < b.thumb_url_default.toUpperCase()) {
return 1;
} else if (a.thumb_url_default.toUpperCase() > b.thumb_url_default.toUpperCase()) {
return -1;
} else {
return 0;
}
});
}
}
}) // end of click listeners
});
d3.select(self.frameElement).style("height", "780px").style("width", "1150px");
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment