formatting
alphabetize funks, put main in one place
This commit is contained in:
parent
975fb0ebff
commit
52b6d7982f
915
4chan_x.coffee
915
4chan_x.coffee
@ -4,6 +4,7 @@
|
|||||||
#
|
#
|
||||||
#TODO - 4chan time
|
#TODO - 4chan time
|
||||||
#addClass, removeClass; remove hide / show; makeDialog el, 'center'
|
#addClass, removeClass; remove hide / show; makeDialog el, 'center'
|
||||||
|
#TODO - expose 'hidden' configs
|
||||||
|
|
||||||
config =
|
config =
|
||||||
'Thread Hiding': [true, 'Hide entire threads']
|
'Thread Hiding': [true, 'Hide entire threads']
|
||||||
@ -23,8 +24,7 @@ config =
|
|||||||
'Post in Title': [true, 'Show the op\'s post in the tab title']
|
'Post in Title': [true, 'Show the op\'s post in the tab title']
|
||||||
'Sauce': [true, 'Add sauce to images']
|
'Sauce': [true, 'Add sauce to images']
|
||||||
|
|
||||||
#TODO - expose 'hidden' configs
|
#utility
|
||||||
|
|
||||||
AEOS =
|
AEOS =
|
||||||
init: ->
|
init: ->
|
||||||
#x-browser
|
#x-browser
|
||||||
@ -49,7 +49,6 @@ AEOS =
|
|||||||
style.type = 'text/css'
|
style.type = 'text/css'
|
||||||
style.textContent = css
|
style.textContent = css
|
||||||
document.getElementsByTagName('head')[0].appendChild style
|
document.getElementsByTagName('head')[0].appendChild style
|
||||||
|
|
||||||
#dialog styling
|
#dialog styling
|
||||||
GM_addStyle '
|
GM_addStyle '
|
||||||
div.dialog {
|
div.dialog {
|
||||||
@ -63,13 +62,11 @@ AEOS =
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
'
|
'
|
||||||
|
|
||||||
#dialog creation
|
#dialog creation
|
||||||
makeDialog: (id, position) ->
|
makeDialog: (id, position) ->
|
||||||
dialog = document.createElement 'div'
|
dialog = document.createElement 'div'
|
||||||
dialog.className = 'reply dialog'
|
dialog.className = 'reply dialog'
|
||||||
dialog.id = id
|
dialog.id = id
|
||||||
|
|
||||||
switch position
|
switch position
|
||||||
when 'topleft'
|
when 'topleft'
|
||||||
left = '0px'
|
left = '0px'
|
||||||
@ -83,14 +80,11 @@ AEOS =
|
|||||||
when 'bottomright'
|
when 'bottomright'
|
||||||
left = null
|
left = null
|
||||||
top = null
|
top = null
|
||||||
|
|
||||||
left = GM_getValue "#{id}Left", left
|
left = GM_getValue "#{id}Left", left
|
||||||
top = GM_getValue "#{id}Top", top
|
top = GM_getValue "#{id}Top", top
|
||||||
if left then dialog.style.left = left else dialog.style.right = '0px'
|
if left then dialog.style.left = left else dialog.style.right = '0px'
|
||||||
if top then dialog.style.top = top else dialog.style.bottom = '0px'
|
if top then dialog.style.top = top else dialog.style.bottom = '0px'
|
||||||
|
|
||||||
dialog
|
dialog
|
||||||
|
|
||||||
#movement
|
#movement
|
||||||
move: (e) ->
|
move: (e) ->
|
||||||
div = @parentNode
|
div = @parentNode
|
||||||
@ -101,39 +95,31 @@ AEOS =
|
|||||||
#factor out div from document dimensions
|
#factor out div from document dimensions
|
||||||
AEOS.width = document.body.clientWidth - div.offsetWidth
|
AEOS.width = document.body.clientWidth - div.offsetWidth
|
||||||
AEOS.height = document.body.clientHeight - div.offsetHeight
|
AEOS.height = document.body.clientHeight - div.offsetHeight
|
||||||
|
|
||||||
document.addEventListener 'mousemove', AEOS.moveMove, true
|
document.addEventListener 'mousemove', AEOS.moveMove, true
|
||||||
document.addEventListener 'mouseup', AEOS.moveEnd, true
|
document.addEventListener 'mouseup', AEOS.moveEnd, true
|
||||||
|
|
||||||
moveMove: (e) ->
|
moveMove: (e) ->
|
||||||
div = AEOS.div
|
div = AEOS.div
|
||||||
|
|
||||||
left = e.clientX - AEOS.dx
|
left = e.clientX - AEOS.dx
|
||||||
if left < 20 then left = '0px'
|
if left < 20 then left = '0px'
|
||||||
else if AEOS.width - left < 20 then left = ''
|
else if AEOS.width - left < 20 then left = ''
|
||||||
right = if left then '' else '0px'
|
right = if left then '' else '0px'
|
||||||
div.style.left = left
|
div.style.left = left
|
||||||
div.style.right = right
|
div.style.right = right
|
||||||
|
|
||||||
top = e.clientY - AEOS.dy
|
top = e.clientY - AEOS.dy
|
||||||
if top < 20 then top = '0px'
|
if top < 20 then top = '0px'
|
||||||
else if AEOS.height - top < 20 then top = ''
|
else if AEOS.height - top < 20 then top = ''
|
||||||
bottom = if top then '' else '0px'
|
bottom = if top then '' else '0px'
|
||||||
div.style.top = top
|
div.style.top = top
|
||||||
div.style.bottom = bottom
|
div.style.bottom = bottom
|
||||||
|
|
||||||
moveEnd: ->
|
moveEnd: ->
|
||||||
document.removeEventListener 'mousemove', AEOS.moveMove, true
|
document.removeEventListener 'mousemove', AEOS.moveMove, true
|
||||||
document.removeEventListener 'mouseup', AEOS.moveEnd, true
|
document.removeEventListener 'mouseup', AEOS.moveEnd, true
|
||||||
|
|
||||||
div = AEOS.div
|
div = AEOS.div
|
||||||
id = div.id
|
id = div.id
|
||||||
GM_setValue "#{id}Left", div.style.left
|
GM_setValue "#{id}Left", div.style.left
|
||||||
GM_setValue "#{id}Top", div.style.top
|
GM_setValue "#{id}Top", div.style.top
|
||||||
|
|
||||||
AEOS.init()
|
|
||||||
d = document
|
d = document
|
||||||
#utility funks
|
|
||||||
$ = (selector, root) ->
|
$ = (selector, root) ->
|
||||||
root or= d.body
|
root or= d.body
|
||||||
root.querySelector(selector)
|
root.querySelector(selector)
|
||||||
@ -190,6 +176,434 @@ x = (path, root) ->
|
|||||||
d.evaluate(path, root, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).
|
d.evaluate(path, root, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).
|
||||||
singleNodeValue
|
singleNodeValue
|
||||||
|
|
||||||
|
#funks
|
||||||
|
autohide = ->
|
||||||
|
qr = $ '#qr'
|
||||||
|
klass = qr.className
|
||||||
|
if klass.indexOf('auto') is -1
|
||||||
|
klass += ' auto'
|
||||||
|
else
|
||||||
|
klass = klass.replace(' auto', '')
|
||||||
|
qr.className = klass
|
||||||
|
|
||||||
|
autoWatch = ->
|
||||||
|
#TODO look for subject
|
||||||
|
autoText = $('textarea', this).value.slice(0, 25)
|
||||||
|
GM_setValue('autoText', "/#{BOARD}/ - #{autoText}")
|
||||||
|
|
||||||
|
close = ->
|
||||||
|
div = this.parentNode.parentNode
|
||||||
|
remove div
|
||||||
|
|
||||||
|
clearHidden = ->
|
||||||
|
#'hidden' might be misleading; it's the number of IDs we're *looking* for,
|
||||||
|
# not the number of posts actually hidden on the page.
|
||||||
|
GM_deleteValue("hiddenReplies/#{BOARD}/")
|
||||||
|
GM_deleteValue("hiddenThreads/#{BOARD}/")
|
||||||
|
@value = "hidden: 0"
|
||||||
|
hiddenReplies = []
|
||||||
|
hiddenThreads = []
|
||||||
|
|
||||||
|
cooldown = ->
|
||||||
|
submit = $ '#qr input[type=submit]'
|
||||||
|
seconds = parseInt submit.value
|
||||||
|
if seconds == 0
|
||||||
|
submit.disabled = false
|
||||||
|
submit.value = 'Submit'
|
||||||
|
auto = submit.previousSibling.lastChild
|
||||||
|
if auto.checked
|
||||||
|
$('#qr form').submit()
|
||||||
|
#submit.click() doesn't work
|
||||||
|
else
|
||||||
|
submit.value = seconds - 1
|
||||||
|
window.setTimeout cooldown, 1000
|
||||||
|
|
||||||
|
editSauce = ->
|
||||||
|
ta = $ '#options textarea'
|
||||||
|
if ta.style.display then show ta else hide ta
|
||||||
|
|
||||||
|
expandComment = (e) ->
|
||||||
|
e.preventDefault()
|
||||||
|
a = this
|
||||||
|
href = a.getAttribute('href')
|
||||||
|
r = new XMLHttpRequest()
|
||||||
|
r.onload = ->
|
||||||
|
onloadComment(this.responseText, a, href)
|
||||||
|
r.open('GET', href, true)
|
||||||
|
r.send()
|
||||||
|
xhrs.push({
|
||||||
|
r: r,
|
||||||
|
id: href.match(/\d+/)[0]
|
||||||
|
})
|
||||||
|
|
||||||
|
expandThread = ->
|
||||||
|
id = x('preceding-sibling::input[1]', this).name
|
||||||
|
span = this
|
||||||
|
#close expanded thread
|
||||||
|
if span.textContent[0] is '-'
|
||||||
|
#goddamit moot
|
||||||
|
num = if board is 'b' then 3 else 5
|
||||||
|
table = x("following::br[@clear][1]/preceding::table[#{num}]", span)
|
||||||
|
while (prev = table.previousSibling) and (prev.nodeName is 'TABLE')
|
||||||
|
remove(prev)
|
||||||
|
span.textContent = span.textContent.replace('-', '+')
|
||||||
|
return
|
||||||
|
span.textContent = span.textContent.replace('+', 'X Loading...')
|
||||||
|
#load cache
|
||||||
|
for xhr in xhrs
|
||||||
|
if xhr.id == id
|
||||||
|
#why can't we just xhr.r.onload()?
|
||||||
|
onloadThread(xhr.r.responseText, span)
|
||||||
|
return
|
||||||
|
#create new request
|
||||||
|
r = new XMLHttpRequest()
|
||||||
|
r.onload = ->
|
||||||
|
onloadThread(this.responseText, span)
|
||||||
|
r.open('GET', "res/#{id}", true)
|
||||||
|
r.send()
|
||||||
|
xhrs.push({
|
||||||
|
r: r,
|
||||||
|
id: id
|
||||||
|
})
|
||||||
|
|
||||||
|
hideReply = (reply) ->
|
||||||
|
if p = this.parentNode
|
||||||
|
reply = p.nextSibling
|
||||||
|
hiddenReplies.push({
|
||||||
|
id: reply.id
|
||||||
|
timestamp: getTime()
|
||||||
|
})
|
||||||
|
GM_setValue("hiddenReplies/#{BOARD}/", JSON.stringify(hiddenReplies))
|
||||||
|
name = $('span.commentpostername', reply).textContent
|
||||||
|
trip = $('span.postertrip', reply)?.textContent || ''
|
||||||
|
table = x('ancestor::table', reply)
|
||||||
|
hide(table)
|
||||||
|
if getConfig 'Show Stubs'
|
||||||
|
a = n 'a',
|
||||||
|
textContent: "[ + ] #{name} #{trip}"
|
||||||
|
className: 'pointer'
|
||||||
|
listener: ['click', showReply]
|
||||||
|
div = n 'div'
|
||||||
|
addTo div, a
|
||||||
|
inBefore table, div
|
||||||
|
|
||||||
|
hideThread = (div) ->
|
||||||
|
if p = @parentNode
|
||||||
|
div = p
|
||||||
|
hiddenThreads.push {
|
||||||
|
id: div.id
|
||||||
|
timestamp: getTime()
|
||||||
|
}
|
||||||
|
GM_setValue("hiddenThreads/#{BOARD}/", JSON.stringify(hiddenThreads))
|
||||||
|
hide div
|
||||||
|
if getConfig 'Show Stubs'
|
||||||
|
if span = $ '.omittedposts', div
|
||||||
|
num = Number(span.textContent.match(/\d+/)[0])
|
||||||
|
else
|
||||||
|
num = 0
|
||||||
|
num += $$('table', div).length
|
||||||
|
text = if num is 1 then "1 reply" else "#{num} replies"
|
||||||
|
name = $('span.postername', div).textContent
|
||||||
|
trip = $('span.postername + span.postertrip', div)?.textContent || ''
|
||||||
|
a = n 'a',
|
||||||
|
textContent: "[ + ] #{name}#{trip} (#{text})"
|
||||||
|
className: 'pointer'
|
||||||
|
listener: ['click', showThread]
|
||||||
|
inBefore div, a
|
||||||
|
|
||||||
|
iframeLoad = ->
|
||||||
|
if iframeLoop = !iframeLoop
|
||||||
|
return
|
||||||
|
$('iframe').src = 'about:blank'
|
||||||
|
qr = $('#qr')
|
||||||
|
if error = GM_getValue('error')
|
||||||
|
span = n 'span',
|
||||||
|
textContent: error
|
||||||
|
className: 'error'
|
||||||
|
addTo qr, span
|
||||||
|
$('input[title=autohide]:checked', qr)?.click()
|
||||||
|
else if REPLY and getConfig 'Persistent QR'
|
||||||
|
$('textarea', qr).value = ''
|
||||||
|
$('input[name=recaptcha_response_field]', qr).value = ''
|
||||||
|
submit = $('input[type=submit]', qr)
|
||||||
|
submit.value = 30
|
||||||
|
submit.disabled = true
|
||||||
|
window.setTimeout cooldown, 1000
|
||||||
|
auto = submit.previousSibling.lastChild
|
||||||
|
if auto.checked
|
||||||
|
#unhide the qr so you know it's ready for the next item
|
||||||
|
$('input[title=autohide]:checked', qr)?.click()
|
||||||
|
else
|
||||||
|
remove qr
|
||||||
|
recaptchaReload()
|
||||||
|
|
||||||
|
nodeInserted = (e) ->
|
||||||
|
target = e.target
|
||||||
|
if target.nodeName is 'TABLE'
|
||||||
|
for callback in callbacks
|
||||||
|
callback(target)
|
||||||
|
else if target.id is 'recaptcha_challenge_field' and qr = $ '#qr'
|
||||||
|
$('#recaptcha_image img', qr).src = "http://www.google.com/recaptcha/api/image?c=" + target.value
|
||||||
|
$('#recaptcha_challenge_field', qr).value = target.value
|
||||||
|
|
||||||
|
onloadComment = (responseText, a, href) ->
|
||||||
|
[_, op, id] = href.match(/(\d+)#(\d+)/)
|
||||||
|
[replies, opbq] = parseResponse(responseText)
|
||||||
|
if id is op
|
||||||
|
html = opbq.innerHTML
|
||||||
|
else
|
||||||
|
#css selectors don't like ids starting with numbers,
|
||||||
|
# getElementById only works for root document.
|
||||||
|
for reply in replies
|
||||||
|
if reply.id == id
|
||||||
|
html = $('blockquote', reply).innerHTML
|
||||||
|
bq = x('ancestor::blockquote', a)
|
||||||
|
bq.innerHTML = html
|
||||||
|
|
||||||
|
onloadThread = (responseText, span) ->
|
||||||
|
[replies, opbq] = parseResponse(responseText)
|
||||||
|
span.textContent = span.textContent.replace('X Loading...', '- ')
|
||||||
|
#make sure all comments are fully expanded
|
||||||
|
span.previousSibling.innerHTML = opbq.innerHTML
|
||||||
|
while (next = span.nextSibling) and not next.clear#<br clear>
|
||||||
|
remove(next)
|
||||||
|
if next
|
||||||
|
for reply in replies
|
||||||
|
inBefore next, x('ancestor::table', reply)
|
||||||
|
else#threading
|
||||||
|
div = span.parentNode
|
||||||
|
for reply in replies
|
||||||
|
addTo div, x('ancestor::table', reply)
|
||||||
|
|
||||||
|
options = ->
|
||||||
|
if div = $ '#options'
|
||||||
|
remove div
|
||||||
|
else
|
||||||
|
div = AEOS.makeDialog 'options', 'center'
|
||||||
|
hiddenNum = hiddenReplies.length + hiddenThreads.length
|
||||||
|
html = '<div class="move">Options <a class=pointer>X</a></div><div>'
|
||||||
|
for option, value of config
|
||||||
|
description = value[1]
|
||||||
|
checked = if getConfig option then "checked" else ""
|
||||||
|
html += "<label title=\"#{description}\">#{option}<input #{checked} name=\"#{option}\" type=\"checkbox\"></label><br>"
|
||||||
|
html += "<div><a class=sauce>Edit Sauce</a></div>"
|
||||||
|
html += "<div><textarea cols=50 rows=4 style=\"display: none;\"></textarea></div>"
|
||||||
|
html += "<input type=\"button\" value=\"hidden: #{hiddenNum}\"><br>"
|
||||||
|
div.innerHTML = html
|
||||||
|
$('div.move', div).addEventListener 'mousedown', AEOS.move, true
|
||||||
|
$('a.pointer', div).addEventListener 'click', optionsClose, true
|
||||||
|
$('a.sauce', div).addEventListener 'click', editSauce, true
|
||||||
|
$('textarea', div).value = GM_getValue 'saucePrefix', defaultSaucePrefix
|
||||||
|
$('input[type="button"]', div).addEventListener 'click', clearHidden, true
|
||||||
|
addTo d.body, div
|
||||||
|
|
||||||
|
optionsClose = ->
|
||||||
|
div = this.parentNode.parentNode
|
||||||
|
inputs = $$('input', div)
|
||||||
|
for input in inputs
|
||||||
|
GM_setValue(input.name, input.checked)
|
||||||
|
GM_setValue 'saucePrefix', $('textarea', div).value
|
||||||
|
remove div
|
||||||
|
|
||||||
|
parseResponse = (responseText) ->
|
||||||
|
body = n 'body',
|
||||||
|
innerHTML: responseText
|
||||||
|
replies = $$('td.reply', body)
|
||||||
|
opbq = $('blockquote', body)
|
||||||
|
return [replies, opbq]
|
||||||
|
|
||||||
|
quickReply = (e) ->
|
||||||
|
unless qr = $('#qr')
|
||||||
|
#make quick reply dialog
|
||||||
|
qr = AEOS.makeDialog 'qr', 'topleft'
|
||||||
|
titlebar = n 'div',
|
||||||
|
innerHTML: 'Quick Reply '
|
||||||
|
className: 'move'
|
||||||
|
listener: ['mousedown', AEOS.move]
|
||||||
|
addTo qr, titlebar
|
||||||
|
autohideB = n 'input',
|
||||||
|
type: 'checkbox'
|
||||||
|
className: 'pointer'
|
||||||
|
title: 'autohide'
|
||||||
|
listener: ['click', autohide]
|
||||||
|
closeB = n 'a',
|
||||||
|
textContent: 'X'
|
||||||
|
className: 'pointer'
|
||||||
|
title: 'close'
|
||||||
|
listener: ['click', close]
|
||||||
|
addTo titlebar, autohideB, tn(' '), closeB
|
||||||
|
form = $ 'form[name=post]'
|
||||||
|
clone = form.cloneNode(true)
|
||||||
|
#remove recaptcha scripts
|
||||||
|
for script in $$ 'script', clone
|
||||||
|
remove script
|
||||||
|
$('input[name=recaptcha_response_field]', clone).
|
||||||
|
addEventListener('keydown', recaptchaListener, true)
|
||||||
|
clone.addEventListener('submit', submit, true)
|
||||||
|
clone.target = 'iframe'
|
||||||
|
if not REPLY
|
||||||
|
#figure out which thread we're replying to
|
||||||
|
xpath = 'preceding::span[@class="postername"][1]/preceding::input[1]'
|
||||||
|
input = n 'input',
|
||||||
|
type: 'hidden'
|
||||||
|
name: 'resto'
|
||||||
|
value: x(xpath, this).name
|
||||||
|
addTo clone, input
|
||||||
|
else if getConfig 'Persistent QR'
|
||||||
|
submit = $ 'input[type=submit]', clone
|
||||||
|
auto = n 'label',
|
||||||
|
textContent: 'Auto'
|
||||||
|
autoBox = n 'input',
|
||||||
|
type: 'checkbox'
|
||||||
|
addTo auto, autoBox
|
||||||
|
inBefore submit, auto
|
||||||
|
addTo qr, clone
|
||||||
|
addTo d.body, qr
|
||||||
|
if e
|
||||||
|
e.preventDefault()
|
||||||
|
$('input[title=autohide]:checked', qr)?.click()
|
||||||
|
selection = window.getSelection()
|
||||||
|
id = x('preceding::span[@id][1]', selection.anchorNode)?.id
|
||||||
|
text = selection.toString()
|
||||||
|
textarea = $('textarea', qr)
|
||||||
|
textarea.focus()
|
||||||
|
#we can't just use @textContent b/c of the xxxs. goddamit moot.
|
||||||
|
textarea.value += '>>' + @parentNode.id.match(/\d+$/)[0] + '\n'
|
||||||
|
if text and id is this.parentNode.id
|
||||||
|
textarea.value += ">#{text}\n"
|
||||||
|
|
||||||
|
recaptchaListener = (e) ->
|
||||||
|
if e.keyCode is 8 and this.value is ''
|
||||||
|
recaptchaReload()
|
||||||
|
|
||||||
|
recaptchaReload = ->
|
||||||
|
window.location = 'javascript:Recaptcha.reload()'
|
||||||
|
|
||||||
|
redirect = ->
|
||||||
|
switch BOARD
|
||||||
|
when 'a', 'g', 'lit', 'sci', 'tv'
|
||||||
|
url = "http://green-oval.net/cgi-board.pl/#{BOARD}/thread/#{THREAD_ID}#p"
|
||||||
|
when 'cgl', 'jp', 'm', 'tg'
|
||||||
|
url = "http://archive.easymodo.net/cgi-board.pl/#{BOARD}/thread/#{THREAD_ID}#p"
|
||||||
|
else
|
||||||
|
url = "http://boards.4chan.org/#{BOARD}"
|
||||||
|
location.href = url
|
||||||
|
|
||||||
|
replyNav = ->
|
||||||
|
if REPLY
|
||||||
|
window.location = if @textContent is '▲' then '#navtop' else '#navbot'
|
||||||
|
else
|
||||||
|
direction = if @textContent is '▲' then 'preceding' else 'following'
|
||||||
|
op = x("#{direction}::span[starts-with(@id, 'nothread')][1]", this).id
|
||||||
|
window.location = "##{op}"
|
||||||
|
|
||||||
|
report = ->
|
||||||
|
input = x('preceding-sibling::input[1]', this)
|
||||||
|
input.click()
|
||||||
|
$('input[value="Report"]').click()
|
||||||
|
input.click()
|
||||||
|
|
||||||
|
showReply = ->
|
||||||
|
div = this.parentNode
|
||||||
|
table = div.nextSibling
|
||||||
|
show(table)
|
||||||
|
remove(div)
|
||||||
|
id = $('td.reply, td.replyhl', table).id
|
||||||
|
slice(hiddenReplies, id)
|
||||||
|
GM_setValue("hiddenReplies/#{BOARD}/", JSON.stringify(hiddenReplies))
|
||||||
|
|
||||||
|
showThread = ->
|
||||||
|
div = @nextSibling
|
||||||
|
show div
|
||||||
|
hide this
|
||||||
|
id = div.id
|
||||||
|
slice hiddenThreads, id
|
||||||
|
GM_setValue("hiddenThreads/#{BOARD}/", JSON.stringify(hiddenThreads))
|
||||||
|
|
||||||
|
submit = (e) ->
|
||||||
|
if span = @nextSibling
|
||||||
|
remove(span)
|
||||||
|
recaptcha = $('input[name=recaptcha_response_field]', this)
|
||||||
|
if recaptcha.value
|
||||||
|
$('#qr input[title=autohide]:not(:checked)')?.click()
|
||||||
|
else
|
||||||
|
e.preventDefault()
|
||||||
|
span = n 'span',
|
||||||
|
className: 'error'
|
||||||
|
textContent: 'You forgot to type in the verification.'
|
||||||
|
addTo @parentNode, span
|
||||||
|
alert 'You forgot to type in the verification.'
|
||||||
|
recaptcha.focus()
|
||||||
|
|
||||||
|
stopPropagation = (e) ->
|
||||||
|
e.stopPropagation()
|
||||||
|
|
||||||
|
threadF = (current) ->
|
||||||
|
div = n 'div',
|
||||||
|
className: 'thread'
|
||||||
|
a = n 'a',
|
||||||
|
textContent: '[ - ]'
|
||||||
|
className: 'pointer'
|
||||||
|
listener: ['click', hideThread]
|
||||||
|
addTo div, a
|
||||||
|
inBefore current, div
|
||||||
|
while (!current.clear)#<br clear>
|
||||||
|
addTo div, current
|
||||||
|
current = div.nextSibling
|
||||||
|
addTo div, current
|
||||||
|
current = div.nextSibling
|
||||||
|
id = $('input[value="delete"]', div).name
|
||||||
|
div.id = id
|
||||||
|
#check if we should hide the thread
|
||||||
|
for hidden in hiddenThreads
|
||||||
|
if id == hidden.id
|
||||||
|
hideThread(div)
|
||||||
|
current = current.nextSibling.nextSibling
|
||||||
|
if current.nodeName isnt 'CENTER'
|
||||||
|
threadF(current)
|
||||||
|
|
||||||
|
watch = ->
|
||||||
|
id = this.nextSibling.name
|
||||||
|
if this.src[0] is 'd'#data:png
|
||||||
|
this.src = favNormal
|
||||||
|
text = "/#{BOARD}/ - " +
|
||||||
|
x('following-sibling::blockquote', this).textContent.slice(0,25)
|
||||||
|
watched[BOARD] or= []
|
||||||
|
watched[BOARD].push({
|
||||||
|
id: id,
|
||||||
|
text: text
|
||||||
|
})
|
||||||
|
else
|
||||||
|
this.src = favEmpty
|
||||||
|
watched[BOARD] = slice(watched[BOARD], id)
|
||||||
|
GM_setValue('watched', JSON.stringify(watched))
|
||||||
|
watcherUpdate()
|
||||||
|
|
||||||
|
watcherUpdate = ->
|
||||||
|
div = n 'div'
|
||||||
|
for board of watched
|
||||||
|
for thread in watched[board]
|
||||||
|
a = n 'a',
|
||||||
|
textContent: 'X'
|
||||||
|
className: 'pointer'
|
||||||
|
listener: ['click', watchX]
|
||||||
|
link = n 'a',
|
||||||
|
textContent: thread.text
|
||||||
|
href: "/#{board}/res/#{thread.id}"
|
||||||
|
addTo div, a, tn(' '), link, n('br')
|
||||||
|
old = $('#watcher div:last-child')
|
||||||
|
replace(old, div)
|
||||||
|
|
||||||
|
watchX = ->
|
||||||
|
[board, _, id] = @nextElementSibling.
|
||||||
|
getAttribute('href').substring(1).split('/')
|
||||||
|
watched[board] = slice(watched[board], id)
|
||||||
|
GM_setValue('watched', JSON.stringify(watched))
|
||||||
|
watcherUpdate()
|
||||||
|
if input = $("input[name=\"#{id}\"]")
|
||||||
|
favicon = input.previousSibling
|
||||||
|
favicon.src = favEmpty
|
||||||
|
|
||||||
#let's get this party started.
|
#let's get this party started.
|
||||||
watched = JSON.parse(GM_getValue('watched', '{}'))
|
watched = JSON.parse(GM_getValue('watched', '{}'))
|
||||||
if location.hostname.split('.')[0] is 'sys'
|
if location.hostname.split('.')[0] is 'sys'
|
||||||
@ -311,475 +725,8 @@ GM_addStyle('
|
|||||||
')
|
')
|
||||||
|
|
||||||
|
|
||||||
clearHidden = ->
|
|
||||||
#'hidden' might be misleading; it's the number of IDs we're *looking* for,
|
|
||||||
# not the number of posts actually hidden on the page.
|
|
||||||
GM_deleteValue("hiddenReplies/#{BOARD}/")
|
|
||||||
GM_deleteValue("hiddenThreads/#{BOARD}/")
|
|
||||||
@value = "hidden: 0"
|
|
||||||
hiddenReplies = []
|
|
||||||
hiddenThreads = []
|
|
||||||
|
|
||||||
|
|
||||||
editSauce = ->
|
|
||||||
ta = $ '#options textarea'
|
|
||||||
if ta.style.display then show ta else hide ta
|
|
||||||
|
|
||||||
options = ->
|
|
||||||
if div = $ '#options'
|
|
||||||
remove div
|
|
||||||
else
|
|
||||||
div = AEOS.makeDialog 'options', 'center'
|
|
||||||
hiddenNum = hiddenReplies.length + hiddenThreads.length
|
|
||||||
html = '<div class="move">Options <a class=pointer>X</a></div><div>'
|
|
||||||
for option, value of config
|
|
||||||
description = value[1]
|
|
||||||
checked = if getConfig option then "checked" else ""
|
|
||||||
html += "<label title=\"#{description}\">#{option}<input #{checked} name=\"#{option}\" type=\"checkbox\"></label><br>"
|
|
||||||
html += "<div><a class=sauce>Edit Sauce</a></div>"
|
|
||||||
html += "<div><textarea cols=50 rows=4 style=\"display: none;\"></textarea></div>"
|
|
||||||
html += "<input type=\"button\" value=\"hidden: #{hiddenNum}\"><br>"
|
|
||||||
div.innerHTML = html
|
|
||||||
$('div.move', div).addEventListener 'mousedown', AEOS.move, true
|
|
||||||
$('a.pointer', div).addEventListener 'click', optionsClose, true
|
|
||||||
$('a.sauce', div).addEventListener 'click', editSauce, true
|
|
||||||
$('textarea', div).value = GM_getValue 'saucePrefix', defaultSaucePrefix
|
|
||||||
$('input[type="button"]', div).addEventListener 'click', clearHidden, true
|
|
||||||
addTo d.body, div
|
|
||||||
|
|
||||||
|
|
||||||
showThread = ->
|
|
||||||
div = @nextSibling
|
|
||||||
show div
|
|
||||||
hide this
|
|
||||||
id = div.id
|
|
||||||
slice hiddenThreads, id
|
|
||||||
GM_setValue("hiddenThreads/#{BOARD}/", JSON.stringify(hiddenThreads))
|
|
||||||
|
|
||||||
|
|
||||||
hideThread = (div) ->
|
|
||||||
if p = @parentNode
|
|
||||||
div = p
|
|
||||||
hiddenThreads.push {
|
|
||||||
id: div.id
|
|
||||||
timestamp: getTime()
|
|
||||||
}
|
|
||||||
GM_setValue("hiddenThreads/#{BOARD}/", JSON.stringify(hiddenThreads))
|
|
||||||
hide div
|
|
||||||
if getConfig 'Show Stubs'
|
|
||||||
if span = $ '.omittedposts', div
|
|
||||||
num = Number(span.textContent.match(/\d+/)[0])
|
|
||||||
else
|
|
||||||
num = 0
|
|
||||||
num += $$('table', div).length
|
|
||||||
text = if num is 1 then "1 reply" else "#{num} replies"
|
|
||||||
name = $('span.postername', div).textContent
|
|
||||||
trip = $('span.postername + span.postertrip', div)?.textContent || ''
|
|
||||||
a = n 'a',
|
|
||||||
textContent: "[ + ] #{name}#{trip} (#{text})"
|
|
||||||
className: 'pointer'
|
|
||||||
listener: ['click', showThread]
|
|
||||||
inBefore div, a
|
|
||||||
|
|
||||||
|
|
||||||
threadF = (current) ->
|
|
||||||
div = n 'div',
|
|
||||||
className: 'thread'
|
|
||||||
a = n 'a',
|
|
||||||
textContent: '[ - ]'
|
|
||||||
className: 'pointer'
|
|
||||||
listener: ['click', hideThread]
|
|
||||||
addTo div, a
|
|
||||||
|
|
||||||
inBefore current, div
|
|
||||||
while (!current.clear)#<br clear>
|
|
||||||
addTo div, current
|
|
||||||
current = div.nextSibling
|
|
||||||
addTo div, current
|
|
||||||
current = div.nextSibling
|
|
||||||
|
|
||||||
id = $('input[value="delete"]', div).name
|
|
||||||
div.id = id
|
|
||||||
#check if we should hide the thread
|
|
||||||
for hidden in hiddenThreads
|
|
||||||
if id == hidden.id
|
|
||||||
hideThread(div)
|
|
||||||
|
|
||||||
current = current.nextSibling.nextSibling
|
|
||||||
if current.nodeName isnt 'CENTER'
|
|
||||||
threadF(current)
|
|
||||||
|
|
||||||
|
|
||||||
showReply = ->
|
|
||||||
div = this.parentNode
|
|
||||||
table = div.nextSibling
|
|
||||||
show(table)
|
|
||||||
remove(div)
|
|
||||||
id = $('td.reply, td.replyhl', table).id
|
|
||||||
slice(hiddenReplies, id)
|
|
||||||
GM_setValue("hiddenReplies/#{BOARD}/", JSON.stringify(hiddenReplies))
|
|
||||||
|
|
||||||
|
|
||||||
hideReply = (reply) ->
|
|
||||||
if p = this.parentNode
|
|
||||||
reply = p.nextSibling
|
|
||||||
hiddenReplies.push({
|
|
||||||
id: reply.id
|
|
||||||
timestamp: getTime()
|
|
||||||
})
|
|
||||||
GM_setValue("hiddenReplies/#{BOARD}/", JSON.stringify(hiddenReplies))
|
|
||||||
|
|
||||||
name = $('span.commentpostername', reply).textContent
|
|
||||||
trip = $('span.postertrip', reply)?.textContent || ''
|
|
||||||
table = x('ancestor::table', reply)
|
|
||||||
hide(table)
|
|
||||||
if getConfig 'Show Stubs'
|
|
||||||
a = n 'a',
|
|
||||||
textContent: "[ + ] #{name} #{trip}"
|
|
||||||
className: 'pointer'
|
|
||||||
listener: ['click', showReply]
|
|
||||||
div = n 'div'
|
|
||||||
addTo div, a
|
|
||||||
inBefore table, div
|
|
||||||
|
|
||||||
|
|
||||||
optionsClose = ->
|
|
||||||
div = this.parentNode.parentNode
|
|
||||||
inputs = $$('input', div)
|
|
||||||
for input in inputs
|
|
||||||
GM_setValue(input.name, input.checked)
|
|
||||||
GM_setValue 'saucePrefix', $('textarea', div).value
|
|
||||||
remove div
|
|
||||||
|
|
||||||
|
|
||||||
close = ->
|
|
||||||
div = this.parentNode.parentNode
|
|
||||||
remove div
|
|
||||||
|
|
||||||
cooldown = ->
|
|
||||||
submit = $ '#qr input[type=submit]'
|
|
||||||
seconds = parseInt submit.value
|
|
||||||
if seconds == 0
|
|
||||||
submit.disabled = false
|
|
||||||
submit.value = 'Submit'
|
|
||||||
auto = submit.previousSibling.lastChild
|
|
||||||
if auto.checked
|
|
||||||
$('#qr form').submit()
|
|
||||||
#submit.click() doesn't work
|
|
||||||
else
|
|
||||||
submit.value = seconds - 1
|
|
||||||
window.setTimeout cooldown, 1000
|
|
||||||
|
|
||||||
iframeLoad = ->
|
|
||||||
if iframeLoop = !iframeLoop
|
|
||||||
return
|
|
||||||
$('iframe').src = 'about:blank'
|
|
||||||
|
|
||||||
qr = $('#qr')
|
|
||||||
if error = GM_getValue('error')
|
|
||||||
span = n 'span',
|
|
||||||
textContent: error
|
|
||||||
className: 'error'
|
|
||||||
addTo qr, span
|
|
||||||
$('input[title=autohide]:checked', qr)?.click()
|
|
||||||
else if REPLY and getConfig 'Persistent QR'
|
|
||||||
$('textarea', qr).value = ''
|
|
||||||
$('input[name=recaptcha_response_field]', qr).value = ''
|
|
||||||
submit = $('input[type=submit]', qr)
|
|
||||||
submit.value = 30
|
|
||||||
submit.disabled = true
|
|
||||||
window.setTimeout cooldown, 1000
|
|
||||||
auto = submit.previousSibling.lastChild
|
|
||||||
if auto.checked
|
|
||||||
#unhide the qr so you know it's ready for the next item
|
|
||||||
$('input[title=autohide]:checked', qr)?.click()
|
|
||||||
else
|
|
||||||
remove qr
|
|
||||||
|
|
||||||
recaptchaReload()
|
|
||||||
|
|
||||||
|
|
||||||
submit = (e) ->
|
|
||||||
if span = @nextSibling
|
|
||||||
remove(span)
|
|
||||||
recaptcha = $('input[name=recaptcha_response_field]', this)
|
|
||||||
if recaptcha.value
|
|
||||||
$('#qr input[title=autohide]:not(:checked)')?.click()
|
|
||||||
else
|
|
||||||
e.preventDefault()
|
|
||||||
span = n 'span',
|
|
||||||
className: 'error'
|
|
||||||
textContent: 'You forgot to type in the verification.'
|
|
||||||
addTo @parentNode, span
|
|
||||||
alert 'You forgot to type in the verification.'
|
|
||||||
recaptcha.focus()
|
|
||||||
|
|
||||||
|
|
||||||
autohide = ->
|
|
||||||
qr = $ '#qr'
|
|
||||||
klass = qr.className
|
|
||||||
if klass.indexOf('auto') is -1
|
|
||||||
klass += ' auto'
|
|
||||||
else
|
|
||||||
klass = klass.replace(' auto', '')
|
|
||||||
qr.className = klass
|
|
||||||
|
|
||||||
|
|
||||||
quickReply = (e) ->
|
|
||||||
unless qr = $('#qr')
|
|
||||||
#make quick reply dialog
|
|
||||||
qr = AEOS.makeDialog 'qr', 'topleft'
|
|
||||||
|
|
||||||
titlebar = n 'div',
|
|
||||||
innerHTML: 'Quick Reply '
|
|
||||||
className: 'move'
|
|
||||||
listener: ['mousedown', AEOS.move]
|
|
||||||
addTo qr, titlebar
|
|
||||||
|
|
||||||
autohideB = n 'input',
|
|
||||||
type: 'checkbox'
|
|
||||||
className: 'pointer'
|
|
||||||
title: 'autohide'
|
|
||||||
listener: ['click', autohide]
|
|
||||||
closeB = n 'a',
|
|
||||||
textContent: 'X'
|
|
||||||
className: 'pointer'
|
|
||||||
title: 'close'
|
|
||||||
listener: ['click', close]
|
|
||||||
addTo titlebar, autohideB, tn(' '), closeB
|
|
||||||
|
|
||||||
form = $ 'form[name=post]'
|
|
||||||
clone = form.cloneNode(true)
|
|
||||||
#remove recaptcha scripts
|
|
||||||
for script in $$ 'script', clone
|
|
||||||
remove script
|
|
||||||
$('input[name=recaptcha_response_field]', clone).
|
|
||||||
addEventListener('keydown', recaptchaListener, true)
|
|
||||||
clone.addEventListener('submit', submit, true)
|
|
||||||
clone.target = 'iframe'
|
|
||||||
if not REPLY
|
|
||||||
#figure out which thread we're replying to
|
|
||||||
xpath = 'preceding::span[@class="postername"][1]/preceding::input[1]'
|
|
||||||
input = n 'input',
|
|
||||||
type: 'hidden'
|
|
||||||
name: 'resto'
|
|
||||||
value: x(xpath, this).name
|
|
||||||
addTo clone, input
|
|
||||||
else if getConfig 'Persistent QR'
|
|
||||||
submit = $ 'input[type=submit]', clone
|
|
||||||
auto = n 'label',
|
|
||||||
textContent: 'Auto'
|
|
||||||
autoBox = n 'input',
|
|
||||||
type: 'checkbox'
|
|
||||||
addTo auto, autoBox
|
|
||||||
inBefore submit, auto
|
|
||||||
addTo qr, clone
|
|
||||||
addTo d.body, qr
|
|
||||||
|
|
||||||
if e
|
|
||||||
e.preventDefault()
|
|
||||||
|
|
||||||
$('input[title=autohide]:checked', qr)?.click()
|
|
||||||
|
|
||||||
selection = window.getSelection()
|
|
||||||
id = x('preceding::span[@id][1]', selection.anchorNode)?.id
|
|
||||||
text = selection.toString()
|
|
||||||
|
|
||||||
textarea = $('textarea', qr)
|
|
||||||
textarea.focus()
|
|
||||||
#we can't just use @textContent b/c of the xxxs. goddamit moot.
|
|
||||||
textarea.value += '>>' + @parentNode.id.match(/\d+$/)[0] + '\n'
|
|
||||||
if text and id is this.parentNode.id
|
|
||||||
textarea.value += ">#{text}\n"
|
|
||||||
|
|
||||||
watch = ->
|
|
||||||
id = this.nextSibling.name
|
|
||||||
if this.src[0] is 'd'#data:png
|
|
||||||
this.src = favNormal
|
|
||||||
text = "/#{BOARD}/ - " +
|
|
||||||
x('following-sibling::blockquote', this).textContent.slice(0,25)
|
|
||||||
watched[BOARD] or= []
|
|
||||||
watched[BOARD].push({
|
|
||||||
id: id,
|
|
||||||
text: text
|
|
||||||
})
|
|
||||||
else
|
|
||||||
this.src = favEmpty
|
|
||||||
watched[BOARD] = slice(watched[BOARD], id)
|
|
||||||
|
|
||||||
GM_setValue('watched', JSON.stringify(watched))
|
|
||||||
watcherUpdate()
|
|
||||||
|
|
||||||
|
|
||||||
watchX = ->
|
|
||||||
[board, _, id] = @nextElementSibling.
|
|
||||||
getAttribute('href').substring(1).split('/')
|
|
||||||
watched[board] = slice(watched[board], id)
|
|
||||||
GM_setValue('watched', JSON.stringify(watched))
|
|
||||||
watcherUpdate()
|
|
||||||
if input = $("input[name=\"#{id}\"]")
|
|
||||||
favicon = input.previousSibling
|
|
||||||
favicon.src = favEmpty
|
|
||||||
|
|
||||||
|
|
||||||
watcherUpdate = ->
|
|
||||||
div = n 'div'
|
|
||||||
for board of watched
|
|
||||||
for thread in watched[board]
|
|
||||||
a = n 'a',
|
|
||||||
textContent: 'X'
|
|
||||||
className: 'pointer'
|
|
||||||
listener: ['click', watchX]
|
|
||||||
link = n 'a',
|
|
||||||
textContent: thread.text
|
|
||||||
href: "/#{board}/res/#{thread.id}"
|
|
||||||
addTo div, a, tn(' '), link, n('br')
|
|
||||||
old = $('#watcher div:last-child')
|
|
||||||
replace(old, div)
|
|
||||||
|
|
||||||
|
|
||||||
parseResponse = (responseText) ->
|
|
||||||
body = n 'body',
|
|
||||||
innerHTML: responseText
|
|
||||||
replies = $$('td.reply', body)
|
|
||||||
opbq = $('blockquote', body)
|
|
||||||
return [replies, opbq]
|
|
||||||
|
|
||||||
|
|
||||||
onloadThread = (responseText, span) ->
|
|
||||||
[replies, opbq] = parseResponse(responseText)
|
|
||||||
span.textContent = span.textContent.replace('X Loading...', '- ')
|
|
||||||
|
|
||||||
#make sure all comments are fully expanded
|
|
||||||
span.previousSibling.innerHTML = opbq.innerHTML
|
|
||||||
while (next = span.nextSibling) and not next.clear#<br clear>
|
|
||||||
remove(next)
|
|
||||||
if next
|
|
||||||
for reply in replies
|
|
||||||
inBefore next, x('ancestor::table', reply)
|
|
||||||
else#threading
|
|
||||||
div = span.parentNode
|
|
||||||
for reply in replies
|
|
||||||
addTo div, x('ancestor::table', reply)
|
|
||||||
|
|
||||||
|
|
||||||
expandThread = ->
|
|
||||||
id = x('preceding-sibling::input[1]', this).name
|
|
||||||
span = this
|
|
||||||
|
|
||||||
#close expanded thread
|
|
||||||
if span.textContent[0] is '-'
|
|
||||||
#goddamit moot
|
|
||||||
num = if board is 'b' then 3 else 5
|
|
||||||
table = x("following::br[@clear][1]/preceding::table[#{num}]", span)
|
|
||||||
while (prev = table.previousSibling) and (prev.nodeName is 'TABLE')
|
|
||||||
remove(prev)
|
|
||||||
span.textContent = span.textContent.replace('-', '+')
|
|
||||||
return
|
|
||||||
|
|
||||||
span.textContent = span.textContent.replace('+', 'X Loading...')
|
|
||||||
#load cache
|
|
||||||
for xhr in xhrs
|
|
||||||
if xhr.id == id
|
|
||||||
#why can't we just xhr.r.onload()?
|
|
||||||
onloadThread(xhr.r.responseText, span)
|
|
||||||
return
|
|
||||||
|
|
||||||
#create new request
|
|
||||||
r = new XMLHttpRequest()
|
|
||||||
r.onload = ->
|
|
||||||
onloadThread(this.responseText, span)
|
|
||||||
r.open('GET', "res/#{id}", true)
|
|
||||||
r.send()
|
|
||||||
xhrs.push({
|
|
||||||
r: r,
|
|
||||||
id: id
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
onloadComment = (responseText, a, href) ->
|
|
||||||
[_, op, id] = href.match(/(\d+)#(\d+)/)
|
|
||||||
[replies, opbq] = parseResponse(responseText)
|
|
||||||
if id is op
|
|
||||||
html = opbq.innerHTML
|
|
||||||
else
|
|
||||||
#css selectors don't like ids starting with numbers,
|
|
||||||
# getElementById only works for root document.
|
|
||||||
for reply in replies
|
|
||||||
if reply.id == id
|
|
||||||
html = $('blockquote', reply).innerHTML
|
|
||||||
bq = x('ancestor::blockquote', a)
|
|
||||||
bq.innerHTML = html
|
|
||||||
|
|
||||||
|
|
||||||
expandComment = (e) ->
|
|
||||||
e.preventDefault()
|
|
||||||
a = this
|
|
||||||
href = a.getAttribute('href')
|
|
||||||
r = new XMLHttpRequest()
|
|
||||||
r.onload = ->
|
|
||||||
onloadComment(this.responseText, a, href)
|
|
||||||
r.open('GET', href, true)
|
|
||||||
r.send()
|
|
||||||
xhrs.push({
|
|
||||||
r: r,
|
|
||||||
id: href.match(/\d+/)[0]
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
report = ->
|
|
||||||
input = x('preceding-sibling::input[1]', this)
|
|
||||||
input.click()
|
|
||||||
$('input[value="Report"]').click()
|
|
||||||
input.click()
|
|
||||||
|
|
||||||
|
|
||||||
nodeInserted = (e) ->
|
|
||||||
target = e.target
|
|
||||||
if target.nodeName is 'TABLE'
|
|
||||||
for callback in callbacks
|
|
||||||
callback(target)
|
|
||||||
else if target.id is 'recaptcha_challenge_field' and qr = $ '#qr'
|
|
||||||
$('#recaptcha_image img', qr).src = "http://www.google.com/recaptcha/api/image?c=" + target.value
|
|
||||||
$('#recaptcha_challenge_field', qr).value = target.value
|
|
||||||
|
|
||||||
|
|
||||||
autoWatch = ->
|
|
||||||
#TODO look for subject
|
|
||||||
autoText = $('textarea', this).value.slice(0, 25)
|
|
||||||
GM_setValue('autoText', "/#{BOARD}/ - #{autoText}")
|
|
||||||
|
|
||||||
|
|
||||||
stopPropagation = (e) ->
|
|
||||||
e.stopPropagation()
|
|
||||||
|
|
||||||
|
|
||||||
replyNav = ->
|
|
||||||
if REPLY
|
|
||||||
window.location = if @textContent is '▲' then '#navtop' else '#navbot'
|
|
||||||
else
|
|
||||||
direction = if @textContent is '▲' then 'preceding' else 'following'
|
|
||||||
op = x("#{direction}::span[starts-with(@id, 'nothread')][1]", this).id
|
|
||||||
window.location = "##{op}"
|
|
||||||
|
|
||||||
recaptchaReload = ->
|
|
||||||
window.location = 'javascript:Recaptcha.reload()'
|
|
||||||
|
|
||||||
recaptchaListener = (e) ->
|
|
||||||
if e.keyCode is 8 and this.value is ''
|
|
||||||
recaptchaReload()
|
|
||||||
|
|
||||||
redirect = ->
|
|
||||||
switch BOARD
|
|
||||||
when 'a', 'g', 'lit', 'sci', 'tv'
|
|
||||||
url = "http://green-oval.net/cgi-board.pl/#{BOARD}/thread/#{THREAD_ID}#p"
|
|
||||||
when 'cgl', 'jp', 'm', 'tg'
|
|
||||||
url = "http://archive.easymodo.net/cgi-board.pl/#{BOARD}/thread/#{THREAD_ID}#p"
|
|
||||||
else
|
|
||||||
url = "http://boards.4chan.org/#{BOARD}"
|
|
||||||
location.href = url
|
|
||||||
|
|
||||||
#main part 2...
|
#main part 2...
|
||||||
|
AEOS.init()
|
||||||
if navtopr = $ '#navtopr a'
|
if navtopr = $ '#navtopr a'
|
||||||
text = navtopr.nextSibling #css doesn't see text nodes
|
text = navtopr.nextSibling #css doesn't see text nodes
|
||||||
a = n 'a',
|
a = n 'a',
|
||||||
|
|||||||
1069
4chan_x.js
1069
4chan_x.js
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user