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)()