diff --git a/CHANGELOG.md b/CHANGELOG.md index 3863161cf..74743e9d3 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,7 @@ **MayhemYDG**: +- Compatibility fixes for Greasemonkey v2. +- The QR won't duplicate single-word captchas anymore if you've input numbers only (like a street address). +- Removed the `Download Link` feature on Chrome/Opera as it is not working as intended anymore. - [Security fix](https://github.com/MayhemYDG/4chan-x/issues/1634). ### v1.7.33 diff --git a/LICENSE b/LICENSE index dbe46531e..111576e58 100755 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ /* -* 4chan X - Version 1.7.33 - 2014-05-29 +* 4chan X - Version 1.7.33 - 2014-06-22 * * Licensed under the MIT license. * https://github.com/ccd0/4chan-x/blob/master/LICENSE diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index 408883484..40c6b1abc 100644 --- a/builds/4chan-X.user.js +++ b/builds/4chan-X.user.js @@ -24,7 +24,7 @@ // ==/UserScript== /* -* 4chan X - Version 1.7.33 - 2014-05-29 +* 4chan X - Version 1.7.33 - 2014-06-22 * * Licensed under the MIT license. * https://github.com/ccd0/4chan-x/blob/master/LICENSE @@ -215,7 +215,6 @@ 'Persistent QR': [true, 'The Quick reply won\'t disappear after posting.'], 'Auto Hide QR': [true, 'Automatically hide the quick reply when posting.'], 'Open Post in New Tab': [true, 'Open new threads or replies to a thread from the index in a new tab.'], - 'Remember Subject': [false, 'Remember the subject field, instead of resetting after posting.'], 'Remember QR Size': [false, 'Remember the size of the Quick reply.'], 'Remember Spoiler': [false, 'Remember the spoiler state, instead of resetting after posting.'], 'Hide Original Post Form': [true, 'Hide the normal post form.'], @@ -655,6 +654,9 @@ if (root == null) { root = d; } + if ((detail != null) && typeof cloneInto === 'function') { + detail = cloneInto(detail, d.defaultView); + } return root.dispatchEvent(new CustomEvent(event, { bubbles: true, detail: detail @@ -1961,8 +1963,8 @@ Header = { init: function() { var barFixedToggler, barPositionToggler, customNavToggler, editCustomNav, footerToggler, headerToggler, linkJustifyToggler, menuButton, scrollHeaderToggler, shortcutToggler; - this.menu = new UI.Menu('header'); - menuButton = $.el('span', { + this.menu = new UI.Menu(); + menuButton = $.el('a', { className: 'menu-button', innerHTML: '' }); @@ -2025,8 +2027,7 @@ $.sync('Header auto-hide', this.setBarVisibility); $.sync('Centered links', this.setLinkJustify); this.addShortcut(menuButton); - $.event('AddMenuEntry', { - type: 'header', + this.menu.addEntry({ el: $.el('span', { textContent: 'Header' }), @@ -2473,7 +2474,7 @@ className: 'shortcut brackets-wrap' }); $.add(shortcut, el); - return $.prepend(Header.shortcuts, shortcut); + return $.add(Header.shortcuts, shortcut); }, rmShortcut: function(el) { return $.rm(el.parentElement); @@ -2482,12 +2483,9 @@ return Header.menu.toggle(e, this, g); }, createNotification: function(e) { - var cb, content, lifetime, notice, type, _ref; - _ref = e.detail, type = _ref.type, content = _ref.content, lifetime = _ref.lifetime, cb = _ref.cb; - notice = new Notice(type, content, lifetime); - if (cb) { - return cb(notice); - } + var content, lifetime, notice, type, _ref; + _ref = e.detail, type = _ref.type, content = _ref.content, lifetime = _ref.lifetime; + return notice = new Notice(type, content, lifetime); }, areNotificationsEnabled: false, enableDesktopNotifications: function() { @@ -2630,8 +2628,7 @@ $.on(input, 'change', this.cb.replies); } } - $.event('AddMenuEntry', { - type: 'header', + Header.menu.addEntry({ el: $.el('span', { textContent: 'Index Navigation' }), @@ -2748,8 +2745,7 @@ if (g.VIEW !== 'index' || !Conf['Menu'] || g.BOARD.ID === 'f') { return; } - return $.event('AddMenuEntry', { - type: 'post', + return Menu.menu.addEntry({ el: $.el('a', { href: 'javascript:;' }), @@ -3023,7 +3019,7 @@ } onSameIndex = g.VIEW === 'index' && a.pathname.split('/')[1] === g.BOARD.ID; needChange = Index.cb.indexNav(a, onSameIndex); - if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || !onSameIndex) { + if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || !onSameIndex || g.BOARD.ID === 'f') { return; } e.preventDefault(); @@ -3554,8 +3550,7 @@ if (!infinite) { $.rmAll(Index.root); } - $.add(Index.root, nodes); - return $.event('IndexBuild', nodes); + return $.add(Index.root, nodes); }, isSearching: false, clearSearch: function() { @@ -4216,15 +4211,11 @@ lastToggledButton = null; - function Menu(type) { - this.type = type; + function Menu() { this.rmEntry = __bind(this.rmEntry, this); - this.addEntry = __bind(this.addEntry, this); this.onFocus = __bind(this.onFocus, this); this.keybinds = __bind(this.keybinds, this); this.close = __bind(this.close, this); - $.on(d, 'AddMenuEntry', this.addEntry); - $.on(d, 'rmMenuEntry', this.rmEntry); this.entries = []; } @@ -4422,12 +4413,7 @@ return style.right = right; }; - Menu.prototype.addEntry = function(e) { - var entry; - entry = e.detail; - if (entry.type !== this.type) { - return; - } + Menu.prototype.addEntry = function(entry) { this.parseEntry(entry); return this.entries.push(entry); }; @@ -4854,7 +4840,6 @@ textContent: 'Filter' }); entry = { - type: 'post', el: div, order: 50, open: function(post) { @@ -4868,7 +4853,7 @@ type = _ref[_i]; entry.subEntries.push(Filter.menu.createSubEntry(type[0], type[1])); } - return $.event('AddMenuEntry', entry); + return Menu.menu.addEntry(entry); }, createSubEntry: function(text, type) { var el; @@ -5047,8 +5032,7 @@ innerHTML: " Make stub" }) }; - $.event('AddMenuEntry', { - type: 'post', + Menu.menu.addEntry({ el: $.el('div', { textContent: 'Hide post', className: 'hide-post-link' @@ -5099,8 +5083,7 @@ return true; } }; - $.event('AddMenuEntry', { - type: 'post', + Menu.menu.addEntry({ el: $.el('div', { textContent: 'Unhide post', className: 'show-post-link' @@ -5124,8 +5107,7 @@ if (g.VIEW !== 'index') { return; } - return $.event('AddMenuEntry', { - type: 'post', + return Menu.menu.addEntry({ el: $.el('a', { href: 'javascript:;' }), @@ -5716,8 +5698,7 @@ }); input = $('input', this.controls); $.on(input, 'change', this.toggle); - $.event('AddMenuEntry', this.entry = { - type: 'header', + Header.menu.addEntry(this.entry = { el: this.controls, order: 98 }); @@ -6024,16 +6005,6 @@ } }); $.before($.id('togglePostFormLink'), 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); - }); $.on(d, 'dragover', QR.dragOver); $.on(d, 'drop', QR.dropFile); $.on(d, 'dragstart dragend', QR.drag); @@ -6622,9 +6593,8 @@ return $.add(nodes.form, flag); } }, - preSubmitHooks: [], submit: function(e) { - var challenge, err, extra, filetag, formData, hook, options, post, response, textOnly, thread, threadID, _i, _len, _ref, _ref1; + var challenge, err, extra, filetag, formData, options, post, response, textOnly, thread, threadID, _ref; if (e != null) { e.preventDefault(); } @@ -6657,17 +6627,9 @@ err = 'No file selected.'; } else if (post.file && thread.fileLimit) { err = 'Max limit of image replies has been reached.'; - } else { - _ref = QR.preSubmitHooks; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - hook = _ref[_i]; - if (err = hook(post, thread)) { - break; - } - } } if (QR.captcha.isEnabled && !err) { - _ref1 = QR.captcha.getOne(), challenge = _ref1.challenge, response = _ref1.response; + _ref = QR.captcha.getOne(), challenge = _ref.challenge, response = _ref.response; if (!response) { err = 'No valid captcha.'; } @@ -6802,11 +6764,12 @@ }); ThreadUpdater.postID = postID; $.event('QRPostSuccessful', { - board: g.BOARD, + boardID: g.BOARD.ID, threadID: threadID, postID: postID }); $.event('QRPostSuccessful_', { + boardID: g.BOARD.ID, threadID: threadID, postID: postID }); @@ -6978,7 +6941,7 @@ } if (response) { response = response.trim(); - if (!/\s/.test(response)) { + if (!/\s|^\d+$/.test(response)) { response = "" + response + " " + response; } } @@ -7423,8 +7386,7 @@ rectEl = this.nodes.el.getBoundingClientRect(); rectList = this.nodes.el.parentNode.getBoundingClientRect(); this.nodes.el.parentNode.scrollLeft += rectEl.left + rectEl.width / 2 - rectList.left - rectList.width / 2; - this.load(); - return $.event('QRPostSelection', this); + return this.load(); }; _Class.prototype.load = function() { @@ -7719,8 +7681,7 @@ }); FappeTyme[lc] = input = el.firstElementChild; $.on(input, 'change', FappeTyme.cb.toggle.bind(input)); - $.event('AddMenuEntry', { - type: 'header', + Header.menu.addEntry({ el: el, order: 97 }); @@ -7806,7 +7767,7 @@ nodes[key] = $(value, dialog); } menuButton = $('.menu-button', dialog); - nodes.menu = new UI.Menu('gallery'); + nodes.menu = new UI.Menu(); cb = Gallery.cb; $.on(nodes.frame, 'click', cb.blank); $.on(nodes.next, 'click', cb.advance); @@ -7819,8 +7780,7 @@ createSubEntry = Gallery.menu.createSubEntry; for (name in Config.gallery) { el = createSubEntry(name).el; - $.event('AddMenuEntry', { - type: 'gallery', + nodes.menu.addEntry({ el: el, order: 0 }); @@ -8049,8 +8009,7 @@ for (name in Config.gallery) { subEntries.push(createSubEntry(name)); } - return $.event('AddMenuEntry', { - type: 'header', + return Header.menu.addEntry({ el: el, order: 105, subEntries: subEntries @@ -8423,8 +8382,7 @@ conf = _ref[name]; subEntries.push(createSubEntry(name, conf[1])); } - return $.event('AddMenuEntry', { - type: 'header', + return Header.menu.addEntry({ el: el, order: 105, subEntries: subEntries @@ -8602,8 +8560,7 @@ }); this.el = prefetch.firstElementChild; $.on(this.el, 'change', this.toggle); - return $.event('AddMenuEntry', { - type: 'header', + return Header.menu.addEntry({ el: prefetch, order: 104 }); @@ -9363,7 +9320,6 @@ textContent: 'Archive' }); entry = { - type: 'post', el: div, order: 90, open: function(_arg) { @@ -9382,7 +9338,7 @@ type = _ref[_i]; entry.subEntries.push(this.createSubEntry(type[0], type[1])); } - return $.event('AddMenuEntry', entry); + return Menu.menu.addEntry(entry); }, createSubEntry: function(text, type) { var el, open; @@ -9459,8 +9415,7 @@ return true; } }; - return $.event('AddMenuEntry', { - type: 'post', + return Menu.menu.addEntry({ el: div, order: 40, open: function(post) { @@ -9568,8 +9523,7 @@ className: 'download-link', textContent: 'Download file' }); - return $.event('AddMenuEntry', { - type: 'post', + return Menu.menu.addEntry({ el: a, order: 100, open: function(_arg) { @@ -9591,8 +9545,7 @@ if (!Conf['Menu']) { return; } - return $.event('AddMenuEntry', { - type: 'post', + return Menu.menu.addEntry({ el: $.el('div', { textContent: 'Labels' }), @@ -9630,7 +9583,7 @@ innerHTML: '', href: 'javascript:;' }); - this.menu = new UI.Menu('post'); + this.menu = new UI.Menu(); Post.callbacks.push({ name: 'Menu', cb: this.node @@ -9683,8 +9636,7 @@ textContent: 'Report this post' }); $.on(a, 'click', ReportLink.report); - return $.event('AddMenuEntry', { - type: 'post', + return Menu.menu.addEntry({ el: a, order: 10, open: function(post) { @@ -9945,8 +9897,7 @@ subEntries.push({ el: this.settings }); - $.event('AddMenuEntry', this.entry = { - type: 'header', + Header.menu.addEntry(this.entry = { el: $.el('span', { textContent: 'Updater' }), @@ -10097,7 +10048,7 @@ ThreadUpdater.thread.kill(); $.event('ThreadUpdate', { 404: true, - thread: ThreadUpdater.thread + threadID: ThreadUpdater.thread.fullID }); break; default: @@ -10196,7 +10147,7 @@ return new Notice('info', "The thread is " + change + ".", 30); }, parse: function(postObjects) { - var OP, count, deletedFiles, deletedPosts, files, index, node, num, post, postObject, posts, root, scroll, sendEvent, _i, _j, _len, _len1; + var OP, count, files, index, node, num, post, postObject, posts, root, scroll, sendEvent, _i, _j, _len, _len1; OP = postObjects[0]; Build.spoilerRange[ThreadUpdater.thread.board] = OP.custom_spoiler; ThreadUpdater.updateThreadStatus('Sticky', !!OP.sticky); @@ -10221,19 +10172,15 @@ node = Build.postFromObject(postObject, ThreadUpdater.thread.board.ID); posts.push(new Post(node, ThreadUpdater.thread, ThreadUpdater.thread.board)); } - deletedPosts = []; - deletedFiles = []; ThreadUpdater.thread.posts.forEach(function(post) { var ID; ID = +post.ID; if (__indexOf.call(index, ID) < 0) { post.kill(); - deletedPosts.push(post); } else if (post.isDead) { post.resurrect(); - } else if (post.file && !(post.file.isDead || __indexOf.call(files, ID) >= 0)) { + } else if (post.file && !post.file.isDead && __indexOf.call(files, ID) < 0) { post.kill(true); - deletedFiles.push(post); } if (ThreadUpdater.postID && ThreadUpdater.postID === ID) { return ThreadUpdater.foundPost = true; @@ -10242,10 +10189,10 @@ sendEvent = function() { return $.event('ThreadUpdate', { 404: false, - thread: ThreadUpdater.thread, - newPosts: posts, - deletedPosts: deletedPosts, - deletedFiles: deletedFiles, + threadID: ThreadUpdater.thread.fullID, + newPosts: posts.map(function(post) { + return post.fullID; + }), postCount: OP.replies + 1, fileCount: OP.images + (!!ThreadUpdater.thread.OP.file && !ThreadUpdater.thread.OP.file.isDead) }); @@ -10420,14 +10367,14 @@ 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; + var boardID, postID, threadID, _ref; + _ref = e.detail, boardID = _ref.boardID, threadID = _ref.threadID, postID = _ref.postID; if (postID === threadID) { if (Conf['Auto Watch']) { return $.set('AutoWatch', threadID); } } else if (Conf['Auto Watch Reply']) { - return ThreadWatcher.add(board.threads[threadID]); + return ThreadWatcher.add(g.threads[boardID + '.' + threadID]); } }, onIndexRefresh: function() { @@ -10456,7 +10403,7 @@ }, onThreadRefresh: function(e) { var thread; - thread = e.detail.thread; + thread = g.threads[e.detail.threadID]; if (!(e.detail[404] && ThreadWatcher.db.get({ boardID: thread.board.ID, threadID: thread.ID @@ -10668,12 +10615,12 @@ if (!Conf['Thread Watcher']) { return; } - menu = new UI.Menu('thread watcher'); + menu = new UI.Menu(); $.on($('.menu-button', ThreadWatcher.dialog), 'click', function(e) { return menu.toggle(e, this, ThreadWatcher); }); this.addHeaderMenuEntry(); - return this.addMenuEntries(); + return this.addMenuEntries(menu); }, addHeaderMenuEntry: function() { var entryEl; @@ -10683,8 +10630,7 @@ entryEl = $.el('a', { href: 'javascript:;' }); - $.event('AddMenuEntry', { - type: 'header', + Header.menu.addEntry({ el: entryEl, order: 60 }); @@ -10699,13 +10645,12 @@ return entryEl.textContent = text; }); }, - addMenuEntries: function() { + addMenuEntries: function(menu) { var cb, conf, entries, entry, name, refresh, subEntries, _i, _len, _ref, _ref1; entries = []; entries.push({ cb: ThreadWatcher.cb.openAll, entry: { - type: 'thread watcher', el: $.el('a', { textContent: 'Open all threads' }) @@ -10717,7 +10662,6 @@ entries.push({ cb: ThreadWatcher.cb.checkThreads, entry: { - type: 'thread watcher', el: $.el('a', { textContent: 'Check 404\'d threads' }) @@ -10729,7 +10673,6 @@ entries.push({ cb: ThreadWatcher.cb.pruneDeads, entry: { - type: 'thread watcher', el: $.el('a', { textContent: 'Prune 404\'d threads' }) @@ -10746,7 +10689,6 @@ } entries.push({ entry: { - type: 'thread watcher', el: $.el('span', { textContent: 'Settings' }), @@ -10764,7 +10706,7 @@ if (refresh) { this.refreshers.push(refresh.bind(entry)); } - $.event('AddMenuEntry', entry); + menu.addEntry(entry); } }, createSubEntry: function(name, desc) { @@ -10964,11 +10906,13 @@ onUpdate: function(e) { if (e.detail[404]) { return Unread.update(); - } else if (!Conf['Quote Threading']) { - return Unread.addPosts(e.detail.newPosts); - } else { + } else if (Conf['Quote Threading']) { Unread.read(); return Unread.update(); + } else { + return Unread.addPosts(e.detail.newPosts.map(function(fullID) { + return g.posts[fullID]; + })); } }, readSinglePost: function(post) { @@ -11114,7 +11058,7 @@ } return Redirect.data = o; }, - archives: [{"uid":0,"name":"Foolz","domain":"archive.foolz.us","http":true,"https":true,"software":"foolfuuka","boards":["a","biz","co","diy","gd","jp","m","sci","sp","tg","tv","vg","vp","vr","wsg"],"files":["a","biz","diy","gd","jp","m","sci","tg","vg","vp","vr","wsg"]},{"uid":1,"name":"NSFW Foolz","domain":"nsfw.foolz.us","http":true,"https":true,"software":"foolfuuka","boards":["u"],"files":["u"]},{"uid":2,"name":"The Dark Cave","domain":"archive.thedarkcave.org","http":true,"https":true,"software":"foolfuuka","boards":["c","int","out","po"],"files":["c","po"]},{"uid":3,"name":"4plebs Archive","domain":"archive.4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["adv","hr","o","pol","s4s","tg","trv","tv","x"],"files":["adv","hr","o","pol","s4s","tg","trv","tv","x"]},{"uid":18,"name":"4plebs Flash Archive","domain":"flash.4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["f"],"files":["f"]},{"uid":4,"name":"Nyafuu","domain":"archive.nyafuu.org","http":true,"https":true,"software":"foolfuuka","boards":["c","e","w","wg"],"files":["c","e","w","wg"]},{"uid":5,"name":"Love is Over","domain":"archive.loveisover.me","http":true,"https":true,"software":"foolfuuka","boards":["d","i","lgbt"],"files":["d","i","lgbt"]},{"uid":8,"name":"Rebecca Black Tech","domain":"rbt.asia","http":false,"https":true,"software":"fuuka","boards":["cgl","g","mu","w"],"files":["cgl","g","mu","w"]},{"uid":9,"name":"Heinessen","domain":"archive.heinessen.com","http":true,"https":false,"software":"fuuka","boards":["an","fit","k","mlp","r9k","toy"],"files":["an","fit","k","mlp","r9k","toy"]},{"uid":10,"name":"warosu","domain":"fuuka.warosu.org","http":false,"https":true,"software":"fuuka","boards":["3","biz","cgl","ck","diy","fa","g","ic","jp","lit","sci","tg","vr"],"files":["3","biz","cgl","ck","diy","fa","ic","jp","lit","sci","tg","vr"]},{"uid":15,"name":"fgts","domain":"fgts.eu","http":true,"https":true,"software":"foolfuuka","boards":["asp","cm","h","hc","hm","n","p","r","s","soc","y"],"files":["asp","cm","h","hc","hm","n","p","r","s","soc","y"]},{"uid":16,"name":"maware","domain":"archive.mawa.re","http":true,"https":false,"software":"foolfuuka","boards":["t"],"files":["t"]},{"uid":17,"name":"installgentoo.com","domain":"chan.installgentoo.com","http":true,"https":false,"software":"foolfuuka","boards":["g","t"],"files":["g","t"]},{"uid":19,"name":"Innovandalism Archive","domain":"boards.innovandalism.eu","http":true,"https":false,"software":"foolfuuka","boards":["v"],"files":[]},{"uid":13,"name":"Foolz Beta","domain":"beta.foolz.us","http":true,"https":true,"withCredentials":true,"software":"foolfuuka","boards":["a","biz","co","d","diy","gd","jp","m","s4s","sci","sp","tg","tv","u","vg","vp","vr","wsg"],"files":["a","biz","d","diy","gd","jp","m","s4s","sci","tg","u","vg","vp","vr","wsg"]},{"uid":19,"name":"Innovandalism Archive","domain":"boards.innovandalism.eu","http":true,"https":false,"software":"foolfuuka","boards":["v"],"files":[]}], + archives: [{"uid":0,"name":"Foolz","domain":"archive.foolz.us","http":true,"https":true,"software":"foolfuuka","boards":["a","biz","c","co","diy","gd","int","jp","m","out","po","sci","sp","tg","tv","vg","vp","vr","wsg"],"files":["a","biz","c","co","diy","gd","jp","m","po","sci","tg","vg","vp","vr","wsg"]},{"uid":1,"name":"NSFW Foolz","domain":"nsfw.foolz.us","http":true,"https":true,"software":"foolfuuka","boards":["u"],"files":["u"]},{"uid":3,"name":"4plebs Archive","domain":"archive.4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["adv","f","hr","o","pol","s4s","tg","trv","tv","x"],"files":["adv","f","hr","o","pol","s4s","tg","trv","tv","x"]},{"uid":4,"name":"Nyafuu","domain":"archive.nyafuu.org","http":true,"https":true,"software":"foolfuuka","boards":["c","e","w","wg"],"files":["c","e","w","wg"]},{"uid":5,"name":"Love is Over","domain":"archive.loveisover.me","http":true,"https":true,"software":"foolfuuka","boards":["d","i","lgbt"],"files":["d","i","lgbt"]},{"uid":8,"name":"Rebecca Black Tech","domain":"archive.rebeccablacktech.com","http":false,"https":true,"software":"fuuka","boards":["cgl","g","mu","w"],"files":["cgl","g","mu","w"]},{"uid":9,"name":"Heinessen","domain":"archive.heinessen.com","http":true,"https":false,"software":"fuuka","boards":["an","fit","k","mlp","r9k","toy"],"files":["an","fit","k","mlp","r9k","toy"]},{"uid":10,"name":"warosu","domain":"warosu.org","http":false,"https":true,"software":"fuuka","boards":["3","biz","cgl","ck","diy","fa","g","ic","jp","lit","sci","tg","vr"],"files":["3","biz","cgl","ck","diy","fa","ic","jp","lit","sci","tg","vr"]},{"uid":15,"name":"fgts","domain":"fgts.jp","http":true,"https":true,"software":"foolfuuka","boards":["asp","cm","h","hc","hm","n","p","r","s","soc","y"],"files":["asp","cm","h","hc","hm","n","p","r","s","soc","y"]},{"uid":16,"name":"maware","domain":"archive.mawa.re","http":true,"https":false,"software":"foolfuuka","boards":["t"],"files":["t"]},{"uid":19,"name":"Deniable Plausibility","domain":"boards.deniableplausibility.net","http":true,"https":false,"software":"foolfuuka","boards":["v","vg"],"files":["v","vg"]},{"uid":19,"name":"Innovandalism Archive","domain":"boards.innovandalism.eu","http":true,"https":false,"software":"foolfuuka","boards":["v"],"files":[]},{"uid":13,"name":"Foolz Beta","domain":"beta.foolz.us","http":true,"https":true,"withCredentials":true,"software":"foolfuuka","boards":["a","biz","c","co","d","diy","gd","int","jp","m","out","po","s4s","sci","sp","tg","tv","u","vg","vp","vr","wsg"],"files":["a","biz","c","co","d","diy","gd","jp","m","po","s4s","sci","tg","u","vg","vp","vr","wsg"]}], to: function(dest, data) { var archive; archive = (dest === 'search' || dest === 'board' ? Redirect.data.thread : Redirect.data[dest])[data.boardID]; @@ -11183,7 +11127,6 @@ return; } entry = { - type: 'header', el: $.el('a', { textContent: 'Show announcement', className: 'show-announcement', @@ -11194,7 +11137,7 @@ return psa.hidden; } }; - $.event('AddMenuEntry', entry); + Header.menu.addEntry(entry); $.on(entry.el, 'click', PSAHiding.toggle); PSAHiding.btn = btn = $.el('span', { innerHTML: '[Dismiss]', @@ -11352,8 +11295,7 @@ input = $('input', el); $.on(input, 'change', this.toggle); $.sync('Header catalog links', CatalogLinks.set); - $.event('AddMenuEntry', { - type: 'header', + Header.menu.addEntry({ el: el, order: 95 }); @@ -11885,7 +11827,7 @@ }); } if (board === 'sci') { - $.globalEval("window.addEventListener('jsmath', function(e) {\n if (jsMath.loaded) {\n // process one post\n jsMath.ProcessBeforeShowing(e.detail);\n } else {\n // load jsMath and process whole document\n jsMath.Autoload.Script.Push('ProcessBeforeShowing', [null]);\n jsMath.Autoload.LoadJsMath();\n }\n}, false);"); + $.globalEval("window.addEventListener('jsmath', function(e) {\n if (jsMath.loaded) {\n // process one post\n jsMath.ProcessBeforeShowing(document.getElementById(e.detail));\n } else {\n // load jsMath and process whole document\n jsMath.Autoload.Script.Push('ProcessBeforeShowing', [null]);\n jsMath.Autoload.LoadJsMath();\n }\n}, false);"); return Post.callbacks.push({ name: 'Parse /sci/ math', cb: this.math @@ -11912,7 +11854,7 @@ if (this.isClone || !$('.math', this.nodes.comment)) { return; } - return $.event('jsmath', this.nodes.post, window); + return $.event('jsmath', this.nodes.post.id, window); } }; @@ -12215,31 +12157,31 @@ } break; case Conf['Next thread']: - if (g.VIEW !== 'index') { + if (g.VIEW !== 'index' || Conf['Index Mode'] === 'catalog') { return; } Nav.scroll(+1); break; case Conf['Previous thread']: - if (g.VIEW !== 'index') { + if (g.VIEW !== 'index' || Conf['Index Mode'] === 'catalog') { return; } Nav.scroll(-1); break; case Conf['Expand thread']: - if (g.VIEW !== 'index') { + if (g.VIEW !== 'index' || Conf['Index Mode'] === 'catalog') { return; } ExpandThread.toggle(thread); break; case Conf['Open thread']: - if (g.VIEW !== 'index') { + if (g.VIEW !== 'index' || Conf['Index Mode'] === 'catalog') { return; } Keybinds.open(thread); break; case Conf['Open thread tab']: - if (g.VIEW !== 'index') { + if (g.VIEW !== 'index' || Conf['Index Mode'] === 'catalog') { return; } Keybinds.open(thread, true); @@ -12628,7 +12570,7 @@ var response; e.preventDefault(); response = field.value.trim(); - if (!/\s/.test(response)) { + if (!/\s|^\d+$/.test(response)) { field.value = "" + response + " " + response; } return this.submit(); @@ -13174,7 +13116,6 @@ Settings.addSection('Sauce', Settings.sauce); Settings.addSection('Advanced', Settings.advanced); Settings.addSection('Keybinds', Settings.keybinds); - $.on(d, 'AddSettingsSection', Settings.addSection); $.on(d, 'OpenSettings', function(e) { return Settings.open(e.detail); }); @@ -13238,10 +13179,7 @@ }, sections: [], addSection: function(title, open) { - var hyphenatedTitle, _ref; - if (typeof title !== 'string') { - _ref = title.detail, title = _ref.title, open = _ref.open; - } + var hyphenatedTitle; hyphenatedTitle = title.toLowerCase().replace(/\s+/g, '-'); return Settings.sections.push({ title: title, @@ -13923,7 +13861,6 @@ init('Banner', Banner); init('Navigate', Navigate); init('Flash Features', Flash); - $.on(d, 'AddCallback', Main.addCallback); return $.ready(Main.initReady); }, initStyle: function() { @@ -14071,25 +14008,6 @@ return $.set('previousversion', g.VERSION); }); }, - addCallback: function(e) { - var Klass, obj; - obj = e.detail; - if (typeof obj.callback.name !== 'string') { - throw new Error("Invalid callback name: " + obj.callback.name); - } - switch (obj.type) { - case 'Post': - Klass = Post; - break; - case 'Thread': - Klass = Thread; - break; - default: - return; - } - obj.callback.isAddon = true; - return Klass.callbacks.push(obj.callback); - }, handleErrors: function(errors) { var div, error, logs, _i, _len; if (!(errors instanceof Array)) { diff --git a/builds/crx/script.js b/builds/crx/script.js index 901610e8a..5afed68d6 100644 --- a/builds/crx/script.js +++ b/builds/crx/script.js @@ -1,6 +1,6 @@ // Generated by CoffeeScript /* -* 4chan X - Version 1.7.33 - 2014-05-29 +* 4chan X - Version 1.7.33 - 2014-06-22 * * Licensed under the MIT license. * https://github.com/ccd0/4chan-x/blob/master/LICENSE @@ -170,7 +170,6 @@ 'Report Link': [true, 'Add a report link to the menu.'], 'Post Hiding Link': [true, 'Add a link to hide posts.'], 'Delete Link': [true, 'Add post and image deletion links to the menu.'], - 'Download Link': [true, 'Add a download with original filename link to the menu. Chrome-only currently.'], 'Archive Link': [true, 'Add an archive link to the menu.'] }, 'Monitoring': { @@ -192,7 +191,6 @@ 'Persistent QR': [true, 'The Quick reply won\'t disappear after posting.'], 'Auto Hide QR': [true, 'Automatically hide the quick reply when posting.'], 'Open Post in New Tab': [true, 'Open new threads or replies to a thread from the index in a new tab.'], - 'Remember Subject': [false, 'Remember the subject field, instead of resetting after posting.'], 'Remember Spoiler': [false, 'Remember the spoiler state, instead of resetting after posting.'], 'Hide Original Post Form': [true, 'Hide the normal post form.'], 'Cooldown': [true, 'Indicate the remaining time before posting again.'], @@ -2020,8 +2018,8 @@ Header = { init: function() { var barFixedToggler, barPositionToggler, customNavToggler, editCustomNav, footerToggler, headerToggler, linkJustifyToggler, menuButton, scrollHeaderToggler, shortcutToggler; - this.menu = new UI.Menu('header'); - menuButton = $.el('span', { + this.menu = new UI.Menu(); + menuButton = $.el('a', { className: 'menu-button', innerHTML: '' }); @@ -2084,8 +2082,7 @@ $.sync('Header auto-hide', this.setBarVisibility); $.sync('Centered links', this.setLinkJustify); this.addShortcut(menuButton); - $.event('AddMenuEntry', { - type: 'header', + this.menu.addEntry({ el: $.el('span', { textContent: 'Header' }), @@ -2532,7 +2529,7 @@ className: 'shortcut brackets-wrap' }); $.add(shortcut, el); - return $.prepend(Header.shortcuts, shortcut); + return $.add(Header.shortcuts, shortcut); }, rmShortcut: function(el) { return $.rm(el.parentElement); @@ -2541,12 +2538,9 @@ return Header.menu.toggle(e, this, g); }, createNotification: function(e) { - var cb, content, lifetime, notice, type, _ref; - _ref = e.detail, type = _ref.type, content = _ref.content, lifetime = _ref.lifetime, cb = _ref.cb; - notice = new Notice(type, content, lifetime); - if (cb) { - return cb(notice); - } + var content, lifetime, notice, type, _ref; + _ref = e.detail, type = _ref.type, content = _ref.content, lifetime = _ref.lifetime; + return notice = new Notice(type, content, lifetime); }, areNotificationsEnabled: false, enableDesktopNotifications: function() { @@ -2689,8 +2683,7 @@ $.on(input, 'change', this.cb.replies); } } - $.event('AddMenuEntry', { - type: 'header', + Header.menu.addEntry({ el: $.el('span', { textContent: 'Index Navigation' }), @@ -2807,8 +2800,7 @@ if (g.VIEW !== 'index' || !Conf['Menu'] || g.BOARD.ID === 'f') { return; } - return $.event('AddMenuEntry', { - type: 'post', + return Menu.menu.addEntry({ el: $.el('a', { href: 'javascript:;' }), @@ -3082,7 +3074,7 @@ } onSameIndex = g.VIEW === 'index' && a.pathname.split('/')[1] === g.BOARD.ID; needChange = Index.cb.indexNav(a, onSameIndex); - if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || !onSameIndex) { + if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || !onSameIndex || g.BOARD.ID === 'f') { return; } e.preventDefault(); @@ -3613,8 +3605,7 @@ if (!infinite) { $.rmAll(Index.root); } - $.add(Index.root, nodes); - return $.event('IndexBuild', nodes); + return $.add(Index.root, nodes); }, isSearching: false, clearSearch: function() { @@ -4275,15 +4266,11 @@ lastToggledButton = null; - function Menu(type) { - this.type = type; + function Menu() { this.rmEntry = __bind(this.rmEntry, this); - this.addEntry = __bind(this.addEntry, this); this.onFocus = __bind(this.onFocus, this); this.keybinds = __bind(this.keybinds, this); this.close = __bind(this.close, this); - $.on(d, 'AddMenuEntry', this.addEntry); - $.on(d, 'rmMenuEntry', this.rmEntry); this.entries = []; } @@ -4481,12 +4468,7 @@ return style.right = right; }; - Menu.prototype.addEntry = function(e) { - var entry; - entry = e.detail; - if (entry.type !== this.type) { - return; - } + Menu.prototype.addEntry = function(entry) { this.parseEntry(entry); return this.entries.push(entry); }; @@ -4906,7 +4888,6 @@ textContent: 'Filter' }); entry = { - type: 'post', el: div, order: 50, open: function(post) { @@ -4920,7 +4901,7 @@ type = _ref[_i]; entry.subEntries.push(Filter.menu.createSubEntry(type[0], type[1])); } - return $.event('AddMenuEntry', entry); + return Menu.menu.addEntry(entry); }, createSubEntry: function(text, type) { var el; @@ -5099,8 +5080,7 @@ innerHTML: " Make stub" }) }; - $.event('AddMenuEntry', { - type: 'post', + Menu.menu.addEntry({ el: $.el('div', { textContent: 'Hide post', className: 'hide-post-link' @@ -5151,8 +5131,7 @@ return true; } }; - $.event('AddMenuEntry', { - type: 'post', + Menu.menu.addEntry({ el: $.el('div', { textContent: 'Unhide post', className: 'show-post-link' @@ -5176,8 +5155,7 @@ if (g.VIEW !== 'index') { return; } - return $.event('AddMenuEntry', { - type: 'post', + return Menu.menu.addEntry({ el: $.el('a', { href: 'javascript:;' }), @@ -5768,8 +5746,7 @@ }); input = $('input', this.controls); $.on(input, 'change', this.toggle); - $.event('AddMenuEntry', this.entry = { - type: 'header', + Header.menu.addEntry(this.entry = { el: this.controls, order: 98 }); @@ -6076,16 +6053,6 @@ } }); $.before($.id('togglePostFormLink'), 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); - }); $.on(d, 'paste', QR.paste); $.on(d, 'dragover', QR.dragOver); $.on(d, 'drop', QR.dropFile); @@ -6669,9 +6636,8 @@ return $.add(nodes.form, flag); } }, - preSubmitHooks: [], submit: function(e) { - var challenge, err, extra, filetag, formData, hook, options, post, response, textOnly, thread, threadID, _i, _len, _ref, _ref1; + var challenge, err, extra, filetag, formData, options, post, response, textOnly, thread, threadID, _ref; if (e != null) { e.preventDefault(); } @@ -6704,17 +6670,9 @@ err = 'No file selected.'; } else if (post.file && thread.fileLimit) { err = 'Max limit of image replies has been reached.'; - } else { - _ref = QR.preSubmitHooks; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - hook = _ref[_i]; - if (err = hook(post, thread)) { - break; - } - } } if (QR.captcha.isEnabled && !err) { - _ref1 = QR.captcha.getOne(), challenge = _ref1.challenge, response = _ref1.response; + _ref = QR.captcha.getOne(), challenge = _ref.challenge, response = _ref.response; if (!response) { err = 'No valid captcha.'; } @@ -6849,11 +6807,12 @@ }); ThreadUpdater.postID = postID; $.event('QRPostSuccessful', { - board: g.BOARD, + boardID: g.BOARD.ID, threadID: threadID, postID: postID }); $.event('QRPostSuccessful_', { + boardID: g.BOARD.ID, threadID: threadID, postID: postID }); @@ -7025,7 +6984,7 @@ } if (response) { response = response.trim(); - if (!/\s/.test(response)) { + if (!/\s|^\d+$/.test(response)) { response = "" + response + " " + response; } } @@ -7464,8 +7423,7 @@ rectEl = this.nodes.el.getBoundingClientRect(); rectList = this.nodes.el.parentNode.getBoundingClientRect(); this.nodes.el.parentNode.scrollLeft += rectEl.left + rectEl.width / 2 - rectList.left - rectList.width / 2; - this.load(); - return $.event('QRPostSelection', this); + return this.load(); }; _Class.prototype.load = function() { @@ -7757,8 +7715,7 @@ }); FappeTyme[lc] = input = el.firstElementChild; $.on(input, 'change', FappeTyme.cb.toggle.bind(input)); - $.event('AddMenuEntry', { - type: 'header', + Header.menu.addEntry({ el: el, order: 97 }); @@ -7844,7 +7801,7 @@ nodes[key] = $(value, dialog); } menuButton = $('.menu-button', dialog); - nodes.menu = new UI.Menu('gallery'); + nodes.menu = new UI.Menu(); cb = Gallery.cb; $.on(nodes.frame, 'click', cb.blank); $.on(nodes.next, 'click', cb.advance); @@ -7857,8 +7814,7 @@ createSubEntry = Gallery.menu.createSubEntry; for (name in Config.gallery) { el = createSubEntry(name).el; - $.event('AddMenuEntry', { - type: 'gallery', + nodes.menu.addEntry({ el: el, order: 0 }); @@ -8087,8 +8043,7 @@ for (name in Config.gallery) { subEntries.push(createSubEntry(name)); } - return $.event('AddMenuEntry', { - type: 'header', + return Header.menu.addEntry({ el: el, order: 105, subEntries: subEntries @@ -8450,8 +8405,7 @@ conf = _ref[name]; subEntries.push(createSubEntry(name, conf[1])); } - return $.event('AddMenuEntry', { - type: 'header', + return Header.menu.addEntry({ el: el, order: 105, subEntries: subEntries @@ -8618,8 +8572,7 @@ }); this.el = prefetch.firstElementChild; $.on(this.el, 'change', this.toggle); - return $.event('AddMenuEntry', { - type: 'header', + return Header.menu.addEntry({ el: prefetch, order: 104 }); @@ -9379,7 +9332,6 @@ textContent: 'Archive' }); entry = { - type: 'post', el: div, order: 90, open: function(_arg) { @@ -9398,7 +9350,7 @@ type = _ref[_i]; entry.subEntries.push(this.createSubEntry(type[0], type[1])); } - return $.event('AddMenuEntry', entry); + return Menu.menu.addEntry(entry); }, createSubEntry: function(text, type) { var el, open; @@ -9475,8 +9427,7 @@ return true; } }; - return $.event('AddMenuEntry', { - type: 'post', + return Menu.menu.addEntry({ el: div, order: 40, open: function(post) { @@ -9584,8 +9535,7 @@ className: 'download-link', textContent: 'Download file' }); - return $.event('AddMenuEntry', { - type: 'post', + return Menu.menu.addEntry({ el: a, order: 100, open: function(_arg) { @@ -9607,8 +9557,7 @@ if (!Conf['Menu']) { return; } - return $.event('AddMenuEntry', { - type: 'post', + return Menu.menu.addEntry({ el: $.el('div', { textContent: 'Labels' }), @@ -9646,7 +9595,7 @@ innerHTML: '', href: 'javascript:;' }); - this.menu = new UI.Menu('post'); + this.menu = new UI.Menu(); Post.callbacks.push({ name: 'Menu', cb: this.node @@ -9699,8 +9648,7 @@ textContent: 'Report this post' }); $.on(a, 'click', ReportLink.report); - return $.event('AddMenuEntry', { - type: 'post', + return Menu.menu.addEntry({ el: a, order: 10, open: function(post) { @@ -9961,8 +9909,7 @@ subEntries.push({ el: this.settings }); - $.event('AddMenuEntry', this.entry = { - type: 'header', + Header.menu.addEntry(this.entry = { el: $.el('span', { textContent: 'Updater' }), @@ -10113,7 +10060,7 @@ ThreadUpdater.thread.kill(); $.event('ThreadUpdate', { 404: true, - thread: ThreadUpdater.thread + threadID: ThreadUpdater.thread.fullID }); break; default: @@ -10212,7 +10159,7 @@ return new Notice('info', "The thread is " + change + ".", 30); }, parse: function(postObjects) { - var OP, count, deletedFiles, deletedPosts, files, index, node, num, post, postObject, posts, root, scroll, sendEvent, _i, _j, _len, _len1; + var OP, count, files, index, node, num, post, postObject, posts, root, scroll, sendEvent, _i, _j, _len, _len1; OP = postObjects[0]; Build.spoilerRange[ThreadUpdater.thread.board] = OP.custom_spoiler; ThreadUpdater.updateThreadStatus('Sticky', !!OP.sticky); @@ -10237,19 +10184,15 @@ node = Build.postFromObject(postObject, ThreadUpdater.thread.board.ID); posts.push(new Post(node, ThreadUpdater.thread, ThreadUpdater.thread.board)); } - deletedPosts = []; - deletedFiles = []; ThreadUpdater.thread.posts.forEach(function(post) { var ID; ID = +post.ID; if (__indexOf.call(index, ID) < 0) { post.kill(); - deletedPosts.push(post); } else if (post.isDead) { post.resurrect(); - } else if (post.file && !(post.file.isDead || __indexOf.call(files, ID) >= 0)) { + } else if (post.file && !post.file.isDead && __indexOf.call(files, ID) < 0) { post.kill(true); - deletedFiles.push(post); } if (ThreadUpdater.postID && ThreadUpdater.postID === ID) { return ThreadUpdater.foundPost = true; @@ -10258,10 +10201,10 @@ sendEvent = function() { return $.event('ThreadUpdate', { 404: false, - thread: ThreadUpdater.thread, - newPosts: posts, - deletedPosts: deletedPosts, - deletedFiles: deletedFiles, + threadID: ThreadUpdater.thread.fullID, + newPosts: posts.map(function(post) { + return post.fullID; + }), postCount: OP.replies + 1, fileCount: OP.images + (!!ThreadUpdater.thread.OP.file && !ThreadUpdater.thread.OP.file.isDead) }); @@ -10436,14 +10379,14 @@ 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; + var boardID, postID, threadID, _ref; + _ref = e.detail, boardID = _ref.boardID, threadID = _ref.threadID, postID = _ref.postID; if (postID === threadID) { if (Conf['Auto Watch']) { return $.set('AutoWatch', threadID); } } else if (Conf['Auto Watch Reply']) { - return ThreadWatcher.add(board.threads[threadID]); + return ThreadWatcher.add(g.threads[boardID + '.' + threadID]); } }, onIndexRefresh: function() { @@ -10472,7 +10415,7 @@ }, onThreadRefresh: function(e) { var thread; - thread = e.detail.thread; + thread = g.threads[e.detail.threadID]; if (!(e.detail[404] && ThreadWatcher.db.get({ boardID: thread.board.ID, threadID: thread.ID @@ -10684,12 +10627,12 @@ if (!Conf['Thread Watcher']) { return; } - menu = new UI.Menu('thread watcher'); + menu = new UI.Menu(); $.on($('.menu-button', ThreadWatcher.dialog), 'click', function(e) { return menu.toggle(e, this, ThreadWatcher); }); this.addHeaderMenuEntry(); - return this.addMenuEntries(); + return this.addMenuEntries(menu); }, addHeaderMenuEntry: function() { var entryEl; @@ -10699,8 +10642,7 @@ entryEl = $.el('a', { href: 'javascript:;' }); - $.event('AddMenuEntry', { - type: 'header', + Header.menu.addEntry({ el: entryEl, order: 60 }); @@ -10715,13 +10657,12 @@ return entryEl.textContent = text; }); }, - addMenuEntries: function() { + addMenuEntries: function(menu) { var cb, conf, entries, entry, name, refresh, subEntries, _i, _len, _ref, _ref1; entries = []; entries.push({ cb: ThreadWatcher.cb.openAll, entry: { - type: 'thread watcher', el: $.el('a', { textContent: 'Open all threads' }) @@ -10733,7 +10674,6 @@ entries.push({ cb: ThreadWatcher.cb.checkThreads, entry: { - type: 'thread watcher', el: $.el('a', { textContent: 'Check 404\'d threads' }) @@ -10745,7 +10685,6 @@ entries.push({ cb: ThreadWatcher.cb.pruneDeads, entry: { - type: 'thread watcher', el: $.el('a', { textContent: 'Prune 404\'d threads' }) @@ -10762,7 +10701,6 @@ } entries.push({ entry: { - type: 'thread watcher', el: $.el('span', { textContent: 'Settings' }), @@ -10780,7 +10718,7 @@ if (refresh) { this.refreshers.push(refresh.bind(entry)); } - $.event('AddMenuEntry', entry); + menu.addEntry(entry); } }, createSubEntry: function(name, desc) { @@ -10980,11 +10918,13 @@ onUpdate: function(e) { if (e.detail[404]) { return Unread.update(); - } else if (!Conf['Quote Threading']) { - return Unread.addPosts(e.detail.newPosts); - } else { + } else if (Conf['Quote Threading']) { Unread.read(); return Unread.update(); + } else { + return Unread.addPosts(e.detail.newPosts.map(function(fullID) { + return g.posts[fullID]; + })); } }, readSinglePost: function(post) { @@ -11129,7 +11069,7 @@ } return Redirect.data = o; }, - archives: [{"uid":0,"name":"Foolz","domain":"archive.foolz.us","http":true,"https":true,"software":"foolfuuka","boards":["a","biz","co","diy","gd","jp","m","sci","sp","tg","tv","vg","vp","vr","wsg"],"files":["a","biz","diy","gd","jp","m","sci","tg","vg","vp","vr","wsg"]},{"uid":1,"name":"NSFW Foolz","domain":"nsfw.foolz.us","http":true,"https":true,"software":"foolfuuka","boards":["u"],"files":["u"]},{"uid":2,"name":"The Dark Cave","domain":"archive.thedarkcave.org","http":true,"https":true,"software":"foolfuuka","boards":["c","int","out","po"],"files":["c","po"]},{"uid":3,"name":"4plebs Archive","domain":"archive.4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["adv","hr","o","pol","s4s","tg","trv","tv","x"],"files":["adv","hr","o","pol","s4s","tg","trv","tv","x"]},{"uid":18,"name":"4plebs Flash Archive","domain":"flash.4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["f"],"files":["f"]},{"uid":4,"name":"Nyafuu","domain":"archive.nyafuu.org","http":true,"https":true,"software":"foolfuuka","boards":["c","e","w","wg"],"files":["c","e","w","wg"]},{"uid":5,"name":"Love is Over","domain":"archive.loveisover.me","http":true,"https":true,"software":"foolfuuka","boards":["d","i","lgbt"],"files":["d","i","lgbt"]},{"uid":8,"name":"Rebecca Black Tech","domain":"rbt.asia","http":false,"https":true,"software":"fuuka","boards":["cgl","g","mu","w"],"files":["cgl","g","mu","w"]},{"uid":9,"name":"Heinessen","domain":"archive.heinessen.com","http":true,"https":false,"software":"fuuka","boards":["an","fit","k","mlp","r9k","toy"],"files":["an","fit","k","mlp","r9k","toy"]},{"uid":10,"name":"warosu","domain":"fuuka.warosu.org","http":false,"https":true,"software":"fuuka","boards":["3","biz","cgl","ck","diy","fa","g","ic","jp","lit","sci","tg","vr"],"files":["3","biz","cgl","ck","diy","fa","ic","jp","lit","sci","tg","vr"]},{"uid":15,"name":"fgts","domain":"fgts.eu","http":true,"https":true,"software":"foolfuuka","boards":["asp","cm","h","hc","hm","n","p","r","s","soc","y"],"files":["asp","cm","h","hc","hm","n","p","r","s","soc","y"]},{"uid":16,"name":"maware","domain":"archive.mawa.re","http":true,"https":false,"software":"foolfuuka","boards":["t"],"files":["t"]},{"uid":17,"name":"installgentoo.com","domain":"chan.installgentoo.com","http":true,"https":false,"software":"foolfuuka","boards":["g","t"],"files":["g","t"]},{"uid":19,"name":"Innovandalism Archive","domain":"boards.innovandalism.eu","http":true,"https":false,"software":"foolfuuka","boards":["v"],"files":[]},{"uid":13,"name":"Foolz Beta","domain":"beta.foolz.us","http":true,"https":true,"withCredentials":true,"software":"foolfuuka","boards":["a","biz","co","d","diy","gd","jp","m","s4s","sci","sp","tg","tv","u","vg","vp","vr","wsg"],"files":["a","biz","d","diy","gd","jp","m","s4s","sci","tg","u","vg","vp","vr","wsg"]},{"uid":19,"name":"Innovandalism Archive","domain":"boards.innovandalism.eu","http":true,"https":false,"software":"foolfuuka","boards":["v"],"files":[]}], + archives: [{"uid":0,"name":"Foolz","domain":"archive.foolz.us","http":true,"https":true,"software":"foolfuuka","boards":["a","biz","c","co","diy","gd","int","jp","m","out","po","sci","sp","tg","tv","vg","vp","vr","wsg"],"files":["a","biz","c","co","diy","gd","jp","m","po","sci","tg","vg","vp","vr","wsg"]},{"uid":1,"name":"NSFW Foolz","domain":"nsfw.foolz.us","http":true,"https":true,"software":"foolfuuka","boards":["u"],"files":["u"]},{"uid":3,"name":"4plebs Archive","domain":"archive.4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["adv","f","hr","o","pol","s4s","tg","trv","tv","x"],"files":["adv","f","hr","o","pol","s4s","tg","trv","tv","x"]},{"uid":4,"name":"Nyafuu","domain":"archive.nyafuu.org","http":true,"https":true,"software":"foolfuuka","boards":["c","e","w","wg"],"files":["c","e","w","wg"]},{"uid":5,"name":"Love is Over","domain":"archive.loveisover.me","http":true,"https":true,"software":"foolfuuka","boards":["d","i","lgbt"],"files":["d","i","lgbt"]},{"uid":8,"name":"Rebecca Black Tech","domain":"archive.rebeccablacktech.com","http":false,"https":true,"software":"fuuka","boards":["cgl","g","mu","w"],"files":["cgl","g","mu","w"]},{"uid":9,"name":"Heinessen","domain":"archive.heinessen.com","http":true,"https":false,"software":"fuuka","boards":["an","fit","k","mlp","r9k","toy"],"files":["an","fit","k","mlp","r9k","toy"]},{"uid":10,"name":"warosu","domain":"warosu.org","http":false,"https":true,"software":"fuuka","boards":["3","biz","cgl","ck","diy","fa","g","ic","jp","lit","sci","tg","vr"],"files":["3","biz","cgl","ck","diy","fa","ic","jp","lit","sci","tg","vr"]},{"uid":15,"name":"fgts","domain":"fgts.jp","http":true,"https":true,"software":"foolfuuka","boards":["asp","cm","h","hc","hm","n","p","r","s","soc","y"],"files":["asp","cm","h","hc","hm","n","p","r","s","soc","y"]},{"uid":16,"name":"maware","domain":"archive.mawa.re","http":true,"https":false,"software":"foolfuuka","boards":["t"],"files":["t"]},{"uid":19,"name":"Deniable Plausibility","domain":"boards.deniableplausibility.net","http":true,"https":false,"software":"foolfuuka","boards":["v","vg"],"files":["v","vg"]},{"uid":19,"name":"Innovandalism Archive","domain":"boards.innovandalism.eu","http":true,"https":false,"software":"foolfuuka","boards":["v"],"files":[]},{"uid":13,"name":"Foolz Beta","domain":"beta.foolz.us","http":true,"https":true,"withCredentials":true,"software":"foolfuuka","boards":["a","biz","c","co","d","diy","gd","int","jp","m","out","po","s4s","sci","sp","tg","tv","u","vg","vp","vr","wsg"],"files":["a","biz","c","co","d","diy","gd","jp","m","po","s4s","sci","tg","u","vg","vp","vr","wsg"]}], to: function(dest, data) { var archive; archive = (dest === 'search' || dest === 'board' ? Redirect.data.thread : Redirect.data[dest])[data.boardID]; @@ -11198,7 +11138,6 @@ return; } entry = { - type: 'header', el: $.el('a', { textContent: 'Show announcement', className: 'show-announcement', @@ -11209,7 +11148,7 @@ return psa.hidden; } }; - $.event('AddMenuEntry', entry); + Header.menu.addEntry(entry); $.on(entry.el, 'click', PSAHiding.toggle); PSAHiding.btn = btn = $.el('span', { innerHTML: '[Dismiss]', @@ -11367,8 +11306,7 @@ input = $('input', el); $.on(input, 'change', this.toggle); $.sync('Header catalog links', CatalogLinks.set); - $.event('AddMenuEntry', { - type: 'header', + Header.menu.addEntry({ el: el, order: 95 }); @@ -11900,7 +11838,7 @@ }); } if (board === 'sci') { - $.globalEval("window.addEventListener('jsmath', function(e) {\n if (jsMath.loaded) {\n // process one post\n jsMath.ProcessBeforeShowing(e.detail);\n } else {\n // load jsMath and process whole document\n jsMath.Autoload.Script.Push('ProcessBeforeShowing', [null]);\n jsMath.Autoload.LoadJsMath();\n }\n}, false);"); + $.globalEval("window.addEventListener('jsmath', function(e) {\n if (jsMath.loaded) {\n // process one post\n jsMath.ProcessBeforeShowing(document.getElementById(e.detail));\n } else {\n // load jsMath and process whole document\n jsMath.Autoload.Script.Push('ProcessBeforeShowing', [null]);\n jsMath.Autoload.LoadJsMath();\n }\n}, false);"); return Post.callbacks.push({ name: 'Parse /sci/ math', cb: this.math @@ -11927,7 +11865,7 @@ if (this.isClone || !$('.math', this.nodes.comment)) { return; } - return $.event('jsmath', this.nodes.post, window); + return $.event('jsmath', this.nodes.post.id, window); } }; @@ -12230,31 +12168,31 @@ } break; case Conf['Next thread']: - if (g.VIEW !== 'index') { + if (g.VIEW !== 'index' || Conf['Index Mode'] === 'catalog') { return; } Nav.scroll(+1); break; case Conf['Previous thread']: - if (g.VIEW !== 'index') { + if (g.VIEW !== 'index' || Conf['Index Mode'] === 'catalog') { return; } Nav.scroll(-1); break; case Conf['Expand thread']: - if (g.VIEW !== 'index') { + if (g.VIEW !== 'index' || Conf['Index Mode'] === 'catalog') { return; } ExpandThread.toggle(thread); break; case Conf['Open thread']: - if (g.VIEW !== 'index') { + if (g.VIEW !== 'index' || Conf['Index Mode'] === 'catalog') { return; } Keybinds.open(thread); break; case Conf['Open thread tab']: - if (g.VIEW !== 'index') { + if (g.VIEW !== 'index' || Conf['Index Mode'] === 'catalog') { return; } Keybinds.open(thread, true); @@ -12643,7 +12581,7 @@ var response; e.preventDefault(); response = field.value.trim(); - if (!/\s/.test(response)) { + if (!/\s|^\d+$/.test(response)) { field.value = "" + response + " " + response; } return this.submit(); @@ -13194,7 +13132,6 @@ Settings.addSection('Sauce', Settings.sauce); Settings.addSection('Advanced', Settings.advanced); Settings.addSection('Keybinds', Settings.keybinds); - $.on(d, 'AddSettingsSection', Settings.addSection); $.on(d, 'OpenSettings', function(e) { return Settings.open(e.detail); }); @@ -13258,10 +13195,7 @@ }, sections: [], addSection: function(title, open) { - var hyphenatedTitle, _ref; - if (typeof title !== 'string') { - _ref = title.detail, title = _ref.title, open = _ref.open; - } + var hyphenatedTitle; hyphenatedTitle = title.toLowerCase().replace(/\s+/g, '-'); return Settings.sections.push({ title: title, @@ -13941,7 +13875,6 @@ init('Banner', Banner); init('Navigate', Navigate); init('Flash Features', Flash); - $.on(d, 'AddCallback', Main.addCallback); return $.ready(Main.initReady); }, initStyle: function() { @@ -14074,25 +14007,6 @@ return $.set('previousversion', g.VERSION); }); }, - addCallback: function(e) { - var Klass, obj; - obj = e.detail; - if (typeof obj.callback.name !== 'string') { - throw new Error("Invalid callback name: " + obj.callback.name); - } - switch (obj.type) { - case 'Post': - Klass = Post; - break; - case 'Thread': - Klass = Thread; - break; - default: - return; - } - obj.callback.isAddon = true; - return Klass.callbacks.push(obj.callback); - }, handleErrors: function(errors) { var div, error, logs, _i, _len; if (!(errors instanceof Array)) { diff --git a/css/style.css b/css/style.css index 13be06eec..ab1ceca49 100644 --- a/css/style.css +++ b/css/style.css @@ -8,7 +8,6 @@ .field { background-color: #FFF; border: 1px solid #CCC; - -moz-box-sizing: border-box; box-sizing: border-box; color: #333; font-family: inherit; @@ -235,7 +234,6 @@ body > .desktop:not(hr):not(.navLinks):not(#boardNavDesktop):not(#boardNavDeskto position: absolute; } .message { - -moz-box-sizing: border-box; box-sizing: border-box; padding: 6px 20px; max-height: 200px; @@ -245,7 +243,6 @@ body > .desktop:not(hr):not(.navLinks):not(#boardNavDesktop):not(#boardNavDeskto /* Settings */ :root.fourchan-x body { - -moz-box-sizing: border-box; box-sizing: border-box; } #overlay { @@ -258,7 +255,6 @@ body > .desktop:not(hr):not(.navLinks):not(#boardNavDesktop):not(#boardNavDeskto width: 100%; } #fourchanx-settings { - -moz-box-sizing: border-box; box-sizing: border-box; box-shadow: 0 0 15px rgba(0, 0, 0, .15); height: 600px; @@ -400,16 +396,16 @@ body > .desktop:not(hr):not(.navLinks):not(#boardNavDesktop):not(#boardNavDeskto text-decoration: none; } .catalog-mode .board { - text-align: center; + display: flex; + flex-wrap: wrap; + justify-content: center; } .catalog-thread { display: inline-flex; - text-align: left; flex-direction: column; align-items: center; margin: 0 2px 5px; word-break: break-word; - vertical-align: top; } .catalog-small .catalog-thread { width: 165px; @@ -682,7 +678,6 @@ a.hide-announcement { clear: both; } #ihover { - -moz-box-sizing: border-box; box-sizing: border-box; max-height: 100%; max-width: 75%; @@ -824,7 +819,6 @@ a.hide-announcement { border: 1px solid #808080; color: #FFF !important; font-size: 12px; - -moz-box-sizing: border-box; box-sizing: border-box; cursor: move; display: inline-block; diff --git a/package.json b/package.json index ee3a8a796..5d14eef64 100755 --- a/package.json +++ b/package.json @@ -27,18 +27,18 @@ } }, "devDependencies": { - "font-awesome": "~4.0.3", - "grunt": "~0.4.4", - "grunt-bump": "~0.0.13", + "font-awesome": "~4.1.0", + "grunt": "~0.4.5", + "grunt-bump": "~0.0.14", "grunt-concurrent": "~0.5.0", "grunt-contrib-clean": "~0.5.0", "grunt-contrib-coffee": "~0.10.1", - "grunt-contrib-compress": "~0.8.0", + "grunt-contrib-compress": "~0.9.1", "grunt-contrib-concat": "~0.4.0", "grunt-contrib-copy": "~0.5.0", "grunt-contrib-watch": "~0.6.1", "grunt-shell": "~0.7.0", - "load-grunt-tasks": "~0.4.0" + "load-grunt-tasks": "~0.5.0" }, "repository": { "type": "git", diff --git a/src/Archive/archives.json b/src/Archive/archives.json index 0fb712920..8c631a051 100644 --- a/src/Archive/archives.json +++ b/src/Archive/archives.json @@ -5,8 +5,8 @@ "http": true, "https": true, "software": "foolfuuka", - "boards": ["a", "biz", "co", "diy", "gd", "jp", "m", "sci", "sp", "tg", "tv", "vg", "vp", "vr", "wsg"], - "files": ["a", "biz", "diy", "gd", "jp", "m", "sci", "tg", "vg", "vp", "vr", "wsg"] + "boards": ["a", "biz", "c", "co", "diy", "gd", "int", "jp", "m", "out", "po", "sci", "sp", "tg", "tv", "vg", "vp", "vr", "wsg"], + "files": ["a", "biz", "c", "co", "diy", "gd", "jp", "m", "po", "sci", "tg", "vg", "vp", "vr", "wsg"] }, { "uid": 1, "name": "NSFW Foolz", @@ -16,15 +16,6 @@ "software": "foolfuuka", "boards": ["u"], "files": ["u"] -}, { - "uid": 2, - "name": "The Dark Cave", - "domain": "archive.thedarkcave.org", - "http": true, - "https": true, - "software": "foolfuuka", - "boards": ["c", "int", "out", "po"], - "files": ["c", "po"] }, { "uid": 3, "name": "4plebs Archive", @@ -32,17 +23,8 @@ "http": true, "https": true, "software": "foolfuuka", - "boards": ["adv", "hr", "o", "pol", "s4s", "tg", "trv", "tv", "x"], - "files": ["adv", "hr", "o", "pol", "s4s", "tg", "trv", "tv", "x"] -}, { - "uid": 18, - "name": "4plebs Flash Archive", - "domain": "flash.4plebs.org", - "http": true, - "https": true, - "software": "foolfuuka", - "boards": ["f"], - "files": ["f"] + "boards": ["adv", "f", "hr", "o", "pol", "s4s", "tg", "trv", "tv", "x"], + "files": ["adv", "f", "hr", "o", "pol", "s4s", "tg", "trv", "tv", "x"] }, { "uid": 4, "name": "Nyafuu", @@ -64,7 +46,7 @@ }, { "uid": 8, "name": "Rebecca Black Tech", - "domain": "rbt.asia", + "domain": "archive.rebeccablacktech.com", "http": false, "https": true, "software": "fuuka", @@ -82,7 +64,7 @@ }, { "uid": 10, "name": "warosu", - "domain": "fuuka.warosu.org", + "domain": "warosu.org", "http": false, "https": true, "software": "fuuka", @@ -91,7 +73,7 @@ }, { "uid": 15, "name": "fgts", - "domain": "fgts.eu", + "domain": "fgts.jp", "http": true, "https": true, "software": "foolfuuka", @@ -107,14 +89,14 @@ "boards": ["t"], "files": ["t"] }, { - "uid": 17, - "name": "installgentoo.com", - "domain": "chan.installgentoo.com", + "uid": 19, + "name": "Deniable Plausibility", + "domain": "boards.deniableplausibility.net", "http": true, "https": false, "software": "foolfuuka", - "boards": ["g", "t"], - "files": ["g", "t"] + "boards": ["v", "vg"], + "files": ["v", "vg"] }, { "uid": 19, "name": "Innovandalism Archive", @@ -132,15 +114,6 @@ "https": true, "withCredentials": true, "software": "foolfuuka", - "boards": ["a", "biz", "co", "d", "diy", "gd", "jp", "m", "s4s", "sci", "sp", "tg", "tv", "u", "vg", "vp", "vr", "wsg"], - "files": ["a", "biz", "d", "diy", "gd", "jp", "m", "s4s", "sci", "tg", "u", "vg", "vp", "vr", "wsg"] -}, { - "uid": 19, - "name": "Innovandalism Archive", - "domain": "boards.innovandalism.eu", - "http": true, - "https": false, - "software": "foolfuuka", - "boards": ["v"], - "files": [] + "boards": ["a", "biz", "c", "co", "d", "diy", "gd", "int", "jp", "m", "out", "po", "s4s", "sci", "sp", "tg", "tv", "u", "vg", "vp", "vr", "wsg"], + "files": ["a", "biz", "c", "co", "d", "diy", "gd","jp", "m", "po", "s4s", "sci", "tg", "u", "vg", "vp", "vr", "wsg"] }] diff --git a/src/Filtering/Filter.coffee b/src/Filtering/Filter.coffee index 1805f4a34..7231f44f0 100755 --- a/src/Filtering/Filter.coffee +++ b/src/Filtering/Filter.coffee @@ -170,7 +170,6 @@ Filter = textContent: 'Filter' entry = - type: 'post' el: div order: 50 open: (post) -> @@ -195,7 +194,7 @@ Filter = # Add a sub entry for each filter type. entry.subEntries.push Filter.menu.createSubEntry type[0], type[1] - $.event 'AddMenuEntry', entry + Menu.menu.addEntry entry createSubEntry: (text, type) -> el = $.el 'a', diff --git a/src/Filtering/PostHiding.coffee b/src/Filtering/PostHiding.coffee index b1298cf07..29c6a43c3 100755 --- a/src/Filtering/PostHiding.coffee +++ b/src/Filtering/PostHiding.coffee @@ -88,8 +88,7 @@ PostHiding = makeStub = el: $.el 'label', innerHTML: " Make stub" - $.event 'AddMenuEntry', - type: 'post' + Menu.menu.addEntry el: $.el 'div', textContent: 'Hide post' className: 'hide-post-link' @@ -117,8 +116,7 @@ PostHiding = @el.firstChild.checked = if 'hideRecursively' of data then data.hideRecursively else Conf['Recursive Hiding'] true - $.event 'AddMenuEntry', - type: 'post' + Menu.menu.addEntry el: $.el 'div', textContent: 'Unhide post' className: 'show-post-link' @@ -132,8 +130,7 @@ PostHiding = subEntries: [apply, thisPost, replies] return if g.VIEW isnt 'index' - $.event 'AddMenuEntry', - type: 'post' + Menu.menu.addEntry el: $.el 'a', href: 'javascript:;' order: 20 open: (post) -> diff --git a/src/General/Config.coffee b/src/General/Config.coffee index 7df0703bd..809080ca8 100755 --- a/src/General/Config.coffee +++ b/src/General/Config.coffee @@ -229,12 +229,6 @@ Config = true 'Add post and image deletion links to the menu.' ] - <% if (type === 'crx') { %> - 'Download Link': [ - true - 'Add a download with original filename link to the menu. Chrome-only currently.' - ] - <% } %> 'Archive Link': [ true 'Add an archive link to the menu.' @@ -307,10 +301,6 @@ Config = true 'Open new threads or replies to a thread from the index in a new tab.' ] - 'Remember Subject': [ - false - 'Remember the subject field, instead of resetting after posting.' - ] <% if (type === 'userscript') { %> 'Remember QR Size': [ false diff --git a/src/General/Header.coffee b/src/General/Header.coffee index b13592888..219ddc7cf 100755 --- a/src/General/Header.coffee +++ b/src/General/Header.coffee @@ -1,8 +1,8 @@ Header = init: -> - @menu = new UI.Menu 'header' + @menu = new UI.Menu() - menuButton = $.el 'span', + menuButton = $.el 'a', className: 'menu-button' innerHTML: '' @@ -62,10 +62,8 @@ Header = @addShortcut menuButton - $.event 'AddMenuEntry', - type: 'header' - el: $.el 'span', - textContent: 'Header' + @menu.addEntry + el: $.el 'span', textContent: 'Header' order: 107 subEntries: [ el: barFixedToggler @@ -436,7 +434,7 @@ Header = shortcut = $.el 'span', className: 'shortcut brackets-wrap' $.add shortcut, el - $.prepend Header.shortcuts, shortcut + $.add Header.shortcuts, shortcut rmShortcut: (el) -> $.rm el.parentElement @@ -445,9 +443,8 @@ Header = Header.menu.toggle e, @, g createNotification: (e) -> - {type, content, lifetime, cb} = e.detail + {type, content, lifetime} = e.detail notice = new Notice type, content, lifetime - cb notice if cb areNotificationsEnabled: false enableDesktopNotifications: -> diff --git a/src/General/Index.coffee b/src/General/Index.coffee index 5050ddb47..48bc222b2 100644 --- a/src/General/Index.coffee +++ b/src/General/Index.coffee @@ -73,8 +73,7 @@ Index = when 'Show Replies' $.on input, 'change', @cb.replies - $.event 'AddMenuEntry', - type: 'header' + Header.menu.addEntry el: $.el 'span', textContent: 'Index Navigation' order: 98 @@ -171,8 +170,7 @@ Index = init: -> return if g.VIEW isnt 'index' or !Conf['Menu'] or g.BOARD.ID is 'f' - $.event 'AddMenuEntry', - type: 'post' + Menu.menu.addEntry el: $.el 'a', href: 'javascript:;' order: 19 open: ({thread}) -> @@ -372,7 +370,7 @@ Index = onSameIndex = g.VIEW is 'index' and a.pathname.split('/')[1] is g.BOARD.ID needChange = Index.cb.indexNav a, onSameIndex # Do nav if this isn't a simple click, or different board. - return if e.shiftKey or e.altKey or e.ctrlKey or e.metaKey or !onSameIndex + return if e.shiftKey or e.altKey or e.ctrlKey or e.metaKey or !onSameIndex or g.BOARD.ID is 'f' e.preventDefault() Index.update() unless needChange @@ -781,7 +779,6 @@ Index = $.rmAll Index.root unless infinite $.add Index.root, nodes - $.event 'IndexBuild', nodes isSearching: false diff --git a/src/General/Main.coffee b/src/General/Main.coffee index 436f83b5e..39153ae15 100755 --- a/src/General/Main.coffee +++ b/src/General/Main.coffee @@ -142,7 +142,6 @@ Main = init 'Navigate', Navigate init 'Flash Features', Flash - $.on d, 'AddCallback', Main.addCallback $.ready Main.initReady initStyle: -> @@ -260,20 +259,6 @@ Main = Settings.open() $.set 'previousversion', g.VERSION - addCallback: (e) -> - obj = e.detail - unless typeof obj.callback.name is 'string' - throw new Error "Invalid callback name: #{obj.callback.name}" - switch obj.type - when 'Post' - Klass = Post - when 'Thread' - Klass = Thread - else - return - obj.callback.isAddon = true - Klass.callbacks.push obj.callback - handleErrors: (errors) -> unless errors instanceof Array error = errors diff --git a/src/General/Settings.coffee b/src/General/Settings.coffee index 2d12a4871..226e358c6 100755 --- a/src/General/Settings.coffee +++ b/src/General/Settings.coffee @@ -16,8 +16,7 @@ Settings = Settings.addSection 'Advanced', Settings.advanced Settings.addSection 'Keybinds', Settings.keybinds - $.on d, 'AddSettingsSection', Settings.addSection - $.on d, 'OpenSettings', (e) -> Settings.open e.detail + $.on d, 'OpenSettings', (e) -> Settings.open e.detail settings = JSON.parse(localStorage.getItem '4chan-settings') or {} return if settings.disableAll @@ -72,8 +71,6 @@ Settings = sections: [] addSection: (title, open) -> - if typeof title isnt 'string' - {title, open} = title.detail hyphenatedTitle = title.toLowerCase().replace /\s+/g, '-' Settings.sections.push {title, hyphenatedTitle, open} openSection: -> diff --git a/src/General/UI.coffee b/src/General/UI.coffee index 95f229de5..63dd8bfe7 100755 --- a/src/General/UI.coffee +++ b/src/General/UI.coffee @@ -21,10 +21,7 @@ UI = do -> currentMenu = null lastToggledButton = null - constructor: (@type) -> - # Doc here: https://github.com/MayhemYDG/4chan-x/wiki/Menu-API - $.on d, 'AddMenuEntry', @addEntry - $.on d, 'rmMenuEntry', @rmEntry + constructor: -> @entries = [] makeMenu: -> @@ -190,9 +187,7 @@ UI = do -> style.left = left style.right = right - addEntry: (e) => - entry = e.detail - return if entry.type isnt @type + addEntry: (entry) -> @parseEntry entry @entries.push entry diff --git a/src/General/lib/$.coffee b/src/General/lib/$.coffee index a957fa75d..89d2f43e3 100755 --- a/src/General/lib/$.coffee +++ b/src/General/lib/$.coffee @@ -179,6 +179,10 @@ $.off = (el, events, handler) -> return $.event = (event, detail, root=d) -> + <% if (type === 'userscript') { %> + if detail? and typeof cloneInto is 'function' + detail = cloneInto detail, d.defaultView + <% } %> root.dispatchEvent new CustomEvent event, {bubbles: true, detail} $.open = diff --git a/src/Images/FappeTyme.coffee b/src/Images/FappeTyme.coffee index 17376bae2..14e3b1809 100755 --- a/src/Images/FappeTyme.coffee +++ b/src/Images/FappeTyme.coffee @@ -11,8 +11,7 @@ FappeTyme = FappeTyme[lc] = input = el.firstElementChild $.on input, 'change', FappeTyme.cb.toggle.bind input - $.event 'AddMenuEntry', - type: 'header' + Header.menu.addEntry el: el order: 97 diff --git a/src/Images/Gallery.coffee b/src/Images/Gallery.coffee index dfd58a3a4..c7bc58336 100644 --- a/src/Images/Gallery.coffee +++ b/src/Images/Gallery.coffee @@ -60,7 +60,7 @@ Gallery = } menuButton = $ '.menu-button', dialog - nodes.menu = new UI.Menu 'gallery' + nodes.menu = new UI.Menu() {cb} = Gallery $.on nodes.frame, 'click', cb.blank @@ -76,8 +76,7 @@ Gallery = for name of Config.gallery {el} = createSubEntry name - $.event 'AddMenuEntry', - type: 'gallery' + nodes.menu.addEntry el: el order: 0 @@ -251,8 +250,7 @@ Gallery = for name of Config.gallery subEntries.push createSubEntry name - $.event 'AddMenuEntry', - type: 'header' + Header.menu.addEntry el: el order: 105 subEntries: subEntries diff --git a/src/Images/ImageExpand.coffee b/src/Images/ImageExpand.coffee index 7026e5ed4..0b6d99a8b 100755 --- a/src/Images/ImageExpand.coffee +++ b/src/Images/ImageExpand.coffee @@ -266,8 +266,7 @@ ImageExpand = for name, conf of Config.imageExpansion subEntries.push createSubEntry name, conf[1] - $.event 'AddMenuEntry', - type: 'header' + Header.menu.addEntry el: el order: 105 subEntries: subEntries diff --git a/src/Images/ImageLoader.coffee b/src/Images/ImageLoader.coffee index 3d2bc850b..556df5f78 100755 --- a/src/Images/ImageLoader.coffee +++ b/src/Images/ImageLoader.coffee @@ -16,8 +16,7 @@ ImageLoader = @el = prefetch.firstElementChild $.on @el, 'change', @toggle - $.event 'AddMenuEntry', - type: 'header' + Header.menu.addEntry el: prefetch order: 104 diff --git a/src/Menu/ArchiveLink.coffee b/src/Menu/ArchiveLink.coffee index bffef2c98..0d38f935f 100755 --- a/src/Menu/ArchiveLink.coffee +++ b/src/Menu/ArchiveLink.coffee @@ -6,7 +6,6 @@ ArchiveLink = textContent: 'Archive' entry = - type: 'post' el: div order: 90 open: ({ID, thread, board}) -> @@ -25,7 +24,7 @@ ArchiveLink = # Add a sub entry for each type. entry.subEntries.push @createSubEntry type[0], type[1] - $.event 'AddMenuEntry', entry + Menu.menu.addEntry entry createSubEntry: (text, type) -> el = $.el 'a', diff --git a/src/Menu/DeleteLink.coffee b/src/Menu/DeleteLink.coffee index ed6d985c1..864c81e33 100755 --- a/src/Menu/DeleteLink.coffee +++ b/src/Menu/DeleteLink.coffee @@ -26,8 +26,7 @@ DeleteLink = $.on fileEl, 'click', DeleteLink.delete true - $.event 'AddMenuEntry', - type: 'post' + Menu.menu.addEntry el: div order: 40 open: (post) -> diff --git a/src/Menu/DownloadLink.coffee b/src/Menu/DownloadLink.coffee index 0ac266f05..554649efe 100755 --- a/src/Menu/DownloadLink.coffee +++ b/src/Menu/DownloadLink.coffee @@ -5,8 +5,7 @@ DownloadLink = a = $.el 'a', className: 'download-link' textContent: 'Download file' - $.event 'AddMenuEntry', - type: 'post' + Menu.menu.addEntry el: a order: 100 open: ({file}) -> diff --git a/src/Menu/Labels.coffee b/src/Menu/Labels.coffee index 726377b7d..0f04953c4 100644 --- a/src/Menu/Labels.coffee +++ b/src/Menu/Labels.coffee @@ -2,8 +2,7 @@ Labels = init: -> return if !Conf['Menu'] - $.event 'AddMenuEntry', - type: 'post' + Menu.menu.addEntry el: $.el 'div', textContent: 'Labels' order: 60 open: (post, addSubEntry) -> diff --git a/src/Menu/Menu.coffee b/src/Menu/Menu.coffee index 251b0bf8b..3a6140510 100755 --- a/src/Menu/Menu.coffee +++ b/src/Menu/Menu.coffee @@ -7,7 +7,7 @@ Menu = innerHTML: '' href: 'javascript:;' - @menu = new UI.Menu 'post' + @menu = new UI.Menu() Post.callbacks.push name: 'Menu' cb: @node diff --git a/src/Menu/ReportLink.coffee b/src/Menu/ReportLink.coffee index c246c903f..58d2dc6bb 100755 --- a/src/Menu/ReportLink.coffee +++ b/src/Menu/ReportLink.coffee @@ -7,8 +7,7 @@ ReportLink = href: 'javascript:;' textContent: 'Report this post' $.on a, 'click', ReportLink.report - $.event 'AddMenuEntry', - type: 'post' + Menu.menu.addEntry el: a order: 10 open: (post) -> diff --git a/src/Miscellaneous/AnnouncementHiding.coffee b/src/Miscellaneous/AnnouncementHiding.coffee index bda6bf64a..0eaee0492 100755 --- a/src/Miscellaneous/AnnouncementHiding.coffee +++ b/src/Miscellaneous/AnnouncementHiding.coffee @@ -11,14 +11,13 @@ PSAHiding = return entry = - type: 'header' el: $.el 'a', textContent: 'Show announcement' className: 'show-announcement' href: 'javascript:;' order: 50 open: -> psa.hidden - $.event 'AddMenuEntry', entry + Header.menu.addEntry entry $.on entry.el, 'click', PSAHiding.toggle PSAHiding.btn = btn = $.el 'span', diff --git a/src/Miscellaneous/CatalogLinks.coffee b/src/Miscellaneous/CatalogLinks.coffee index ce8bc8b3e..2c39609fb 100755 --- a/src/Miscellaneous/CatalogLinks.coffee +++ b/src/Miscellaneous/CatalogLinks.coffee @@ -10,8 +10,7 @@ CatalogLinks = $.on input, 'change', @toggle $.sync 'Header catalog links', CatalogLinks.set - $.event 'AddMenuEntry', - type: 'header' + Header.menu.addEntry el: el order: 95 diff --git a/src/Miscellaneous/Fourchan.coffee b/src/Miscellaneous/Fourchan.coffee index a0da2637d..14f7b491b 100755 --- a/src/Miscellaneous/Fourchan.coffee +++ b/src/Miscellaneous/Fourchan.coffee @@ -18,7 +18,7 @@ Fourchan = window.addEventListener('jsmath', function(e) { if (jsMath.loaded) { // process one post - jsMath.ProcessBeforeShowing(e.detail); + jsMath.ProcessBeforeShowing(document.getElementById(e.detail)); } else { // load jsMath and process whole document jsMath.Autoload.Script.Push('ProcessBeforeShowing', [null]); @@ -39,4 +39,4 @@ Fourchan = return math: -> return if @isClone or !$ '.math', @nodes.comment - $.event 'jsmath', @nodes.post, window + $.event 'jsmath', @nodes.post.id, window diff --git a/src/Miscellaneous/Keybinds.coffee b/src/Miscellaneous/Keybinds.coffee index ff4708649..be42b8601 100755 --- a/src/Miscellaneous/Keybinds.coffee +++ b/src/Miscellaneous/Keybinds.coffee @@ -144,19 +144,19 @@ Keybinds = Index.setIndexMode 'catalog' # Thread Navigation when Conf['Next thread'] - return if g.VIEW isnt 'index' + return if g.VIEW isnt 'index' or Conf['Index Mode'] is 'catalog' Nav.scroll +1 when Conf['Previous thread'] - return if g.VIEW isnt 'index' + return if g.VIEW isnt 'index' or Conf['Index Mode'] is 'catalog' Nav.scroll -1 when Conf['Expand thread'] - return if g.VIEW isnt 'index' + return if g.VIEW isnt 'index' or Conf['Index Mode'] is 'catalog' ExpandThread.toggle thread when Conf['Open thread'] - return if g.VIEW isnt 'index' + return if g.VIEW isnt 'index' or Conf['Index Mode'] is 'catalog' Keybinds.open thread when Conf['Open thread tab'] - return if g.VIEW isnt 'index' + return if g.VIEW isnt 'index' or Conf['Index Mode'] is 'catalog' Keybinds.open thread, true # Reply Navigation when Conf['Next reply'] diff --git a/src/Miscellaneous/Report.coffee b/src/Miscellaneous/Report.coffee index 109c55aa0..4bf7020f1 100755 --- a/src/Miscellaneous/Report.coffee +++ b/src/Miscellaneous/Report.coffee @@ -9,5 +9,5 @@ Report = $.on $('form'), 'submit', (e) -> e.preventDefault() response = field.value.trim() - field.value = "#{response} #{response}" unless /\s/.test response + field.value = "#{response} #{response}" unless /\s|^\d+$/.test response @submit() diff --git a/src/Monitoring/ThreadUpdater.coffee b/src/Monitoring/ThreadUpdater.coffee index 444dde3fa..38a09b264 100755 --- a/src/Monitoring/ThreadUpdater.coffee +++ b/src/Monitoring/ThreadUpdater.coffee @@ -47,8 +47,7 @@ ThreadUpdater = subEntries.push el: @settings - $.event 'AddMenuEntry', @entry = - type: 'header' + Header.menu.addEntry @entry = el: $.el 'span', textContent: 'Updater' order: 110 @@ -169,7 +168,7 @@ ThreadUpdater = ThreadUpdater.thread.kill() $.event 'ThreadUpdate', 404: true - thread: ThreadUpdater.thread + threadID: ThreadUpdater.thread.fullID else ThreadUpdater.outdateCount++ ThreadUpdater.setInterval() @@ -292,9 +291,6 @@ ThreadUpdater = node = Build.postFromObject postObject, ThreadUpdater.thread.board.ID posts.push new Post node, ThreadUpdater.thread, ThreadUpdater.thread.board - deletedPosts = [] - deletedFiles = [] - # Check for deleted posts/files. ThreadUpdater.thread.posts.forEach (post) -> # XXX tmp fix for 4chan's racing condition @@ -304,12 +300,10 @@ ThreadUpdater = unless ID in index post.kill() - deletedPosts.push post else if post.isDead post.resurrect() - else if post.file and not (post.file.isDead or ID in files) + else if post.file and !post.file.isDead and ID not in files post.kill true - deletedFiles.push post # Fetching your own posts after posting if ThreadUpdater.postID and ThreadUpdater.postID is ID @@ -318,10 +312,8 @@ ThreadUpdater = sendEvent = -> $.event 'ThreadUpdate', 404: false - thread: ThreadUpdater.thread - newPosts: posts - deletedPosts: deletedPosts - deletedFiles: deletedFiles + threadID: ThreadUpdater.thread.fullID + newPosts: posts.map (post) -> post.fullID postCount: OP.replies + 1 fileCount: OP.images + (!!ThreadUpdater.thread.OP.file and !ThreadUpdater.thread.OP.file.isDead) diff --git a/src/Monitoring/ThreadWatcher.coffee b/src/Monitoring/ThreadWatcher.coffee index 303edd3d6..b91068fd4 100755 --- a/src/Monitoring/ThreadWatcher.coffee +++ b/src/Monitoring/ThreadWatcher.coffee @@ -88,12 +88,12 @@ ThreadWatcher = [boardID, threadID] = @parentNode.dataset.fullID.split '.' ThreadWatcher.rm boardID, +threadID post: (e) -> - {board, postID, threadID} = e.detail + {boardID, threadID, postID} = e.detail if postID is threadID if Conf['Auto Watch'] $.set 'AutoWatch', threadID else if Conf['Auto Watch Reply'] - ThreadWatcher.add board.threads[threadID] + ThreadWatcher.add g.threads[boardID + '.' + threadID] onIndexRefresh: -> boardID = g.BOARD.ID for threadID, data of ThreadWatcher.db.data.boards[boardID] when not data.isDead and threadID not of g.BOARD.threads @@ -104,7 +104,7 @@ ThreadWatcher = ThreadWatcher.db.set {boardID, threadID, val: data} ThreadWatcher.refresh() onThreadRefresh: (e) -> - {thread} = e.detail + thread = g.threads[e.detail.threadID] return unless e.detail[404] and ThreadWatcher.db.get {boardID: thread.board.ID, threadID: thread.ID} # Update 404 status. ThreadWatcher.add thread @@ -227,18 +227,17 @@ ThreadWatcher = refreshers: [] init: -> return if !Conf['Thread Watcher'] - menu = new UI.Menu 'thread watcher' + menu = new UI.Menu() $.on $('.menu-button', ThreadWatcher.dialog), 'click', (e) -> menu.toggle e, @, ThreadWatcher @addHeaderMenuEntry() - @addMenuEntries() + @addMenuEntries menu addHeaderMenuEntry: -> return if g.VIEW isnt 'thread' entryEl = $.el 'a', href: 'javascript:;' - $.event 'AddMenuEntry', - type: 'header' + Header.menu.addEntry el: entryEl order: 60 $.on entryEl, 'click', -> ThreadWatcher.toggle g.threads["#{g.BOARD}.#{g.THREADID}"] @@ -251,14 +250,13 @@ ThreadWatcher = $.rmClass entryEl, rmClass entryEl.textContent = text - addMenuEntries: -> + addMenuEntries: (menu) -> entries = [] # `Open all` entry entries.push cb: ThreadWatcher.cb.openAll entry: - type: 'thread watcher' el: $.el 'a', textContent: 'Open all threads' refresh: -> (if ThreadWatcher.list.firstElementChild then $.rmClass else $.addClass) @el, 'disabled' @@ -267,7 +265,6 @@ ThreadWatcher = entries.push cb: ThreadWatcher.cb.checkThreads entry: - type: 'thread watcher' el: $.el 'a', textContent: 'Check 404\'d threads' refresh: -> (if $('div:not(.dead-thread)', ThreadWatcher.list) then $.rmClass else $.addClass) @el, 'disabled' @@ -276,7 +273,6 @@ ThreadWatcher = entries.push cb: ThreadWatcher.cb.pruneDeads entry: - type: 'thread watcher' el: $.el 'a', textContent: 'Prune 404\'d threads' refresh: -> (if $('.dead-thread', ThreadWatcher.list) then $.rmClass else $.addClass) @el, 'disabled' @@ -287,7 +283,6 @@ ThreadWatcher = subEntries.push @createSubEntry name, conf[1] entries.push entry: - type: 'thread watcher' el: $.el 'span', textContent: 'Settings' subEntries: subEntries @@ -296,7 +291,7 @@ ThreadWatcher = entry.el.href = 'javascript:;' if entry.el.nodeName is 'A' $.on entry.el, 'click', cb if cb @refreshers.push refresh.bind entry if refresh - $.event 'AddMenuEntry', entry + menu.addEntry entry return createSubEntry: (name, desc) -> entry = diff --git a/src/Monitoring/Unread.coffee b/src/Monitoring/Unread.coffee index 6d17b4eba..245630605 100755 --- a/src/Monitoring/Unread.coffee +++ b/src/Monitoring/Unread.coffee @@ -122,11 +122,11 @@ Unread = onUpdate: (e) -> if e.detail[404] Unread.update() - else if !Conf['Quote Threading'] - Unread.addPosts e.detail.newPosts - else + else if Conf['Quote Threading'] Unread.read() Unread.update() + else + Unread.addPosts e.detail.newPosts.map (fullID) -> g.posts[fullID] readSinglePost: (post) -> {ID} = post diff --git a/src/Posting/QR.captcha.coffee b/src/Posting/QR.captcha.coffee index 71accd6b0..e0b320286 100644 --- a/src/Posting/QR.captcha.coffee +++ b/src/Posting/QR.captcha.coffee @@ -93,7 +93,7 @@ QR.captcha = response = response.trim() # one-word-captcha: # If there's only one word, duplicate it. - response = "#{response} #{response}" unless /\s/.test response + response = "#{response} #{response}" unless /\s|^\d+$/.test response {challenge, response} save: -> diff --git a/src/Posting/QR.coffee b/src/Posting/QR.coffee index b79b875c0..a8401cfe2 100644 --- a/src/Posting/QR.coffee +++ b/src/Posting/QR.coffee @@ -53,11 +53,6 @@ QR = $.before $.id('togglePostFormLink'), link - $.on d, 'QRGetSelectedPost', ({detail: cb}) -> - cb QR.selected - $.on d, 'QRAddPreSubmitHook', ({detail: cb}) -> - QR.preSubmitHooks.push cb - <% if (type === 'crx') { %> $.on d, 'paste', QR.paste <% } %> @@ -580,8 +575,6 @@ QR = nodes.flag = flag $.add nodes.form, flag - preSubmitHooks: [] - submit: (e) -> e?.preventDefault() @@ -614,9 +607,6 @@ QR = err = 'No file selected.' else if post.file and thread.fileLimit err = 'Max limit of image replies has been reached.' - else for hook in QR.preSubmitHooks - if err = hook post, thread - break if QR.captcha.isEnabled and !err {challenge, response} = QR.captcha.getOne() @@ -775,11 +765,11 @@ QR = # Post/upload confirmed as successful. $.event 'QRPostSuccessful', { - board: g.BOARD + boardID: g.BOARD.ID threadID postID } - $.event 'QRPostSuccessful_', {threadID, postID} + $.event 'QRPostSuccessful_', {boardID: g.BOARD.ID, threadID, postID} # Enable auto-posting if we have stuff left to post, disable it otherwise. postsCount = QR.posts.length - 1 diff --git a/src/Posting/QR.post.coffee b/src/Posting/QR.post.coffee index 3ce11883c..f4b483cd2 100644 --- a/src/Posting/QR.post.coffee +++ b/src/Posting/QR.post.coffee @@ -112,7 +112,6 @@ QR.post = class rectList = @nodes.el.parentNode.getBoundingClientRect() @nodes.el.parentNode.scrollLeft += rectEl.left + rectEl.width/2 - rectList.left - rectList.width/2 @load() - $.event 'QRPostSelection', @ load: -> # Load this post's values. diff --git a/src/Quotelinks/QuoteThreading.coffee b/src/Quotelinks/QuoteThreading.coffee index 2ac2d695f..2269cdd2b 100755 --- a/src/Quotelinks/QuoteThreading.coffee +++ b/src/Quotelinks/QuoteThreading.coffee @@ -13,8 +13,7 @@ QuoteThreading = input = $ 'input', @controls $.on input, 'change', @toggle - $.event 'AddMenuEntry', @entry = - type: 'header' + Header.menu.addEntry @entry = el: @controls order: 98