undo d -> $.d

This commit is contained in:
James Campos 2012-03-16 04:11:56 -07:00
parent 128dd341f7
commit 5dafc95c5d
2 changed files with 164 additions and 162 deletions

View File

@ -73,7 +73,7 @@
*/
(function() {
var $, $$, Anonymize, AutoGif, Config, ExpandComment, ExpandThread, Favicon, FileInfo, Filter, GetTitle, ImageExpand, ImageHover, Keybinds, Main, Nav, Options, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, Quotify, Redirect, ReplyHiding, ReportButton, RevealSpoilers, Sauce, StrikethroughQuotes, ThreadHiding, ThreadStats, Threading, Time, TitlePost, UI, Unread, Updater, Watcher, _base;
var $, $$, Anonymize, AutoGif, Config, ExpandComment, ExpandThread, Favicon, FileInfo, Filter, GetTitle, ImageExpand, ImageHover, Keybinds, Main, Nav, Options, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, Quotify, Redirect, ReplyHiding, ReportButton, RevealSpoilers, Sauce, StrikethroughQuotes, ThreadHiding, ThreadStats, Threading, Time, TitlePost, UI, Unread, Updater, Watcher, d, _base;
Config = {
main: {
@ -195,7 +195,7 @@
UI = {
dialog: function(id, position, html) {
var el, saved;
el = $.d.createElement('div');
el = d.createElement('div');
el.className = 'reply dialog';
el.innerHTML = html;
el.id = id;
@ -207,13 +207,13 @@
var el, rect;
e.preventDefault();
UI.el = el = this.parentNode;
$.d.addEventListener('mousemove', UI.drag, false);
$.d.addEventListener('mouseup', UI.dragend, false);
d.addEventListener('mousemove', UI.drag, false);
d.addEventListener('mouseup', UI.dragend, false);
rect = el.getBoundingClientRect();
UI.dx = e.clientX - rect.left;
UI.dy = e.clientY - rect.top;
UI.width = $.d.body.clientWidth - el.offsetWidth;
return UI.height = $.d.body.clientHeight - el.offsetHeight;
UI.width = d.body.clientWidth - el.offsetWidth;
return UI.height = d.body.clientHeight - el.offsetHeight;
},
drag: function(e) {
var bottom, left, right, style, top;
@ -233,15 +233,15 @@
var el;
el = UI.el;
localStorage["" + Main.namespace + el.id + ".position"] = el.style.cssText;
$.d.removeEventListener('mousemove', UI.drag, false);
return $.d.removeEventListener('mouseup', UI.dragend, false);
d.removeEventListener('mousemove', UI.drag, false);
return d.removeEventListener('mouseup', UI.dragend, false);
},
hover: function(e) {
var clientHeight, clientWidth, clientX, clientY, el, height, style, top, _ref;
clientX = e.clientX, clientY = e.clientY;
el = UI.el;
style = el.style;
_ref = $.d.body, clientHeight = _ref.clientHeight, clientWidth = _ref.clientWidth;
_ref = d.body, clientHeight = _ref.clientHeight, clientWidth = _ref.clientWidth;
height = el.offsetHeight;
top = clientY - 120;
style.top = clientHeight <= height || top <= 0 ? 0 : top + height >= clientHeight ? clientHeight - height : top;
@ -259,6 +259,8 @@
}
};
d = document;
/*
loosely follows the jquery api:
http://api.jquery.com/
@ -266,7 +268,7 @@
*/
$ = function(selector, root) {
if (root == null) root = $.d.body;
if (root == null) root = d.body;
return root.querySelector(selector);
};
@ -284,16 +286,15 @@
HOUR: 1000 * 60 * 60,
DAY: 1000 * 60 * 60 * 24,
log: typeof (_base = console.log).bind === "function" ? _base.bind(console) : void 0,
d: document,
engine: /WebKit|Presto|Gecko/.exec(navigator.userAgent)[0].toLowerCase(),
ready: function(fc) {
var cb;
if (/interactive|complete/.test($.d.readyState)) return setTimeout(fc);
if (/interactive|complete/.test(d.readyState)) return setTimeout(fc);
cb = function() {
$.off($.d, 'DOMContentLoaded', cb);
$.off(d, 'DOMContentLoaded', cb);
return fc();
};
return $.on($.d, 'DOMContentLoaded', cb);
return $.on(d, 'DOMContentLoaded', cb);
},
sync: function(key, cb) {
return $.on(window, 'storage', function(e) {
@ -303,7 +304,7 @@
});
},
id: function(id) {
return $.d.getElementById(id);
return d.getElementById(id);
},
ajax: function(url, callbacks, opts) {
var form, headers, key, r, type, upCallbacks, val;
@ -367,12 +368,12 @@
style = $.el('style', {
textContent: css
});
$.add($.d.head, style);
$.add(d.head, style);
return style;
},
x: function(path, root) {
if (root == null) root = $.d.body;
return $.d.evaluate(path, root, null, 8, null).singleNodeValue;
if (root == null) root = d.body;
return d.evaluate(path, root, null, 8, null).singleNodeValue;
},
addClass: function(el, className) {
return el.classList.add(className);
@ -384,12 +385,12 @@
return el.parentNode.removeChild(el);
},
tn: function(s) {
return $.d.createTextNode(s);
return d.createTextNode(s);
},
nodes: function(nodes) {
var frag, node, _i, _len;
if (nodes instanceof Node) return nodes;
frag = $.d.createDocumentFragment();
frag = d.createDocumentFragment();
for (_i = 0, _len = nodes.length; _i < _len; _i++) {
node = nodes[_i];
frag.appendChild(node);
@ -413,7 +414,7 @@
},
el: function(tag, properties) {
var el;
el = $.d.createElement(tag);
el = d.createElement(tag);
if (properties) $.extend(el, properties);
return el;
},
@ -439,7 +440,7 @@
0200 EST (UTC-05) = 0700 UTC
0200 EDT (UTC-04) = 0600 UTC
*/
var d, date, day, hours, month, sunday;
var date, day, hours, month, sunday;
d = new Date();
date = d.getUTCDate();
day = d.getUTCDay();
@ -507,7 +508,7 @@
});
$$ = function(selector, root) {
if (root == null) root = $.d.body;
if (root == null) root = d.body;
return Array.prototype.slice.call(root.querySelectorAll(selector));
};
@ -635,7 +636,7 @@
comment: function(post) {
var data, i, nodes, text, _ref;
text = [];
nodes = $.d.evaluate('.//br|.//text()', post.el.lastChild, null, 7, null);
nodes = d.evaluate('.//br|.//text()', post.el.lastChild, null, 7, null);
for (i = 0, _ref = nodes.snapshotLength; 0 <= _ref ? i < _ref : i > _ref; 0 <= _ref ? i++ : i--) {
text.push((data = nodes.snapshotItem(i).data) ? data : '\n');
}
@ -713,10 +714,10 @@
a.textContent = "" + req.status + " " + req.statusText;
return;
}
doc = $.d.implementation.createHTMLDocument(null);
doc = d.implementation.createHTMLDocument(null);
doc.documentElement.innerHTML = req.responseText;
Threading.op($('body > form', doc).firstChild);
node = $.d.importNode(doc.getElementById(replyID));
node = d.importNode(doc.getElementById(replyID));
quotes = node.getElementsByClassName('quotelink');
for (_i = 0, _len = quotes.length; _i < _len; _i++) {
quote = quotes[_i];
@ -816,13 +817,13 @@
return;
}
a.textContent = a.textContent.replace('\u00d7 Loading...', '-');
doc = $.d.implementation.createHTMLDocument(null);
doc = d.implementation.createHTMLDocument(null);
doc.documentElement.innerHTML = req.responseText;
nodes = [];
_ref = $$('.reply', doc);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
reply = _ref[_i];
table = $.d.importNode(reply.parentNode.parentNode.parentNode);
table = d.importNode(reply.parentNode.parentNode.parentNode);
_ref2 = $$('.quotelink', table);
for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
quote = _ref2[_j];
@ -912,7 +913,7 @@
node = _ref[_i];
node.removeAttribute('accesskey');
}
return $.on($.d, 'keydown', Keybinds.keydown);
return $.on(d, 'keydown', Keybinds.keydown);
},
keydown: function(e) {
var key, o, range, selEnd, selStart, ta, thread, value, _ref, _ref2;
@ -1108,7 +1109,7 @@
td.className = 'reply';
td.removeAttribute('tabindex');
rect = td.getBoundingClientRect();
if (rect.bottom >= 0 && rect.top <= $.d.body.clientHeight) {
if (rect.bottom >= 0 && rect.top <= d.body.clientHeight) {
next = delta === +1 ? $.x('following::td[@class="reply"]', td) : $.x('preceding::td[@class="reply"]', td);
if (!next) {
td.className = 'replyhl';
@ -1120,7 +1121,7 @@
return;
}
rect = next.getBoundingClientRect();
if (rect.top < 0 || rect.bottom > $.d.body.clientHeight) {
if (rect.top < 0 || rect.bottom > d.body.clientHeight) {
next.scrollIntoView(delta === -1);
}
next.className = 'replyhl';
@ -1134,7 +1135,7 @@
for (_i = 0, _len = replies.length; _i < _len; _i++) {
reply = replies[_i];
rect = reply.getBoundingClientRect();
if (delta === +1 && rect.top >= 0 || delta === -1 && rect.bottom <= $.d.body.clientHeight) {
if (delta === +1 && rect.top >= 0 || delta === -1 && rect.bottom <= d.body.clientHeight) {
reply.className = 'replyhl';
reply.tabIndex = 0;
reply.focus();
@ -1161,7 +1162,7 @@
$.on(prev, 'click', this.prev);
$.on(next, 'click', this.next);
$.add(span, [prev, $.tn(' '), next]);
return $.add($.d.body, span);
return $.add(d.body, span);
},
prev: function() {
if (Main.REPLY) {
@ -1172,7 +1173,7 @@
},
next: function() {
if (Main.REPLY) {
return window.scrollTo(0, $.d.body.scrollHeight);
return window.scrollTo(0, d.body.scrollHeight);
} else {
return Nav.scroll(+1);
}
@ -1221,7 +1222,7 @@
if (!Main.REPLY) $('select', QR.el).value = 'new';
return $('textarea', QR.el).focus();
});
form = $.d.forms[0];
form = d.forms[0];
$.before(form, link);
}
if (/chrome/i.test(navigator.userAgent)) {
@ -1249,21 +1250,21 @@
return setTimeout(loadChecking, 500, this);
}
});
$.add($.d.head, iframe);
$.add(d.head, iframe);
}
script = $.el('script', {
textContent: 'Recaptcha.focus_response_field=function(){}'
});
$.add($.d.head, script);
$.add(d.head, script);
$.rm(script);
if (Conf['Persistent QR']) {
QR.dialog();
if (Conf['Auto Hide QR']) QR.hide();
}
$.on($.d, 'dragover', QR.dragOver);
$.on($.d, 'drop', QR.dropFile);
$.on($.d, 'dragstart', QR.drag);
return $.on($.d, 'dragend', QR.drag);
$.on(d, 'dragover', QR.dragOver);
$.on(d, 'drop', QR.dropFile);
$.on(d, 'dragstart', QR.drag);
return $.on(d, 'dragend', QR.drag);
},
node: function(post) {
return $.on($('.quotejs + .quotejs', post.el), 'click', QR.quote);
@ -1282,7 +1283,7 @@
QR.message.send({
req: 'abort'
});
$.d.activeElement.blur();
d.activeElement.blur();
$.removeClass(QR.el, 'dump');
_ref = QR.replies;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
@ -1298,7 +1299,7 @@
return QR.cleanError();
},
hide: function() {
$.d.activeElement.blur();
d.activeElement.blur();
$.addClass(QR.el, 'autohide');
return $.id('autohide').checked = true;
},
@ -1316,7 +1317,7 @@
if (node) $.replace(el.firstChild, node);
QR.open();
if (/captcha|verification/i.test(err)) $('[autocomplete]', QR.el).focus();
if ($.d.hidden || $.d.oHidden || $.d.mozHidden || $.d.webkitHidden) {
if (d.hidden || d.oHidden || d.mozHidden || d.webkitHidden) {
return alert(err);
}
},
@ -1400,8 +1401,8 @@
drag: function(e) {
var i;
i = e.type === 'dragstart' ? 'off' : 'on';
$[i]($.d, 'dragover', QR.dragOver);
return $[i]($.d, 'drop', QR.dropFile);
$[i](d, 'dragover', QR.dragOver);
return $[i](d, 'drop', QR.dropFile);
},
dragOver: function(e) {
e.preventDefault();
@ -1807,8 +1808,8 @@
QR.status();
QR.cooldown.init();
QR.captcha.init();
$.add($.d.body, QR.el);
e = $.d.createEvent('CustomEvent');
$.add(d.body, QR.el);
e = d.createEvent('CustomEvent');
e.initEvent('QRDialogCreation', true, false);
return QR.el.dispatchEvent(e);
},
@ -1865,7 +1866,7 @@
upfile: reply.file,
spoiler: reply.spoiler,
mode: 'regist',
pwd: (m = $.d.cookie.match(/4chan_pass=([^;]+)/)) ? decodeURIComponent(m[1]) : $('[name=pwd]').value,
pwd: (m = d.cookie.match(/4chan_pass=([^;]+)/)) ? decodeURIComponent(m[1]) : $('[name=pwd]').value,
recaptcha_challenge_field: challenge,
recaptcha_response_field: response + ' '
};
@ -2295,8 +2296,8 @@
return e.stopPropagation();
});
$.add(overlay, dialog);
$.add($.d.body, overlay);
$.d.body.style.setProperty('overflow', 'hidden', null);
$.add(d.body, overlay);
d.body.style.setProperty('overflow', 'hidden', null);
Options.backlink.call(back);
Options.time.call(time);
Options.fileInfo.call(fileInfoR);
@ -2305,7 +2306,7 @@
},
close: function() {
$.rm(this);
return $.d.body.style.removeProperty('overflow');
return d.body.style.removeProperty('overflow');
},
clearHidden: function() {
$["delete"]("hiddenReplies/" + Main.BOARD + "/");
@ -2501,7 +2502,7 @@
$.on(input, 'click', this.update);
}
}
$.add($.d.body, dialog);
$.add(d.body, dialog);
this.retryCoef = 10;
return this.lastModified = 0;
},
@ -2529,7 +2530,7 @@
return Updater.scrollBG = this.checked ? function() {
return true;
} : function() {
return !($.d.hidden || $.d.oHidden || $.d.mozHidden || $.d.webkitHidden);
return !(d.hidden || d.oHidden || d.mozHidden || d.webkitHidden);
};
},
update: function() {
@ -2543,7 +2544,7 @@
if (Conf['Unread Count']) {
Unread.title = Unread.title.match(/^.+-/)[0] + ' 404';
} else {
$.d.title = $.d.title.match(/^.+-/)[0] + ' 404';
d.title = d.title.match(/^.+-/)[0] + ' 404';
}
Unread.update(true);
QR.message.send({
@ -2568,7 +2569,7 @@
return;
}
Updater.lastModified = this.getResponseHeader('Last-Modified');
doc = $.d.implementation.createHTMLDocument(null);
doc = d.implementation.createHTMLDocument(null);
doc.documentElement.innerHTML = this.responseText;
id = $('input', Updater.br.previousElementSibling).name;
nodes = [];
@ -2579,7 +2580,7 @@
nodes.push(reply.parentNode.parentNode.parentNode);
}
newPosts = nodes.length;
scroll = Conf['Scrolling'] && Updater.scrollBG() && newPosts && Updater.br.previousElementSibling.getBoundingClientRect().bottom - $.d.body.clientHeight < 25;
scroll = Conf['Scrolling'] && Updater.scrollBG() && newPosts && Updater.br.previousElementSibling.getBoundingClientRect().bottom - d.body.clientHeight < 25;
if (Conf['Verbose']) {
Updater.count.textContent = "+" + newPosts;
Updater.count.className = newPosts ? 'new' : null;
@ -2626,7 +2627,7 @@
var favicon, html, input, inputs, _i, _len;
html = '<div class=move>Thread Watcher</div>';
this.dialog = UI.dialog('watcher', 'top: 50px; left: 0px;', html);
$.add($.d.body, this.dialog);
$.add(d.body, this.dialog);
inputs = $$('.op > input');
for (_i = 0, _len = inputs.length; _i < _len; _i++) {
input = inputs[_i];
@ -2753,7 +2754,7 @@
createSauceLink: function(link) {
var domain, el, href;
domain = link.match(/(\w+)\.\w+\//)[1];
href = link.replace(/(\$\d)/g, function(parameter) {
href = link.replace(/(\d)/g, function(parameter) {
switch (parameter) {
case '$1':
return "http://thumbs.4chan.org' + img.pathname.replace(/src(\\/\\d+).+$/, 'thumb$1s.jpg') + '";
@ -3028,7 +3029,7 @@
TitlePost = {
init: function() {
return $.d.title = GetTitle();
return d.title = GetTitle();
}
};
@ -3168,7 +3169,7 @@
inline.textContent = "" + req.status + " " + req.statusText;
return;
}
doc = $.d.implementation.createHTMLDocument(null);
doc = d.implementation.createHTMLDocument(null);
doc.documentElement.innerHTML = req.responseText;
node = id === threadID ? Threading.op($('body > form', doc).firstChild) : doc.getElementById(id);
newInline = QuoteInline.table(id, node.innerHTML);
@ -3220,7 +3221,7 @@
id: 'qp',
className: 'reply dialog'
});
$.add($.d.body, qp);
$.add(d.body, qp);
id = this.hash.slice(1);
if (el = $.id(id)) {
qp.innerHTML = el.innerHTML;
@ -3260,7 +3261,7 @@
qp.textContent = "" + req.status + " " + req.statusText;
return;
}
doc = $.d.implementation.createHTMLDocument(null);
doc = d.implementation.createHTMLDocument(null);
doc.documentElement.innerHTML = req.responseText;
node = id === threadID ? Threading.op($('body > form', doc).firstChild) : doc.getElementById(id);
qp.innerHTML = node.innerHTML;
@ -3318,7 +3319,7 @@
node: function(post) {
var a, board, data, i, id, index, m, node, nodes, quote, quotes, snapshot, text, _i, _len, _ref;
if (post["class"] === 'inline') return;
snapshot = $.d.evaluate('.//text()[not(parent::a)]', post.el.lastChild, null, 6, null);
snapshot = d.evaluate('.//text()[not(parent::a)]', post.el.lastChild, null, 6, null);
for (i = 0, _ref = snapshot.snapshotLength; 0 <= _ref ? i < _ref : i > _ref; 0 <= _ref ? i++ : i--) {
node = snapshot.snapshotItem(i);
data = node.data;
@ -3381,7 +3382,7 @@
var dialog;
dialog = UI.dialog('stats', 'bottom: 0; left: 0;', '<div class=move><span id=postcount>0</span> / <span id=imagecount>0</span></div>');
dialog.className = 'dialog';
$.add($.d.body, dialog);
$.add(d.body, dialog);
this.posts = this.images = 0;
this.imgLimit = (function() {
switch (Main.BOARD) {
@ -3412,7 +3413,7 @@
Unread = {
init: function() {
this.title = $.d.title;
this.title = d.title;
this.update();
$.on(window, 'scroll', Unread.scroll);
return Main.callbacks.push(this.node);
@ -3431,7 +3432,7 @@
},
scroll: function() {
var bottom, height, i, reply, _len, _ref;
height = $.d.body.clientHeight;
height = d.body.clientHeight;
_ref = Unread.replies;
for (i = 0, _len = _ref.length; i < _len; i++) {
reply = _ref[i];
@ -3450,7 +3451,7 @@
return;
}
return this.scheduled = setTimeout((function() {
return $.d.title = "(" + count + ") " + Unread.title;
return d.title = "(" + count + ") " + Unread.title;
}), 5);
},
update: function(forceUpdate) {
@ -3460,14 +3461,14 @@
if (Conf['Unread Count']) this.setTitle(count);
if (!(Conf['Unread Favicon'] && (count < 2 || forceUpdate))) return;
Favicon.el.href = Main.dead ? count ? Favicon.unreadDead : Favicon.dead : count ? Favicon.unread : Favicon["default"];
return $.add($.d.head, Favicon.el);
return $.add(d.head, Favicon.el);
}
};
Favicon = {
init: function() {
var href;
this.el = $('link[rel="shortcut icon"]', $.d.head);
this.el = $('link[rel="shortcut icon"]', d.head);
this.el.type = 'image/x-icon';
href = this.el.href;
this.SFW = /ws.ico$/.test(href);
@ -3588,7 +3589,7 @@
id: 'ihover',
src: this.parentNode.href
});
$.add($.d.body, UI.el);
$.add(d.body, UI.el);
$.on(UI.el, 'load', ImageHover.load);
$.on(this, 'mousemove', UI.hover);
return $.on(this, 'mouseout', ImageHover.mouseout);
@ -3703,8 +3704,8 @@
thumb = a.firstChild;
if (thumb.hidden) {
rect = a.getBoundingClientRect();
if (rect.top < 0) $.d.body.scrollTop += rect.top - 42;
if (rect.left < 0) $.d.body.scrollLeft += rect.left;
if (rect.top < 0) d.body.scrollTop += rect.top - 42;
if (rect.left < 0) d.body.scrollLeft += rect.left;
return ImageExpand.contract(thumb);
} else {
return ImageExpand.expand(thumb);
@ -3768,7 +3769,7 @@
return $.prepend(form, controls);
},
resize: function() {
return ImageExpand.style.textContent = ".fitheight img[md5] + img {max-height:" + $.d.body.clientHeight + "px;}";
return ImageExpand.style.textContent = ".fitheight img[md5] + img {max-height:" + d.body.clientHeight + "px;}";
}
};
@ -3831,7 +3832,7 @@
return;
case 'images.4chan.org':
$.ready(function() {
if ($.d.title === '4chan - 404') return Redirect.init();
if (d.title === '4chan - 404') return Redirect.init();
});
return;
}
@ -3843,7 +3844,7 @@
now = Date.now();
if (Conf['Check for Updates'] && $.get('lastUpdate', 0) < now - 6 * $.HOUR) {
$.ready(function() {
return $.add($.d.head, $.el('script', {
return $.add(d.head, $.el('script', {
src: 'https://raw.github.com/mayhemydg/4chan-x/master/latest.js'
}));
});
@ -3887,13 +3888,13 @@
},
ready: function() {
var MutationObserver, form, nav, node, nodes, observer, _i, _j, _len, _len2, _ref, _ref2;
if ($.d.title === '4chan - 404') {
if (d.title === '4chan - 404') {
Redirect.init();
return;
}
if (!$.id('navtopr')) return;
$.addClass($.d.body, "chanx_" + (Main.version.split('.')[1]));
$.addClass($.d.body, $.engine);
$.addClass(d.body, "chanx_" + (Main.version.split('.')[1]));
$.addClass(d.body, $.engine);
_ref = ['navtop', 'navbot'];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
nav = _ref[_i];
@ -3968,11 +3969,11 @@
}
},
addStyle: function() {
$.off($.d, 'DOMNodeInserted', Main.addStyle);
if ($.d.head) {
$.off(d, 'DOMNodeInserted', Main.addStyle);
if (d.head) {
return $.addStyle(Main.css);
} else {
return $.on($.d, 'DOMNodeInserted', Main.addStyle);
return $.on(d, 'DOMNodeInserted', Main.addStyle);
}
},
message: function(e) {

View File

@ -154,9 +154,11 @@ Config =
'Auto Update': [true, 'Automatically fetch new posts']
'Interval': 30
d = document
UI =
dialog: (id, position, html) ->
el = $.d.createElement 'div'
el = d.createElement 'div'
el.className = 'reply dialog'
el.innerHTML = html
el.id = id
@ -167,16 +169,16 @@ UI =
#prevent text selection
e.preventDefault()
UI.el = el = @parentNode
$.d.addEventListener 'mousemove', UI.drag, false
$.d.addEventListener 'mouseup', UI.dragend, false
d.addEventListener 'mousemove', UI.drag, false
d.addEventListener 'mouseup', UI.dragend, false
#distance from pointer to el edge is constant; calculate it here.
# XXX opera reports el.offsetLeft / el.offsetTop as 0
rect = el.getBoundingClientRect()
UI.dx = e.clientX - rect.left
UI.dy = e.clientY - rect.top
#factor out el from document dimensions
UI.width = $.d.body.clientWidth - el.offsetWidth
UI.height = $.d.body.clientHeight - el.offsetHeight
UI.width = d.body.clientWidth - el.offsetWidth
UI.height = d.body.clientHeight - el.offsetHeight
drag: (e) ->
left = e.clientX - UI.dx
top = e.clientY - UI.dy
@ -203,13 +205,13 @@ UI =
#a = (b = c.b, c).a;
{el} = UI
localStorage["#{Main.namespace}#{el.id}.position"] = el.style.cssText
$.d.removeEventListener 'mousemove', UI.drag, false
$.d.removeEventListener 'mouseup', UI.dragend, false
d.removeEventListener 'mousemove', UI.drag, false
d.removeEventListener 'mouseup', UI.dragend, false
hover: (e) ->
{clientX, clientY} = e
{el} = UI
{style} = el
{clientHeight, clientWidth} = $.d.body
{clientHeight, clientWidth} = d.body
height = el.offsetHeight
top = clientY - 120
@ -237,7 +239,7 @@ loosely follows the jquery api:
http://api.jquery.com/
not chainable
###
$ = (selector, root=$.d.body) ->
$ = (selector, root=d.body) ->
root.querySelector selector
$.extend = (object, properties) ->
@ -253,22 +255,21 @@ $.extend $,
log:
# XXX GreaseMonkey can't into console.log.bind
console.log.bind? console
d: document
engine: /WebKit|Presto|Gecko/.exec(navigator.userAgent)[0].toLowerCase()
ready: (fc) ->
if /interactive|complete/.test $.d.readyState
if /interactive|complete/.test d.readyState
# Execute the functions in parallel.
# If one fails, do not stop the others.
return setTimeout fc
cb = ->
$.off $.d, 'DOMContentLoaded', cb
$.off d, 'DOMContentLoaded', cb
fc()
$.on $.d, 'DOMContentLoaded', cb
$.on d, 'DOMContentLoaded', cb
sync: (key, cb) ->
$.on window, 'storage', (e) ->
cb JSON.parse e.newValue if e.key is "#{Main.namespace}#{key}"
id: (id) ->
$.d.getElementById id
d.getElementById id
ajax: (url, callbacks, opts={}) ->
{type, headers, upCallbacks, form} = opts
r = new XMLHttpRequest()
@ -301,11 +302,11 @@ $.extend $,
addStyle: (css) ->
style = $.el 'style',
textContent: css
$.add $.d.head, style
$.add d.head, style
style
x: (path, root=$.d.body) ->
x: (path, root=d.body) ->
# XPathResult.ANY_UNORDERED_NODE_TYPE is 8
$.d.evaluate(path, root, null, 8, null).
d.evaluate(path, root, null, 8, null).
singleNodeValue
addClass: (el, className) ->
el.classList.add className
@ -314,11 +315,11 @@ $.extend $,
rm: (el) ->
el.parentNode.removeChild el
tn: (s) ->
$.d.createTextNode s
d.createTextNode s
nodes: (nodes) ->
if nodes instanceof Node
return nodes
frag = $.d.createDocumentFragment()
frag = d.createDocumentFragment()
for node in nodes
frag.appendChild node
frag
@ -333,7 +334,7 @@ $.extend $,
replace: (root, el) ->
root.parentNode.replaceChild $.nodes(el), root
el: (tag, properties) ->
el = $.d.createElement tag
el = d.createElement tag
$.extend el, properties if properties
el
on: (el, eventType, handler) ->
@ -432,7 +433,7 @@ $.extend $,
name = Main.namespace + name
localStorage[name] = JSON.stringify value
$$ = (selector, root=$.d.body) ->
$$ = (selector, root=d.body) ->
Array::slice.call root.querySelectorAll selector
Filter =
@ -567,7 +568,7 @@ Filter =
comment: (post) ->
text = []
# XPathResult.ORDERED_NODE_SNAPSHOT_TYPE is 7
nodes = $.d.evaluate './/br|.//text()', post.el.lastChild, null, 7, null
nodes = d.evaluate './/br|.//text()', post.el.lastChild, null, 7, null
for i in [0...nodes.snapshotLength]
text.push if data = nodes.snapshotItem(i).data then data else '\n'
text.join ''
@ -620,13 +621,13 @@ ExpandComment =
a.textContent = "#{req.status} #{req.statusText}"
return
doc = $.d.implementation.createHTMLDocument null
doc = d.implementation.createHTMLDocument null
doc.documentElement.innerHTML = req.responseText
Threading.op $('body > form', doc).firstChild
# Import the node to fix quote.hashes
# as they're empty when in a different document.
node = $.d.importNode doc.getElementById replyID
node = d.importNode doc.getElementById replyID
quotes = node.getElementsByClassName 'quotelink'
for quote in quotes
@ -703,12 +704,12 @@ ExpandThread =
a.textContent = a.textContent.replace '\u00d7 Loading...', '-'
doc = $.d.implementation.createHTMLDocument null
doc = d.implementation.createHTMLDocument null
doc.documentElement.innerHTML = req.responseText
nodes = []
for reply in $$ '.reply', doc
table = $.d.importNode reply.parentNode.parentNode.parentNode
table = d.importNode reply.parentNode.parentNode.parentNode
for quote in $$ '.quotelink', table
if (href = quote.getAttribute 'href') is quote.hash #add pathname to normal quotes
quote.pathname = pathname
@ -779,7 +780,7 @@ Keybinds =
init: ->
for node in $$ '[accesskey]'
node.removeAttribute 'accesskey'
$.on $.d, 'keydown', Keybinds.keydown
$.on d, 'keydown', Keybinds.keydown
keydown: (e) ->
if not (key = Keybinds.keyCode(e)) or /TEXTAREA|INPUT/.test(e.target.nodeName) and not (e.altKey or e.ctrlKey or e.keyCode is 27)
@ -912,7 +913,7 @@ Keybinds =
td.className = 'reply'
td.removeAttribute 'tabindex'
rect = td.getBoundingClientRect()
if rect.bottom >= 0 and rect.top <= $.d.body.clientHeight # We're at least partially visible
if rect.bottom >= 0 and rect.top <= d.body.clientHeight # We're at least partially visible
next =
if delta is +1
$.x 'following::td[@class="reply"]', td
@ -925,7 +926,7 @@ Keybinds =
return
return unless Main.REPLY or $.x('ancestor::div[@class="thread"]', next) is thread
rect = next.getBoundingClientRect()
if rect.top < 0 or rect.bottom > $.d.body.clientHeight
if rect.top < 0 or rect.bottom > d.body.clientHeight
next.scrollIntoView delta is -1
next.className = 'replyhl'
next.tabIndex = 0
@ -936,7 +937,7 @@ Keybinds =
replies.reverse() if delta is -1
for reply in replies
rect = reply.getBoundingClientRect()
if delta is +1 and rect.top >= 0 or delta is -1 and rect.bottom <= $.d.body.clientHeight
if delta is +1 and rect.top >= 0 or delta is -1 and rect.bottom <= d.body.clientHeight
reply.className = 'replyhl'
reply.tabIndex = 0
reply.focus()
@ -958,7 +959,7 @@ Nav =
$.on next, 'click', @next
$.add span, [prev, $.tn(' '), next]
$.add $.d.body, span
$.add d.body, span
prev: ->
if Main.REPLY
@ -968,7 +969,7 @@ Nav =
next: ->
if Main.REPLY
window.scrollTo 0, $.d.body.scrollHeight
window.scrollTo 0, d.body.scrollHeight
else
Nav.scroll +1
@ -1009,7 +1010,7 @@ QR =
QR.open()
$('select', QR.el).value = 'new' unless Main.REPLY
$('textarea', QR.el).focus()
form = $.d.forms[0]
form = d.forms[0]
$.before form, link
# CORS is ignored for content script on Chrome, but not Safari/Oprah/Firefox.
@ -1026,20 +1027,20 @@ QR =
iframe.src = 'about:blank'
setTimeout (-> iframe.src = 'https://sys.4chan.org/robots.txt'), 100
$.on iframe, 'load', -> if @src isnt 'about:blank' then setTimeout loadChecking, 500, @
$.add $.d.head, iframe
$.add d.head, iframe
# Prevent original captcha input from being focused on reload.
script = $.el 'script', textContent: 'Recaptcha.focus_response_field=function(){}'
$.add $.d.head, script
$.add d.head, script
$.rm script
if Conf['Persistent QR']
QR.dialog()
QR.hide() if Conf['Auto Hide QR']
$.on $.d, 'dragover', QR.dragOver
$.on $.d, 'drop', QR.dropFile
$.on $.d, 'dragstart', QR.drag
$.on $.d, 'dragend', QR.drag
$.on d, 'dragover', QR.dragOver
$.on d, 'drop', QR.dropFile
$.on d, 'dragstart', QR.drag
$.on d, 'dragend', QR.drag
node: (post) ->
$.on $('.quotejs + .quotejs', post.el), 'click', QR.quote
@ -1053,7 +1054,7 @@ QR =
close: ->
QR.el.hidden = true
QR.message.send req: 'abort'
$.d.activeElement.blur()
d.activeElement.blur()
$.removeClass QR.el, 'dump'
for i in QR.replies
QR.replies[0].rm()
@ -1064,7 +1065,7 @@ QR =
spoiler.click()
QR.cleanError()
hide: ->
$.d.activeElement.blur()
d.activeElement.blur()
$.addClass QR.el, 'autohide'
$.id('autohide').checked = true
unhide: ->
@ -1081,7 +1082,7 @@ QR =
if /captcha|verification/i.test err
# Focus the captcha input on captcha error.
$('[autocomplete]', QR.el).focus()
alert err if $.d.hidden or $.d.oHidden or $.d.mozHidden or $.d.webkitHidden
alert err if d.hidden or d.oHidden or d.mozHidden or d.webkitHidden
cleanError: ->
$('.warning', QR.el).textContent = null
@ -1164,8 +1165,8 @@ QR =
drag: (e) ->
# Let it drag anything from the page.
i = if e.type is 'dragstart' then 'off' else 'on'
$[i] $.d, 'dragover', QR.dragOver
$[i] $.d, 'drop', QR.dropFile
$[i] d, 'dragover', QR.dragOver
$[i] d, 'drop', QR.dropFile
dragOver: (e) ->
e.preventDefault()
e.dataTransfer.dropEffect = 'copy' # cursor feedback
@ -1490,11 +1491,11 @@ QR =
QR.status()
QR.cooldown.init()
QR.captcha.init()
$.add $.d.body, QR.el
$.add d.body, QR.el
# Create a custom event when the QR dialog is first initialized.
# Use it to extend the QR's functionalities, or for XTRM RICE.
e = $.d.createEvent 'CustomEvent'
e = d.createEvent 'CustomEvent'
e.initEvent 'QRDialogCreation', true, false
QR.el.dispatchEvent e
@ -1554,7 +1555,7 @@ QR =
upfile: reply.file
spoiler: reply.spoiler
mode: 'regist'
pwd: if m = $.d.cookie.match(/4chan_pass=([^;]+)/) then decodeURIComponent m[1] else $('[name=pwd]').value
pwd: if m = d.cookie.match(/4chan_pass=([^;]+)/) then decodeURIComponent m[1] else $('[name=pwd]').value
recaptcha_challenge_field: challenge
recaptcha_response_field: response + ' '
@ -1938,8 +1939,8 @@ Options =
$.on overlay, 'click', Options.close
$.on dialog, 'click', (e) -> e.stopPropagation()
$.add overlay, dialog
$.add $.d.body, overlay
$.d.body.style.setProperty 'overflow', 'hidden', null
$.add d.body, overlay
d.body.style.setProperty 'overflow', 'hidden', null
Options.backlink.call back
Options.time.call time
@ -1949,7 +1950,7 @@ Options =
close: ->
$.rm this
$.d.body.style.removeProperty 'overflow'
d.body.style.removeProperty 'overflow'
clearHidden: ->
#'hidden' might be misleading; it's the number of IDs we're *looking* for,
@ -2125,7 +2126,7 @@ Updater =
else if input.type is 'button'
$.on input, 'click', @update
$.add $.d.body, dialog
$.add d.body, dialog
@retryCoef = 10
@lastModified = 0
@ -2150,7 +2151,7 @@ Updater =
if @checked
-> true
else
-> !($.d.hidden or $.d.oHidden or $.d.mozHidden or $.d.webkitHidden)
-> !(d.hidden or d.oHidden or d.mozHidden or d.webkitHidden)
update: ->
if @status is 404
Updater.timer.textContent = ''
@ -2161,7 +2162,7 @@ Updater =
if Conf['Unread Count']
Unread.title = Unread.title.match(/^.+-/)[0] + ' 404'
else
$.d.title = $.d.title.match(/^.+-/)[0] + ' 404'
d.title = d.title.match(/^.+-/)[0] + ' 404'
Unread.update true
QR.message.send req: 'abort'
QR.status()
@ -2183,7 +2184,7 @@ Updater =
return
Updater.lastModified = @getResponseHeader 'Last-Modified'
doc = $.d.implementation.createHTMLDocument null
doc = d.implementation.createHTMLDocument null
doc.documentElement.innerHTML = @responseText
id = $('input', Updater.br.previousElementSibling).name
@ -2194,7 +2195,7 @@ Updater =
newPosts = nodes.length
scroll = Conf['Scrolling'] && Updater.scrollBG() && newPosts &&
Updater.br.previousElementSibling.getBoundingClientRect().bottom - $.d.body.clientHeight < 25
Updater.br.previousElementSibling.getBoundingClientRect().bottom - d.body.clientHeight < 25
if Conf['Verbose']
Updater.count.textContent = "+#{newPosts}"
Updater.count.className = if newPosts then 'new' else null
@ -2232,7 +2233,7 @@ Watcher =
init: ->
html = '<div class=move>Thread Watcher</div>'
@dialog = UI.dialog 'watcher', 'top: 50px; left: 0px;', html
$.add $.d.body, @dialog
$.add d.body, @dialog
#add watch buttons
inputs = $$ '.op > input'
@ -2334,7 +2335,7 @@ Sauce =
createSauceLink: (link) ->
domain = link.match(/(\w+)\.\w+\//)[1]
href = link.replace /(\$\d)/g, (parameter) ->
href = link.replace /(\d)/g, (parameter) ->
switch parameter
when '$1'
"http://thumbs.4chan.org' + img.pathname.replace(/src(\\/\\d+).+$/, 'thumb$1s.jpg') + '"
@ -2531,7 +2532,7 @@ GetTitle = (thread) ->
TitlePost =
init: ->
$.d.title = GetTitle()
d.title = GetTitle()
QuoteBacklink =
init: ->
@ -2636,7 +2637,7 @@ QuoteInline =
inline.textContent = "#{req.status} #{req.statusText}"
return
doc = $.d.implementation.createHTMLDocument null
doc = d.implementation.createHTMLDocument null
doc.documentElement.innerHTML = req.responseText
node =
@ -2675,7 +2676,7 @@ QuotePreview =
qp = UI.el = $.el 'div',
id: 'qp'
className: 'reply dialog'
$.add $.d.body, qp
$.add d.body, qp
id = @hash[1..]
if el = $.id id
@ -2708,7 +2709,7 @@ QuotePreview =
qp.textContent = "#{req.status} #{req.statusText}"
return
doc = $.d.implementation.createHTMLDocument null
doc = d.implementation.createHTMLDocument null
doc.documentElement.innerHTML = req.responseText
node =
@ -2763,7 +2764,7 @@ Quotify =
# XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE is 6
# Get all the text nodes that are not inside an anchor.
snapshot = $.d.evaluate './/text()[not(parent::a)]', post.el.lastChild, null, 6, null
snapshot = d.evaluate './/text()[not(parent::a)]', post.el.lastChild, null, 6, null
for i in [0...snapshot.snapshotLength]
node = snapshot.snapshotItem i
@ -2833,7 +2834,7 @@ ThreadStats =
init: ->
dialog = UI.dialog 'stats', 'bottom: 0; left: 0;', '<div class=move><span id=postcount>0</span> / <span id=imagecount>0</span></div>'
dialog.className = 'dialog'
$.add $.d.body, dialog
$.add d.body, dialog
@posts = @images = 0
@imgLimit =
switch Main.BOARD
@ -2855,7 +2856,7 @@ ThreadStats =
Unread =
init: ->
@title = $.d.title
@title = d.title
@update()
$.on window, 'scroll', Unread.scroll
Main.callbacks.push @node
@ -2872,7 +2873,7 @@ Unread =
Unread.update()
scroll: ->
height = $.d.body.clientHeight
height = d.body.clientHeight
for reply, i in Unread.replies
{bottom} = reply.getBoundingClientRect()
if bottom > height #post is not completely read
@ -2889,7 +2890,7 @@ Unread =
@setTitle count
return
@scheduled = setTimeout (->
$.d.title = "(#{count}) #{Unread.title}"
d.title = "(#{count}) #{Unread.title}"
), 5
update: (forceUpdate) ->
@ -2918,11 +2919,11 @@ Unread =
#`favicon.href = href` doesn't work on Firefox
#`favicon.href = href` isn't enough on Opera
#Opera won't always update the favicon if the href didn't not change
$.add $.d.head, Favicon.el
$.add d.head, Favicon.el
Favicon =
init: ->
@el = $ 'link[rel="shortcut icon"]', $.d.head
@el = $ 'link[rel="shortcut icon"]', d.head
@el.type = 'image/x-icon'
{href} = @el
@SFW = /ws.ico$/.test href
@ -2994,7 +2995,7 @@ ImageHover =
UI.el = $.el 'img'
id: 'ihover'
src: @parentNode.href
$.add $.d.body, UI.el
$.add d.body, UI.el
$.on UI.el, 'load', ImageHover.load
$.on @, 'mousemove', UI.hover
$.on @, 'mouseout', ImageHover.mouseout
@ -3077,8 +3078,8 @@ ImageExpand =
thumb = a.firstChild
if thumb.hidden
rect = a.getBoundingClientRect()
$.d.body.scrollTop += rect.top - 42 if rect.top < 0
$.d.body.scrollLeft += rect.left if rect.left < 0
d.body.scrollTop += rect.top - 42 if rect.top < 0
d.body.scrollLeft += rect.left if rect.left < 0
ImageExpand.contract thumb
else
ImageExpand.expand thumb
@ -3136,7 +3137,7 @@ ImageExpand =
$.prepend form, controls
resize: ->
ImageExpand.style.textContent = ".fitheight img[md5] + img {max-height:#{$.d.body.clientHeight}px;}"
ImageExpand.style.textContent = ".fitheight img[md5] + img {max-height:#{d.body.clientHeight}px;}"
Main =
init: ->
@ -3182,7 +3183,7 @@ Main =
QR.message.send req: 'status', ready: true, banned: true
return
when 'images.4chan.org'
$.ready -> Redirect.init() if $.d.title is '4chan - 404'
$.ready -> Redirect.init() if d.title is '4chan - 404'
return
$.ready Options.init
@ -3194,7 +3195,7 @@ Main =
now = Date.now()
if Conf['Check for Updates'] and $.get('lastUpdate', 0) < now - 6*$.HOUR
$.ready -> $.add $.d.head, $.el 'script', src: 'https://raw.github.com/mayhemydg/4chan-x/master/latest.js'
$.ready -> $.add d.head, $.el 'script', src: 'https://raw.github.com/mayhemydg/4chan-x/master/latest.js'
$.set 'lastUpdate', now
Main.hiddenReplies = $.get "hiddenReplies/#{Main.BOARD}/", {}
@ -3271,13 +3272,13 @@ Main =
$.ready Main.ready
ready: ->
if $.d.title is '4chan - 404'
if d.title is '4chan - 404'
Redirect.init()
return
unless $.id 'navtopr'
return
$.addClass $.d.body, "chanx_#{Main.version.split('.')[1]}"
$.addClass $.d.body, $.engine
$.addClass d.body, "chanx_#{Main.version.split('.')[1]}"
$.addClass d.body, $.engine
for nav in ['navtop', 'navbot']
$.addClass $("a[href$='/#{Main.BOARD}/']", $.id nav), 'current'
form = $ 'form[name=delform]'
@ -3340,11 +3341,11 @@ Main =
$.on form, 'DOMNodeInserted', Main.listener
addStyle: ->
$.off $.d, 'DOMNodeInserted', Main.addStyle
if $.d.head
$.off d, 'DOMNodeInserted', Main.addStyle
if d.head
$.addStyle Main.css
else # XXX fox
$.on $.d, 'DOMNodeInserted', Main.addStyle
$.on d, 'DOMNodeInserted', Main.addStyle
message: (e) ->
{data} = e