Created
January 8, 2012 21:38
-
-
Save PetrKaleta/1579788 to your computer and use it in GitHub Desktop.
Micro JavaScript library written in CoffeeScript to solve my needs when creating mobile web apps for iOS.
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
### | |
Caffeinated.js 1.0.1 | |
(c) 2012 Petr Kaleta, @petrkaleta | |
Caffeinated.js is freely distributable under the MIT license. | |
Micro JavaScript library written in CoffeeScript to make my life easier when creating mobile web apps for iOS. | |
I don't like extending built-in JavaScript objects, so I've created this lib as an separate object. | |
I used underscore identifier to make its calls short as possible. So please do not mess this lib with gorgeous | |
Underscore.js lib by Jeremy Ashkenas, DocumentCloud Inc. | |
Some methods are inspired or borrowed from popular JavaScript frameworks like jQuery, Underscore.js and Prototype.js | |
Note: feel free to change lib's identifier to prevent conflicts with Underscore.js | |
Changelog: | |
1.0.1: | |
- added offset(el) method to get element's position relative to window | |
- renamed scrollTop method to scrollTo(target) and now accepts numeric or element attribute | |
to specify scroll position | |
### | |
_ = | |
# Caffeinated Way | |
# -------------------------------------------------- | |
# More caffeinated way to setTimeout | |
after: (ms, func) -> setTimeout func, ms | |
# More caffeinated way to setInterval | |
every: (ms, func) -> setInterval func, ms | |
# Object Related Functions | |
# -------------------------------------------------- | |
# Fill object with missing default properties | |
defaults: (obj, def) -> | |
(obj[prop] = def[prop] unless obj[prop]?) for prop of def | |
obj | |
# Detection Properties | |
# -------------------------------------------------- | |
# Supports browser's feature? | |
supports: { | |
touch : 'ontouchstart' of window | |
history : window.history? | |
classList : 'classList' of document.createElement 'span' | |
} | |
# CSS Related Functions | |
# -------------------------------------------------- | |
# Show element | |
show: (el) -> | |
el.style['display'] = '' if el.style['display'] is 'none' | |
# Hide element | |
hide: (el) -> | |
el.style['display'] = 'none' unless el.style['display'] is 'none' | |
# Add CSS class | |
addClass: (el, cls) -> | |
if @supports.classList | |
el.classList.add cls | |
else | |
el.className += " #{cls}" unless @hasClass el, cls | |
# Remove CSS class | |
removeClass: (el, cls) -> | |
if @supports.classList | |
el.classList.remove cls | |
else | |
el.className = el.className.replace new RegExp('(\\s|^)' + cls + '(\\s|$)') if @hasClass el, cls | |
# Toggle CSS class | |
toggleClass: (el, cls) -> | |
if @supports.classList | |
el.classList.toggle cls | |
else | |
if @hasClass el, cls then @removeClass el, cls else @addClass el, cls | |
# Has CSS class? | |
hasClass: (el, cls) -> | |
if @supports.classList | |
el.classList.contains cls | |
else | |
el.className.match new RegExp('(\\s|^)' + cls + '(\\s|$)') | |
# Switch CSS class with one of its variants | |
switchClass: (el, cls1, cls2) -> | |
if @hasClass(el, cls1) or @hasClass(el, cls2) | |
@toggleClass el, cls1 | |
@toggleClass el, cls2 | |
else | |
@addClass el, cls1 | |
# DOM Related Functions | |
# -------------------------------------------------- | |
# Append contents (HTML/DOMElement) into element | |
append: (el, contents) -> | |
# if contents is HTML append it using wrapper else if its DOMElement append it directly | |
if typeof contents is 'string' | |
# used just for htmlString => DOMElement conversion | |
wrap = document.createElement 'span' | |
wrap.innerHTML = contents | |
# append all first childs | |
el.appendChild wrap.firstChild while wrap.firstChild | |
else if contents.nodeType? | |
el.appendChild contents | |
return | |
# Remove all contents of element | |
empty: (el) -> | |
el.removeChild el.firstChild while el.firstChild | |
# Get HTML5 data attribute value | |
# Automatic type conversion (boolean, numeric, JSON, string) | |
getData: (el, key) -> | |
data = el.getAttribute "data-#{key}" | |
if typeof data is 'string' | |
try | |
value = if data is 'true' then true else | |
if data is 'false' then false else | |
if data is 'null' then null else | |
if not isNaN(parseFloat(data)) and isFinite(data) then parseFloat(data) else | |
if /^(?:\{.*\}|\[.*\])$/.test(data) then JSON.parse(data) else data | |
value | |
catch error | |
data | |
# Set HTML5 data attribute value | |
# Objects are stringified to JSON | |
setData: (el, key, value) -> | |
value = if typeof value is 'object' then JSON.stringify value else value | |
el.setAttribute "data-#{key}", value | |
# Get elements offset relative to window | |
offset: (el) -> | |
curLeft = curTop = 0 | |
if el.offsetParent | |
loop | |
curLeft += el.offsetLeft | |
curTop += el.offsetTop | |
break unless el = el.offsetParent | |
left: curLeft, top: curTop | |
# Scroll window by y axis to the target (numeric position/DOMElement's position) | |
scrollTo: (target) -> | |
if typeof target is 'number' | |
window.scrollTo 0, target | |
else if target.nodeType? | |
window.scrollTo 0, @offset(target).top | |
# Simulate click event using touch events (remove click delay on iOS) | |
# Uses click event if browser has no touch support | |
listenTouchClick: (el, func, shouldPreventAction = no) -> | |
if @supports.touch | |
hasMoved = false | |
onTouchStart = (e) -> | |
e.preventDefault() if shouldPreventAction | |
hasMoved = false | |
# detection listeners | |
el.addEventListener 'touchmove', onTouchMove, no | |
el.addEventListener 'touchend', onTouchEnd, no | |
onTouchMove = -> | |
hasMoved = true | |
onTouchEnd = (e) -> | |
el.removeEventListener 'touchmove', onTouchMove, no | |
el.removeEventListener 'touchend', onTouchEnd, no | |
# callback | |
func.call(null, e) unless hasMoved | |
el.addEventListener 'touchstart', onTouchStart, no | |
else | |
el.addEventListener 'click', func, no | |
# URL Related Functions | |
# -------------------------------------------------- | |
# Get url params Object | |
params: -> | |
hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split '&' | |
obj = {} | |
for hash in hashes | |
[key, value] = hash.split '=' | |
obj[key] = value | |
obj | |
# Change URL in addressbar | |
# Makes redirect if browser has no history support | |
updateUrl: (newUrl) -> | |
if @supports.history | |
window.history.replaceState null, null, newUrl | |
else | |
window.location.href = newUrl |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment