Created
February 4, 2012 05:06
-
-
Save alanhogan/1735493 to your computer and use it in GitHub Desktop.
Modified humane.js
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
# humane.js | |
# Humanized Messages for Notifications | |
# @author Marc Harter (@wavded) | |
# @example | |
# humane('hello world'); | |
# See more usage examples at: http://wavded.github.com/humane-js/ | |
# | |
# Modified by Alan Hogan (@alanhogan) | |
# (Diverged 2012-01-27.) | |
# Now has underscore.js as a dependency. | |
# (But it would be easy to remove.) | |
# Now returns an id , whether you set one or not, when new notifications are created. | |
# You can call remove(id) to remove | |
# that message (whether it has shown yet, or not). | |
# IDs do not have to be unique, but the ones we generate will be. | |
# The use case is that sometimes you will want to clear some messages | |
# immediately if some other event happens (e.g., user reconnects → | |
# clear offline notice, or ajax completes → remove "sending" message) | |
root = this | |
((win, doc) -> | |
doc = win.document | |
normalizeEvent = (name) -> | |
(if eventPrefix then eventPrefix + name else name.toLowerCase()) | |
getConfig = (type, config) -> | |
(if win.humane[type][config] isnt undefined then win.humane[type][config] else win.humane[config]) | |
setup = -> | |
humaneEl = doc.createElement("div") | |
humaneEl.id = "humane" | |
humaneEl.className = "humane" | |
doc.body.appendChild humaneEl | |
for vendor of vendors | |
if vendor + "TransitionProperty" of humaneEl.style | |
eventPrefix = vendors[vendor] | |
useTransitions = true | |
animate = jsAnimateOpacity unless useTransitions | |
isSetup = true | |
run() | |
run = -> | |
return if animationInProgress | |
return unless queue.length | |
after = null | |
animationInProgress = true | |
if timeout | |
clearTimeout timeout | |
timeout = null | |
next = queue.shift() | |
currentMessage = | |
type: next[0] | |
message: next[1] | |
opts: next[2] | |
content = currentMessage.message | |
type = currentMessage.type | |
if getConfig(type, "clickToClose") is true | |
on_ humaneEl, "click", remove | |
on_ humaneEl, "touchstart", remove | |
timeoutInMillis = currentMessage.opts.timeout | |
if timeoutInMillis > 0 | |
timeout = setTimeout(-> | |
unless eventing | |
on_ doc.body, "mousemove", remove | |
on_ doc.body, "click", remove | |
on_ doc.body, "keypress", remove | |
on_ doc.body, "touchstart", remove | |
eventing = true | |
remove() if currentMessage.opts.waitForMove isnt true | |
, timeoutInMillis) | |
events["show"] type, content, "show" | |
content = "<ul><li>" + content.join("<li>") + "</ul>" if isArray(content) | |
humaneEl.innerHTML = content | |
humaneEl.style.display = "block" | |
setTimeout (-> | |
animate 1, type | |
), 50 | |
animate = (level, type) -> | |
if level is 1 | |
humaneEl.className = "humane humane-" + type + " humane-animate" | |
else | |
humaneEl.className = humaneEl.className.replace(" humane-animate", "") | |
on_ humaneEl, normalizeEvent("TransitionEnd"), end | |
remove = (id) -> | |
removeCurrent = false | |
if id isnt undefined | |
# Remove any messages from the queue with this id | |
queue = _.reject(queue, (msg) -> msg.id == id) | |
if currentMessage and currentMessage.id == id | |
removeCurrent = true | |
else | |
removeCurrent = true | |
if removeCurrent | |
currentMessage = {} | |
off_ doc.body, "mousemove", remove | |
off_ doc.body, "click", remove | |
off_ doc.body, "keypress", remove | |
off_ doc.body, "touchstart", remove | |
off_ humaneEl, "click", remove | |
off_ humaneEl, "touchstart", remove | |
eventing = false | |
animate 0 if animationInProgress | |
end = -> | |
off_ humaneEl, normalizeEvent("TransitionEnd"), end if useTransitions | |
animationInProgress = false | |
currentMessage.opts.callback() if currentMessage.opts.callback | |
events["hide"] currentMessage.type, currentMessage.message, "hide" | |
humaneEl.style.display = "none" | |
run() | |
jsAnimateOpacity = (level, type) -> | |
interval = undefined | |
opacity = undefined | |
if level is 1 | |
opacity = 0 | |
humaneEl.className = "humane humane-js-animate humane-" + type | |
setOpacity 0 if useFilter | |
humaneEl.style.zIndex = 1000000 | |
interval = setInterval(-> | |
if opacity < 1 | |
opacity += 0.1 | |
opacity = 1 if opacity > 1 | |
setOpacity opacity | |
else | |
clearInterval interval | |
, 100 / 20) | |
else | |
opacity = 1 | |
interval = setInterval(-> | |
if opacity > 0 | |
opacity -= 0.1 | |
opacity = 0 if opacity < 0 | |
setOpacity opacity | |
else | |
humaneEl.className = humaneEl.className.replace(" humane-js-animate", "") | |
humaneEl.style.zIndex = -1 | |
clearInterval interval | |
end() | |
, 100 / 20) | |
notifier = (type) -> | |
(message, opts) -> | |
opts ||= {} | |
_.defaults(opts, { | |
timeout: getConfig(type, 'timeout') | |
waitForMove: getConfig(type, 'waitForMove') | |
clickToClose: getConfig(type, 'clickToClose') | |
id: _.uniqueId("humane_#{type}_") | |
}) | |
queue.push [ type, message, opts ] | |
events["add"] type, message, "add" | |
run() if isSetup | |
return opts.id | |
humane = undefined | |
on_ = undefined | |
off_ = undefined | |
isArray = undefined | |
eventing = false | |
useTransitions = false | |
animationInProgress = false | |
humaneEl = null | |
timeout = null | |
useFilter = /msie [678]/i.test(navigator.userAgent) | |
vendors = | |
Webkit: "webkit" | |
Moz: "" | |
O: "o" | |
ms: "MS" | |
eventPrefix = "" | |
isSetup = false | |
currentMessage = {} | |
noop = -> | |
events = | |
add: noop | |
show: noop | |
hide: noop | |
queue = [] | |
if "addEventListener" of win | |
on_ = (obj, type, fn) -> | |
obj.addEventListener type, fn, false | |
off_ = (obj, type, fn) -> | |
obj.removeEventListener type, fn, false | |
else | |
on_ = (obj, type, fn) -> | |
obj.attachEvent "on" + type, fn | |
off_ = (obj, type, fn) -> | |
obj.detachEvent "on" + type, fn | |
isArray = Array.isArray or (obj) -> | |
Object::toString.call(obj) is "[object Array]" | |
on_ win, "load", setup | |
setOpacity = (if useFilter then (opacity) -> | |
humaneEl.filters.item("DXImageTransform.Microsoft.Alpha").Opacity = opacity * 100 | |
else (opacity) -> | |
humaneEl.style.opacity = String(opacity) | |
) | |
humane = notifier("log") | |
humane.log = notifier("log") | |
humane.error = notifier("error") | |
humane.info = notifier("info") | |
humane.success = notifier("success") | |
humane.remove = remove | |
humane.timeout = 2500 | |
humane.waitForMove = false | |
humane.clickToClose = false | |
humane.on = (type, handler) -> | |
events[type] = handler | |
win.humane = humane | |
)(root) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment