Don't extend $.

This commit is contained in:
Nicolas Stepien 2013-04-24 23:44:06 +02:00
parent d2eda107c4
commit dcba887954

View File

@ -6,241 +6,238 @@ $ = (selector, root=d.body) ->
$$ = (selector, root=d.body) -> $$ = (selector, root=d.body) ->
[root.querySelectorAll(selector)...] [root.querySelectorAll(selector)...]
$.SECOND = 1000
$.MINUTE = 1000 * 60
$.HOUR = 1000 * 60 * 60
$.DAY = 1000 * 60 * 60 * 24
$.id = (id) ->
d.getElementById id
$.ready = (fc) ->
if d.readyState in ['interactive', 'complete']
$.queueTask fc
return
cb = ->
$.off d, 'DOMContentLoaded', cb
fc()
$.on d, 'DOMContentLoaded', cb
$.formData = (form) ->
if form instanceof HTMLFormElement
return new FormData form
fd = new FormData()
for key, val of form
continue unless val
# XXX GM bug
# if val instanceof Blob
if val.size and val.name
fd.append key, val, val.name
else
fd.append key, val
fd
$.extend = (object, properties) -> $.extend = (object, properties) ->
for key, val of properties for key, val of properties
object[key] = val object[key] = val
return return
$.ajax = (url, callbacks, opts={}) ->
$.extend $, {type, cred, headers, upCallbacks, form, sync} = opts
SECOND: 1000 r = new XMLHttpRequest()
MINUTE: 1000 * 60 type or= form and 'post' or 'get'
HOUR : 1000 * 60 * 60 r.open type, url, !sync
DAY : 1000 * 60 * 60 * 24 for key, val of headers
id: (id) -> r.setRequestHeader key, val
d.getElementById id $.extend r, callbacks
ready: (fc) -> $.extend r.upload, upCallbacks
if d.readyState in ['interactive', 'complete'] r.withCredentials = cred
$.queueTask fc r.send form
return r
cb = -> $.cache = do ->
$.off d, 'DOMContentLoaded', cb reqs = {}
fc() (url, cb) ->
$.on d, 'DOMContentLoaded', cb if req = reqs[url]
formData: (form) -> if req.readyState is 4
if form instanceof HTMLFormElement cb.call req
return new FormData form
fd = new FormData()
for key, val of form
continue unless val
# XXX GM bug
# if val instanceof Blob
if val.size and val.name
fd.append key, val, val.name
else else
fd.append key, val req.callbacks.push cb
fd return
ajax: (url, callbacks, opts={}) -> rm = -> delete reqs[url]
{type, cred, headers, upCallbacks, form, sync} = opts req = $.ajax url,
r = new XMLHttpRequest() onload: (e) ->
type or= form and 'post' or 'get' cb.call @, e for cb in @callbacks
r.open type, url, !sync delete @callbacks
for key, val of headers onabort: rm
r.setRequestHeader key, val onerror: rm
$.extend r, callbacks req.callbacks = [cb]
$.extend r.upload, upCallbacks reqs[url] = req
r.withCredentials = cred $.cb =
r.send form checked: ->
r $.set @name, @checked
cache: do -> Conf[@name] = @checked
reqs = {} value: ->
(url, cb) -> $.set @name, @value.trim()
if req = reqs[url] Conf[@name] = @value
if req.readyState is 4 $.asap = (test, cb) ->
cb.call req if test()
else cb()
req.callbacks.push cb else
return setTimeout $.asap, 25, test, cb
rm = -> delete reqs[url] $.addStyle = (css) ->
req = $.ajax url, style = $.el 'style',
onload: (e) -> textContent: css
cb.call @, e for cb in @callbacks $.asap (-> d.head), ->
delete @callbacks $.add d.head, style
onabort: rm style
onerror: rm $.x = (path, root=d.body) ->
req.callbacks = [cb] # XPathResult.ANY_UNORDERED_NODE_TYPE === 8
reqs[url] = req d.evaluate(path, root, null, 8, null).singleNodeValue
cb: $.addClass = (el, className) ->
checked: -> el.classList.add className
$.set @name, @checked $.rmClass = (el, className) ->
Conf[@name] = @checked el.classList.remove className
value: -> $.hasClass = (el, className) ->
$.set @name, @value.trim() el.classList.contains className
Conf[@name] = @value $.rm = do ->
asap: (test, cb) -> if 'remove' of Element.prototype
if test() (el) -> el.remove()
cb() else
else (el) -> el.parentNode?.removeChild el
setTimeout $.asap, 25, test, cb $.rmAll = (root) ->
addStyle: (css) -> # jsperf.com/emptify-element
style = $.el 'style', while node = root.firstChild
textContent: css # HTMLSelectElement.remove !== Element.remove
$.asap (-> d.head), -> root.removeChild node
$.add d.head, style return
style $.tn = (s) ->
x: (path, root=d.body) -> d.createTextNode s
# XPathResult.ANY_UNORDERED_NODE_TYPE === 8 $.nodes = (nodes) ->
d.evaluate(path, root, null, 8, null).singleNodeValue unless nodes instanceof Array
addClass: (el, className) -> return nodes
el.classList.add className frag = d.createDocumentFragment()
rmClass: (el, className) -> for node in nodes
el.classList.remove className frag.appendChild node
hasClass: (el, className) -> frag
el.classList.contains className $.add = (parent, el) ->
rm: do -> parent.appendChild $.nodes el
if 'remove' of Element.prototype $.prepend = (parent, el) ->
(el) -> el.remove() parent.insertBefore $.nodes(el), parent.firstChild
else $.after = (root, el) ->
(el) -> el.parentNode?.removeChild el root.parentNode.insertBefore $.nodes(el), root.nextSibling
rmAll: (root) -> $.before = (root, el) ->
# jsperf.com/emptify-element root.parentNode.insertBefore $.nodes(el), root
while node = root.firstChild $.replace = (root, el) ->
# HTMLSelectElement.remove !== Element.remove root.parentNode.replaceChild $.nodes(el), root
root.removeChild node $.el = (tag, properties) ->
return el = d.createElement tag
tn: (s) -> $.extend el, properties if properties
d.createTextNode s el
nodes: (nodes) -> $.on = (el, events, handler) ->
unless nodes instanceof Array for event in events.split ' '
return nodes el.addEventListener event, handler, false
frag = d.createDocumentFragment() return
for node in nodes $.off = (el, events, handler) ->
frag.appendChild node for event in events.split ' '
frag el.removeEventListener event, handler, false
add: (parent, el) -> return
parent.appendChild $.nodes el $.event = (event, detail, root=d) ->
prepend: (parent, el) -> root.dispatchEvent new CustomEvent event, {bubbles: true, detail}
parent.insertBefore $.nodes(el), parent.firstChild $.open = do ->
after: (root, el) -> if GM_openInTab?
root.parentNode.insertBefore $.nodes(el), root.nextSibling (URL) ->
before: (root, el) -> # XXX fix GM opening file://// for protocol-less URLs.
root.parentNode.insertBefore $.nodes(el), root a = $.el 'a', href: URL
replace: (root, el) -> GM_openInTab a.href
root.parentNode.replaceChild $.nodes(el), root else
el: (tag, properties) -> (URL) -> window.open URL, '_blank'
el = d.createElement tag $.debounce = (wait, fn) ->
$.extend el, properties if properties timeout = null
el that = null
on: (el, events, handler) -> args = null
for event in events.split ' ' exec = ->
el.addEventListener event, handler, false fn.apply that, args
return
off: (el, events, handler) ->
for event in events.split ' '
el.removeEventListener event, handler, false
return
event: (event, detail, root=d) ->
root.dispatchEvent new CustomEvent event, {bubbles: true, detail}
open: do ->
if GM_openInTab?
(URL) ->
# XXX fix GM opening file://// for protocol-less URLs.
a = $.el 'a', href: URL
GM_openInTab a.href
else
(URL) -> window.open URL, '_blank'
debounce: (wait, fn) ->
timeout = null timeout = null
that = null ->
args = null args = arguments
exec = -> that = this
fn.apply that, args if timeout
timeout = null # stop current reset
-> clearTimeout timeout
args = arguments else
that = this exec()
if timeout
# stop current reset
clearTimeout timeout
else
exec()
# after wait, let next invocation execute immediately # after wait, let next invocation execute immediately
timeout = setTimeout exec, wait timeout = setTimeout exec, wait
queueTask: do -> $.queueTask = do ->
# inspired by https://www.w3.org/Bugs/Public/show_bug.cgi?id=15007 # inspired by https://www.w3.org/Bugs/Public/show_bug.cgi?id=15007
taskQueue = [] taskQueue = []
execTask = -> execTask = ->
task = taskQueue.shift() task = taskQueue.shift()
func = task[0] func = task[0]
args = Array::slice.call task, 1 args = Array::slice.call task, 1
func.apply func, args func.apply func, args
if window.MessageChannel if window.MessageChannel
taskChannel = new MessageChannel() taskChannel = new MessageChannel()
taskChannel.port1.onmessage = execTask taskChannel.port1.onmessage = execTask
-> ->
taskQueue.push arguments taskQueue.push arguments
taskChannel.port2.postMessage null taskChannel.port2.postMessage null
else # XXX Firefox else # XXX Firefox
-> ->
taskQueue.push arguments taskQueue.push arguments
setTimeout execTask, 0 setTimeout execTask, 0
globalEval: (code) -> $.globalEval = (code) ->
script = $.el 'script', script = $.el 'script',
textContent: code textContent: code
$.add (d.head or doc), script $.add (d.head or doc), script
$.rm script $.rm script
bytesToString: (size) -> $.bytesToString = (size) ->
unit = 0 # Bytes unit = 0 # Bytes
while size >= 1024 while size >= 1024
size /= 1024 size /= 1024
unit++ unit++
# Remove trailing 0s. # Remove trailing 0s.
size = size =
if unit > 1 if unit > 1
# Keep the size as a float if the size is greater than 2^20 B. # Keep the size as a float if the size is greater than 2^20 B.
# Round to hundredth. # Round to hundredth.
Math.round(size * 100) / 100 Math.round(size * 100) / 100
else else
# Round to an integer otherwise. # Round to an integer otherwise.
Math.round size Math.round size
"#{size} #{['B', 'KB', 'MB', 'GB'][unit]}" "#{size} #{['B', 'KB', 'MB', 'GB'][unit]}"
syncing: {} $.syncing = {}
sync: do -> $.sync = do ->
<% if (type === 'crx') { %> <% if (type === 'crx') { %>
chrome.storage.onChanged.addListener (changes) -> chrome.storage.onChanged.addListener (changes) ->
for key of changes for key of changes
if cb = $.syncing[key] if cb = $.syncing[key]
cb changes[key].newValue cb changes[key].newValue
return return
(key, cb) -> $.syncing[key] = cb (key, cb) -> $.syncing[key] = cb
<% } else { %> <% } else { %>
window.addEventListener 'storage', (e) -> $.on window, 'storage', (e) ->
if cb = $.syncing[e.key] if cb = $.syncing[e.key]
cb JSON.parse e.newValue cb JSON.parse e.newValue
, false (key, cb) -> $.syncing[g.NAMESPACE + key] = cb
(key, cb) -> $.syncing[g.NAMESPACE + key] = cb
<% } %> <% } %>
item: (key, val) -> $.item = (key, val) ->
item = {} item = {}
item[key] = val item[key] = val
item item
<% if (type === 'crx') { %> <% if (type === 'crx') { %>
# https://developer.chrome.com/extensions/storage.html # https://developer.chrome.com/extensions/storage.html
delete: (keys) -> $.delete = (keys) ->
chrome.storage.sync.remove keys chrome.storage.sync.remove keys
get: (key, val, cb) -> $.get = (key, val, cb) ->
if typeof cb is 'function' if typeof cb is 'function'
items = $.item key, val items = $.item key, val
else else
items = key items = key
cb = val cb = val
chrome.storage.sync.get items, cb chrome.storage.sync.get items, cb
set: (key, val) -> $.set = (key, val) ->
items = if typeof key is 'string' items = if typeof key is 'string'
$.item key, val $.item key, val
else else
key key
chrome.storage.sync.set items chrome.storage.sync.set items
<% } else if (type === 'userjs') { %> <% } else if (type === 'userjs') { %>
do -> do ->
# http://www.opera.com/docs/userjs/specs/#scriptstorage # http://www.opera.com/docs/userjs/specs/#scriptstorage
@ -287,38 +284,38 @@ do ->
return return
<% } else { %> <% } else { %>
# http://wiki.greasespot.net/Main_Page # http://wiki.greasespot.net/Main_Page
delete: (keys) -> $.delete = (keys) ->
unless keys instanceof Array unless keys instanceof Array
keys = [keys] keys = [keys]
for key in keys for key in keys
key = g.NAMESPACE + key key = g.NAMESPACE + key
localStorage.removeItem key localStorage.removeItem key
GM_deleteValue key GM_deleteValue key
return return
get: (key, val, cb) -> $.get = (key, val, cb) ->
if typeof cb is 'function' if typeof cb is 'function'
items = $.item key, val items = $.item key, val
else else
items = key items = key
cb = val cb = val
$.queueTask -> $.queueTask ->
for key of items for key of items
if val = GM_getValue g.NAMESPACE + key if val = GM_getValue g.NAMESPACE + key
items[key] = JSON.parse val items[key] = JSON.parse val
cb items cb items
set: do -> $.set = do ->
set = (key, val) -> set = (key, val) ->
key = g.NAMESPACE + key key = g.NAMESPACE + key
val = JSON.stringify val val = JSON.stringify val
if key of $.syncing if key of $.syncing
# for `storage` events # for `storage` events
localStorage.setItem key, val localStorage.setItem key, val
GM_setValue key, val GM_setValue key, val
(keys, val) -> (keys, val) ->
if typeof keys is 'string' if typeof keys is 'string'
set keys, val set keys, val
return
for key, val of keys
set key, val
return return
for key, val of keys
set key, val
return
<% } %> <% } %>