Last active
December 18, 2015 03:29
-
-
Save zachdunn/5718686 to your computer and use it in GitHub Desktop.
Time series using range input and smart markers. Built off a AngularJS directive structure.
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
#wrapper{width:960px; margin:10px auto;} | |
#time-series{ | |
margin-top:40px; | |
} | |
*{ | |
font-family:"Helvetica Neue", Helvetica, Arial, sans-serif; | |
} | |
.time-bracket{background:#EFEFEF;} | |
.time-bracket p{margin:0; color:#222; text-align:center;} | |
.time-bracket .ts-label{text-transform: uppercase; font-weight:bold; letter-spacing:1px; font-size:11px; margin-bottom:6px;} | |
.ts-startTime, .ts-endTime{ | |
font-size:12px; | |
} | |
.start-time{float:left;} | |
.end-time{float:left;} | |
.time-bracket{ | |
display:inline-block; width:175px; padding:15px; box-sizing:border-box; | |
} | |
.ts-startTime span, .ts-endTime span{display:block;} | |
.tick{width:2px; height:77px; position:absolute; background:#222; background:rgba(0,0,0,.3);} | |
.tick .indicator-arrow{ | |
margin-left:-5px; | |
position:absolute; | |
bottom:-11px; | |
opacity:.5; | |
} | |
.tick.active .indicator-arrow { | |
opacity:1; | |
} | |
.day-list ul{ | |
margin:0 175px 25px 175px; | |
padding:0; | |
list-style:none; | |
display:block; | |
clear:both; | |
} | |
.day-list li{ | |
font-size:13px; | |
width:122px; | |
box-sizing:border-box; | |
margin:0; padding:0; | |
display:inline-block; | |
float:left; | |
border-bottom:5px solid #efefef; | |
text-align:center; | |
line-height:1.3em; | |
} | |
.day-list li.active, .day-list li.active:hover{ | |
border-bottom:5px solid #EF3344; | |
} | |
.day-list li:hover{ | |
border-bottom:5px solid #F07D86; | |
} | |
.day-list li span.day{ | |
clear:both; | |
display:block; | |
} | |
.day-list a{ | |
display:block; | |
height:100%; width:100%; | |
padding:15px; | |
box-sizing:border-box; | |
text-decoration:none; | |
color:#888; | |
} | |
.day-list a .day{ | |
color:#333; | |
} | |
.day-list li .date{ | |
font-style:italic; | |
font-size:12px; | |
} | |
.day-list li.active .day{ | |
font-weight:bold; | |
} | |
input[type="range"]{ | |
-webkit-appearance:none; | |
background:#EF3344; | |
width:610px; | |
height:77px; | |
cursor:pointer; | |
margin:0; | |
} | |
input[type="range"]::-webkit-slider-thumb{ | |
-webkit-appearance:none; | |
background:#FFF; | |
opacity:.7; | |
width:2px; | |
height:77px; | |
} | |
.ts-marker{ | |
background:#222; | |
color:#FFF; | |
font-size:11px; | |
text-align:center; | |
border-radius:3px; | |
padding:10px; | |
position:absolute; | |
top:-15px; | |
} | |
.ts-tickContainer{float:left;} | |
.ts-marker p{line-height:1.0em; margin:0;} | |
#time-bar-wrap{position:relative; display:inline-block; width:610px; float:left;} | |
/* Regular Content */ | |
.content{ | |
clear:both; | |
padding:30px; | |
} | |
.content h2{ | |
color:#333; | |
} | |
.content.faded{ | |
opacity:0.5; | |
} | |
.clearfix{ | |
zoom: 1; | |
} | |
.clearfix:before, | |
.clearfix:after { | |
display: table; | |
content: ""; | |
zoom: 1; | |
} | |
.clearfix:after { | |
clear: both; | |
} |
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> | |
<html> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Time Series</title> | |
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> | |
<script type="text/javascript" src="time-series.js"></script> | |
<link rel="stylesheet" href="time-series.css"> | |
</head> | |
<body> | |
<div id="wrapper"> | |
<div id="time-series"> | |
<div class="day-list"> | |
<ul class="clearfix"> | |
<li> | |
<a href="#"> | |
<span class="day">Wednesday</span> | |
<span class="date">May 29, 2013</a> | |
</a> | |
</li> | |
<li> | |
<a href="#"> | |
<span class="day">Thursday</span> | |
<span class="date">May 30, 2013</a> | |
</a> | |
</li> | |
<li class="active"> | |
<a href="#"> | |
<span class="day">Friday</span> | |
<span class="date">May 31, 2013</a> | |
</a> | |
</li> | |
</ul> | |
</div> | |
<time-slider callback="layoutSliderChanged" min="layoutStartTimeMS" max="layoutEndTimeMS" ticks="layoutSectionTimes" step="60000" class="ng-isolate-scope ng-scope"> | |
<div class="ts-container clearfix"> | |
<div class="start-time time-bracket"> | |
<p class="ts-label">Start Time</p> | |
<p class="ts-startTime"> | |
<span class="time">2:00 AM</span> | |
<span class="date">Friday May 31, 2013</span> | |
</p> | |
</div> | |
<div id="time-bar-wrap"> | |
<div style="display: inline-block" class="ts-tickContainer"> | |
<div class="tick" style="left: 389.56111111111113px;"> | |
<img class="indicator-arrow" width="12" height="12" src="arrow.svg"> | |
</div> | |
<div class="tick" style="left: 423.89444444444445px;"> | |
<img class="indicator-arrow" width="12" height="12" src="arrow.svg"> | |
</div> | |
<div class="tick" style="left: 465.6666666666667px;"> | |
<img class="indicator-arrow" width="12" height="12" src="arrow.svg"> | |
</div> | |
<div class="tick" style="left: 436.48333333333335px;"> | |
<img class="indicator-arrow" width="12" height="12" src="arrow.svg"> | |
</div> | |
<div class="tick" style="left: 441.6333333333333px;"> | |
<img class="indicator-arrow" width="12" height="12" src="arrow.svg"> | |
</div> | |
<div class="tick" style="left: 294px;"> | |
<img class="indicator-arrow" width="12" height="12" src="arrow.svg"> | |
</div> | |
<div class="tick" style="left: 355.22777777777776px;"> | |
<img class="indicator-arrow" width="12" height="12" src="arrow.svg"> | |
</div> | |
<div class="tick" style="left: 474.25px;"> | |
<img class="indicator-arrow" width="12" height="12" src="arrow.svg"> | |
</div> | |
<div class="tick" style="left: 180px;"> | |
<img class="indicator-arrow" width="12" height="12" src="arrow.svg"> | |
</div> | |
<div class="tick" style="left: 362.66666666666663px;"> | |
<img class="indicator-arrow" width="12" height="12" src="arrow.svg"> | |
</div> | |
<div class="tick" style="left: 50px;"> | |
<img class="indicator-arrow" width="12" height="12" src="arrow.svg"> | |
</div> | |
</div> | |
<input id="time-selection" type="range" min="1369980000000" max="1370001600000" step="60000"> | |
<div class="ts-marker"> | |
<p> | |
<span class="ts-time">4:47 AM</span> | |
<span class="ts-date">Friday, May 31</span> | |
</p> | |
</div> | |
</div> | |
<div class="end-time time-bracket"> | |
<p class="ts-label">End Time</p> | |
<p class="ts-endTime"> | |
<span class="time">8:00 PM</span> | |
<span class="date">Friday May 31, 2013</span> | |
</p> | |
</div> | |
</div> | |
</time-slider> | |
</div> | |
<div class="content"> | |
<h2>Scheduled Content (<span class="active-count">0</span> active)</h2> | |
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p> | |
</div> | |
</div> | |
</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
$(function() { | |
var el, newPoint, newPlace, offset, selectLocation; | |
// Get marker for later | |
var marker = $('.ts-marker'); | |
// Select all range inputs, watch for change | |
$("#time-selection").on('mousedown', function(){ | |
$('.content').addClass('faded'); | |
}).on('mouseup', function(){ | |
$('.content').removeClass('faded'); | |
}); | |
$("#time-selection").on('change', function() { | |
// Cache this for efficiency | |
el = $(this); | |
// Measure width of range input | |
width = el.width(); | |
// Figure out placement percentage between left and right of input | |
newPoint = (el.val() - el.attr("min")) / (el.attr("max") - el.attr("min")); | |
marker.find('p').text(new Date(parseInt(el.val())).toUTCString()); | |
// Not really needed anymore | |
offset = -(marker.width() / 2); | |
// Prevent bubble from going beyond left or right (unsupported browsers) | |
if (newPoint < 0) { newPlace = 0; } | |
else if (newPoint > 1) { newPlace = width; } | |
else { newPlace = width * newPoint + offset; offset -= newPoint; } | |
selectLocation = width * newPoint //Same as newPlace without offset | |
// Move bubble | |
marker.css({ | |
left: newPlace | |
}); | |
// Highlight tick marks in a 10px range of slider | |
$('.tick').removeClass('active').css({top:0}); | |
var activeTick = $('.tick').filter(function(){ | |
upperBound = selectLocation + 10; | |
lowerBound = selectLocation - 10; | |
tickPos = parseInt($(this).position().left); | |
return tickPos < upperBound && tickPos > lowerBound; | |
}); | |
//console.log('Eval from ' + selectLocation); | |
$(activeTick).addClass('active'); | |
// Display the current active count in body | |
$('.active-count').text(activeTick.length); | |
// Stagger multiple active ticks to prevent crowding | |
if (activeTick.length > 0) { | |
stepOffset = 0; | |
activeTick.each(function(index, value){ | |
el = $(value); | |
el.css({top: 11*stepOffset}); | |
stepOffset++; | |
}); | |
} | |
}).trigger('change'); // Fake a change to position bubble at page load | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment