From 5c43ffb27240f78e558005576245fffd0ebfab45 Mon Sep 17 00:00:00 2001 From: Zixaphir Date: Sun, 25 Aug 2013 08:31:34 -0700 Subject: [PATCH] Get some rudimentary error handling setup in the gallery This is mostly just Mayhem's ImageExpand error code, refactored for the context of the gallery. --- builds/4chan-X.user.js | 496 +++++++++++++++++++++++++++++++++++++- builds/crx/script.js | 496 +++++++++++++++++++++++++++++++++++++- src/Images/Gallery.coffee | 43 +++- 3 files changed, 1018 insertions(+), 17 deletions(-) diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index fed2a8d05..e9e17e841 100644 --- a/builds/4chan-X.user.js +++ b/builds/4chan-X.user.js @@ -353,6 +353,7 @@ Array.prototype.indexOf = function(object) { var i; + i = this.length; while (i--) { if (this[i] === object) { @@ -371,6 +372,7 @@ $.extend = function(object, properties) { var key, val; + for (key in properties) { val = properties[key]; if (!properties.hasOwnProperty(key)) { @@ -388,6 +390,7 @@ $.ready = function(fc) { var cb; + if (d.readyState !== 'loading') { $.queueTask(fc); return; @@ -401,6 +404,7 @@ $.formData = function(form) { var fd, key, val; + if (form instanceof HTMLFormElement) { return new FormData(form); } @@ -420,6 +424,7 @@ $.extend = function(object, properties) { var key, val; + for (key in properties) { val = properties[key]; object[key] = val; @@ -428,9 +433,11 @@ $.ajax = (function() { var lastModified; + lastModified = {}; return function(url, options, extra) { var form, r, sync, type, upCallbacks, whenModified; + if (extra == null) { extra = {}; } @@ -453,9 +460,11 @@ $.cache = (function() { var reqs; + reqs = {}; return function(url, cb, options) { var err, req, rm; + if (req = reqs[url]) { if (req.readyState === 4) { cb.call(req, req.evt); @@ -475,6 +484,7 @@ } $.on(req, 'load', function(e) { var _i, _len, _ref; + _ref = this.callbacks; for (_i = 0, _len = _ref.length; _i < _len; _i++) { cb = _ref[_i]; @@ -510,6 +520,7 @@ $.addStyle = function(css, id) { var style; + style = $.el('style', { id: id, textContent: css @@ -556,6 +567,7 @@ } else { return function(el) { var _ref; + return (_ref = el.parentNode) != null ? _ref.removeChild(el) : void 0; }; } @@ -563,6 +575,7 @@ $.rmAll = function(root) { var node; + while (node = root.firstChild) { root.removeChild(node); } @@ -578,6 +591,7 @@ $.nodes = function(nodes) { var frag, node, _i, _len; + if (!(nodes instanceof Array)) { return nodes; } @@ -611,6 +625,7 @@ $.el = function(tag, properties) { var el; + el = d.createElement(tag); if (properties) { $.extend(el, properties); @@ -620,6 +635,7 @@ $.on = function(el, events, handler) { var event, _i, _len, _ref; + _ref = events.split(' '); for (_i = 0, _len = _ref.length; _i < _len; _i++) { event = _ref[_i]; @@ -629,6 +645,7 @@ $.off = function(el, events, handler) { var event, _i, _len, _ref; + _ref = events.split(' '); for (_i = 0, _len = _ref.length; _i < _len; _i++) { event = _ref[_i]; @@ -650,6 +667,7 @@ $.debounce = function(wait, fn) { var args, exec, lastCall, that, timeout; + lastCall = 0; timeout = null; that = null; @@ -671,9 +689,11 @@ $.queueTask = (function() { var execTask, taskChannel, taskQueue; + taskQueue = []; execTask = function() { var args, func, task; + task = taskQueue.shift(); func = task[0]; args = Array.prototype.slice.call(task, 1); @@ -696,6 +716,7 @@ $.globalEval = function(code) { var script; + script = $.el('script', { textContent: code }); @@ -705,6 +726,7 @@ $.bytesToString = function(size) { var unit; + unit = 0; while (size >= 1024) { size /= 1024; @@ -720,6 +742,7 @@ $.item = function(key, val) { var item; + item = {}; item[key] = val; return item; @@ -730,6 +753,7 @@ $.sync = (function() { $.on(window, 'storage', function(e) { var cb; + if (cb = $.syncing[e.key]) { return cb(JSON.parse(e.newValue)); } @@ -741,6 +765,7 @@ $["delete"] = function(keys) { var key, _i, _len; + if (!(keys instanceof Array)) { keys = [keys]; } @@ -754,6 +779,7 @@ $.get = function(key, val, cb) { var items; + if (typeof cb === 'function') { items = $.item(key, val); } else { @@ -772,6 +798,7 @@ $.set = (function() { var set; + set = function(key, val) { key = g.NAMESPACE + key; val = JSON.stringify(val); @@ -782,6 +809,7 @@ }; return function(keys, val) { var key; + if (typeof keys === 'string') { set(keys, val); return; @@ -849,6 +877,7 @@ function Post(root, thread, board, that) { var capcode, date, email, flag, info, name, post, subject, tripcode, uniqueID; + this.thread = thread; this.board = board; if (that == null) { @@ -924,6 +953,7 @@ Post.prototype.parseComment = function() { var bq, i, node, nodes, text; + this.nodes.comment.normalize(); bq = this.nodes.comment.cloneNode(true); nodes = $$('.abbr, .capcodeReplies, .exif, b', bq); @@ -942,6 +972,7 @@ Post.prototype.parseQuotes = function() { var quotelink, _i, _len, _ref; + this.quotes = []; _ref = $$('.quotelink', this.nodes.comment); for (_i = 0, _len = _ref.length; _i < _len; _i++) { @@ -952,6 +983,7 @@ Post.prototype.parseQuote = function(quotelink) { var fullID, match; + if (!(match = quotelink.href.match(/boards\.4chan\.org\/([^\/]+)\/res\/\d+#p(\d+)$/))) { return; } @@ -967,6 +999,7 @@ Post.prototype.parseFile = function(that) { var alt, anchor, fileEl, fileInfo, size, thumb, unit; + if (!((fileEl = $('.file', this.nodes.post)) && (thumb = $('img[data-md5]', fileEl)))) { return; } @@ -997,6 +1030,7 @@ Post.prototype.kill = function(file, now) { var clone, quotelink, strong, _i, _j, _len, _len1, _ref, _ref1; + now || (now = new Date()); if (file) { if (this.file.isDead) { @@ -1045,6 +1079,7 @@ Post.prototype.resurrect = function() { var clone, quotelink, strong, _i, _j, _len, _len1, _ref, _ref1; + delete this.isDead; delete this.timeOfDeath; $.rmClass(this.nodes.root, 'deleted-post'); @@ -1078,6 +1113,7 @@ Post.prototype.rmClone = function(index) { var clone, _i, _len, _ref; + this.clones.splice(index, 1); _ref = this.clones.slice(index); for (_i = 0, _len = _ref.length; _i < _len; _i++) { @@ -1095,6 +1131,7 @@ function Clone(origin, context) { 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']; @@ -1182,6 +1219,7 @@ function DataBoard(key, sync, dontClean) { var init, _this = this; + this.key = key; this.onSync = __bind(this.onSync, this); this.data = Conf[key]; @@ -1205,6 +1243,7 @@ DataBoard.prototype["delete"] = function(_arg) { var boardID, postID, threadID; + boardID = _arg.boardID, threadID = _arg.threadID, postID = _arg.postID; if (postID) { delete this.data.boards[boardID][threadID][postID]; @@ -1225,6 +1264,7 @@ DataBoard.prototype.deleteIfEmpty = function(_arg) { var boardID, threadID; + boardID = _arg.boardID, threadID = _arg.threadID; if (threadID) { if (!Object.keys(this.data.boards[boardID][threadID]).length) { @@ -1240,6 +1280,7 @@ DataBoard.prototype.set = function(_arg) { var boardID, postID, threadID, val, _base, _base1, _base2; + boardID = _arg.boardID, threadID = _arg.threadID, postID = _arg.postID, val = _arg.val; if (postID !== void 0) { ((_base = ((_base1 = this.data.boards)[boardID] || (_base1[boardID] = {})))[threadID] || (_base[threadID] = {}))[postID] = val; @@ -1253,6 +1294,7 @@ DataBoard.prototype.get = function(_arg) { var ID, board, boardID, defaultValue, postID, thread, threadID, val, _i, _len; + boardID = _arg.boardID, threadID = _arg.threadID, postID = _arg.postID, defaultValue = _arg.defaultValue; if (board = this.data.boards[boardID]) { if (!threadID) { @@ -1276,6 +1318,7 @@ DataBoard.prototype.clean = function() { var boardID, now, val, _ref; + _ref = this.data.boards; for (boardID in _ref) { val = _ref[boardID]; @@ -1295,8 +1338,10 @@ DataBoard.prototype.ajaxClean = function(boardID) { var _this = this; + return $.cache("//api.4chan.org/" + boardID + "/threads.json", function(e) { var board, page, thread, threads, _i, _j, _len, _len1, _ref, _ref1; + if (e.target.status !== 200) { return; } @@ -1398,8 +1443,10 @@ }, toBlob: function() { var _base; + return (_base = HTMLCanvasElement.prototype).toBlob || (_base.toBlob = function(cb) { var data, i, l, ui8a, _i; + data = atob(this.toDataURL().slice(22)); l = data.length; ui8a = new Uint8Array(l); @@ -1437,6 +1484,7 @@ init: function() { var barFixedToggler, barPositionToggler, customNavToggler, editCustomNav, footerToggler, headerToggler, linkJustifyToggler, menuButton, shortcutToggler, _this = this; + this.menu = new UI.Menu('header'); menuButton = $.el('span', { className: 'menu-button', @@ -1537,6 +1585,7 @@ }); $.ready(function() { var a, cs; + _this.footer = $.id('boardNavDesktopFoot'); if (a = $("a[href*='/" + g.BOARD + "/']", $.id('boardNavDesktopFoot'))) { a.className = 'current'; @@ -1571,6 +1620,7 @@ }), setBoardList: function() { var a, boardList, btn, fourchannav, fullBoardList; + fourchannav = $.id('boardNavDesktop'); if (a = $("a[href*='/" + g.BOARD + "/']", fourchannav)) { a.className = 'current'; @@ -1592,6 +1642,7 @@ }, generateBoardList: function(text) { var as, list, nodes; + list = $('#custom-board-list', Header.bar); $.rmAll(list); if (!text) { @@ -1600,6 +1651,7 @@ as = $$('#full-board-list a[title]', Header.bar); nodes = text.match(/[\w@]+((-(all|title|replace|full|index|catalog|url:"[^"]+[^"]"|text:"[^"]+")|\,"[^"]+[^"]"))*|[^\w@]+/g).map(function(t) { var a, board, m, _i, _len; + if (/^[^\w@]/.test(t)) { return $.tn(t); } @@ -1650,6 +1702,7 @@ }, toggleBoardList: function() { var bar, custom, full, showBoardList; + bar = Header.bar; custom = $('#custom-board-list', bar); full = $('#full-board-list', bar); @@ -1685,6 +1738,7 @@ }, toggleLinkJustify: function() { var centered; + $.event('CloseMenu'); centered = this.nodeName === 'INPUT' ? this.checked : void 0; Header.setLinkJustify(centered); @@ -1728,6 +1782,7 @@ }, toggleBarVisibility: function() { var hide, message; + hide = this.nodeName === 'INPUT' ? this.checked : !$.hasClass(Header.bar, 'autohide'); this.checked = hide; $.set('Header auto-hide', Conf['Header auto-hide'] = hide); @@ -1741,6 +1796,7 @@ }, toggleFooterVisibility: function() { var hide, message; + $.event('CloseMenu'); hide = this.nodeName === 'INPUT' ? this.checked : !!Header.footer.hidden; Header.setFooterVisibility(hide); @@ -1750,6 +1806,7 @@ }, setCustomNav: function(show) { var btn, cust, full, _ref; + Header.customNavToggler.checked = show; cust = $('#custom-board-list', Header.bar); full = $('#full-board-list', Header.bar); @@ -1762,12 +1819,14 @@ }, editCustomNav: function() { var settings; + Settings.open('Advanced'); settings = $.id('fourchanx-settings'); return $('input[name=boardnav]', settings).focus(); }, hashScroll: function() { var hash, post; + if (!((hash = this.location.hash.slice(1)) && (post = $.id(hash)))) { return; } @@ -1778,6 +1837,7 @@ }, scrollToPost: function(post) { var headRect, top; + top = post.getBoundingClientRect().top; if (Conf['Fixed Header'] && !Conf['Bottom Header']) { headRect = Header.bar.getBoundingClientRect(); @@ -1787,6 +1847,7 @@ }, addShortcut: function(el) { var shortcut; + shortcut = $.el('span', { className: 'shortcut brackets-wrap' }); @@ -1798,6 +1859,7 @@ }, createNotification: function(e) { var cb, content, lifetime, notif, type, _ref; + _ref = e.detail, type = _ref.type, content = _ref.content, lifetime = _ref.lifetime, cb = _ref.cb; notif = new Notice(type, content, lifetime); if (cb) { @@ -1807,6 +1869,7 @@ areNotificationsEnabled: false, enableDesktopNotifications: function() { var authorize, disable, el, notice, _ref; + if (!(window.Notification && Conf['Desktop Notifications'])) { return; } @@ -1842,6 +1905,7 @@ spoilerRange: {}, shortFilename: function(filename, isReply) { var threshold; + threshold = isReply ? 30 : 40; if (filename.length - 4 > threshold) { return "" + filename.slice(0, threshold - 5) + "(...)." + filename.slice(-3); @@ -1851,6 +1915,7 @@ }, postFromObject: function(data, boardID) { var o; + o = { postID: data.no, threadID: data.resto || data.no, @@ -1895,6 +1960,7 @@ */ var a, boardID, capcode, capcodeClass, capcodeReplies, capcodeStart, closed, comment, container, date, dateUTC, email, emailEnd, emailStart, ext, file, fileDims, fileHTML, fileInfo, fileSize, fileThumb, filename, flag, flagCode, flagName, href, imgSrc, isClosed, isOP, isSticky, name, postID, quote, shortFilename, spoilerRange, staticPath, sticky, subject, threadID, tripcode, uniqueID, userID, _i, _len, _ref; + postID = o.postID, threadID = o.threadID, boardID = o.boardID, name = o.name, capcode = o.capcode, tripcode = o.tripcode, uniqueID = o.uniqueID, email = o.email, subject = o.subject, flagCode = o.flagCode, flagName = o.flagName, date = o.date, dateUTC = o.dateUTC, isSticky = o.isSticky, isClosed = o.isClosed, comment = o.comment, capcodeReplies = o.capcodeReplies, file = o.file; isOP = postID === threadID; staticPath = '//static.4chan.org/image/'; @@ -1993,6 +2059,7 @@ }, capcodeReplies: function(_arg) { var array, boardID, bq, capcodeReplies, capcodeType, generateCapcodeReplies, html, root, threadID; + boardID = _arg.boardID, threadID = _arg.threadID, bq = _arg.bq, root = _arg.root, capcodeReplies = _arg.capcodeReplies; if (!capcodeReplies) { return; @@ -2029,6 +2096,7 @@ Get = { threadExcerpt: function(thread) { var OP, excerpt, _ref; + OP = thread.OP; excerpt = ((_ref = OP.info.subject) != null ? _ref.trim() : void 0) || OP.info.comment.replace(/\n+/g, ' // ') || Conf['Anonymize'] && 'Anonymous' || $('.nameBlock', OP.nodes.info).textContent.trim(); if (excerpt.length > 70) { @@ -2044,6 +2112,7 @@ }, postFromRoot: function(root) { var boardID, index, link, post, postID; + link = $('a[title="Highlight this post"]', root); boardID = link.pathname.split('/')[1]; postID = link.hash.slice(2); @@ -2063,6 +2132,7 @@ }, postDataFromLink: function(link) { var boardID, path, postID, threadID, _ref; + if (link.hostname === 'boards.4chan.org') { path = link.pathname.split('/'); boardID = path[1]; @@ -2080,6 +2150,7 @@ }, allQuotelinksLinkingTo: function(post) { var ID, quote, quotedPost, quotelinks, quoterPost, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3; + quotelinks = []; _ref = g.posts; for (ID in _ref) { @@ -2108,12 +2179,14 @@ } return quotelinks.filter(function(quotelink) { var boardID, postID, _ref4; + _ref4 = Get.postDataFromLink(quotelink), boardID = _ref4.boardID, postID = _ref4.postID; return boardID === post.board.ID && postID === post.ID; }); }, postClone: function(boardID, threadID, postID, root, context) { var post, url; + if (post = g.posts["" + boardID + "." + postID]) { Get.insert(post, root, context); return; @@ -2136,6 +2209,7 @@ }, insert: function(post, root, context) { var clone, nodes; + if (!root.parentNode) { return; } @@ -2149,6 +2223,7 @@ }, fetchedPost: function(req, boardID, threadID, postID, root, context) { var board, post, posts, status, thread, url, _i, _len; + if (post = g.posts["" + boardID + "." + postID]) { Get.insert(post, root, context); return; @@ -2202,6 +2277,7 @@ }, archivedPost: function(req, boardID, postID, root, context) { var board, bq, comment, data, o, post, thread, threadID, _ref; + if (post = g.posts["" + boardID + "." + postID]) { Get.insert(post, root, context); return; @@ -2298,8 +2374,10 @@ UI = (function() { var Menu, dialog, drag, dragend, dragstart, hover, hoverend, hoverstart, touchend, touchmove; + dialog = function(id, position, html) { var child, el, move, _i, _len, _ref; + el = $.el('div', { className: 'dialog', innerHTML: html, @@ -2341,6 +2419,7 @@ Menu.prototype.makeMenu = function() { var menu; + menu = $.el('div', { className: 'dialog', id: 'menu', @@ -2355,6 +2434,7 @@ Menu.prototype.toggle = function(e, button, data) { var previousButton; + e.preventDefault(); e.stopPropagation(); if (currentMenu) { @@ -2372,6 +2452,7 @@ Menu.prototype.open = function(button, data) { var bLeft, bRect, bTop, bottom, cHeight, cWidth, entry, left, mRect, menu, right, style, top, _i, _len, _ref, _ref1, _ref2; + menu = this.makeMenu(); currentMenu = menu; lastToggledButton = button; @@ -2410,6 +2491,7 @@ Menu.prototype.insertEntry = function(entry, parent, data) { var subEntry, submenu, _i, _len, _ref; + if (typeof entry.open === 'function') { if (!entry.open(data)) { return; @@ -2443,6 +2525,7 @@ Menu.prototype.findNextEntry = function(entry, direction) { var entries; + entries = __slice.call(entry.parentNode.children); entries.sort(function(first, second) { return +(first.style.order || first.style.webkitOrder) - +(second.style.order || second.style.webkitOrder); @@ -2452,6 +2535,7 @@ Menu.prototype.keybinds = function(e) { var entry, next, nextPrev, subEntry, submenu; + entry = $('.focused', currentMenu); while (subEntry = $('.focused', entry)) { entry = subEntry; @@ -2497,6 +2581,7 @@ Menu.prototype.focus = function(entry) { var bottom, cHeight, cWidth, eRect, focused, left, right, sRect, style, submenu, top, _i, _len, _ref, _ref1, _ref2; + while (focused = $.x('parent::*/child::*[contains(@class,"focused")]', entry)) { $.rmClass(focused, 'focused'); } @@ -2524,6 +2609,7 @@ Menu.prototype.addEntry = function(e) { var entry; + entry = e.detail; if (entry.type !== this.type) { return; @@ -2534,6 +2620,7 @@ Menu.prototype.parseEntry = function(entry) { var el, style, subEntries, subEntry, _i, _len; + el = entry.el, subEntries = entry.subEntries; $.addClass(el, 'entry'); $.on(el, 'focus mouseover', (function(e) { @@ -2557,6 +2644,7 @@ })(); dragstart = function(e) { var el, isTouching, o, rect, screenHeight, screenWidth, _ref; + if (e.type === 'mousedown' && e.button !== 0) { return; } @@ -2595,6 +2683,7 @@ }; touchmove = function(e) { var touch, _i, _len, _ref; + _ref = e.changedTouches; for (_i = 0, _len = _ref.length; _i < _len; _i++) { touch = _ref[_i]; @@ -2606,6 +2695,7 @@ }; drag = function(e) { var bottom, clientX, clientY, left, right, style, top; + clientX = e.clientX, clientY = e.clientY; left = clientX - this.dx; left = left < 10 ? 0 : this.width - left < 10 ? null : left / this.screenWidth * 100 + '%'; @@ -2621,6 +2711,7 @@ }; touchend = function(e) { var touch, _i, _len, _ref; + _ref = e.changedTouches; for (_i = 0, _len = _ref.length; _i < _len; _i++) { touch = _ref[_i]; @@ -2642,6 +2733,7 @@ }; hoverstart = function(_arg) { var asapTest, cb, el, endEvents, latestEvent, o, root; + root = _arg.root, el = _arg.el, latestEvent = _arg.latestEvent, endEvents = _arg.endEvents, asapTest = _arg.asapTest, cb = _arg.cb; o = { root: root, @@ -2676,6 +2768,7 @@ }; hover = function(e) { var clientX, clientY, height, left, right, style, top, _ref; + this.latestEvent = e; height = this.el.offsetHeight; clientX = e.clientX, clientY = e.clientY; @@ -2719,6 +2812,7 @@ }, node: function() { var email, name, tripcode, _ref; + if (this.info.capcode || this.isClone) { return; } @@ -2745,6 +2839,7 @@ filters: {}, init: function() { var boards, err, filter, hl, key, op, regexp, stub, top, _i, _len, _ref, _ref1, _ref2, _ref3, _ref4; + if (g.VIEW === 'catalog' || !Conf['Filter']) { return; } @@ -2781,6 +2876,7 @@ op = ((_ref2 = filter.match(/[^t]op:(yes|no|only)/)) != null ? _ref2[1] : void 0) || 'yes'; stub = (function() { var _ref3; + switch ((_ref3 = filter.match(/stub:(yes|no)/)) != null ? _ref3[1] : void 0) { case 'yes': return true; @@ -2811,6 +2907,7 @@ }, createFilter: function(regexp, op, stub, hl, top) { var settings, test; + test = typeof regexp === 'string' ? function(value) { return regexp === value; } : function(value) { @@ -2834,6 +2931,7 @@ }, node: function() { var filter, firstThread, key, result, thisThread, value, _i, _len, _ref; + if (this.isClone) { return; } @@ -2945,6 +3043,7 @@ menu: { init: function() { var div, entry, type, _i, _len, _ref; + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Filter']) { return; } @@ -2970,6 +3069,7 @@ }, createSubEntry: function(text, type) { var el; + el = $.el('a', { href: 'javascript:;', textContent: text @@ -2980,6 +3080,7 @@ el: el, open: function(post) { var value; + value = Filter[type](post); return value !== false; } @@ -2987,6 +3088,7 @@ }, makeFilter: function() { var re, type, value; + type = this.dataset.type; value = Filter[type](Filter.menu.post); re = ['uniqueID', 'MD5'].contains(type) ? value : value.replace(/\/|\\|\^|\$|\n|\.|\(|\)|\{|\}|\[|\]|\?|\*|\+|\|/g, function(c) { @@ -3001,6 +3103,7 @@ re = ['uniqueID', 'MD5'].contains(type) ? "/" + re + "/" : "/^" + re + "$/"; return $.get(type, Conf[type], function(item) { var save, section, select, ta, tl; + save = item[type]; save = save ? "" + save + "\n" + re : re; $.set(type, save); @@ -3034,6 +3137,7 @@ }, node: function() { var data; + if (!this.isReply || this.isClone) { return; } @@ -3057,6 +3161,7 @@ menu: { init: function() { var apply, div, hideStubLink, makeStub, replies, thisPost; + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Reply Hiding Link']) { return; } @@ -3127,6 +3232,7 @@ order: 20, open: function(post) { var data; + if (!post.isReply || post.isClone || !post.isHidden) { return false; } @@ -3158,6 +3264,7 @@ order: 15, open: function(post) { var data; + if (!post.isReply || post.isClone || !post.isHidden) { return false; } @@ -3174,6 +3281,7 @@ }, hide: function() { var makeStub, parent, post, replies, thisPost; + parent = this.parentNode; thisPost = $('input[name=thisPost]', parent).checked; replies = $('input[name=replies]', parent).checked; @@ -3192,6 +3300,7 @@ }, show: function() { var data, parent, post, replies, thisPost; + parent = this.parentNode; thisPost = $('input[name=thisPost]', parent).checked; replies = $('input[name=replies]', parent).checked; @@ -3215,6 +3324,7 @@ }, hideStub: function() { var post; + post = PostHiding.menu.post; post.nodes.root.hidden = true; $.event('CloseMenu'); @@ -3222,6 +3332,7 @@ }, makeButton: function(post, type) { var a; + a = $.el('a', { className: "" + type + "-reply-button", innerHTML: " " + (type === 'hide' ? '-' : '+') + " ", @@ -3232,6 +3343,7 @@ }, saveHiddenState: function(post, isHiding, thisPost, makeStub, hideRecursively) { var data; + data = { boardID: post.board.ID, threadID: post.thread.ID, @@ -3250,12 +3362,14 @@ }, toggle: function() { var post; + post = Get.postFromNode(this); PostHiding[(post.isHidden ? 'show' : 'hide')](post); return PostHiding.saveHiddenState(post, post.isHidden); }, hide: function(post, makeStub, hideRecursively) { var a, button, postInfo, quotelink, _i, _len, _ref; + if (makeStub == null) { makeStub = Conf['Stubs']; } @@ -3290,6 +3404,7 @@ }, show: function(post, showRecursively) { var quotelink, _i, _len, _ref; + if (showRecursively == null) { showRecursively = Conf['Recursive Hiding']; } @@ -3325,6 +3440,7 @@ }, node: function() { var i, obj, quote, recursive, _i, _j, _len, _len1, _ref, _ref1; + if (this.isClone) { return; } @@ -3342,6 +3458,7 @@ }, add: function() { var args, obj, post, recursive, _base, _name; + recursive = arguments[0], post = arguments[1], args = 3 <= arguments.length ? __slice.call(arguments, 2) : []; obj = (_base = Recursive.recursives)[_name = post.fullID] || (_base[_name] = { recursives: [], @@ -3352,6 +3469,7 @@ }, rm: function(recursive, post) { var i, obj, rec, _i, _len, _ref; + if (!(obj = Recursive.recursives[post.fullID])) { return; } @@ -3366,6 +3484,7 @@ }, apply: function() { var ID, args, fullID, post, recursive, _ref; + recursive = arguments[0], post = arguments[1], args = 3 <= arguments.length ? __slice.call(arguments, 2) : []; fullID = post.fullID; _ref = g.posts; @@ -3392,6 +3511,7 @@ }, node: function() { var data; + if (data = ThreadHiding.db.get({ boardID: this.board.ID, threadID: this.ID @@ -3405,6 +3525,7 @@ }, syncCatalog: function() { var hiddenThreads, hiddenThreadsOnCatalog, threadID; + hiddenThreads = ThreadHiding.db.get({ boardID: g.BOARD.ID, defaultValue: {} @@ -3431,6 +3552,7 @@ cleanCatalog: function(hiddenThreadsOnCatalog) { return $.cache("//api.4chan.org/" + g.BOARD + "/threads.json", function() { var page, thread, threads, _i, _j, _len, _len1, _ref, _ref1; + if (this.status !== 200) { return; } @@ -3456,6 +3578,7 @@ menu: { init: function() { var apply, div, hideStubLink, makeStub; + if (g.VIEW !== 'index' || !Conf['Menu'] || !Conf['Thread Hiding Link']) { return; } @@ -3477,6 +3600,7 @@ order: 20, open: function(_arg) { var isReply, thread; + thread = _arg.thread, isReply = _arg.isReply; if (isReply || thread.isHidden) { return false; @@ -3504,6 +3628,7 @@ order: 20, open: function(_arg) { var isReply, thread; + thread = _arg.thread, isReply = _arg.isReply; if (isReply || !thread.isHidden) { return false; @@ -3523,6 +3648,7 @@ order: 15, open: function(_arg) { var isReply, thread; + thread = _arg.thread, isReply = _arg.isReply; if (isReply || !thread.isHidden) { return false; @@ -3533,6 +3659,7 @@ }, hide: function() { var makeStub, thread; + makeStub = $('input', this.parentNode).checked; thread = ThreadHiding.menu.thread; ThreadHiding.hide(thread, makeStub); @@ -3541,6 +3668,7 @@ }, show: function() { var thread; + thread = ThreadHiding.menu.thread; ThreadHiding.show(thread); ThreadHiding.saveHiddenState(thread); @@ -3548,6 +3676,7 @@ }, hideStub: function() { var thread; + thread = ThreadHiding.menu.thread; ThreadHiding.hide(thread, false); $.event('CloseMenu'); @@ -3555,6 +3684,7 @@ }, makeButton: function(thread, type) { var a; + a = $.el('a', { className: "" + type + "-thread-button", innerHTML: " " + (type === 'hide' ? '-' : '+') + " ", @@ -3566,6 +3696,7 @@ }, saveHiddenState: function(thread, makeStub) { var hiddenThreadsOnCatalog; + hiddenThreadsOnCatalog = JSON.parse(localStorage.getItem("4chan-hide-t-" + g.BOARD)) || {}; if (thread.isHidden) { ThreadHiding.db.set({ @@ -3598,6 +3729,7 @@ }, hide: function(thread, makeStub) { var OP, a, numReplies, opInfo, span, threadRoot; + if (makeStub == null) { makeStub = Conf['Stubs']; } @@ -3621,6 +3753,7 @@ }, show: function(thread) { var threadRoot; + if (thread.stub) { $.rm(thread.stub); delete thread.stub; @@ -3633,6 +3766,7 @@ QuoteBacklink = { init: function() { var format; + if (g.VIEW === 'catalog' || !Conf['Quote Backlinks']) { return; } @@ -3650,6 +3784,7 @@ }, firstNode: function() { var a, clone, container, containers, frag, link, post, quote, _i, _j, _k, _len, _len1, _len2, _ref, _ref1; + if (this.isClone || !this.quotes.length) { return; } @@ -3687,6 +3822,7 @@ }, secondNode: function() { var container; + if (this.isClone && (this.origin.isReply || Conf['OP Backlinks'])) { this.nodes.backlinkContainer = $('.container', this.nodes.info); return; @@ -3700,6 +3836,7 @@ }, getContainer: function(id) { var _base; + return (_base = this.containers)[id] || (_base[id] = $.el('span', { className: 'container' })); @@ -3722,6 +3859,7 @@ }, node: function() { var board, boardID, quotelink, thread, threadID, _i, _len, _ref, _ref1, _ref2; + if (this.isClone && this.thread === this.context.thread) { return; } @@ -3751,6 +3889,7 @@ if (Conf['Quote Hash Navigation']) { this.node = function() { var link, _i, _len, _ref; + _ref = this.nodes.quotelinks.concat(__slice.call(this.nodes.backlinks)); for (_i = 0, _len = _ref.length; _i < _len; _i++) { link = _ref[_i]; @@ -3763,6 +3902,7 @@ } else { this.node = function() { var link, _i, _len, _ref; + _ref = this.nodes.quotelinks.concat(__slice.call(this.nodes.backlinks)); for (_i = 0, _len = _ref.length; _i < _len; _i++) { link = _ref[_i]; @@ -3789,6 +3929,7 @@ }, toggle: function(e) { var boardID, context, postID, threadID, _ref; + if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) { return; } @@ -3814,6 +3955,7 @@ }, add: function(quotelink, boardID, threadID, postID, context) { var inline, isBacklink, post, qroot, root; + isBacklink = $.hasClass(quotelink, 'backlink'); inline = $.el('div', { id: "i" + postID, @@ -3838,6 +3980,7 @@ }, rm: function(quotelink, boardID, threadID, postID, context) { var el, inlined, isBacklink, post, qroot, root, _ref; + isBacklink = $.hasClass(quotelink, 'backlink'); root = QuoteInline.findRoot(quotelink, isBacklink); root = $.x("following-sibling::div[@id='i" + postID + "'][1]", root); @@ -3879,6 +4022,7 @@ }, node: function() { var boardID, fullID, i, postID, quotelink, quotelinks, quotes, _ref; + if (this.isClone && this.thread === this.context.thread) { return; } @@ -3921,6 +4065,7 @@ }, node: function() { var link, _i, _len, _ref; + _ref = this.nodes.quotelinks.concat(__slice.call(this.nodes.backlinks)); for (_i = 0, _len = _ref.length; _i < _len; _i++) { link = _ref[_i]; @@ -3929,6 +4074,7 @@ }, mouseover: function(e) { var boardID, clone, origin, post, postID, posts, qp, quote, quoterID, threadID, _i, _j, _len, _len1, _ref, _ref1; + if ($.hasClass(this, 'inlined')) { return; } @@ -3972,6 +4118,7 @@ }, mouseout: function() { var clone, post, root, _i, _len, _ref; + if (!(root = this.el.firstElementChild)) { return; } @@ -4001,6 +4148,7 @@ }, node: function() { var boardID, postID, quotelink, _i, _len, _ref, _ref1, _ref2; + if (this.isClone) { return; } @@ -4023,6 +4171,7 @@ QuoteThreading = { init: function() { var input; + if (!(Conf['Quote Threading'] && g.VIEW === 'thread')) { return; } @@ -4045,6 +4194,7 @@ }, setup: function() { var ID, post, posts; + $.off(d, '4chanXInitFinished', QuoteThreading.setup); posts = g.posts; for (ID in posts) { @@ -4057,6 +4207,7 @@ }, node: function() { var ID, fullID, keys, len, post, posts, qid, quote, quotes, uniq, _i, _len; + if (this.isClone || !QuoteThreading.enabled || this.thread.OP === this) { return; } @@ -4086,6 +4237,7 @@ }, nodeinsert: function() { var bottom, height, qpost, qroot, threadContainer, top, _ref; + qpost = g.posts[this.threaded]; delete this.threaded; delete this.cb; @@ -4114,6 +4266,7 @@ }, toggle: function() { var container, containers, node, post, replies, reply, thread, _i, _j, _k, _len, _len1, _len2, _ref; + thread = $('.thread'); replies = $$('.thread > .replyContainer, .threadContainer > .replyContainer', thread); QuoteThreading.enabled = this.checked; @@ -4130,6 +4283,7 @@ } else { replies.sort(function(a, b) { var aID, bID; + aID = Number(a.id.slice(2)); bID = Number(b.id.slice(2)); return aID - bID; @@ -4150,6 +4304,7 @@ }, kb: function() { var control; + control = $.id('threadingControl'); return control.click(); } @@ -4176,6 +4331,7 @@ }, node: function() { var quotelink, _i, _len, _ref; + if (this.isClone) { return; } @@ -4199,6 +4355,7 @@ cb: { seek: function(type) { var highlight, post, posts, result, str; + if (!(Conf['Mark Quotes of You'] && Conf['Quick Reply'])) { return; } @@ -4254,6 +4411,7 @@ }, node: function() { var deadlink, _i, _len, _ref; + _ref = $$('.deadlink', this.nodes.comment); for (_i = 0, _len = _ref.length; _i < _len; _i++) { deadlink = _ref[_i]; @@ -4268,6 +4426,7 @@ }, parseDeadlink: function(deadlink) { var a, boardID, m, post, postID, quote, quoteID, redirect, _ref; + if ($.hasClass(deadlink.parentNode, 'prettyprint')) { Quotify.fixDeadlink(deadlink); return; @@ -4360,6 +4519,7 @@ }, node: function() { var data, el, end, endNode, i, index, items, length, link, links, node, result, saved, snapshot, space, test, word, _i, _len, _ref; + if (this.isClone) { if (Conf['Embedding']) { i = 0; @@ -4436,6 +4596,7 @@ }, makeRange: function(startNode, endNode, startOffset, endOffset) { var range; + range = document.createRange(); range.setStart(startNode, startOffset); range.setEnd(endNode, endOffset); @@ -4443,6 +4604,7 @@ }, makeLink: function(range) { var a, char, i, text; + text = range.toString(); i = 0; while (/[(\[{<>]/.test(text.charAt(i))) { @@ -4488,6 +4650,7 @@ }, services: function(link) { var href, key, match, type, _ref; + href = link.href; _ref = Linkify.types; for (key in _ref) { @@ -4500,6 +4663,7 @@ }, embed: function(data) { var embed, href, key, link, name, options, uid, value, _ref; + key = data[0], uid = data[1], options = data[2], link = data[3]; href = link.href; embed = $.el('a', { @@ -4528,6 +4692,7 @@ }, title: function(data) { var embed, err, key, link, options, service, title, titles, uid; + key = data[0], uid = data[1], options = data[2], link = data[3], embed = data[4]; if (!(service = Linkify.types[key].title)) { return; @@ -4564,18 +4729,21 @@ cb: { toggle: function() { var string, _ref; + _ref = $.hasClass(this, "embedded") ? ['unembed', '(embed)'] : ['embed', '(unembed)'], string = _ref[0], this.textContent = _ref[1]; $.replace(this.previousElementSibling, Linkify.cb[string](this)); return $.toggleClass(this, 'embedded'); }, embed: function(a) { var el, style, type; + el = (type = Linkify.types[a.dataset.key]).el(a); el.style.cssText = (style = type.style) ? style : "border: 0; width: 640px; height: 390px"; return el; }, unembed: function(a) { var el; + el = $.el('a', { rel: 'nofollow noreferrer', target: 'blank', @@ -4588,6 +4756,7 @@ }, title: function(response, data) { var embed, key, link, options, service, text, uid; + key = data[0], uid = data[1], options = data[2], link = data[3], embed = data[4]; service = Linkify.types[key].title; switch (response.status) { @@ -4627,6 +4796,7 @@ regExp: /.*(?:gist.github.com.*\/)([^\/][^\/]*)$/, el: function(a) { var div; + return div = $.el('iframe', { src: "http://www.purplegene.com/script?url=https://gist.github.com/" + a.dataset.uid + ".js" }); @@ -4637,6 +4807,7 @@ }, text: function(_arg) { var file, files; + files = _arg.files; for (file in files) { if (files.hasOwnProperty(file)) { @@ -4684,6 +4855,7 @@ regExp: /.*(?:pastebin.com\/(?!u\/))([^#\&\?]*).*/, el: function(a) { var div; + return div = $.el('iframe', { src: "http://pastebin.com/embed_iframe.php?i=" + a.dataset.uid }); @@ -4694,6 +4866,7 @@ style: 'height: auto; width: 500px; display: inline-block;', el: function(a) { var div; + div = $.el('div', { className: "soundcloud", name: "soundcloud" @@ -4719,6 +4892,7 @@ style: "border: none; width: 640px; height: 360px;", el: function(a) { var channel, chapter, result, _; + if (result = /(\w+)\/(?:[a-z]\/)?(\d+)/i.exec(a.dataset.uid)) { _ = result[0], channel = result[1], chapter = result[2]; return $.el('object', { @@ -4790,6 +4964,7 @@ QR = { init: function() { var sc; + if (!Conf['Quick Reply']) { return; } @@ -4836,6 +5011,7 @@ }, initReady: function() { var link; + QR.postingIsEnabled = !!$.id('postForm'); if (!QR.postingIsEnabled) { return; @@ -4855,11 +5031,13 @@ $.before($.id('postForm'), link); $.on(d, 'QRGetSelectedPost', function(_arg) { var cb; + cb = _arg.detail; return cb(QR.selected); }); $.on(d, 'QRAddPreSubmitHook', function(_arg) { var cb; + cb = _arg.detail; return QR.preSubmitHooks.push(cb); }); @@ -4888,6 +5066,7 @@ }, open: function() { var err; + if (QR.nodes) { QR.nodes.el.hidden = false; QR.unhide(); @@ -4906,6 +5085,7 @@ }, close: function() { var post, _i, _len, _ref; + if (QR.req) { QR.abort(); return; @@ -4960,6 +5140,7 @@ }, error: function(err) { var el; + QR.open(); if (typeof err === 'string') { el = $.tn(err); @@ -4986,6 +5167,7 @@ }, notify: function(el) { var notice, notif; + notice = new Notice('warning', el); QR.notifications.push(notice); if (!Header.areNotificationsEnabled) { @@ -5002,6 +5184,7 @@ notifications: [], cleanNotifications: function() { var notification, _i, _len, _ref; + _ref = QR.notifications; for (_i = 0, _len = _ref.length; _i < _len; _i++) { notification = _ref[_i]; @@ -5011,6 +5194,7 @@ }, status: function() { var disabled, status, thread, value; + if (!QR.nodes) { return; } @@ -5032,6 +5216,7 @@ QR.persona.getPassword(); return $.get('QR.personas', Conf['QR.personas'], function(_arg) { var arr, item, personas, type, types, _i, _len, _ref; + personas = _arg['QR.personas']; types = { name: [], @@ -5051,6 +5236,7 @@ }, parseItem: function(item, types) { var boards, match, type, val, _ref, _ref1; + if (item[0] === '#') { return; } @@ -5079,6 +5265,7 @@ }, loadPersonas: function(type, arr) { var list, val, _i, _len; + list = $("#list-" + type, QR.nodes.el); for (_i = 0, _len = arr.length; _i < _len; _i++) { val = arr[_i]; @@ -5091,6 +5278,7 @@ }, getPassword: function() { var input, m; + if (!QR.persona.pwd) { QR.persona.pwd = (m = d.cookie.match(/4chan_pass=([^;]+)/)) ? decodeURIComponent(m[1]) : (input = $.id('postPassword')) ? input.value : $.id('delPassword').value; } @@ -5099,6 +5287,7 @@ get: function(cb) { return $.get('QR.persona', {}, function(_arg) { var persona; + persona = _arg['QR.persona']; return cb(persona); }); @@ -5106,6 +5295,7 @@ set: function(post) { return $.get('QR.persona', {}, function(_arg) { var persona; + persona = _arg['QR.persona']; persona = { name: post.name, @@ -5119,6 +5309,7 @@ cooldown: { init: function() { var board; + if (!Conf['Cooldown']) { return; } @@ -5160,6 +5351,7 @@ }, sync: function(cooldowns) { var id; + for (id in cooldowns) { QR.cooldown.cooldowns[id] = cooldowns[id]; } @@ -5167,6 +5359,7 @@ }, set: function(data) { var cooldown, delay, hasFile, isReply, isSage, post, req, start, type, upSpd; + if (!Conf['Cooldown']) { return; } @@ -5206,6 +5399,7 @@ }, count: function() { var cooldown, cooldowns, elapsed, hasFile, isReply, isSage, now, post, seconds, start, type, types, upSpd, upSpdAccuracy, update, _ref; + if (!Object.keys(QR.cooldown.cooldowns).length) { $["delete"]("" + g.BOARD + ".cooldown"); delete QR.cooldown.isCounting; @@ -5259,6 +5453,7 @@ }, quote: function(e) { var caretPos, com, index, post, range, s, sel, text, thread, _ref; + if (e != null) { e.preventDefault(); } @@ -5296,6 +5491,7 @@ }, characterCount: function() { var count, counter; + counter = QR.nodes.charCount; count = QR.nodes.com.textLength; counter.textContent = count; @@ -5304,6 +5500,7 @@ }, drag: function(e) { var toggle; + toggle = e.type === 'dragstart' ? $.off : $.on; toggle(d, 'dragover', QR.dragOver); return toggle(d, 'drop', QR.dropFile); @@ -5323,6 +5520,7 @@ }, paste: function(e) { var blob, files, item, _i, _len, _ref; + files = []; _ref = e.clipboardData.items; for (_i = 0, _len = _ref.length; _i < _len; _i++) { @@ -5346,6 +5544,7 @@ }, handleFiles: function(files) { var file, isSingle, max, _i, _len; + if (this !== QR) { files = __slice.call(this.files); this.value = null; @@ -5366,6 +5565,7 @@ }, handleFile: function(file, isSingle, max) { var post; + if (file.size > max) { QR.error("" + file.name + ": File too large (file: " + ($.bytesToString(file.size)) + ", max: " + ($.bytesToString(max)) + ")."); return; @@ -5400,9 +5600,6 @@ if (e.ctrlKey && e.type === 'click') { $.addClass(QR.nodes.filename, 'edit'); QR.nodes.filename.focus(); - if (e.keyCode && e.keyCode === 13) { - return; - } return $.on(QR.nodes.filename, 'blur', function() { return $.rmClass(QR.nodes.filename, 'edit'); }); @@ -5419,6 +5616,7 @@ this.select = __bind(this.select, this); var el, elm, event, prev, _i, _j, _len, _len1, _ref, _ref1, _this = this; + el = $.el('a', { className: 'qr-preview', draggable: true, @@ -5478,6 +5676,7 @@ _Class.prototype.rm = function() { var index; + this["delete"](); index = QR.posts.indexOf(this); if (QR.posts.length === 1) { @@ -5497,6 +5696,7 @@ _Class.prototype.lock = function(lock) { var name, _i, _len, _ref; + if (lock == null) { lock = true; } @@ -5521,6 +5721,7 @@ _Class.prototype.select = function() { var rectEl, rectList; + if (QR.selected) { QR.selected.nodes.el.id = null; QR.selected.forceSave(); @@ -5537,6 +5738,7 @@ _Class.prototype.load = function() { var name, _i, _len, _ref; + _ref = ['thread', 'name', 'email', 'sub', 'com', 'filename']; for (_i = 0, _len = _ref.length; _i < _len; _i++) { name = _ref[_i]; @@ -5548,6 +5750,7 @@ _Class.prototype.save = function(input) { var name, _ref; + if (input.type === 'checkbox') { this.spoiler = input.checked; return; @@ -5578,6 +5781,7 @@ _Class.prototype.forceSave = function() { var name, _i, _len, _ref; + if (this !== QR.selected) { return; } @@ -5607,9 +5811,11 @@ _Class.prototype.setThumbnail = function() { var fileURL, img, _this = this; + img = $.el('img'); img.onload = function() { var cv, height, s, width; + s = 90 * 2; if (_this.file.type === 'image/gif') { s *= 3; @@ -5660,6 +5866,7 @@ _Class.prototype.updateFilename = function() { var long; + long = "" + this.filename + " (" + this.filesize + ")\nCtrl+click to edit filename. Shift+click to clear."; this.nodes.el.title = long; if (this !== QR.selected) { @@ -5682,9 +5889,11 @@ _Class.prototype.pasteText = function(file) { var reader, _this = this; + reader = new FileReader(); reader.onload = function(e) { var text; + text = e.target.result; if (_this.com) { _this.com += "\n" + text; @@ -5723,6 +5932,7 @@ _Class.prototype.drop = function() { var el, index, newIndex, oldIndex, post; + $.rmClass(this, 'over'); if (!this.draggable) { return; @@ -5757,6 +5967,7 @@ ready: function() { var imgContainer, input, setLifetime, _this = this; + setLifetime = function(e) { return _this.lifetime = e.detail; }; @@ -5793,6 +6004,7 @@ }); $.get('captchas', [], function(_arg) { var captchas; + captchas = _arg.captchas; return _this.sync(captchas); }); @@ -5809,6 +6021,7 @@ }, getOne: function() { var captcha, challenge, response; + this.clear(); if (captcha = this.captchas.shift()) { challenge = captcha.challenge, response = captcha.response; @@ -5833,6 +6046,7 @@ }, save: function() { var response; + if (!(response = this.nodes.input.value.trim())) { return; } @@ -5847,6 +6061,7 @@ }, clear: function() { var captcha, i, now, _i, _len, _ref; + now = Date.now(); _ref = this.captchas; for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { @@ -5864,6 +6079,7 @@ }, load: function() { var challenge; + if (!this.nodes.challenge.firstChild) { return; } @@ -5876,6 +6092,7 @@ }, count: function() { var count; + count = this.captchas.length; this.nodes.input.placeholder = (function() { switch (count) { @@ -5908,6 +6125,7 @@ }, dialog: function() { var check, dialog, elm, i, items, key, mimeTypes, name, nodes, thread, value, _ref; + QR.nodes = nodes = { el: dialog = UI.dialog('qr', 'top:0;right:0;', "
×
No selected file×+
") }; @@ -6030,6 +6248,7 @@ preSubmitHooks: [], submit: function(e) { var challenge, err, extra, filetag, hook, options, post, postData, response, textOnly, thread, threadID, _i, _len, _ref, _ref1; + if (e != null) { e.preventDefault(); } @@ -6143,6 +6362,7 @@ }, response: function() { var URL, ban, board, captchasCount, err, h1, isReply, m, notif, post, postID, postsCount, req, resDoc, threadID, _, _ref, _ref1; + req = QR.req; delete QR.req; post = QR.posts[0]; @@ -6256,6 +6476,7 @@ FappeTyme = { init: function() { var el, input; + if (!(Conf['Fappe Tyme'] || Conf['Werk Tyme']) || g.VIEW === 'catalog' || g.BOARD === 'f') { return; } @@ -6311,6 +6532,7 @@ Gallery = { init: function() { var el; + if (g.VIEW === 'catalog' || g.BOARD === 'f' || !Conf['Gallery']) { return; } @@ -6330,6 +6552,7 @@ }, node: function() { var _ref; + if (!((_ref = this.file) != null ? _ref.isImage : void 0)) { return; } @@ -6343,6 +6566,7 @@ }, build: function(image) { var cb, createSubEntry, dialog, el, file, files, i, key, menuButton, name, nodes, value, _i, _len, _ref, _ref1; + Gallery.images = []; nodes = Gallery.nodes = {}; nodes.el = dialog = $.el('div', { @@ -6403,15 +6627,18 @@ return nodes.total.textContent = --i; }, generateThumb: function(file) { - var double, thumb, title; + var double, post, thumb, title; + + post = Get.postFromNode(file); title = ($('.fileText a', file)).textContent; - thumb = ($('.fileThumb', file)).cloneNode(true); + thumb = post.file.thumb.parentNode; if (double = $('img + img', thumb)) { $.rm(double); } thumb.className = 'gal-thumb'; thumb.title = title; thumb.dataset.id = Gallery.images.length; + thumb.dataset.post = $('a[title="Highlight this post"]', post.nodes.info).href; thumb.firstElementChild.style.cssText = ''; $.on(thumb, 'click', Gallery.cb.open); Gallery.images.push(thumb); @@ -6420,6 +6647,7 @@ cb: { keybinds: function(e) { var cb, key; + if (!(key = Keybinds.keyCode(e))) { return; } @@ -6445,6 +6673,7 @@ }, open: function(e) { var el, img, name, nodes, rect, top; + if (e) { e.preventDefault(); } @@ -6461,7 +6690,7 @@ src: name.href = this.href, title: name.download = name.textContent = this.title }); - img.dataset.id = this.dataset.id; + $.extend(img.dataset, this.dataset); $.replace(nodes.current, img); nodes.count.textContent = +this.dataset.id + 1; nodes.current = img; @@ -6475,13 +6704,68 @@ return; } } - return nodes.thumbs.scrollTop += top; + nodes.thumbs.scrollTop += top; + return $.on(img, 'error', function() { + return Gallery.cb.error(img, thumb); + }); }, image: function(e) { e.preventDefault(); e.stopPropagation(); return Gallery.build(this); }, + error: function(img, thumb) { + var URL, post, revived, src; + + post = Get.postFromLink($.el('a', { + href: img.dataset.post + })); + delete post.file.fullImage; + src = this.src.split('/'); + if (src[2] === 'images.4chan.org') { + URL = Redirect.to('file', { + boardID: src[3], + filename: src[5] + }); + if (URL) { + thumb.href = URL; + if (Gallery.nodes.current !== img) { + return; + } + revived = $.el('img', { + src: URL, + title: img.title + }); + $.extend(revived.dataset, img.dataset); + $.replace(img, revived); + return; + } + if (g.DEAD || post.isDead || post.file.isDead) { + return; + } + } + return $.ajax("//api.4chan.org/" + post.board + "/res/" + post.thread + ".json", { + onload: function() { + var i, postObj; + + if (this.status !== 200) { + return; + } + i = 0; + while (postObj = JSON.parse(this.response).posts[i++]) { + if (postObj.no === post.ID) { + break; + } + } + if (!postObj.no) { + return post.kill(); + } + if (postObj.filedeleted) { + return post.kill(true); + } + } + }); + }, prev: function() { return Gallery.cb.open.call(Gallery.images[+Gallery.nodes.current.dataset.id - 1]); }, @@ -6507,6 +6791,7 @@ menu: { init: function() { var createSubEntry, el, name, subEntries, _i, _len, _ref; + if (g.VIEW === 'catalog' || !Conf['Gallery'] || Conf['Image Expansion']) { return; } @@ -6530,6 +6815,7 @@ }, createSubEntry: function(name) { var input, label; + label = $.el('label', { innerHTML: " " + name }); @@ -6565,6 +6851,7 @@ }, node: function() { var thumb, _ref; + if (!((_ref = this.file) != null ? _ref.isImage : void 0)) { return; } @@ -6589,6 +6876,7 @@ }, toggleAll: function() { var ID, file, func, post, _i, _len, _ref, _ref1; + $.event('CloseMenu'); if (ImageExpand.on = $.hasClass(ImageExpand.EAI, 'expand-all-shortcut')) { ImageExpand.EAI.className = 'contract-all-shortcut fourchanx-icon icon-resize-small'; @@ -6622,6 +6910,7 @@ }, toggle: function(post) { var headRect, rect, root, thumb, x, y; + thumb = post.file.thumb; if (!(post.file.isExpanded || $.hasClass(thumb, 'expanding'))) { ImageExpand.expand(post); @@ -6631,6 +6920,7 @@ root = post.nodes.root; rect = (Conf['Advance on contract'] ? (function() { var next; + next = root; while (next = $.x("following::div[contains(@class,'postContainer')][1]", next)) { if ($('.stub', next) || next.offsetHeight === 0) { @@ -6661,6 +6951,7 @@ }, expand: function(post, src) { var img, thumb; + thumb = post.file.thumb; if (post.isHidden || post.file.isExpanded || $.hasClass(thumb, 'expanding')) { return; @@ -6688,6 +6979,7 @@ }, completeExpand: function(post) { var prev, thumb; + thumb = post.file.thumb; if (!$.hasClass(thumb, 'expanding')) { return; @@ -6701,6 +6993,7 @@ prev = post.nodes.root.getBoundingClientRect(); return $.queueTask(function() { var curr; + $.addClass(post.nodes.root, 'expanded-image'); $.rmClass(post.file.thumb, 'expanding'); if (!(prev.top + prev.height <= 0)) { @@ -6712,6 +7005,7 @@ }, error: function() { var URL, post, src, timeoutID; + post = Get.postFromNode(this); $.rm(this); delete post.file.fullImage; @@ -6737,6 +7031,7 @@ return $.ajax("//api.4chan.org/" + post.board + "/res/" + post.thread + ".json", { onload: function() { var postObj, _i, _len, _ref; + if (this.status !== 200) { return; } @@ -6760,6 +7055,7 @@ menu: { init: function() { var conf, createSubEntry, el, name, subEntries, _ref; + if (g.VIEW === 'catalog' || !Conf['Image Expansion']) { return; } @@ -6783,6 +7079,7 @@ }, createSubEntry: function(name, desc) { var input, label; + label = $.el('label', { innerHTML: " " + name, title: desc @@ -6813,6 +7110,7 @@ }, node: function() { var _ref; + if (!((_ref = this.file) != null ? _ref.isImage : void 0)) { return; } @@ -6820,6 +7118,7 @@ }, mouseover: function(e) { var el, post; + post = Get.postFromNode(this); el = $.el('img', { id: 'ihover', @@ -6841,6 +7140,7 @@ error: function() { var URL, post, src, timeoutID, _this = this; + if (!doc.contains(this)) { return; } @@ -6865,6 +7165,7 @@ return $.ajax("//api.4chan.org/" + post.board + "/res/" + post.thread + ".json", { onload: function() { var postObj, _i, _len, _ref; + if (this.status !== 200) { return; } @@ -6890,6 +7191,7 @@ ImageLoader = { init: function() { var prefetch; + if (g.VIEW === 'catalog') { return; } @@ -6916,6 +7218,7 @@ }, node: function() { var URL, img, string, style, thumb, type, _ref, _ref1; + if (this.isClone || this.isHidden || this.thread.isHidden || !((_ref = this.file) != null ? _ref.isImage : void 0)) { return; } @@ -6937,6 +7240,7 @@ }, toggle: function() { var enabled, id, post, _ref; + enabled = Conf['prefetch'] = this.checked; if (enabled) { _ref = g.threads["" + g.BOARD.ID + "." + g.THREADID].posts; @@ -6960,6 +7264,7 @@ }, node: function() { var thumb, _ref; + if (this.isClone || !((_ref = this.file) != null ? _ref.isSpoiler : void 0)) { return; } @@ -6972,6 +7277,7 @@ Sauce = { init: function() { var err, link, links, _i, _len, _ref; + if (g.VIEW === 'catalog' || !Conf['Sauce']) { return; } @@ -7001,6 +7307,7 @@ }, createSauceLink: function(link) { var m, text; + link = link.replace(/%(T?URL|MD5|board)/ig, function(parameter) { switch (parameter) { case '%TURL': @@ -7021,6 +7328,7 @@ }, node: function() { var link, nodes, _i, _len, _ref; + if (this.isClone || !this.file) { return; } @@ -7037,6 +7345,7 @@ ArchiveLink = { init: function() { var div, entry, type, _i, _len, _ref; + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Archive Link']) { return; } @@ -7049,6 +7358,7 @@ order: 90, open: function(_arg) { var ID, board, thread; + ID = _arg.ID, thread = _arg.thread, board = _arg.board; return !!Redirect.to('thread', { postID: ID, @@ -7067,12 +7377,14 @@ }, createSubEntry: function(text, type) { var el, open; + el = $.el('a', { textContent: text, target: '_blank' }); open = type === 'post' ? function(_arg) { var ID, board, thread; + ID = _arg.ID, thread = _arg.thread, board = _arg.board; el.href = Redirect.to('thread', { postID: ID, @@ -7082,6 +7394,7 @@ return true; } : function(post) { var value; + value = Filter[type](post); if (!value) { return false; @@ -7104,6 +7417,7 @@ DeleteLink = { init: function() { var div, fileEl, fileEntry, postEl, postEntry; + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Delete Link']) { return; } @@ -7131,6 +7445,7 @@ el: fileEl, open: function(_arg) { var file; + file = _arg.file; if (!file || file.isDead) { return false; @@ -7146,6 +7461,7 @@ order: 40, open: function(post) { var node; + if (post.isDead || post.board.ID === 'q') { return false; } @@ -7160,6 +7476,7 @@ }, "delete": function() { var fileOnly, form, link, post; + post = DeleteLink.post; if (DeleteLink.cooldown.counting === post) { return; @@ -7189,6 +7506,7 @@ }, load: function(link, post, fileOnly, resDoc) { var msg, s; + if (resDoc.title === '4chan - Banned') { s = 'Banned!'; } else if (msg = resDoc.getElementById('errmsg')) { @@ -7209,6 +7527,7 @@ cooldown: { start: function(post, node) { var length, seconds, _ref; + if (!((_ref = QR.db) != null ? _ref.get({ boardID: post.board.ID, threadID: post.thread.ID, @@ -7242,6 +7561,7 @@ DownloadLink = { init: function() { var a; + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Download Link']) { return; } @@ -7255,6 +7575,7 @@ order: 100, open: function(_arg) { var file; + file = _arg.file; if (!file) { return false; @@ -7287,6 +7608,7 @@ }, makeButton: (function() { var a; + a = $.el('a', { className: 'menu-button brackets-wrap', innerHTML: '', @@ -7294,6 +7616,7 @@ }); return function() { var button; + button = a.cloneNode(true); $.on(button, 'click', Menu.toggle); return button; @@ -7301,6 +7624,7 @@ })(), toggle: function(e) { var post; + post = Get.postFromNode(this); return Menu.menu.toggle(e, this, post); } @@ -7309,6 +7633,7 @@ ReportLink = { init: function() { var a; + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Report Link']) { return; } @@ -7330,6 +7655,7 @@ }, report: function() { var id, post, set, url; + post = ReportLink.post; url = "//sys.4chan.org/" + post.board + "/imgboard.php?mode=report&no=" + post; id = Date.now(); @@ -7342,6 +7668,7 @@ init: function() { return $.ready(function() { var href; + Favicon.el = $('link[rel="shortcut icon"]', d.head); Favicon.el.type = 'image/x-icon'; href = Favicon.el.href; @@ -7415,6 +7742,7 @@ init: function() { var sc, _this = this; + if (g.VIEW !== 'thread' || !Conf['Thread Stats']) { return; } @@ -7443,6 +7771,7 @@ }, node: function() { var ID, fileCount, post, postCount, _ref; + postCount = 0; fileCount = 0; _ref = this.posts; @@ -7460,6 +7789,7 @@ }, onUpdate: function(e) { var fileCount, postCount, _ref; + if (e.detail[404]) { return; } @@ -7468,6 +7798,7 @@ }, update: function(postCount, fileCount) { var fileCountEl, postCountEl, thread; + thread = ThreadStats.thread, postCountEl = ThreadStats.postCountEl, fileCountEl = ThreadStats.fileCountEl; postCountEl.textContent = postCount; fileCountEl.textContent = fileCount; @@ -7492,6 +7823,7 @@ }, onThreadsLoad: function() { var page, pages, thread, _i, _j, _len, _len1, _ref; + if (!(Conf["Page Count in Stats"] && this.status === 200)) { return; } @@ -7515,6 +7847,7 @@ init: function() { var checked, conf, el, input, name, sc, settings, subEntries, _ref, _this = this; + if (g.VIEW !== 'thread' || !Conf['Thread Updater']) { return; } @@ -7664,6 +7997,7 @@ }, interval: function() { var val; + val = +this.value; if (val < 1) { val = 1; @@ -7673,6 +8007,7 @@ }, load: function() { var klass, req, text, _ref; + req = ThreadUpdater.req; switch (req.status) { case 200: @@ -7705,6 +8040,7 @@ }, getInterval: function() { var i, j; + i = ThreadUpdater.interval; j = Math.min(ThreadUpdater.outdateCount, 10); if (!d.hidden) { @@ -7714,12 +8050,14 @@ }, intervalShortcut: function() { var settings; + Settings.open('Advanced'); settings = $.id('fourchanx-settings'); return $('input[name=Interval]', settings).focus(); }, set: function(name, text, klass) { var el, node; + el = ThreadUpdater[name]; if (node = el.firstChild) { node.data = text; @@ -7732,6 +8070,7 @@ }, timeout: function() { var n; + ThreadUpdater.timeoutID = setTimeout(ThreadUpdater.timeout, 1000); if (!(n = --ThreadUpdater.seconds)) { return ThreadUpdater.update(); @@ -7744,6 +8083,7 @@ }, update: function() { var url; + if (!ThreadUpdater.online) { return; } @@ -7766,6 +8106,7 @@ }, updateThreadStatus: function(title, OP) { var icon, message, root, titleLC; + titleLC = title.toLowerCase(); if (ThreadUpdater.thread["is" + title] === !!OP[titleLC]) { return; @@ -7792,6 +8133,7 @@ }, parse: function(postObjects) { var ID, OP, count, deletedFiles, deletedPosts, files, index, key, node, num, post, postObject, posts, root, scroll, _i, _len, _ref; + OP = postObjects[0]; Build.spoilerRange[ThreadUpdater.thread.board] = OP.custom_spoiler; ThreadUpdater.updateThreadStatus('Sticky', OP); @@ -7877,6 +8219,7 @@ } $.queueTask(function() { var length, threadID; + threadID = ThreadUpdater.thread.ID; length = $$('.thread > .postContainer', ThreadUpdater.root).length; return Fourchan.parseThread(threadID, length - count, length); @@ -7897,6 +8240,7 @@ ThreadWatcher = { init: function() { var now, sc; + if (!Conf['Thread Watcher']) { return; } @@ -7929,6 +8273,7 @@ } $.get('WatchedThreads', null, function(_arg) { var WatchedThreads, boardID, data, threadID, threads, _ref; + WatchedThreads = _arg.WatchedThreads; if (!WatchedThreads) { return; @@ -7954,6 +8299,7 @@ }, node: function() { var toggler; + toggler = $.el('img', { className: 'watch-thread-link' }); @@ -7975,6 +8321,7 @@ } return $.get('AutoWatch', 0, function(_arg) { var AutoWatch, thread; + AutoWatch = _arg.AutoWatch; if (!(thread = g.BOARD.threads[AutoWatch])) { return; @@ -7990,6 +8337,7 @@ cb: { openAll: function() { var a, _i, _len, _ref; + if ($.hasClass(this, 'disabled')) { return; } @@ -8008,6 +8356,7 @@ }, pruneDeads: function() { var boardID, data, threadID, _i, _len, _ref, _ref1; + if ($.hasClass(this, 'disabled')) { return; } @@ -8031,11 +8380,13 @@ }, rm: function() { var boardID, threadID, _ref; + _ref = this.parentNode.dataset.fullID.split('.'), boardID = _ref[0], threadID = _ref[1]; return ThreadWatcher.rm(boardID, +threadID); }, post: function(e) { var board, postID, threadID, _ref; + _ref = e.detail, board = _ref.board, postID = _ref.postID, threadID = _ref.threadID; if (postID === threadID) { if (Conf['Auto Watch']) { @@ -8047,6 +8398,7 @@ }, threadUpdate: function(e) { var thread; + thread = e.detail.thread; if (!(e.detail[404] && ThreadWatcher.db.get({ boardID: thread.board.ID, @@ -8063,6 +8415,7 @@ }, fetchAllStatus: function() { var thread, threads, _i, _len; + if (!(threads = ThreadWatcher.getAll()).length) { return; } @@ -8074,6 +8427,7 @@ }, fetchStatus: function(_arg) { var boardID, data, fetchCount, threadID; + boardID = _arg.boardID, threadID = _arg.threadID, data = _arg.data; if (data.isDead) { return; @@ -8083,6 +8437,7 @@ return $.ajax("//api.4chan.org/" + boardID + "/res/" + threadID + ".json", { onloadend: function() { var status; + fetchCount.fetched++; if (fetchCount.fetched === fetchCount.fetching) { fetchCount.fetched = 0; @@ -8113,6 +8468,7 @@ }, getAll: function() { var all, boardID, data, threadID, threads, _ref; + all = []; _ref = ThreadWatcher.db.data.boards; for (boardID in _ref) { @@ -8133,6 +8489,7 @@ }, makeLine: function(boardID, threadID, data) { var div, fullID, href, link, x; + x = $.el('a', { textContent: '×', href: 'javascript:;' @@ -8163,6 +8520,7 @@ }, refresh: function() { var boardID, data, helper, list, nodes, refresher, thread, threadID, toggler, watched, _i, _j, _len, _len1, _ref, _ref1, _ref2, _ref3; + nodes = []; _ref = ThreadWatcher.getAll(); for (_i = 0, _len = _ref.length; _i < _len; _i++) { @@ -8192,6 +8550,7 @@ }, toggle: function(thread) { var boardID, threadID; + boardID = thread.board.ID; threadID = thread.ID; if (ThreadWatcher.db.get({ @@ -8205,6 +8564,7 @@ }, add: function(thread) { var boardID, data, threadID; + data = {}; boardID = thread.board.ID; threadID = thread.ID; @@ -8235,6 +8595,7 @@ }, convert: function(oldFormat) { var boardID, data, newFormat, threadID, threads; + newFormat = {}; for (boardID in oldFormat) { threads = oldFormat[boardID]; @@ -8251,6 +8612,7 @@ refreshers: [], init: function() { var menu; + if (!Conf['Thread Watcher']) { return; } @@ -8263,6 +8625,7 @@ }, addHeaderMenuEntry: function() { var entryEl; + if (g.VIEW !== 'thread') { return; } @@ -8279,6 +8642,7 @@ }); return this.refreshers.push(function() { var addClass, rmClass, text, _ref; + _ref = $('.current', ThreadWatcher.list) ? ['unwatch-thread', 'watch-thread', 'Unwatch thread'] : ['watch-thread', 'unwatch-thread', 'Watch thread'], addClass = _ref[0], rmClass = _ref[1], text = _ref[2]; $.addClass(entryEl, addClass); $.rmClass(entryEl, rmClass); @@ -8287,6 +8651,7 @@ }, addMenuEntries: function() { var cb, conf, entries, entry, name, refresh, subEntries, _i, _len, _ref, _ref1, _results; + entries = []; entries.push({ cb: ThreadWatcher.cb.openAll, @@ -8357,6 +8722,7 @@ }, createSubEntry: function(name, desc) { var entry, input; + entry = { type: 'thread watcher', el: $.el('label', { @@ -8408,6 +8774,7 @@ }, ready: function() { var ID, post, posts, _ref; + $.off(d, '4chanXInitFinished', Unread.ready); posts = []; _ref = Unread.thread.posts; @@ -8422,6 +8789,7 @@ }, scroll: function() { var checkPosition, hash, onload, post, posts, root; + if (!Conf['Scroll to Last Read Post']) { return; } @@ -8458,6 +8826,7 @@ }, sync: function() { var lastReadPost; + lastReadPost = Unread.db.get({ boardID: Unread.thread.board.ID, threadID: Unread.thread.ID, @@ -8476,6 +8845,7 @@ }, addPosts: function(posts) { var ID, data, post, _i, _len; + for (_i = 0, _len = posts.length; _i < _len; _i++) { post = posts[_i]; ID = post.ID; @@ -8503,6 +8873,7 @@ }, addPostQuotingYou: function(post) { var quotelink, _i, _len, _ref; + if (!QR.db) { return; } @@ -8518,6 +8889,7 @@ }, openNotification: function(post) { var name, notif; + if (!Header.areNotificationsEnabled) { return; } @@ -8543,6 +8915,7 @@ }, readSinglePost: function(post) { var i; + if ((i = Unread.posts.indexOf(post)) === -1) { return; } @@ -8558,6 +8931,7 @@ }, readArray: function(arr) { var i, post, _i, _len; + for (i = _i = 0, _len = arr.length; _i < _len; i = ++_i) { post = arr[i]; if (post.ID > Unread.lastReadPost) { @@ -8568,6 +8942,7 @@ }, read: $.debounce(50, function(e) { var ID, height, i, post, posts; + if (d.hidden || !Unread.posts.length) { return; } @@ -8620,6 +8995,7 @@ }), setLine: function(force) { var post; + if (!(d.hidden || force === true)) { return; } @@ -8632,6 +9008,7 @@ }, update: function() { var count; + count = Unread.posts.length; if (Conf['Unread Count']) { d.title = "" + (Conf['Quoted Title'] && Unread.postsQuotingYou.length ? '(!) ' : '') + (count || !Conf['Hide Unread Count at (0)'] ? "(" + count + ") " : '') + (g.DEAD ? "/" + g.BOARD + "/ - 404" : "" + Unread.title); @@ -8652,6 +9029,7 @@ }, init: function() { var archive, boardID, boards, data, id, name, type, _i, _len, _ref, _ref1, _ref2; + _ref = Conf['selectedArchives']; for (boardID in _ref) { data = _ref[boardID]; @@ -8783,6 +9161,7 @@ }, to: function(dest, data) { var archive; + archive = (dest === 'search' ? Redirect.data.thread : Redirect.data[dest])[data.boardID]; if (!archive) { return ''; @@ -8791,6 +9170,7 @@ }, protocol: function(archive) { var protocol; + protocol = location.protocol; if (!archive[protocol.slice(0, -1)]) { protocol = protocol === 'https:' ? 'http:' : 'https:'; @@ -8799,6 +9179,7 @@ }, thread: function(archive, _arg) { var boardID, path, postID, threadID; + boardID = _arg.boardID, threadID = _arg.threadID, postID = _arg.postID; path = threadID ? "" + boardID + "/thread/" + threadID : "" + boardID + "/post/" + postID; if (archive.software === 'foolfuuka') { @@ -8811,6 +9192,7 @@ }, post: function(archive, _arg) { var URL, boardID, postID, protocol; + boardID = _arg.boardID, postID = _arg.postID; protocol = Redirect.protocol(archive); if (['Foolz', 'NSFW Foolz'].contains(archive.name)) { @@ -8822,11 +9204,13 @@ }, file: function(archive, _arg) { var boardID, filename; + boardID = _arg.boardID, filename = _arg.filename; return "" + (Redirect.protocol(archive)) + archive.domain + "/" + boardID + "/full_image/" + filename; }, search: function(archive, _arg) { var boardID, path, type, value; + boardID = _arg.boardID, type = _arg.type, value = _arg.value; type = type === 'name' ? 'username' : type === 'MD5' ? 'image' : type; value = encodeURIComponent(value); @@ -8845,6 +9229,7 @@ }, setup: function() { var btn, entry, psa; + $.off(d, '4chanXInitFinished', PSAHiding.setup); if (!(psa = $.id('globalMessage'))) { $.rmClass(doc, 'hide-announcement'); @@ -8873,6 +9258,7 @@ $.on(btn, 'click', PSAHiding.toggle); $.get('hiddenPSA', 0, function(_arg) { var hiddenPSA; + hiddenPSA = _arg.hiddenPSA; PSAHiding.sync(hiddenPSA); $.before(psa, btn); @@ -8882,6 +9268,7 @@ }, toggle: function(e) { var UTC; + if ($.hasClass(this, 'hide-announcement')) { UTC = +$.id('globalMessage').dataset.utc; $.set('hiddenPSA', UTC); @@ -8893,6 +9280,7 @@ }, sync: function(UTC) { var hr, psa; + psa = $.id('globalMessage'); psa.hidden = PSAHiding.btn.hidden = UTC && UTC >= +psa.dataset.utc ? true : false; if ((hr = psa.nextElementSibling) && hr.nodeName === 'HR') { @@ -8913,6 +9301,7 @@ }, ready: function() { var banner, child, children, i; + banner = $(".boardBanner"); children = banner.children; i = 0; @@ -8932,6 +9321,7 @@ cb: { toggle: (function() { var types; + types = { jpg: 227, png: 270, @@ -8939,6 +9329,7 @@ }; return function() { var num, type; + type = Object.keys(types)[Math.floor(3 * Math.random())]; num = Math.floor(types[type] * Math.random()); return this.src = "//static.4chan.org/image/title/" + num + "." + type; @@ -8958,6 +9349,7 @@ }, focus: function() { var items, string, string2; + this.textContent = this.innerHTML; string = "" + g.BOARD + "." + this.className; string2 = "" + string + ".orig"; @@ -8980,6 +9372,7 @@ }, custom: function(child) { var cachedTest, string; + cachedTest = child.innerHTML; string = "" + g.BOARD + "." + child.className; $.on(child, 'click keydown focus blur', function(e) { @@ -8987,6 +9380,7 @@ }); $.get(string, cachedTest, function(item) { var string2, title; + if (!(title = item[string])) { return; } @@ -9010,6 +9404,7 @@ CatalogLinks = { init: function() { var el, input; + if (!Conf['Catalog Links']) { return; } @@ -9033,12 +9428,14 @@ }, toggle: function() { var useCatalog; + $.event('CloseMenu'); $.set('Header catalog links', useCatalog = this.checked); return CatalogLinks.set(useCatalog); }, set: function(useCatalog) { var a, board, path, _i, _len, _ref; + path = useCatalog ? 'catalog' : ''; _ref = $$("#board-list a[href*=\"boards.4chan.org\"]:not(.catalog),\n#boardNavDesktopFoot a[href*=\"boards.4chan.org\"]"); for (_i = 0, _len = _ref.length; _i < _len; _i++) { @@ -9073,6 +9470,7 @@ }, node: function() { var rgb, span, style, uid; + if (this.isClone || !(uid = this.info.uniqueID)) { return; } @@ -9089,6 +9487,7 @@ }, compute: function(uid) { var hash, rgb; + if (IDColor.ids[uid]) { return IDColor.ids[uid]; } @@ -9099,6 +9498,7 @@ }, hash: function(uid) { var i, msg; + msg = 0; i = 0; while (i < 8) { @@ -9144,6 +9544,7 @@ }, node: function() { var dicestats, roll, _ref; + if (this.isClone || !(dicestats = (_ref = this.info.email) != null ? _ref.match(/dice[+\s](\d+)d(\d+)/) : void 0)) { return; } @@ -9155,6 +9556,7 @@ Emoji = { init: function() { var css, icon, name, pos, _ref; + if (!Conf['Emoji']) { return; } @@ -9224,6 +9626,7 @@ }, node: function() { var a; + if (a = $('.abbr > a:not([onclick])', this.nodes.comment)) { return $.on(a, 'click', ExpandComment.cb); } @@ -9235,6 +9638,7 @@ }, expand: function(post) { var a; + if (post.nodes.longComment && !post.nodes.longComment.parentNode) { $.replace(post.nodes.shortComment, post.nodes.longComment); post.nodes.comment = post.nodes.longComment; @@ -9250,6 +9654,7 @@ }, contract: function(post) { var a; + if (!post.nodes.shortComment) { return; } @@ -9260,6 +9665,7 @@ }, parse: function(req, a, post) { var callback, clone, comment, href, postObj, posts, quote, spoilerRange, status, _i, _j, _k, _len, _len1, _len2, _ref, _ref1; + status = req.status; if (![200, 304].contains(status)) { a.textContent = "Error " + req.statusText + " (" + status + ")"; @@ -9322,6 +9728,7 @@ }, node: function() { var a, files, posts, span, _ref; + if (!(span = $.x('following-sibling::span[contains(@class,"summary")][1]', this.OP.nodes.root))) { return; } @@ -9342,6 +9749,7 @@ }, toggle: function(thread) { var a, files, filesCount, inlined, num, post, posts, postsCount, reply, threadRoot, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3, _ref4; + threadRoot = thread.OP.nodes.root.parentNode; a = $('.summary', threadRoot); switch (thread.isExpanded) { @@ -9419,6 +9827,7 @@ }, parse: function(req, thread, a) { var filesCount, link, post, posts, postsCount, postsObj, postsRoot, reply, root, spoilerRange, _i, _len; + if (a.textContent[0] === '+') { return; } @@ -9482,6 +9891,7 @@ }, createFunc: function(format) { var code; + code = format.replace(/%(.)/g, function(s, c) { if (c in FileInfo.formatters) { return "' + FileInfo.formatters." + c + ".call(post) + '"; @@ -9493,6 +9903,7 @@ }, convertUnit: function(size, unit) { var i; + if (unit === 'B') { return "" + (size.toFixed()) + " Bytes"; } @@ -9523,6 +9934,7 @@ }, n: function() { var fullname, shortname; + fullname = this.file.name; shortname = Build.shortFilename(this.file.name, this.isReply); if (fullname === shortname) { @@ -9566,6 +9978,7 @@ Fourchan = { init: function() { var board; + if (g.VIEW === 'catalog') { return; } @@ -9587,6 +10000,7 @@ }, code: function() { var pre, _i, _len, _ref; + if (this.isClone) { return; } @@ -9615,11 +10029,13 @@ Keybinds = { init: function() { var init; + if (g.VIEW === 'catalog' || !Conf['Keybinds']) { return; } init = function() { var node, _i, _len, _ref; + $.off(d, '4chanXInitFinished', init); $.on(d, 'keydown', Keybinds.keydown); _ref = $$('[accesskey]'); @@ -9632,6 +10048,7 @@ }, keydown: function(e) { var form, key, notification, notifications, op, target, thread, threadRoot, _i, _len; + if (!(key = Keybinds.keyCode(e))) { return; } @@ -9812,6 +10229,7 @@ }, keyCode: function(e) { var kc, key; + key = (function() { switch (kc = e.keyCode) { case 8: @@ -9867,6 +10285,7 @@ }, tags: function(tag, ta) { var range, selEnd, selStart, value; + value = ta.value; selStart = ta.selectionStart; selEnd = ta.selectionEnd; @@ -9877,11 +10296,13 @@ }, sage: function() { var isSage; + isSage = /sage/i.test(QR.nodes.email.value); return QR.nodes.email.value = isSage ? "" : "sage"; }, img: function(thread, all) { var post; + if (all) { return ImageExpand.cb.toggleAll(); } else { @@ -9891,6 +10312,7 @@ }, open: function(thread, tab) { var url; + if (g.VIEW !== 'index') { return; } @@ -9903,6 +10325,7 @@ }, hl: function(delta, thread) { var axe, headRect, next, postEl, rect, replies, reply, root, topMargin, _i, _len; + if (!delta) { if (postEl = $('.reply.highlight', thread)) { $.rmClass(postEl, 'highlight'); @@ -9962,6 +10385,7 @@ Nav = { init: function() { var append, next, prev, span; + switch (g.VIEW) { case 'index': if (!Conf['Index Navigation']) { @@ -10012,6 +10436,7 @@ }, getThread: function(full) { var headRect, i, rect, thread, threads, topMargin, _i, _len; + if (Conf['Bottom header'] || !Conf['Fixed Header']) { topMargin = 0; } else { @@ -10037,6 +10462,7 @@ }, scroll: function(delta) { var i, rect, thread, threads, top, topMargin, _ref, _ref1; + _ref = Nav.getThread(true), threads = _ref[0], thread = _ref[1], i = _ref[2], rect = _ref[3], topMargin = _ref[4]; top = rect.top - topMargin; if ((delta === -1 && top > -5) || (delta === +1 && top < 5)) { @@ -10061,6 +10487,7 @@ }, node: function() { var dateEl; + if (this.isClone) { return; } @@ -10070,6 +10497,7 @@ }, relative: function(diff, now, date) { var days, months, number, rounded, unit, years; + unit = (number = diff / $.DAY) >= 1 ? (years = now.getYear() - date.getYear(), months = now.getMonth() - date.getMonth(), days = now.getDate() - date.getDate(), years > 1 ? (number = years - (months < 0 || months === 0 && days < 0), 'year') : years === 1 && (months > 0 || months === 0 && days >= 0) ? (number = years, 'year') : (months = (months + 12) % 12) > 1 ? (number = months - (days < 0), 'month') : months === 1 && days >= 0 ? (number = months, 'month') : 'day') : (number = diff / $.HOUR) >= 1 ? 'hour' : (number = diff / $.MINUTE) >= 1 ? 'minute' : (number = Math.max(0, diff) / $.SECOND, 'second'); rounded = Math.round(number); if (rounded !== 1) { @@ -10080,6 +10508,7 @@ stale: [], flush: function() { var now, update, _i, _len, _ref; + if (d.hidden) { return; } @@ -10095,13 +10524,16 @@ }, setUpdate: function(post) { var markStale, setOwnTimeout, update; + setOwnTimeout = function(diff) { var delay; + delay = diff < $.MINUTE ? $.SECOND - (diff + $.SECOND / 2) % $.SECOND : diff < $.HOUR ? $.MINUTE - (diff + $.MINUTE / 2) % $.MINUTE : diff < $.DAY ? $.HOUR - (diff + $.HOUR / 2) % $.HOUR : $.DAY - (diff + $.DAY / 2) % $.DAY; return setTimeout(markStale, delay); }; update = function(now) { var date, diff, relative, singlePost, _i, _len, _ref; + date = post.info.date; diff = now - date; relative = RelativeDates.relative(diff, now, date); @@ -10142,6 +10574,7 @@ }, node: function(post) { var spoiler, spoilers, _i, _len; + spoilers = $$('s', this.nodes.comment); for (_i = 0, _len = spoilers.length; _i < _len; _i++) { spoiler = spoilers[_i]; @@ -10161,6 +10594,7 @@ }, ready: function() { var field; + field = $.id('recaptcha_response_field'); $.on(field, 'keydown', function(e) { if (e.keyCode === 8 && !field.value) { @@ -10169,6 +10603,7 @@ }); return $.on($('form'), 'submit', function(e) { var response; + e.preventDefault(); response = field.value.trim(); if (!/\s/.test(response)) { @@ -10198,6 +10633,7 @@ }, createFunc: function(format) { var code; + code = format.replace(/%([A-Za-z])/g, function(s, c) { if (c in Time.formatters) { return "' + Time.formatters." + c + ".call(date) + '"; @@ -10282,6 +10718,7 @@ Settings = { init: function() { var link, settings; + link = $.el('a', { className: 'settings-link fourchanx-icon icon-wrench', textContent: 'Settings', @@ -10291,6 +10728,7 @@ Header.addShortcut(link); $.get('previousversion', null, function(item) { var changelog, el, previous; + if (previous = item['previousversion']) { if (previous === g.VERSION) { return; @@ -10325,6 +10763,7 @@ }, open: function(openSection) { var dialog, html, link, links, overlay, section, sectionToOpen, _i, _len, _ref; + $.off(d, '4chanXInitFinished', Settings.open); if (Settings.dialog) { return; @@ -10377,6 +10816,7 @@ sections: [], addSection: function(title, open) { var hyphenatedTitle, _ref; + if (typeof title !== 'string') { _ref = title.detail, title = _ref.title, open = _ref.open; } @@ -10389,6 +10829,7 @@ }, openSection: function() { var section, selected; + if (selected = $('.tab-selected', Settings.dialog)) { $.rmClass(selected, 'tab-selected'); } @@ -10402,6 +10843,7 @@ }, main: function(section) { var arr, button, description, div, fs, hiddenNum, input, inputs, items, key, obj, _ref; + items = {}; inputs = {}; _ref = Config.main; @@ -10426,6 +10868,7 @@ } $.get(items, function(items) { var val; + for (key in items) { val = items[key]; inputs[key].checked = val; @@ -10440,6 +10883,7 @@ boards: {} }, function(item) { var ID, board, thread, _ref1; + _ref1 = item.hiddenThreads.boards; for (ID in _ref1) { board = _ref1[ID]; @@ -10454,6 +10898,7 @@ boards: {} }, function(item) { var ID, board, post, thread, _ref1; + _ref1 = item.hiddenPosts.boards; for (ID in _ref1) { board = _ref1[ID]; @@ -10473,6 +10918,7 @@ boards: {} }, function(item) { var boardID; + for (boardID in item.hiddenThreads.boards) { localStorage.removeItem("4chan-hide-t-" + boardID); } @@ -10483,6 +10929,7 @@ }, "export": function(now, data) { var a, db, p, _i, _len, _ref; + if (typeof now !== 'number') { now = Date.now(); data = { @@ -10519,6 +10966,7 @@ }, onImport: function() { var file, output, reader; + if (!(file = this.files[0])) { return; } @@ -10530,6 +10978,7 @@ reader = new FileReader(); reader.onload = function(e) { var data, err; + try { data = JSON.parse(e.target.result); Settings.loadSettings(data); @@ -10546,6 +10995,7 @@ }, loadSettings: function(data) { var key, val, version, _ref; + version = data.version.split('.'); if (version[0] === '2') { data = Settings.convertSettings(data, { @@ -10633,6 +11083,7 @@ }, convertSettings: function(data, map) { var newKey, prevKey; + for (prevKey in map) { newKey = map[prevKey]; if (newKey) { @@ -10644,6 +11095,7 @@ }, filter: function(section) { var select; + section.innerHTML = "
"; select = $('select', section); $.on(select, 'change', Settings.selectFilter); @@ -10651,6 +11103,7 @@ }, selectFilter: function() { var div, name, ta; + div = this.nextElementSibling; if ((name = this.value) !== 'guide') { $.rmAll(div); @@ -10670,6 +11123,7 @@ }, sauce: function(section) { var ta; + section.innerHTML = "
Sauce is disabled.
Lines starting with a # will be ignored.
You can specify a display text by appending ;text:[text] to the URL.
"; ta = $('textarea', section); $.get('sauces', Conf['sauces'], function(item) { @@ -10679,6 +11133,7 @@ }, advanced: function(section) { var archive, boardID, boardOptions, boardSelect, boards, data, event, input, inputs, item, items, name, row, rows, ta, table, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3, _ref4; + section.innerHTML = "
Archiver
404 Redirect is disabled.
Thread redirectionPost fetchingFile redirection
Disabled selections indicate that only one archive is available for that board and redirection type.
Custom Board Navigation
New lines will be converted into spaces.

In the following examples for /g/, g can be changed to a different board ID (a, b, etc...), the current board (current), or the Status/Twitter link (status, @).
Board link: g
Title link: g-title
Board link (Replace with title when on that board): g-replace
Full text link: g-full
Custom text link: g-text:\"Install Gentoo\"
Index-only link: g-index
Catalog-only link: g-catalog
External link: external-text:\"Google\",\"http://www.google.com\"
Combinations are possible: g-index-text:\"Technology Index\"
Full board list toggle: toggle-all

[ toggle-all ] [current-title] [g-title / a-title / jp-title] [x / wsg / h] [t-text:\"Piracy\"]
\n will give you
[ + ] [Technology] [Technology / Anime & Manga / Otaku Culture] [x / wsg / h] [Piracy]
\n if you are on /g/.\n
Time Formatting is disabled.
:
Supported format specifiers:
Day: %a, %A, %d, %e
Month: %m, %b, %B
Year: %y, %Y
Hour: %k, %H, %l, %I, %p, %P
Minute: %M
Second: %S
Quote Backlinks formatting is disabled.
:
File Info Formatting is disabled.
:
Link: %l (truncated), %L (untruncated), %T (Unix timestamp)
Original file name: %n (truncated), %N (untruncated), %t (Unix timestamp)
Spoiler indicator: %p
Size: %B (Bytes), %K (KB), %M (MB), %s (4chan default)
Resolution: %r (Displays 'PDF' for PDF files)
Quick Reply Personas is disabled.

\n One item per line.
\n Items will be added in the relevant input's auto-completion list.
\n Password items will always be used, since there is no password input.
\n Lines starting with a # will be ignored.\n

Unread Favicon is disabled.
Emoji is disabled.
\n Sage Icon:
\n Position:
Thread Updater is disabled.
\n Interval:
"; items = {}; inputs = {}; @@ -10698,6 +11153,7 @@ $.on(ta, 'change', $.cb.value); $.get(items, function(items) { var key, val; + for (key in items) { val = items[key]; if (['emojiPos'].contains(key)) { @@ -10768,6 +11224,7 @@ }); $.get('selectedArchives', Conf['selectedArchives'], function(_arg) { var option, selectedArchives, type; + selectedArchives = _arg.selectedArchives; for (boardID in selectedArchives) { data = selectedArchives[boardID]; @@ -10782,6 +11239,7 @@ }, addArchiveCell: function(boardID, data, type) { var archive, i, length, options, select, td; + length = data[type].length; td = $.el('td', { className: 'archive-cell' @@ -10811,8 +11269,10 @@ }, saveSelectedArchive: function() { var _this = this; + return $.get('selectedArchives', Conf['selectedArchives'], function(_arg) { var selectedArchives, _name; + selectedArchives = _arg.selectedArchives; (selectedArchives[_name = _this.dataset.boardid] || (selectedArchives[_name] = {}))[_this.dataset.type] = _this.value; return $.set('selectedArchives', selectedArchives); @@ -10823,6 +11283,7 @@ }, time: function() { var funk; + funk = Time.createFunc(this.value); return this.nextElementSibling.textContent = funk(Time, new Date()); }, @@ -10831,6 +11292,7 @@ }, fileInfo: function() { var data, funk; + data = { isReply: true, file: { @@ -10869,6 +11331,7 @@ }, keybinds: function(section) { var arr, input, inputs, items, key, tbody, tr, _ref; + section.innerHTML = "
Keybinds are disabled.
Allowed keys: a-z, 0-9, Ctrl, Shift, Alt, Meta, Enter, Esc, Up, Down, Right, Left.
Press Backspace to disable a keybind.
ActionsKeybinds
"; tbody = $('tbody', section); items = {}; @@ -10889,6 +11352,7 @@ } return $.get(items, function(items) { var val; + for (key in items) { val = items[key]; inputs[key].value = val; @@ -10897,6 +11361,7 @@ }, keybind: function(e) { var key; + if (e.keyCode === 9) { return; } @@ -10913,8 +11378,10 @@ Main = { init: function() { var db, flatten, _i, _len, _ref; + flatten = function(parent, obj) { var key, val; + if (obj instanceof Array) { Conf[parent] = obj[0]; } else if (typeof obj === 'object') { @@ -10947,6 +11414,7 @@ }, initFeatures: function() { var init, pathname, _ref; + pathname = location.pathname.split('/'); g.BOARD = new Board(pathname[1]); if ((_ref = g.BOARD.ID) === 'z' || _ref === 'fk') { @@ -10974,6 +11442,7 @@ case 'images.4chan.org': $.ready(function() { var URL; + if (Conf['404 Redirect'] && ['4chan - Temporarily Offline', '4chan - 404 Not Found'].contains(d.title)) { Redirect.init(); pathname = location.pathname.split('/'); @@ -10990,6 +11459,7 @@ } init = function(features) { var err, module, name; + for (name in features) { module = features[name]; try { @@ -11069,6 +11539,7 @@ }, initStyle: function() { var mainStyleSheet, setStyle, style, styleSheets, _ref; + $.off(d, '4chanMainInit', Main.initStyle); if (!Main.isThisPageLegit() || $.hasClass(doc, 'fourchan-x')) { return; @@ -11090,6 +11561,7 @@ styleSheets = $$('link[rel="alternate stylesheet"]', d.head); setStyle = function() { var styleSheet, _i, _len; + $.rmClass(doc, style); for (_i = 0, _len = styleSheets.length; _i < _len; _i++) { styleSheet = styleSheets[_i]; @@ -11111,6 +11583,7 @@ }, initReady: function() { var board, err, errors, href, passLink, postRoot, posts, styleSelector, thread, threadRoot, threads, _i, _j, _len, _len1, _ref, _ref1; + if (['4chan - Temporarily Offline', '4chan - 404 Not Found'].contains(d.title)) { if (Conf['404 Redirect'] && g.VIEW === 'thread') { href = Redirect.to('thread', { @@ -11178,6 +11651,7 @@ }, callbackNodes: function(klass, nodes) { var callback, err, errors, i, len, node, _i, _len, _ref; + len = nodes.length; _ref = klass.prototype.callbacks; for (_i = 0, _len = _ref.length; _i < _len; _i++) { @@ -11205,9 +11679,11 @@ }, callbackNodesDB: function(klass, nodes, cb) { var errors, func, i, len, node, queue, softTask; + queue = []; softTask = function() { var args, func, task; + task = queue.shift(); func = task[0]; args = Array.prototype.slice.call(task, 1); @@ -11226,6 +11702,7 @@ errors = null; func = function(node, i) { var callback, err, _i, _len, _ref; + _ref = klass.prototype.callbacks; for (_i = 0, _len = _ref.length; _i < _len; _i++) { callback = _ref[_i]; @@ -11259,6 +11736,7 @@ }, addCallback: function(e) { var Klass, obj; + obj = e.detail; if (typeof obj.callback.name !== 'string') { throw new Error("Invalid callback name: " + obj.callback.name); @@ -11278,6 +11756,7 @@ }, handleErrors: function(errors) { var div, error, logs, _i, _len; + if (!(errors instanceof Array)) { error = errors; } else if (errors.length === 1) { @@ -11292,6 +11771,7 @@ }); $.on(div.lastElementChild, 'click', function() { var _ref; + return _ref = this.textContent === 'show' ? ['hide', false] : ['show', true], this.textContent = _ref[0], logs.hidden = _ref[1], _ref; }); logs = $.el('div', { @@ -11305,6 +11785,7 @@ }, parseError: function(data) { var error, message; + Main.logError(data); message = $.el('div', { textContent: data.message @@ -11321,6 +11802,7 @@ }, isThisPageLegit: function() { var _ref; + if (!('thisPageIsLegit' in Main)) { Main.thisPageIsLegit = location.hostname === 'boards.4chan.org' && !$('link[href*="favicon-status.ico"]', d.head) && ((_ref = d.title) !== '4chan - Temporarily Offline' && _ref !== '4chan - Error' && _ref !== '504 Gateway Time-out'); } diff --git a/builds/crx/script.js b/builds/crx/script.js index 4e5321019..8171024a3 100644 --- a/builds/crx/script.js +++ b/builds/crx/script.js @@ -332,6 +332,7 @@ Array.prototype.indexOf = function(object) { var i; + i = this.length; while (i--) { if (this[i] === object) { @@ -350,6 +351,7 @@ $.extend = function(object, properties) { var key, val; + for (key in properties) { val = properties[key]; if (!properties.hasOwnProperty(key)) { @@ -367,6 +369,7 @@ $.ready = function(fc) { var cb; + if (d.readyState !== 'loading') { $.queueTask(fc); return; @@ -380,6 +383,7 @@ $.formData = function(form) { var fd, key, val; + if (form instanceof HTMLFormElement) { return new FormData(form); } @@ -399,6 +403,7 @@ $.extend = function(object, properties) { var key, val; + for (key in properties) { val = properties[key]; object[key] = val; @@ -407,9 +412,11 @@ $.ajax = (function() { var lastModified; + lastModified = {}; return function(url, options, extra) { var form, r, sync, type, upCallbacks, whenModified; + if (extra == null) { extra = {}; } @@ -432,9 +439,11 @@ $.cache = (function() { var reqs; + reqs = {}; return function(url, cb, options) { var err, req, rm; + if (req = reqs[url]) { if (req.readyState === 4) { cb.call(req, req.evt); @@ -454,6 +463,7 @@ } $.on(req, 'load', function(e) { var _i, _len, _ref; + _ref = this.callbacks; for (_i = 0, _len = _ref.length; _i < _len; _i++) { cb = _ref[_i]; @@ -489,6 +499,7 @@ $.addStyle = function(css, id) { var style; + style = $.el('style', { id: id, textContent: css @@ -535,6 +546,7 @@ } else { return function(el) { var _ref; + return (_ref = el.parentNode) != null ? _ref.removeChild(el) : void 0; }; } @@ -542,6 +554,7 @@ $.rmAll = function(root) { var node; + while (node = root.firstChild) { root.removeChild(node); } @@ -557,6 +570,7 @@ $.nodes = function(nodes) { var frag, node, _i, _len; + if (!(nodes instanceof Array)) { return nodes; } @@ -590,6 +604,7 @@ $.el = function(tag, properties) { var el; + el = d.createElement(tag); if (properties) { $.extend(el, properties); @@ -599,6 +614,7 @@ $.on = function(el, events, handler) { var event, _i, _len, _ref; + _ref = events.split(' '); for (_i = 0, _len = _ref.length; _i < _len; _i++) { event = _ref[_i]; @@ -608,6 +624,7 @@ $.off = function(el, events, handler) { var event, _i, _len, _ref; + _ref = events.split(' '); for (_i = 0, _len = _ref.length; _i < _len; _i++) { event = _ref[_i]; @@ -631,6 +648,7 @@ $.debounce = function(wait, fn) { var args, exec, lastCall, that, timeout; + lastCall = 0; timeout = null; that = null; @@ -652,9 +670,11 @@ $.queueTask = (function() { var execTask, taskChannel, taskQueue; + taskQueue = []; execTask = function() { var args, func, task; + task = taskQueue.shift(); func = task[0]; args = Array.prototype.slice.call(task, 1); @@ -677,6 +697,7 @@ $.globalEval = function(code) { var script; + script = $.el('script', { textContent: code }); @@ -686,6 +707,7 @@ $.bytesToString = function(size) { var unit; + unit = 0; while (size >= 1024) { size /= 1024; @@ -701,6 +723,7 @@ $.item = function(key, val) { var item; + item = {}; item[key] = val; return item; @@ -711,6 +734,7 @@ $.sync = (function() { chrome.storage.onChanged.addListener(function(changes) { var cb, key; + for (key in changes) { if (cb = $.syncing[key]) { cb(changes[key].newValue); @@ -730,6 +754,7 @@ $.get = function(key, val, cb) { var count, done, items, localItems, syncItems; + if (typeof cb === 'function') { items = $.item(key, val); } else { @@ -749,6 +774,7 @@ count = 0; done = function(item) { var lastError; + lastError = chrome.runtime.lastError; if (lastError) { c.error(lastError, lastError.message || 'No message.'); @@ -770,10 +796,12 @@ $.set = (function() { var items, localItems, set; + items = {}; localItems = {}; set = $.debounce($.SECOND, function() { var err, key, _i, _len, _ref; + _ref = $.localKeys; for (_i = 0, _len = _ref.length; _i < _len; _i++) { key = _ref[_i]; @@ -858,6 +886,7 @@ function Post(root, thread, board, that) { var capcode, date, email, flag, info, name, post, subject, tripcode, uniqueID; + this.thread = thread; this.board = board; if (that == null) { @@ -933,6 +962,7 @@ Post.prototype.parseComment = function() { var bq, i, node, nodes, text; + this.nodes.comment.normalize(); bq = this.nodes.comment.cloneNode(true); nodes = $$('.abbr, .capcodeReplies, .exif, b', bq); @@ -951,6 +981,7 @@ Post.prototype.parseQuotes = function() { var quotelink, _i, _len, _ref; + this.quotes = []; _ref = $$('.quotelink', this.nodes.comment); for (_i = 0, _len = _ref.length; _i < _len; _i++) { @@ -961,6 +992,7 @@ Post.prototype.parseQuote = function(quotelink) { var fullID, match; + if (!(match = quotelink.href.match(/boards\.4chan\.org\/([^\/]+)\/res\/\d+#p(\d+)$/))) { return; } @@ -976,6 +1008,7 @@ Post.prototype.parseFile = function(that) { var alt, anchor, fileEl, fileInfo, size, thumb, unit; + if (!((fileEl = $('.file', this.nodes.post)) && (thumb = $('img[data-md5]', fileEl)))) { return; } @@ -1007,6 +1040,7 @@ Post.prototype.kill = function(file, now) { var clone, quotelink, strong, _i, _j, _len, _len1, _ref, _ref1; + now || (now = new Date()); if (file) { if (this.file.isDead) { @@ -1055,6 +1089,7 @@ Post.prototype.resurrect = function() { var clone, quotelink, strong, _i, _j, _len, _len1, _ref, _ref1; + delete this.isDead; delete this.timeOfDeath; $.rmClass(this.nodes.root, 'deleted-post'); @@ -1088,6 +1123,7 @@ Post.prototype.rmClone = function(index) { var clone, _i, _len, _ref; + this.clones.splice(index, 1); _ref = this.clones.slice(index); for (_i = 0, _len = _ref.length; _i < _len; _i++) { @@ -1105,6 +1141,7 @@ function Clone(origin, context) { 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']; @@ -1192,6 +1229,7 @@ function DataBoard(key, sync, dontClean) { var init, _this = this; + this.key = key; this.onSync = __bind(this.onSync, this); this.data = Conf[key]; @@ -1215,6 +1253,7 @@ DataBoard.prototype["delete"] = function(_arg) { var boardID, postID, threadID; + boardID = _arg.boardID, threadID = _arg.threadID, postID = _arg.postID; if (postID) { delete this.data.boards[boardID][threadID][postID]; @@ -1235,6 +1274,7 @@ DataBoard.prototype.deleteIfEmpty = function(_arg) { var boardID, threadID; + boardID = _arg.boardID, threadID = _arg.threadID; if (threadID) { if (!Object.keys(this.data.boards[boardID][threadID]).length) { @@ -1250,6 +1290,7 @@ DataBoard.prototype.set = function(_arg) { var boardID, postID, threadID, val, _base, _base1, _base2; + boardID = _arg.boardID, threadID = _arg.threadID, postID = _arg.postID, val = _arg.val; if (postID !== void 0) { ((_base = ((_base1 = this.data.boards)[boardID] || (_base1[boardID] = {})))[threadID] || (_base[threadID] = {}))[postID] = val; @@ -1263,6 +1304,7 @@ DataBoard.prototype.get = function(_arg) { var ID, board, boardID, defaultValue, postID, thread, threadID, val, _i, _len; + boardID = _arg.boardID, threadID = _arg.threadID, postID = _arg.postID, defaultValue = _arg.defaultValue; if (board = this.data.boards[boardID]) { if (!threadID) { @@ -1286,6 +1328,7 @@ DataBoard.prototype.clean = function() { var boardID, now, val, _ref; + _ref = this.data.boards; for (boardID in _ref) { val = _ref[boardID]; @@ -1305,8 +1348,10 @@ DataBoard.prototype.ajaxClean = function(boardID) { var _this = this; + return $.cache("//api.4chan.org/" + boardID + "/threads.json", function(e) { var board, page, thread, threads, _i, _j, _len, _len1, _ref, _ref1; + if (e.target.status !== 200) { return; } @@ -1412,8 +1457,10 @@ }, toBlob: function() { var _base; + return (_base = HTMLCanvasElement.prototype).toBlob || (_base.toBlob = function(cb) { var data, i, l, ui8a, _i; + data = atob(this.toDataURL().slice(22)); l = data.length; ui8a = new Uint8Array(l); @@ -1451,6 +1498,7 @@ init: function() { var barFixedToggler, barPositionToggler, customNavToggler, editCustomNav, footerToggler, headerToggler, linkJustifyToggler, menuButton, shortcutToggler, _this = this; + this.menu = new UI.Menu('header'); menuButton = $.el('span', { className: 'menu-button', @@ -1551,6 +1599,7 @@ }); $.ready(function() { var a, cs; + _this.footer = $.id('boardNavDesktopFoot'); if (a = $("a[href*='/" + g.BOARD + "/']", $.id('boardNavDesktopFoot'))) { a.className = 'current'; @@ -1585,6 +1634,7 @@ }), setBoardList: function() { var a, boardList, btn, fourchannav, fullBoardList; + fourchannav = $.id('boardNavDesktop'); if (a = $("a[href*='/" + g.BOARD + "/']", fourchannav)) { a.className = 'current'; @@ -1606,6 +1656,7 @@ }, generateBoardList: function(text) { var as, list, nodes; + list = $('#custom-board-list', Header.bar); $.rmAll(list); if (!text) { @@ -1614,6 +1665,7 @@ as = $$('#full-board-list a[title]', Header.bar); nodes = text.match(/[\w@]+((-(all|title|replace|full|index|catalog|url:"[^"]+[^"]"|text:"[^"]+")|\,"[^"]+[^"]"))*|[^\w@]+/g).map(function(t) { var a, board, m, _i, _len; + if (/^[^\w@]/.test(t)) { return $.tn(t); } @@ -1664,6 +1716,7 @@ }, toggleBoardList: function() { var bar, custom, full, showBoardList; + bar = Header.bar; custom = $('#custom-board-list', bar); full = $('#full-board-list', bar); @@ -1699,6 +1752,7 @@ }, toggleLinkJustify: function() { var centered; + $.event('CloseMenu'); centered = this.nodeName === 'INPUT' ? this.checked : void 0; Header.setLinkJustify(centered); @@ -1742,6 +1796,7 @@ }, toggleBarVisibility: function() { var hide, message; + hide = this.nodeName === 'INPUT' ? this.checked : !$.hasClass(Header.bar, 'autohide'); this.checked = hide; $.set('Header auto-hide', Conf['Header auto-hide'] = hide); @@ -1755,6 +1810,7 @@ }, toggleFooterVisibility: function() { var hide, message; + $.event('CloseMenu'); hide = this.nodeName === 'INPUT' ? this.checked : !!Header.footer.hidden; Header.setFooterVisibility(hide); @@ -1764,6 +1820,7 @@ }, setCustomNav: function(show) { var btn, cust, full, _ref; + Header.customNavToggler.checked = show; cust = $('#custom-board-list', Header.bar); full = $('#full-board-list', Header.bar); @@ -1776,12 +1833,14 @@ }, editCustomNav: function() { var settings; + Settings.open('Advanced'); settings = $.id('fourchanx-settings'); return $('input[name=boardnav]', settings).focus(); }, hashScroll: function() { var hash, post; + if (!((hash = this.location.hash.slice(1)) && (post = $.id(hash)))) { return; } @@ -1792,6 +1851,7 @@ }, scrollToPost: function(post) { var headRect, top; + top = post.getBoundingClientRect().top; if (Conf['Fixed Header'] && !Conf['Bottom Header']) { headRect = Header.bar.getBoundingClientRect(); @@ -1801,6 +1861,7 @@ }, addShortcut: function(el) { var shortcut; + shortcut = $.el('span', { className: 'shortcut brackets-wrap' }); @@ -1812,6 +1873,7 @@ }, createNotification: function(e) { var cb, content, lifetime, notif, type, _ref; + _ref = e.detail, type = _ref.type, content = _ref.content, lifetime = _ref.lifetime, cb = _ref.cb; notif = new Notice(type, content, lifetime); if (cb) { @@ -1821,6 +1883,7 @@ areNotificationsEnabled: false, enableDesktopNotifications: function() { var authorize, disable, el, notice, _ref; + if (!(window.Notification && Conf['Desktop Notifications'])) { return; } @@ -1856,6 +1919,7 @@ spoilerRange: {}, shortFilename: function(filename, isReply) { var threshold; + threshold = isReply ? 30 : 40; if (filename.length - 4 > threshold) { return "" + filename.slice(0, threshold - 5) + "(...)." + filename.slice(-3); @@ -1865,6 +1929,7 @@ }, postFromObject: function(data, boardID) { var o; + o = { postID: data.no, threadID: data.resto || data.no, @@ -1909,6 +1974,7 @@ */ var a, boardID, capcode, capcodeClass, capcodeReplies, capcodeStart, closed, comment, container, date, dateUTC, email, emailEnd, emailStart, ext, file, fileDims, fileHTML, fileInfo, fileSize, fileThumb, filename, flag, flagCode, flagName, href, imgSrc, isClosed, isOP, isSticky, name, postID, quote, shortFilename, spoilerRange, staticPath, sticky, subject, threadID, tripcode, uniqueID, userID, _i, _len, _ref; + postID = o.postID, threadID = o.threadID, boardID = o.boardID, name = o.name, capcode = o.capcode, tripcode = o.tripcode, uniqueID = o.uniqueID, email = o.email, subject = o.subject, flagCode = o.flagCode, flagName = o.flagName, date = o.date, dateUTC = o.dateUTC, isSticky = o.isSticky, isClosed = o.isClosed, comment = o.comment, capcodeReplies = o.capcodeReplies, file = o.file; isOP = postID === threadID; staticPath = '//static.4chan.org/image/'; @@ -2007,6 +2073,7 @@ }, capcodeReplies: function(_arg) { var array, boardID, bq, capcodeReplies, capcodeType, generateCapcodeReplies, html, root, threadID; + boardID = _arg.boardID, threadID = _arg.threadID, bq = _arg.bq, root = _arg.root, capcodeReplies = _arg.capcodeReplies; if (!capcodeReplies) { return; @@ -2043,6 +2110,7 @@ Get = { threadExcerpt: function(thread) { var OP, excerpt, _ref; + OP = thread.OP; excerpt = ((_ref = OP.info.subject) != null ? _ref.trim() : void 0) || OP.info.comment.replace(/\n+/g, ' // ') || Conf['Anonymize'] && 'Anonymous' || $('.nameBlock', OP.nodes.info).textContent.trim(); if (excerpt.length > 70) { @@ -2058,6 +2126,7 @@ }, postFromRoot: function(root) { var boardID, index, link, post, postID; + link = $('a[title="Highlight this post"]', root); boardID = link.pathname.split('/')[1]; postID = link.hash.slice(2); @@ -2077,6 +2146,7 @@ }, postDataFromLink: function(link) { var boardID, path, postID, threadID, _ref; + if (link.hostname === 'boards.4chan.org') { path = link.pathname.split('/'); boardID = path[1]; @@ -2094,6 +2164,7 @@ }, allQuotelinksLinkingTo: function(post) { var ID, quote, quotedPost, quotelinks, quoterPost, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3; + quotelinks = []; _ref = g.posts; for (ID in _ref) { @@ -2122,12 +2193,14 @@ } return quotelinks.filter(function(quotelink) { var boardID, postID, _ref4; + _ref4 = Get.postDataFromLink(quotelink), boardID = _ref4.boardID, postID = _ref4.postID; return boardID === post.board.ID && postID === post.ID; }); }, postClone: function(boardID, threadID, postID, root, context) { var post, url; + if (post = g.posts["" + boardID + "." + postID]) { Get.insert(post, root, context); return; @@ -2150,6 +2223,7 @@ }, insert: function(post, root, context) { var clone, nodes; + if (!root.parentNode) { return; } @@ -2163,6 +2237,7 @@ }, fetchedPost: function(req, boardID, threadID, postID, root, context) { var board, post, posts, status, thread, url, _i, _len; + if (post = g.posts["" + boardID + "." + postID]) { Get.insert(post, root, context); return; @@ -2216,6 +2291,7 @@ }, archivedPost: function(req, boardID, postID, root, context) { var board, bq, comment, data, o, post, thread, threadID, _ref; + if (post = g.posts["" + boardID + "." + postID]) { Get.insert(post, root, context); return; @@ -2312,8 +2388,10 @@ UI = (function() { var Menu, dialog, drag, dragend, dragstart, hover, hoverend, hoverstart, touchend, touchmove; + dialog = function(id, position, html) { var child, el, move, _i, _len, _ref; + el = $.el('div', { className: 'dialog', innerHTML: html, @@ -2355,6 +2433,7 @@ Menu.prototype.makeMenu = function() { var menu; + menu = $.el('div', { className: 'dialog', id: 'menu', @@ -2369,6 +2448,7 @@ Menu.prototype.toggle = function(e, button, data) { var previousButton; + e.preventDefault(); e.stopPropagation(); if (currentMenu) { @@ -2386,6 +2466,7 @@ Menu.prototype.open = function(button, data) { var bLeft, bRect, bTop, bottom, cHeight, cWidth, entry, left, mRect, menu, right, style, top, _i, _len, _ref, _ref1, _ref2; + menu = this.makeMenu(); currentMenu = menu; lastToggledButton = button; @@ -2424,6 +2505,7 @@ Menu.prototype.insertEntry = function(entry, parent, data) { var subEntry, submenu, _i, _len, _ref; + if (typeof entry.open === 'function') { if (!entry.open(data)) { return; @@ -2457,6 +2539,7 @@ Menu.prototype.findNextEntry = function(entry, direction) { var entries; + entries = __slice.call(entry.parentNode.children); entries.sort(function(first, second) { return +(first.style.order || first.style.webkitOrder) - +(second.style.order || second.style.webkitOrder); @@ -2466,6 +2549,7 @@ Menu.prototype.keybinds = function(e) { var entry, next, nextPrev, subEntry, submenu; + entry = $('.focused', currentMenu); while (subEntry = $('.focused', entry)) { entry = subEntry; @@ -2511,6 +2595,7 @@ Menu.prototype.focus = function(entry) { var bottom, cHeight, cWidth, eRect, focused, left, right, sRect, style, submenu, top, _i, _len, _ref, _ref1, _ref2; + while (focused = $.x('parent::*/child::*[contains(@class,"focused")]', entry)) { $.rmClass(focused, 'focused'); } @@ -2538,6 +2623,7 @@ Menu.prototype.addEntry = function(e) { var entry; + entry = e.detail; if (entry.type !== this.type) { return; @@ -2548,6 +2634,7 @@ Menu.prototype.parseEntry = function(entry) { var el, style, subEntries, subEntry, _i, _len; + el = entry.el, subEntries = entry.subEntries; $.addClass(el, 'entry'); $.on(el, 'focus mouseover', (function(e) { @@ -2571,6 +2658,7 @@ })(); dragstart = function(e) { var el, isTouching, o, rect, screenHeight, screenWidth, _ref; + if (e.type === 'mousedown' && e.button !== 0) { return; } @@ -2609,6 +2697,7 @@ }; touchmove = function(e) { var touch, _i, _len, _ref; + _ref = e.changedTouches; for (_i = 0, _len = _ref.length; _i < _len; _i++) { touch = _ref[_i]; @@ -2620,6 +2709,7 @@ }; drag = function(e) { var bottom, clientX, clientY, left, right, style, top; + clientX = e.clientX, clientY = e.clientY; left = clientX - this.dx; left = left < 10 ? 0 : this.width - left < 10 ? null : left / this.screenWidth * 100 + '%'; @@ -2635,6 +2725,7 @@ }; touchend = function(e) { var touch, _i, _len, _ref; + _ref = e.changedTouches; for (_i = 0, _len = _ref.length; _i < _len; _i++) { touch = _ref[_i]; @@ -2656,6 +2747,7 @@ }; hoverstart = function(_arg) { var asapTest, cb, el, endEvents, latestEvent, o, root; + root = _arg.root, el = _arg.el, latestEvent = _arg.latestEvent, endEvents = _arg.endEvents, asapTest = _arg.asapTest, cb = _arg.cb; o = { root: root, @@ -2684,6 +2776,7 @@ }; hover = function(e) { var clientX, clientY, height, left, right, style, top, _ref; + this.latestEvent = e; height = this.el.offsetHeight; clientX = e.clientX, clientY = e.clientY; @@ -2726,6 +2819,7 @@ }, node: function() { var email, name, tripcode, _ref; + if (this.info.capcode || this.isClone) { return; } @@ -2752,6 +2846,7 @@ filters: {}, init: function() { var boards, err, filter, hl, key, op, regexp, stub, top, _i, _len, _ref, _ref1, _ref2, _ref3, _ref4; + if (g.VIEW === 'catalog' || !Conf['Filter']) { return; } @@ -2788,6 +2883,7 @@ op = ((_ref2 = filter.match(/[^t]op:(yes|no|only)/)) != null ? _ref2[1] : void 0) || 'yes'; stub = (function() { var _ref3; + switch ((_ref3 = filter.match(/stub:(yes|no)/)) != null ? _ref3[1] : void 0) { case 'yes': return true; @@ -2818,6 +2914,7 @@ }, createFilter: function(regexp, op, stub, hl, top) { var settings, test; + test = typeof regexp === 'string' ? function(value) { return regexp === value; } : function(value) { @@ -2841,6 +2938,7 @@ }, node: function() { var filter, firstThread, key, result, thisThread, value, _i, _len, _ref; + if (this.isClone) { return; } @@ -2952,6 +3050,7 @@ menu: { init: function() { var div, entry, type, _i, _len, _ref; + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Filter']) { return; } @@ -2977,6 +3076,7 @@ }, createSubEntry: function(text, type) { var el; + el = $.el('a', { href: 'javascript:;', textContent: text @@ -2987,6 +3087,7 @@ el: el, open: function(post) { var value; + value = Filter[type](post); return value !== false; } @@ -2994,6 +3095,7 @@ }, makeFilter: function() { var re, type, value; + type = this.dataset.type; value = Filter[type](Filter.menu.post); re = ['uniqueID', 'MD5'].contains(type) ? value : value.replace(/\/|\\|\^|\$|\n|\.|\(|\)|\{|\}|\[|\]|\?|\*|\+|\|/g, function(c) { @@ -3008,6 +3110,7 @@ re = ['uniqueID', 'MD5'].contains(type) ? "/" + re + "/" : "/^" + re + "$/"; return $.get(type, Conf[type], function(item) { var save, section, select, ta, tl; + save = item[type]; save = save ? "" + save + "\n" + re : re; $.set(type, save); @@ -3041,6 +3144,7 @@ }, node: function() { var data; + if (!this.isReply || this.isClone) { return; } @@ -3064,6 +3168,7 @@ menu: { init: function() { var apply, div, hideStubLink, makeStub, replies, thisPost; + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Reply Hiding Link']) { return; } @@ -3134,6 +3239,7 @@ order: 20, open: function(post) { var data; + if (!post.isReply || post.isClone || !post.isHidden) { return false; } @@ -3165,6 +3271,7 @@ order: 15, open: function(post) { var data; + if (!post.isReply || post.isClone || !post.isHidden) { return false; } @@ -3181,6 +3288,7 @@ }, hide: function() { var makeStub, parent, post, replies, thisPost; + parent = this.parentNode; thisPost = $('input[name=thisPost]', parent).checked; replies = $('input[name=replies]', parent).checked; @@ -3199,6 +3307,7 @@ }, show: function() { var data, parent, post, replies, thisPost; + parent = this.parentNode; thisPost = $('input[name=thisPost]', parent).checked; replies = $('input[name=replies]', parent).checked; @@ -3222,6 +3331,7 @@ }, hideStub: function() { var post; + post = PostHiding.menu.post; post.nodes.root.hidden = true; $.event('CloseMenu'); @@ -3229,6 +3339,7 @@ }, makeButton: function(post, type) { var a; + a = $.el('a', { className: "" + type + "-reply-button", innerHTML: " " + (type === 'hide' ? '-' : '+') + " ", @@ -3239,6 +3350,7 @@ }, saveHiddenState: function(post, isHiding, thisPost, makeStub, hideRecursively) { var data; + data = { boardID: post.board.ID, threadID: post.thread.ID, @@ -3257,12 +3369,14 @@ }, toggle: function() { var post; + post = Get.postFromNode(this); PostHiding[(post.isHidden ? 'show' : 'hide')](post); return PostHiding.saveHiddenState(post, post.isHidden); }, hide: function(post, makeStub, hideRecursively) { var a, button, postInfo, quotelink, _i, _len, _ref; + if (makeStub == null) { makeStub = Conf['Stubs']; } @@ -3297,6 +3411,7 @@ }, show: function(post, showRecursively) { var quotelink, _i, _len, _ref; + if (showRecursively == null) { showRecursively = Conf['Recursive Hiding']; } @@ -3332,6 +3447,7 @@ }, node: function() { var i, obj, quote, recursive, _i, _j, _len, _len1, _ref, _ref1; + if (this.isClone) { return; } @@ -3349,6 +3465,7 @@ }, add: function() { var args, obj, post, recursive, _base, _name; + recursive = arguments[0], post = arguments[1], args = 3 <= arguments.length ? __slice.call(arguments, 2) : []; obj = (_base = Recursive.recursives)[_name = post.fullID] || (_base[_name] = { recursives: [], @@ -3359,6 +3476,7 @@ }, rm: function(recursive, post) { var i, obj, rec, _i, _len, _ref; + if (!(obj = Recursive.recursives[post.fullID])) { return; } @@ -3373,6 +3491,7 @@ }, apply: function() { var ID, args, fullID, post, recursive, _ref; + recursive = arguments[0], post = arguments[1], args = 3 <= arguments.length ? __slice.call(arguments, 2) : []; fullID = post.fullID; _ref = g.posts; @@ -3399,6 +3518,7 @@ }, node: function() { var data; + if (data = ThreadHiding.db.get({ boardID: this.board.ID, threadID: this.ID @@ -3412,6 +3532,7 @@ }, syncCatalog: function() { var hiddenThreads, hiddenThreadsOnCatalog, threadID; + hiddenThreads = ThreadHiding.db.get({ boardID: g.BOARD.ID, defaultValue: {} @@ -3438,6 +3559,7 @@ cleanCatalog: function(hiddenThreadsOnCatalog) { return $.cache("//api.4chan.org/" + g.BOARD + "/threads.json", function() { var page, thread, threads, _i, _j, _len, _len1, _ref, _ref1; + if (this.status !== 200) { return; } @@ -3463,6 +3585,7 @@ menu: { init: function() { var apply, div, hideStubLink, makeStub; + if (g.VIEW !== 'index' || !Conf['Menu'] || !Conf['Thread Hiding Link']) { return; } @@ -3484,6 +3607,7 @@ order: 20, open: function(_arg) { var isReply, thread; + thread = _arg.thread, isReply = _arg.isReply; if (isReply || thread.isHidden) { return false; @@ -3511,6 +3635,7 @@ order: 20, open: function(_arg) { var isReply, thread; + thread = _arg.thread, isReply = _arg.isReply; if (isReply || !thread.isHidden) { return false; @@ -3530,6 +3655,7 @@ order: 15, open: function(_arg) { var isReply, thread; + thread = _arg.thread, isReply = _arg.isReply; if (isReply || !thread.isHidden) { return false; @@ -3540,6 +3666,7 @@ }, hide: function() { var makeStub, thread; + makeStub = $('input', this.parentNode).checked; thread = ThreadHiding.menu.thread; ThreadHiding.hide(thread, makeStub); @@ -3548,6 +3675,7 @@ }, show: function() { var thread; + thread = ThreadHiding.menu.thread; ThreadHiding.show(thread); ThreadHiding.saveHiddenState(thread); @@ -3555,6 +3683,7 @@ }, hideStub: function() { var thread; + thread = ThreadHiding.menu.thread; ThreadHiding.hide(thread, false); $.event('CloseMenu'); @@ -3562,6 +3691,7 @@ }, makeButton: function(thread, type) { var a; + a = $.el('a', { className: "" + type + "-thread-button", innerHTML: " " + (type === 'hide' ? '-' : '+') + " ", @@ -3573,6 +3703,7 @@ }, saveHiddenState: function(thread, makeStub) { var hiddenThreadsOnCatalog; + hiddenThreadsOnCatalog = JSON.parse(localStorage.getItem("4chan-hide-t-" + g.BOARD)) || {}; if (thread.isHidden) { ThreadHiding.db.set({ @@ -3605,6 +3736,7 @@ }, hide: function(thread, makeStub) { var OP, a, numReplies, opInfo, span, threadRoot; + if (makeStub == null) { makeStub = Conf['Stubs']; } @@ -3628,6 +3760,7 @@ }, show: function(thread) { var threadRoot; + if (thread.stub) { $.rm(thread.stub); delete thread.stub; @@ -3640,6 +3773,7 @@ QuoteBacklink = { init: function() { var format; + if (g.VIEW === 'catalog' || !Conf['Quote Backlinks']) { return; } @@ -3657,6 +3791,7 @@ }, firstNode: function() { var a, clone, container, containers, frag, link, post, quote, _i, _j, _k, _len, _len1, _len2, _ref, _ref1; + if (this.isClone || !this.quotes.length) { return; } @@ -3694,6 +3829,7 @@ }, secondNode: function() { var container; + if (this.isClone && (this.origin.isReply || Conf['OP Backlinks'])) { this.nodes.backlinkContainer = $('.container', this.nodes.info); return; @@ -3707,6 +3843,7 @@ }, getContainer: function(id) { var _base; + return (_base = this.containers)[id] || (_base[id] = $.el('span', { className: 'container' })); @@ -3729,6 +3866,7 @@ }, node: function() { var board, boardID, quotelink, thread, threadID, _i, _len, _ref, _ref1, _ref2; + if (this.isClone && this.thread === this.context.thread) { return; } @@ -3758,6 +3896,7 @@ if (Conf['Quote Hash Navigation']) { this.node = function() { var link, _i, _len, _ref; + _ref = this.nodes.quotelinks.concat(__slice.call(this.nodes.backlinks)); for (_i = 0, _len = _ref.length; _i < _len; _i++) { link = _ref[_i]; @@ -3770,6 +3909,7 @@ } else { this.node = function() { var link, _i, _len, _ref; + _ref = this.nodes.quotelinks.concat(__slice.call(this.nodes.backlinks)); for (_i = 0, _len = _ref.length; _i < _len; _i++) { link = _ref[_i]; @@ -3796,6 +3936,7 @@ }, toggle: function(e) { var boardID, context, postID, threadID, _ref; + if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) { return; } @@ -3821,6 +3962,7 @@ }, add: function(quotelink, boardID, threadID, postID, context) { var inline, isBacklink, post, qroot, root; + isBacklink = $.hasClass(quotelink, 'backlink'); inline = $.el('div', { id: "i" + postID, @@ -3845,6 +3987,7 @@ }, rm: function(quotelink, boardID, threadID, postID, context) { var el, inlined, isBacklink, post, qroot, root, _ref; + isBacklink = $.hasClass(quotelink, 'backlink'); root = QuoteInline.findRoot(quotelink, isBacklink); root = $.x("following-sibling::div[@id='i" + postID + "'][1]", root); @@ -3886,6 +4029,7 @@ }, node: function() { var boardID, fullID, i, postID, quotelink, quotelinks, quotes, _ref; + if (this.isClone && this.thread === this.context.thread) { return; } @@ -3928,6 +4072,7 @@ }, node: function() { var link, _i, _len, _ref; + _ref = this.nodes.quotelinks.concat(__slice.call(this.nodes.backlinks)); for (_i = 0, _len = _ref.length; _i < _len; _i++) { link = _ref[_i]; @@ -3936,6 +4081,7 @@ }, mouseover: function(e) { var boardID, clone, origin, post, postID, posts, qp, quote, quoterID, threadID, _i, _j, _len, _len1, _ref, _ref1; + if ($.hasClass(this, 'inlined')) { return; } @@ -3979,6 +4125,7 @@ }, mouseout: function() { var clone, post, root, _i, _len, _ref; + if (!(root = this.el.firstElementChild)) { return; } @@ -4008,6 +4155,7 @@ }, node: function() { var boardID, postID, quotelink, _i, _len, _ref, _ref1, _ref2; + if (this.isClone) { return; } @@ -4030,6 +4178,7 @@ QuoteThreading = { init: function() { var input; + if (!(Conf['Quote Threading'] && g.VIEW === 'thread')) { return; } @@ -4052,6 +4201,7 @@ }, setup: function() { var ID, post, posts; + $.off(d, '4chanXInitFinished', QuoteThreading.setup); posts = g.posts; for (ID in posts) { @@ -4064,6 +4214,7 @@ }, node: function() { var ID, fullID, keys, len, post, posts, qid, quote, quotes, uniq, _i, _len; + if (this.isClone || !QuoteThreading.enabled || this.thread.OP === this) { return; } @@ -4093,6 +4244,7 @@ }, nodeinsert: function() { var bottom, height, qpost, qroot, threadContainer, top, _ref; + qpost = g.posts[this.threaded]; delete this.threaded; delete this.cb; @@ -4121,6 +4273,7 @@ }, toggle: function() { var container, containers, node, post, replies, reply, thread, _i, _j, _k, _len, _len1, _len2, _ref; + thread = $('.thread'); replies = $$('.thread > .replyContainer, .threadContainer > .replyContainer', thread); QuoteThreading.enabled = this.checked; @@ -4137,6 +4290,7 @@ } else { replies.sort(function(a, b) { var aID, bID; + aID = Number(a.id.slice(2)); bID = Number(b.id.slice(2)); return aID - bID; @@ -4157,6 +4311,7 @@ }, kb: function() { var control; + control = $.id('threadingControl'); return control.click(); } @@ -4183,6 +4338,7 @@ }, node: function() { var quotelink, _i, _len, _ref; + if (this.isClone) { return; } @@ -4206,6 +4362,7 @@ cb: { seek: function(type) { var highlight, post, posts, result, str; + if (!(Conf['Mark Quotes of You'] && Conf['Quick Reply'])) { return; } @@ -4261,6 +4418,7 @@ }, node: function() { var deadlink, _i, _len, _ref; + _ref = $$('.deadlink', this.nodes.comment); for (_i = 0, _len = _ref.length; _i < _len; _i++) { deadlink = _ref[_i]; @@ -4275,6 +4433,7 @@ }, parseDeadlink: function(deadlink) { var a, boardID, m, post, postID, quote, quoteID, redirect, _ref; + if ($.hasClass(deadlink.parentNode, 'prettyprint')) { Quotify.fixDeadlink(deadlink); return; @@ -4367,6 +4526,7 @@ }, node: function() { var data, el, end, endNode, i, index, items, length, link, links, node, result, saved, snapshot, space, test, word, _i, _len, _ref; + if (this.isClone) { if (Conf['Embedding']) { i = 0; @@ -4443,6 +4603,7 @@ }, makeRange: function(startNode, endNode, startOffset, endOffset) { var range; + range = document.createRange(); range.setStart(startNode, startOffset); range.setEnd(endNode, endOffset); @@ -4450,6 +4611,7 @@ }, makeLink: function(range) { var a, char, i, text; + text = range.toString(); i = 0; while (/[(\[{<>]/.test(text.charAt(i))) { @@ -4495,6 +4657,7 @@ }, services: function(link) { var href, key, match, type, _ref; + href = link.href; _ref = Linkify.types; for (key in _ref) { @@ -4507,6 +4670,7 @@ }, embed: function(data) { var embed, href, key, link, name, options, uid, value, _ref; + key = data[0], uid = data[1], options = data[2], link = data[3]; href = link.href; embed = $.el('a', { @@ -4535,6 +4699,7 @@ }, title: function(data) { var embed, err, key, link, options, service, title, titles, uid; + key = data[0], uid = data[1], options = data[2], link = data[3], embed = data[4]; if (!(service = Linkify.types[key].title)) { return; @@ -4571,18 +4736,21 @@ cb: { toggle: function() { var string, _ref; + _ref = $.hasClass(this, "embedded") ? ['unembed', '(embed)'] : ['embed', '(unembed)'], string = _ref[0], this.textContent = _ref[1]; $.replace(this.previousElementSibling, Linkify.cb[string](this)); return $.toggleClass(this, 'embedded'); }, embed: function(a) { var el, style, type; + el = (type = Linkify.types[a.dataset.key]).el(a); el.style.cssText = (style = type.style) ? style : "border: 0; width: 640px; height: 390px"; return el; }, unembed: function(a) { var el; + el = $.el('a', { rel: 'nofollow noreferrer', target: 'blank', @@ -4595,6 +4763,7 @@ }, title: function(response, data) { var embed, key, link, options, service, text, uid; + key = data[0], uid = data[1], options = data[2], link = data[3], embed = data[4]; service = Linkify.types[key].title; switch (response.status) { @@ -4634,6 +4803,7 @@ regExp: /.*(?:gist.github.com.*\/)([^\/][^\/]*)$/, el: function(a) { var div; + return div = $.el('iframe', { src: "http://www.purplegene.com/script?url=https://gist.github.com/" + a.dataset.uid + ".js" }); @@ -4644,6 +4814,7 @@ }, text: function(_arg) { var file, files; + files = _arg.files; for (file in files) { if (files.hasOwnProperty(file)) { @@ -4691,6 +4862,7 @@ regExp: /.*(?:pastebin.com\/(?!u\/))([^#\&\?]*).*/, el: function(a) { var div; + return div = $.el('iframe', { src: "http://pastebin.com/embed_iframe.php?i=" + a.dataset.uid }); @@ -4701,6 +4873,7 @@ style: 'height: auto; width: 500px; display: inline-block;', el: function(a) { var div; + div = $.el('div', { className: "soundcloud", name: "soundcloud" @@ -4726,6 +4899,7 @@ style: "border: none; width: 640px; height: 360px;", el: function(a) { var channel, chapter, result, _; + if (result = /(\w+)\/(?:[a-z]\/)?(\d+)/i.exec(a.dataset.uid)) { _ = result[0], channel = result[1], chapter = result[2]; return $.el('object', { @@ -4797,6 +4971,7 @@ QR = { init: function() { var sc; + if (!Conf['Quick Reply']) { return; } @@ -4843,6 +5018,7 @@ }, initReady: function() { var link; + QR.postingIsEnabled = !!$.id('postForm'); if (!QR.postingIsEnabled) { return; @@ -4862,11 +5038,13 @@ $.before($.id('postForm'), link); $.on(d, 'QRGetSelectedPost', function(_arg) { var cb; + cb = _arg.detail; return cb(QR.selected); }); $.on(d, 'QRAddPreSubmitHook', function(_arg) { var cb; + cb = _arg.detail; return QR.preSubmitHooks.push(cb); }); @@ -4896,6 +5074,7 @@ }, open: function() { var err; + if (QR.nodes) { QR.nodes.el.hidden = false; QR.unhide(); @@ -4914,6 +5093,7 @@ }, close: function() { var post, _i, _len, _ref; + if (QR.req) { QR.abort(); return; @@ -4963,6 +5143,7 @@ }, error: function(err) { var el; + QR.open(); if (typeof err === 'string') { el = $.tn(err); @@ -4989,6 +5170,7 @@ }, notify: function(el) { var notice, notif; + notice = new Notice('warning', el); QR.notifications.push(notice); if (!Header.areNotificationsEnabled) { @@ -5012,6 +5194,7 @@ notifications: [], cleanNotifications: function() { var notification, _i, _len, _ref; + _ref = QR.notifications; for (_i = 0, _len = _ref.length; _i < _len; _i++) { notification = _ref[_i]; @@ -5021,6 +5204,7 @@ }, status: function() { var disabled, status, thread, value; + if (!QR.nodes) { return; } @@ -5042,6 +5226,7 @@ QR.persona.getPassword(); return $.get('QR.personas', Conf['QR.personas'], function(_arg) { var arr, item, personas, type, types, _i, _len, _ref; + personas = _arg['QR.personas']; types = { name: [], @@ -5061,6 +5246,7 @@ }, parseItem: function(item, types) { var boards, match, type, val, _ref, _ref1; + if (item[0] === '#') { return; } @@ -5089,6 +5275,7 @@ }, loadPersonas: function(type, arr) { var list, val, _i, _len; + list = $("#list-" + type, QR.nodes.el); for (_i = 0, _len = arr.length; _i < _len; _i++) { val = arr[_i]; @@ -5101,6 +5288,7 @@ }, getPassword: function() { var input, m; + if (!QR.persona.pwd) { QR.persona.pwd = (m = d.cookie.match(/4chan_pass=([^;]+)/)) ? decodeURIComponent(m[1]) : (input = $.id('postPassword')) ? input.value : $.id('delPassword').value; } @@ -5109,6 +5297,7 @@ get: function(cb) { return $.get('QR.persona', {}, function(_arg) { var persona; + persona = _arg['QR.persona']; return cb(persona); }); @@ -5116,6 +5305,7 @@ set: function(post) { return $.get('QR.persona', {}, function(_arg) { var persona; + persona = _arg['QR.persona']; persona = { name: post.name, @@ -5129,6 +5319,7 @@ cooldown: { init: function() { var board; + if (!Conf['Cooldown']) { return; } @@ -5170,6 +5361,7 @@ }, sync: function(cooldowns) { var id; + for (id in cooldowns) { QR.cooldown.cooldowns[id] = cooldowns[id]; } @@ -5177,6 +5369,7 @@ }, set: function(data) { var cooldown, delay, hasFile, isReply, isSage, post, req, start, type, upSpd; + if (!Conf['Cooldown']) { return; } @@ -5216,6 +5409,7 @@ }, count: function() { var cooldown, cooldowns, elapsed, hasFile, isReply, isSage, now, post, seconds, start, type, types, upSpd, upSpdAccuracy, update, _ref; + if (!Object.keys(QR.cooldown.cooldowns).length) { $["delete"]("" + g.BOARD + ".cooldown"); delete QR.cooldown.isCounting; @@ -5269,6 +5463,7 @@ }, quote: function(e) { var caretPos, com, index, post, range, s, sel, text, thread, _ref; + if (e != null) { e.preventDefault(); } @@ -5306,6 +5501,7 @@ }, characterCount: function() { var count, counter; + counter = QR.nodes.charCount; count = QR.nodes.com.textLength; counter.textContent = count; @@ -5314,6 +5510,7 @@ }, drag: function(e) { var toggle; + toggle = e.type === 'dragstart' ? $.off : $.on; toggle(d, 'dragover', QR.dragOver); return toggle(d, 'drop', QR.dropFile); @@ -5333,6 +5530,7 @@ }, paste: function(e) { var blob, files, item, _i, _len, _ref; + files = []; _ref = e.clipboardData.items; for (_i = 0, _len = _ref.length; _i < _len; _i++) { @@ -5356,6 +5554,7 @@ }, handleFiles: function(files) { var file, isSingle, max, _i, _len; + if (this !== QR) { files = __slice.call(this.files); this.value = null; @@ -5376,6 +5575,7 @@ }, handleFile: function(file, isSingle, max) { var post; + if (file.size > max) { QR.error("" + file.name + ": File too large (file: " + ($.bytesToString(file.size)) + ", max: " + ($.bytesToString(max)) + ")."); return; @@ -5410,9 +5610,6 @@ if (e.ctrlKey && e.type === 'click') { $.addClass(QR.nodes.filename, 'edit'); QR.nodes.filename.focus(); - if (e.keyCode && e.keyCode === 13) { - return; - } return $.on(QR.nodes.filename, 'blur', function() { return $.rmClass(QR.nodes.filename, 'edit'); }); @@ -5429,6 +5626,7 @@ this.select = __bind(this.select, this); var el, event, prev, _i, _len, _ref, _this = this; + el = $.el('a', { className: 'qr-preview', draggable: true, @@ -5482,6 +5680,7 @@ _Class.prototype.rm = function() { var index; + this["delete"](); index = QR.posts.indexOf(this); if (QR.posts.length === 1) { @@ -5501,6 +5700,7 @@ _Class.prototype.lock = function(lock) { var name, _i, _len, _ref; + if (lock == null) { lock = true; } @@ -5525,6 +5725,7 @@ _Class.prototype.select = function() { var rectEl, rectList; + if (QR.selected) { QR.selected.nodes.el.id = null; QR.selected.forceSave(); @@ -5541,6 +5742,7 @@ _Class.prototype.load = function() { var name, _i, _len, _ref; + _ref = ['thread', 'name', 'email', 'sub', 'com', 'filename']; for (_i = 0, _len = _ref.length; _i < _len; _i++) { name = _ref[_i]; @@ -5552,6 +5754,7 @@ _Class.prototype.save = function(input) { var name, _ref; + if (input.type === 'checkbox') { this.spoiler = input.checked; return; @@ -5582,6 +5785,7 @@ _Class.prototype.forceSave = function() { var name, _i, _len, _ref; + if (this !== QR.selected) { return; } @@ -5611,9 +5815,11 @@ _Class.prototype.setThumbnail = function() { var fileURL, img, _this = this; + img = $.el('img'); img.onload = function() { var cv, height, s, width; + s = 90 * 2; if (_this.file.type === 'image/gif') { s *= 3; @@ -5664,6 +5870,7 @@ _Class.prototype.updateFilename = function() { var long; + long = "" + this.filename + " (" + this.filesize + ")\nCtrl+click to edit filename. Shift+click to clear."; this.nodes.el.title = long; if (this !== QR.selected) { @@ -5686,9 +5893,11 @@ _Class.prototype.pasteText = function(file) { var reader, _this = this; + reader = new FileReader(); reader.onload = function(e) { var text; + text = e.target.result; if (_this.com) { _this.com += "\n" + text; @@ -5727,6 +5936,7 @@ _Class.prototype.drop = function() { var el, index, newIndex, oldIndex, post; + $.rmClass(this, 'over'); if (!this.draggable) { return; @@ -5761,6 +5971,7 @@ ready: function() { var imgContainer, input, setLifetime, _this = this; + setLifetime = function(e) { return _this.lifetime = e.detail; }; @@ -5797,6 +6008,7 @@ }); $.get('captchas', [], function(_arg) { var captchas; + captchas = _arg.captchas; return _this.sync(captchas); }); @@ -5811,6 +6023,7 @@ }, getOne: function() { var captcha, challenge, response; + this.clear(); if (captcha = this.captchas.shift()) { challenge = captcha.challenge, response = captcha.response; @@ -5835,6 +6048,7 @@ }, save: function() { var response; + if (!(response = this.nodes.input.value.trim())) { return; } @@ -5849,6 +6063,7 @@ }, clear: function() { var captcha, i, now, _i, _len, _ref; + now = Date.now(); _ref = this.captchas; for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { @@ -5866,6 +6081,7 @@ }, load: function() { var challenge; + if (!this.nodes.challenge.firstChild) { return; } @@ -5878,6 +6094,7 @@ }, count: function() { var count; + count = this.captchas.length; this.nodes.input.placeholder = (function() { switch (count) { @@ -5910,6 +6127,7 @@ }, dialog: function() { var check, dialog, i, items, key, mimeTypes, name, nodes, thread, value, _ref; + QR.nodes = nodes = { el: dialog = UI.dialog('qr', 'top:0;right:0;', "
×
No selected file×+
") }; @@ -6015,6 +6233,7 @@ preSubmitHooks: [], submit: function(e) { var challenge, err, extra, filetag, hook, options, post, postData, response, textOnly, thread, threadID, _i, _len, _ref, _ref1; + if (e != null) { e.preventDefault(); } @@ -6128,6 +6347,7 @@ }, response: function() { var URL, ban, board, captchasCount, err, h1, isReply, m, notif, post, postID, postsCount, req, resDoc, threadID, _, _ref, _ref1; + req = QR.req; delete QR.req; post = QR.posts[0]; @@ -6241,6 +6461,7 @@ FappeTyme = { init: function() { var el, input; + if (!(Conf['Fappe Tyme'] || Conf['Werk Tyme']) || g.VIEW === 'catalog' || g.BOARD === 'f') { return; } @@ -6296,6 +6517,7 @@ Gallery = { init: function() { var el; + if (g.VIEW === 'catalog' || g.BOARD === 'f' || !Conf['Gallery']) { return; } @@ -6315,6 +6537,7 @@ }, node: function() { var _ref; + if (!((_ref = this.file) != null ? _ref.isImage : void 0)) { return; } @@ -6328,6 +6551,7 @@ }, build: function(image) { var cb, createSubEntry, dialog, el, file, files, i, key, menuButton, name, nodes, value, _i, _len, _ref, _ref1; + Gallery.images = []; nodes = Gallery.nodes = {}; nodes.el = dialog = $.el('div', { @@ -6388,15 +6612,18 @@ return nodes.total.textContent = --i; }, generateThumb: function(file) { - var double, thumb, title; + var double, post, thumb, title; + + post = Get.postFromNode(file); title = ($('.fileText a', file)).textContent; - thumb = ($('.fileThumb', file)).cloneNode(true); + thumb = post.file.thumb.parentNode; if (double = $('img + img', thumb)) { $.rm(double); } thumb.className = 'gal-thumb'; thumb.title = title; thumb.dataset.id = Gallery.images.length; + thumb.dataset.post = $('a[title="Highlight this post"]', post.nodes.info).href; thumb.firstElementChild.style.cssText = ''; $.on(thumb, 'click', Gallery.cb.open); Gallery.images.push(thumb); @@ -6405,6 +6632,7 @@ cb: { keybinds: function(e) { var cb, key; + if (!(key = Keybinds.keyCode(e))) { return; } @@ -6430,6 +6658,7 @@ }, open: function(e) { var el, img, name, nodes, rect, top; + if (e) { e.preventDefault(); } @@ -6446,7 +6675,7 @@ src: name.href = this.href, title: name.download = name.textContent = this.title }); - img.dataset.id = this.dataset.id; + $.extend(img.dataset, this.dataset); $.replace(nodes.current, img); nodes.count.textContent = +this.dataset.id + 1; nodes.current = img; @@ -6460,13 +6689,68 @@ return; } } - return nodes.thumbs.scrollTop += top; + nodes.thumbs.scrollTop += top; + return $.on(img, 'error', function() { + return Gallery.cb.error(img, thumb); + }); }, image: function(e) { e.preventDefault(); e.stopPropagation(); return Gallery.build(this); }, + error: function(img, thumb) { + var URL, post, revived, src; + + post = Get.postFromLink($.el('a', { + href: img.dataset.post + })); + delete post.file.fullImage; + src = this.src.split('/'); + if (src[2] === 'images.4chan.org') { + URL = Redirect.to('file', { + boardID: src[3], + filename: src[5] + }); + if (URL) { + thumb.href = URL; + if (Gallery.nodes.current !== img) { + return; + } + revived = $.el('img', { + src: URL, + title: img.title + }); + $.extend(revived.dataset, img.dataset); + $.replace(img, revived); + return; + } + if (g.DEAD || post.isDead || post.file.isDead) { + return; + } + } + return $.ajax("//api.4chan.org/" + post.board + "/res/" + post.thread + ".json", { + onload: function() { + var i, postObj; + + if (this.status !== 200) { + return; + } + i = 0; + while (postObj = JSON.parse(this.response).posts[i++]) { + if (postObj.no === post.ID) { + break; + } + } + if (!postObj.no) { + return post.kill(); + } + if (postObj.filedeleted) { + return post.kill(true); + } + } + }); + }, prev: function() { return Gallery.cb.open.call(Gallery.images[+Gallery.nodes.current.dataset.id - 1]); }, @@ -6492,6 +6776,7 @@ menu: { init: function() { var createSubEntry, el, name, subEntries, _i, _len, _ref; + if (g.VIEW === 'catalog' || !Conf['Gallery'] || Conf['Image Expansion']) { return; } @@ -6515,6 +6800,7 @@ }, createSubEntry: function(name) { var input, label; + label = $.el('label', { innerHTML: " " + name }); @@ -6550,6 +6836,7 @@ }, node: function() { var thumb, _ref; + if (!((_ref = this.file) != null ? _ref.isImage : void 0)) { return; } @@ -6574,6 +6861,7 @@ }, toggleAll: function() { var ID, file, func, post, _i, _len, _ref, _ref1; + $.event('CloseMenu'); if (ImageExpand.on = $.hasClass(ImageExpand.EAI, 'expand-all-shortcut')) { ImageExpand.EAI.className = 'contract-all-shortcut fourchanx-icon icon-resize-small'; @@ -6607,6 +6895,7 @@ }, toggle: function(post) { var headRect, rect, root, thumb, x, y; + thumb = post.file.thumb; if (!(post.file.isExpanded || $.hasClass(thumb, 'expanding'))) { ImageExpand.expand(post); @@ -6616,6 +6905,7 @@ root = post.nodes.root; rect = (Conf['Advance on contract'] ? (function() { var next; + next = root; while (next = $.x("following::div[contains(@class,'postContainer')][1]", next)) { if ($('.stub', next) || next.offsetHeight === 0) { @@ -6646,6 +6936,7 @@ }, expand: function(post, src) { var img, thumb; + thumb = post.file.thumb; if (post.isHidden || post.file.isExpanded || $.hasClass(thumb, 'expanding')) { return; @@ -6673,6 +6964,7 @@ }, completeExpand: function(post) { var prev, thumb; + thumb = post.file.thumb; if (!$.hasClass(thumb, 'expanding')) { return; @@ -6686,6 +6978,7 @@ prev = post.nodes.root.getBoundingClientRect(); return $.queueTask(function() { var curr; + $.addClass(post.nodes.root, 'expanded-image'); $.rmClass(post.file.thumb, 'expanding'); if (!(prev.top + prev.height <= 0)) { @@ -6697,6 +6990,7 @@ }, error: function() { var URL, post, src, timeoutID; + post = Get.postFromNode(this); $.rm(this); delete post.file.fullImage; @@ -6722,6 +7016,7 @@ return $.ajax("//api.4chan.org/" + post.board + "/res/" + post.thread + ".json", { onload: function() { var postObj, _i, _len, _ref; + if (this.status !== 200) { return; } @@ -6745,6 +7040,7 @@ menu: { init: function() { var conf, createSubEntry, el, name, subEntries, _ref; + if (g.VIEW === 'catalog' || !Conf['Image Expansion']) { return; } @@ -6768,6 +7064,7 @@ }, createSubEntry: function(name, desc) { var input, label; + label = $.el('label', { innerHTML: " " + name, title: desc @@ -6798,6 +7095,7 @@ }, node: function() { var _ref; + if (!((_ref = this.file) != null ? _ref.isImage : void 0)) { return; } @@ -6805,6 +7103,7 @@ }, mouseover: function(e) { var el, post; + post = Get.postFromNode(this); el = $.el('img', { id: 'ihover', @@ -6826,6 +7125,7 @@ error: function() { var URL, post, src, timeoutID, _this = this; + if (!doc.contains(this)) { return; } @@ -6850,6 +7150,7 @@ return $.ajax("//api.4chan.org/" + post.board + "/res/" + post.thread + ".json", { onload: function() { var postObj, _i, _len, _ref; + if (this.status !== 200) { return; } @@ -6875,6 +7176,7 @@ ImageLoader = { init: function() { var prefetch; + if (g.VIEW === 'catalog') { return; } @@ -6901,6 +7203,7 @@ }, node: function() { var URL, img, string, style, thumb, type, _ref, _ref1; + if (this.isClone || this.isHidden || this.thread.isHidden || !((_ref = this.file) != null ? _ref.isImage : void 0)) { return; } @@ -6922,6 +7225,7 @@ }, toggle: function() { var enabled, id, post, _ref; + enabled = Conf['prefetch'] = this.checked; if (enabled) { _ref = g.threads["" + g.BOARD.ID + "." + g.THREADID].posts; @@ -6945,6 +7249,7 @@ }, node: function() { var thumb, _ref; + if (this.isClone || !((_ref = this.file) != null ? _ref.isSpoiler : void 0)) { return; } @@ -6957,6 +7262,7 @@ Sauce = { init: function() { var err, link, links, _i, _len, _ref; + if (g.VIEW === 'catalog' || !Conf['Sauce']) { return; } @@ -6986,6 +7292,7 @@ }, createSauceLink: function(link) { var m, text; + link = link.replace(/%(T?URL|MD5|board)/ig, function(parameter) { switch (parameter) { case '%TURL': @@ -7006,6 +7313,7 @@ }, node: function() { var link, nodes, _i, _len, _ref; + if (this.isClone || !this.file) { return; } @@ -7022,6 +7330,7 @@ ArchiveLink = { init: function() { var div, entry, type, _i, _len, _ref; + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Archive Link']) { return; } @@ -7034,6 +7343,7 @@ order: 90, open: function(_arg) { var ID, board, thread; + ID = _arg.ID, thread = _arg.thread, board = _arg.board; return !!Redirect.to('thread', { postID: ID, @@ -7052,12 +7362,14 @@ }, createSubEntry: function(text, type) { var el, open; + el = $.el('a', { textContent: text, target: '_blank' }); open = type === 'post' ? function(_arg) { var ID, board, thread; + ID = _arg.ID, thread = _arg.thread, board = _arg.board; el.href = Redirect.to('thread', { postID: ID, @@ -7067,6 +7379,7 @@ return true; } : function(post) { var value; + value = Filter[type](post); if (!value) { return false; @@ -7089,6 +7402,7 @@ DeleteLink = { init: function() { var div, fileEl, fileEntry, postEl, postEntry; + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Delete Link']) { return; } @@ -7116,6 +7430,7 @@ el: fileEl, open: function(_arg) { var file; + file = _arg.file; if (!file || file.isDead) { return false; @@ -7131,6 +7446,7 @@ order: 40, open: function(post) { var node; + if (post.isDead || post.board.ID === 'q') { return false; } @@ -7145,6 +7461,7 @@ }, "delete": function() { var fileOnly, form, link, post; + post = DeleteLink.post; if (DeleteLink.cooldown.counting === post) { return; @@ -7174,6 +7491,7 @@ }, load: function(link, post, fileOnly, resDoc) { var msg, s; + if (resDoc.title === '4chan - Banned') { s = 'Banned!'; } else if (msg = resDoc.getElementById('errmsg')) { @@ -7194,6 +7512,7 @@ cooldown: { start: function(post, node) { var length, seconds, _ref; + if (!((_ref = QR.db) != null ? _ref.get({ boardID: post.board.ID, threadID: post.thread.ID, @@ -7227,6 +7546,7 @@ DownloadLink = { init: function() { var a; + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Download Link']) { return; } @@ -7240,6 +7560,7 @@ order: 100, open: function(_arg) { var file; + file = _arg.file; if (!file) { return false; @@ -7272,6 +7593,7 @@ }, makeButton: (function() { var a; + a = $.el('a', { className: 'menu-button brackets-wrap', innerHTML: '', @@ -7279,6 +7601,7 @@ }); return function() { var button; + button = a.cloneNode(true); $.on(button, 'click', Menu.toggle); return button; @@ -7286,6 +7609,7 @@ })(), toggle: function(e) { var post; + post = Get.postFromNode(this); return Menu.menu.toggle(e, this, post); } @@ -7294,6 +7618,7 @@ ReportLink = { init: function() { var a; + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Report Link']) { return; } @@ -7315,6 +7640,7 @@ }, report: function() { var id, post, set, url; + post = ReportLink.post; url = "//sys.4chan.org/" + post.board + "/imgboard.php?mode=report&no=" + post; id = Date.now(); @@ -7327,6 +7653,7 @@ init: function() { return $.ready(function() { var href; + Favicon.el = $('link[rel="shortcut icon"]', d.head); Favicon.el.type = 'image/x-icon'; href = Favicon.el.href; @@ -7400,6 +7727,7 @@ init: function() { var sc, _this = this; + if (g.VIEW !== 'thread' || !Conf['Thread Stats']) { return; } @@ -7428,6 +7756,7 @@ }, node: function() { var ID, fileCount, post, postCount, _ref; + postCount = 0; fileCount = 0; _ref = this.posts; @@ -7445,6 +7774,7 @@ }, onUpdate: function(e) { var fileCount, postCount, _ref; + if (e.detail[404]) { return; } @@ -7453,6 +7783,7 @@ }, update: function(postCount, fileCount) { var fileCountEl, postCountEl, thread; + thread = ThreadStats.thread, postCountEl = ThreadStats.postCountEl, fileCountEl = ThreadStats.fileCountEl; postCountEl.textContent = postCount; fileCountEl.textContent = fileCount; @@ -7477,6 +7808,7 @@ }, onThreadsLoad: function() { var page, pages, thread, _i, _j, _len, _len1, _ref; + if (!(Conf["Page Count in Stats"] && this.status === 200)) { return; } @@ -7500,6 +7832,7 @@ init: function() { var checked, conf, el, input, name, sc, settings, subEntries, _ref, _this = this; + if (g.VIEW !== 'thread' || !Conf['Thread Updater']) { return; } @@ -7649,6 +7982,7 @@ }, interval: function() { var val; + val = +this.value; if (val < 1) { val = 1; @@ -7658,6 +7992,7 @@ }, load: function() { var klass, req, text, _ref; + req = ThreadUpdater.req; switch (req.status) { case 200: @@ -7690,6 +8025,7 @@ }, getInterval: function() { var i, j; + i = ThreadUpdater.interval; j = Math.min(ThreadUpdater.outdateCount, 10); if (!d.hidden) { @@ -7699,12 +8035,14 @@ }, intervalShortcut: function() { var settings; + Settings.open('Advanced'); settings = $.id('fourchanx-settings'); return $('input[name=Interval]', settings).focus(); }, set: function(name, text, klass) { var el, node; + el = ThreadUpdater[name]; if (node = el.firstChild) { node.data = text; @@ -7717,6 +8055,7 @@ }, timeout: function() { var n; + ThreadUpdater.timeoutID = setTimeout(ThreadUpdater.timeout, 1000); if (!(n = --ThreadUpdater.seconds)) { return ThreadUpdater.update(); @@ -7729,6 +8068,7 @@ }, update: function() { var url; + if (!ThreadUpdater.online) { return; } @@ -7751,6 +8091,7 @@ }, updateThreadStatus: function(title, OP) { var icon, message, root, titleLC; + titleLC = title.toLowerCase(); if (ThreadUpdater.thread["is" + title] === !!OP[titleLC]) { return; @@ -7777,6 +8118,7 @@ }, parse: function(postObjects) { var ID, OP, count, deletedFiles, deletedPosts, files, index, key, node, num, post, postObject, posts, root, scroll, _i, _len, _ref; + OP = postObjects[0]; Build.spoilerRange[ThreadUpdater.thread.board] = OP.custom_spoiler; ThreadUpdater.updateThreadStatus('Sticky', OP); @@ -7862,6 +8204,7 @@ } $.queueTask(function() { var length, threadID; + threadID = ThreadUpdater.thread.ID; length = $$('.thread > .postContainer', ThreadUpdater.root).length; return Fourchan.parseThread(threadID, length - count, length); @@ -7882,6 +8225,7 @@ ThreadWatcher = { init: function() { var now, sc; + if (!Conf['Thread Watcher']) { return; } @@ -7914,6 +8258,7 @@ } $.get('WatchedThreads', null, function(_arg) { var WatchedThreads, boardID, data, threadID, threads, _ref; + WatchedThreads = _arg.WatchedThreads; if (!WatchedThreads) { return; @@ -7939,6 +8284,7 @@ }, node: function() { var toggler; + toggler = $.el('img', { className: 'watch-thread-link' }); @@ -7960,6 +8306,7 @@ } return $.get('AutoWatch', 0, function(_arg) { var AutoWatch, thread; + AutoWatch = _arg.AutoWatch; if (!(thread = g.BOARD.threads[AutoWatch])) { return; @@ -7975,6 +8322,7 @@ cb: { openAll: function() { var a, _i, _len, _ref; + if ($.hasClass(this, 'disabled')) { return; } @@ -7993,6 +8341,7 @@ }, pruneDeads: function() { var boardID, data, threadID, _i, _len, _ref, _ref1; + if ($.hasClass(this, 'disabled')) { return; } @@ -8016,11 +8365,13 @@ }, rm: function() { var boardID, threadID, _ref; + _ref = this.parentNode.dataset.fullID.split('.'), boardID = _ref[0], threadID = _ref[1]; return ThreadWatcher.rm(boardID, +threadID); }, post: function(e) { var board, postID, threadID, _ref; + _ref = e.detail, board = _ref.board, postID = _ref.postID, threadID = _ref.threadID; if (postID === threadID) { if (Conf['Auto Watch']) { @@ -8032,6 +8383,7 @@ }, threadUpdate: function(e) { var thread; + thread = e.detail.thread; if (!(e.detail[404] && ThreadWatcher.db.get({ boardID: thread.board.ID, @@ -8048,6 +8400,7 @@ }, fetchAllStatus: function() { var thread, threads, _i, _len; + if (!(threads = ThreadWatcher.getAll()).length) { return; } @@ -8059,6 +8412,7 @@ }, fetchStatus: function(_arg) { var boardID, data, fetchCount, threadID; + boardID = _arg.boardID, threadID = _arg.threadID, data = _arg.data; if (data.isDead) { return; @@ -8068,6 +8422,7 @@ return $.ajax("//api.4chan.org/" + boardID + "/res/" + threadID + ".json", { onloadend: function() { var status; + fetchCount.fetched++; if (fetchCount.fetched === fetchCount.fetching) { fetchCount.fetched = 0; @@ -8098,6 +8453,7 @@ }, getAll: function() { var all, boardID, data, threadID, threads, _ref; + all = []; _ref = ThreadWatcher.db.data.boards; for (boardID in _ref) { @@ -8118,6 +8474,7 @@ }, makeLine: function(boardID, threadID, data) { var div, fullID, href, link, x; + x = $.el('a', { textContent: '×', href: 'javascript:;' @@ -8148,6 +8505,7 @@ }, refresh: function() { var boardID, data, helper, list, nodes, refresher, thread, threadID, toggler, watched, _i, _j, _len, _len1, _ref, _ref1, _ref2, _ref3; + nodes = []; _ref = ThreadWatcher.getAll(); for (_i = 0, _len = _ref.length; _i < _len; _i++) { @@ -8177,6 +8535,7 @@ }, toggle: function(thread) { var boardID, threadID; + boardID = thread.board.ID; threadID = thread.ID; if (ThreadWatcher.db.get({ @@ -8190,6 +8549,7 @@ }, add: function(thread) { var boardID, data, threadID; + data = {}; boardID = thread.board.ID; threadID = thread.ID; @@ -8220,6 +8580,7 @@ }, convert: function(oldFormat) { var boardID, data, newFormat, threadID, threads; + newFormat = {}; for (boardID in oldFormat) { threads = oldFormat[boardID]; @@ -8236,6 +8597,7 @@ refreshers: [], init: function() { var menu; + if (!Conf['Thread Watcher']) { return; } @@ -8248,6 +8610,7 @@ }, addHeaderMenuEntry: function() { var entryEl; + if (g.VIEW !== 'thread') { return; } @@ -8264,6 +8627,7 @@ }); return this.refreshers.push(function() { var addClass, rmClass, text, _ref; + _ref = $('.current', ThreadWatcher.list) ? ['unwatch-thread', 'watch-thread', 'Unwatch thread'] : ['watch-thread', 'unwatch-thread', 'Watch thread'], addClass = _ref[0], rmClass = _ref[1], text = _ref[2]; $.addClass(entryEl, addClass); $.rmClass(entryEl, rmClass); @@ -8272,6 +8636,7 @@ }, addMenuEntries: function() { var cb, conf, entries, entry, name, refresh, subEntries, _i, _len, _ref, _ref1, _results; + entries = []; entries.push({ cb: ThreadWatcher.cb.openAll, @@ -8342,6 +8707,7 @@ }, createSubEntry: function(name, desc) { var entry, input; + entry = { type: 'thread watcher', el: $.el('label', { @@ -8393,6 +8759,7 @@ }, ready: function() { var ID, post, posts, _ref; + $.off(d, '4chanXInitFinished', Unread.ready); posts = []; _ref = Unread.thread.posts; @@ -8407,6 +8774,7 @@ }, scroll: function() { var checkPosition, hash, onload, post, posts, root; + if (!Conf['Scroll to Last Read Post']) { return; } @@ -8443,6 +8811,7 @@ }, sync: function() { var lastReadPost; + lastReadPost = Unread.db.get({ boardID: Unread.thread.board.ID, threadID: Unread.thread.ID, @@ -8461,6 +8830,7 @@ }, addPosts: function(posts) { var ID, data, post, _i, _len; + for (_i = 0, _len = posts.length; _i < _len; _i++) { post = posts[_i]; ID = post.ID; @@ -8488,6 +8858,7 @@ }, addPostQuotingYou: function(post) { var quotelink, _i, _len, _ref; + if (!QR.db) { return; } @@ -8503,6 +8874,7 @@ }, openNotification: function(post) { var name, notif; + if (!Header.areNotificationsEnabled) { return; } @@ -8528,6 +8900,7 @@ }, readSinglePost: function(post) { var i; + if ((i = Unread.posts.indexOf(post)) === -1) { return; } @@ -8543,6 +8916,7 @@ }, readArray: function(arr) { var i, post, _i, _len; + for (i = _i = 0, _len = arr.length; _i < _len; i = ++_i) { post = arr[i]; if (post.ID > Unread.lastReadPost) { @@ -8553,6 +8927,7 @@ }, read: $.debounce(50, function(e) { var ID, height, i, post, posts; + if (d.hidden || !Unread.posts.length) { return; } @@ -8605,6 +8980,7 @@ }), setLine: function(force) { var post; + if (!(d.hidden || force === true)) { return; } @@ -8617,6 +8993,7 @@ }, update: function(dontrepeat) { var count; + count = Unread.posts.length; if (Conf['Unread Count']) { d.title = "" + (Conf['Quoted Title'] && Unread.postsQuotingYou.length ? '(!) ' : '') + (count || !Conf['Hide Unread Count at (0)'] ? "(" + count + ") " : '') + (g.DEAD ? "/" + g.BOARD + "/ - 404" : "" + Unread.title); @@ -8643,6 +9020,7 @@ }, init: function() { var archive, boardID, boards, data, id, name, type, _i, _len, _ref, _ref1, _ref2; + _ref = Conf['selectedArchives']; for (boardID in _ref) { data = _ref[boardID]; @@ -8774,6 +9152,7 @@ }, to: function(dest, data) { var archive; + archive = (dest === 'search' ? Redirect.data.thread : Redirect.data[dest])[data.boardID]; if (!archive) { return ''; @@ -8782,6 +9161,7 @@ }, protocol: function(archive) { var protocol; + protocol = location.protocol; if (!archive[protocol.slice(0, -1)]) { protocol = protocol === 'https:' ? 'http:' : 'https:'; @@ -8790,6 +9170,7 @@ }, thread: function(archive, _arg) { var boardID, path, postID, threadID; + boardID = _arg.boardID, threadID = _arg.threadID, postID = _arg.postID; path = threadID ? "" + boardID + "/thread/" + threadID : "" + boardID + "/post/" + postID; if (archive.software === 'foolfuuka') { @@ -8802,6 +9183,7 @@ }, post: function(archive, _arg) { var URL, boardID, postID, protocol; + boardID = _arg.boardID, postID = _arg.postID; protocol = Redirect.protocol(archive); if (['Foolz', 'NSFW Foolz'].contains(archive.name)) { @@ -8813,11 +9195,13 @@ }, file: function(archive, _arg) { var boardID, filename; + boardID = _arg.boardID, filename = _arg.filename; return "" + (Redirect.protocol(archive)) + archive.domain + "/" + boardID + "/full_image/" + filename; }, search: function(archive, _arg) { var boardID, path, type, value; + boardID = _arg.boardID, type = _arg.type, value = _arg.value; type = type === 'name' ? 'username' : type === 'MD5' ? 'image' : type; value = encodeURIComponent(value); @@ -8836,6 +9220,7 @@ }, setup: function() { var btn, entry, psa; + $.off(d, '4chanXInitFinished', PSAHiding.setup); if (!(psa = $.id('globalMessage'))) { $.rmClass(doc, 'hide-announcement'); @@ -8864,6 +9249,7 @@ $.on(btn, 'click', PSAHiding.toggle); $.get('hiddenPSA', 0, function(_arg) { var hiddenPSA; + hiddenPSA = _arg.hiddenPSA; PSAHiding.sync(hiddenPSA); $.before(psa, btn); @@ -8873,6 +9259,7 @@ }, toggle: function(e) { var UTC; + if ($.hasClass(this, 'hide-announcement')) { UTC = +$.id('globalMessage').dataset.utc; $.set('hiddenPSA', UTC); @@ -8884,6 +9271,7 @@ }, sync: function(UTC) { var hr, psa; + psa = $.id('globalMessage'); psa.hidden = PSAHiding.btn.hidden = UTC && UTC >= +psa.dataset.utc ? true : false; if ((hr = psa.nextElementSibling) && hr.nodeName === 'HR') { @@ -8904,6 +9292,7 @@ }, ready: function() { var banner, child, children, i; + banner = $(".boardBanner"); children = banner.children; i = 0; @@ -8923,6 +9312,7 @@ cb: { toggle: (function() { var types; + types = { jpg: 227, png: 270, @@ -8930,6 +9320,7 @@ }; return function() { var num, type; + type = Object.keys(types)[Math.floor(3 * Math.random())]; num = Math.floor(types[type] * Math.random()); return this.src = "//static.4chan.org/image/title/" + num + "." + type; @@ -8949,6 +9340,7 @@ }, focus: function() { var items, string, string2; + this.textContent = this.innerHTML; string = "" + g.BOARD + "." + this.className; string2 = "" + string + ".orig"; @@ -8971,6 +9363,7 @@ }, custom: function(child) { var cachedTest, string; + cachedTest = child.innerHTML; string = "" + g.BOARD + "." + child.className; $.on(child, 'click keydown focus blur', function(e) { @@ -8978,6 +9371,7 @@ }); $.get(string, cachedTest, function(item) { var string2, title; + if (!(title = item[string])) { return; } @@ -9001,6 +9395,7 @@ CatalogLinks = { init: function() { var el, input; + if (!Conf['Catalog Links']) { return; } @@ -9024,12 +9419,14 @@ }, toggle: function() { var useCatalog; + $.event('CloseMenu'); $.set('Header catalog links', useCatalog = this.checked); return CatalogLinks.set(useCatalog); }, set: function(useCatalog) { var a, board, path, _i, _len, _ref; + path = useCatalog ? 'catalog' : ''; _ref = $$("#board-list a[href*=\"boards.4chan.org\"]:not(.catalog),\n#boardNavDesktopFoot a[href*=\"boards.4chan.org\"]"); for (_i = 0, _len = _ref.length; _i < _len; _i++) { @@ -9064,6 +9461,7 @@ }, node: function() { var rgb, span, style, uid; + if (this.isClone || !(uid = this.info.uniqueID)) { return; } @@ -9080,6 +9478,7 @@ }, compute: function(uid) { var hash, rgb; + if (IDColor.ids[uid]) { return IDColor.ids[uid]; } @@ -9090,6 +9489,7 @@ }, hash: function(uid) { var i, msg; + msg = 0; i = 0; while (i < 8) { @@ -9135,6 +9535,7 @@ }, node: function() { var dicestats, roll, _ref; + if (this.isClone || !(dicestats = (_ref = this.info.email) != null ? _ref.match(/dice[+\s](\d+)d(\d+)/) : void 0)) { return; } @@ -9146,6 +9547,7 @@ Emoji = { init: function() { var css, icon, name, pos, _ref; + if (!Conf['Emoji']) { return; } @@ -9215,6 +9617,7 @@ }, node: function() { var a; + if (a = $('.abbr > a:not([onclick])', this.nodes.comment)) { return $.on(a, 'click', ExpandComment.cb); } @@ -9226,6 +9629,7 @@ }, expand: function(post) { var a; + if (post.nodes.longComment && !post.nodes.longComment.parentNode) { $.replace(post.nodes.shortComment, post.nodes.longComment); post.nodes.comment = post.nodes.longComment; @@ -9241,6 +9645,7 @@ }, contract: function(post) { var a; + if (!post.nodes.shortComment) { return; } @@ -9251,6 +9656,7 @@ }, parse: function(req, a, post) { var callback, clone, comment, href, postObj, posts, quote, spoilerRange, status, _i, _j, _k, _len, _len1, _len2, _ref, _ref1; + status = req.status; if (![200, 304].contains(status)) { a.textContent = "Error " + req.statusText + " (" + status + ")"; @@ -9313,6 +9719,7 @@ }, node: function() { var a, files, posts, span, _ref; + if (!(span = $.x('following-sibling::span[contains(@class,"summary")][1]', this.OP.nodes.root))) { return; } @@ -9333,6 +9740,7 @@ }, toggle: function(thread) { var a, files, filesCount, inlined, num, post, posts, postsCount, reply, threadRoot, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3, _ref4; + threadRoot = thread.OP.nodes.root.parentNode; a = $('.summary', threadRoot); switch (thread.isExpanded) { @@ -9410,6 +9818,7 @@ }, parse: function(req, thread, a) { var filesCount, link, post, posts, postsCount, postsObj, postsRoot, reply, root, spoilerRange, _i, _len; + if (a.textContent[0] === '+') { return; } @@ -9473,6 +9882,7 @@ }, createFunc: function(format) { var code; + code = format.replace(/%(.)/g, function(s, c) { if (c in FileInfo.formatters) { return "' + FileInfo.formatters." + c + ".call(post) + '"; @@ -9484,6 +9894,7 @@ }, convertUnit: function(size, unit) { var i; + if (unit === 'B') { return "" + (size.toFixed()) + " Bytes"; } @@ -9514,6 +9925,7 @@ }, n: function() { var fullname, shortname; + fullname = this.file.name; shortname = Build.shortFilename(this.file.name, this.isReply); if (fullname === shortname) { @@ -9557,6 +9969,7 @@ Fourchan = { init: function() { var board; + if (g.VIEW === 'catalog') { return; } @@ -9578,6 +9991,7 @@ }, code: function() { var pre, _i, _len, _ref; + if (this.isClone) { return; } @@ -9606,11 +10020,13 @@ Keybinds = { init: function() { var init; + if (g.VIEW === 'catalog' || !Conf['Keybinds']) { return; } init = function() { var node, _i, _len, _ref; + $.off(d, '4chanXInitFinished', init); $.on(d, 'keydown', Keybinds.keydown); _ref = $$('[accesskey]'); @@ -9623,6 +10039,7 @@ }, keydown: function(e) { var form, key, notification, notifications, op, target, thread, threadRoot, _i, _len; + if (!(key = Keybinds.keyCode(e))) { return; } @@ -9803,6 +10220,7 @@ }, keyCode: function(e) { var kc, key; + key = (function() { switch (kc = e.keyCode) { case 8: @@ -9858,6 +10276,7 @@ }, tags: function(tag, ta) { var range, selEnd, selStart, value; + value = ta.value; selStart = ta.selectionStart; selEnd = ta.selectionEnd; @@ -9868,11 +10287,13 @@ }, sage: function() { var isSage; + isSage = /sage/i.test(QR.nodes.email.value); return QR.nodes.email.value = isSage ? "" : "sage"; }, img: function(thread, all) { var post; + if (all) { return ImageExpand.cb.toggleAll(); } else { @@ -9882,6 +10303,7 @@ }, open: function(thread, tab) { var url; + if (g.VIEW !== 'index') { return; } @@ -9894,6 +10316,7 @@ }, hl: function(delta, thread) { var axe, headRect, next, postEl, rect, replies, reply, root, topMargin, _i, _len; + if (!delta) { if (postEl = $('.reply.highlight', thread)) { $.rmClass(postEl, 'highlight'); @@ -9953,6 +10376,7 @@ Nav = { init: function() { var append, next, prev, span; + switch (g.VIEW) { case 'index': if (!Conf['Index Navigation']) { @@ -10003,6 +10427,7 @@ }, getThread: function(full) { var headRect, i, rect, thread, threads, topMargin, _i, _len; + if (Conf['Bottom header'] || !Conf['Fixed Header']) { topMargin = 0; } else { @@ -10028,6 +10453,7 @@ }, scroll: function(delta) { var i, rect, thread, threads, top, topMargin, _ref, _ref1; + _ref = Nav.getThread(true), threads = _ref[0], thread = _ref[1], i = _ref[2], rect = _ref[3], topMargin = _ref[4]; top = rect.top - topMargin; if ((delta === -1 && top > -5) || (delta === +1 && top < 5)) { @@ -10052,6 +10478,7 @@ }, node: function() { var dateEl; + if (this.isClone) { return; } @@ -10061,6 +10488,7 @@ }, relative: function(diff, now, date) { var days, months, number, rounded, unit, years; + unit = (number = diff / $.DAY) >= 1 ? (years = now.getYear() - date.getYear(), months = now.getMonth() - date.getMonth(), days = now.getDate() - date.getDate(), years > 1 ? (number = years - (months < 0 || months === 0 && days < 0), 'year') : years === 1 && (months > 0 || months === 0 && days >= 0) ? (number = years, 'year') : (months = (months + 12) % 12) > 1 ? (number = months - (days < 0), 'month') : months === 1 && days >= 0 ? (number = months, 'month') : 'day') : (number = diff / $.HOUR) >= 1 ? 'hour' : (number = diff / $.MINUTE) >= 1 ? 'minute' : (number = Math.max(0, diff) / $.SECOND, 'second'); rounded = Math.round(number); if (rounded !== 1) { @@ -10071,6 +10499,7 @@ stale: [], flush: function() { var now, update, _i, _len, _ref; + if (d.hidden) { return; } @@ -10086,13 +10515,16 @@ }, setUpdate: function(post) { var markStale, setOwnTimeout, update; + setOwnTimeout = function(diff) { var delay; + delay = diff < $.MINUTE ? $.SECOND - (diff + $.SECOND / 2) % $.SECOND : diff < $.HOUR ? $.MINUTE - (diff + $.MINUTE / 2) % $.MINUTE : diff < $.DAY ? $.HOUR - (diff + $.HOUR / 2) % $.HOUR : $.DAY - (diff + $.DAY / 2) % $.DAY; return setTimeout(markStale, delay); }; update = function(now) { var date, diff, relative, singlePost, _i, _len, _ref; + date = post.info.date; diff = now - date; relative = RelativeDates.relative(diff, now, date); @@ -10133,6 +10565,7 @@ }, node: function(post) { var spoiler, spoilers, _i, _len; + spoilers = $$('s', this.nodes.comment); for (_i = 0, _len = spoilers.length; _i < _len; _i++) { spoiler = spoilers[_i]; @@ -10152,6 +10585,7 @@ }, ready: function() { var field; + field = $.id('recaptcha_response_field'); $.on(field, 'keydown', function(e) { if (e.keyCode === 8 && !field.value) { @@ -10160,6 +10594,7 @@ }); return $.on($('form'), 'submit', function(e) { var response; + e.preventDefault(); response = field.value.trim(); if (!/\s/.test(response)) { @@ -10189,6 +10624,7 @@ }, createFunc: function(format) { var code; + code = format.replace(/%([A-Za-z])/g, function(s, c) { if (c in Time.formatters) { return "' + Time.formatters." + c + ".call(date) + '"; @@ -10273,6 +10709,7 @@ Settings = { init: function() { var link, settings; + link = $.el('a', { className: 'settings-link fourchanx-icon icon-wrench', textContent: 'Settings', @@ -10282,6 +10719,7 @@ Header.addShortcut(link); $.get('previousversion', null, function(item) { var changelog, el, previous; + if (previous = item['previousversion']) { if (previous === g.VERSION) { return; @@ -10316,6 +10754,7 @@ }, open: function(openSection) { var dialog, html, link, links, overlay, section, sectionToOpen, _i, _len, _ref; + $.off(d, '4chanXInitFinished', Settings.open); if (Settings.dialog) { return; @@ -10368,6 +10807,7 @@ sections: [], addSection: function(title, open) { var hyphenatedTitle, _ref; + if (typeof title !== 'string') { _ref = title.detail, title = _ref.title, open = _ref.open; } @@ -10380,6 +10820,7 @@ }, openSection: function() { var section, selected; + if (selected = $('.tab-selected', Settings.dialog)) { $.rmClass(selected, 'tab-selected'); } @@ -10393,6 +10834,7 @@ }, main: function(section) { var arr, button, description, div, fs, hiddenNum, input, inputs, items, key, obj, _ref; + items = {}; inputs = {}; _ref = Config.main; @@ -10417,6 +10859,7 @@ } $.get(items, function(items) { var val; + for (key in items) { val = items[key]; inputs[key].checked = val; @@ -10431,6 +10874,7 @@ boards: {} }, function(item) { var ID, board, thread, _ref1; + _ref1 = item.hiddenThreads.boards; for (ID in _ref1) { board = _ref1[ID]; @@ -10445,6 +10889,7 @@ boards: {} }, function(item) { var ID, board, post, thread, _ref1; + _ref1 = item.hiddenPosts.boards; for (ID in _ref1) { board = _ref1[ID]; @@ -10464,6 +10909,7 @@ boards: {} }, function(item) { var boardID; + for (boardID in item.hiddenThreads.boards) { localStorage.removeItem("4chan-hide-t-" + boardID); } @@ -10474,6 +10920,7 @@ }, "export": function(now, data) { var a, db, _i, _len, _ref; + if (typeof now !== 'number') { now = Date.now(); data = { @@ -10508,6 +10955,7 @@ }, onImport: function() { var file, output, reader; + if (!(file = this.files[0])) { return; } @@ -10519,6 +10967,7 @@ reader = new FileReader(); reader.onload = function(e) { var data, err; + try { data = JSON.parse(e.target.result); Settings.loadSettings(data); @@ -10535,6 +10984,7 @@ }, loadSettings: function(data) { var key, val, version, _ref; + version = data.version.split('.'); if (version[0] === '2') { data = Settings.convertSettings(data, { @@ -10622,6 +11072,7 @@ }, convertSettings: function(data, map) { var newKey, prevKey; + for (prevKey in map) { newKey = map[prevKey]; if (newKey) { @@ -10633,6 +11084,7 @@ }, filter: function(section) { var select; + section.innerHTML = "
"; select = $('select', section); $.on(select, 'change', Settings.selectFilter); @@ -10640,6 +11092,7 @@ }, selectFilter: function() { var div, name, ta; + div = this.nextElementSibling; if ((name = this.value) !== 'guide') { $.rmAll(div); @@ -10659,6 +11112,7 @@ }, sauce: function(section) { var ta; + section.innerHTML = "
Sauce is disabled.
Lines starting with a # will be ignored.
You can specify a display text by appending ;text:[text] to the URL.
"; ta = $('textarea', section); $.get('sauces', Conf['sauces'], function(item) { @@ -10668,6 +11122,7 @@ }, advanced: function(section) { var archive, boardID, boardOptions, boardSelect, boards, data, event, input, inputs, item, items, name, row, rows, ta, table, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3, _ref4; + section.innerHTML = "
Archiver
404 Redirect is disabled.
Thread redirectionPost fetchingFile redirection
Disabled selections indicate that only one archive is available for that board and redirection type.
Custom Board Navigation
New lines will be converted into spaces.

In the following examples for /g/, g can be changed to a different board ID (a, b, etc...), the current board (current), or the Status/Twitter link (status, @).
Board link: g
Title link: g-title
Board link (Replace with title when on that board): g-replace
Full text link: g-full
Custom text link: g-text:\"Install Gentoo\"
Index-only link: g-index
Catalog-only link: g-catalog
External link: external-text:\"Google\",\"http://www.google.com\"
Combinations are possible: g-index-text:\"Technology Index\"
Full board list toggle: toggle-all

[ toggle-all ] [current-title] [g-title / a-title / jp-title] [x / wsg / h] [t-text:\"Piracy\"]
\n will give you
[ + ] [Technology] [Technology / Anime & Manga / Otaku Culture] [x / wsg / h] [Piracy]
\n if you are on /g/.\n
Time Formatting is disabled.
:
Supported format specifiers:
Day: %a, %A, %d, %e
Month: %m, %b, %B
Year: %y, %Y
Hour: %k, %H, %l, %I, %p, %P
Minute: %M
Second: %S
Quote Backlinks formatting is disabled.
:
File Info Formatting is disabled.
:
Link: %l (truncated), %L (untruncated), %T (Unix timestamp)
Original file name: %n (truncated), %N (untruncated), %t (Unix timestamp)
Spoiler indicator: %p
Size: %B (Bytes), %K (KB), %M (MB), %s (4chan default)
Resolution: %r (Displays 'PDF' for PDF files)
Quick Reply Personas is disabled.

\n One item per line.
\n Items will be added in the relevant input's auto-completion list.
\n Password items will always be used, since there is no password input.
\n Lines starting with a # will be ignored.\n

Unread Favicon is disabled.
Emoji is disabled.
\n Sage Icon:
\n Position:
Thread Updater is disabled.
\n Interval:
"; items = {}; inputs = {}; @@ -10687,6 +11142,7 @@ $.on(ta, 'change', $.cb.value); $.get(items, function(items) { var key, val; + for (key in items) { val = items[key]; if (['emojiPos'].contains(key)) { @@ -10757,6 +11213,7 @@ }); $.get('selectedArchives', Conf['selectedArchives'], function(_arg) { var option, selectedArchives, type; + selectedArchives = _arg.selectedArchives; for (boardID in selectedArchives) { data = selectedArchives[boardID]; @@ -10771,6 +11228,7 @@ }, addArchiveCell: function(boardID, data, type) { var archive, i, length, options, select, td; + length = data[type].length; td = $.el('td', { className: 'archive-cell' @@ -10800,8 +11258,10 @@ }, saveSelectedArchive: function() { var _this = this; + return $.get('selectedArchives', Conf['selectedArchives'], function(_arg) { var selectedArchives, _name; + selectedArchives = _arg.selectedArchives; (selectedArchives[_name = _this.dataset.boardid] || (selectedArchives[_name] = {}))[_this.dataset.type] = _this.value; return $.set('selectedArchives', selectedArchives); @@ -10812,6 +11272,7 @@ }, time: function() { var funk; + funk = Time.createFunc(this.value); return this.nextElementSibling.textContent = funk(Time, new Date()); }, @@ -10820,6 +11281,7 @@ }, fileInfo: function() { var data, funk; + data = { isReply: true, file: { @@ -10858,6 +11320,7 @@ }, keybinds: function(section) { var arr, input, inputs, items, key, tbody, tr, _ref; + section.innerHTML = "
Keybinds are disabled.
Allowed keys: a-z, 0-9, Ctrl, Shift, Alt, Meta, Enter, Esc, Up, Down, Right, Left.
Press Backspace to disable a keybind.
ActionsKeybinds
"; tbody = $('tbody', section); items = {}; @@ -10878,6 +11341,7 @@ } return $.get(items, function(items) { var val; + for (key in items) { val = items[key]; inputs[key].value = val; @@ -10886,6 +11350,7 @@ }, keybind: function(e) { var key; + if (e.keyCode === 9) { return; } @@ -10902,8 +11367,10 @@ Main = { init: function() { var db, flatten, _i, _len, _ref; + flatten = function(parent, obj) { var key, val; + if (obj instanceof Array) { Conf[parent] = obj[0]; } else if (typeof obj === 'object') { @@ -10945,6 +11412,7 @@ }, initFeatures: function() { var init, pathname, _ref; + pathname = location.pathname.split('/'); g.BOARD = new Board(pathname[1]); if ((_ref = g.BOARD.ID) === 'z' || _ref === 'fk') { @@ -10972,6 +11440,7 @@ case 'images.4chan.org': $.ready(function() { var URL; + if (Conf['404 Redirect'] && ['4chan - Temporarily Offline', '4chan - 404 Not Found'].contains(d.title)) { Redirect.init(); pathname = location.pathname.split('/'); @@ -10988,6 +11457,7 @@ } init = function(features) { var err, module, name; + for (name in features) { module = features[name]; try { @@ -11067,6 +11537,7 @@ }, initStyle: function() { var mainStyleSheet, setStyle, style, styleSheets, _ref; + $.off(d, '4chanMainInit', Main.initStyle); if (!Main.isThisPageLegit() || $.hasClass(doc, 'fourchan-x')) { return; @@ -11088,6 +11559,7 @@ styleSheets = $$('link[rel="alternate stylesheet"]', d.head); setStyle = function() { var styleSheet, _i, _len; + $.rmClass(doc, style); for (_i = 0, _len = styleSheets.length; _i < _len; _i++) { styleSheet = styleSheets[_i]; @@ -11109,6 +11581,7 @@ }, initReady: function() { var board, err, errors, href, passLink, postRoot, posts, styleSelector, thread, threadRoot, threads, _i, _j, _len, _len1, _ref, _ref1; + if (['4chan - Temporarily Offline', '4chan - 404 Not Found'].contains(d.title)) { if (Conf['404 Redirect'] && g.VIEW === 'thread') { href = Redirect.to('thread', { @@ -11176,6 +11649,7 @@ }, callbackNodes: function(klass, nodes) { var callback, err, errors, i, len, node, _i, _len, _ref; + len = nodes.length; _ref = klass.prototype.callbacks; for (_i = 0, _len = _ref.length; _i < _len; _i++) { @@ -11203,9 +11677,11 @@ }, callbackNodesDB: function(klass, nodes, cb) { var errors, func, i, len, node, queue, softTask; + queue = []; softTask = function() { var args, func, task; + task = queue.shift(); func = task[0]; args = Array.prototype.slice.call(task, 1); @@ -11224,6 +11700,7 @@ errors = null; func = function(node, i) { var callback, err, _i, _len, _ref; + _ref = klass.prototype.callbacks; for (_i = 0, _len = _ref.length; _i < _len; _i++) { callback = _ref[_i]; @@ -11257,6 +11734,7 @@ }, addCallback: function(e) { var Klass, obj; + obj = e.detail; if (typeof obj.callback.name !== 'string') { throw new Error("Invalid callback name: " + obj.callback.name); @@ -11276,6 +11754,7 @@ }, handleErrors: function(errors) { var div, error, logs, _i, _len; + if (!(errors instanceof Array)) { error = errors; } else if (errors.length === 1) { @@ -11290,6 +11769,7 @@ }); $.on(div.lastElementChild, 'click', function() { var _ref; + return _ref = this.textContent === 'show' ? ['hide', false] : ['show', true], this.textContent = _ref[0], logs.hidden = _ref[1], _ref; }); logs = $.el('div', { @@ -11303,6 +11783,7 @@ }, parseError: function(data) { var error, message; + Main.logError(data); message = $.el('div', { textContent: data.message @@ -11319,6 +11800,7 @@ }, isThisPageLegit: function() { var _ref; + if (!('thisPageIsLegit' in Main)) { Main.thisPageIsLegit = location.hostname === 'boards.4chan.org' && !$('link[href*="favicon-status.ico"]', d.head) && ((_ref = d.title) !== '4chan - Temporarily Offline' && _ref !== '4chan - Error' && _ref !== '504 Gateway Time-out'); } diff --git a/src/Images/Gallery.coffee b/src/Images/Gallery.coffee index e528941de..078a59995 100644 --- a/src/Images/Gallery.coffee +++ b/src/Images/Gallery.coffee @@ -104,14 +104,16 @@ Gallery = nodes.total.textContent = --i generateThumb: (file) -> + post = Get.postFromNode file title = ($ '.fileText a', file).textContent - thumb = ($ '.fileThumb', file).cloneNode true + thumb = post.file.thumb.parentNode if double = $ 'img + img', thumb $.rm double thumb.className = 'gal-thumb' thumb.title = title - thumb.dataset.id = Gallery.images.length + thumb.dataset.id = Gallery.images.length + thumb.dataset.post = $('a[title="Highlight this post"]', post.nodes.info).href thumb.firstElementChild.style.cssText = '' $.on thumb, 'click', Gallery.cb.open @@ -150,7 +152,7 @@ Gallery = src: name.href = @href title: name.download = name.textContent = @title - img.dataset.id = @dataset.id + $.extend img.dataset, @dataset $.replace nodes.current, img nodes.count.textContent = +@dataset.id + 1 nodes.current = img @@ -165,12 +167,47 @@ Gallery = return if top < 0 nodes.thumbs.scrollTop += top + + $.on img, 'error', -> + Gallery.cb.error img, thumb image: (e) -> e.preventDefault() e.stopPropagation() Gallery.build @ + error: (img, thumb) -> + post = Get.postFromLink $.el 'a', href: img.dataset.post + delete post.file.fullImage + + src = @src.split '/' + if src[2] is 'images.4chan.org' + URL = Redirect.to 'file', + boardID: src[3] + filename: src[5] + if URL + thumb.href = URL + return unless Gallery.nodes.current is img + revived = $.el 'img', + src: URL + title: img.title + $.extend revived.dataset, img.dataset + $.replace img, revived + return + if g.DEAD or post.isDead or post.file.isDead + return + + # XXX CORS for images.4chan.org WHEN? + $.ajax "//api.4chan.org/#{post.board}/res/#{post.thread}.json", onload: -> + return if @status isnt 200 + i = 0 + while postObj = JSON.parse(@response).posts[i++] + break if postObj.no is post.ID + unless postObj.no + return post.kill() + if postObj.filedeleted + post.kill true + prev: -> Gallery.cb.open.call Gallery.images[+Gallery.nodes.current.dataset.id - 1] next: -> Gallery.cb.open.call Gallery.images[+Gallery.nodes.current.dataset.id + 1] toggle: -> (if Gallery.nodes then Gallery.cb.close else Gallery.build)()