diff --git a/CHANGELOG.md b/CHANGELOG.md index a890ab4f6..6b02503c3 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,11 @@ **MayhemYDG**: +- **New feature**: `Desktop Notifications` + - Enabled by default, but you will have to grant your browser permissions to display them or disable them altogether:
+ ![authorize or disable](img/changelog/3.9.0/0.png) + - Clicking on a notification will bring up the relevant tab. (Does not work on Firefox unfortunately, [see bug 874050](https://bugzilla.mozilla.org/show_bug.cgi?id=874050).) + - Notifications will appear when someone quotes you, clicking such notification will also scroll the thread to the relevant post. + - Notifications will appear for posting errors instead of alert popups. + - Opera does *not* support desktop notifications yet. ![filename editing](img/changelog/3.8.0/0.gif) diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index 81dec77ec..7950a0317 100644 --- a/builds/4chan-X.user.js +++ b/builds/4chan-X.user.js @@ -344,6 +344,7 @@ Array.prototype.indexOf = function(object) { var i; + i = this.length; while (i--) { if (this[i] === object) { @@ -362,6 +363,7 @@ $.extend = function(object, properties) { var key, val; + for (key in properties) { val = properties[key]; if (!properties.hasOwnProperty(key)) { @@ -379,6 +381,7 @@ $.ready = function(fc) { var cb; + if (d.readyState !== 'loading') { $.queueTask(fc); return; @@ -392,6 +395,7 @@ $.formData = function(form) { var fd, key, val; + if (form instanceof HTMLFormElement) { return new FormData(form); } @@ -411,6 +415,7 @@ $.extend = function(object, properties) { var key, val; + for (key in properties) { val = properties[key]; object[key] = val; @@ -419,9 +424,11 @@ $.ajax = (function() { var lastModified; + lastModified = {}; return function(url, options, extra) { var form, r, sync, type, upCallbacks, whenModified; + if (extra == null) { extra = {}; } @@ -444,9 +451,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); @@ -466,6 +475,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]; @@ -501,6 +511,7 @@ $.addStyle = function(css, id) { var style; + style = $.el('style', { id: id, textContent: css @@ -547,6 +558,7 @@ } else { return function(el) { var _ref; + return (_ref = el.parentNode) != null ? _ref.removeChild(el) : void 0; }; } @@ -554,6 +566,7 @@ $.rmAll = function(root) { var node; + while (node = root.firstChild) { root.removeChild(node); } @@ -569,6 +582,7 @@ $.nodes = function(nodes) { var frag, node, _i, _len; + if (!(nodes instanceof Array)) { return nodes; } @@ -602,6 +616,7 @@ $.el = function(tag, properties) { var el; + el = d.createElement(tag); if (properties) { $.extend(el, properties); @@ -611,6 +626,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]; @@ -620,6 +636,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]; @@ -641,6 +658,7 @@ $.debounce = function(wait, fn) { var args, exec, lastCall, that, timeout; + lastCall = 0; timeout = null; that = null; @@ -662,9 +680,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); @@ -687,6 +707,7 @@ $.globalEval = function(code) { var script; + script = $.el('script', { textContent: code }); @@ -696,6 +717,7 @@ $.bytesToString = function(size) { var unit; + unit = 0; while (size >= 1024) { size /= 1024; @@ -711,6 +733,7 @@ $.item = function(key, val) { var item; + item = {}; item[key] = val; return item; @@ -721,6 +744,7 @@ $.sync = (function() { $.on(window, 'storage', function(e) { var cb; + if (cb = $.syncing[e.key]) { return cb(JSON.parse(e.newValue)); } @@ -732,6 +756,7 @@ $["delete"] = function(keys) { var key, _i, _len; + if (!(keys instanceof Array)) { keys = [keys]; } @@ -745,6 +770,7 @@ $.get = function(key, val, cb) { var items; + if (typeof cb === 'function') { items = $.item(key, val); } else { @@ -763,6 +789,7 @@ $.set = (function() { var set; + set = function(key, val) { key = g.NAMESPACE + key; val = JSON.stringify(val); @@ -773,6 +800,7 @@ }; return function(keys, val) { var key; + if (typeof keys === 'string') { set(keys, val); return; @@ -840,6 +868,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) { @@ -915,6 +944,7 @@ Post.prototype.parseComment = function() { var bq, i, node, nodes, text; + bq = this.nodes.comment.cloneNode(true); nodes = $$('.abbr, .capcodeReplies, .exif, b', bq); i = 0; @@ -932,6 +962,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++) { @@ -942,6 +973,7 @@ Post.prototype.parseQuote = function(quotelink) { var fullID, match; + if (!(match = quotelink.href.match(/boards\.4chan\.org\/([^\/]+)\/res\/\d+#p(\d+)$/))) { return; } @@ -957,6 +989,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; } @@ -987,6 +1020,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) { @@ -1035,6 +1069,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'); @@ -1068,6 +1103,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++) { @@ -1085,6 +1121,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']; @@ -1172,6 +1209,7 @@ function DataBoard(key, sync, dontClean) { var init, _this = this; + this.key = key; this.onSync = __bind(this.onSync, this); this.data = Conf[key]; @@ -1195,6 +1233,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]; @@ -1215,6 +1254,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) { @@ -1230,6 +1270,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; @@ -1243,6 +1284,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) { @@ -1266,6 +1308,7 @@ DataBoard.prototype.clean = function() { var boardID, now, val, _ref; + _ref = this.data.boards; for (boardID in _ref) { val = _ref[boardID]; @@ -1285,8 +1328,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 === 404) { _this["delete"](boardID); } else if (e.target.status === 200) { @@ -1389,8 +1434,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); @@ -1428,6 +1475,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', @@ -1528,6 +1576,7 @@ }); $.ready(function() { var a, cs; + _this.footer = $.id('boardNavDesktopFoot'); if (a = $("a[href*='/" + g.BOARD + "/']", $.id('boardNavDesktopFoot'))) { a.className = 'current'; @@ -1562,6 +1611,7 @@ }), setBoardList: function() { var a, boardList, btn, fourchannav, fullBoardList; + fourchannav = $.id('boardNavDesktop'); if (a = $("a[href*='/" + g.BOARD + "/']", fourchannav)) { a.className = 'current'; @@ -1583,6 +1633,7 @@ }, generateBoardList: function(text) { var as, list, nodes; + list = $('#custom-board-list', Header.bar); $.rmAll(list); if (!text) { @@ -1591,6 +1642,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); } @@ -1641,6 +1693,7 @@ }, toggleBoardList: function() { var bar, custom, full, showBoardList; + bar = Header.bar; custom = $('#custom-board-list', bar); full = $('#full-board-list', bar); @@ -1676,6 +1729,7 @@ }, toggleLinkJustify: function() { var centered; + $.event('CloseMenu'); centered = this.nodeName === 'INPUT' ? this.checked : void 0; Header.setLinkJustify(centered); @@ -1719,6 +1773,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); @@ -1732,6 +1787,7 @@ }, toggleFooterVisibility: function() { var hide, message; + $.event('CloseMenu'); hide = this.nodeName === 'INPUT' ? this.checked : !!Header.footer.hidden; Header.setFooterVisibility(hide); @@ -1741,6 +1797,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); @@ -1753,12 +1810,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; } @@ -1769,6 +1828,7 @@ }, scrollToPost: function(post) { var headRect, top; + top = post.getBoundingClientRect().top; if (Conf['Fixed Header'] && !Conf['Bottom Header']) { headRect = Header.bar.getBoundingClientRect(); @@ -1778,6 +1838,7 @@ }, addShortcut: function(el) { var shortcut; + shortcut = $.el('span', { className: 'shortcut brackets-wrap' }); @@ -1789,6 +1850,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) { @@ -1798,6 +1860,7 @@ areNotificationsEnabled: false, enableDesktopNotifications: function() { var authorize, disable, el, notice, _ref; + if (!(window.Notification && Conf['Desktop Notifications'])) { return; } @@ -1833,6 +1896,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); @@ -1842,6 +1906,7 @@ }, postFromObject: function(data, boardID) { var o; + o = { postID: data.no, threadID: data.resto || data.no, @@ -1886,6 +1951,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/'; @@ -1984,6 +2050,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; @@ -2020,6 +2087,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) { @@ -2035,6 +2103,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); @@ -2054,6 +2123,7 @@ }, postDataFromLink: function(link) { var boardID, path, postID, threadID, _ref; + if (link.hostname === 'boards.4chan.org') { path = link.pathname.split('/'); boardID = path[1]; @@ -2071,6 +2141,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) { @@ -2099,12 +2170,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; @@ -2127,6 +2200,7 @@ }, insert: function(post, root, context) { var clone, nodes; + if (!root.parentNode) { return; } @@ -2140,6 +2214,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; @@ -2193,6 +2268,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; @@ -2289,8 +2365,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, @@ -2332,6 +2410,7 @@ Menu.prototype.makeMenu = function() { var menu; + menu = $.el('div', { className: 'dialog', id: 'menu', @@ -2346,6 +2425,7 @@ Menu.prototype.toggle = function(e, button, data) { var previousButton; + e.preventDefault(); e.stopPropagation(); if (currentMenu) { @@ -2363,6 +2443,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; @@ -2401,6 +2482,7 @@ Menu.prototype.insertEntry = function(entry, parent, data) { var subEntry, submenu, _i, _len, _ref; + if (typeof entry.open === 'function') { if (!entry.open(data)) { return; @@ -2434,6 +2516,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); @@ -2443,6 +2526,7 @@ Menu.prototype.keybinds = function(e) { var entry, next, nextPrev, subEntry, submenu; + entry = $('.focused', currentMenu); while (subEntry = $('.focused', entry)) { entry = subEntry; @@ -2488,6 +2572,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'); } @@ -2515,6 +2600,7 @@ Menu.prototype.addEntry = function(e) { var entry; + entry = e.detail; if (entry.type !== this.type) { return; @@ -2525,6 +2611,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) { @@ -2548,6 +2635,7 @@ })(); dragstart = function(e) { var el, isTouching, o, rect, screenHeight, screenWidth, _ref; + if (e.type === 'mousedown' && e.button !== 0) { return; } @@ -2586,6 +2674,7 @@ }; touchmove = function(e) { var touch, _i, _len, _ref; + _ref = e.changedTouches; for (_i = 0, _len = _ref.length; _i < _len; _i++) { touch = _ref[_i]; @@ -2597,6 +2686,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 + '%'; @@ -2612,6 +2702,7 @@ }; touchend = function(e) { var touch, _i, _len, _ref; + _ref = e.changedTouches; for (_i = 0, _len = _ref.length; _i < _len; _i++) { touch = _ref[_i]; @@ -2633,6 +2724,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, @@ -2667,6 +2759,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; @@ -2710,6 +2803,7 @@ }, node: function() { var email, name, tripcode, _ref; + if (this.info.capcode || this.isClone) { return; } @@ -2736,6 +2830,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; } @@ -2772,6 +2867,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; @@ -2802,6 +2898,7 @@ }, createFilter: function(regexp, op, stub, hl, top) { var settings, test; + test = typeof regexp === 'string' ? function(value) { return regexp === value; } : function(value) { @@ -2825,6 +2922,7 @@ }, node: function() { var filter, firstThread, key, result, thisThread, value, _i, _len, _ref; + if (this.isClone) { return; } @@ -2936,6 +3034,7 @@ menu: { init: function() { var div, entry, type, _i, _len, _ref; + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Filter']) { return; } @@ -2961,6 +3060,7 @@ }, createSubEntry: function(text, type) { var el; + el = $.el('a', { href: 'javascript:;', textContent: text @@ -2971,6 +3071,7 @@ el: el, open: function(post) { var value; + value = Filter[type](post); return value !== false; } @@ -2978,6 +3079,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) { @@ -2992,6 +3094,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); @@ -3025,6 +3128,7 @@ }, node: function() { var data; + if (!this.isReply || this.isClone) { return; } @@ -3048,6 +3152,7 @@ menu: { init: function() { var apply, div, hideStubLink, makeStub, replies, thisPost; + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Reply Hiding Link']) { return; } @@ -3118,6 +3223,7 @@ order: 20, open: function(post) { var data; + if (!post.isReply || post.isClone || !post.isHidden) { return false; } @@ -3149,6 +3255,7 @@ order: 15, open: function(post) { var data; + if (!post.isReply || post.isClone || !post.isHidden) { return false; } @@ -3165,6 +3272,7 @@ }, hide: function() { var makeStub, parent, post, replies, thisPost; + parent = this.parentNode; thisPost = $('input[name=thisPost]', parent).checked; replies = $('input[name=replies]', parent).checked; @@ -3183,6 +3291,7 @@ }, show: function() { var data, parent, post, replies, thisPost; + parent = this.parentNode; thisPost = $('input[name=thisPost]', parent).checked; replies = $('input[name=replies]', parent).checked; @@ -3206,6 +3315,7 @@ }, hideStub: function() { var post; + post = PostHiding.menu.post; post.nodes.root.hidden = true; $.event('CloseMenu'); @@ -3213,6 +3323,7 @@ }, makeButton: function(post, type) { var a; + a = $.el('a', { className: "" + type + "-reply-button", innerHTML: " " + (type === 'hide' ? '-' : '+') + " ", @@ -3223,6 +3334,7 @@ }, saveHiddenState: function(post, isHiding, thisPost, makeStub, hideRecursively) { var data; + data = { boardID: post.board.ID, threadID: post.thread.ID, @@ -3241,12 +3353,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']; } @@ -3281,6 +3395,7 @@ }, show: function(post, showRecursively) { var quotelink, _i, _len, _ref; + if (showRecursively == null) { showRecursively = Conf['Recursive Hiding']; } @@ -3316,6 +3431,7 @@ }, node: function() { var i, obj, quote, recursive, _i, _j, _len, _len1, _ref, _ref1; + if (this.isClone) { return; } @@ -3333,6 +3449,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: [], @@ -3343,6 +3460,7 @@ }, rm: function(recursive, post) { var i, obj, rec, _i, _len, _ref; + if (!(obj = Recursive.recursives[post.fullID])) { return; } @@ -3357,6 +3475,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; @@ -3383,6 +3502,7 @@ }, node: function() { var data; + if (data = ThreadHiding.db.get({ boardID: this.board.ID, threadID: this.ID @@ -3396,6 +3516,7 @@ }, syncCatalog: function() { var hiddenThreads, hiddenThreadsOnCatalog, threadID; + hiddenThreads = ThreadHiding.db.get({ boardID: g.BOARD.ID, defaultValue: {} @@ -3422,6 +3543,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; } @@ -3447,6 +3569,7 @@ menu: { init: function() { var apply, div, hideStubLink, makeStub; + if (g.VIEW !== 'index' || !Conf['Menu'] || !Conf['Thread Hiding Link']) { return; } @@ -3468,6 +3591,7 @@ order: 20, open: function(_arg) { var isReply, thread; + thread = _arg.thread, isReply = _arg.isReply; if (isReply || thread.isHidden) { return false; @@ -3495,6 +3619,7 @@ order: 20, open: function(_arg) { var isReply, thread; + thread = _arg.thread, isReply = _arg.isReply; if (isReply || !thread.isHidden) { return false; @@ -3514,6 +3639,7 @@ order: 15, open: function(_arg) { var isReply, thread; + thread = _arg.thread, isReply = _arg.isReply; if (isReply || !thread.isHidden) { return false; @@ -3524,6 +3650,7 @@ }, hide: function() { var makeStub, thread; + makeStub = $('input', this.parentNode).checked; thread = ThreadHiding.menu.thread; ThreadHiding.hide(thread, makeStub); @@ -3532,6 +3659,7 @@ }, show: function() { var thread; + thread = ThreadHiding.menu.thread; ThreadHiding.show(thread); ThreadHiding.saveHiddenState(thread); @@ -3539,6 +3667,7 @@ }, hideStub: function() { var thread; + thread = ThreadHiding.menu.thread; ThreadHiding.hide(thread, false); $.event('CloseMenu'); @@ -3546,6 +3675,7 @@ }, makeButton: function(thread, type) { var a; + a = $.el('a', { className: "" + type + "-thread-button", innerHTML: " " + (type === 'hide' ? '-' : '+') + " ", @@ -3557,6 +3687,7 @@ }, saveHiddenState: function(thread, makeStub) { var hiddenThreadsOnCatalog; + hiddenThreadsOnCatalog = JSON.parse(localStorage.getItem("4chan-hide-t-" + g.BOARD)) || {}; if (thread.isHidden) { ThreadHiding.db.set({ @@ -3589,6 +3720,7 @@ }, hide: function(thread, makeStub) { var OP, a, numReplies, opInfo, span, threadRoot; + if (makeStub == null) { makeStub = Conf['Stubs']; } @@ -3612,6 +3744,7 @@ }, show: function(thread) { var threadRoot; + if (thread.stub) { $.rm(thread.stub); delete thread.stub; @@ -3624,6 +3757,7 @@ QuoteBacklink = { init: function() { var format; + if (g.VIEW === 'catalog' || !Conf['Quote Backlinks']) { return; } @@ -3641,6 +3775,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; } @@ -3678,6 +3813,7 @@ }, secondNode: function() { var container; + if (this.isClone && (this.origin.isReply || Conf['OP Backlinks'])) { this.nodes.backlinkContainer = $('.container', this.nodes.info); return; @@ -3691,6 +3827,7 @@ }, getContainer: function(id) { var _base; + return (_base = this.containers)[id] || (_base[id] = $.el('span', { className: 'container' })); @@ -3713,6 +3850,7 @@ }, node: function() { var board, boardID, quotelink, thread, threadID, _i, _len, _ref, _ref1, _ref2; + if (this.isClone && this.thread === this.context.thread) { return; } @@ -3742,6 +3880,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]; @@ -3754,6 +3893,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]; @@ -3780,6 +3920,7 @@ }, toggle: function(e) { var boardID, context, postID, threadID, _ref; + if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) { return; } @@ -3805,6 +3946,7 @@ }, add: function(quotelink, boardID, threadID, postID, context) { var inline, isBacklink, post, qroot, root; + isBacklink = $.hasClass(quotelink, 'backlink'); inline = $.el('div', { id: "i" + postID, @@ -3829,6 +3971,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); @@ -3870,6 +4013,7 @@ }, node: function() { var boardID, fullID, i, postID, quotelink, quotelinks, quotes, _ref; + if (this.isClone && this.thread === this.context.thread) { return; } @@ -3912,6 +4056,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]; @@ -3920,6 +4065,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; } @@ -3963,6 +4109,7 @@ }, mouseout: function() { var clone, post, root, _i, _len, _ref; + if (!(root = this.el.firstElementChild)) { return; } @@ -3992,6 +4139,7 @@ }, node: function() { var boardID, postID, quotelink, _i, _len, _ref, _ref1, _ref2; + if (this.isClone) { return; } @@ -4014,6 +4162,7 @@ QuoteThreading = { init: function() { var input; + if (!(Conf['Quote Threading'] && g.VIEW === 'thread')) { return; } @@ -4036,6 +4185,7 @@ }, setup: function() { var ID, post, posts; + $.off(d, '4chanXInitFinished', QuoteThreading.setup); posts = g.posts; for (ID in posts) { @@ -4048,6 +4198,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; } @@ -4077,6 +4228,7 @@ }, nodeinsert: function() { var bottom, height, qpost, qroot, threadContainer, top, _ref; + qpost = g.posts[this.threaded]; delete this.threaded; delete this.cb; @@ -4105,6 +4257,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; @@ -4121,6 +4274,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; @@ -4141,6 +4295,7 @@ }, kb: function() { var control; + control = $.id('threadingControl'); return control.click(); } @@ -4167,6 +4322,7 @@ }, node: function() { var quotelink, _i, _len, _ref; + if (this.isClone) { return; } @@ -4190,6 +4346,7 @@ cb: { seek: function(type) { var highlight, post, posts, result, str; + if (!(Conf['Mark Quotes of You'] && Conf['Quick Reply'])) { return; } @@ -4245,6 +4402,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]; @@ -4259,6 +4417,7 @@ }, parseDeadlink: function(deadlink) { var a, boardID, m, post, postID, quote, quoteID, redirect, _ref; + if ($.hasClass(deadlink.parentNode, 'prettyprint')) { Quotify.fixDeadlink(deadlink); return; @@ -4351,6 +4510,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; @@ -4426,6 +4586,7 @@ }, makeRange: function(startNode, endNode, startOffset, endOffset) { var range; + range = document.createRange(); range.setStart(startNode, startOffset); range.setEnd(endNode, endOffset); @@ -4433,6 +4594,7 @@ }, makeLink: function(range) { var a, char, i, text; + text = range.toString(); i = 0; while (/[(\[{<>]/.test(text.charAt(i))) { @@ -4478,6 +4640,7 @@ }, services: function(link) { var href, key, match, type, _ref; + href = link.href; _ref = Linkify.types; for (key in _ref) { @@ -4490,6 +4653,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', { @@ -4518,6 +4682,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; @@ -4554,18 +4719,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', @@ -4578,6 +4746,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) { @@ -4617,6 +4786,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" }); @@ -4627,6 +4797,7 @@ }, text: function(_arg) { var file, files; + files = _arg.files; for (file in files) { if (files.hasOwnProperty(file)) { @@ -4674,6 +4845,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 }); @@ -4684,6 +4856,7 @@ style: 'height: auto; width: 500px; display: inline-block;', el: function(a) { var div; + div = $.el('div', { className: "soundcloud", name: "soundcloud" @@ -4709,6 +4882,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', { @@ -4780,6 +4954,7 @@ QR = { init: function() { var sc; + if (!Conf['Quick Reply']) { return; } @@ -4826,6 +5001,7 @@ }, initReady: function() { var link; + QR.postingIsEnabled = !!$.id('postForm'); if (!QR.postingIsEnabled) { return; @@ -4845,11 +5021,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); }); @@ -4878,6 +5056,7 @@ }, open: function() { var err; + if (QR.nodes) { QR.nodes.el.hidden = false; QR.unhide(); @@ -4896,6 +5075,7 @@ }, close: function() { var post, _i, _len, _ref; + if (QR.req) { QR.abort(); return; @@ -4948,6 +5128,7 @@ }, error: function(err) { var el; + QR.open(); if (typeof err === 'string') { el = $.tn(err); @@ -4974,6 +5155,7 @@ }, notify: function(el) { var notice, notif; + notice = new Notice('warning', el); QR.notifications.push(notice); if (!Header.areNotificationsEnabled) { @@ -4990,6 +5172,7 @@ notifications: [], cleanNotifications: function() { var notification, _i, _len, _ref; + _ref = QR.notifications; for (_i = 0, _len = _ref.length; _i < _len; _i++) { notification = _ref[_i]; @@ -4999,6 +5182,7 @@ }, status: function() { var disabled, status, thread, value; + if (!QR.nodes) { return; } @@ -5020,6 +5204,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: [], @@ -5039,6 +5224,7 @@ }, parseItem: function(item, types) { var boards, match, type, val, _ref, _ref1; + if (item[0] === '#') { return; } @@ -5067,6 +5253,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]; @@ -5079,6 +5266,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; } @@ -5087,6 +5275,7 @@ get: function(cb) { return $.get('QR.persona', {}, function(_arg) { var persona; + persona = _arg['QR.persona']; return cb(persona); }); @@ -5094,6 +5283,7 @@ set: function(post) { return $.get('QR.persona', {}, function(_arg) { var persona; + persona = _arg['QR.persona']; persona = { name: post.name, @@ -5107,6 +5297,7 @@ cooldown: { init: function() { var board; + if (!Conf['Cooldown']) { return; } @@ -5148,6 +5339,7 @@ }, sync: function(cooldowns) { var id; + for (id in cooldowns) { QR.cooldown.cooldowns[id] = cooldowns[id]; } @@ -5155,6 +5347,7 @@ }, set: function(data) { var cooldown, delay, hasFile, isReply, isSage, post, req, start, type, upSpd; + if (!Conf['Cooldown']) { return; } @@ -5194,6 +5387,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; @@ -5247,6 +5441,7 @@ }, quote: function(e) { var caretPos, com, index, post, range, s, sel, text, thread, _ref; + if (e != null) { e.preventDefault(); } @@ -5284,6 +5479,7 @@ }, characterCount: function() { var count, counter; + counter = QR.nodes.charCount; count = QR.nodes.com.textLength; counter.textContent = count; @@ -5292,6 +5488,7 @@ }, drag: function(e) { var toggle; + toggle = e.type === 'dragstart' ? $.off : $.on; toggle(d, 'dragover', QR.dragOver); return toggle(d, 'drop', QR.dropFile); @@ -5311,6 +5508,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++) { @@ -5350,6 +5548,7 @@ }, fileInput: function(files) { var file, length, max, post, _i, _len; + if (this instanceof Element) { files = __slice.call(this.files); QR.nodes.fileInput.value = null; @@ -5399,6 +5598,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, @@ -5458,6 +5658,7 @@ _Class.prototype.rm = function() { var index; + this["delete"](); index = QR.posts.indexOf(this); if (QR.posts.length === 1) { @@ -5477,6 +5678,7 @@ _Class.prototype.lock = function(lock) { var name, _i, _len, _ref; + if (lock == null) { lock = true; } @@ -5501,6 +5703,7 @@ _Class.prototype.select = function() { var rectEl, rectList; + if (QR.selected) { QR.selected.nodes.el.id = null; QR.selected.forceSave(); @@ -5517,6 +5720,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]; @@ -5528,6 +5732,7 @@ _Class.prototype.save = function(input) { var name, _ref; + if (input.type === 'checkbox') { this.spoiler = input.checked; return; @@ -5549,7 +5754,7 @@ return; } this.file.newName = this.filename.replace(/[/\\]/g, '-'); - if (!/\.(jpe?g|png|gif|pdf|sfw)$/i.test(this.filename)) { + if (!/\.(jpe?g|png|gif|pdf|swf)$/i.test(this.filename)) { this.file.newName += '.jpg'; } return this.updateFilename(); @@ -5558,6 +5763,7 @@ _Class.prototype.forceSave = function() { var name, _i, _len, _ref; + if (this !== QR.selected) { return; } @@ -5587,9 +5793,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; @@ -5640,6 +5848,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) { @@ -5662,9 +5871,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; @@ -5702,6 +5913,7 @@ _Class.prototype.drop = function() { var el, index, newIndex, oldIndex, post; + $.rmClass(this, 'over'); if (!this.draggable) { return; @@ -5736,6 +5948,7 @@ ready: function() { var imgContainer, input, setLifetime, _this = this; + setLifetime = function(e) { return _this.lifetime = e.detail; }; @@ -5772,6 +5985,7 @@ }); $.get('captchas', [], function(_arg) { var captchas; + captchas = _arg.captchas; return _this.sync(captchas); }); @@ -5788,6 +6002,7 @@ }, getOne: function() { var captcha, challenge, response; + this.clear(); if (captcha = this.captchas.shift()) { challenge = captcha.challenge, response = captcha.response; @@ -5812,6 +6027,7 @@ }, save: function() { var response; + if (!(response = this.nodes.input.value.trim())) { return; } @@ -5826,6 +6042,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) { @@ -5843,6 +6060,7 @@ }, load: function() { var challenge; + if (!this.nodes.challenge.firstChild) { return; } @@ -5855,6 +6073,7 @@ }, count: function() { var count; + count = this.captchas.length; this.nodes.input.placeholder = (function() { switch (count) { @@ -5887,6 +6106,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×+
") }; @@ -6009,6 +6229,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(); } @@ -6122,6 +6343,7 @@ }, response: function() { var URL, ban, board, err, h1, isReply, m, post, postID, req, resDoc, threadID, _, _ref, _ref1; + req = QR.req; delete QR.req; post = QR.posts[0]; @@ -6220,6 +6442,7 @@ FappeTyme = { init: function() { var el, input; + if (!Conf['Fappe Tyme'] || g.VIEW === 'catalog' || g.BOARD === 'f') { return; } @@ -6271,6 +6494,7 @@ }, node: function() { var thumb, _ref; + if (!((_ref = this.file) != null ? _ref.isImage : void 0)) { return; } @@ -6295,6 +6519,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 icon icon-resize-small'; @@ -6328,6 +6553,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); @@ -6337,6 +6563,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) { @@ -6367,6 +6594,7 @@ }, expand: function(post, src) { var img, thumb; + thumb = post.file.thumb; if (post.isHidden || post.file.isExpanded || $.hasClass(thumb, 'expanding')) { return; @@ -6394,6 +6622,7 @@ }, completeExpand: function(post) { var prev, thumb; + thumb = post.file.thumb; if (!$.hasClass(thumb, 'expanding')) { return; @@ -6407,6 +6636,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)) { @@ -6418,6 +6648,7 @@ }, error: function() { var URL, post, src, timeoutID; + post = Get.postFromNode(this); $.rm(this); delete post.file.fullImage; @@ -6443,6 +6674,7 @@ return $.ajax("//api.4chan.org/" + post.board + "/res/" + post.thread + ".json", { onload: function() { var postObj, _i, _len, _ref; + if (this.status !== 200) { return; } @@ -6466,6 +6698,7 @@ menu: { init: function() { var conf, createSubEntry, el, name, subEntries, _ref; + if (g.VIEW === 'catalog' || !Conf['Image Expansion']) { return; } @@ -6489,6 +6722,7 @@ }, createSubEntry: function(name, desc) { var input, label; + label = $.el('label', { innerHTML: " " + name, title: desc @@ -6522,6 +6756,7 @@ }, node: function() { var _ref; + if (!((_ref = this.file) != null ? _ref.isImage : void 0)) { return; } @@ -6529,6 +6764,7 @@ }, mouseover: function(e) { var el, post; + post = Get.postFromNode(this); el = $.el('img', { id: 'ihover', @@ -6550,6 +6786,7 @@ error: function() { var URL, post, src, timeoutID, _this = this; + if (!doc.contains(this)) { return; } @@ -6574,6 +6811,7 @@ return $.ajax("//api.4chan.org/" + post.board + "/res/" + post.thread + ".json", { onload: function() { var postObj, _i, _len, _ref; + if (this.status !== 200) { return; } @@ -6599,6 +6837,7 @@ ImageLoader = { init: function() { var prefetch; + if (g.VIEW === 'catalog') { return; } @@ -6625,6 +6864,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; } @@ -6646,6 +6886,7 @@ }, toggle: function() { var enabled, id, post, _ref; + enabled = Conf['prefetch'] = this.checked; if (enabled) { _ref = g.threads["" + g.BOARD.ID + "." + g.THREADID].posts; @@ -6669,6 +6910,7 @@ }, node: function() { var thumb, _ref; + if (this.isClone || !((_ref = this.file) != null ? _ref.isSpoiler : void 0)) { return; } @@ -6681,6 +6923,7 @@ Sauce = { init: function() { var err, link, links, _i, _len, _ref; + if (g.VIEW === 'catalog' || !Conf['Sauce']) { return; } @@ -6710,6 +6953,7 @@ }, createSauceLink: function(link) { var m, text; + link = link.replace(/%(T?URL|MD5|board)/ig, function(parameter) { switch (parameter) { case '%TURL': @@ -6730,6 +6974,7 @@ }, node: function() { var link, nodes, _i, _len, _ref; + if (this.isClone || !this.file) { return; } @@ -6746,6 +6991,7 @@ ArchiveLink = { init: function() { var div, entry, type, _i, _len, _ref; + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Archive Link']) { return; } @@ -6758,6 +7004,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, @@ -6776,12 +7023,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, @@ -6791,6 +7040,7 @@ return true; } : function(post) { var value; + value = Filter[type](post); if (!value) { return false; @@ -6813,6 +7063,7 @@ DeleteLink = { init: function() { var div, fileEl, fileEntry, postEl, postEntry; + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Delete Link']) { return; } @@ -6840,6 +7091,7 @@ el: fileEl, open: function(_arg) { var file; + file = _arg.file; if (!file || file.isDead) { return false; @@ -6855,6 +7107,7 @@ order: 40, open: function(post) { var node; + if (post.isDead || post.board.ID === 'q') { return false; } @@ -6869,6 +7122,7 @@ }, "delete": function() { var fileOnly, form, link, post; + post = DeleteLink.post; if (DeleteLink.cooldown.counting === post) { return; @@ -6898,6 +7152,7 @@ }, load: function(link, post, fileOnly, resDoc) { var msg, s; + if (resDoc.title === '4chan - Banned') { s = 'Banned!'; } else if (msg = resDoc.getElementById('errmsg')) { @@ -6918,6 +7173,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, @@ -6951,6 +7207,7 @@ DownloadLink = { init: function() { var a; + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Download Link']) { return; } @@ -6964,6 +7221,7 @@ order: 100, open: function(_arg) { var file; + file = _arg.file; if (!file) { return false; @@ -6996,6 +7254,7 @@ }, makeButton: (function() { var a; + a = $.el('a', { className: 'menu-button brackets-wrap', innerHTML: '', @@ -7003,6 +7262,7 @@ }); return function() { var button; + button = a.cloneNode(true); $.on(button, 'click', Menu.toggle); return button; @@ -7010,6 +7270,7 @@ })(), toggle: function(e) { var post; + post = Get.postFromNode(this); return Menu.menu.toggle(e, this, post); } @@ -7018,6 +7279,7 @@ ReportLink = { init: function() { var a; + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Report Link']) { return; } @@ -7039,6 +7301,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(); @@ -7051,6 +7314,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; @@ -7125,6 +7389,7 @@ init: function() { var sc, _this = this; + if (g.VIEW !== 'thread' || !Conf['Thread Stats']) { return; } @@ -7153,6 +7418,7 @@ }, node: function() { var ID, fileCount, post, postCount, _ref; + postCount = 0; fileCount = 0; _ref = this.posts; @@ -7170,6 +7436,7 @@ }, onUpdate: function(e) { var fileCount, postCount, _ref; + if (e.detail[404]) { return; } @@ -7178,6 +7445,7 @@ }, update: function(postCount, fileCount) { var fileCountEl, postCountEl, thread; + thread = ThreadStats.thread, postCountEl = ThreadStats.postCountEl, fileCountEl = ThreadStats.fileCountEl; postCountEl.textContent = postCount; fileCountEl.textContent = fileCount; @@ -7202,6 +7470,7 @@ }, onThreadsLoad: function() { var page, pages, thread, _i, _j, _len, _len1, _ref; + if (!(Conf["Page Count in Stats"] && this.status === 200)) { return; } @@ -7225,6 +7494,7 @@ init: function() { var checked, conf, el, input, name, sc, settings, subEntries, _ref, _this = this; + if (g.VIEW !== 'thread' || !Conf['Thread Updater']) { return; } @@ -7374,6 +7644,7 @@ }, interval: function() { var val; + val = +this.value; if (val < 1) { val = 1; @@ -7383,6 +7654,7 @@ }, load: function() { var klass, req, text, _ref; + req = ThreadUpdater.req; switch (req.status) { case 200: @@ -7415,6 +7687,7 @@ }, getInterval: function() { var i, j; + i = ThreadUpdater.interval; j = Math.min(ThreadUpdater.outdateCount, 10); if (!d.hidden) { @@ -7424,12 +7697,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; @@ -7442,6 +7717,7 @@ }, timeout: function() { var n; + ThreadUpdater.timeoutID = setTimeout(ThreadUpdater.timeout, 1000); if (!(n = --ThreadUpdater.seconds)) { return ThreadUpdater.update(); @@ -7454,6 +7730,7 @@ }, update: function() { var url; + if (!ThreadUpdater.online) { return; } @@ -7476,6 +7753,7 @@ }, updateThreadStatus: function(title, OP) { var icon, message, root, titleLC; + titleLC = title.toLowerCase(); if (ThreadUpdater.thread["is" + title] === !!OP[titleLC]) { return; @@ -7502,6 +7780,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); @@ -7587,6 +7866,7 @@ } $.queueTask(function() { var length, threadID; + threadID = ThreadUpdater.thread.ID; length = $$('.thread > .postContainer', ThreadUpdater.root).length; return Fourchan.parseThread(threadID, length - count, length); @@ -7607,6 +7887,7 @@ ThreadWatcher = { init: function() { var now, sc; + if (!Conf['Thread Watcher']) { return; } @@ -7639,6 +7920,7 @@ } $.get('WatchedThreads', null, function(_arg) { var WatchedThreads, boardID, data, threadID, threads, _ref; + WatchedThreads = _arg.WatchedThreads; if (!WatchedThreads) { return; @@ -7664,6 +7946,7 @@ }, node: function() { var toggler; + toggler = $.el('img', { className: 'watch-thread-link' }); @@ -7685,6 +7968,7 @@ } return $.get('AutoWatch', 0, function(_arg) { var AutoWatch, thread; + AutoWatch = _arg.AutoWatch; if (!(thread = g.BOARD.threads[AutoWatch])) { return; @@ -7700,6 +7984,7 @@ cb: { openAll: function() { var a, _i, _len, _ref; + if ($.hasClass(this, 'disabled')) { return; } @@ -7718,6 +8003,7 @@ }, pruneDeads: function() { var boardID, data, threadID, _i, _len, _ref, _ref1; + if ($.hasClass(this, 'disabled')) { return; } @@ -7741,11 +8027,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']) { @@ -7757,6 +8045,7 @@ }, threadUpdate: function(e) { var thread; + thread = e.detail.thread; if (!(e.detail[404] && ThreadWatcher.db.get({ boardID: thread.board.ID, @@ -7773,6 +8062,7 @@ }, fetchAllStatus: function() { var thread, threads, _i, _len; + if (!(threads = ThreadWatcher.getAll()).length) { return; } @@ -7784,6 +8074,7 @@ }, fetchStatus: function(_arg) { var boardID, data, fetchCount, threadID; + boardID = _arg.boardID, threadID = _arg.threadID, data = _arg.data; if (data.isDead) { return; @@ -7793,6 +8084,7 @@ return $.ajax("//api.4chan.org/" + boardID + "/res/" + threadID + ".json", { onloadend: function() { var status; + fetchCount.fetched++; if (fetchCount.fetched === fetchCount.fetching) { fetchCount.fetched = 0; @@ -7823,6 +8115,7 @@ }, getAll: function() { var all, boardID, data, threadID, threads, _ref; + all = []; _ref = ThreadWatcher.db.data.boards; for (boardID in _ref) { @@ -7843,6 +8136,7 @@ }, makeLine: function(boardID, threadID, data) { var div, fullID, href, link, x; + x = $.el('a', { textContent: '×', href: 'javascript:;' @@ -7873,6 +8167,7 @@ }, refresh: function() { var boardID, data, 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++) { @@ -7900,6 +8195,7 @@ }, toggle: function(thread) { var boardID, threadID; + boardID = thread.board.ID; threadID = thread.ID; if (ThreadWatcher.db.get({ @@ -7913,6 +8209,7 @@ }, add: function(thread) { var boardID, data, threadID; + data = {}; boardID = thread.board.ID; threadID = thread.ID; @@ -7943,6 +8240,7 @@ }, convert: function(oldFormat) { var boardID, data, newFormat, threadID, threads; + newFormat = {}; for (boardID in oldFormat) { threads = oldFormat[boardID]; @@ -7959,6 +8257,7 @@ refreshers: [], init: function() { var menu; + if (!Conf['Thread Watcher']) { return; } @@ -7971,6 +8270,7 @@ }, addHeaderMenuEntry: function() { var entryEl; + if (g.VIEW !== 'thread') { return; } @@ -7987,6 +8287,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); @@ -7995,6 +8296,7 @@ }, addMenuEntries: function() { var cb, conf, entries, entry, name, refresh, subEntries, _i, _len, _ref, _ref1, _results; + entries = []; entries.push({ cb: ThreadWatcher.cb.openAll, @@ -8065,6 +8367,7 @@ }, createSubEntry: function(name, desc) { var entry, input; + entry = { type: 'thread watcher', el: $.el('label', { @@ -8116,6 +8419,7 @@ }, ready: function() { var ID, post, posts, _ref; + $.off(d, '4chanXInitFinished', Unread.ready); posts = []; _ref = Unread.thread.posts; @@ -8132,6 +8436,7 @@ }, scroll: function() { var checkPosition, hash, onload, post, posts, root; + if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) { return; } @@ -8161,6 +8466,7 @@ } checkPosition = function(target) { var height, top, _ref; + _ref = target.getBoundingClientRect(), top = _ref.top, height = _ref.height; return top + height - doc.clientHeight > 0; }; @@ -8168,6 +8474,7 @@ }, sync: function() { var lastReadPost; + lastReadPost = Unread.db.get({ boardID: Unread.thread.board.ID, threadID: Unread.thread.ID, @@ -8184,6 +8491,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; @@ -8211,6 +8519,7 @@ }, addPostQuotingYou: function(post) { var quotelink, _i, _len, _ref; + if (!QR.db) { return; } @@ -8227,6 +8536,7 @@ }, openNotification: function(post) { var name, notif; + if (!Header.areNotificationsEnabled) { return; } @@ -8252,6 +8562,7 @@ }, readSinglePost: function(post) { var i; + if ((i = Unread.posts.indexOf(post)) === -1) { return; } @@ -8267,6 +8578,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) { @@ -8277,6 +8589,7 @@ }, read: $.debounce(50, function(e) { var ID, bottom, height, i, post, posts; + if (d.hidden || !Unread.posts.length) { return; } @@ -8332,6 +8645,7 @@ }), setLine: function(force) { var post, root; + if (!(d.hidden || force === true)) { return; } @@ -8346,6 +8660,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); @@ -8366,6 +8681,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]; @@ -8497,6 +8813,7 @@ }, to: function(dest, data) { var archive; + archive = (dest === 'search' ? Redirect.data.thread : Redirect.data[dest])[data.boardID]; if (!archive) { return ''; @@ -8505,6 +8822,7 @@ }, protocol: function(archive) { var protocol; + protocol = location.protocol; if (!archive[protocol.slice(0, -1)]) { protocol = protocol === 'https:' ? 'http:' : 'https:'; @@ -8513,6 +8831,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') { @@ -8525,6 +8844,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)) { @@ -8536,11 +8856,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); @@ -8559,6 +8881,7 @@ }, setup: function() { var btn, entry, psa; + $.off(d, '4chanXInitFinished', PSAHiding.setup); if (!(psa = $.id('globalMessage'))) { $.rmClass(doc, 'hide-announcement'); @@ -8587,6 +8910,7 @@ $.on(btn, 'click', PSAHiding.toggle); $.get('hiddenPSA', 0, function(_arg) { var hiddenPSA; + hiddenPSA = _arg.hiddenPSA; PSAHiding.sync(hiddenPSA); $.before(psa, btn); @@ -8596,6 +8920,7 @@ }, toggle: function(e) { var UTC; + if ($.hasClass(this, 'hide-announcement')) { UTC = +$.id('globalMessage').dataset.utc; $.set('hiddenPSA', UTC); @@ -8607,6 +8932,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') { @@ -8627,6 +8953,7 @@ }, ready: function() { var banner, child, children, i; + banner = $(".boardBanner"); children = banner.children; i = 0; @@ -8646,6 +8973,7 @@ cb: { toggle: (function() { var types; + types = { jpg: 227, png: 270, @@ -8653,6 +8981,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; @@ -8672,6 +9001,7 @@ }, focus: function() { var items, string, string2; + this.textContent = this.innerHTML; string = "" + g.BOARD + "." + this.className; string2 = "" + string + ".orig"; @@ -8694,6 +9024,7 @@ }, custom: function(child) { var cachedTest, string; + cachedTest = child.innerHTML; string = "" + g.BOARD + "." + child.className; $.on(child, 'click keydown focus blur', function(e) { @@ -8701,6 +9032,7 @@ }); $.get(string, cachedTest, function(item) { var string2, title; + if (!(title = item[string])) { return; } @@ -8724,6 +9056,7 @@ CatalogLinks = { init: function() { var el, input; + if (!Conf['Catalog Links']) { return; } @@ -8747,12 +9080,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++) { @@ -8787,6 +9122,7 @@ }, node: function() { var str, uid; + if (this.isClone || !(str = this.info.uniqueID)) { return; } @@ -8798,6 +9134,7 @@ }, compute: function(str) { var hash, rgb; + hash = IDColor.hash(str); rgb = [(hash >> 24) & 0xFF, (hash >> 16) & 0xFF, (hash >> 8) & 0xFF]; rgb[3] = ((rgb[0] * 0.299) + (rgb[1] * 0.587) + (rgb[2] * 0.114)) > 125; @@ -8809,6 +9146,7 @@ }, hash: function(str) { var i, msg; + msg = 0; i = 0; while (i < 8) { @@ -8854,6 +9192,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; } @@ -8865,6 +9204,7 @@ Emoji = { init: function() { var css, icon, name, pos, _ref; + if (!Conf['Emoji']) { return; } @@ -8934,6 +9274,7 @@ }, node: function() { var a; + if (a = $('.abbr > a:not([onclick])', this.nodes.comment)) { return $.on(a, 'click', ExpandComment.cb); } @@ -8945,6 +9286,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; @@ -8960,6 +9302,7 @@ }, contract: function(post) { var a; + if (!post.nodes.shortComment) { return; } @@ -8970,6 +9313,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 + ")"; @@ -9032,6 +9376,7 @@ }, node: function() { var a, files, posts, span, _ref; + if (!(span = $.x('following-sibling::span[contains(@class,"summary")][1]', this.OP.nodes.root))) { return; } @@ -9052,6 +9397,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) { @@ -9129,6 +9475,7 @@ }, parse: function(req, thread, a) { var filesCount, link, post, posts, postsCount, postsObj, postsRoot, reply, root, spoilerRange, _i, _len; + if (a.textContent[0] === '+') { return; } @@ -9192,6 +9539,7 @@ }, createFunc: function(format) { var code; + code = format.replace(/%(.)/g, function(s, c) { if (c in FileInfo.formatters) { return "' + FileInfo.formatters." + c + ".call(post) + '"; @@ -9203,6 +9551,7 @@ }, convertUnit: function(size, unit) { var i; + if (unit === 'B') { return "" + (size.toFixed()) + " Bytes"; } @@ -9233,6 +9582,7 @@ }, n: function() { var fullname, shortname; + fullname = this.file.name; shortname = Build.shortFilename(this.file.name, this.isReply); if (fullname === shortname) { @@ -9276,6 +9626,7 @@ Fourchan = { init: function() { var board; + if (g.VIEW === 'catalog') { return; } @@ -9297,6 +9648,7 @@ }, code: function() { var pre, _i, _len, _ref; + if (this.isClone) { return; } @@ -9325,11 +9677,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]'); @@ -9342,6 +9696,7 @@ }, keydown: function(e) { var form, key, notification, notifications, op, target, thread, threadRoot, _i, _len; + if (!(key = Keybinds.keyCode(e))) { return; } @@ -9519,6 +9874,7 @@ }, keyCode: function(e) { var kc, key; + key = (function() { switch (kc = e.keyCode) { case 8: @@ -9574,6 +9930,7 @@ }, tags: function(tag, ta) { var range, selEnd, selStart, value; + value = ta.value; selStart = ta.selectionStart; selEnd = ta.selectionEnd; @@ -9584,11 +9941,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 { @@ -9598,6 +9957,7 @@ }, open: function(thread, tab) { var url; + if (g.VIEW !== 'index') { return; } @@ -9610,6 +9970,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'); @@ -9669,6 +10030,7 @@ Nav = { init: function() { var append, next, prev, span; + switch (g.VIEW) { case 'index': if (!Conf['Index Navigation']) { @@ -9719,6 +10081,7 @@ }, getThread: function(full) { var headRect, i, rect, thread, threads, topMargin, _i, _len; + if (Conf['Bottom header'] || !Conf['Fixed Header']) { topMargin = 0; } else { @@ -9744,6 +10107,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)) { @@ -9768,6 +10132,7 @@ }, node: function() { var dateEl; + if (this.isClone) { return; } @@ -9777,6 +10142,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) { @@ -9787,6 +10153,7 @@ stale: [], flush: function() { var now, update, _i, _len, _ref; + if (d.hidden) { return; } @@ -9802,13 +10169,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); @@ -9849,6 +10219,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]; @@ -9868,6 +10239,7 @@ }, ready: function() { var field; + field = $.id('recaptcha_response_field'); $.on(field, 'keydown', function(e) { if (e.keyCode === 8 && !field.value) { @@ -9876,6 +10248,7 @@ }); return $.on($('form'), 'submit', function(e) { var response; + e.preventDefault(); response = field.value.trim(); if (!/\s/.test(response)) { @@ -9905,6 +10278,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) + '"; @@ -9989,6 +10363,7 @@ Settings = { init: function() { var link, settings; + link = $.el('a', { className: 'settings-link icon icon-wrench', textContent: 'Settings', @@ -9998,6 +10373,7 @@ Header.addShortcut(link); $.get('previousversion', null, function(item) { var changelog, el, previous; + if (previous = item['previousversion']) { if (previous === g.VERSION) { return; @@ -10032,6 +10408,7 @@ }, open: function(openSection) { var dialog, html, link, links, overlay, section, sectionToOpen, _i, _len, _ref; + $.off(d, '4chanXInitFinished', Settings.open); if (Settings.dialog) { return; @@ -10084,6 +10461,7 @@ sections: [], addSection: function(title, open) { var hyphenatedTitle, _ref; + if (typeof title !== 'string') { _ref = title.detail, title = _ref.title, open = _ref.open; } @@ -10096,6 +10474,7 @@ }, openSection: function() { var section, selected; + if (selected = $('.tab-selected', Settings.dialog)) { $.rmClass(selected, 'tab-selected'); } @@ -10109,6 +10488,7 @@ }, main: function(section) { var arr, button, description, div, fs, hiddenNum, input, inputs, items, key, obj, _ref; + items = {}; inputs = {}; _ref = Config.main; @@ -10133,6 +10513,7 @@ } $.get(items, function(items) { var val; + for (key in items) { val = items[key]; inputs[key].checked = val; @@ -10147,6 +10528,7 @@ boards: {} }, function(item) { var ID, board, thread, _ref1; + _ref1 = item.hiddenThreads.boards; for (ID in _ref1) { board = _ref1[ID]; @@ -10161,6 +10543,7 @@ boards: {} }, function(item) { var ID, board, post, thread, _ref1; + _ref1 = item.hiddenPosts.boards; for (ID in _ref1) { board = _ref1[ID]; @@ -10180,6 +10563,7 @@ boards: {} }, function(item) { var boardID; + for (boardID in item.hiddenThreads.boards) { localStorage.removeItem("4chan-hide-t-" + boardID); } @@ -10190,6 +10574,7 @@ }, "export": function(now, data) { var a, db, p, _i, _len, _ref; + if (typeof now !== 'number') { now = Date.now(); data = { @@ -10226,6 +10611,7 @@ }, onImport: function() { var file, output, reader; + if (!(file = this.files[0])) { return; } @@ -10237,6 +10623,7 @@ reader = new FileReader(); reader.onload = function(e) { var data, err; + try { data = JSON.parse(e.target.result); Settings.loadSettings(data); @@ -10253,6 +10640,7 @@ }, loadSettings: function(data) { var key, val, version, _ref; + version = data.version.split('.'); if (version[0] === '2') { data = Settings.convertSettings(data, { @@ -10340,6 +10728,7 @@ }, convertSettings: function(data, map) { var newKey, prevKey; + for (prevKey in map) { newKey = map[prevKey]; if (newKey) { @@ -10351,6 +10740,7 @@ }, filter: function(section) { var select; + section.innerHTML = "
"; select = $('select', section); $.on(select, 'change', Settings.selectFilter); @@ -10358,6 +10748,7 @@ }, selectFilter: function() { var div, name, ta; + div = this.nextElementSibling; if ((name = this.value) !== 'guide') { $.rmAll(div); @@ -10377,6 +10768,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) { @@ -10386,6 +10778,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 = {}; @@ -10405,6 +10798,7 @@ $.on(ta, 'change', $.cb.value); $.get(items, function(items) { var key, val; + for (key in items) { val = items[key]; if (['emojiPos'].contains(key)) { @@ -10475,6 +10869,7 @@ }); $.get('selectedArchives', Conf['selectedArchives'], function(_arg) { var option, selectedArchives, type; + selectedArchives = _arg.selectedArchives; for (boardID in selectedArchives) { data = selectedArchives[boardID]; @@ -10489,6 +10884,7 @@ }, addArchiveCell: function(boardID, data, type) { var archive, i, length, options, select, td; + length = data[type].length; td = $.el('td', { className: 'archive-cell' @@ -10518,8 +10914,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); @@ -10530,6 +10928,7 @@ }, time: function() { var funk; + funk = Time.createFunc(this.value); return this.nextElementSibling.textContent = funk(Time, new Date()); }, @@ -10538,6 +10937,7 @@ }, fileInfo: function() { var data, funk; + data = { isReply: true, file: { @@ -10576,6 +10976,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 = {}; @@ -10596,6 +10997,7 @@ } return $.get(items, function(items) { var val; + for (key in items) { val = items[key]; inputs[key].value = val; @@ -10604,6 +11006,7 @@ }, keybind: function(e) { var key; + if (e.keyCode === 9) { return; } @@ -10620,8 +11023,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') { @@ -10654,6 +11059,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') { @@ -10681,6 +11087,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('/'); @@ -10697,6 +11104,7 @@ } init = function(features) { var err, module, name; + for (name in features) { module = features[name]; try { @@ -10775,6 +11183,7 @@ }, initStyle: function() { var mainStyleSheet, setStyle, style, styleSheets, _ref; + $.off(d, '4chanMainInit', Main.initStyle); if (!Main.isThisPageLegit() || $.hasClass(doc, 'fourchan-x')) { return; @@ -10796,6 +11205,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]; @@ -10817,6 +11227,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', { @@ -10883,6 +11294,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++) { @@ -10910,9 +11322,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); @@ -10931,6 +11345,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]; @@ -10964,6 +11379,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); @@ -10983,6 +11399,7 @@ }, handleErrors: function(errors) { var div, error, logs, _i, _len; + if (!(errors instanceof Array)) { error = errors; } else if (errors.length === 1) { @@ -10997,6 +11414,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', { @@ -11010,6 +11428,7 @@ }, parseError: function(data) { var error, message; + Main.logError(data); message = $.el('div', { textContent: data.message @@ -11026,6 +11445,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 a30fb6a86..08a211fdd 100644 --- a/builds/crx/script.js +++ b/builds/crx/script.js @@ -323,6 +323,7 @@ Array.prototype.indexOf = function(object) { var i; + i = this.length; while (i--) { if (this[i] === object) { @@ -341,6 +342,7 @@ $.extend = function(object, properties) { var key, val; + for (key in properties) { val = properties[key]; if (!properties.hasOwnProperty(key)) { @@ -358,6 +360,7 @@ $.ready = function(fc) { var cb; + if (d.readyState !== 'loading') { $.queueTask(fc); return; @@ -371,6 +374,7 @@ $.formData = function(form) { var fd, key, val; + if (form instanceof HTMLFormElement) { return new FormData(form); } @@ -390,6 +394,7 @@ $.extend = function(object, properties) { var key, val; + for (key in properties) { val = properties[key]; object[key] = val; @@ -398,9 +403,11 @@ $.ajax = (function() { var lastModified; + lastModified = {}; return function(url, options, extra) { var form, r, sync, type, upCallbacks, whenModified; + if (extra == null) { extra = {}; } @@ -423,9 +430,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); @@ -445,6 +454,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]; @@ -480,6 +490,7 @@ $.addStyle = function(css, id) { var style; + style = $.el('style', { id: id, textContent: css @@ -526,6 +537,7 @@ } else { return function(el) { var _ref; + return (_ref = el.parentNode) != null ? _ref.removeChild(el) : void 0; }; } @@ -533,6 +545,7 @@ $.rmAll = function(root) { var node; + while (node = root.firstChild) { root.removeChild(node); } @@ -548,6 +561,7 @@ $.nodes = function(nodes) { var frag, node, _i, _len; + if (!(nodes instanceof Array)) { return nodes; } @@ -581,6 +595,7 @@ $.el = function(tag, properties) { var el; + el = d.createElement(tag); if (properties) { $.extend(el, properties); @@ -590,6 +605,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]; @@ -599,6 +615,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]; @@ -622,6 +639,7 @@ $.debounce = function(wait, fn) { var args, exec, lastCall, that, timeout; + lastCall = 0; timeout = null; that = null; @@ -643,9 +661,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); @@ -668,6 +688,7 @@ $.globalEval = function(code) { var script; + script = $.el('script', { textContent: code }); @@ -677,6 +698,7 @@ $.bytesToString = function(size) { var unit; + unit = 0; while (size >= 1024) { size /= 1024; @@ -692,6 +714,7 @@ $.item = function(key, val) { var item; + item = {}; item[key] = val; return item; @@ -702,6 +725,7 @@ $.sync = (function() { chrome.storage.onChanged.addListener(function(changes) { var cb, key; + for (key in changes) { if (cb = $.syncing[key]) { cb(changes[key].newValue); @@ -721,6 +745,7 @@ $.get = function(key, val, cb) { var count, done, items, localItems, syncItems; + if (typeof cb === 'function') { items = $.item(key, val); } else { @@ -740,6 +765,7 @@ count = 0; done = function(item) { var lastError; + lastError = chrome.runtime.lastError; if (lastError) { c.error(lastError, lastError.message || 'No message.'); @@ -761,10 +787,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]; @@ -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; + bq = this.nodes.comment.cloneNode(true); nodes = $$('.abbr, .capcodeReplies, .exif, b', bq); i = 0; @@ -941,6 +971,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++) { @@ -951,6 +982,7 @@ Post.prototype.parseQuote = function(quotelink) { var fullID, match; + if (!(match = quotelink.href.match(/boards\.4chan\.org\/([^\/]+)\/res\/\d+#p(\d+)$/))) { return; } @@ -966,6 +998,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 === 404) { _this["delete"](boardID); } else if (e.target.status === 200) { @@ -1403,8 +1448,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); @@ -1442,6 +1489,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', @@ -1542,6 +1590,7 @@ }); $.ready(function() { var a, cs; + _this.footer = $.id('boardNavDesktopFoot'); if (a = $("a[href*='/" + g.BOARD + "/']", $.id('boardNavDesktopFoot'))) { a.className = 'current'; @@ -1576,6 +1625,7 @@ }), setBoardList: function() { var a, boardList, btn, fourchannav, fullBoardList; + fourchannav = $.id('boardNavDesktop'); if (a = $("a[href*='/" + g.BOARD + "/']", fourchannav)) { a.className = 'current'; @@ -1597,6 +1647,7 @@ }, generateBoardList: function(text) { var as, list, nodes; + list = $('#custom-board-list', Header.bar); $.rmAll(list); if (!text) { @@ -1605,6 +1656,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); } @@ -1655,6 +1707,7 @@ }, toggleBoardList: function() { var bar, custom, full, showBoardList; + bar = Header.bar; custom = $('#custom-board-list', bar); full = $('#full-board-list', bar); @@ -1690,6 +1743,7 @@ }, toggleLinkJustify: function() { var centered; + $.event('CloseMenu'); centered = this.nodeName === 'INPUT' ? this.checked : void 0; Header.setLinkJustify(centered); @@ -1733,6 +1787,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); @@ -1746,6 +1801,7 @@ }, toggleFooterVisibility: function() { var hide, message; + $.event('CloseMenu'); hide = this.nodeName === 'INPUT' ? this.checked : !!Header.footer.hidden; Header.setFooterVisibility(hide); @@ -1755,6 +1811,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); @@ -1767,12 +1824,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; } @@ -1783,6 +1842,7 @@ }, scrollToPost: function(post) { var headRect, top; + top = post.getBoundingClientRect().top; if (Conf['Fixed Header'] && !Conf['Bottom Header']) { headRect = Header.bar.getBoundingClientRect(); @@ -1792,6 +1852,7 @@ }, addShortcut: function(el) { var shortcut; + shortcut = $.el('span', { className: 'shortcut brackets-wrap' }); @@ -1803,6 +1864,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) { @@ -1812,6 +1874,7 @@ areNotificationsEnabled: false, enableDesktopNotifications: function() { var authorize, disable, el, notice, _ref; + if (!(window.Notification && Conf['Desktop Notifications'])) { return; } @@ -1847,6 +1910,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); @@ -1856,6 +1920,7 @@ }, postFromObject: function(data, boardID) { var o; + o = { postID: data.no, threadID: data.resto || data.no, @@ -1900,6 +1965,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/'; @@ -1998,6 +2064,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; @@ -2034,6 +2101,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) { @@ -2049,6 +2117,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); @@ -2068,6 +2137,7 @@ }, postDataFromLink: function(link) { var boardID, path, postID, threadID, _ref; + if (link.hostname === 'boards.4chan.org') { path = link.pathname.split('/'); boardID = path[1]; @@ -2085,6 +2155,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) { @@ -2113,12 +2184,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; @@ -2141,6 +2214,7 @@ }, insert: function(post, root, context) { var clone, nodes; + if (!root.parentNode) { return; } @@ -2154,6 +2228,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; @@ -2207,6 +2282,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; @@ -2303,8 +2379,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, @@ -2346,6 +2424,7 @@ Menu.prototype.makeMenu = function() { var menu; + menu = $.el('div', { className: 'dialog', id: 'menu', @@ -2360,6 +2439,7 @@ Menu.prototype.toggle = function(e, button, data) { var previousButton; + e.preventDefault(); e.stopPropagation(); if (currentMenu) { @@ -2377,6 +2457,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; @@ -2415,6 +2496,7 @@ Menu.prototype.insertEntry = function(entry, parent, data) { var subEntry, submenu, _i, _len, _ref; + if (typeof entry.open === 'function') { if (!entry.open(data)) { return; @@ -2448,6 +2530,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); @@ -2457,6 +2540,7 @@ Menu.prototype.keybinds = function(e) { var entry, next, nextPrev, subEntry, submenu; + entry = $('.focused', currentMenu); while (subEntry = $('.focused', entry)) { entry = subEntry; @@ -2502,6 +2586,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'); } @@ -2529,6 +2614,7 @@ Menu.prototype.addEntry = function(e) { var entry; + entry = e.detail; if (entry.type !== this.type) { return; @@ -2539,6 +2625,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) { @@ -2562,6 +2649,7 @@ })(); dragstart = function(e) { var el, isTouching, o, rect, screenHeight, screenWidth, _ref; + if (e.type === 'mousedown' && e.button !== 0) { return; } @@ -2600,6 +2688,7 @@ }; touchmove = function(e) { var touch, _i, _len, _ref; + _ref = e.changedTouches; for (_i = 0, _len = _ref.length; _i < _len; _i++) { touch = _ref[_i]; @@ -2611,6 +2700,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 + '%'; @@ -2626,6 +2716,7 @@ }; touchend = function(e) { var touch, _i, _len, _ref; + _ref = e.changedTouches; for (_i = 0, _len = _ref.length; _i < _len; _i++) { touch = _ref[_i]; @@ -2647,6 +2738,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, @@ -2675,6 +2767,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; @@ -2717,6 +2810,7 @@ }, node: function() { var email, name, tripcode, _ref; + if (this.info.capcode || this.isClone) { return; } @@ -2743,6 +2837,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; } @@ -2779,6 +2874,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; @@ -2809,6 +2905,7 @@ }, createFilter: function(regexp, op, stub, hl, top) { var settings, test; + test = typeof regexp === 'string' ? function(value) { return regexp === value; } : function(value) { @@ -2832,6 +2929,7 @@ }, node: function() { var filter, firstThread, key, result, thisThread, value, _i, _len, _ref; + if (this.isClone) { return; } @@ -2943,6 +3041,7 @@ menu: { init: function() { var div, entry, type, _i, _len, _ref; + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Filter']) { return; } @@ -2968,6 +3067,7 @@ }, createSubEntry: function(text, type) { var el; + el = $.el('a', { href: 'javascript:;', textContent: text @@ -2978,6 +3078,7 @@ el: el, open: function(post) { var value; + value = Filter[type](post); return value !== false; } @@ -2985,6 +3086,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) { @@ -2999,6 +3101,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); @@ -3032,6 +3135,7 @@ }, node: function() { var data; + if (!this.isReply || this.isClone) { return; } @@ -3055,6 +3159,7 @@ menu: { init: function() { var apply, div, hideStubLink, makeStub, replies, thisPost; + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Reply Hiding Link']) { return; } @@ -3125,6 +3230,7 @@ order: 20, open: function(post) { var data; + if (!post.isReply || post.isClone || !post.isHidden) { return false; } @@ -3156,6 +3262,7 @@ order: 15, open: function(post) { var data; + if (!post.isReply || post.isClone || !post.isHidden) { return false; } @@ -3172,6 +3279,7 @@ }, hide: function() { var makeStub, parent, post, replies, thisPost; + parent = this.parentNode; thisPost = $('input[name=thisPost]', parent).checked; replies = $('input[name=replies]', parent).checked; @@ -3190,6 +3298,7 @@ }, show: function() { var data, parent, post, replies, thisPost; + parent = this.parentNode; thisPost = $('input[name=thisPost]', parent).checked; replies = $('input[name=replies]', parent).checked; @@ -3213,6 +3322,7 @@ }, hideStub: function() { var post; + post = PostHiding.menu.post; post.nodes.root.hidden = true; $.event('CloseMenu'); @@ -3220,6 +3330,7 @@ }, makeButton: function(post, type) { var a; + a = $.el('a', { className: "" + type + "-reply-button", innerHTML: " " + (type === 'hide' ? '-' : '+') + " ", @@ -3230,6 +3341,7 @@ }, saveHiddenState: function(post, isHiding, thisPost, makeStub, hideRecursively) { var data; + data = { boardID: post.board.ID, threadID: post.thread.ID, @@ -3248,12 +3360,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']; } @@ -3288,6 +3402,7 @@ }, show: function(post, showRecursively) { var quotelink, _i, _len, _ref; + if (showRecursively == null) { showRecursively = Conf['Recursive Hiding']; } @@ -3323,6 +3438,7 @@ }, node: function() { var i, obj, quote, recursive, _i, _j, _len, _len1, _ref, _ref1; + if (this.isClone) { return; } @@ -3340,6 +3456,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: [], @@ -3350,6 +3467,7 @@ }, rm: function(recursive, post) { var i, obj, rec, _i, _len, _ref; + if (!(obj = Recursive.recursives[post.fullID])) { return; } @@ -3364,6 +3482,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; @@ -3390,6 +3509,7 @@ }, node: function() { var data; + if (data = ThreadHiding.db.get({ boardID: this.board.ID, threadID: this.ID @@ -3403,6 +3523,7 @@ }, syncCatalog: function() { var hiddenThreads, hiddenThreadsOnCatalog, threadID; + hiddenThreads = ThreadHiding.db.get({ boardID: g.BOARD.ID, defaultValue: {} @@ -3429,6 +3550,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; } @@ -3454,6 +3576,7 @@ menu: { init: function() { var apply, div, hideStubLink, makeStub; + if (g.VIEW !== 'index' || !Conf['Menu'] || !Conf['Thread Hiding Link']) { return; } @@ -3475,6 +3598,7 @@ order: 20, open: function(_arg) { var isReply, thread; + thread = _arg.thread, isReply = _arg.isReply; if (isReply || thread.isHidden) { return false; @@ -3502,6 +3626,7 @@ order: 20, open: function(_arg) { var isReply, thread; + thread = _arg.thread, isReply = _arg.isReply; if (isReply || !thread.isHidden) { return false; @@ -3521,6 +3646,7 @@ order: 15, open: function(_arg) { var isReply, thread; + thread = _arg.thread, isReply = _arg.isReply; if (isReply || !thread.isHidden) { return false; @@ -3531,6 +3657,7 @@ }, hide: function() { var makeStub, thread; + makeStub = $('input', this.parentNode).checked; thread = ThreadHiding.menu.thread; ThreadHiding.hide(thread, makeStub); @@ -3539,6 +3666,7 @@ }, show: function() { var thread; + thread = ThreadHiding.menu.thread; ThreadHiding.show(thread); ThreadHiding.saveHiddenState(thread); @@ -3546,6 +3674,7 @@ }, hideStub: function() { var thread; + thread = ThreadHiding.menu.thread; ThreadHiding.hide(thread, false); $.event('CloseMenu'); @@ -3553,6 +3682,7 @@ }, makeButton: function(thread, type) { var a; + a = $.el('a', { className: "" + type + "-thread-button", innerHTML: " " + (type === 'hide' ? '-' : '+') + " ", @@ -3564,6 +3694,7 @@ }, saveHiddenState: function(thread, makeStub) { var hiddenThreadsOnCatalog; + hiddenThreadsOnCatalog = JSON.parse(localStorage.getItem("4chan-hide-t-" + g.BOARD)) || {}; if (thread.isHidden) { ThreadHiding.db.set({ @@ -3596,6 +3727,7 @@ }, hide: function(thread, makeStub) { var OP, a, numReplies, opInfo, span, threadRoot; + if (makeStub == null) { makeStub = Conf['Stubs']; } @@ -3619,6 +3751,7 @@ }, show: function(thread) { var threadRoot; + if (thread.stub) { $.rm(thread.stub); delete thread.stub; @@ -3631,6 +3764,7 @@ QuoteBacklink = { init: function() { var format; + if (g.VIEW === 'catalog' || !Conf['Quote Backlinks']) { return; } @@ -3648,6 +3782,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; } @@ -3685,6 +3820,7 @@ }, secondNode: function() { var container; + if (this.isClone && (this.origin.isReply || Conf['OP Backlinks'])) { this.nodes.backlinkContainer = $('.container', this.nodes.info); return; @@ -3698,6 +3834,7 @@ }, getContainer: function(id) { var _base; + return (_base = this.containers)[id] || (_base[id] = $.el('span', { className: 'container' })); @@ -3720,6 +3857,7 @@ }, node: function() { var board, boardID, quotelink, thread, threadID, _i, _len, _ref, _ref1, _ref2; + if (this.isClone && this.thread === this.context.thread) { return; } @@ -3749,6 +3887,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]; @@ -3761,6 +3900,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]; @@ -3787,6 +3927,7 @@ }, toggle: function(e) { var boardID, context, postID, threadID, _ref; + if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) { return; } @@ -3812,6 +3953,7 @@ }, add: function(quotelink, boardID, threadID, postID, context) { var inline, isBacklink, post, qroot, root; + isBacklink = $.hasClass(quotelink, 'backlink'); inline = $.el('div', { id: "i" + postID, @@ -3836,6 +3978,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); @@ -3877,6 +4020,7 @@ }, node: function() { var boardID, fullID, i, postID, quotelink, quotelinks, quotes, _ref; + if (this.isClone && this.thread === this.context.thread) { return; } @@ -3919,6 +4063,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]; @@ -3927,6 +4072,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; } @@ -3970,6 +4116,7 @@ }, mouseout: function() { var clone, post, root, _i, _len, _ref; + if (!(root = this.el.firstElementChild)) { return; } @@ -3999,6 +4146,7 @@ }, node: function() { var boardID, postID, quotelink, _i, _len, _ref, _ref1, _ref2; + if (this.isClone) { return; } @@ -4021,6 +4169,7 @@ QuoteThreading = { init: function() { var input; + if (!(Conf['Quote Threading'] && g.VIEW === 'thread')) { return; } @@ -4043,6 +4192,7 @@ }, setup: function() { var ID, post, posts; + $.off(d, '4chanXInitFinished', QuoteThreading.setup); posts = g.posts; for (ID in posts) { @@ -4055,6 +4205,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; } @@ -4084,6 +4235,7 @@ }, nodeinsert: function() { var bottom, height, qpost, qroot, threadContainer, top, _ref; + qpost = g.posts[this.threaded]; delete this.threaded; delete this.cb; @@ -4112,6 +4264,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; @@ -4128,6 +4281,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; @@ -4148,6 +4302,7 @@ }, kb: function() { var control; + control = $.id('threadingControl'); return control.click(); } @@ -4174,6 +4329,7 @@ }, node: function() { var quotelink, _i, _len, _ref; + if (this.isClone) { return; } @@ -4197,6 +4353,7 @@ cb: { seek: function(type) { var highlight, post, posts, result, str; + if (!(Conf['Mark Quotes of You'] && Conf['Quick Reply'])) { return; } @@ -4252,6 +4409,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]; @@ -4266,6 +4424,7 @@ }, parseDeadlink: function(deadlink) { var a, boardID, m, post, postID, quote, quoteID, redirect, _ref; + if ($.hasClass(deadlink.parentNode, 'prettyprint')) { Quotify.fixDeadlink(deadlink); return; @@ -4358,6 +4517,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; @@ -4433,6 +4593,7 @@ }, makeRange: function(startNode, endNode, startOffset, endOffset) { var range; + range = document.createRange(); range.setStart(startNode, startOffset); range.setEnd(endNode, endOffset); @@ -4440,6 +4601,7 @@ }, makeLink: function(range) { var a, char, i, text; + text = range.toString(); i = 0; while (/[(\[{<>]/.test(text.charAt(i))) { @@ -4485,6 +4647,7 @@ }, services: function(link) { var href, key, match, type, _ref; + href = link.href; _ref = Linkify.types; for (key in _ref) { @@ -4497,6 +4660,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', { @@ -4525,6 +4689,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; @@ -4561,18 +4726,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', @@ -4585,6 +4753,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) { @@ -4624,6 +4793,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" }); @@ -4634,6 +4804,7 @@ }, text: function(_arg) { var file, files; + files = _arg.files; for (file in files) { if (files.hasOwnProperty(file)) { @@ -4681,6 +4852,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 }); @@ -4691,6 +4863,7 @@ style: 'height: auto; width: 500px; display: inline-block;', el: function(a) { var div; + div = $.el('div', { className: "soundcloud", name: "soundcloud" @@ -4716,6 +4889,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', { @@ -4787,6 +4961,7 @@ QR = { init: function() { var sc; + if (!Conf['Quick Reply']) { return; } @@ -4833,6 +5008,7 @@ }, initReady: function() { var link; + QR.postingIsEnabled = !!$.id('postForm'); if (!QR.postingIsEnabled) { return; @@ -4852,11 +5028,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); }); @@ -4886,6 +5064,7 @@ }, open: function() { var err; + if (QR.nodes) { QR.nodes.el.hidden = false; QR.unhide(); @@ -4904,6 +5083,7 @@ }, close: function() { var post, _i, _len, _ref; + if (QR.req) { QR.abort(); return; @@ -4951,6 +5131,7 @@ }, error: function(err) { var el; + QR.open(); if (typeof err === 'string') { el = $.tn(err); @@ -4977,6 +5158,7 @@ }, notify: function(el) { var notice, notif; + notice = new Notice('warning', el); QR.notifications.push(notice); if (!Header.areNotificationsEnabled) { @@ -5000,6 +5182,7 @@ notifications: [], cleanNotifications: function() { var notification, _i, _len, _ref; + _ref = QR.notifications; for (_i = 0, _len = _ref.length; _i < _len; _i++) { notification = _ref[_i]; @@ -5009,6 +5192,7 @@ }, status: function() { var disabled, status, thread, value; + if (!QR.nodes) { return; } @@ -5030,6 +5214,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: [], @@ -5049,6 +5234,7 @@ }, parseItem: function(item, types) { var boards, match, type, val, _ref, _ref1; + if (item[0] === '#') { return; } @@ -5077,6 +5263,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]; @@ -5089,6 +5276,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; } @@ -5097,6 +5285,7 @@ get: function(cb) { return $.get('QR.persona', {}, function(_arg) { var persona; + persona = _arg['QR.persona']; return cb(persona); }); @@ -5104,6 +5293,7 @@ set: function(post) { return $.get('QR.persona', {}, function(_arg) { var persona; + persona = _arg['QR.persona']; persona = { name: post.name, @@ -5117,6 +5307,7 @@ cooldown: { init: function() { var board; + if (!Conf['Cooldown']) { return; } @@ -5158,6 +5349,7 @@ }, sync: function(cooldowns) { var id; + for (id in cooldowns) { QR.cooldown.cooldowns[id] = cooldowns[id]; } @@ -5165,6 +5357,7 @@ }, set: function(data) { var cooldown, delay, hasFile, isReply, isSage, post, req, start, type, upSpd; + if (!Conf['Cooldown']) { return; } @@ -5204,6 +5397,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; @@ -5257,6 +5451,7 @@ }, quote: function(e) { var caretPos, com, index, post, range, s, sel, text, thread, _ref; + if (e != null) { e.preventDefault(); } @@ -5294,6 +5489,7 @@ }, characterCount: function() { var count, counter; + counter = QR.nodes.charCount; count = QR.nodes.com.textLength; counter.textContent = count; @@ -5302,6 +5498,7 @@ }, drag: function(e) { var toggle; + toggle = e.type === 'dragstart' ? $.off : $.on; toggle(d, 'dragover', QR.dragOver); return toggle(d, 'drop', QR.dropFile); @@ -5321,6 +5518,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++) { @@ -5360,6 +5558,7 @@ }, fileInput: function(files) { var file, length, max, post, _i, _len; + if (this instanceof Element) { files = __slice.call(this.files); QR.nodes.fileInput.value = null; @@ -5409,6 +5608,7 @@ this.select = __bind(this.select, this); var el, event, prev, _i, _len, _ref, _this = this; + el = $.el('a', { className: 'qr-preview', draggable: true, @@ -5462,6 +5662,7 @@ _Class.prototype.rm = function() { var index; + this["delete"](); index = QR.posts.indexOf(this); if (QR.posts.length === 1) { @@ -5481,6 +5682,7 @@ _Class.prototype.lock = function(lock) { var name, _i, _len, _ref; + if (lock == null) { lock = true; } @@ -5505,6 +5707,7 @@ _Class.prototype.select = function() { var rectEl, rectList; + if (QR.selected) { QR.selected.nodes.el.id = null; QR.selected.forceSave(); @@ -5521,6 +5724,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]; @@ -5532,6 +5736,7 @@ _Class.prototype.save = function(input) { var name, _ref; + if (input.type === 'checkbox') { this.spoiler = input.checked; return; @@ -5553,7 +5758,7 @@ return; } this.file.newName = this.filename.replace(/[/\\]/g, '-'); - if (!/\.(jpe?g|png|gif|pdf|sfw)$/i.test(this.filename)) { + if (!/\.(jpe?g|png|gif|pdf|swf)$/i.test(this.filename)) { this.file.newName += '.jpg'; } return this.updateFilename(); @@ -5562,6 +5767,7 @@ _Class.prototype.forceSave = function() { var name, _i, _len, _ref; + if (this !== QR.selected) { return; } @@ -5591,9 +5797,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; @@ -5644,6 +5852,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) { @@ -5666,9 +5875,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; @@ -5706,6 +5917,7 @@ _Class.prototype.drop = function() { var el, index, newIndex, oldIndex, post; + $.rmClass(this, 'over'); if (!this.draggable) { return; @@ -5740,6 +5952,7 @@ ready: function() { var imgContainer, input, setLifetime, _this = this; + setLifetime = function(e) { return _this.lifetime = e.detail; }; @@ -5776,6 +5989,7 @@ }); $.get('captchas', [], function(_arg) { var captchas; + captchas = _arg.captchas; return _this.sync(captchas); }); @@ -5790,6 +6004,7 @@ }, getOne: function() { var captcha, challenge, response; + this.clear(); if (captcha = this.captchas.shift()) { challenge = captcha.challenge, response = captcha.response; @@ -5814,6 +6029,7 @@ }, save: function() { var response; + if (!(response = this.nodes.input.value.trim())) { return; } @@ -5828,6 +6044,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) { @@ -5845,6 +6062,7 @@ }, load: function() { var challenge; + if (!this.nodes.challenge.firstChild) { return; } @@ -5857,6 +6075,7 @@ }, count: function() { var count; + count = this.captchas.length; this.nodes.input.placeholder = (function() { switch (count) { @@ -5889,6 +6108,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×+
") }; @@ -5994,6 +6214,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(); } @@ -6107,6 +6328,7 @@ }, response: function() { var URL, ban, board, err, h1, isReply, m, post, postID, req, resDoc, threadID, _, _ref, _ref1; + req = QR.req; delete QR.req; post = QR.posts[0]; @@ -6205,6 +6427,7 @@ FappeTyme = { init: function() { var el, input; + if (!Conf['Fappe Tyme'] || g.VIEW === 'catalog' || g.BOARD === 'f') { return; } @@ -6256,6 +6479,7 @@ }, node: function() { var thumb, _ref; + if (!((_ref = this.file) != null ? _ref.isImage : void 0)) { return; } @@ -6280,6 +6504,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 icon icon-resize-small'; @@ -6313,6 +6538,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); @@ -6322,6 +6548,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) { @@ -6352,6 +6579,7 @@ }, expand: function(post, src) { var img, thumb; + thumb = post.file.thumb; if (post.isHidden || post.file.isExpanded || $.hasClass(thumb, 'expanding')) { return; @@ -6379,6 +6607,7 @@ }, completeExpand: function(post) { var prev, thumb; + thumb = post.file.thumb; if (!$.hasClass(thumb, 'expanding')) { return; @@ -6392,6 +6621,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)) { @@ -6403,6 +6633,7 @@ }, error: function() { var URL, post, src, timeoutID; + post = Get.postFromNode(this); $.rm(this); delete post.file.fullImage; @@ -6428,6 +6659,7 @@ return $.ajax("//api.4chan.org/" + post.board + "/res/" + post.thread + ".json", { onload: function() { var postObj, _i, _len, _ref; + if (this.status !== 200) { return; } @@ -6451,6 +6683,7 @@ menu: { init: function() { var conf, createSubEntry, el, name, subEntries, _ref; + if (g.VIEW === 'catalog' || !Conf['Image Expansion']) { return; } @@ -6474,6 +6707,7 @@ }, createSubEntry: function(name, desc) { var input, label; + label = $.el('label', { innerHTML: " " + name, title: desc @@ -6507,6 +6741,7 @@ }, node: function() { var _ref; + if (!((_ref = this.file) != null ? _ref.isImage : void 0)) { return; } @@ -6514,6 +6749,7 @@ }, mouseover: function(e) { var el, post; + post = Get.postFromNode(this); el = $.el('img', { id: 'ihover', @@ -6535,6 +6771,7 @@ error: function() { var URL, post, src, timeoutID, _this = this; + if (!doc.contains(this)) { return; } @@ -6559,6 +6796,7 @@ return $.ajax("//api.4chan.org/" + post.board + "/res/" + post.thread + ".json", { onload: function() { var postObj, _i, _len, _ref; + if (this.status !== 200) { return; } @@ -6584,6 +6822,7 @@ ImageLoader = { init: function() { var prefetch; + if (g.VIEW === 'catalog') { return; } @@ -6610,6 +6849,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; } @@ -6631,6 +6871,7 @@ }, toggle: function() { var enabled, id, post, _ref; + enabled = Conf['prefetch'] = this.checked; if (enabled) { _ref = g.threads["" + g.BOARD.ID + "." + g.THREADID].posts; @@ -6654,6 +6895,7 @@ }, node: function() { var thumb, _ref; + if (this.isClone || !((_ref = this.file) != null ? _ref.isSpoiler : void 0)) { return; } @@ -6666,6 +6908,7 @@ Sauce = { init: function() { var err, link, links, _i, _len, _ref; + if (g.VIEW === 'catalog' || !Conf['Sauce']) { return; } @@ -6695,6 +6938,7 @@ }, createSauceLink: function(link) { var m, text; + link = link.replace(/%(T?URL|MD5|board)/ig, function(parameter) { switch (parameter) { case '%TURL': @@ -6715,6 +6959,7 @@ }, node: function() { var link, nodes, _i, _len, _ref; + if (this.isClone || !this.file) { return; } @@ -6731,6 +6976,7 @@ ArchiveLink = { init: function() { var div, entry, type, _i, _len, _ref; + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Archive Link']) { return; } @@ -6743,6 +6989,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, @@ -6761,12 +7008,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, @@ -6776,6 +7025,7 @@ return true; } : function(post) { var value; + value = Filter[type](post); if (!value) { return false; @@ -6798,6 +7048,7 @@ DeleteLink = { init: function() { var div, fileEl, fileEntry, postEl, postEntry; + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Delete Link']) { return; } @@ -6825,6 +7076,7 @@ el: fileEl, open: function(_arg) { var file; + file = _arg.file; if (!file || file.isDead) { return false; @@ -6840,6 +7092,7 @@ order: 40, open: function(post) { var node; + if (post.isDead || post.board.ID === 'q') { return false; } @@ -6854,6 +7107,7 @@ }, "delete": function() { var fileOnly, form, link, post; + post = DeleteLink.post; if (DeleteLink.cooldown.counting === post) { return; @@ -6883,6 +7137,7 @@ }, load: function(link, post, fileOnly, resDoc) { var msg, s; + if (resDoc.title === '4chan - Banned') { s = 'Banned!'; } else if (msg = resDoc.getElementById('errmsg')) { @@ -6903,6 +7158,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, @@ -6936,6 +7192,7 @@ DownloadLink = { init: function() { var a; + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Download Link']) { return; } @@ -6949,6 +7206,7 @@ order: 100, open: function(_arg) { var file; + file = _arg.file; if (!file) { return false; @@ -6981,6 +7239,7 @@ }, makeButton: (function() { var a; + a = $.el('a', { className: 'menu-button brackets-wrap', innerHTML: '', @@ -6988,6 +7247,7 @@ }); return function() { var button; + button = a.cloneNode(true); $.on(button, 'click', Menu.toggle); return button; @@ -6995,6 +7255,7 @@ })(), toggle: function(e) { var post; + post = Get.postFromNode(this); return Menu.menu.toggle(e, this, post); } @@ -7003,6 +7264,7 @@ ReportLink = { init: function() { var a; + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Report Link']) { return; } @@ -7024,6 +7286,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(); @@ -7036,6 +7299,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; @@ -7110,6 +7374,7 @@ init: function() { var sc, _this = this; + if (g.VIEW !== 'thread' || !Conf['Thread Stats']) { return; } @@ -7138,6 +7403,7 @@ }, node: function() { var ID, fileCount, post, postCount, _ref; + postCount = 0; fileCount = 0; _ref = this.posts; @@ -7155,6 +7421,7 @@ }, onUpdate: function(e) { var fileCount, postCount, _ref; + if (e.detail[404]) { return; } @@ -7163,6 +7430,7 @@ }, update: function(postCount, fileCount) { var fileCountEl, postCountEl, thread; + thread = ThreadStats.thread, postCountEl = ThreadStats.postCountEl, fileCountEl = ThreadStats.fileCountEl; postCountEl.textContent = postCount; fileCountEl.textContent = fileCount; @@ -7187,6 +7455,7 @@ }, onThreadsLoad: function() { var page, pages, thread, _i, _j, _len, _len1, _ref; + if (!(Conf["Page Count in Stats"] && this.status === 200)) { return; } @@ -7210,6 +7479,7 @@ init: function() { var checked, conf, el, input, name, sc, settings, subEntries, _ref, _this = this; + if (g.VIEW !== 'thread' || !Conf['Thread Updater']) { return; } @@ -7359,6 +7629,7 @@ }, interval: function() { var val; + val = +this.value; if (val < 1) { val = 1; @@ -7368,6 +7639,7 @@ }, load: function() { var klass, req, text, _ref; + req = ThreadUpdater.req; switch (req.status) { case 200: @@ -7400,6 +7672,7 @@ }, getInterval: function() { var i, j; + i = ThreadUpdater.interval; j = Math.min(ThreadUpdater.outdateCount, 10); if (!d.hidden) { @@ -7409,12 +7682,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; @@ -7427,6 +7702,7 @@ }, timeout: function() { var n; + ThreadUpdater.timeoutID = setTimeout(ThreadUpdater.timeout, 1000); if (!(n = --ThreadUpdater.seconds)) { return ThreadUpdater.update(); @@ -7439,6 +7715,7 @@ }, update: function() { var url; + if (!ThreadUpdater.online) { return; } @@ -7461,6 +7738,7 @@ }, updateThreadStatus: function(title, OP) { var icon, message, root, titleLC; + titleLC = title.toLowerCase(); if (ThreadUpdater.thread["is" + title] === !!OP[titleLC]) { return; @@ -7487,6 +7765,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); @@ -7572,6 +7851,7 @@ } $.queueTask(function() { var length, threadID; + threadID = ThreadUpdater.thread.ID; length = $$('.thread > .postContainer', ThreadUpdater.root).length; return Fourchan.parseThread(threadID, length - count, length); @@ -7592,6 +7872,7 @@ ThreadWatcher = { init: function() { var now, sc; + if (!Conf['Thread Watcher']) { return; } @@ -7624,6 +7905,7 @@ } $.get('WatchedThreads', null, function(_arg) { var WatchedThreads, boardID, data, threadID, threads, _ref; + WatchedThreads = _arg.WatchedThreads; if (!WatchedThreads) { return; @@ -7649,6 +7931,7 @@ }, node: function() { var toggler; + toggler = $.el('img', { className: 'watch-thread-link' }); @@ -7670,6 +7953,7 @@ } return $.get('AutoWatch', 0, function(_arg) { var AutoWatch, thread; + AutoWatch = _arg.AutoWatch; if (!(thread = g.BOARD.threads[AutoWatch])) { return; @@ -7685,6 +7969,7 @@ cb: { openAll: function() { var a, _i, _len, _ref; + if ($.hasClass(this, 'disabled')) { return; } @@ -7703,6 +7988,7 @@ }, pruneDeads: function() { var boardID, data, threadID, _i, _len, _ref, _ref1; + if ($.hasClass(this, 'disabled')) { return; } @@ -7726,11 +8012,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']) { @@ -7742,6 +8030,7 @@ }, threadUpdate: function(e) { var thread; + thread = e.detail.thread; if (!(e.detail[404] && ThreadWatcher.db.get({ boardID: thread.board.ID, @@ -7758,6 +8047,7 @@ }, fetchAllStatus: function() { var thread, threads, _i, _len; + if (!(threads = ThreadWatcher.getAll()).length) { return; } @@ -7769,6 +8059,7 @@ }, fetchStatus: function(_arg) { var boardID, data, fetchCount, threadID; + boardID = _arg.boardID, threadID = _arg.threadID, data = _arg.data; if (data.isDead) { return; @@ -7778,6 +8069,7 @@ return $.ajax("//api.4chan.org/" + boardID + "/res/" + threadID + ".json", { onloadend: function() { var status; + fetchCount.fetched++; if (fetchCount.fetched === fetchCount.fetching) { fetchCount.fetched = 0; @@ -7808,6 +8100,7 @@ }, getAll: function() { var all, boardID, data, threadID, threads, _ref; + all = []; _ref = ThreadWatcher.db.data.boards; for (boardID in _ref) { @@ -7828,6 +8121,7 @@ }, makeLine: function(boardID, threadID, data) { var div, fullID, href, link, x; + x = $.el('a', { textContent: '×', href: 'javascript:;' @@ -7858,6 +8152,7 @@ }, refresh: function() { var boardID, data, 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++) { @@ -7885,6 +8180,7 @@ }, toggle: function(thread) { var boardID, threadID; + boardID = thread.board.ID; threadID = thread.ID; if (ThreadWatcher.db.get({ @@ -7898,6 +8194,7 @@ }, add: function(thread) { var boardID, data, threadID; + data = {}; boardID = thread.board.ID; threadID = thread.ID; @@ -7928,6 +8225,7 @@ }, convert: function(oldFormat) { var boardID, data, newFormat, threadID, threads; + newFormat = {}; for (boardID in oldFormat) { threads = oldFormat[boardID]; @@ -7944,6 +8242,7 @@ refreshers: [], init: function() { var menu; + if (!Conf['Thread Watcher']) { return; } @@ -7956,6 +8255,7 @@ }, addHeaderMenuEntry: function() { var entryEl; + if (g.VIEW !== 'thread') { return; } @@ -7972,6 +8272,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); @@ -7980,6 +8281,7 @@ }, addMenuEntries: function() { var cb, conf, entries, entry, name, refresh, subEntries, _i, _len, _ref, _ref1, _results; + entries = []; entries.push({ cb: ThreadWatcher.cb.openAll, @@ -8050,6 +8352,7 @@ }, createSubEntry: function(name, desc) { var entry, input; + entry = { type: 'thread watcher', el: $.el('label', { @@ -8101,6 +8404,7 @@ }, ready: function() { var ID, post, posts, _ref; + $.off(d, '4chanXInitFinished', Unread.ready); posts = []; _ref = Unread.thread.posts; @@ -8117,6 +8421,7 @@ }, scroll: function() { var checkPosition, hash, onload, post, posts, root; + if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) { return; } @@ -8146,6 +8451,7 @@ } checkPosition = function(target) { var height, top, _ref; + _ref = target.getBoundingClientRect(), top = _ref.top, height = _ref.height; return top + height - doc.clientHeight > 0; }; @@ -8153,6 +8459,7 @@ }, sync: function() { var lastReadPost; + lastReadPost = Unread.db.get({ boardID: Unread.thread.board.ID, threadID: Unread.thread.ID, @@ -8169,6 +8476,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; @@ -8196,6 +8504,7 @@ }, addPostQuotingYou: function(post) { var quotelink, _i, _len, _ref; + if (!QR.db) { return; } @@ -8212,6 +8521,7 @@ }, openNotification: function(post) { var name, notif; + if (!Header.areNotificationsEnabled) { return; } @@ -8237,6 +8547,7 @@ }, readSinglePost: function(post) { var i; + if ((i = Unread.posts.indexOf(post)) === -1) { return; } @@ -8252,6 +8563,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) { @@ -8262,6 +8574,7 @@ }, read: $.debounce(50, function(e) { var ID, bottom, height, i, post, posts; + if (d.hidden || !Unread.posts.length) { return; } @@ -8317,6 +8630,7 @@ }), setLine: function(force) { var post, root; + if (!(d.hidden || force === true)) { return; } @@ -8331,6 +8645,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); @@ -8356,6 +8671,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]; @@ -8487,6 +8803,7 @@ }, to: function(dest, data) { var archive; + archive = (dest === 'search' ? Redirect.data.thread : Redirect.data[dest])[data.boardID]; if (!archive) { return ''; @@ -8495,6 +8812,7 @@ }, protocol: function(archive) { var protocol; + protocol = location.protocol; if (!archive[protocol.slice(0, -1)]) { protocol = protocol === 'https:' ? 'http:' : 'https:'; @@ -8503,6 +8821,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') { @@ -8515,6 +8834,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)) { @@ -8526,11 +8846,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); @@ -8549,6 +8871,7 @@ }, setup: function() { var btn, entry, psa; + $.off(d, '4chanXInitFinished', PSAHiding.setup); if (!(psa = $.id('globalMessage'))) { $.rmClass(doc, 'hide-announcement'); @@ -8577,6 +8900,7 @@ $.on(btn, 'click', PSAHiding.toggle); $.get('hiddenPSA', 0, function(_arg) { var hiddenPSA; + hiddenPSA = _arg.hiddenPSA; PSAHiding.sync(hiddenPSA); $.before(psa, btn); @@ -8586,6 +8910,7 @@ }, toggle: function(e) { var UTC; + if ($.hasClass(this, 'hide-announcement')) { UTC = +$.id('globalMessage').dataset.utc; $.set('hiddenPSA', UTC); @@ -8597,6 +8922,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') { @@ -8617,6 +8943,7 @@ }, ready: function() { var banner, child, children, i; + banner = $(".boardBanner"); children = banner.children; i = 0; @@ -8636,6 +8963,7 @@ cb: { toggle: (function() { var types; + types = { jpg: 227, png: 270, @@ -8643,6 +8971,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; @@ -8662,6 +8991,7 @@ }, focus: function() { var items, string, string2; + this.textContent = this.innerHTML; string = "" + g.BOARD + "." + this.className; string2 = "" + string + ".orig"; @@ -8684,6 +9014,7 @@ }, custom: function(child) { var cachedTest, string; + cachedTest = child.innerHTML; string = "" + g.BOARD + "." + child.className; $.on(child, 'click keydown focus blur', function(e) { @@ -8691,6 +9022,7 @@ }); $.get(string, cachedTest, function(item) { var string2, title; + if (!(title = item[string])) { return; } @@ -8714,6 +9046,7 @@ CatalogLinks = { init: function() { var el, input; + if (!Conf['Catalog Links']) { return; } @@ -8737,12 +9070,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++) { @@ -8777,6 +9112,7 @@ }, node: function() { var str, uid; + if (this.isClone || !(str = this.info.uniqueID)) { return; } @@ -8788,6 +9124,7 @@ }, compute: function(str) { var hash, rgb; + hash = IDColor.hash(str); rgb = [(hash >> 24) & 0xFF, (hash >> 16) & 0xFF, (hash >> 8) & 0xFF]; rgb[3] = ((rgb[0] * 0.299) + (rgb[1] * 0.587) + (rgb[2] * 0.114)) > 125; @@ -8799,6 +9136,7 @@ }, hash: function(str) { var i, msg; + msg = 0; i = 0; while (i < 8) { @@ -8844,6 +9182,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; } @@ -8855,6 +9194,7 @@ Emoji = { init: function() { var css, icon, name, pos, _ref; + if (!Conf['Emoji']) { return; } @@ -8924,6 +9264,7 @@ }, node: function() { var a; + if (a = $('.abbr > a:not([onclick])', this.nodes.comment)) { return $.on(a, 'click', ExpandComment.cb); } @@ -8935,6 +9276,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; @@ -8950,6 +9292,7 @@ }, contract: function(post) { var a; + if (!post.nodes.shortComment) { return; } @@ -8960,6 +9303,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 + ")"; @@ -9022,6 +9366,7 @@ }, node: function() { var a, files, posts, span, _ref; + if (!(span = $.x('following-sibling::span[contains(@class,"summary")][1]', this.OP.nodes.root))) { return; } @@ -9042,6 +9387,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) { @@ -9119,6 +9465,7 @@ }, parse: function(req, thread, a) { var filesCount, link, post, posts, postsCount, postsObj, postsRoot, reply, root, spoilerRange, _i, _len; + if (a.textContent[0] === '+') { return; } @@ -9182,6 +9529,7 @@ }, createFunc: function(format) { var code; + code = format.replace(/%(.)/g, function(s, c) { if (c in FileInfo.formatters) { return "' + FileInfo.formatters." + c + ".call(post) + '"; @@ -9193,6 +9541,7 @@ }, convertUnit: function(size, unit) { var i; + if (unit === 'B') { return "" + (size.toFixed()) + " Bytes"; } @@ -9223,6 +9572,7 @@ }, n: function() { var fullname, shortname; + fullname = this.file.name; shortname = Build.shortFilename(this.file.name, this.isReply); if (fullname === shortname) { @@ -9266,6 +9616,7 @@ Fourchan = { init: function() { var board; + if (g.VIEW === 'catalog') { return; } @@ -9287,6 +9638,7 @@ }, code: function() { var pre, _i, _len, _ref; + if (this.isClone) { return; } @@ -9315,11 +9667,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]'); @@ -9332,6 +9686,7 @@ }, keydown: function(e) { var form, key, notification, notifications, op, target, thread, threadRoot, _i, _len; + if (!(key = Keybinds.keyCode(e))) { return; } @@ -9509,6 +9864,7 @@ }, keyCode: function(e) { var kc, key; + key = (function() { switch (kc = e.keyCode) { case 8: @@ -9564,6 +9920,7 @@ }, tags: function(tag, ta) { var range, selEnd, selStart, value; + value = ta.value; selStart = ta.selectionStart; selEnd = ta.selectionEnd; @@ -9574,11 +9931,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 { @@ -9588,6 +9947,7 @@ }, open: function(thread, tab) { var url; + if (g.VIEW !== 'index') { return; } @@ -9600,6 +9960,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'); @@ -9659,6 +10020,7 @@ Nav = { init: function() { var append, next, prev, span; + switch (g.VIEW) { case 'index': if (!Conf['Index Navigation']) { @@ -9709,6 +10071,7 @@ }, getThread: function(full) { var headRect, i, rect, thread, threads, topMargin, _i, _len; + if (Conf['Bottom header'] || !Conf['Fixed Header']) { topMargin = 0; } else { @@ -9734,6 +10097,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)) { @@ -9758,6 +10122,7 @@ }, node: function() { var dateEl; + if (this.isClone) { return; } @@ -9767,6 +10132,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) { @@ -9777,6 +10143,7 @@ stale: [], flush: function() { var now, update, _i, _len, _ref; + if (d.hidden) { return; } @@ -9792,13 +10159,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); @@ -9839,6 +10209,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]; @@ -9858,6 +10229,7 @@ }, ready: function() { var field; + field = $.id('recaptcha_response_field'); $.on(field, 'keydown', function(e) { if (e.keyCode === 8 && !field.value) { @@ -9866,6 +10238,7 @@ }); return $.on($('form'), 'submit', function(e) { var response; + e.preventDefault(); response = field.value.trim(); if (!/\s/.test(response)) { @@ -9895,6 +10268,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) + '"; @@ -9979,6 +10353,7 @@ Settings = { init: function() { var link, settings; + link = $.el('a', { className: 'settings-link icon icon-wrench', textContent: 'Settings', @@ -9988,6 +10363,7 @@ Header.addShortcut(link); $.get('previousversion', null, function(item) { var changelog, el, previous; + if (previous = item['previousversion']) { if (previous === g.VERSION) { return; @@ -10022,6 +10398,7 @@ }, open: function(openSection) { var dialog, html, link, links, overlay, section, sectionToOpen, _i, _len, _ref; + $.off(d, '4chanXInitFinished', Settings.open); if (Settings.dialog) { return; @@ -10074,6 +10451,7 @@ sections: [], addSection: function(title, open) { var hyphenatedTitle, _ref; + if (typeof title !== 'string') { _ref = title.detail, title = _ref.title, open = _ref.open; } @@ -10086,6 +10464,7 @@ }, openSection: function() { var section, selected; + if (selected = $('.tab-selected', Settings.dialog)) { $.rmClass(selected, 'tab-selected'); } @@ -10099,6 +10478,7 @@ }, main: function(section) { var arr, button, description, div, fs, hiddenNum, input, inputs, items, key, obj, _ref; + items = {}; inputs = {}; _ref = Config.main; @@ -10123,6 +10503,7 @@ } $.get(items, function(items) { var val; + for (key in items) { val = items[key]; inputs[key].checked = val; @@ -10137,6 +10518,7 @@ boards: {} }, function(item) { var ID, board, thread, _ref1; + _ref1 = item.hiddenThreads.boards; for (ID in _ref1) { board = _ref1[ID]; @@ -10151,6 +10533,7 @@ boards: {} }, function(item) { var ID, board, post, thread, _ref1; + _ref1 = item.hiddenPosts.boards; for (ID in _ref1) { board = _ref1[ID]; @@ -10170,6 +10553,7 @@ boards: {} }, function(item) { var boardID; + for (boardID in item.hiddenThreads.boards) { localStorage.removeItem("4chan-hide-t-" + boardID); } @@ -10180,6 +10564,7 @@ }, "export": function(now, data) { var a, db, _i, _len, _ref; + if (typeof now !== 'number') { now = Date.now(); data = { @@ -10214,6 +10599,7 @@ }, onImport: function() { var file, output, reader; + if (!(file = this.files[0])) { return; } @@ -10225,6 +10611,7 @@ reader = new FileReader(); reader.onload = function(e) { var data, err; + try { data = JSON.parse(e.target.result); Settings.loadSettings(data); @@ -10241,6 +10628,7 @@ }, loadSettings: function(data) { var key, val, version, _ref; + version = data.version.split('.'); if (version[0] === '2') { data = Settings.convertSettings(data, { @@ -10328,6 +10716,7 @@ }, convertSettings: function(data, map) { var newKey, prevKey; + for (prevKey in map) { newKey = map[prevKey]; if (newKey) { @@ -10339,6 +10728,7 @@ }, filter: function(section) { var select; + section.innerHTML = "
"; select = $('select', section); $.on(select, 'change', Settings.selectFilter); @@ -10346,6 +10736,7 @@ }, selectFilter: function() { var div, name, ta; + div = this.nextElementSibling; if ((name = this.value) !== 'guide') { $.rmAll(div); @@ -10365,6 +10756,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) { @@ -10374,6 +10766,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 = {}; @@ -10393,6 +10786,7 @@ $.on(ta, 'change', $.cb.value); $.get(items, function(items) { var key, val; + for (key in items) { val = items[key]; if (['emojiPos'].contains(key)) { @@ -10463,6 +10857,7 @@ }); $.get('selectedArchives', Conf['selectedArchives'], function(_arg) { var option, selectedArchives, type; + selectedArchives = _arg.selectedArchives; for (boardID in selectedArchives) { data = selectedArchives[boardID]; @@ -10477,6 +10872,7 @@ }, addArchiveCell: function(boardID, data, type) { var archive, i, length, options, select, td; + length = data[type].length; td = $.el('td', { className: 'archive-cell' @@ -10506,8 +10902,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); @@ -10518,6 +10916,7 @@ }, time: function() { var funk; + funk = Time.createFunc(this.value); return this.nextElementSibling.textContent = funk(Time, new Date()); }, @@ -10526,6 +10925,7 @@ }, fileInfo: function() { var data, funk; + data = { isReply: true, file: { @@ -10564,6 +10964,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 = {}; @@ -10584,6 +10985,7 @@ } return $.get(items, function(items) { var val; + for (key in items) { val = items[key]; inputs[key].value = val; @@ -10592,6 +10994,7 @@ }, keybind: function(e) { var key; + if (e.keyCode === 9) { return; } @@ -10608,8 +11011,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') { @@ -10651,6 +11056,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') { @@ -10678,6 +11084,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('/'); @@ -10694,6 +11101,7 @@ } init = function(features) { var err, module, name; + for (name in features) { module = features[name]; try { @@ -10772,6 +11180,7 @@ }, initStyle: function() { var mainStyleSheet, setStyle, style, styleSheets, _ref; + $.off(d, '4chanMainInit', Main.initStyle); if (!Main.isThisPageLegit() || $.hasClass(doc, 'fourchan-x')) { return; @@ -10793,6 +11202,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]; @@ -10814,6 +11224,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', { @@ -10880,6 +11291,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++) { @@ -10907,9 +11319,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); @@ -10928,6 +11342,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]; @@ -10961,6 +11376,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); @@ -10980,6 +11396,7 @@ }, handleErrors: function(errors) { var div, error, logs, _i, _len; + if (!(errors instanceof Array)) { error = errors; } else if (errors.length === 1) { @@ -10994,6 +11411,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', { @@ -11007,6 +11425,7 @@ }, parseError: function(data) { var error, message; + Main.logError(data); message = $.el('div', { textContent: data.message @@ -11023,6 +11442,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/img/changelog/3.9.0/0.png b/img/changelog/3.9.0/0.png new file mode 100644 index 000000000..1fc40ae98 Binary files /dev/null and b/img/changelog/3.9.0/0.png differ diff --git a/src/General/Config.coffee b/src/General/Config.coffee index 4547167c1..f58f04908 100755 --- a/src/General/Config.coffee +++ b/src/General/Config.coffee @@ -309,7 +309,6 @@ Config = true 'When disabled, shows a red border on the CAPTCHA input until a key is pressed instead of a notification.' ] - 'Quote Links': 'Quote Backlinks': [ true diff --git a/src/Posting/QuickReply.coffee b/src/Posting/QuickReply.coffee index bdf431f47..7ba89a224 100755 --- a/src/Posting/QuickReply.coffee +++ b/src/Posting/QuickReply.coffee @@ -648,7 +648,7 @@ QR = when 'filename' return unless @file @file.newName = @filename.replace /[/\\]/g, '-' - unless /\.(jpe?g|png|gif|pdf|sfw)$/i.test @filename + unless /\.(jpe?g|png|gif|pdf|swf)$/i.test @filename # 4chan will truncate the filename if it has no extension, # but it will always replace the extension by the correct one, # so we suffix it with '.jpg' when needed.