Fix classes
This commit is contained in:
parent
02fd87266e
commit
ba66d077cd
@ -3141,26 +3141,24 @@
|
||||
};
|
||||
|
||||
Callbacks.prototype.execute = function(nodes) {
|
||||
var cb, err, errors, i, j, name, node;
|
||||
i = 0;
|
||||
while (name = this.keys[i++]) {
|
||||
j = 0;
|
||||
cb = this[name];
|
||||
while (node = nodes[j++]) {
|
||||
try {
|
||||
if (!cb.disconnected) {
|
||||
cb.call(node);
|
||||
}
|
||||
} catch (_error) {
|
||||
err = _error;
|
||||
if (!errors) {
|
||||
errors = [];
|
||||
}
|
||||
errors.push({
|
||||
message: ['"', name, '" crashed on node ', this.type, ' No.', node.ID, ' (', node.board, ').'].join(''),
|
||||
error: err
|
||||
});
|
||||
var err, errors, name, node, _i, _j, _len, _len1, _ref;
|
||||
_ref = this.keys;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
name = _ref[_i];
|
||||
try {
|
||||
for (_j = 0, _len1 = nodes.length; _j < _len1; _j++) {
|
||||
node = nodes[_j];
|
||||
this[name].call(node);
|
||||
}
|
||||
} catch (_error) {
|
||||
err = _error;
|
||||
if (!errors) {
|
||||
errors = [];
|
||||
}
|
||||
errors.push({
|
||||
message: ['"', name, '" crashed on node ', this.type, ' No.', node.ID, ' (', node.board, ').'].join(''),
|
||||
error: err
|
||||
});
|
||||
}
|
||||
}
|
||||
if (errors) {
|
||||
@ -3216,13 +3214,16 @@
|
||||
}
|
||||
|
||||
Thread.prototype.setPage = function(pageNum) {
|
||||
var icon, key, _i, _len, _ref;
|
||||
icon = $('.page-num', this.OP.nodes.info);
|
||||
_ref = ['title', 'textContent'];
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
key = _ref[_i];
|
||||
icon[key] = icon[key].replace(/\d+/, pageNum);
|
||||
var icon, info, quote, _ref;
|
||||
_ref = this.OP.nodes, info = _ref.info, quote = _ref.quote;
|
||||
if (!(icon = $('.page-num', info))) {
|
||||
icon = $.el('span', {
|
||||
className: 'page-num'
|
||||
});
|
||||
$.after(quote, [$.tn(' '), icon]);
|
||||
}
|
||||
icon.title = "This thread is on page " + pageNum + " in the original index.";
|
||||
icon.textContent = "[" + pageNum + "]";
|
||||
if (this.catalogView) {
|
||||
return this.catalogView.nodes.pageCount.textContent = pageNum;
|
||||
}
|
||||
@ -3239,7 +3240,7 @@
|
||||
};
|
||||
|
||||
Thread.prototype.setStatus = function(type, status) {
|
||||
var name, typeLC;
|
||||
var name;
|
||||
name = "is" + type;
|
||||
if (this[name] === status) {
|
||||
return;
|
||||
@ -3248,7 +3249,6 @@
|
||||
if (!this.OP) {
|
||||
return;
|
||||
}
|
||||
typeLC = type.toLowerCase();
|
||||
this.setIcon('Sticky', this.isSticky);
|
||||
this.setIcon('Closed', this.isClosed && !this.isArchived);
|
||||
return this.setIcon('Archived', this.isArchived);
|
||||
@ -3275,7 +3275,7 @@
|
||||
title: type,
|
||||
className: "" + typeLC + "Icon retina"
|
||||
});
|
||||
root = type !== 'Sticky' && this.isSticky ? $('.stickyIcon', this.OP.nodes.info) : $('.page-num', this.OP.nodes.info) || $('[title="Reply to this post"]', this.OP.nodes.info);
|
||||
root = type !== 'Sticky' && this.isSticky ? $('.stickyIcon', this.OP.nodes.info) : $('.page-num', this.OP.nodes.info) || this.OP.nodes.quote;
|
||||
$.after(root, [$.tn(' '), icon]);
|
||||
if (!this.catalogView) {
|
||||
return;
|
||||
@ -3349,11 +3349,12 @@
|
||||
this.board = this.thread.board;
|
||||
this.nodes = {
|
||||
root: root,
|
||||
thumb: $('.thumb', root),
|
||||
icons: $('.thread-icons', root),
|
||||
thumb: $('.catalog-thumb', root),
|
||||
icons: $('.catalog-icons', root),
|
||||
postCount: $('.post-count', root),
|
||||
fileCount: $('.file-count', root),
|
||||
pageCount: $('.page-count', root)
|
||||
pageCount: $('.page-count', root),
|
||||
comment: $('.comment', root)
|
||||
};
|
||||
this.thread.catalogView = this;
|
||||
}
|
||||
@ -3378,17 +3379,18 @@
|
||||
}
|
||||
this.ID = +root.id.slice(2);
|
||||
this.fullID = "" + this.board + "." + this.ID;
|
||||
post = $('.post', root);
|
||||
info = $('.postInfo', post);
|
||||
if (that.isOriginalMarkup) {
|
||||
this.cleanup(root, post);
|
||||
}
|
||||
post = $('.post', root);
|
||||
info = $('.postInfo', post);
|
||||
root.dataset.fullID = this.fullID;
|
||||
this.nodes = {
|
||||
root: root,
|
||||
post: post,
|
||||
info: info,
|
||||
nameBlock: $('.nameBlock', info),
|
||||
quote: $('.postNum > a:nth-of-type(2)', info),
|
||||
comment: $('.postMessage', post),
|
||||
links: [],
|
||||
quotelinks: [],
|
||||
@ -3396,8 +3398,12 @@
|
||||
};
|
||||
if (!(this.isReply = $.hasClass(post, 'reply'))) {
|
||||
this.thread.OP = this;
|
||||
this.thread.isArchived = !!$('.archivedIcon', info);
|
||||
this.thread.isSticky = !!$('.stickyIcon', info);
|
||||
this.thread.isClosed = !!$('.closedIcon', info);
|
||||
this.thread.isClosed = this.thread.isArchived || !!$('.closedIcon', info);
|
||||
if (this.thread.isArchived) {
|
||||
this.thread.kill();
|
||||
}
|
||||
}
|
||||
this.info = {};
|
||||
this.info.nameBlock = Conf['Anonymize'] ? 'Anonymous' : this.nodes.nameBlock.textContent.trim();
|
||||
@ -3448,27 +3454,45 @@
|
||||
}
|
||||
|
||||
Post.prototype.parseComment = function() {
|
||||
var bq, i, node, nodes, text;
|
||||
var bq, i, node, nodes, spoilers;
|
||||
this.nodes.comment.normalize();
|
||||
bq = this.nodes.comment.cloneNode(true);
|
||||
nodes = $$('.abbr, .exif, b', bq);
|
||||
nodes = $$('.abbr, .exif, b, marquee', bq);
|
||||
i = 0;
|
||||
while (node = nodes[i++]) {
|
||||
$.rm(node);
|
||||
}
|
||||
this.info.comment = this.nodesToText(bq);
|
||||
spoilers = $$('s', bq);
|
||||
return this.info.commentSpoilered = (function() {
|
||||
var _i, _len;
|
||||
if (spoilers.length) {
|
||||
for (_i = 0, _len = spoilers.length; _i < _len; _i++) {
|
||||
node = spoilers[_i];
|
||||
$.replace(node, $.tn('[spoiler]'));
|
||||
}
|
||||
return this.nodesToText(bq);
|
||||
} else {
|
||||
return this.info.comment;
|
||||
}
|
||||
}).call(this);
|
||||
};
|
||||
|
||||
Post.prototype.nodesToText = function(bq) {
|
||||
var i, node, nodes, text;
|
||||
text = "";
|
||||
nodes = $.X('.//br|.//text()', bq);
|
||||
i = 0;
|
||||
while (node = nodes.snapshotItem(i++)) {
|
||||
text += node.data || '\n';
|
||||
}
|
||||
return this.info.comment = text.trim().replace(/\s+$/gm, '');
|
||||
return text.trim().replace(/\s+$/gm, '');
|
||||
};
|
||||
|
||||
Post.prototype.parseQuotes = function() {
|
||||
var quotelink, _i, _len, _ref;
|
||||
this.quotes = [];
|
||||
_ref = $$('.quotelink', this.nodes.comment);
|
||||
_ref = $$(':not(pre) > .quotelink', this.nodes.comment);
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
quotelink = _ref[_i];
|
||||
this.parseQuote(quotelink);
|
||||
@ -3477,7 +3501,7 @@
|
||||
|
||||
Post.prototype.parseQuote = function(quotelink) {
|
||||
var fullID, match;
|
||||
if (!(match = quotelink.href.match(/boards\.4chan\.org\/([^\/]+)\/thread\/\d+.*\#p(\d+)$/))) {
|
||||
if (!(match = quotelink.href.match(/boards\.4chan\.org\/([^\/]+)\/(?:res|thread)\/\d+(?:\/[^#]*)?#p(\d+)$/))) {
|
||||
return;
|
||||
}
|
||||
this.nodes.quotelinks.push(quotelink);
|
||||
@ -3511,30 +3535,26 @@
|
||||
size *= 1024;
|
||||
}
|
||||
this.file.sizeInBytes = size;
|
||||
this.file.thumbURL = that.isArchived ? thumb.src : "" + location.protocol + "//t.4cdn.org/" + this.board + "/" + (this.file.URL.match(/(\d+)\./)[1]) + "s.jpg";
|
||||
this.file.thumbURL = "" + location.protocol + "//t.4cdn.org/" + this.board + "/" + (this.file.URL.match(/(\d+)\./)[1]) + "s.jpg";
|
||||
this.file.isImage = /(jpg|png|gif)$/i.test(this.file.URL);
|
||||
this.file.isVideo = /webm$/i.test(this.file.URL);
|
||||
nameNode = $('a', fileText);
|
||||
if (this.file.isImage || this.file.isVideo) {
|
||||
this.file.dimensions = fileText.childNodes[2].data.match(/\d+x\d+/)[0];
|
||||
this.file.dimensions = nameNode.nextSibling.textContent.match(/\d+x\d+/)[0];
|
||||
}
|
||||
return this.file.name = !this.file.isSpoiler && (nameNode = $('a', fileText)) ? nameNode.title || nameNode.textContent : fileText.title;
|
||||
return this.file.name = fileText.title || nameNode.title || nameNode.textContent;
|
||||
};
|
||||
|
||||
Post.prototype.cleanup = function(root, post) {
|
||||
var node, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2;
|
||||
Post.prototype.cleanup = function(root) {
|
||||
var node, _i, _j, _len, _len1, _ref, _ref1;
|
||||
_ref = $$('.mobile', root);
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
node = _ref[_i];
|
||||
$.rm(node);
|
||||
}
|
||||
_ref1 = $$('[id]:not(.exif)', post);
|
||||
_ref1 = $$('.desktop', root);
|
||||
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
|
||||
node = _ref1[_j];
|
||||
node.removeAttribute('id');
|
||||
}
|
||||
_ref2 = $$('.desktop', root);
|
||||
for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
|
||||
node = _ref2[_k];
|
||||
$.rmClass(node, 'desktop');
|
||||
}
|
||||
};
|
||||
@ -3606,9 +3626,6 @@
|
||||
return;
|
||||
}
|
||||
this.isHidden = false;
|
||||
this.labels = this.labels.filter(function(label) {
|
||||
return !/^(Manually hidden|Recursively hidden|Hidden by)/.test(label);
|
||||
});
|
||||
_ref = Get.allQuotelinksLinkingTo(this);
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
quotelink = _ref[_i];
|
||||
@ -3637,8 +3654,7 @@
|
||||
return delete this.nodes.stub;
|
||||
};
|
||||
|
||||
Post.prototype.highlight = function(label, highlight, top) {
|
||||
this.labels.push(label);
|
||||
Post.prototype.highlight = function(highlight, top) {
|
||||
if (__indexOf.call(this.highlights, highlight) < 0) {
|
||||
this.highlights.push(highlight);
|
||||
$.addClass(this.nodes.root, highlight);
|
||||
@ -3751,7 +3767,7 @@
|
||||
__extends(Clone, _super);
|
||||
|
||||
function Clone(origin, context, contractThumb) {
|
||||
var file, info, inline, inlined, key, nodes, post, root, val, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3, _ref4, _ref5;
|
||||
var file, info, inline, inlined, key, nodes, post, root, val, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3;
|
||||
this.origin = origin;
|
||||
this.context = context;
|
||||
_ref = ['ID', 'fullID', 'board', 'thread', 'info', 'quotes', 'isReply'];
|
||||
@ -3760,13 +3776,15 @@
|
||||
this[key] = origin[key];
|
||||
}
|
||||
nodes = origin.nodes;
|
||||
root = nodes.root.cloneNode(true);
|
||||
root = contractThumb ? this.cloneWithoutVideo(nodes.root) : nodes.root.cloneNode(true);
|
||||
post = $('.post', root);
|
||||
info = $('.postInfo', post);
|
||||
this.nodes = {
|
||||
root: root,
|
||||
post: post,
|
||||
info: info,
|
||||
nameBlock: $('.nameBlock', info),
|
||||
quote: $('.postNum > a:nth-of-type(2)', info),
|
||||
comment: $('.postMessage', post),
|
||||
quotelinks: [],
|
||||
backlinks: info.getElementsByClassName('backlink')
|
||||
@ -3800,10 +3818,10 @@
|
||||
this.nodes.uniqueID = $('.posteruid', info);
|
||||
}
|
||||
if (nodes.capcode) {
|
||||
this.nodes.capcode = $('.capcode', info);
|
||||
this.nodes.capcode = $('.capcode.hand', info);
|
||||
}
|
||||
if (nodes.flag) {
|
||||
this.nodes.flag = $('.countryFlag', info);
|
||||
this.nodes.flag = $('.flag, .countryFlag', info);
|
||||
}
|
||||
if (nodes.date) {
|
||||
this.nodes.date = $('.dateTime', info);
|
||||
@ -3818,18 +3836,11 @@
|
||||
}
|
||||
file = $('.file', post);
|
||||
this.file.text = file.firstElementChild;
|
||||
this.file.thumb = $('img[data-md5], video[data-md5]', file);
|
||||
this.file.thumb = $('.fileThumb > [data-md5]', file);
|
||||
this.file.fullImage = $('.full-image', file);
|
||||
this.file.videoControls = $('.video-controls', this.file.text);
|
||||
if (contractThumb) {
|
||||
$.rmClass(root, 'expanded-image');
|
||||
$.rmClass(this.file.thumb, 'expanding');
|
||||
}
|
||||
this.file.isExpanded = $.hasClass(root, 'expanded-image');
|
||||
if ((_ref4 = this.file.fullImage) != null) {
|
||||
_ref4.removeAttribute('id');
|
||||
}
|
||||
if ((_ref5 = $('.video-controls', this.file.text)) != null) {
|
||||
_ref5.remove();
|
||||
ImageExpand.contract(this);
|
||||
}
|
||||
}
|
||||
if (origin.isDead) {
|
||||
@ -3839,6 +3850,23 @@
|
||||
root.dataset.clone = origin.clones.push(this) - 1;
|
||||
}
|
||||
|
||||
Clone.prototype.cloneWithoutVideo = function(node) {
|
||||
var child, clone, _i, _len, _ref;
|
||||
if (node.tagName === 'VIDEO' && !node.dataset.md5) {
|
||||
return [];
|
||||
} else if (node.nodeType === Node.ELEMENT_NODE && $('video', node)) {
|
||||
clone = node.cloneNode(false);
|
||||
_ref = node.childNodes;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
child = _ref[_i];
|
||||
$.add(clone, this.cloneWithoutVideo(child));
|
||||
}
|
||||
return clone;
|
||||
} else {
|
||||
return node.cloneNode(true);
|
||||
}
|
||||
};
|
||||
|
||||
return Clone;
|
||||
|
||||
})(Post);
|
||||
@ -4012,12 +4040,13 @@
|
||||
})();
|
||||
|
||||
Notice = (function() {
|
||||
function Notice(type, content, timeout) {
|
||||
function Notice(type, content, timeout, onclose) {
|
||||
this.timeout = timeout;
|
||||
this.onclose = onclose;
|
||||
this.close = __bind(this.close, this);
|
||||
this.add = __bind(this.add, this);
|
||||
this.el = $.el('div', {
|
||||
innerHTML: '<a href=javascript:; class="close fa" title=Close>\uf00d</a><div class=message></div>'
|
||||
innerHTML: "<a href=\"javascript:;\" class=\"close fa fa-times\" title=\"Close\"></a><div class=\"message\"></div>"
|
||||
});
|
||||
this.el.style.opacity = 0;
|
||||
this.setType(type);
|
||||
@ -4049,7 +4078,8 @@
|
||||
|
||||
Notice.prototype.close = function() {
|
||||
$.off(d, 'visibilitychange', this.add);
|
||||
return $.rm(this.el);
|
||||
$.rm(this.el);
|
||||
return typeof this.onclose === "function" ? this.onclose() : void 0;
|
||||
};
|
||||
|
||||
return Notice;
|
||||
@ -4089,7 +4119,7 @@
|
||||
|
||||
RandomAccessList.prototype.before = function(root, item) {
|
||||
var prev;
|
||||
if (item.next === root) {
|
||||
if (item.next === root || item === root) {
|
||||
return;
|
||||
}
|
||||
this.rmi(item);
|
||||
@ -4099,6 +4129,8 @@
|
||||
item.prev = prev;
|
||||
if (prev) {
|
||||
return prev.next = item;
|
||||
} else {
|
||||
return this.first = item;
|
||||
}
|
||||
};
|
||||
|
||||
@ -4114,6 +4146,8 @@
|
||||
item.next = next;
|
||||
if (next) {
|
||||
return next.prev = item;
|
||||
} else {
|
||||
return this.last = item;
|
||||
}
|
||||
};
|
||||
|
||||
@ -4125,7 +4159,11 @@
|
||||
}
|
||||
this.rmi(item);
|
||||
item.next = first;
|
||||
first.prev = item;
|
||||
if (first) {
|
||||
first.prev = item;
|
||||
} else {
|
||||
this.last = item;
|
||||
}
|
||||
this.first = item;
|
||||
return delete item.prev;
|
||||
};
|
||||
@ -4279,7 +4317,28 @@
|
||||
})();
|
||||
|
||||
Polyfill = {
|
||||
init: function() {},
|
||||
init: function() {
|
||||
this.notificationPermission();
|
||||
this.toBlob();
|
||||
return this.visibility();
|
||||
},
|
||||
notificationPermission: function() {
|
||||
if (!window.Notification || 'permission' in Notification || !window.webkitNotifications) {
|
||||
return;
|
||||
}
|
||||
return Object.defineProperty(Notification, 'permission', {
|
||||
get: function() {
|
||||
switch (webkitNotifications.checkPermission()) {
|
||||
case 0:
|
||||
return 'granted';
|
||||
case 1:
|
||||
return 'default';
|
||||
case 2:
|
||||
return 'denied';
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
toBlob: function() {
|
||||
var _base;
|
||||
return (_base = HTMLCanvasElement.prototype).toBlob || (_base.toBlob = function(cb) {
|
||||
@ -4294,6 +4353,26 @@
|
||||
type: 'image/png'
|
||||
}));
|
||||
});
|
||||
},
|
||||
visibility: function() {
|
||||
if ('visibilityState' in d) {
|
||||
return;
|
||||
}
|
||||
Object.defineProperties(HTMLDocument.prototype, {
|
||||
visibilityState: {
|
||||
get: function() {
|
||||
return this.webkitVisibilityState;
|
||||
}
|
||||
},
|
||||
hidden: {
|
||||
get: function() {
|
||||
return this.webkitHidden;
|
||||
}
|
||||
}
|
||||
});
|
||||
return $.on(d, 'webkitvisibilitychange', function() {
|
||||
return $.event('visibilitychange');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@ -13442,7 +13521,7 @@
|
||||
MarkNewIPs.ipCount = this.ipCount;
|
||||
MarkNewIPs.postIDs = (function() {
|
||||
var _i, _len, _ref, _results;
|
||||
_ref = this.post.keys;
|
||||
_ref = this.posts.keys;
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
x = _ref[_i];
|
||||
|
||||
@ -3167,26 +3167,24 @@
|
||||
};
|
||||
|
||||
Callbacks.prototype.execute = function(nodes) {
|
||||
var cb, err, errors, i, j, name, node;
|
||||
i = 0;
|
||||
while (name = this.keys[i++]) {
|
||||
j = 0;
|
||||
cb = this[name];
|
||||
while (node = nodes[j++]) {
|
||||
try {
|
||||
if (!cb.disconnected) {
|
||||
cb.call(node);
|
||||
}
|
||||
} catch (_error) {
|
||||
err = _error;
|
||||
if (!errors) {
|
||||
errors = [];
|
||||
}
|
||||
errors.push({
|
||||
message: ['"', name, '" crashed on node ', this.type, ' No.', node.ID, ' (', node.board, ').'].join(''),
|
||||
error: err
|
||||
});
|
||||
var err, errors, name, node, _i, _j, _len, _len1, _ref;
|
||||
_ref = this.keys;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
name = _ref[_i];
|
||||
try {
|
||||
for (_j = 0, _len1 = nodes.length; _j < _len1; _j++) {
|
||||
node = nodes[_j];
|
||||
this[name].call(node);
|
||||
}
|
||||
} catch (_error) {
|
||||
err = _error;
|
||||
if (!errors) {
|
||||
errors = [];
|
||||
}
|
||||
errors.push({
|
||||
message: ['"', name, '" crashed on node ', this.type, ' No.', node.ID, ' (', node.board, ').'].join(''),
|
||||
error: err
|
||||
});
|
||||
}
|
||||
}
|
||||
if (errors) {
|
||||
@ -3242,13 +3240,16 @@
|
||||
}
|
||||
|
||||
Thread.prototype.setPage = function(pageNum) {
|
||||
var icon, key, _i, _len, _ref;
|
||||
icon = $('.page-num', this.OP.nodes.info);
|
||||
_ref = ['title', 'textContent'];
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
key = _ref[_i];
|
||||
icon[key] = icon[key].replace(/\d+/, pageNum);
|
||||
var icon, info, quote, _ref;
|
||||
_ref = this.OP.nodes, info = _ref.info, quote = _ref.quote;
|
||||
if (!(icon = $('.page-num', info))) {
|
||||
icon = $.el('span', {
|
||||
className: 'page-num'
|
||||
});
|
||||
$.after(quote, [$.tn(' '), icon]);
|
||||
}
|
||||
icon.title = "This thread is on page " + pageNum + " in the original index.";
|
||||
icon.textContent = "[" + pageNum + "]";
|
||||
if (this.catalogView) {
|
||||
return this.catalogView.nodes.pageCount.textContent = pageNum;
|
||||
}
|
||||
@ -3265,7 +3266,7 @@
|
||||
};
|
||||
|
||||
Thread.prototype.setStatus = function(type, status) {
|
||||
var name, typeLC;
|
||||
var name;
|
||||
name = "is" + type;
|
||||
if (this[name] === status) {
|
||||
return;
|
||||
@ -3274,7 +3275,6 @@
|
||||
if (!this.OP) {
|
||||
return;
|
||||
}
|
||||
typeLC = type.toLowerCase();
|
||||
this.setIcon('Sticky', this.isSticky);
|
||||
this.setIcon('Closed', this.isClosed && !this.isArchived);
|
||||
return this.setIcon('Archived', this.isArchived);
|
||||
@ -3301,7 +3301,7 @@
|
||||
title: type,
|
||||
className: "" + typeLC + "Icon retina"
|
||||
});
|
||||
root = type !== 'Sticky' && this.isSticky ? $('.stickyIcon', this.OP.nodes.info) : $('.page-num', this.OP.nodes.info) || $('[title="Reply to this post"]', this.OP.nodes.info);
|
||||
root = type !== 'Sticky' && this.isSticky ? $('.stickyIcon', this.OP.nodes.info) : $('.page-num', this.OP.nodes.info) || this.OP.nodes.quote;
|
||||
$.after(root, [$.tn(' '), icon]);
|
||||
if (!this.catalogView) {
|
||||
return;
|
||||
@ -3375,11 +3375,12 @@
|
||||
this.board = this.thread.board;
|
||||
this.nodes = {
|
||||
root: root,
|
||||
thumb: $('.thumb', root),
|
||||
icons: $('.thread-icons', root),
|
||||
thumb: $('.catalog-thumb', root),
|
||||
icons: $('.catalog-icons', root),
|
||||
postCount: $('.post-count', root),
|
||||
fileCount: $('.file-count', root),
|
||||
pageCount: $('.page-count', root)
|
||||
pageCount: $('.page-count', root),
|
||||
comment: $('.comment', root)
|
||||
};
|
||||
this.thread.catalogView = this;
|
||||
}
|
||||
@ -3404,17 +3405,18 @@
|
||||
}
|
||||
this.ID = +root.id.slice(2);
|
||||
this.fullID = "" + this.board + "." + this.ID;
|
||||
post = $('.post', root);
|
||||
info = $('.postInfo', post);
|
||||
if (that.isOriginalMarkup) {
|
||||
this.cleanup(root, post);
|
||||
}
|
||||
post = $('.post', root);
|
||||
info = $('.postInfo', post);
|
||||
root.dataset.fullID = this.fullID;
|
||||
this.nodes = {
|
||||
root: root,
|
||||
post: post,
|
||||
info: info,
|
||||
nameBlock: $('.nameBlock', info),
|
||||
quote: $('.postNum > a:nth-of-type(2)', info),
|
||||
comment: $('.postMessage', post),
|
||||
links: [],
|
||||
quotelinks: [],
|
||||
@ -3422,8 +3424,12 @@
|
||||
};
|
||||
if (!(this.isReply = $.hasClass(post, 'reply'))) {
|
||||
this.thread.OP = this;
|
||||
this.thread.isArchived = !!$('.archivedIcon', info);
|
||||
this.thread.isSticky = !!$('.stickyIcon', info);
|
||||
this.thread.isClosed = !!$('.closedIcon', info);
|
||||
this.thread.isClosed = this.thread.isArchived || !!$('.closedIcon', info);
|
||||
if (this.thread.isArchived) {
|
||||
this.thread.kill();
|
||||
}
|
||||
}
|
||||
this.info = {};
|
||||
this.info.nameBlock = Conf['Anonymize'] ? 'Anonymous' : this.nodes.nameBlock.textContent.trim();
|
||||
@ -3474,27 +3480,45 @@
|
||||
}
|
||||
|
||||
Post.prototype.parseComment = function() {
|
||||
var bq, i, node, nodes, text;
|
||||
var bq, i, node, nodes, spoilers;
|
||||
this.nodes.comment.normalize();
|
||||
bq = this.nodes.comment.cloneNode(true);
|
||||
nodes = $$('.abbr, .exif, b', bq);
|
||||
nodes = $$('.abbr, .exif, b, marquee', bq);
|
||||
i = 0;
|
||||
while (node = nodes[i++]) {
|
||||
$.rm(node);
|
||||
}
|
||||
this.info.comment = this.nodesToText(bq);
|
||||
spoilers = $$('s', bq);
|
||||
return this.info.commentSpoilered = (function() {
|
||||
var _i, _len;
|
||||
if (spoilers.length) {
|
||||
for (_i = 0, _len = spoilers.length; _i < _len; _i++) {
|
||||
node = spoilers[_i];
|
||||
$.replace(node, $.tn('[spoiler]'));
|
||||
}
|
||||
return this.nodesToText(bq);
|
||||
} else {
|
||||
return this.info.comment;
|
||||
}
|
||||
}).call(this);
|
||||
};
|
||||
|
||||
Post.prototype.nodesToText = function(bq) {
|
||||
var i, node, nodes, text;
|
||||
text = "";
|
||||
nodes = $.X('.//br|.//text()', bq);
|
||||
i = 0;
|
||||
while (node = nodes.snapshotItem(i++)) {
|
||||
text += node.data || '\n';
|
||||
}
|
||||
return this.info.comment = text.trim().replace(/\s+$/gm, '');
|
||||
return text.trim().replace(/\s+$/gm, '');
|
||||
};
|
||||
|
||||
Post.prototype.parseQuotes = function() {
|
||||
var quotelink, _i, _len, _ref;
|
||||
this.quotes = [];
|
||||
_ref = $$('.quotelink', this.nodes.comment);
|
||||
_ref = $$(':not(pre) > .quotelink', this.nodes.comment);
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
quotelink = _ref[_i];
|
||||
this.parseQuote(quotelink);
|
||||
@ -3503,7 +3527,7 @@
|
||||
|
||||
Post.prototype.parseQuote = function(quotelink) {
|
||||
var fullID, match;
|
||||
if (!(match = quotelink.href.match(/boards\.4chan\.org\/([^\/]+)\/thread\/\d+.*\#p(\d+)$/))) {
|
||||
if (!(match = quotelink.href.match(/boards\.4chan\.org\/([^\/]+)\/(?:res|thread)\/\d+(?:\/[^#]*)?#p(\d+)$/))) {
|
||||
return;
|
||||
}
|
||||
this.nodes.quotelinks.push(quotelink);
|
||||
@ -3517,7 +3541,7 @@
|
||||
};
|
||||
|
||||
Post.prototype.parseFile = function(that) {
|
||||
var anchor, fileEl, fileText, nameNode, size, thumb, unit, _ref;
|
||||
var anchor, fileEl, fileText, nameNode, size, thumb, unit;
|
||||
if (!((fileEl = $('.file', this.nodes.post)) && (thumb = $('img[data-md5]', fileEl)))) {
|
||||
return;
|
||||
}
|
||||
@ -3537,31 +3561,26 @@
|
||||
size *= 1024;
|
||||
}
|
||||
this.file.sizeInBytes = size;
|
||||
this.file.thumbURL = that.isArchived ? thumb.src : "" + location.protocol + "//t.4cdn.org/" + this.board + "/" + (this.file.URL.match(/(\d+)\./)[1]) + "s.jpg";
|
||||
this.file.thumbURL = "" + location.protocol + "//t.4cdn.org/" + this.board + "/" + (this.file.URL.match(/(\d+)\./)[1]) + "s.jpg";
|
||||
this.file.isImage = /(jpg|png|gif)$/i.test(this.file.URL);
|
||||
this.file.isVideo = /webm$/i.test(this.file.URL);
|
||||
nameNode = $('a', fileText);
|
||||
if (this.file.isImage || this.file.isVideo) {
|
||||
this.file.dimensions = fileText.childNodes[2].data.match(/\d+x\d+/)[0];
|
||||
this.file.dimensions = nameNode.nextSibling.textContent.match(/\d+x\d+/)[0];
|
||||
}
|
||||
this.file.name = !this.file.isSpoiler && (nameNode = $('a', fileText)) ? nameNode.title || nameNode.textContent : fileText.title;
|
||||
return this.file.name = (_ref = this.file.name) != null ? _ref.replace(/%22/g, '"') : void 0;
|
||||
return this.file.name = fileText.title || nameNode.title || nameNode.textContent;
|
||||
};
|
||||
|
||||
Post.prototype.cleanup = function(root, post) {
|
||||
var node, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2;
|
||||
Post.prototype.cleanup = function(root) {
|
||||
var node, _i, _j, _len, _len1, _ref, _ref1;
|
||||
_ref = $$('.mobile', root);
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
node = _ref[_i];
|
||||
$.rm(node);
|
||||
}
|
||||
_ref1 = $$('[id]:not(.exif)', post);
|
||||
_ref1 = $$('.desktop', root);
|
||||
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
|
||||
node = _ref1[_j];
|
||||
node.removeAttribute('id');
|
||||
}
|
||||
_ref2 = $$('.desktop', root);
|
||||
for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
|
||||
node = _ref2[_k];
|
||||
$.rmClass(node, 'desktop');
|
||||
}
|
||||
};
|
||||
@ -3633,9 +3652,6 @@
|
||||
return;
|
||||
}
|
||||
this.isHidden = false;
|
||||
this.labels = this.labels.filter(function(label) {
|
||||
return !/^(Manually hidden|Recursively hidden|Hidden by)/.test(label);
|
||||
});
|
||||
_ref = Get.allQuotelinksLinkingTo(this);
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
quotelink = _ref[_i];
|
||||
@ -3664,8 +3680,7 @@
|
||||
return delete this.nodes.stub;
|
||||
};
|
||||
|
||||
Post.prototype.highlight = function(label, highlight, top) {
|
||||
this.labels.push(label);
|
||||
Post.prototype.highlight = function(highlight, top) {
|
||||
if (__indexOf.call(this.highlights, highlight) < 0) {
|
||||
this.highlights.push(highlight);
|
||||
$.addClass(this.nodes.root, highlight);
|
||||
@ -3778,7 +3793,7 @@
|
||||
__extends(Clone, _super);
|
||||
|
||||
function Clone(origin, context, contractThumb) {
|
||||
var file, info, inline, inlined, key, nodes, post, root, val, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3, _ref4, _ref5;
|
||||
var file, info, inline, inlined, key, nodes, post, root, val, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3;
|
||||
this.origin = origin;
|
||||
this.context = context;
|
||||
_ref = ['ID', 'fullID', 'board', 'thread', 'info', 'quotes', 'isReply'];
|
||||
@ -3787,13 +3802,15 @@
|
||||
this[key] = origin[key];
|
||||
}
|
||||
nodes = origin.nodes;
|
||||
root = nodes.root.cloneNode(true);
|
||||
root = contractThumb ? this.cloneWithoutVideo(nodes.root) : nodes.root.cloneNode(true);
|
||||
post = $('.post', root);
|
||||
info = $('.postInfo', post);
|
||||
this.nodes = {
|
||||
root: root,
|
||||
post: post,
|
||||
info: info,
|
||||
nameBlock: $('.nameBlock', info),
|
||||
quote: $('.postNum > a:nth-of-type(2)', info),
|
||||
comment: $('.postMessage', post),
|
||||
quotelinks: [],
|
||||
backlinks: info.getElementsByClassName('backlink')
|
||||
@ -3827,10 +3844,10 @@
|
||||
this.nodes.uniqueID = $('.posteruid', info);
|
||||
}
|
||||
if (nodes.capcode) {
|
||||
this.nodes.capcode = $('.capcode', info);
|
||||
this.nodes.capcode = $('.capcode.hand', info);
|
||||
}
|
||||
if (nodes.flag) {
|
||||
this.nodes.flag = $('.countryFlag', info);
|
||||
this.nodes.flag = $('.flag, .countryFlag', info);
|
||||
}
|
||||
if (nodes.date) {
|
||||
this.nodes.date = $('.dateTime', info);
|
||||
@ -3845,18 +3862,11 @@
|
||||
}
|
||||
file = $('.file', post);
|
||||
this.file.text = file.firstElementChild;
|
||||
this.file.thumb = $('img[data-md5], video[data-md5]', file);
|
||||
this.file.thumb = $('.fileThumb > [data-md5]', file);
|
||||
this.file.fullImage = $('.full-image', file);
|
||||
this.file.videoControls = $('.video-controls', this.file.text);
|
||||
if (contractThumb) {
|
||||
$.rmClass(root, 'expanded-image');
|
||||
$.rmClass(this.file.thumb, 'expanding');
|
||||
}
|
||||
this.file.isExpanded = $.hasClass(root, 'expanded-image');
|
||||
if ((_ref4 = this.file.fullImage) != null) {
|
||||
_ref4.removeAttribute('id');
|
||||
}
|
||||
if ((_ref5 = $('.video-controls', this.file.text)) != null) {
|
||||
_ref5.remove();
|
||||
ImageExpand.contract(this);
|
||||
}
|
||||
}
|
||||
if (origin.isDead) {
|
||||
@ -3866,6 +3876,23 @@
|
||||
root.dataset.clone = origin.clones.push(this) - 1;
|
||||
}
|
||||
|
||||
Clone.prototype.cloneWithoutVideo = function(node) {
|
||||
var child, clone, _i, _len, _ref;
|
||||
if (node.tagName === 'VIDEO' && !node.dataset.md5) {
|
||||
return [];
|
||||
} else if (node.nodeType === Node.ELEMENT_NODE && $('video', node)) {
|
||||
clone = node.cloneNode(false);
|
||||
_ref = node.childNodes;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
child = _ref[_i];
|
||||
$.add(clone, this.cloneWithoutVideo(child));
|
||||
}
|
||||
return clone;
|
||||
} else {
|
||||
return node.cloneNode(true);
|
||||
}
|
||||
};
|
||||
|
||||
return Clone;
|
||||
|
||||
})(Post);
|
||||
@ -4039,12 +4066,13 @@
|
||||
})();
|
||||
|
||||
Notice = (function() {
|
||||
function Notice(type, content, timeout) {
|
||||
function Notice(type, content, timeout, onclose) {
|
||||
this.timeout = timeout;
|
||||
this.onclose = onclose;
|
||||
this.close = __bind(this.close, this);
|
||||
this.add = __bind(this.add, this);
|
||||
this.el = $.el('div', {
|
||||
innerHTML: '<a href=javascript:; class="close fa" title=Close>\uf00d</a><div class=message></div>'
|
||||
innerHTML: "<a href=\"javascript:;\" class=\"close fa fa-times\" title=\"Close\"></a><div class=\"message\"></div>"
|
||||
});
|
||||
this.el.style.opacity = 0;
|
||||
this.setType(type);
|
||||
@ -4076,7 +4104,8 @@
|
||||
|
||||
Notice.prototype.close = function() {
|
||||
$.off(d, 'visibilitychange', this.add);
|
||||
return $.rm(this.el);
|
||||
$.rm(this.el);
|
||||
return typeof this.onclose === "function" ? this.onclose() : void 0;
|
||||
};
|
||||
|
||||
return Notice;
|
||||
@ -4116,7 +4145,7 @@
|
||||
|
||||
RandomAccessList.prototype.before = function(root, item) {
|
||||
var prev;
|
||||
if (item.next === root) {
|
||||
if (item.next === root || item === root) {
|
||||
return;
|
||||
}
|
||||
this.rmi(item);
|
||||
@ -4126,6 +4155,8 @@
|
||||
item.prev = prev;
|
||||
if (prev) {
|
||||
return prev.next = item;
|
||||
} else {
|
||||
return this.first = item;
|
||||
}
|
||||
};
|
||||
|
||||
@ -4141,6 +4172,8 @@
|
||||
item.next = next;
|
||||
if (next) {
|
||||
return next.prev = item;
|
||||
} else {
|
||||
return this.last = item;
|
||||
}
|
||||
};
|
||||
|
||||
@ -4152,7 +4185,11 @@
|
||||
}
|
||||
this.rmi(item);
|
||||
item.next = first;
|
||||
first.prev = item;
|
||||
if (first) {
|
||||
first.prev = item;
|
||||
} else {
|
||||
this.last = item;
|
||||
}
|
||||
this.first = item;
|
||||
return delete item.prev;
|
||||
};
|
||||
@ -4307,7 +4344,26 @@
|
||||
|
||||
Polyfill = {
|
||||
init: function() {
|
||||
return this.toBlob();
|
||||
this.notificationPermission();
|
||||
this.toBlob();
|
||||
return this.visibility();
|
||||
},
|
||||
notificationPermission: function() {
|
||||
if (!window.Notification || 'permission' in Notification || !window.webkitNotifications) {
|
||||
return;
|
||||
}
|
||||
return Object.defineProperty(Notification, 'permission', {
|
||||
get: function() {
|
||||
switch (webkitNotifications.checkPermission()) {
|
||||
case 0:
|
||||
return 'granted';
|
||||
case 1:
|
||||
return 'default';
|
||||
case 2:
|
||||
return 'denied';
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
toBlob: function() {
|
||||
var _base;
|
||||
@ -4323,6 +4379,26 @@
|
||||
type: 'image/png'
|
||||
}));
|
||||
});
|
||||
},
|
||||
visibility: function() {
|
||||
if ('visibilityState' in d) {
|
||||
return;
|
||||
}
|
||||
Object.defineProperties(HTMLDocument.prototype, {
|
||||
visibilityState: {
|
||||
get: function() {
|
||||
return this.webkitVisibilityState;
|
||||
}
|
||||
},
|
||||
hidden: {
|
||||
get: function() {
|
||||
return this.webkitHidden;
|
||||
}
|
||||
}
|
||||
});
|
||||
return $.on(d, 'webkitvisibilitychange', function() {
|
||||
return $.event('visibilitychange');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@ -13469,7 +13545,7 @@
|
||||
MarkNewIPs.ipCount = this.ipCount;
|
||||
MarkNewIPs.postIDs = (function() {
|
||||
var _i, _len, _ref, _results;
|
||||
_ref = this.post.keys;
|
||||
_ref = this.posts.keys;
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
x = _ref[_i];
|
||||
|
||||
@ -11,21 +11,13 @@ class Callbacks
|
||||
disconnect: (name) -> @[name].disconnected = true if @[name]
|
||||
|
||||
execute: (nodes) ->
|
||||
i = 0
|
||||
# c.time 'Features'
|
||||
while name = @keys[i++]
|
||||
j = 0
|
||||
cb = @[name]
|
||||
# c.time name
|
||||
while node = nodes[j++]
|
||||
try
|
||||
cb.call node unless cb.disconnected
|
||||
catch err
|
||||
errors = [] unless errors
|
||||
errors.push
|
||||
message: ['"', name, '" crashed on node ', @type, ' No.', node.ID, ' (', node.board, ').'].join('')
|
||||
error: err
|
||||
# c.timeEnd name
|
||||
# c.timeEnd 'Features'
|
||||
for name in @keys
|
||||
try
|
||||
@[name].call node for node in nodes
|
||||
catch err
|
||||
errors = [] unless errors
|
||||
errors.push
|
||||
message: ['"', name, '" crashed on node ', @type, ' No.', node.ID, ' (', node.board, ').'].join('')
|
||||
error: err
|
||||
|
||||
Main.handleErrors errors if errors
|
||||
|
||||
@ -7,9 +7,10 @@ class CatalogThread
|
||||
@board = @thread.board
|
||||
@nodes =
|
||||
root: root
|
||||
thumb: $ '.thumb', root
|
||||
icons: $ '.thread-icons', root
|
||||
postCount: $ '.post-count', root
|
||||
fileCount: $ '.file-count', root
|
||||
pageCount: $ '.page-count', root
|
||||
thumb: $ '.catalog-thumb', root
|
||||
icons: $ '.catalog-icons', root
|
||||
postCount: $ '.post-count', root
|
||||
fileCount: $ '.file-count', root
|
||||
pageCount: $ '.page-count', root
|
||||
comment: $ '.comment', root
|
||||
@thread.catalogView = @
|
||||
|
||||
@ -9,4 +9,4 @@
|
||||
<%= grunt.file.read('src/General/lib/randomaccesslist.class') %>
|
||||
<%= grunt.file.read('src/General/lib/simpledict.class') %>
|
||||
<%= grunt.file.read('src/General/lib/set.class') %>
|
||||
<%= grunt.file.read('src/General/lib/connection.class') %>
|
||||
<%= grunt.file.read('src/General/lib/connection.class') %>
|
||||
|
||||
@ -5,13 +5,18 @@ class Clone extends Post
|
||||
@[key] = origin[key]
|
||||
|
||||
{nodes} = origin
|
||||
root = nodes.root.cloneNode true
|
||||
root = if contractThumb
|
||||
@cloneWithoutVideo nodes.root
|
||||
else
|
||||
nodes.root.cloneNode true
|
||||
post = $ '.post', root
|
||||
info = $ '.postInfo', post
|
||||
@nodes =
|
||||
root: root
|
||||
post: post
|
||||
info: info
|
||||
nameBlock: $ '.nameBlock', info
|
||||
quote: $ '.postNum > a:nth-of-type(2)', info
|
||||
comment: $ '.postMessage', post
|
||||
quotelinks: []
|
||||
backlinks: info.getElementsByClassName 'backlink'
|
||||
@ -37,9 +42,9 @@ class Clone extends Post
|
||||
if nodes.uniqueID
|
||||
@nodes.uniqueID = $ '.posteruid', info
|
||||
if nodes.capcode
|
||||
@nodes.capcode = $ '.capcode', info
|
||||
@nodes.capcode = $ '.capcode.hand', info
|
||||
if nodes.flag
|
||||
@nodes.flag = $ '.countryFlag', info
|
||||
@nodes.flag = $ '.flag, .countryFlag', info
|
||||
if nodes.date
|
||||
@nodes.date = $ '.dateTime', info
|
||||
|
||||
@ -53,21 +58,23 @@ class Clone extends Post
|
||||
@file[key] = val
|
||||
file = $ '.file', post
|
||||
@file.text = file.firstElementChild
|
||||
@file.thumb = $ 'img[data-md5], video[data-md5]', file
|
||||
@file.thumb = $ '.fileThumb > [data-md5]', file
|
||||
@file.fullImage = $ '.full-image', file
|
||||
@file.videoControls = $ '.video-controls', @file.text
|
||||
|
||||
# Contract thumbnails in quote preview
|
||||
if contractThumb
|
||||
$.rmClass root, 'expanded-image'
|
||||
$.rmClass @file.thumb, 'expanding'
|
||||
@file.isExpanded = $.hasClass root, 'expanded-image'
|
||||
|
||||
# Remove any #ihover ID
|
||||
@file.fullImage?.removeAttribute 'id'
|
||||
|
||||
# Remove video controls.
|
||||
($ '.video-controls', @file.text)?.remove()
|
||||
ImageExpand.contract @ if contractThumb
|
||||
|
||||
@isDead = true if origin.isDead
|
||||
@isClone = true
|
||||
root.dataset.clone = origin.clones.push(@) - 1
|
||||
root.dataset.clone = origin.clones.push(@) - 1
|
||||
|
||||
cloneWithoutVideo: (node) ->
|
||||
if node.tagName is 'VIDEO' and !node.dataset.md5 # (exception for WebM thumbnails)
|
||||
[]
|
||||
else if node.nodeType is Node.ELEMENT_NODE and $ 'video', node
|
||||
clone = node.cloneNode false
|
||||
$.add clone, @cloneWithoutVideo child for child in node.childNodes
|
||||
clone
|
||||
else
|
||||
node.cloneNode true
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
class Notice
|
||||
constructor: (type, content, @timeout) ->
|
||||
constructor: (type, content, @timeout, @onclose) ->
|
||||
@el = $.el 'div',
|
||||
innerHTML: '<a href=javascript:; class="close fa" title=Close>\uf00d</a><div class=message></div>'
|
||||
<%= html('<a href="javascript:;" class="close fa fa-times" title="Close"></a><div class="message"></div>') %>
|
||||
@el.style.opacity = 0
|
||||
@setType type
|
||||
$.on @el.firstElementChild, 'click', @close
|
||||
@ -27,3 +27,4 @@ class Notice
|
||||
close: =>
|
||||
$.off d, 'visibilitychange', @add
|
||||
$.rm @el
|
||||
@onclose?()
|
||||
|
||||
@ -1,8 +1,19 @@
|
||||
Polyfill =
|
||||
init: ->
|
||||
<% if (type === 'crx') { %>
|
||||
@notificationPermission()
|
||||
@toBlob()
|
||||
<% } %>
|
||||
@visibility()
|
||||
notificationPermission: ->
|
||||
return if !window.Notification or 'permission' of Notification or !window.webkitNotifications
|
||||
Object.defineProperty Notification, 'permission',
|
||||
get: ->
|
||||
switch webkitNotifications.checkPermission()
|
||||
when 0
|
||||
'granted'
|
||||
when 1
|
||||
'default'
|
||||
when 2
|
||||
'denied'
|
||||
toBlob: ->
|
||||
HTMLCanvasElement::toBlob or= (cb) ->
|
||||
data = atob @toDataURL()[22..]
|
||||
@ -12,3 +23,12 @@ Polyfill =
|
||||
for i in [0...l] by 1
|
||||
ui8a[i] = data.charCodeAt i
|
||||
cb new Blob [ui8a], type: 'image/png'
|
||||
visibility: ->
|
||||
# page visibility API
|
||||
return if 'visibilityState' of d
|
||||
Object.defineProperties HTMLDocument.prototype,
|
||||
visibilityState:
|
||||
get: -> @webkitVisibilityState
|
||||
hidden:
|
||||
get: -> @webkitHidden
|
||||
$.on d, 'webkitvisibilitychange', -> $.event 'visibilitychange'
|
||||
|
||||
@ -6,15 +6,16 @@ class Post
|
||||
@ID = +root.id[2..]
|
||||
@fullID = "#{@board}.#{@ID}"
|
||||
|
||||
@cleanup root, post if that.isOriginalMarkup
|
||||
post = $ '.post', root
|
||||
info = $ '.postInfo', post
|
||||
@cleanup root, post if that.isOriginalMarkup
|
||||
root.dataset.fullID = @fullID
|
||||
@nodes =
|
||||
root: root
|
||||
post: post
|
||||
info: info
|
||||
nameBlock: $ '.nameBlock', info
|
||||
quote: $ '.postNum > a:nth-of-type(2)', info
|
||||
comment: $ '.postMessage', post
|
||||
links: []
|
||||
quotelinks: []
|
||||
@ -22,8 +23,10 @@ class Post
|
||||
|
||||
unless @isReply = $.hasClass post, 'reply'
|
||||
@thread.OP = @
|
||||
@thread.isSticky = !!$ '.stickyIcon', info
|
||||
@thread.isClosed = !!$ '.closedIcon', info
|
||||
@thread.isArchived = !!$ '.archivedIcon', info
|
||||
@thread.isSticky = !!$ '.stickyIcon', info
|
||||
@thread.isClosed = @thread.isArchived or !!$ '.closedIcon', info
|
||||
@thread.kill() if @thread.isArchived
|
||||
|
||||
@info = {}
|
||||
@info.nameBlock = if Conf['Anonymize']
|
||||
@ -71,28 +74,44 @@ class Post
|
||||
parseComment: ->
|
||||
# Merge text nodes and remove empty ones.
|
||||
@nodes.comment.normalize()
|
||||
|
||||
# Get the comment's text.
|
||||
# <br> -> \n
|
||||
# Remove:
|
||||
# 'Comment too long'...
|
||||
# EXIF data. (/p/)
|
||||
# Rolls. (/tg/)
|
||||
# Marquees. (/pol/)
|
||||
# Preceding and following new lines.
|
||||
# Trailing spaces.
|
||||
bq = @nodes.comment.cloneNode true
|
||||
nodes = $$ '.abbr, .exif, b', bq
|
||||
nodes = $$ '.abbr, .exif, b, marquee', bq
|
||||
i = 0
|
||||
while node = nodes[i++]
|
||||
$.rm node
|
||||
$.rm node while node = nodes[i++]
|
||||
@info.comment = @nodesToText bq
|
||||
|
||||
# Get the comment's text with spoilers hidden.
|
||||
spoilers = $$ 's', bq
|
||||
@info.commentSpoilered = if spoilers.length
|
||||
for node in spoilers
|
||||
$.replace node, $.tn '[spoiler]'
|
||||
@nodesToText bq
|
||||
else
|
||||
@info.comment
|
||||
|
||||
nodesToText: (bq) ->
|
||||
text = ""
|
||||
nodes = $.X './/br|.//text()', bq
|
||||
i = 0
|
||||
while node = nodes.snapshotItem i++
|
||||
text += node.data or '\n'
|
||||
@info.comment = text.trim().replace /\s+$/gm, ''
|
||||
text.trim().replace /\s+$/gm, ''
|
||||
|
||||
parseQuotes: ->
|
||||
@quotes = []
|
||||
for quotelink in $$ '.quotelink', @nodes.comment
|
||||
# XXX https://github.com/4chan/4chan-JS/issues/77
|
||||
# 4chan currently creates quote links inside [code] tags; ignore them
|
||||
for quotelink in $$ ':not(pre) > .quotelink', @nodes.comment
|
||||
@parseQuote quotelink
|
||||
return
|
||||
|
||||
@ -106,9 +125,8 @@ class Post
|
||||
return unless match = quotelink.href.match ///
|
||||
boards\.4chan\.org/
|
||||
([^/]+) # boardID
|
||||
/thread/\d+
|
||||
.* # thread slug
|
||||
\#p(\d+) # postID
|
||||
/(?:res|thread)/\d+(?:\/[^#]*)?#p
|
||||
(\d+) # postID
|
||||
$
|
||||
///
|
||||
|
||||
@ -122,7 +140,7 @@ class Post
|
||||
|
||||
parseFile: (that) ->
|
||||
return unless (fileEl = $ '.file', @nodes.post) and thumb = $ 'img[data-md5]', fileEl
|
||||
# Supports JPG/PNG/GIF/WEBM/PDF.
|
||||
# Supports JPG/PNG/GIF/PDF.
|
||||
# Flash files are not supported.
|
||||
anchor = thumb.parentNode
|
||||
fileText = fileEl.firstElementChild
|
||||
@ -137,32 +155,17 @@ class Post
|
||||
unit = ['B', 'KB', 'MB', 'GB'].indexOf @file.size.match(/\w+$/)[0]
|
||||
size *= 1024 while unit-- > 0
|
||||
@file.sizeInBytes = size
|
||||
@file.thumbURL = if that.isArchived
|
||||
thumb.src
|
||||
else
|
||||
"#{location.protocol}//t.4cdn.org/#{@board}/#{@file.URL.match(/(\d+)\./)[1]}s.jpg"
|
||||
@file.thumbURL = "#{location.protocol}//t.4cdn.org/#{@board}/#{@file.URL.match(/(\d+)\./)[1]}s.jpg"
|
||||
@file.isImage = /(jpg|png|gif)$/i.test @file.URL
|
||||
@file.isVideo = /webm$/i.test @file.URL
|
||||
nameNode = $ 'a', fileText
|
||||
if @file.isImage or @file.isVideo
|
||||
@file.dimensions = fileText.childNodes[2].data.match(/\d+x\d+/)[0]
|
||||
@file.name = if !@file.isSpoiler and nameNode = $ 'a', fileText
|
||||
nameNode.title or nameNode.textContent
|
||||
else
|
||||
fileText.title
|
||||
<% if (type === 'crx') { %>
|
||||
# replace %22 with quotes, see:
|
||||
# crbug.com/81193
|
||||
# webk.it/62107
|
||||
# https://www.w3.org/Bugs/Public/show_bug.cgi?id=16909
|
||||
# http://www.whatwg.org/specs/web-apps/current-work/#multipart-form-data
|
||||
@file.name = @file.name?.replace /%22/g, '"'
|
||||
<% } %>
|
||||
@file.dimensions = nameNode.nextSibling.textContent.match(/\d+x\d+/)[0]
|
||||
@file.name = fileText.title or nameNode.title or nameNode.textContent
|
||||
|
||||
cleanup: (root, post) ->
|
||||
cleanup: (root) ->
|
||||
for node in $$ '.mobile', root
|
||||
$.rm node
|
||||
for node in $$ '[id]:not(.exif)', post
|
||||
node.removeAttribute 'id'
|
||||
for node in $$ '.desktop', root
|
||||
$.rmClass node, 'desktop'
|
||||
return
|
||||
@ -209,9 +212,6 @@ class Post
|
||||
show: (showRecursively=Conf['Recursive Hiding']) ->
|
||||
return if !@isHidden
|
||||
@isHidden = false
|
||||
@labels = @labels.filter (label) ->
|
||||
# This is lame.
|
||||
!/^(Manually hidden|Recursively hidden|Hidden by)/.test label
|
||||
|
||||
for quotelink in Get.allQuotelinksLinkingTo @
|
||||
$.rmClass quotelink, 'filtered'
|
||||
@ -233,8 +233,7 @@ class Post
|
||||
@nodes.post.previousElementSibling.hidden = false
|
||||
$.rm @nodes.stub
|
||||
delete @nodes.stub
|
||||
highlight: (label, highlight, top) ->
|
||||
@labels.push label
|
||||
highlight: (highlight, top) ->
|
||||
unless highlight in @highlights
|
||||
@highlights.push highlight
|
||||
$.addClass @nodes.root, highlight
|
||||
|
||||
@ -21,7 +21,7 @@ class RandomAccessList
|
||||
@length++
|
||||
|
||||
before: (root, item) ->
|
||||
return if item.next is root
|
||||
return if item.next is root or item is root
|
||||
|
||||
@rmi item
|
||||
|
||||
@ -29,7 +29,10 @@ class RandomAccessList
|
||||
root.prev = item
|
||||
item.next = root
|
||||
item.prev = prev
|
||||
prev.next = item if prev
|
||||
if prev
|
||||
prev.next = item
|
||||
else
|
||||
@first = item
|
||||
|
||||
after: (root, item) ->
|
||||
return if item.prev is root
|
||||
@ -40,14 +43,20 @@ class RandomAccessList
|
||||
root.next = item
|
||||
item.prev = root
|
||||
item.next = next
|
||||
next.prev = item if next
|
||||
if next
|
||||
next.prev = item
|
||||
else
|
||||
@last = item
|
||||
|
||||
prepend: (item) ->
|
||||
{first} = @
|
||||
return if item is first or not @[item.ID]
|
||||
@rmi item
|
||||
item.next = first
|
||||
first.prev = item
|
||||
if first
|
||||
first.prev = item
|
||||
else
|
||||
@last = item
|
||||
@first = item
|
||||
delete item.prev
|
||||
|
||||
@ -77,4 +86,4 @@ class RandomAccessList
|
||||
if next
|
||||
next.prev = prev
|
||||
else
|
||||
@last = prev
|
||||
@last = prev
|
||||
|
||||
@ -22,24 +22,28 @@ class Thread
|
||||
g.threads.push @fullID, board.threads.push @, @
|
||||
|
||||
setPage: (pageNum) ->
|
||||
icon = $ '.page-num', @OP.nodes.info
|
||||
for key in ['title', 'textContent']
|
||||
icon[key] = icon[key].replace /\d+/, pageNum
|
||||
{info, quote} = @OP.nodes
|
||||
unless icon = $ '.page-num', info
|
||||
icon = $.el 'span', className: 'page-num'
|
||||
$.after quote, [$.tn(' '), icon]
|
||||
icon.title = "This thread is on page #{pageNum} in the original index."
|
||||
icon.textContent = "[#{pageNum}]"
|
||||
@catalogView.nodes.pageCount.textContent = pageNum if @catalogView
|
||||
|
||||
setCount: (type, count, reachedLimit) ->
|
||||
return unless @catalogView
|
||||
el = @catalogView.nodes["#{type}Count"]
|
||||
el.textContent = count
|
||||
(if reachedLimit then $.addClass else $.rmClass) el, 'warning'
|
||||
|
||||
setStatus: (type, status) ->
|
||||
name = "is#{type}"
|
||||
return if @[name] is status
|
||||
@[name] = status
|
||||
return unless @OP
|
||||
typeLC = type.toLowerCase()
|
||||
|
||||
@setIcon 'Sticky', @isSticky
|
||||
@setIcon 'Closed', @isClosed and !@isArchived
|
||||
@setIcon 'Sticky', @isSticky
|
||||
@setIcon 'Closed', @isClosed and !@isArchived
|
||||
@setIcon 'Archived', @isArchived
|
||||
|
||||
setIcon: (type, status) ->
|
||||
@ -58,11 +62,10 @@ class Thread
|
||||
title: type
|
||||
className: "#{typeLC}Icon retina"
|
||||
|
||||
root =
|
||||
if type isnt 'Sticky' and @isSticky
|
||||
$ '.stickyIcon', @OP.nodes.info
|
||||
else
|
||||
$('.page-num', @OP.nodes.info) or $('[title="Reply to this post"]', @OP.nodes.info)
|
||||
root = if type isnt 'Sticky' and @isSticky
|
||||
$ '.stickyIcon', @OP.nodes.info
|
||||
else
|
||||
$('.page-num', @OP.nodes.info) or @OP.nodes.quote
|
||||
$.after root, [$.tn(' '), icon]
|
||||
|
||||
return unless @catalogView
|
||||
@ -71,6 +74,7 @@ class Thread
|
||||
pin: ->
|
||||
@isPinned = true
|
||||
$.addClass @catalogView.nodes.root, 'pinned' if @catalogView
|
||||
|
||||
unpin: ->
|
||||
@isPinned = false
|
||||
$.rmClass @catalogView.nodes.root, 'pinned' if @catalogView
|
||||
@ -81,6 +85,7 @@ class Thread
|
||||
@OP.nodes.root.parentElement.hidden = true
|
||||
if button = $ '.hide-post-button', @OP.nodes.root
|
||||
$.replace button, PostHiding.makeButton false
|
||||
|
||||
show: ->
|
||||
return if !@isHidden
|
||||
@isHidden = false
|
||||
|
||||
@ -7,7 +7,7 @@ MarkNewIPs =
|
||||
|
||||
node: ->
|
||||
MarkNewIPs.ipCount = @ipCount
|
||||
MarkNewIPs.postIDs = (+x for x in @post.keys)
|
||||
MarkNewIPs.postIDs = (+x for x in @posts.keys)
|
||||
$.on d, 'ThreadUpdate', MarkNewIPs.onUpdate
|
||||
|
||||
onUpdate: (e) ->
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user