A bit of cleanup in $. Add $.hasClass.

This commit is contained in:
Nicolas Stepien 2012-08-25 02:59:55 +02:00
parent 7b49ae4c76
commit e9f3c0e49b
2 changed files with 116 additions and 114 deletions

View File

@ -214,7 +214,7 @@
el.className = 'reply dialog'; el.className = 'reply dialog';
el.innerHTML = html; el.innerHTML = html;
el.id = id; el.id = id;
el.style.cssText = localStorage.getItem("" + Main.namespace + id + ".position") || position; el.style.cssText = localStorage.getItem("" + $.NAMESPACE + id + ".position") || position;
el.querySelector('.move').addEventListener('mousedown', UI.dragstart, false); el.querySelector('.move').addEventListener('mousedown', UI.dragstart, false);
return el; return el;
}, },
@ -243,7 +243,7 @@
return style.bottom = top ? null : '0px'; return style.bottom = top ? null : '0px';
}, },
dragend: function() { dragend: function() {
localStorage.setItem("" + Main.namespace + UI.el.id + ".position", UI.el.style.cssText); localStorage.setItem("" + $.NAMESPACE + UI.el.id + ".position", UI.el.style.cssText);
d.removeEventListener('mousemove', UI.drag, false); d.removeEventListener('mousemove', UI.drag, false);
d.removeEventListener('mouseup', UI.dragend, false); d.removeEventListener('mouseup', UI.dragend, false);
return delete UI.el; return delete UI.el;
@ -293,16 +293,24 @@
}; };
$.extend($, { $.extend($, {
NAMESPACE: '4chan_X.',
SECOND: 1000, SECOND: 1000,
MINUTE: 1000 * 60, MINUTE: 1000 * 60,
HOUR: 1000 * 60 * 60, HOUR: 1000 * 60 * 60,
DAY: 1000 * 60 * 60 * 24, DAY: 1000 * 60 * 60 * 24,
log: console.log.bind(console), log: console.log.bind(console),
engine: /WebKit|Presto|Gecko/.exec(navigator.userAgent)[0].toLowerCase(), engine: /WebKit|Presto|Gecko/.exec(navigator.userAgent)[0].toLowerCase(),
id: function(id) {
return d.getElementById(id);
},
ready: function(fc) { ready: function(fc) {
var cb; var cb;
if (/interactive|complete/.test(d.readyState)) { if (/interactive|complete/.test(d.readyState)) {
return setTimeout(fc); try {
fc();
} finally {
return;
}
} }
cb = function() { cb = function() {
$.off(d, 'DOMContentLoaded', cb); $.off(d, 'DOMContentLoaded', cb);
@ -312,25 +320,21 @@
}, },
sync: function(key, cb) { sync: function(key, cb) {
return $.on(window, 'storage', function(e) { return $.on(window, 'storage', function(e) {
if (e.key === ("" + Main.namespace + key)) { if (e.key === ("" + $.NAMESPACE + key)) {
return cb(JSON.parse(e.newValue)); return cb(JSON.parse(e.newValue));
} }
}); });
}, },
id: function(id) { formData: function(form) {
return d.getElementById(id);
},
formData: function(arg) {
var fd, key, val; var fd, key, val;
if (arg instanceof HTMLFormElement) { if (form instanceof HTMLFormElement) {
fd = new FormData(arg); return new FormData(form);
} else { }
fd = new FormData(); fd = new FormData();
for (key in arg) { for (key in form) {
val = arg[key]; val = form[key];
if (val) { if (val) {
fd.append(key, val); fd.append(key, val);
}
} }
} }
return fd; return fd;
@ -354,35 +358,34 @@
return r; return r;
}, },
cache: function(url, cb) { cache: function(url, cb) {
var req; var req, reqs, _base;
if (req = $.cache.requests[url]) { reqs = (_base = $.cache).requests || (_base.requests = {});
if (req = reqs[url]) {
if (req.readyState === 4) { if (req.readyState === 4) {
return cb.call(req); cb.call(req);
} else { } else {
return req.callbacks.push(cb); req.callbacks.push(cb);
} }
} else { return;
req = $.ajax(url, {
onload: function() {
var _i, _len, _ref, _results;
_ref = this.callbacks;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
cb = _ref[_i];
_results.push(cb.call(this));
}
return _results;
},
onabort: function() {
return delete $.cache.requests[url];
},
onerror: function() {
return delete $.cache.requests[url];
}
});
req.callbacks = [cb];
return $.cache.requests[url] = req;
} }
req = $.ajax(url, {
onload: function() {
var _i, _len, _ref;
_ref = this.callbacks;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
cb = _ref[_i];
cb.call(this);
}
},
onabort: function() {
return delete reqs[url];
},
onerror: function() {
return delete reqs[url];
}
});
req.callbacks = [cb];
return reqs[url] = req;
}, },
cb: { cb: {
checked: function() { checked: function() {
@ -414,6 +417,9 @@
rmClass: function(el, className) { rmClass: function(el, className) {
return el.classList.remove(className); return el.classList.remove(className);
}, },
hasClass: function(el, className) {
return el.classList.contains(className);
},
rm: function(el) { rm: function(el) {
return el.parentNode.removeChild(el); return el.parentNode.removeChild(el);
}, },
@ -432,11 +438,11 @@
} }
return frag; return frag;
}, },
add: function(parent, children) { add: function(parent, el) {
return parent.appendChild($.nodes(children)); return parent.appendChild($.nodes(el));
}, },
prepend: function(parent, children) { prepend: function(parent, el) {
return parent.insertBefore($.nodes(children), parent.firstChild); return parent.insertBefore($.nodes(el), parent.firstChild);
}, },
after: function(root, el) { after: function(root, el) {
return root.parentNode.insertBefore($.nodes(el), root.nextSibling); return root.parentNode.insertBefore($.nodes(el), root.nextSibling);
@ -472,10 +478,7 @@
} }
}, },
open: function(url) { open: function(url) {
return (GM_openInTab || window.open)(location.protocol + url, '_blank'); return (GM_openInTab || window.open)(url, '_blank');
},
event: function(el, e) {
return el.dispatchEvent(e);
}, },
globalEval: function(code) { globalEval: function(code) {
var script; var script;
@ -487,9 +490,9 @@
}, },
shortenFilename: function(filename, isOP) { shortenFilename: function(filename, isOP) {
var threshold; var threshold;
threshold = 30 + 10 * isOP; threshold = isOP ? 40 : 30;
if (filename.replace(/\.\w+$/, '').length > threshold) { if (filename.length - 4 > threshold) {
return "" + filename.slice(0, threshold - 5) + "(...)" + (filename.match(/\.\w+$/)); return "" + filename.slice(0, threshold - 5) + "(...)." + (filename.match(/\w+$/));
} else { } else {
return filename; return filename;
} }
@ -506,41 +509,38 @@
} }
}); });
$.cache.requests = {};
$.extend($, typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null ? { $.extend($, typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null ? {
"delete": function(name) { "delete": function(name) {
name = Main.namespace + name; return GM_deleteValue($.NAMESPACE + name);
return GM_deleteValue(name);
}, },
get: function(name, defaultValue) { get: function(name, defaultValue) {
var value; var value;
name = Main.namespace + name; if (value = GM_getValue($.NAMESPACE + name)) {
if (value = GM_getValue(name)) {
return JSON.parse(value); return JSON.parse(value);
} else { } else {
return defaultValue; return defaultValue;
} }
}, },
set: function(name, value) { set: function(name, value) {
name = Main.namespace + name; name = $.NAMESPACE + name;
localStorage.setItem(name, JSON.stringify(value)); value = JSON.stringify(value);
return GM_setValue(name, JSON.stringify(value)); localStorage.setItem(name, value);
return GM_setValue(name, value);
} }
} : { } : {
"delete": function(name) { "delete": function(name) {
return localStorage.removeItem(Main.namespace + name); return localStorage.removeItem($.NAMESPACE + name);
}, },
get: function(name, defaultValue) { get: function(name, defaultValue) {
var value; var value;
if (value = localStorage.getItem(Main.namespace + name)) { if (value = localStorage.getItem($.NAMESPACE + name)) {
return JSON.parse(value); return JSON.parse(value);
} else { } else {
return defaultValue; return defaultValue;
} }
}, },
set: function(name, value) { set: function(name, value) {
return localStorage.setItem(Main.namespace + name, JSON.stringify(value)); return localStorage.setItem($.NAMESPACE + name, JSON.stringify(value));
} }
}); });

View File

@ -175,7 +175,7 @@ UI =
el.className = 'reply dialog' el.className = 'reply dialog'
el.innerHTML = html el.innerHTML = html
el.id = id el.id = id
el.style.cssText = localStorage.getItem("#{Main.namespace}#{id}.position") or position el.style.cssText = localStorage.getItem("#{$.NAMESPACE}#{id}.position") or position
el.querySelector('.move').addEventListener 'mousedown', UI.dragstart, false el.querySelector('.move').addEventListener 'mousedown', UI.dragstart, false
el el
dragstart: (e) -> dragstart: (e) ->
@ -207,7 +207,7 @@ UI =
style.right = if left then null else '0px' style.right = if left then null else '0px'
style.bottom = if top then null else '0px' style.bottom = if top then null else '0px'
dragend: -> dragend: ->
localStorage.setItem "#{Main.namespace}#{UI.el.id}.position", UI.el.style.cssText localStorage.setItem "#{$.NAMESPACE}#{UI.el.id}.position", UI.el.style.cssText
d.removeEventListener 'mousemove', UI.drag, false d.removeEventListener 'mousemove', UI.drag, false
d.removeEventListener 'mouseup', UI.dragend, false d.removeEventListener 'mouseup', UI.dragend, false
delete UI.el delete UI.el
@ -250,33 +250,35 @@ $.extend = (object, properties) ->
return return
$.extend $, $.extend $,
NAMESPACE: '4chan_X.'
SECOND: 1000 SECOND: 1000
MINUTE: 1000 *60 MINUTE: 1000 *60
HOUR : 1000 *60 * 60 HOUR : 1000 *60 * 60
DAY : 1000 *60 * 60 * 24 DAY : 1000 *60 * 60 * 24
log: console.log.bind console log: console.log.bind console
engine: /WebKit|Presto|Gecko/.exec(navigator.userAgent)[0].toLowerCase() engine: /WebKit|Presto|Gecko/.exec(navigator.userAgent)[0].toLowerCase()
id: (id) ->
d.getElementById id
ready: (fc) -> ready: (fc) ->
if /interactive|complete/.test d.readyState if /interactive|complete/.test d.readyState
# Execute the functions in parallel. try
# If one fails, do not stop the others. fc()
return setTimeout fc finally
return
cb = -> cb = ->
$.off d, 'DOMContentLoaded', cb $.off d, 'DOMContentLoaded', cb
fc() fc()
$.on d, 'DOMContentLoaded', cb $.on d, 'DOMContentLoaded', cb
sync: (key, cb) -> sync: (key, cb) ->
$.on window, 'storage', (e) -> $.on window, 'storage', (e) ->
cb JSON.parse e.newValue if e.key is "#{Main.namespace}#{key}" if e.key is "#{$.NAMESPACE}#{key}"
id: (id) -> cb JSON.parse e.newValue
d.getElementById id formData: (form) ->
formData: (arg) -> if form instanceof HTMLFormElement
if arg instanceof HTMLFormElement return new FormData form
fd = new FormData arg fd = new FormData()
else for key, val of form
fd = new FormData() fd.append key, val if val
for key, val of arg
fd.append key, val if val
fd fd
ajax: (url, callbacks, opts={}) -> ajax: (url, callbacks, opts={}) ->
{type, headers, upCallbacks, form} = opts {type, headers, upCallbacks, form} = opts
@ -290,18 +292,21 @@ $.extend $,
r.send form r.send form
r r
cache: (url, cb) -> cache: (url, cb) ->
if req = $.cache.requests[url] reqs = $.cache.requests or= {}
if req = reqs[url]
if req.readyState is 4 if req.readyState is 4
cb.call req cb.call req
else else
req.callbacks.push cb req.callbacks.push cb
else return
req = $.ajax url, req = $.ajax url,
onload: -> cb.call @ for cb in @callbacks onload: ->
onabort: -> delete $.cache.requests[url] cb.call @ for cb in @callbacks
onerror: -> delete $.cache.requests[url] return
req.callbacks = [cb] onabort: -> delete reqs[url]
$.cache.requests[url] = req onerror: -> delete reqs[url]
req.callbacks = [cb]
reqs[url] = req
cb: cb:
checked: -> checked: ->
$.set @name, @checked $.set @name, @checked
@ -316,12 +321,13 @@ $.extend $,
style style
x: (path, root=d.body) -> x: (path, root=d.body) ->
# XPathResult.ANY_UNORDERED_NODE_TYPE is 8 # XPathResult.ANY_UNORDERED_NODE_TYPE is 8
d.evaluate(path, root, null, 8, null). d.evaluate(path, root, null, 8, null).singleNodeValue
singleNodeValue
addClass: (el, className) -> addClass: (el, className) ->
el.classList.add className el.classList.add className
rmClass: (el, className) -> rmClass: (el, className) ->
el.classList.remove className el.classList.remove className
hasClass: (el, className) ->
el.classList.contains className
rm: (el) -> rm: (el) ->
el.parentNode.removeChild el el.parentNode.removeChild el
tn: (s) -> tn: (s) ->
@ -329,17 +335,17 @@ $.extend $,
nodes: (nodes) -> nodes: (nodes) ->
# In (at least) Chrome, elements created inside different # In (at least) Chrome, elements created inside different
# scripts/window contexts inherit from unequal prototypes. # scripts/window contexts inherit from unequal prototypes.
# window_ext1.Node !== window_ext2.Node # window_context1.Node !== window_context2.Node
unless nodes instanceof Array unless nodes instanceof Array
return nodes return nodes
frag = d.createDocumentFragment() frag = d.createDocumentFragment()
for node in nodes for node in nodes
frag.appendChild node frag.appendChild node
frag frag
add: (parent, children) -> add: (parent, el) ->
parent.appendChild $.nodes children parent.appendChild $.nodes el
prepend: (parent, children) -> prepend: (parent, el) ->
parent.insertBefore $.nodes(children), parent.firstChild parent.insertBefore $.nodes(el), parent.firstChild
after: (root, el) -> after: (root, el) ->
root.parentNode.insertBefore $.nodes(el), root.nextSibling root.parentNode.insertBefore $.nodes(el), root.nextSibling
before: (root, el) -> before: (root, el) ->
@ -359,20 +365,19 @@ $.extend $,
el.removeEventListener event, handler, false el.removeEventListener event, handler, false
return return
open: (url) -> open: (url) ->
(GM_openInTab or window.open) location.protocol + url, '_blank' (GM_openInTab or window.open) url, '_blank'
event: (el, e) ->
el.dispatchEvent e
globalEval: (code) -> globalEval: (code) ->
script = $.el 'script', textContent: code script = $.el 'script',
textContent: code
$.add d.head, script $.add d.head, script
$.rm script $.rm script
shortenFilename: (filename, isOP) -> shortenFilename: (filename, isOP) ->
# FILENAME SHORTENING SCIENCE: # FILENAME SHORTENING SCIENCE:
# OPs have a +10 characters threshold. # OPs have a +10 characters threshold.
# The file extension is not taken into account. # The file extension is not taken into account.
threshold = 30 + 10 * isOP threshold = if isOP then 40 else 30
if filename.replace(/\.\w+$/, '').length > threshold if filename.length - 4 > threshold
"#{filename[...threshold - 5]}(...)#{filename.match(/\.\w+$/)}" "#{filename[...threshold - 5]}(...).#{filename.match(/\w+$/)}"
else else
filename filename
bytesToString: (size) -> bytesToString: (size) ->
@ -391,34 +396,31 @@ $.extend $,
Math.round size Math.round size
"#{size} #{['B', 'KB', 'MB', 'GB'][unit]}" "#{size} #{['B', 'KB', 'MB', 'GB'][unit]}"
$.cache.requests = {}
$.extend $, $.extend $,
if GM_deleteValue? if GM_deleteValue?
delete: (name) -> delete: (name) ->
name = Main.namespace + name GM_deleteValue $.NAMESPACE + name
GM_deleteValue name
get: (name, defaultValue) -> get: (name, defaultValue) ->
name = Main.namespace + name if value = GM_getValue $.NAMESPACE + name
if value = GM_getValue name
JSON.parse value JSON.parse value
else else
defaultValue defaultValue
set: (name, value) -> set: (name, value) ->
name = Main.namespace + name name = $.NAMESPACE + name
value = JSON.stringify value
# for `storage` events # for `storage` events
localStorage.setItem name, JSON.stringify value localStorage.setItem name, value
GM_setValue name, JSON.stringify value GM_setValue name, value
else else
delete: (name) -> delete: (name) ->
localStorage.removeItem Main.namespace + name localStorage.removeItem $.NAMESPACE + name
get: (name, defaultValue) -> get: (name, defaultValue) ->
if value = localStorage.getItem Main.namespace + name if value = localStorage.getItem $.NAMESPACE + name
JSON.parse value JSON.parse value
else else
defaultValue defaultValue
set: (name, value) -> set: (name, value) ->
localStorage.setItem Main.namespace + name, JSON.stringify value localStorage.setItem $.NAMESPACE + name, JSON.stringify value
$$ = (selector, root=d.body) -> $$ = (selector, root=d.body) ->
Array::slice.call root.querySelectorAll selector Array::slice.call root.querySelectorAll selector