Created
October 9, 2013 21:50
-
-
Save tmcw/6909075 to your computer and use it in GitHub Desktop.
This file contains 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
GIF89a ? ??????!? , DnX ; |
This file contains 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
.dragdealer { | |
position: absolute; | |
height: 20px; | |
background: url(cr-hatch-light-gray.gif); | |
margin-bottom: 1em; | |
top:495px; | |
} | |
.dragdealer .handle { | |
position: absolute; | |
cursor: pointer; | |
} | |
.dragdealer .red-bar { | |
width: 120px; | |
height: 20px; | |
background: #333333; | |
color: #FFF; | |
line-height: 20px; | |
text-align: center; | |
border-radius:1px; | |
-moz-border-radius:3px; | |
-webkit-border-radius:3px; | |
} | |
.dragdealer .disabled { | |
background: #898989; | |
} |
This file contains 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
/** | |
* Dragdealer JS v0.9.5 | |
* http://code.ovidiu.ch/dragdealer-js | |
* | |
* Copyright (c) 2010, Ovidiu Chereches | |
* MIT License | |
* http://legal.ovidiu.ch/licenses/MIT | |
*/ | |
/* Cursor */ | |
var Cursor = | |
{ | |
x: 0, y: 0, | |
init: function() | |
{ | |
this.setEvent('mouse'); | |
this.setEvent('touch'); | |
}, | |
setEvent: function(type) | |
{ | |
var moveHandler = document['on' + type + 'move'] || function(){}; | |
document['on' + type + 'move'] = function(e) | |
{ | |
moveHandler(e); | |
Cursor.refresh(e); | |
} | |
}, | |
refresh: function(e) | |
{ | |
if(!e) | |
{ | |
e = window.event; | |
} | |
if(e.type == 'mousemove') | |
{ | |
this.set(e); | |
} | |
else if(e.touches) | |
{ | |
this.set(e.touches[0]); | |
} | |
}, | |
set: function(e) | |
{ | |
if(e.pageX || e.pageY) | |
{ | |
this.x = e.pageX; | |
this.y = e.pageY; | |
} | |
else if(e.clientX || e.clientY) | |
{ | |
this.x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; | |
this.y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; | |
} | |
} | |
}; | |
Cursor.init(); | |
/* Position */ | |
var Position = | |
{ | |
get: function(obj) | |
{ | |
var curleft = curtop = 0; | |
if(obj.offsetParent) | |
{ | |
do | |
{ | |
curleft += obj.offsetLeft; | |
curtop += obj.offsetTop; | |
} | |
while((obj = obj.offsetParent)); | |
} | |
return [curleft, curtop]; | |
} | |
}; | |
/* Dragdealer */ | |
var Dragdealer = function(wrapper, options) | |
{ | |
if(typeof(wrapper) == 'string') | |
{ | |
wrapper = document.getElementById(wrapper); | |
} | |
if(!wrapper) | |
{ | |
return; | |
} | |
var handle = wrapper.getElementsByTagName('div')[0]; | |
if(!handle || handle.className.search(/(^|\s)handle(\s|$)/) == -1) | |
{ | |
return; | |
} | |
this.init(wrapper, handle, options || {}); | |
this.setup(); | |
}; | |
Dragdealer.prototype = | |
{ | |
init: function(wrapper, handle, options) | |
{ | |
this.wrapper = wrapper; | |
this.handle = handle; | |
this.options = options; | |
this.disabled = this.getOption('disabled', false); | |
this.horizontal = this.getOption('horizontal', true); | |
this.vertical = this.getOption('vertical', false); | |
this.slide = this.getOption('slide', true); | |
this.steps = this.getOption('steps', 0); | |
this.snap = this.getOption('snap', false); | |
this.loose = this.getOption('loose', false); | |
this.speed = this.getOption('speed', 10) / 100; | |
this.xPrecision = this.getOption('xPrecision', 0); | |
this.yPrecision = this.getOption('yPrecision', 0); | |
this.callback = options.callback || null; | |
this.animationCallback = options.animationCallback || null; | |
this.bounds = { | |
left: options.left || 0, right: -(options.right || 0), | |
top: options.top || 0, bottom: -(options.bottom || 0), | |
x0: 0, x1: 0, xRange: 0, | |
y0: 0, y1: 0, yRange: 0 | |
}; | |
this.value = { | |
prev: [-1, -1], | |
current: [options.x || 0, options.y || 0], | |
target: [options.x || 0, options.y || 0] | |
}; | |
this.offset = { | |
wrapper: [0, 0], | |
mouse: [0, 0], | |
prev: [-999999, -999999], | |
current: [0, 0], | |
target: [0, 0] | |
}; | |
this.change = [0, 0]; | |
this.activity = false; | |
this.dragging = false; | |
this.tapping = false; | |
}, | |
getOption: function(name, defaultValue) | |
{ | |
return this.options[name] !== undefined ? this.options[name] : defaultValue; | |
}, | |
setup: function() | |
{ | |
this.setWrapperOffset(); | |
this.setBoundsPadding(); | |
this.setBounds(); | |
this.setSteps(); | |
this.addListeners(); | |
}, | |
setWrapperOffset: function() | |
{ | |
this.offset.wrapper = Position.get(this.wrapper); | |
}, | |
setBoundsPadding: function() | |
{ | |
if(!this.bounds.left && !this.bounds.right) | |
{ | |
this.bounds.left = Position.get(this.handle)[0] - this.offset.wrapper[0]; | |
this.bounds.right = -this.bounds.left; | |
} | |
if(!this.bounds.top && !this.bounds.bottom) | |
{ | |
this.bounds.top = Position.get(this.handle)[1] - this.offset.wrapper[1]; | |
this.bounds.bottom = -this.bounds.top; | |
} | |
}, | |
setBounds: function() | |
{ | |
this.bounds.x0 = this.bounds.left; | |
this.bounds.x1 = this.wrapper.offsetWidth + this.bounds.right; | |
this.bounds.xRange = (this.bounds.x1 - this.bounds.x0) - this.handle.offsetWidth; | |
this.bounds.y0 = this.bounds.top; | |
this.bounds.y1 = this.wrapper.offsetHeight + this.bounds.bottom; | |
this.bounds.yRange = (this.bounds.y1 - this.bounds.y0) - this.handle.offsetHeight; | |
this.bounds.xStep = 1 / (this.xPrecision || Math.max(this.wrapper.offsetWidth, this.handle.offsetWidth)); | |
this.bounds.yStep = 1 / (this.yPrecision || Math.max(this.wrapper.offsetHeight, this.handle.offsetHeight)); | |
}, | |
setSteps: function() | |
{ | |
if(this.steps > 1) | |
{ | |
this.stepRatios = []; | |
for(var i = 0; i <= this.steps - 1; i++) | |
{ | |
this.stepRatios[i] = i / (this.steps - 1); | |
} | |
} | |
}, | |
addListeners: function() | |
{ | |
var self = this; | |
this.wrapper.onselectstart = function() | |
{ | |
return false; | |
} | |
this.handle.onmousedown = this.handle.ontouchstart = function(e) | |
{ | |
self.handleDownHandler(e); | |
}; | |
this.wrapper.onmousedown = this.wrapper.ontouchstart = function(e) | |
{ | |
self.wrapperDownHandler(e); | |
}; | |
var mouseUpHandler = document.onmouseup || function(){}; | |
document.onmouseup = function(e) | |
{ | |
mouseUpHandler(e); | |
self.documentUpHandler(e); | |
}; | |
var touchEndHandler = document.ontouchend || function(){}; | |
document.ontouchend = function(e) | |
{ | |
touchEndHandler(e); | |
self.documentUpHandler(e); | |
}; | |
var resizeHandler = window.onresize || function(){}; | |
window.onresize = function(e) | |
{ | |
resizeHandler(e); | |
self.documentResizeHandler(e); | |
}; | |
this.wrapper.onmousemove = function(e) | |
{ | |
self.activity = true; | |
} | |
this.wrapper.onclick = function(e) | |
{ | |
return !self.activity; | |
} | |
this.interval = setInterval(function(){ self.animate() }, 25); | |
self.animate(false, true); | |
}, | |
handleDownHandler: function(e) | |
{ | |
this.activity = false; | |
Cursor.refresh(e); | |
this.preventDefaults(e, true); | |
this.startDrag(); | |
this.cancelEvent(e); | |
}, | |
wrapperDownHandler: function(e) | |
{ | |
Cursor.refresh(e); | |
this.preventDefaults(e, true); | |
this.startTap(); | |
}, | |
documentUpHandler: function(e) | |
{ | |
this.stopDrag(); | |
this.stopTap(); | |
//this.cancelEvent(e); | |
}, | |
documentResizeHandler: function(e) | |
{ | |
this.setWrapperOffset(); | |
this.setBounds(); | |
this.update(); | |
}, | |
enable: function() | |
{ | |
this.disabled = false; | |
this.handle.className = this.handle.className.replace(/\s?disabled/g, ''); | |
}, | |
disable: function() | |
{ | |
this.disabled = true; | |
this.handle.className += ' disabled'; | |
}, | |
setStep: function(x, y, snap) | |
{ | |
this.setValue( | |
this.steps && x > 1 ? (x - 1) / (this.steps - 1) : 0, | |
this.steps && y > 1 ? (y - 1) / (this.steps - 1) : 0, | |
snap | |
); | |
}, | |
setValue: function(x, y, snap) | |
{ | |
this.setTargetValue([x, y || 0]); | |
if(snap) | |
{ | |
this.groupCopy(this.value.current, this.value.target); | |
} | |
}, | |
startTap: function(target) | |
{ | |
if(this.disabled) | |
{ | |
return; | |
} | |
this.tapping = true; | |
if(target === undefined) | |
{ | |
target = [ | |
Cursor.x - this.offset.wrapper[0] - (this.handle.offsetWidth / 2), | |
Cursor.y - this.offset.wrapper[1] - (this.handle.offsetHeight / 2) | |
]; | |
} | |
this.setTargetOffset(target); | |
}, | |
stopTap: function() | |
{ | |
if(this.disabled || !this.tapping) | |
{ | |
return; | |
} | |
this.tapping = false; | |
this.setTargetValue(this.value.current); | |
this.result(); | |
}, | |
startDrag: function() | |
{ | |
if(this.disabled) | |
{ | |
return; | |
} | |
this.offset.mouse = [ | |
Cursor.x - Position.get(this.handle)[0], | |
Cursor.y - Position.get(this.handle)[1] | |
]; | |
this.dragging = true; | |
}, | |
stopDrag: function() | |
{ | |
if(this.disabled || !this.dragging) | |
{ | |
return; | |
} | |
this.dragging = false; | |
var target = this.groupClone(this.value.current); | |
if(this.slide) | |
{ | |
var ratioChange = this.change; | |
target[0] += ratioChange[0] * 4; | |
target[1] += ratioChange[1] * 4; | |
} | |
this.setTargetValue(target); | |
this.result(); | |
}, | |
feedback: function() | |
{ | |
var value = this.value.current; | |
if(this.snap && this.steps > 1) | |
{ | |
value = this.getClosestSteps(value); | |
} | |
if(!this.groupCompare(value, this.value.prev)) | |
{ | |
if(typeof(this.animationCallback) == 'function') | |
{ | |
this.animationCallback(value[0], value[1]); | |
} | |
this.groupCopy(this.value.prev, value); | |
} | |
}, | |
result: function() | |
{ | |
if(typeof(this.callback) == 'function') | |
{ | |
this.callback(this.value.target[0], this.value.target[1]); | |
} | |
}, | |
animate: function(direct, first) | |
{ | |
if(direct && !this.dragging) | |
{ | |
return; | |
} | |
if(this.dragging) | |
{ | |
var prevTarget = this.groupClone(this.value.target); | |
var offset = [ | |
Cursor.x - this.offset.wrapper[0] - this.offset.mouse[0], | |
Cursor.y - this.offset.wrapper[1] - this.offset.mouse[1] | |
]; | |
this.setTargetOffset(offset, this.loose); | |
this.change = [ | |
this.value.target[0] - prevTarget[0], | |
this.value.target[1] - prevTarget[1] | |
]; | |
} | |
if(this.dragging || first) | |
{ | |
this.groupCopy(this.value.current, this.value.target); | |
} | |
if(this.dragging || this.glide() || first) | |
{ | |
this.update(); | |
this.feedback(); | |
} | |
}, | |
glide: function() | |
{ | |
var diff = [ | |
this.value.target[0] - this.value.current[0], | |
this.value.target[1] - this.value.current[1] | |
]; | |
if(!diff[0] && !diff[1]) | |
{ | |
return false; | |
} | |
if(Math.abs(diff[0]) > this.bounds.xStep || Math.abs(diff[1]) > this.bounds.yStep) | |
{ | |
this.value.current[0] += diff[0] * this.speed; | |
this.value.current[1] += diff[1] * this.speed; | |
} | |
else | |
{ | |
this.groupCopy(this.value.current, this.value.target); | |
} | |
return true; | |
}, | |
update: function() | |
{ | |
if(!this.snap) | |
{ | |
this.offset.current = this.getOffsetsByRatios(this.value.current); | |
} | |
else | |
{ | |
this.offset.current = this.getOffsetsByRatios( | |
this.getClosestSteps(this.value.current) | |
); | |
} | |
this.show(); | |
}, | |
show: function() | |
{ | |
if(!this.groupCompare(this.offset.current, this.offset.prev)) | |
{ | |
if(this.horizontal) | |
{ | |
this.handle.style.left = String(this.offset.current[0]) + 'px'; | |
} | |
if(this.vertical) | |
{ | |
this.handle.style.top = String(this.offset.current[1]) + 'px'; | |
} | |
this.groupCopy(this.offset.prev, this.offset.current); | |
} | |
}, | |
setTargetValue: function(value, loose) | |
{ | |
var target = loose ? this.getLooseValue(value) : this.getProperValue(value); | |
this.groupCopy(this.value.target, target); | |
this.offset.target = this.getOffsetsByRatios(target); | |
}, | |
setTargetOffset: function(offset, loose) | |
{ | |
var value = this.getRatiosByOffsets(offset); | |
var target = loose ? this.getLooseValue(value) : this.getProperValue(value); | |
this.groupCopy(this.value.target, target); | |
this.offset.target = this.getOffsetsByRatios(target); | |
}, | |
getLooseValue: function(value) | |
{ | |
var proper = this.getProperValue(value); | |
return [ | |
proper[0] + ((value[0] - proper[0]) / 4), | |
proper[1] + ((value[1] - proper[1]) / 4) | |
]; | |
}, | |
getProperValue: function(value) | |
{ | |
var proper = this.groupClone(value); | |
proper[0] = Math.max(proper[0], 0); | |
proper[1] = Math.max(proper[1], 0); | |
proper[0] = Math.min(proper[0], 1); | |
proper[1] = Math.min(proper[1], 1); | |
if((!this.dragging && !this.tapping) || this.snap) | |
{ | |
if(this.steps > 1) | |
{ | |
proper = this.getClosestSteps(proper); | |
} | |
} | |
return proper; | |
}, | |
getRatiosByOffsets: function(group) | |
{ | |
return [ | |
this.getRatioByOffset(group[0], this.bounds.xRange, this.bounds.x0), | |
this.getRatioByOffset(group[1], this.bounds.yRange, this.bounds.y0) | |
]; | |
}, | |
getRatioByOffset: function(offset, range, padding) | |
{ | |
return range ? (offset - padding) / range : 0; | |
}, | |
getOffsetsByRatios: function(group) | |
{ | |
return [ | |
this.getOffsetByRatio(group[0], this.bounds.xRange, this.bounds.x0), | |
this.getOffsetByRatio(group[1], this.bounds.yRange, this.bounds.y0) | |
]; | |
}, | |
getOffsetByRatio: function(ratio, range, padding) | |
{ | |
return Math.round(ratio * range) + padding; | |
}, | |
getClosestSteps: function(group) | |
{ | |
return [ | |
this.getClosestStep(group[0]), | |
this.getClosestStep(group[1]) | |
]; | |
}, | |
getClosestStep: function(value) | |
{ | |
var k = 0; | |
var min = 1; | |
for(var i = 0; i <= this.steps - 1; i++) | |
{ | |
if(Math.abs(this.stepRatios[i] - value) < min) | |
{ | |
min = Math.abs(this.stepRatios[i] - value); | |
k = i; | |
} | |
} | |
return this.stepRatios[k]; | |
}, | |
groupCompare: function(a, b) | |
{ | |
return a[0] == b[0] && a[1] == b[1]; | |
}, | |
groupCopy: function(a, b) | |
{ | |
a[0] = b[0]; | |
a[1] = b[1]; | |
}, | |
groupClone: function(a) | |
{ | |
return [a[0], a[1]]; | |
}, | |
preventDefaults: function(e, selection) | |
{ | |
if(!e) | |
{ | |
e = window.event; | |
} | |
if(e.preventDefault) | |
{ | |
e.preventDefault(); | |
} | |
e.returnValue = false; | |
if(selection && document.selection) | |
{ | |
document.selection.empty(); | |
} | |
}, | |
cancelEvent: function(e) | |
{ | |
if(!e) | |
{ | |
e = window.event; | |
} | |
if(e.stopPropagation) | |
{ | |
e.stopPropagation(); | |
} | |
e.cancelBubble = true; | |
} | |
}; |
This file contains 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></title> | |
<script src='//api.tiles.mapbox.com/mapbox.js/v1.3.1/mapbox.js'></script> | |
<script src='dragdealer.js'></script> | |
<link href='//api.tiles.mapbox.com/mapbox.js/v1.3.1/mapbox.css' rel='stylesheet' /> | |
<link href='dragdealer.css' rel='stylesheet' /> | |
<link href='style.css' rel='stylesheet' /> | |
<!--[if lte IE 8]> | |
<link href='//api.tiles.mapbox.com/mapbox.js/v1.3.1/mapbox.ie.css' rel='stylesheet'> | |
<![endif]--> | |
<style> | |
body { margin:0; padding:0; } | |
#map { | |
width:650px; | |
height:495px; | |
} | |
</style> | |
</head> | |
<body> | |
<div id='map'></div> | |
<div id='azavea-slider' class='dragdealer' style='width:650px'> | |
<div id='azavea-slide-bar' class='red-bar handle'></div> | |
</div> | |
<script type='text/javascript'> | |
var number_years = 22, | |
start_year = 1990, | |
map = L.mapbox.map('map') | |
.setView([40, -100.50], 4), | |
years = [], | |
currentOverlay; | |
map.addControl(L.mapbox.legendControl().addLegend('<div class="overlay-legend"><div class="scale"> <ul class="labels"> <li><span style="background:#0C5D00;"></span>Over 99th percentile</li><li><span style="background:#5C8100;"></span>98th - 99th percentile</li><li><span style="background:#7E9C00;"></span>95th - 98th percentile</li><li><span style="background:#B8C300;"></span>90th - 95th percentile</li><li><span style="background:#D2CF00;"></span>70th - 95thth percentile</li><li><span style="background:#DCDA53;"></span>10th - 70th percentile</li><li><span style="background:#E6E4A6;"></span>Below 10th percentile</li></ul> </div> </div>')); | |
for (var y = start_year; y <= start_year + number_years; y += 2) { | |
var year = { | |
year: y, | |
tiles: L.mapbox.tileLayer('sunlight.pop_' + y), | |
grid: L.mapbox.gridLayer('sunlight.pop_' + y) | |
}; | |
years.push(year); | |
} | |
currentOverlay = years[0].tiles.addTo(map); | |
currentGrid = years[0].grid.addTo(map); | |
currentGridControl = L.mapbox.gridControl(years[0].grid).addTo(map); | |
var timeout; | |
var slideBar = document.getElementById('azavea-slide-bar'); | |
var azaveaSlider = new Dragdealer('azavea-slider', { | |
x: 0, | |
steps: 1 + number_years / 2, | |
snap: true, | |
animationCallback: onslide | |
}); | |
function onslide(x, y) { | |
var numForward = x * ((number_years / 2)), | |
yearNumber = start_year + (numForward * 2); | |
slideBar.innerHTML = yearNumber; | |
if (currentGridControl) map.removeControl(currentGridControl); | |
currentOverlay = years[numForward].tiles.addTo(map); | |
currentGrid = years[numForward].grid.addTo(map); | |
currentGridControl = L.mapbox.gridControl(currentGrid).addTo(map); | |
if (timeout) window.clearTimeout(timeout); | |
timeout = window.setTimeout(cleanup, 100); | |
} | |
function cleanup() { | |
map.eachLayer(function(l) { | |
if (l !== currentOverlay && l !== currentGrid) { | |
map.removeLayer(l); | |
} | |
}); | |
} | |
</script> | |
</body> | |
</html> |
This file contains 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
/* Overidden legend styles */ | |
.wax-legend .overlay-legend { | |
padding-top: 1px; | |
min-width: 143px; | |
} | |
.wax-legend .title { | |
text-align: left; | |
margin-bottom: 1px; | |
font-weight: bold; | |
font-size: 90%; | |
line-height: 14px; | |
width: 143px; | |
} | |
.wax-legend .title2 { | |
text-align: left; | |
margin-top: 1px; | |
margin-bottom: 4px; | |
font-size: 75%; | |
line-height: 14px; | |
width: 143px; | |
} | |
.wax-legend .overlay-legend.drought .title2 { | |
width: 185px; | |
} | |
.wax-legend .overlay-legend.commitment .title { | |
width: 160px; | |
} | |
.wax-legend .scale { | |
clear: both; | |
} | |
.wax-legend .scale ul { | |
margin: 0; | |
padding: 0; | |
list-style: none !important; | |
-webkit-padding-start: 0 !important; | |
} | |
.wax-legend .scale ul li { | |
font-size: 80%; | |
list-style: none !important; | |
margin-left: 0px !important; | |
padding:2px 0; | |
} | |
.wax-legend ul.labels li span { | |
display:inline-block; | |
vertical-align:middle; | |
height: 16px; | |
width: 30px; | |
border: .5px solid #333; | |
margin-right: 5px; | |
margin-left: 0px !important; | |
} | |
.wax-legend ul li span { | |
display: block; | |
margin-left: 0px !important; | |
} | |
.wax-legend .source1 { | |
font-size: 70%; | |
color: #666; | |
margin-top: 1px; | |
clear: both; | |
} | |
.wax-legend .source2 { | |
font-size: 70%; | |
color: #666; | |
margin-top: 1px; | |
clear: both; | |
} | |
.wax-attribution a, | |
.wax-legend a { | |
color: #7F8A8C; | |
text-decoration: none !important; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment