Last active
July 9, 2021 08:51
-
-
Save djamshed/1845538 to your computer and use it in GitHub Desktop.
Leaderboard in d3.js
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> | |
<head> | |
<meta charset="utf-8"> | |
<!-- Use the .htaccess and remove these lines to avoid edge case issues. | |
More info: h5bp.com/b/378 --> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> | |
<title>Leaderboard with D3</title> | |
<meta name="description" content=""> | |
<meta name="author" content="Djam Saidmuradov"> | |
<!-- Mobile viewport optimized: j.mp/bplateviewport --> | |
<meta name="viewport" content="width=device-width,initial-scale=1"> | |
<link href='http://fonts.googleapis.com/css?family=Gudea:400,700' rel='stylesheet'> | |
<link rel="stylesheet" href="http://twitter.github.com/bootstrap/assets/css/bootstrap.css"> | |
<link rel="stylesheet" href="style.css"> | |
<!-- end CSS--> | |
</head> | |
<body> | |
<div id="container"> | |
<header> | |
</header> | |
<div id="main" role="main"> | |
<div id="toolbar"> | |
<form class="well form-search"> | |
<input type = "text" title="Search by name" placeholder="search name" id="searchInput"/> | |
<button type="submit" class="btn" id="searchBtn">Search by name</button> | |
<span style="margin-left: 20px;">Show:</span> | |
<a id="desc" class="btn" href="#">Leaders</a> | |
or | |
<a id="asc" class ="btn" href="#">Laggards</a> | |
</form> | |
</div> | |
<div id="leaderboard"> | |
</div> | |
</div> | |
<footer> | |
</footer> | |
</div> <!--! end of #container --> | |
<!-- JavaScript at the bottom for fast page loading --> | |
<!-- Grab Google CDN's jQuery, with a protocol relative URL; fall back to local if offline --> | |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> | |
<script src=" https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js"></script> | |
<script src="https://raw.github.com/cdnjs/cdnjs/master/ajax/libs/twitter-bootstrap/2.0.0/bootstrap.min.js"></script> | |
<script src="http://d3js.org/d3.v2.min.js"></script> | |
<!-- scripts concatenated and minified via ant build script--> | |
<script defer src="plugins.js"></script> | |
<script defer src="script.js"></script> | |
<!-- end scripts--> | |
</body> | |
</html> |
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
// usage: log('inside coolFunc', this, arguments); | |
// paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/ | |
window.log = function(){ | |
log.history = log.history || []; // store logs to an array for reference | |
log.history.push(arguments); | |
if(this.console) { | |
arguments.callee = arguments.callee.caller; | |
var newarr = [].slice.call(arguments); | |
(typeof console.log === 'object' ? log.apply.call(console.log, console, newarr) : console.log.apply(console, newarr)); | |
} | |
}; | |
// make it safe to use console.log always | |
(function(b){function c(){}for(var d="assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,timeStamp,profile,profileEnd,time,timeEnd,trace,warn".split(","),a;a=d.pop();){b[a]=b[a]||c}})((function(){try | |
{console.log();return window.console;}catch(err){return window.console={};}})()); | |
// place any jQuery/helper plugins in here, instead of separate, slower script files. |
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
/* Author: Djam | |
*/ | |
const DATA_SIZE = 15; //num of random data items to generate | |
const DISPLAYED_ROWS = 5; | |
const HOVER_DURATION = 1000; | |
const CELL_WIDTH = 200; | |
var MODE_ASC = false; | |
var data = [], | |
columns, | |
cells; | |
//----------------------------------------------- handlers, util functions | |
function addHandlers (){ | |
$('#searchInput').keypress(function(e){ if((e.keyCode || e.which) == 13 /* Enter */) return searchItems(); }); | |
$('#searchBtn').click(function (e) { return searchItems(); }); | |
$('#asc').click(function (e) {MODE_ASC = true; reloadCells(); return false; }); | |
$('#desc').click(function (e) {MODE_ASC = false; reloadCells(); return false; }); | |
} | |
function searchItems(){ | |
var searchStr = $('#searchInput').val(); | |
cells.classed('selected', false); | |
cells.filter(function(cellData){return cellData.name.toLowerCase() === searchStr.toLowerCase();}) | |
.classed('selected', true); | |
return false; | |
} | |
//money format function | |
var money = d3.format("0,.2f") | |
//rank format function (returns 1st, 23rd, etc..) | |
function rank(num) | |
{ | |
if (num == 0) return "0"; | |
switch (num % 100) | |
{ | |
case 11: | |
case 12: | |
case 13: | |
return num + "th"; | |
} | |
switch (num % 10) | |
{ | |
case 1: return num + "st"; | |
case 2: return num + "nd"; | |
case 3: return num + "rd"; | |
} | |
return num + "th"; | |
} | |
//----------------------------------------------- Data | |
//create data | |
var columnObj = [ | |
{name: "Total Budget", ascending: false}, | |
{name: "Paid to Date", ascending: false}, | |
{name: "Prior period", ascending: false} | |
]; | |
function createSampleData(){ | |
for ( var num in d3.range(DATA_SIZE)){ | |
var datum = {name: "Name "+ num}; | |
for( var i in columnObj){ | |
datum[columnObj[i].name] = Math.random() * 100000; | |
} | |
data.push(datum); | |
} | |
} | |
//-----------------------------------------------Leaderboard implementation | |
//removes styles attribute | |
function removeStyles (el, properties) { | |
if (properties) | |
properties.foreach(function (prop) {el.style(prop, null);}); | |
else | |
el.attr('style', null); | |
} | |
//animates selection to hovered state (used for "out of range" cells) | |
function animateToHovered(selection){ | |
if(selection.empty()) return; | |
var _height = selection.style('height'); | |
selection.style('height', '0px'); | |
selection.style('opacity', 0.5); | |
selection | |
.transition() | |
.duration(100) | |
.style('height', _height) | |
.transition() | |
.delay(100) | |
.duration(300) | |
.style('opacity', 1) | |
//remove animated properties | |
.each('end', function (d, i) { removeStyles ( d3.select(this)); }) | |
; | |
} | |
//animates selection to selected state (used for "out of range" cells) | |
function animateToSelected(selection){ | |
if(selection.empty()) return; | |
var _bgcolor = selection.style('background-color'); | |
var _color = selection.style('color'); | |
//it starts with hovered colors | |
//FIXME: find a way to get hovered colors | |
selection.style('background-color', '#DFDFDF'); | |
selection.style('color', '#404040'); | |
//animate to selected colors | |
selection | |
.transition() | |
.duration(500) | |
.style('background-color', _bgcolor) | |
.style('color', _color) | |
//remove animated properties | |
.each('end', function (d, i) { removeStyles ( d3.select(this)); }) | |
; | |
} | |
function initLeaderboard(){ | |
//Columns | |
columns = d3.select("#leaderboard") | |
.selectAll(".leaderboard-column") | |
.data(columnObj) | |
.text(function(d){ return d.name}) | |
; | |
// Enter… | |
columns.enter() | |
.append("div") | |
.style("width", function (d, i) { return CELL_WIDTH +"px"; }) | |
.style("left", function (d, i) { return i * CELL_WIDTH +"px"; }) | |
.classed("leaderboard-column", true) | |
.text(function(d){ return d.name}) | |
; | |
// Exit… | |
columns.exit() | |
.remove(); | |
//Cells | |
reloadCells(); | |
//Enter | |
cells.enter() | |
.append('div') | |
.classed("leaderboard-cell", true) | |
.classed('cell-out-of-range', function(d, i){ | |
return i >= DISPLAYED_ROWS; | |
}) | |
; | |
//Exit | |
cells.exit() | |
.remove(); | |
//cell title | |
cells.append('div') | |
.classed("title", true) | |
.text(function(d,i,j) { | |
return d['name']; | |
}); | |
//cell rank+value container | |
var vals = cells.append('div') | |
.classed("val-container", true); | |
//rank | |
vals.append('div') | |
.classed("rank", true) | |
.text(function(d,i,j) { | |
return rank(i+1); | |
}); | |
//value | |
vals.append('div') | |
.classed("value", true) | |
.text(function(d,i,j) { | |
return "$" + money(d[columnObj[j].name]); | |
}); | |
//------------------------Cell Event handlers | |
//Cell click | |
cells.on("click", function(d, i){ | |
//deselect all | |
cells.classed('selected', false); | |
//select relevant ones | |
var selected = cells.filter(function(cellData){ return d === cellData;}) | |
.classed('selected', true) | |
; | |
//animate color for those out of range | |
columns.selectAll('.leaderboard-cell.cell-out-of-range.selected').call(animateToSelected); | |
}); | |
//cell mouse over | |
cells.on("mouseover", function(d, i){ | |
var hovered = cells.filter(function(cellData){ return d === cellData;}) | |
.classed('hovered', true) | |
; | |
//fade in those out of range | |
columns.selectAll('.leaderboard-cell.cell-out-of-range.hovered').call(animateToHovered); | |
}); | |
//cell mouse out | |
cells.on("mouseout", function(d, i){ | |
var hovered = cells.filter(function(cellData){ return d === cellData;}) | |
.classed('hovered', false) | |
; | |
}); | |
} | |
function reloadCells(){ | |
//Cells | |
cells = | |
columns.selectAll(".leaderboard-cell") | |
.data( | |
function(columnObj){ | |
//data sorted by the current columnObj | |
return data.sort(function(a, b){ | |
return MODE_ASC ? d3.ascending(a[columnObj.name], b[columnObj.name]) | |
: d3.descending(a[columnObj.name], b[columnObj.name]) | |
}) | |
} | |
, function (d){ return d.name; }) | |
.classed('cell-out-of-range', function(d, i){ | |
return i >= DISPLAYED_ROWS; | |
}) | |
; | |
cells.order(); | |
} | |
//-----------------------------------------------Start | |
function start(){ | |
addHandlers(); | |
createSampleData(); | |
initLeaderboard(); | |
} | |
start(); |
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
/* | |
* HTML5 ✰ Boilerplate | |
* | |
* What follows is the result of much research on cross-browser styling. | |
* Credit left inline and big thanks to Nicolas Gallagher, Jonathan Neal, | |
* Kroc Camen, and the H5BP dev community and team. | |
* | |
* Detailed information about this CSS: h5bp.com/css | |
* | |
* ==|== normalize ========================================================== | |
*/ | |
/* ============================================================================= | |
HTML5 display definitions | |
========================================================================== */ | |
article, aside, details, figcaption, figure, footer, header, hgroup, nav, section { display: block; } | |
audio, canvas, video { display: inline-block; *display: inline; *zoom: 1; } | |
audio:not([controls]) { display: none; } | |
[hidden] { display: none; } | |
/* ============================================================================= | |
Base | |
========================================================================== */ | |
/* | |
* 1. Correct text resizing oddly in IE6/7 when body font-size is set using em units | |
* 2. Force vertical scrollbar in non-IE | |
* 3. Prevent iOS text size adjust on device orientation change, without disabling user zoom: h5bp.com/g | |
*/ | |
html { font-size: 100%; overflow-y: scroll; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; } | |
body { margin: 0; font-size: 13px; line-height: 1.231; } | |
body, button, input, select, textarea { font-family: sans-serif; color: #222; } | |
/* | |
* Remove text-shadow in selection highlight: h5bp.com/i | |
* These selection declarations have to be separate | |
* Also: hot pink! (or customize the background color to match your design) | |
*/ | |
::-moz-selection { background: #fe57a1; color: #fff; text-shadow: none; } | |
::selection { background: #fe57a1; color: #fff; text-shadow: none; } | |
/* ============================================================================= | |
Links | |
========================================================================== */ | |
a { color: #00e; } | |
a:visited { color: #551a8b; } | |
a:hover { color: #06e; } | |
a:focus { outline: thin dotted; } | |
/* Improve readability when focused and hovered in all browsers: h5bp.com/h */ | |
a:hover, a:active { outline: 0; } | |
/* ============================================================================= | |
Typography | |
========================================================================== */ | |
abbr[title] { border-bottom: 1px dotted; } | |
b, strong { font-weight: bold; } | |
blockquote { margin: 1em 40px; } | |
dfn { font-style: italic; } | |
hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; } | |
ins { background: #ff9; color: #000; text-decoration: none; } | |
mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; } | |
/* Redeclare monospace font family: h5bp.com/j */ | |
pre, code, kbd, samp { font-family: monospace, monospace; _font-family: 'courier new', monospace; font-size: 1em; } | |
/* Improve readability of pre-formatted text in all browsers */ | |
pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; } | |
q { quotes: none; } | |
q:before, q:after { content: ""; content: none; } | |
small { font-size: 85%; } | |
/* Position subscript and superscript content without affecting line-height: h5bp.com/k */ | |
sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } | |
sup { top: -0.5em; } | |
sub { bottom: -0.25em; } | |
/* ============================================================================= | |
Lists | |
========================================================================== */ | |
ul, ol { margin: 1em 0; padding: 0 0 0 40px; } | |
dd { margin: 0 0 0 40px; } | |
nav ul, nav ol { list-style: none; list-style-image: none; margin: 0; padding: 0; } | |
/* ============================================================================= | |
Embedded content | |
========================================================================== */ | |
/* | |
* 1. Improve image quality when scaled in IE7: h5bp.com/d | |
* 2. Remove the gap between images and borders on image containers: h5bp.com/e | |
*/ | |
img { border: 0; -ms-interpolation-mode: bicubic; vertical-align: middle; } | |
/* | |
* Correct overflow not hidden in IE9 | |
*/ | |
svg:not(:root) { overflow: hidden; } | |
/* ============================================================================= | |
Figures | |
========================================================================== */ | |
figure { margin: 0; } | |
/* ============================================================================= | |
Forms | |
========================================================================== */ | |
form { margin: 0; } | |
fieldset { border: 0; margin: 0; padding: 0; } | |
/* Indicate that 'label' will shift focus to the associated form element */ | |
label { cursor: pointer; } | |
/* | |
* 1. Correct color not inheriting in IE6/7/8/9 | |
* 2. Correct alignment displayed oddly in IE6/7 | |
*/ | |
legend { border: 0; *margin-left: -7px; padding: 0; } | |
/* | |
* 1. Correct font-size not inheriting in all browsers | |
* 2. Remove margins in FF3/4 S5 Chrome | |
* 3. Define consistent vertical alignment display in all browsers | |
*/ | |
button, input, select, textarea { font-size: 100%; margin: 0; vertical-align: baseline; *vertical-align: middle; } | |
/* | |
* 1. Define line-height as normal to match FF3/4 (set using !important in the UA stylesheet) | |
* 2. Correct inner spacing displayed oddly in IE6/7 | |
*/ | |
button, input { line-height: normal; *overflow: visible; } | |
/* | |
* Reintroduce inner spacing in 'table' to avoid overlap and whitespace issues in IE6/7 | |
*/ | |
table button, table input { *overflow: auto; } | |
/* | |
* 1. Display hand cursor for clickable form elements | |
* 2. Allow styling of clickable form elements in iOS | |
*/ | |
button, input[type="button"], input[type="reset"], input[type="submit"] { cursor: pointer; -webkit-appearance: button; } | |
/* | |
* Consistent box sizing and appearance | |
*/ | |
input[type="checkbox"], input[type="radio"] { box-sizing: border-box; } | |
input[type="search"] { -webkit-appearance: textfield; -moz-box-sizing: content-box; -webkit-box-sizing: content-box; box-sizing: content-box; } | |
input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; } | |
/* | |
* Remove inner padding and border in FF3/4: h5bp.com/l | |
*/ | |
button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; } | |
/* | |
* 1. Remove default vertical scrollbar in IE6/7/8/9 | |
* 2. Allow only vertical resizing | |
*/ | |
textarea { overflow: auto; vertical-align: top; resize: vertical; } | |
/* Colors for form validity */ | |
input:valid, textarea:valid { } | |
input:invalid, textarea:invalid { background-color: #f0dddd; } | |
/* ============================================================================= | |
Tables | |
========================================================================== */ | |
table { border-collapse: collapse; border-spacing: 0; } | |
td { vertical-align: top; } | |
/* ==|== primary styles ===================================================== | |
Author: Djam | |
========================================================================== */ | |
#main { | |
margin: 10px; | |
} | |
#leaderboard { | |
font-family: 'Gudea', sans-serif; | |
font-size: 13px; | |
color: #404040; | |
position:relative; | |
height: 350px; | |
} | |
.leaderboard-column { | |
position:absolute; | |
text-align: center; | |
} | |
.leaderboard-cell { | |
padding: 5px; | |
border: 1px solid #D0D2D3; | |
text-align: left; | |
cursor: pointer; | |
background-color: #FFF; | |
-webkit-transition: all .5s ease; | |
-moz-transition: all .5s ease; | |
-o-transition: all .5s ease; | |
transition: all .5s ease; | |
} | |
.leaderboard-cell div { | |
/*FIXME: disabling mouse events on the cell children, who were firing mouseover/mouseout... use mouseenter/mouseleave instead */ | |
pointer-events: none; | |
} | |
.leaderboard-cell .val-container { | |
position:relative; | |
height:20px; | |
} | |
.leaderboard-cell .rank{ | |
display:none; | |
position: absolute; | |
left: 0px; | |
bottom: 0px; | |
} | |
.leaderboard-cell .value{ | |
font-size: 18px; | |
font-weight: bold; | |
width:100%; | |
text-align: right; | |
position: absolute; | |
left: 0px; | |
bottom: 0px; | |
} | |
.leaderboard-cell.hovered { | |
background-color: #DFDFDF; | |
cursor: pointer; | |
} | |
.leaderboard-cell.selected { | |
background-color: #6AB6DA; | |
color: white; | |
} | |
.leaderboard-cell.cell-out-of-range { | |
display: none; | |
-webkit-transition: none; | |
-moz-transition: none; | |
-o-transition: all 0s ease; | |
transition: none; | |
} | |
.leaderboard-cell.cell-out-of-range .title { | |
display:none; | |
} | |
.leaderboard-cell.cell-out-of-range .value { | |
font-size: 13px; | |
font-weight: normal; | |
padding-bottom: 2px; | |
} | |
.leaderboard-cell.cell-out-of-range.selected, .leaderboard-cell.cell-out-of-range.hovered { | |
display: block; | |
} | |
.leaderboard-cell.hovered .rank, .leaderboard-cell.selected .rank{ | |
display: block; | |
} | |
/* ==|== non-semantic helper classes ======================================== | |
Please define your styles before this section. | |
========================================================================== */ | |
/* For image replacement */ | |
.ir { display: block; border: 0; text-indent: -999em; overflow: hidden; background-color: transparent; background-repeat: no-repeat; text-align: left; direction: ltr; } | |
.ir br { display: none; } | |
/* Hide from both screenreaders and browsers: h5bp.com/u */ | |
.hidden { display: none !important; visibility: hidden; } | |
/* Hide only visually, but have it available for screenreaders: h5bp.com/v */ | |
.visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } | |
/* Extends the .visuallyhidden class to allow the element to be focusable when navigated to via the keyboard: h5bp.com/p */ | |
.visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; } | |
/* Hide visually and from screenreaders, but maintain layout */ | |
.invisible { visibility: hidden; } | |
/* Contain floats: h5bp.com/q */ | |
.clearfix:before, .clearfix:after { content: ""; display: table; } | |
.clearfix:after { clear: both; } | |
.clearfix { zoom: 1; } | |
/* ==|== media queries ====================================================== | |
PLACEHOLDER Media Queries for Responsive Design. | |
These override the primary ('mobile first') styles | |
Modify as content requires. | |
========================================================================== */ | |
@media only screen and (min-width: 480px) { | |
/* Style adjustments for viewports 480px and over go here */ | |
} | |
@media only screen and (min-width: 768px) { | |
/* Style adjustments for viewports 768px and over go here */ | |
} | |
/* ==|== print styles ======================================================= | |
Print styles. | |
Inlined to avoid required HTTP connection: h5bp.com/r | |
========================================================================== */ | |
@media print { | |
* { background: transparent !important; color: black !important; text-shadow: none !important; filter:none !important; -ms-filter: none !important; } /* Black prints faster: h5bp.com/s */ | |
a, a:visited { text-decoration: underline; } | |
a[href]:after { content: " (" attr(href) ")"; } | |
abbr[title]:after { content: " (" attr(title) ")"; } | |
.ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; } /* Don't show links for images, or javascript/internal links */ | |
pre, blockquote { border: 1px solid #999; page-break-inside: avoid; } | |
thead { display: table-header-group; } /* h5bp.com/t */ | |
tr, img { page-break-inside: avoid; } | |
img { max-width: 100% !important; } | |
@page { margin: 0.5cm; } | |
p, h2, h3 { orphans: 3; widows: 3; } | |
h2, h3 { page-break-after: avoid; } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Could you please fix the broken link to d3.js, using http://d3js.org/d3.v2.min.js ? Thanks!