From 75f41069adce6c31312323c76f7e48ff8d07cf13 Mon Sep 17 00:00:00 2001 From: ahodesuka Date: Mon, 20 Feb 2012 00:08:37 -0600 Subject: [PATCH 1/9] Add an option to only expand images which have not been scrolled past when using the expand all button. --- 4chan_x.user.js | 9 ++++++++- script.coffee | 7 ++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index e365c8737..96bc0d33b 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -100,6 +100,7 @@ Imaging: { 'Image Auto-Gif': [false, 'Animate gif thumbnails'], 'Image Expansion': [true, 'Expand images'], + 'Expand All (Unscrolled)': [false, 'Expand all images will only expand those which you have not scrolled past'], 'Image Hover': [false, 'Show full image on mouseover'], 'Sauce': [true, 'Add sauce to images'], 'Reveal Spoilers': [false, 'Replace spoiler thumbnails by the original thumbnail'] @@ -3392,7 +3393,13 @@ _ref = $$('img[md5]'); for (_i = 0, _len = _ref.length; _i < _len; _i++) { thumb = _ref[_i]; - imgExpand.expand(thumb); + if (conf['Expand All (Unscrolled)']) { + if (thumb.getBoundingClientRect().bottom >= 0) { + imgExpand.expand(thumb); + } + } else { + imgExpand.expand(thumb); + } } } else { _ref2 = $$('img[md5][hidden]'); diff --git a/script.coffee b/script.coffee index 0b8a6c988..0227df801 100644 --- a/script.coffee +++ b/script.coffee @@ -22,6 +22,7 @@ config = Imaging: 'Image Auto-Gif': [false, 'Animate gif thumbnails'] 'Image Expansion': [true, 'Expand images'] + 'Expand All (Unscrolled)': [false, 'Expand all images will only expand those which you have not scrolled past'] 'Image Hover': [false, 'Show full image on mouseover'] 'Sauce': [true, 'Add sauce to images'] 'Reveal Spoilers': [false, 'Replace spoiler thumbnails by the original thumbnail'] @@ -2663,7 +2664,11 @@ imgExpand = imgExpand.on = @checked if imgExpand.on #expand for thumb in $$ 'img[md5]' - imgExpand.expand thumb + if conf['Expand All (Unscrolled)'] + if thumb.getBoundingClientRect().bottom >= 0 + imgExpand.expand thumb + else + imgExpand.expand thumb else #contract for thumb in $$ 'img[md5][hidden]' imgExpand.contract thumb From 2b62ce1231b6f5b1eb8734f1c2450373dbcba00c Mon Sep 17 00:00:00 2001 From: James Campos Date: Mon, 20 Feb 2012 14:16:48 -0800 Subject: [PATCH 2/9] build on ahodesuka's work --- 4chan_x.user.js | 29 +++++++++++++++-------------- script.coffee | 16 +++++++++------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 14d46fec2..341bf5cdb 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -100,7 +100,7 @@ Imaging: { 'Image Auto-Gif': [false, 'Animate gif thumbnails'], 'Image Expansion': [true, 'Expand images'], - 'Expand All (Unscrolled)': [false, 'Expand all images will only expand those which you have not scrolled past'], + 'Expand From Current': [true, 'Expand images from current position to thread end'], 'Image Hover': [false, 'Show full image on mouseover'], 'Sauce': [true, 'Add sauce to images'], 'Reveal Spoilers': [false, 'Replace spoiler thumbnails by the original thumbnail'] @@ -3388,24 +3388,25 @@ return imgExpand.toggle(this); }, all: function() { - var thumb, _i, _j, _len, _len2, _ref, _ref2; + var i, thumb, thumbs, _i, _j, _len, _len2, _len3, _ref; imgExpand.on = this.checked; if (imgExpand.on) { - _ref = $$('img[md5]'); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - thumb = _ref[_i]; - if (conf['Expand All (Unscrolled)']) { - if (thumb.getBoundingClientRect().bottom >= 0) { - imgExpand.expand(thumb); - } - } else { - imgExpand.expand(thumb); + thumbs = $$('img[md5]'); + if (conf['Expand From Current']) { + for (i = 0, _len = thumbs.length; i < _len; i++) { + thumb = thumbs[i]; + if (thumb.getBoundingClientRect().top > 0) break; } + thumbs = thumbs.slice(i); + } + for (_i = 0, _len2 = thumbs.length; _i < _len2; _i++) { + thumb = thumbs[_i]; + imgExpand.expand(thumb); } } else { - _ref2 = $$('img[md5][hidden]'); - for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) { - thumb = _ref2[_j]; + _ref = $$('img[md5][hidden]'); + for (_j = 0, _len3 = _ref.length; _j < _len3; _j++) { + thumb = _ref[_j]; imgExpand.contract(thumb); } } diff --git a/script.coffee b/script.coffee index a4ea526a9..c7c429310 100644 --- a/script.coffee +++ b/script.coffee @@ -22,7 +22,7 @@ config = Imaging: 'Image Auto-Gif': [false, 'Animate gif thumbnails'] 'Image Expansion': [true, 'Expand images'] - 'Expand All (Unscrolled)': [false, 'Expand all images will only expand those which you have not scrolled past'] + 'Expand From Current': [true, 'Expand images from current position to thread end'] 'Image Hover': [false, 'Show full image on mouseover'] 'Sauce': [true, 'Add sauce to images'] 'Reveal Spoilers': [false, 'Replace spoiler thumbnails by the original thumbnail'] @@ -2664,12 +2664,14 @@ imgExpand = all: -> imgExpand.on = @checked if imgExpand.on #expand - for thumb in $$ 'img[md5]' - if conf['Expand All (Unscrolled)'] - if thumb.getBoundingClientRect().bottom >= 0 - imgExpand.expand thumb - else - imgExpand.expand thumb + thumbs = $$ 'img[md5]' + if conf['Expand From Current'] + for thumb, i in thumbs + if thumb.getBoundingClientRect().top > 0 + break + thumbs = thumbs[i...] + for thumb in thumbs + imgExpand.expand thumb else #contract for thumb in $$ 'img[md5][hidden]' imgExpand.contract thumb From a77191821bc9fd8eecbfda4cac8de19bae006f55 Mon Sep 17 00:00:00 2001 From: James Campos Date: Mon, 20 Feb 2012 14:22:59 -0800 Subject: [PATCH 3/9] expandImage, singular --- 4chan_x.user.js | 4 ++-- script.coffee | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 341bf5cdb..f1bcab6b6 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -169,7 +169,7 @@ expandThread: ['e', 'Expand thread'], watch: ['w', 'Watch thread'], hide: ['x', 'Hide thread'], - expandImages: ['m', 'Expand selected image'], + expandImage: ['m', 'Expand selected image'], expandAllImages: ['M', 'Expand all images'], update: ['u', 'Update now'], unreadCountTo0: ['z', 'Reset unread status'] @@ -933,7 +933,7 @@ case conf.expandThread: expandThread.toggle(thread); break; - case conf.expandImages: + case conf.expandImage: keybinds.img(thread); break; case conf.nextThread: diff --git a/script.coffee b/script.coffee index c7c429310..fab4742ab 100644 --- a/script.coffee +++ b/script.coffee @@ -98,7 +98,7 @@ config = expandThread: ['e', 'Expand thread'] watch: ['w', 'Watch thread'] hide: ['x', 'Hide thread'] - expandImages: ['m', 'Expand selected image'] + expandImage: ['m', 'Expand selected image'] expandAllImages: ['M', 'Expand all images'] update: ['u', 'Update now'] unreadCountTo0: ['z', 'Reset unread status'] @@ -699,7 +699,7 @@ keybinds = keybinds.open thread when conf.expandThread expandThread.toggle thread - when conf.expandImages + when conf.expandImage keybinds.img thread when conf.nextThread return if g.REPLY From 28e403c47091b4f6948f68b5d24086374c68a9cc Mon Sep 17 00:00:00 2001 From: James Campos Date: Mon, 20 Feb 2012 14:23:41 -0800 Subject: [PATCH 4/9] changelog --- changelog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/changelog b/changelog index 6560e094b..8007556dc 100644 --- a/changelog +++ b/changelog @@ -1,4 +1,6 @@ master +- aeosynth / ahodesuka + expand images from current position 2.26.4 - Mayhem From 75d8209d7a6deced31d45c0b7f8c7d20f8a8ed87 Mon Sep 17 00:00:00 2001 From: ahodesuka Date: Mon, 20 Feb 2012 19:43:29 -0600 Subject: [PATCH 5/9] Revert return of auto noko. --- changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog b/changelog index 8007556dc..001f66986 100644 --- a/changelog +++ b/changelog @@ -95,7 +95,7 @@ master see https://github.com/MayhemYDG/4chan-x/issues/136 2.24.4 -- ahokadesuka +- ahodesuka Scroll back up when unexpanding images. - e000 Prevent absurd cooldown durations. From a07fb2c9cbed3856b0f4b9246964098e5f19d46e Mon Sep 17 00:00:00 2001 From: ahodesuka Date: Mon, 20 Feb 2012 20:03:26 -0600 Subject: [PATCH 6/9] Auto noko to replies from the main board when not in dump mode. --- 4chan_x.user.js | 169 +++++++++++++++++++++++++------------------ changelog | 4 +- script.coffee | 186 ++++++++++++++++++++++++++++++++---------------- 3 files changed, 224 insertions(+), 135 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index f1bcab6b6..3324b7de9 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -90,9 +90,8 @@ }, Filtering: { 'Anonymize': [false, 'Make everybody anonymous'], - 'Filter': [false, 'Self-moderation placebo'], - 'Filter OPs': [false, 'Filter OPs along with their threads'], - 'Recursive Filtering': [false, 'Filter replies of filtered posts, recursively'], + 'Filter': [true, 'Self-moderation placebo'], + 'Recursive Filtering': [true, 'Filter replies of filtered posts, recursively'], 'Reply Hiding': [true, 'Hide single replies'], 'Thread Hiding': [true, 'Hide entire threads'], 'Show Stubs': [true, 'Of hidden threads / replies'] @@ -100,7 +99,6 @@ Imaging: { 'Image Auto-Gif': [false, 'Animate gif thumbnails'], 'Image Expansion': [true, 'Expand images'], - 'Expand From Current': [true, 'Expand images from current position to thread end'], 'Image Hover': [false, 'Show full image on mouseover'], 'Sauce': [true, 'Add sauce to images'], 'Reveal Spoilers': [false, 'Replace spoiler thumbnails by the original thumbnail'] @@ -120,6 +118,7 @@ 'Cooldown': [true, 'Prevent "flood detected" errors.'], 'Persistent QR': [false, 'The Quick reply won\'t disappear after posting.'], 'Auto Hide QR': [true, 'Automatically hide the quick reply when posting.'], + 'Auto Noko': [true, 'Always redirect to your post unless you are in dump mode'], 'Remember QR size': [false, 'Remember the size of the Quick reply (Firefox only).'], 'Remember Subject': [false, 'Remember the subject field, instead of resetting after posting.'], 'Remember Spoiler': [false, 'Remember the spoiler state, instead of resetting after posting.'], @@ -143,6 +142,7 @@ subject: '', comment: '', filename: '', + dimensions: '', filesize: '', md5: '' }, @@ -169,7 +169,7 @@ expandThread: ['e', 'Expand thread'], watch: ['w', 'Watch thread'], hide: ['x', 'Hide thread'], - expandImage: ['m', 'Expand selected image'], + expandImages: ['m', 'Expand selected image'], expandAllImages: ['M', 'Expand all images'], update: ['u', 'Update now'], unreadCountTo0: ['z', 'Reset unread status'] @@ -533,86 +533,113 @@ }; filter = { - regexps: {}, - callbacks: [], + filters: {}, init: function() { - var f, filter, key, m, _i, _len; + var boards, filter, hl, key, op, regexp, _i, _len, _ref, _ref2, _ref3; for (key in config.filter) { - if (!(m = conf[key].match(/^\/.+\/\w*$/gm))) continue; - this.regexps[key] = []; - for (_i = 0, _len = m.length; _i < _len; _i++) { - filter = m[_i]; - f = filter.match(/^\/(.+)\/(\w*)$/); + this.filters[key] = []; + _ref = conf[key].split('\n'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + filter = _ref[_i]; + if (filter[0] === '#') continue; + if (!(regexp = filter.match(/\/(.+)\/(\w*)/))) continue; + filter = filter.replace(regexp[0], ''); + boards = ((_ref2 = filter.match(/boards:([^;]+)/)) != null ? _ref2[1].toLowerCase() : void 0) || 'global'; + if (boards !== 'global' && boards.split(',').indexOf(g.BOARD) === -1) { + continue; + } try { - this.regexps[key].push(RegExp(f[1], f[2])); + regexp = RegExp(regexp[1], regexp[2]); } catch (e) { alert(e.message); + continue; } + op = ((_ref3 = filter.match(/op:(yes|no|only)/)) != null ? _ref3[1].toLowerCase() : void 0) || 'no'; + hl = /highlight/.test(filter); + this.filters[key].push(this.createFilter(regexp, op, hl)); } - this.callbacks.push(this[key]); + if (!this.filters[key].length) delete this.filters[key]; } - return g.callbacks.push(this.node); + if (Object.keys(this.filters).length) return g.callbacks.push(this.node); + }, + createFilter: function(regexp, op, hl) { + return function(root, value, isOP) { + if (isOP && op === 'no' || !isOP && op === 'only') return false; + if (!regexp.test(value)) return false; + if (hl) { + $.addClass(root, 'filter_highlight'); + } else if (isOP) { + threadHiding.hideHide(root.parentNode); + } else { + replyHiding.hideHide(root.previousSibling); + } + return true; + }; }, node: function(root) { - if (!root.className) { - if (filter.callbacks.some(function(callback) { - return callback(root); - })) { - return replyHiding.hideHide($('td:not([nowrap])', root)); - } - } else if (root.className === 'op' && !g.REPLY && conf['Filter OPs']) { - if (filter.callbacks.some(function(callback) { - return callback(root); - })) { - return threadHiding.hideHide(root.parentNode); - } + var isOP, key, klass; + klass = root.className; + if (/\binlined\b/.test(klass)) return; + if (!(isOP = klass === 'op')) root = $('td[id]', root); + for (key in filter.filters) { + if (filter.test(root, key, isOP)) return; } }, - test: function(key, value) { - return filter.regexps[key].some(function(regexp) { - return regexp.test(value); - }); + test: function(root, key, isOP) { + var filter, value, _i, _len, _ref; + value = this[key](root, isOP); + if (value === false) return false; + _ref = this.filters[key]; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + filter = _ref[_i]; + if (filter(root, value, isOP)) return true; + } + return false; }, - name: function(root) { + name: function(root, isOP) { var name; - name = root.className === 'op' ? $('.postername', root) : $('.commentpostername', root); - return filter.test('name', name.textContent); + name = isOP ? $('.postername', root) : $('.commentpostername', root); + return name.textContent; }, tripcode: function(root) { var trip; - if (trip = $('.postertrip', root)) { - return filter.test('tripcode', trip.textContent); - } + if (trip = $('.postertrip', root)) return trip.textContent; + return false; }, email: function(root) { var mail; - if (mail = $('.linkmail', root)) return filter.test('email', mail.href); + if (!(mail = $('.linkmail', root))) return mail.href; + return false; }, - subject: function(root) { + subject: function(root, isOP) { var sub; - sub = root.className === 'op' ? $('.filetitle', root) : $('.replytitle', root); - return filter.test('subject', sub.textContent); + sub = isOP ? $('.filetitle', root) : $('.replytitle', root); + return sub.textContent; }, comment: function(root) { - return filter.test('comment', ($.el('a', { + return ($.el('a', { innerHTML: $('blockquote', root).innerHTML.replace(/
/g, '\n') - })).textContent); + })).textContent; }, filename: function(root) { var file; - if (file = $('.filesize span', root)) { - return filter.test('filename', file.title); - } + if (file = $('.filesize > span', root)) return file.title; + return false; + }, + dimensions: function(root) { + var span; + if (span = $('.filesize', root)) return span.textContent.match(/\d+x\d+/)[0]; + return false; }, filesize: function(root) { var img; - if (img = $('img[md5]', root)) return filter.test('filesize', img.alt); + if (img = $('img[md5]', root)) return img.alt; + return false; }, md5: function(root) { var img; - if (img = $('img[md5]', root)) { - return filter.test('md5', img.getAttribute('md5')); - } + if (img = $('img[md5]', root)) return img.getAttribute('md5'); + return false; } }; @@ -933,7 +960,7 @@ case conf.expandThread: expandThread.toggle(thread); break; - case conf.expandImage: + case conf.expandImages: keybinds.img(thread); break; case conf.nextThread: @@ -1224,7 +1251,7 @@ $.before(form, link); } g.callbacks.push(this.node); - if (engine === 'webkit') { + if (/chrome/i.test(navigator.userAgent)) { qr.status({ ready: true }); @@ -1679,7 +1706,7 @@ }); ta.style.cssText = $.get('qr.size', ''); } - mimeTypes = $('.rules').textContent.match(/: (.+) /)[1].toLowerCase().replace(/\w+/g, function(type) { + mimeTypes = $('.rules').firstChild.textContent.match(/: (.+) /)[1].toLowerCase().replace(/\w+/g, function(type) { switch (type) { case 'jpg': return 'image/jpeg'; @@ -1833,7 +1860,7 @@ reader.readAsBinaryString(reply.file); return; } - if (engine === 'webkit') { + if (/chrome/i.test(navigator.userAgent)) { qr.message.post(post); return; } @@ -1888,6 +1915,9 @@ } else { qr.cooldown.auto = qr.replies.length > 1; qr.cooldown.set(/sage/i.test(reply.email) ? 60 : 30); + if (conf['Auto Noko'] && !g.REPLY && !qr.cooldown.auto) { + location.href = "http://boards.4chan.org/" + g.BOARD + "/res/" + thread + "#" + postNumber; + } } if (conf['Persistent QR'] || qr.cooldown.auto) { reply.rm(); @@ -1900,7 +1930,7 @@ message: { send: function(data) { var host, window; - if (engine === 'webkit') { + if (/chrome/i.test(navigator.userAgent)) { qr.message.receive(data); return; } @@ -2091,6 +2121,7 @@

Subject:

\

Comment:

\

Filename:

\ +

Image dimensions:

\

Filesize:

\

Image MD5:

\ \ @@ -3388,25 +3419,18 @@ return imgExpand.toggle(this); }, all: function() { - var i, thumb, thumbs, _i, _j, _len, _len2, _len3, _ref; + var thumb, _i, _j, _len, _len2, _ref, _ref2; imgExpand.on = this.checked; if (imgExpand.on) { - thumbs = $$('img[md5]'); - if (conf['Expand From Current']) { - for (i = 0, _len = thumbs.length; i < _len; i++) { - thumb = thumbs[i]; - if (thumb.getBoundingClientRect().top > 0) break; - } - thumbs = thumbs.slice(i); - } - for (_i = 0, _len2 = thumbs.length; _i < _len2; _i++) { - thumb = thumbs[_i]; + _ref = $$('img[md5]'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + thumb = _ref[_i]; imgExpand.expand(thumb); } } else { - _ref = $$('img[md5][hidden]'); - for (_j = 0, _len3 = _ref.length; _j < _len3; _j++) { - thumb = _ref[_j]; + _ref2 = $$('img[md5][hidden]'); + for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) { + thumb = _ref2[_j]; imgExpand.contract(thumb); } } @@ -4040,13 +4064,16 @@ img[md5], img[md5] + img {\ .inlined {\ opacity: .5;\ }\ -.inline td.reply {\ +.inline .reply {\ background-color: rgba(255, 255, 255, 0.15);\ border: 1px solid rgba(128, 128, 128, 0.5);\ }\ .filetitle, .replytitle, .postername, .commentpostername, .postertrip {\ background: none;\ }\ +.filter_highlight {\ + box-shadow: -5px 0 rgba(255,0,0,0.5);\ +}\ .filtered {\ text-decoration: line-through;\ }\ diff --git a/changelog b/changelog index 001f66986..f3258e431 100644 --- a/changelog +++ b/changelog @@ -1,6 +1,6 @@ master -- aeosynth / ahodesuka - expand images from current position +- ahodesuka + Add auto noko option for replies from the main board and not dumping. 2.26.4 - Mayhem diff --git a/script.coffee b/script.coffee index fab4742ab..f4b95367f 100644 --- a/script.coffee +++ b/script.coffee @@ -13,16 +13,14 @@ config = 'Check for Updates': [true, 'Check for updated versions of 4chan X'] Filtering: 'Anonymize': [false, 'Make everybody anonymous'] - 'Filter': [false, 'Self-moderation placebo'] - 'Filter OPs': [false, 'Filter OPs along with their threads'] - 'Recursive Filtering': [false, 'Filter replies of filtered posts, recursively'] + 'Filter': [true, 'Self-moderation placebo'] + 'Recursive Filtering': [true, 'Filter replies of filtered posts, recursively'] 'Reply Hiding': [true, 'Hide single replies'] 'Thread Hiding': [true, 'Hide entire threads'] 'Show Stubs': [true, 'Of hidden threads / replies'] Imaging: 'Image Auto-Gif': [false, 'Animate gif thumbnails'] 'Image Expansion': [true, 'Expand images'] - 'Expand From Current': [true, 'Expand images from current position to thread end'] 'Image Hover': [false, 'Show full image on mouseover'] 'Sauce': [true, 'Add sauce to images'] 'Reveal Spoilers': [false, 'Replace spoiler thumbnails by the original thumbnail'] @@ -40,6 +38,7 @@ config = 'Cooldown': [true, 'Prevent "flood detected" errors.'] 'Persistent QR': [false, 'The Quick reply won\'t disappear after posting.'] 'Auto Hide QR': [true, 'Automatically hide the quick reply when posting.'] + 'Auto Noko': [true, 'Always redirect to your post unless you are in dump mode'] 'Remember QR size': [false, 'Remember the size of the Quick reply (Firefox only).'] 'Remember Subject': [false, 'Remember the subject field, instead of resetting after posting.'] 'Remember Spoiler': [false, 'Remember the spoiler state, instead of resetting after posting.'] @@ -54,14 +53,15 @@ config = 'Indicate Cross-thread Quotes': [true, 'Add \'(Cross-thread)\' to cross-threads quotes'] 'Forward Hiding': [true, 'Hide original posts of inlined backlinks'] filter: - name: '' - tripcode: '' - email: '' - subject: '' - comment: '' - filename: '' - filesize: '' - md5: '' + name: '' + tripcode: '' + email: '' + subject: '' + comment: '' + filename: '' + dimensions: '' + filesize: '' + md5: '' sauces: [ 'http://iqdb.org/?url=$1' 'http://www.google.com/searchbyimage?image_url=$1' @@ -98,7 +98,7 @@ config = expandThread: ['e', 'Expand thread'] watch: ['w', 'Watch thread'] hide: ['x', 'Hide thread'] - expandImage: ['m', 'Expand selected image'] + expandImages: ['m', 'Expand selected image'] expandAllImages: ['M', 'Expand all images'] update: ['u', 'Update now'] unreadCountTo0: ['z', 'Reset unread status'] @@ -409,58 +409,117 @@ $$ = (selector, root=d.body) -> Array::slice.call root.querySelectorAll selector filter = - regexps: {} - callbacks: [] + filters: {} init: -> for key of config.filter - unless m = conf[key].match /^\/.+\/\w*$/gm - continue - @regexps[key] = [] - for filter in m - f = filter.match /^\/(.+)\/(\w*)$/ - try - @regexps[key].push RegExp f[1], f[2] - catch e - alert e.message - #only execute what's filterable - @callbacks.push @[key] + @filters[key] = [] + for filter in conf[key].split('\n') + continue if filter[0] is '#' - g.callbacks.push @node + unless regexp = filter.match /\/(.+)\/(\w*)/ + continue + + # Don't mix up filter flags with the regular expression. + filter = filter.replace regexp[0], '' + + # Do not add this filter to the list if it's not a global one + # and it's not specifically applicable to the current board. + # Defaults to global. + boards = filter.match(/boards:([^;]+)/)?[1].toLowerCase() or 'global' + if boards isnt 'global' and boards.split(',').indexOf(g.BOARD) is -1 + continue + + try + # Please, don't write silly regular expressions. + regexp = RegExp regexp[1], regexp[2] + catch e + # I warned you, bro. + alert e.message + continue + + # Filter OPs along with their threads, replies only, or both. + # Defaults to replies only. + op = filter.match(/op:(yes|no|only)/)?[1].toLowerCase() or 'no' + + # Highlight the post, or hide it. + # Defaults to post hiding. + hl = /highlight/.test filter + + @filters[key].push @createFilter regexp, op, hl + + # Only execute filter types that contain valid filters. + unless @filters[key].length + delete @filters[key] + + if Object.keys(@filters).length + g.callbacks.push @node + + createFilter: (regexp, op, hl) -> + (root, value, isOP) -> + if isOP and op is 'no' or !isOP and op is 'only' + return false + unless regexp.test value + return false + if hl + $.addClass root, 'filter_highlight' + else if isOP + threadHiding.hideHide root.parentNode + else + replyHiding.hideHide root.previousSibling + true node: (root) -> - unless root.className - if filter.callbacks.some((callback) -> callback root) - replyHiding.hideHide $ 'td:not([nowrap])', root - else if root.className is 'op' and not g.REPLY and conf['Filter OPs'] - if filter.callbacks.some((callback) -> callback root) - threadHiding.hideHide root.parentNode + klass = root.className + return if /\binlined\b/.test klass + unless isOP = klass is 'op' + root = $ 'td[id]', root + for key of filter.filters + if filter.test root, key, isOP + return - test: (key, value) -> - filter.regexps[key].some (regexp) -> regexp.test value + test: (root, key, isOP) -> + value = @[key] root, isOP + if value is false + # Return if there's nothing to filter (no tripcode for example). + return false - name: (root) -> - name = if root.className is 'op' then $ '.postername', root else $ '.commentpostername', root - filter.test 'name', name.textContent + for filter in @filters[key] + if filter root, value, isOP + return true + false + + name: (root, isOP) -> + name = if isOP then $ '.postername', root else $ '.commentpostername', root + name.textContent tripcode: (root) -> if trip = $ '.postertrip', root - filter.test 'tripcode', trip.textContent + return trip.textContent + false email: (root) -> - if mail = $ '.linkmail', root - filter.test 'email', mail.href - subject: (root) -> - sub = if root.className is 'op' then $ '.filetitle', root else $ '.replytitle', root - filter.test 'subject', sub.textContent + unless mail = $ '.linkmail', root + return mail.href + false + subject: (root, isOP) -> + sub = if isOP then $ '.filetitle', root else $ '.replytitle', root + sub.textContent comment: (root) -> - filter.test 'comment', ($.el 'a', innerHTML: $('blockquote', root).innerHTML.replace /
/g, '\n').textContent + ($.el 'a', innerHTML: $('blockquote', root).innerHTML.replace /
/g, '\n').textContent filename: (root) -> - if file = $ '.filesize span', root - filter.test 'filename', file.title + if file = $ '.filesize > span', root + return file.title + false + dimensions: (root) -> + if span = $ '.filesize', root + return span.textContent.match(/\d+x\d+/)[0] + return false filesize: (root) -> if img = $ 'img[md5]', root - filter.test 'filesize', img.alt + return img.alt + false md5: (root) -> if img = $ 'img[md5]', root - filter.test 'md5', img.getAttribute('md5') + return img.getAttribute 'md5' + false strikethroughQuotes = init: -> @@ -699,7 +758,7 @@ keybinds = keybinds.open thread when conf.expandThread expandThread.toggle thread - when conf.expandImage + when conf.expandImages keybinds.img thread when conf.nextThread return if g.REPLY @@ -901,7 +960,8 @@ qr = $.before form, link g.callbacks.push @node - if engine is 'webkit' + # CORS is ignored for content script on Chrome, but not Safari/Oprah/Firefox. + if /chrome/i.test navigator.userAgent qr.status ready: true else iframe = $.el 'iframe', @@ -1266,7 +1326,7 @@ qr = ta.style.cssText = $.get 'qr.size', '' # Allow only this board's supported files. - mimeTypes = $('.rules').textContent.match(/: (.+) /)[1].toLowerCase().replace /\w+/g, (type) -> + mimeTypes = $('.rules').firstChild.textContent.match(/: (.+) /)[1].toLowerCase().replace /\w+/g, (type) -> switch type when 'jpg' 'image/jpeg' @@ -1406,7 +1466,8 @@ qr = reader.readAsBinaryString reply.file return - if engine is 'webkit' + # CORS is ignored for content script on Chrome, but not Safari/Oprah/Firefox. + if /chrome/i.test navigator.userAgent qr.message.post post return qr.message.send post @@ -1457,6 +1518,8 @@ qr = # Enable auto-posting if we have stuff to post, disable it otherwise. qr.cooldown.auto = qr.replies.length > 1 qr.cooldown.set if /sage/i.test reply.email then 60 else 30 + # auto-noko + location.href = "http://boards.4chan.org/#{g.BOARD}/res/#{thread}##{postNumber}" if conf['Auto Noko'] && !g.REPLY && !qr.cooldown.auto if conf['Persistent QR'] or qr.cooldown.auto reply.rm() @@ -1468,7 +1531,8 @@ qr = message: send: (data) -> - if engine is 'webkit' + # CORS is ignored for content script on Chrome, but not Safari/Oprah/Firefox. + if /chrome/i.test navigator.userAgent qr.message.receive data return data.qr = true @@ -1627,6 +1691,7 @@ options =

Subject:

Comment:

Filename:

+

Image dimensions:

Filesize:

Image MD5:

@@ -2664,13 +2729,7 @@ imgExpand = all: -> imgExpand.on = @checked if imgExpand.on #expand - thumbs = $$ 'img[md5]' - if conf['Expand From Current'] - for thumb, i in thumbs - if thumb.getBoundingClientRect().top > 0 - break - thumbs = thumbs[i...] - for thumb in thumbs + for thumb in $$ 'img[md5]' imgExpand.expand thumb else #contract for thumb in $$ 'img[md5][hidden]' @@ -3310,13 +3369,16 @@ img[md5], img[md5] + img { .inlined { opacity: .5; } -.inline td.reply { +.inline .reply { background-color: rgba(255, 255, 255, 0.15); border: 1px solid rgba(128, 128, 128, 0.5); } .filetitle, .replytitle, .postername, .commentpostername, .postertrip { background: none; } +.filter_highlight { + box-shadow: -5px 0 rgba(255,0,0,0.5); +} .filtered { text-decoration: line-through; } From e47a3ccf58e0659b9e059161ee6591dca73ccd08 Mon Sep 17 00:00:00 2001 From: ahodesuka Date: Mon, 20 Feb 2012 20:14:59 -0600 Subject: [PATCH 7/9] Clean up changelog. --- changelog | 3 --- 1 file changed, 3 deletions(-) diff --git a/changelog b/changelog index 8b252f753..7b303228c 100644 --- a/changelog +++ b/changelog @@ -1,8 +1,6 @@ master -<<<<<<< HEAD - ahodesuka Add auto noko option for replies from the main board and not dumping. -======= - Mayhem The Filter now has per filter settings: - Filter the OP along its thread, replies only, or both. @@ -11,7 +9,6 @@ master New filter group: Image dimensions. Fix posting on Safari. Fix rare case where the QR would not accept certain image types. ->>>>>>> 15b7a55fe01b90965f3663202b71d799456ff95e 2.26.4 - Mayhem From f474a0c3c8eeedb62a444f4339b83602dc82e06d Mon Sep 17 00:00:00 2001 From: ahodesuka Date: Mon, 20 Feb 2012 20:21:37 -0600 Subject: [PATCH 8/9] Update and build. --- script.coffee | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/script.coffee b/script.coffee index f4b95367f..17c305030 100644 --- a/script.coffee +++ b/script.coffee @@ -2851,6 +2851,11 @@ Main = $.ready options.init + if conf['Quick Reply'] and conf['Hide Original Post Form'] + Main.css += 'form[name=post] { display: none; }' + + Main.addStyle() + now = Date.now() if conf['Check for Updates'] and $.get('lastUpdate', 0) < now - 6*HOUR $.ready -> $.add d.head, $.el 'script', src: 'https://raw.github.com/mayhemydg/4chan-x/master/latest.js' @@ -2921,11 +2926,6 @@ Main = if conf['Fix XXX\'d Post Numbers'] unxify.init() - if conf['Quick Reply'] and conf['Hide Original Post Form'] - Main.css += 'form[name=post] { display: none; }' - - Main.addStyle() - $.ready Main.ready ready: -> From 0297ac9c955b5e87e3c9297fdce7c2a757017041 Mon Sep 17 00:00:00 2001 From: ahodesuka Date: Mon, 20 Feb 2012 21:57:51 -0600 Subject: [PATCH 9/9] Change auto noko to open reply in new tab. --- 4chan_x.user.js | 9 +++++---- changelog | 2 +- script.coffee | 7 ++++--- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 50b08f21e..c228aa4ae 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -118,7 +118,7 @@ 'Cooldown': [true, 'Prevent "flood detected" errors.'], 'Persistent QR': [false, 'The Quick reply won\'t disappear after posting.'], 'Auto Hide QR': [true, 'Automatically hide the quick reply when posting.'], - 'Auto Noko': [true, 'Always redirect to your post unless you are in dump mode'], + 'Open Reply in New Tab': [false, 'Open replies in a new tab that are made from the main board.'], 'Remember QR size': [false, 'Remember the size of the Quick reply (Firefox only).'], 'Remember Subject': [false, 'Remember the subject field, instead of resetting after posting.'], 'Remember Spoiler': [false, 'Remember the spoiler state, instead of resetting after posting.'], @@ -1867,7 +1867,7 @@ return qr.message.send(post); }, response: function(html) { - var b, doc, err, node, persona, postNumber, reply, thread, _, _ref; + var b, doc, err, node, open, persona, postNumber, reply, thread, _, _ref; doc = $.el('a', { innerHTML: html }); @@ -1915,8 +1915,9 @@ } else { qr.cooldown.auto = qr.replies.length > 1; qr.cooldown.set(/sage/i.test(reply.email) ? 60 : 30); - if (conf['Auto Noko'] && !g.REPLY && !qr.cooldown.auto) { - location.href = "http://boards.4chan.org/" + g.BOARD + "/res/" + thread + "#" + postNumber; + if (conf['Open Reply in New Tab'] && !g.REPLY && !qr.cooldown.auto) { + open = GM_openInTab || window.open; + open("http://boards.4chan.org/" + g.BOARD + "/res/" + thread + "#" + postNumber, "_blank"); } } if (conf['Persistent QR'] || qr.cooldown.auto) { diff --git a/changelog b/changelog index 95e73aab9..199f2d762 100644 --- a/changelog +++ b/changelog @@ -1,6 +1,6 @@ master - ahodesuka - Add auto noko option for replies from the main board and not dumping. + Add Open Reply in New Tab option for replies made from the main board (not dumping). - Mayhem The Filter now has per filter settings: - Filter the OP along its thread, replies only, or both. diff --git a/script.coffee b/script.coffee index 17c305030..c6816e961 100644 --- a/script.coffee +++ b/script.coffee @@ -38,7 +38,7 @@ config = 'Cooldown': [true, 'Prevent "flood detected" errors.'] 'Persistent QR': [false, 'The Quick reply won\'t disappear after posting.'] 'Auto Hide QR': [true, 'Automatically hide the quick reply when posting.'] - 'Auto Noko': [true, 'Always redirect to your post unless you are in dump mode'] + 'Open Reply in New Tab': [false, 'Open replies in a new tab that are made from the main board.'] 'Remember QR size': [false, 'Remember the size of the Quick reply (Firefox only).'] 'Remember Subject': [false, 'Remember the subject field, instead of resetting after posting.'] 'Remember Spoiler': [false, 'Remember the spoiler state, instead of resetting after posting.'] @@ -1518,8 +1518,9 @@ qr = # Enable auto-posting if we have stuff to post, disable it otherwise. qr.cooldown.auto = qr.replies.length > 1 qr.cooldown.set if /sage/i.test reply.email then 60 else 30 - # auto-noko - location.href = "http://boards.4chan.org/#{g.BOARD}/res/#{thread}##{postNumber}" if conf['Auto Noko'] && !g.REPLY && !qr.cooldown.auto + if conf['Open Reply in New Tab'] && !g.REPLY && !qr.cooldown.auto + open = GM_openInTab or window.open + open "http://boards.4chan.org/#{g.BOARD}/res/#{thread}##{postNumber}", "_blank" if conf['Persistent QR'] or qr.cooldown.auto reply.rm()