-
-
Save bf4/1078afb9c527f90d37bb1e5a5e65c0be to your computer and use it in GitHub Desktop.
First conversion of http://everytimezone.com/ JavaScript code to CoffeeScript
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
# Two things are important to note: | |
# | |
# 1) The code is fugly, because it was a JavaScript/iPad experiment. | |
# I know that it is ugly, so pretty please don't comment on that part. | |
# 2) I tried to use as many CoffeeScript features as possible, | |
# including but not limited to list comprehensions, | |
# heredocs, destructuring assignment and also the "do" operator | |
# | |
# I welcome comments about stuff that is not CoffeeScripty enough, or what I should | |
# write differently. | |
cities = [ | |
[-10, 'Honolulu', 'HAST UTC-10'] | |
[-7, 'San Francisco', 'PDT UTC-7'] | |
[-5, 'Chicago', 'CDT UTC-5'] | |
[-4, 'New York', 'EDT UTC-4'] | |
[-3, 'Rio de Janeiro', 'BRT UTC-3'] | |
[0, 'London', 'GMT UTC'] | |
[2, 'Vienna', 'CET UTC+1'] | |
[5.5, 'Mumbai', 'IST UTC+5:30'], | |
[8, 'Hong Kong', 'HKT UTC+8'] | |
[9, 'Tokyo', 'JST UTC+9'] | |
[10, 'Sydney', 'EST UTC+10'] | |
[12, 'Auckland', 'NZST UTC+12']].reverse() | |
citiesright = false | |
config = | |
format: "ampm" | |
months = 'January February March April May June July August September October November December'.split ' ' | |
ua = navigator.userAgent | |
webkit = ua.indexOf('AppleWebKit/') > -1 | |
moz = ua.indexOf('Gecko') > -1 and not webkit | |
opera = ua.indexOf('Opera') > -1 | |
ie = ua.indexOf('MSIE') > -1 | |
offsp = null | |
transprop = | |
if webkit then 'webkitTransform' | |
else if ie then 'msTransform' | |
else if moz then 'MozTransform' | |
else if opera then 'OTransform' | |
else 'transform' | |
transstr = | |
if webkit then '-webkit-transform' | |
else if ie then '-ms-transform' | |
else if moz then '-moz-transform' | |
else if opera then '-o-transform' | |
transitionstr = | |
if webkit then '-webkit-transition' | |
else if ie then '-ms-transition' | |
else if moz then '-moz-transition' | |
else if opera then '-o-transition' | |
supportsTouch = document.createTouch? | |
scale = 72 | |
now = new Date | |
current = now | |
day = current.getDate() | |
month = current.getMonth() | |
nowminutes = now.getHours() * 60 + now.getMinutes() | |
localoffset = now.getTimezoneOffset() | |
dragging = off | |
Function::delay = (seconds) -> setTimeout @, seconds * 1000 | |
Date::addDays = (days) -> new Date @getTime()+(days * 1000 * 60 * 60 * 24) | |
$ = (id) -> | |
document.getElementById id | |
html = (id, html = '') -> | |
$(id).innerHTML = html | |
css = (id, style) -> | |
$(id).style.cssText += ';' + style | |
anim = (id, transform, opacity = 1, dur = 0.5) -> | |
css id, "#{transitionstr}:all #{dur}s; #{transstr}: | |
#{transform}; opacity:#{opacity}" | |
translateX = (element, x, anim = false) -> | |
return if isNaN x | |
element.style.cssText += ";#{transitionstr}:all 0.4s;" if anim | |
element.style[transprop] = if webkit and supportsTouch | |
"translate3d(#{x}px,0,0)" | |
else | |
"translateX(#{x}px)" | |
ctx = $('canvas').getContext '2d' | |
defaultg = ctx.createLinearGradient 0, 0, 230, 0 | |
activeg = ctx.createLinearGradient 0, 0, 230, 0 | |
localg = ctx.createLinearGradient 0, 0, 230, 0 | |
roundg = ctx.createLinearGradient 0, 0, 0, 23 | |
topg = ctx.createLinearGradient 0, 0, 0, 23 | |
bottomg = ctx.createLinearGradient 0, 23, 0, 0 | |
defaultg.addColorStop stop[0], stop[1] for stop in [ | |
[0, '#4b4c4d'], [0.249,'#4b4c4d'], [0.25,'#575b5c'] | |
[0.329,'#575b5c'], [0.33,'#6b7071'], [0.749,'#6b7071'] | |
[0.75,'#575b5c'], [0.909,'#575b5c'], [0.91,'#4b4c4d'] | |
[1, '#4b4c4d']] | |
activeg.addColorStop stop[0], stop[1] for stop in [ | |
[0, '#5485b1'], [0.249,'#5485b1'], [0.25,'#3cafc5'] | |
[0.329,'#3cafc5'], [0.33,'#55c8e4'], [0.749,'#55c8e4'] | |
[0.75,'#3cafc5'], [0.909,'#3cafc5'], [0.91,'#5485b1'] | |
[1, '#5485b1']] | |
localg.addColorStop stop[0], stop[1] for stop in [ | |
[0, '#8abb29'], [0.249,'#8abb29'], [0.25,'#a5df3b'] | |
[0.329,'#a5df3b'], [0.33,'#b8ff41'], [0.749,'#b8ff41'] | |
[0.75,'#a5df3b'], [0.909,'#a5df3b'], [0.91,'#8abb29'] | |
[1, '#8abb29']] | |
roundg.addColorStop 0, 'rgba(0,0,0,0)' | |
roundg.addColorStop 1, 'rgba(0,0,0,0.4)' | |
topg.addColorStop 0, 'rgba(255,255,255,0.3)' | |
topg.addColorStop 0.025, 'rgba(255,255,255,0)' | |
bottomg.addColorStop 0, 'rgba(255,255,255,0.3)' | |
bottomg.addColorStop 0.025, 'rgba(255,255,255,0)' | |
rr = (w, h, rad) -> | |
ctx.beginPath() | |
ctx.moveTo rad, 0 | |
ctx.lineTo w - rad, 0 | |
ctx.bezierCurveTo w, 0, w, 0, w, rad | |
ctx.lineTo w, h - rad | |
ctx.bezierCurveTo w, h, w, h, w - rad, h | |
ctx.lineTo rad, h | |
ctx.bezierCurveTo 0, h, 0, h, 0, h - rad | |
ctx.lineTo 0, rad | |
ctx.bezierCurveTo 0, 0, 0, 0, rad, 0 | |
ctx.fill() | |
drawBox = (x, y, w, h, gradient = defaultg) -> | |
ctx.save() | |
ctx.translate x, y | |
ctx.fillStyle = gradient | |
ctx.clearRect 0, 0, w, h | |
rr w, h, 18 | |
ctx.fillStyle = roundg | |
rr w, h, 18 | |
ctx.fillStyle = topg | |
rr w, h, 18 | |
ctx.fillStyle = bottomg | |
rr w, h, 18 | |
ctx.restore() | |
hr2p = (hr) -> 50 + (-hr * (100 / scale)) | |
ext = [hr2p(-12 - 24), hr2p(12)] | |
ext.push Math.abs(ext[1])+Math.abs(ext[0]) | |
cel = [] | |
tz = (id, city, zone, zonedesc) -> | |
cityWidth = ((700 / scale * 24) | 0) - 5 + 'px' | |
dy = current.addDays(-1) | |
dt = current.addDays(1) | |
el = document.createElement('div') | |
timeel = document.createElement('div') | |
nameel = document.createElement('div') | |
offsetLeft | |
el.className = "city-wrapper#{if (-zone * 60) == localoffset then ' local' else ''}" | |
el.id = "city_#{id}" | |
el.innerHTML = """ | |
<div class="city" style="width:#{cityWidth}" id="city_#{id}_1">#{months[dy.getMonth()]} #{dy.getDate()}</div> | |
<div class="city" style="width:#{cityWidth}" id="city_#{id}_2">#{months[current.getMonth()]} #{current.getDate()}</div> | |
<div class="city" style="width:#{cityWidth}" id="city_#{id}_3">#{months[dt.getMonth()]} #{dt.getDate()}</div> | |
""" | |
$('cities').appendChild el | |
timeel.className = 'city-time' | |
$('time_info').appendChild timeel | |
timeel.style.cssText += ";top:#{(11 - id) * 60}px" | |
nameel.className = 'city-name' | |
nameel.innerHTML = "#{city}<span class='tz'>#{zonedesc}</span>" | |
$('cities_info').appendChild nameel | |
nameel.style.cssText += ";top:#{110 + id * 60}px" | |
css "city_#{id}", "left:#{hr2p(zone + 24)}%" | |
offsetLeft = $("city_#{id}").offsetLeft | |
c1 = $("city_#{id}_1") | |
x = c1.offsetLeft + offsetLeft | |
y = c1.offsetTop + (80 + (11 - id) * 60) | |
w = c1.offsetWidth | |
h = c1.offsetHeight | |
drawBox x, y, w, h | |
c2 = $("city_#{id}_2") | |
x2 = c2.offsetLeft + offsetLeft | |
y2 = c2.offsetTop + (80 + (11 - id) * 60) | |
w2 = c2.offsetWidth | |
h2 = c2.offsetHeight | |
drawBox x2, y2, w2, h2 | |
c3 = $("city_#{id}_3") | |
x3 = c3.offsetLeft + offsetLeft | |
y3 = c3.offsetTop + (80 + (11 - id) * 60) | |
w3 = c3.offsetWidth | |
h3 = c3.offsetHeight | |
drawBox x3, y3, w3, h3 | |
cel.push [ | |
0, 0, 0, 0, 0, 0 | |
$("city_#{id}_1") | |
$("city_#{id}_2") | |
$("city_#{id}_3") | |
false, false, false | |
timeel, | |
$("city_#{id}") | |
zone, | |
nameel, | |
false, | |
[x, y, w, h] | |
[x2, y2, w2, h2] | |
[x3, y3, w3, h3] | |
(-zone * 60) == localoffset | |
] | |
renderinfo = -> | |
n = offsp | |
p = n - cOffL + 48 | |
cbase = now + localoffset / 60 | |
i = cities.length | |
while i-- | |
celc = cel[i] | |
c = cbase + celc[14] | |
c1 = c < 0 | |
c3 = c >= 24 | |
c2 = c >= 0 and !c3 | |
if c1 and !celc[9] | |
celc[6].className = 'city active' | |
celc[9] = true | |
drawBox(celc[17][0], celc[17][1], celc[17][2], celc[17][3], if celc[20] then localg else activeg) | |
else if not c1 and celc[9] | |
celc[6].className = 'city' | |
celc[9] = false | |
drawBox(celc[17][0], celc[17][1], celc[17][2], celc[17][3]) | |
if c2 and !celc[10] | |
celc[7].className = 'city active' | |
celc[10] = true | |
drawBox(celc[18][0], celc[18][1], celc[18][2], celc[18][3], if celc[20] then localg else activeg) | |
else if not c2 and celc[10] | |
celc[7].className = 'city' | |
celc[10] = false | |
drawBox(celc[18][0], celc[18][1], celc[18][2], celc[18][3]) | |
if c3 and !celc[11] | |
celc[8].className = 'city active' | |
celc[11] = true | |
drawBox(celc[19][0], celc[19][1], celc[19][2], celc[19][3], if celc[20] then localg else activeg) | |
else if not c3 and celc[11] | |
celc[8].className = 'city' | |
celc[11] = false | |
drawBox(celc[19][0], celc[19][1], celc[19][2], celc[19][3]) | |
celc[12].innerHTML = formattime now + celc[14] + (localoffset / 60) | |
if not celc[16] | |
celc[16] = true | |
celc[15].style.cssText += ";top:#{celc[13].offsetTop}px" | |
translateX $('time_info'), 15 + n + cOffL | |
if n<170 and not citiesright | |
translateX $('cities_info'), cOffL + 550, true | |
citiesright = true | |
else if n>500 and citiesright | |
translateX $('cities_info'), cOffL, true | |
citiesright = false | |
updateinfo = -> | |
html 'localtime', formattime now | |
tn = document.createTextNode ' ' | |
$('localtime').appendChild tn | |
renderinfo() | |
formattime = (time) -> | |
time = 24 - Math.abs time % 24 if time < 0 | |
time = time % 24 if time >= 24 | |
mins = Math.abs ((time * 60) % 60) | 0 | |
mins = "0#{mins}" if mins < 10 | |
time = time | 0 | |
if config.format == "ampm" | |
suffix = "am" | |
[time, suffix] = [time % 12, "pm"] if time >= 12 | |
time = 12 if time == 0 | |
"#{time}:#{mins} #{suffix}" | |
else | |
"#{time}:#{mins}" | |
timeselector = (px) -> | |
p = hr2p -now - localoffset / 60 | |
d = -((p / 100) * 700) + 700 / (24 / now) | |
if px | |
css 'now', 'left:0px' | |
translateX $('now'), px | |
offsp = px | |
else | |
css 'now', "left:#{p}%" | |
offsp = p * 7 | |
updateinfo() | |
currenttime = (time) -> | |
p = hr2p(-time - localoffset / 60) | |
d = -((p / 100) * 700) + 700 / (24 / time) | |
css 'cnow', 'left:'+p+'%' | |
html 'clocaltime', formattime(time) | |
setupGrid = -> | |
html 'cities' | |
html 'cities_info' | |
cel = [] | |
i = cities.length | |
while i-- | |
tz i, cities[i][1], cities[i][0], cities[i][2] | |
translateX $('cities_info'), cOffL | |
timeselector() | |
cOffL = $('content').offsetLeft | |
setupGrid() | |
if webkit | |
(-> anim('wrapper','rotateY(0deg)')) | |
.delay(0.5) | |
currenttime nowminutes / 60 | |
now = nowminutes / 60 | |
timeselector() | |
css 'canvas', "left:#{cOffL}px" | |
updateLocalTime = -> | |
localNow = new Date | |
currenttime localNow.getHours() + localNow.getMinutes() / 60 | |
setInterval updateLocalTime, 1000 | |
updateLocalTime() | |
move = (event) -> | |
return if not dragging | |
pageX = event.pageX | |
pageX = event.touches[0].pageX if event.touches? | |
now = (pageX - cOffL - 350) / 700 * scale - localoffset / 60 | |
timeselector pageX - cOffL | |
event.preventDefault() if event.touches? | |
if window.orientation? | |
window.changeorientation = do -> | |
$('wrapper').className = "o#{orientation}" | |
cOffL = $('content').offsetLeft | |
arguments.callee | |
wrapper = $('wrapper') | |
wrapper[if supportsTouch then "ontouchstart" else "onmousedown"] = (event) -> | |
element = event.target | |
element = element.parentNode if element.nodeType isnt 1 | |
return if element.tagName? and element.tagName in ['A', 'IMG'] | |
if event.touches? | |
return if event.touches[0].pageY < 50 | |
return if event.touches[0].pageX < cOffL | |
dragging = on | |
move(event) | |
wrapper[if supportsTouch then "ontouchmove" else "onmousemove"] = move | |
wrapper[if supportsTouch then "ontouchend" else "onmouseup"] = -> dragging = off |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment