Help out decaffeinate. #829
This commit is contained in:
parent
6a16010cfb
commit
ad9c3df4dc
@ -139,7 +139,7 @@ Redirect =
|
||||
if type is 'capcode'
|
||||
value = {'Developer': 'dev'}[value] or value.toLowerCase()
|
||||
else if type is 'image'
|
||||
value = value.replace /[+/=]/g, (c) -> {'+': '-', '/': '_', '=': ''}[c]
|
||||
value = value.replace /[+/=]/g, (c) -> ({'+': '-', '/': '_', '=': ''})[c]
|
||||
value = encodeURIComponent value
|
||||
path = if archive.software is 'foolfuuka'
|
||||
"#{boardID}/search/#{type}/#{value}/"
|
||||
|
||||
@ -11,7 +11,7 @@ Filter =
|
||||
for line in Conf[key].split '\n'
|
||||
continue if line[0] is '#'
|
||||
|
||||
unless regexp = line.match /\/(.+)\/(\w*)/
|
||||
if not (regexp = line.match /\/(.+)\/(\w*)/)
|
||||
continue
|
||||
|
||||
# Don't mix up filter flags with the regular expression.
|
||||
|
||||
@ -84,7 +84,7 @@ PostHiding =
|
||||
open: (post) ->
|
||||
if !post.isReply or post.isClone or !post.isHidden
|
||||
return false
|
||||
unless data = PostHiding.db.get {boardID: post.board.ID, threadID: post.thread.ID, postID: post.ID}
|
||||
if not (data = PostHiding.db.get {boardID: post.board.ID, threadID: post.thread.ID, postID: post.ID})
|
||||
return false
|
||||
PostHiding.menu.post = post
|
||||
thisPost.firstChild.checked = post.isHidden
|
||||
@ -104,7 +104,7 @@ PostHiding =
|
||||
open: (post) ->
|
||||
if !post.isReply or post.isClone or !post.isHidden
|
||||
return false
|
||||
unless data = PostHiding.db.get {boardID: post.board.ID, threadID: post.thread.ID, postID: post.ID}
|
||||
if not (data = PostHiding.db.get {boardID: post.board.ID, threadID: post.thread.ID, postID: post.ID})
|
||||
return false
|
||||
PostHiding.menu.post = post
|
||||
|
||||
|
||||
@ -14,14 +14,15 @@ Recursive =
|
||||
return
|
||||
|
||||
add: (recursive, post, args...) ->
|
||||
obj = Recursive.recursives[post.fullID] or=
|
||||
obj = Recursive.recursives[post.fullID] or= {
|
||||
recursives: []
|
||||
args: []
|
||||
}
|
||||
obj.recursives.push recursive
|
||||
obj.args.push args
|
||||
|
||||
rm: (recursive, post) ->
|
||||
return unless obj = Recursive.recursives[post.fullID]
|
||||
return if not (obj = Recursive.recursives[post.fullID])
|
||||
for rec, i in obj.recursives when rec is recursive
|
||||
obj.recursives.splice i, 1
|
||||
obj.args.splice i, 1
|
||||
|
||||
@ -22,10 +22,11 @@ ThreadHiding =
|
||||
@hiddenThreads = JSON.parse(localStorage.getItem "4chan-hide-t-#{g.BOARD}") or {}
|
||||
Main.ready ->
|
||||
# 4chan's catalog sets the style to "display: none;" when hiding or unhiding a thread.
|
||||
new MutationObserver(ThreadHiding.catalogSave).observe $.id('threads'),
|
||||
new MutationObserver(ThreadHiding.catalogSave).observe $.id('threads'), {
|
||||
attributes: true
|
||||
subtree: true
|
||||
attributeFilter: ['style']
|
||||
}
|
||||
|
||||
catalogSave: ->
|
||||
hiddenThreads2 = JSON.parse(localStorage.getItem "4chan-hide-t-#{g.BOARD}") or {}
|
||||
@ -78,7 +79,7 @@ ThreadHiding =
|
||||
return false
|
||||
ThreadHiding.menu.thread = thread
|
||||
true
|
||||
subEntries: [el: apply; el: makeStub]
|
||||
subEntries: [{el: apply}, {el: makeStub}]
|
||||
|
||||
div = $.el 'a',
|
||||
className: 'show-thread-link'
|
||||
|
||||
@ -105,7 +105,7 @@ Build.Test =
|
||||
testAll: ->
|
||||
g.posts.forEach (post) ->
|
||||
unless post.isClone or post.isFetchedQuote
|
||||
unless (abbr = $ '.abbr', post.nodes.comment) and /Comment too long\./.test(abbr.textContent)
|
||||
if not ((abbr = $ '.abbr', post.nodes.comment) and /Comment too long\./.test(abbr.textContent))
|
||||
Build.Test.testOne post
|
||||
return
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ Build =
|
||||
unescape: (text) ->
|
||||
return text unless text?
|
||||
text.replace(/<[^>]*>/g, '').replace /&(amp|#039|quot|lt|gt|#44);/g, (c) ->
|
||||
{'&': '&', ''': "'", '"': '"', '<': '<', '>': '>', ',': ','}[c]
|
||||
(({'&': '&', ''': "'", '"': '"', '<': '<', '>': '>', ',': ','})[c])
|
||||
|
||||
shortFilename: (filename) ->
|
||||
ext = filename.match(/\.?[^\.]*$/)[0]
|
||||
@ -149,7 +149,7 @@ Build =
|
||||
for quote in $$ '.quotelink', container
|
||||
href = quote.getAttribute 'href'
|
||||
if (href[0] is '#') and !(Build.sameThread boardID, threadID)
|
||||
quote.href = "/#{boardID}/thread/#{threadID}" + href
|
||||
quote.href = ("/#{boardID}/thread/#{threadID}") + href
|
||||
else if (match = href.match /^\/([^\/]+)\/thread\/(\d+)/) and (Build.sameThread match[1], match[2])
|
||||
quote.href = href.match(/(#[^#]*)?$/)[0] or '#'
|
||||
else if /^\d+(#|$)/.test(href) and not (g.VIEW is 'thread' and g.BOARD.ID is boardID) # used on /f/
|
||||
@ -199,7 +199,7 @@ Build =
|
||||
src = "#{staticPath}spoiler"
|
||||
if spoilerRange = Build.spoilerRange[thread.board]
|
||||
# Randomize the spoiler image.
|
||||
src += "-#{thread.board}" + Math.floor 1 + spoilerRange * Math.random()
|
||||
src += ("-#{thread.board}") + Math.floor 1 + spoilerRange * Math.random()
|
||||
src += '.png'
|
||||
imgClass = 'spoiler-file'
|
||||
else if data.filedeleted
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
Get =
|
||||
threadExcerpt: (thread) ->
|
||||
{OP} = thread
|
||||
excerpt = "/#{thread.board}/ - " + (
|
||||
excerpt = ("/#{thread.board}/ - ") + (
|
||||
OP.info.subject?.trim() or
|
||||
OP.info.commentDisplay.replace(/\n+/g, ' // ') or
|
||||
OP.file?.name or
|
||||
|
||||
@ -246,7 +246,7 @@ Header =
|
||||
a.textContent = if /-title/.test(t) or /-replace/.test(t) and boardID is g.BOARD.ID
|
||||
a.title or a.textContent
|
||||
else if /-full/.test t
|
||||
"/#{boardID}/" + (if a.title then " - #{a.title}" else '')
|
||||
("/#{boardID}/") + (if a.title then " - #{a.title}" else '')
|
||||
else
|
||||
text or boardID
|
||||
|
||||
|
||||
@ -20,10 +20,11 @@ Index =
|
||||
Conf['Index Mode'] = history.state?.mode
|
||||
@currentSort = history.state?.sort
|
||||
@currentSort or=
|
||||
if typeof Conf['Index Sort'] is 'object'
|
||||
if typeof Conf['Index Sort'] is 'object' then (
|
||||
Conf['Index Sort'][g.BOARD.ID] or 'bump'
|
||||
else
|
||||
) else (
|
||||
Conf['Index Sort']
|
||||
)
|
||||
@currentPage = @getCurrentPage()
|
||||
@processHash()
|
||||
|
||||
@ -594,7 +595,7 @@ Index =
|
||||
if Index.liveThreadData[0]
|
||||
Build.spoilerRange[g.BOARD.ID] = Index.liveThreadData[0].custom_spoiler
|
||||
g.BOARD.threads.forEach (thread) ->
|
||||
thread.collect() unless thread.ID in Index.liveThreadIDs
|
||||
(thread.collect() unless thread.ID in Index.liveThreadIDs)
|
||||
return
|
||||
|
||||
buildThreads: ->
|
||||
@ -616,7 +617,7 @@ Index =
|
||||
thread = new Thread threadData.no, g.BOARD
|
||||
threads.push thread
|
||||
|
||||
unless (OP = thread.OP) and not OP.isFetchedQuote
|
||||
if not ((OP = thread.OP) and not OP.isFetchedQuote)
|
||||
OP = new Post Build.postFromObject(threadData, g.BOARD.ID, true), thread, g.BOARD
|
||||
posts.push OP
|
||||
thread.setPage i // Index.threadsNumPerPage + 1
|
||||
@ -638,7 +639,7 @@ Index =
|
||||
buildReplies: (threads) ->
|
||||
posts = []
|
||||
for thread in threads
|
||||
continue unless (lastReplies = Index.liveThreadDict[thread.ID].last_replies)
|
||||
continue if not (lastReplies = Index.liveThreadDict[thread.ID].last_replies)
|
||||
nodes = []
|
||||
for data in lastReplies
|
||||
if (post = thread.posts[data.no]) and not post.isFetchedQuote
|
||||
@ -681,7 +682,7 @@ Index =
|
||||
buildCatalogReplies: (threads) ->
|
||||
for thread in threads
|
||||
{nodes} = thread.catalogView
|
||||
continue unless (lastReplies = Index.liveThreadDict[thread.ID].last_replies)
|
||||
continue if not (lastReplies = Index.liveThreadDict[thread.ID].last_replies)
|
||||
|
||||
if nodes.replies
|
||||
# RelativeDates will stop updating elements if they go out of document.
|
||||
@ -816,7 +817,7 @@ Index =
|
||||
Index.pageLoad false
|
||||
|
||||
querySearch: (query) ->
|
||||
return unless keywords = query.toLowerCase().match /\S+/g
|
||||
return if not (keywords = query.toLowerCase().match /\S+/g)
|
||||
Index.sortedThreads.filter (thread) ->
|
||||
Index.searchMatch thread, keywords
|
||||
|
||||
|
||||
@ -183,7 +183,7 @@ Settings =
|
||||
if $.hasStorage
|
||||
for boardID of hiddenThreads.boards
|
||||
localStorage.removeItem "4chan-hide-t-#{boardID}"
|
||||
$.delete ['hiddenThreads', 'hiddenPosts']
|
||||
($.delete ['hiddenThreads', 'hiddenPosts'])
|
||||
$.after $('input[name="Stubs"]', section).parentNode.parentNode, div
|
||||
|
||||
export: ->
|
||||
@ -191,7 +191,7 @@ Settings =
|
||||
$.get Conf, (Conf) ->
|
||||
# Don't export cached JSON data.
|
||||
delete Conf['boardConfig']
|
||||
Settings.downloadExport {version: g.VERSION, date: Date.now(), Conf}
|
||||
(Settings.downloadExport {version: g.VERSION, date: Date.now(), Conf})
|
||||
|
||||
downloadExport: (data) ->
|
||||
a = $.el 'a',
|
||||
@ -206,7 +206,7 @@ Settings =
|
||||
$('input[type=file]', @parentNode).click()
|
||||
|
||||
onImport: ->
|
||||
return unless file = @files[0]
|
||||
return if not (file = @files[0])
|
||||
@value = null
|
||||
output = $('.imp-exp-result')
|
||||
unless confirm 'Your current settings will be entirely overwritten, are you sure?'
|
||||
@ -437,7 +437,7 @@ Settings =
|
||||
className: 'field'
|
||||
spellcheck: false
|
||||
$.get name, Conf[name], (item) ->
|
||||
ta.value = item[name]
|
||||
(ta.value = item[name])
|
||||
$.on ta, 'change', $.cb.value
|
||||
$.add div, ta
|
||||
return
|
||||
@ -449,7 +449,7 @@ Settings =
|
||||
$('.warning', section).hidden = Conf['Sauce']
|
||||
ta = $ 'textarea', section
|
||||
$.get 'sauces', Conf['sauces'], (item) ->
|
||||
ta.value = item['sauces']
|
||||
(ta.value = item['sauces'])
|
||||
$.on ta, 'change', $.cb.value
|
||||
|
||||
advanced: (section) ->
|
||||
@ -530,10 +530,11 @@ Settings =
|
||||
for {uid, name, boards, files, software} in Conf['archives']
|
||||
continue unless software in ['fuuka', 'foolfuuka']
|
||||
for boardID in boards
|
||||
o = archBoards[boardID] or=
|
||||
o = archBoards[boardID] or= {
|
||||
thread: []
|
||||
post: []
|
||||
file: []
|
||||
}
|
||||
archive = [uid ? name, name]
|
||||
o.thread.push archive
|
||||
o.post.push archive if software is 'foolfuuka'
|
||||
@ -546,10 +547,11 @@ Settings =
|
||||
className: "board-#{boardID}"
|
||||
row.hidden = boardID isnt g.BOARD.ID
|
||||
|
||||
boardOptions.push $.el 'option',
|
||||
boardOptions.push $.el 'option', {
|
||||
textContent: "/#{boardID}/"
|
||||
value: "board-#{boardID}"
|
||||
selected: boardID is g.BOARD.ID
|
||||
}
|
||||
|
||||
o = archBoards[boardID]
|
||||
$.add row, Settings.addArchiveCell boardID, o, item for item in ['thread', 'post', 'file']
|
||||
@ -587,13 +589,14 @@ Settings =
|
||||
i = 0
|
||||
while i < length
|
||||
archive = data[type][i++]
|
||||
options.push $.el 'option',
|
||||
options.push $.el 'option', {
|
||||
value: JSON.stringify archive[0]
|
||||
textContent: archive[1]
|
||||
}
|
||||
|
||||
$.extend td, <%= html('<select></select>') %>
|
||||
select = td.firstElementChild
|
||||
unless select.disabled = length is 1
|
||||
if not (select.disabled = length is 1)
|
||||
# XXX GM can't into datasets
|
||||
select.setAttribute 'data-boardid', boardID
|
||||
select.setAttribute 'data-type', type
|
||||
@ -616,7 +619,7 @@ Settings =
|
||||
@nextElementSibling.textContent = Time.format @value, new Date()
|
||||
|
||||
backlink: ->
|
||||
@nextElementSibling.textContent = @value.replace /%(?:id|%)/g, (x) -> {'%id': '123456789', '%%': '%'}[x]
|
||||
@nextElementSibling.textContent = @value.replace /%(?:id|%)/g, (x) -> ({'%id': '123456789', '%%': '%'})[x]
|
||||
|
||||
fileInfo: ->
|
||||
data =
|
||||
|
||||
@ -5,7 +5,7 @@ dialog = (id, position, properties) ->
|
||||
$.extend el, properties
|
||||
el.style.cssText = position
|
||||
$.get "#{id}.position", position, (item) ->
|
||||
el.style.cssText = item["#{id}.position"]
|
||||
(el.style.cssText = item["#{id}.position"])
|
||||
|
||||
move = $ '.move', el
|
||||
$.on move, 'touchstart mousedown', dragstart
|
||||
@ -153,7 +153,7 @@ class Menu
|
||||
if next = @findNextEntry entry, +1
|
||||
@focus next
|
||||
when 39 # Right
|
||||
if (submenu = $ '.submenu', entry) and next = submenu.firstElementChild
|
||||
if (submenu = $ '.submenu', entry) and (next = submenu.firstElementChild)
|
||||
while nextPrev = @findNextEntry next, -1
|
||||
next = nextPrev
|
||||
@focus next
|
||||
@ -178,7 +178,7 @@ class Menu
|
||||
$.addClass entry, 'focused'
|
||||
|
||||
# Submenu positioning.
|
||||
return unless submenu = $ '.submenu', entry
|
||||
return if not (submenu = $ '.submenu', entry)
|
||||
sRect = submenu.getBoundingClientRect()
|
||||
eRect = entry.getBoundingClientRect()
|
||||
cHeight = doc.clientHeight
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
Gallery =
|
||||
init: ->
|
||||
return unless @enabled = Conf['Gallery'] and g.VIEW in ['index', 'thread'] and g.BOARD.ID isnt 'f'
|
||||
return if not (@enabled = Conf['Gallery'] and g.VIEW in ['index', 'thread'] and g.BOARD.ID isnt 'f')
|
||||
|
||||
@delay = Conf['Slide Delay']
|
||||
|
||||
@ -202,7 +202,7 @@ Gallery =
|
||||
ImageCommon.error @, g.posts[@dataset.post], null, (url) =>
|
||||
return unless url
|
||||
Gallery.images[@dataset.id].href = url
|
||||
@src = url if Gallery.nodes.current is @
|
||||
(@src = url if Gallery.nodes.current is @)
|
||||
|
||||
cacheError: ->
|
||||
delete Gallery.cache
|
||||
@ -236,7 +236,7 @@ Gallery =
|
||||
|
||||
cb:
|
||||
keybinds: (e) ->
|
||||
return unless key = Keybinds.keyCode e
|
||||
return if not (key = Keybinds.keyCode e)
|
||||
|
||||
cb = switch key
|
||||
when Conf['Close'], Conf['Open Gallery']
|
||||
|
||||
@ -27,7 +27,7 @@ ImageCommon =
|
||||
|
||||
decodeError: (file, post) ->
|
||||
return false unless file.error?.code is MediaError.MEDIA_ERR_DECODE
|
||||
unless message = $ '.warning', post.file.thumb.parentNode
|
||||
if not (message = $ '.warning', post.file.thumb.parentNode)
|
||||
message = $.el 'div', className: 'warning'
|
||||
$.after post.file.thumb, message
|
||||
message.textContent = 'Error: Corrupt or unplayable video'
|
||||
@ -35,9 +35,10 @@ ImageCommon =
|
||||
|
||||
error: (file, post, delay, cb) ->
|
||||
src = post.file.url.split '/'
|
||||
URL = Redirect.to 'file',
|
||||
URL = Redirect.to 'file', {
|
||||
boardID: post.board.ID
|
||||
filename: src[src.length - 1]
|
||||
}
|
||||
unless Conf['404 Redirect'] and URL and Redirect.securityCheck URL
|
||||
URL = null
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
ImageExpand =
|
||||
init: ->
|
||||
return unless @enabled = Conf['Image Expansion'] and g.VIEW in ['index', 'thread'] and g.BOARD.ID isnt 'f'
|
||||
return if not (@enabled = Conf['Image Expansion'] and g.VIEW in ['index', 'thread'] and g.BOARD.ID isnt 'f')
|
||||
|
||||
@EAI = $.el 'a',
|
||||
className: 'expand-all-shortcut fa fa-expand'
|
||||
@ -273,7 +273,7 @@ ImageExpand =
|
||||
ImageCommon.error @, post, 10 * $.SECOND, (URL) ->
|
||||
if post.file.isExpanding or post.file.isExpanded
|
||||
ImageExpand.contract post
|
||||
ImageExpand.expand post, URL if URL
|
||||
(ImageExpand.expand post, URL if URL)
|
||||
|
||||
menu:
|
||||
init: ->
|
||||
|
||||
@ -19,7 +19,7 @@ Sauce =
|
||||
cb: @node
|
||||
|
||||
createSauceLink: (link, post) ->
|
||||
return null unless link = link.trim()
|
||||
return null if not (link = link.trim())
|
||||
|
||||
parts = {}
|
||||
for part, i in link.split /;(?=(?:text|boards|types|sandbox):?)/
|
||||
@ -60,7 +60,7 @@ Sauce =
|
||||
nodes = []
|
||||
skipped = []
|
||||
for link in Sauce.links
|
||||
unless (node = Sauce.createSauceLink link, @)
|
||||
if not (node = Sauce.createSauceLink link, @)
|
||||
node = Sauce.link.cloneNode false
|
||||
skipped.push [link, node]
|
||||
nodes.push $.tn(' '), node
|
||||
@ -79,7 +79,7 @@ Sauce =
|
||||
URL: (post) -> post.file.url
|
||||
IMG: (post, ext) -> if ext in ['gif', 'jpg', 'png'] then post.file.url else post.file.thumbURL
|
||||
MD5: (post) -> post.file.MD5
|
||||
sMD5: (post) -> post.file.MD5?.replace /[+/=]/g, (c) -> {'+': '-', '/': '_', '=': ''}[c]
|
||||
sMD5: (post) -> post.file.MD5?.replace /[+/=]/g, (c) -> ({'+': '-', '/': '_', '=': ''})[c]
|
||||
hMD5: (post) -> if post.file.MD5 then ("0#{c.charCodeAt(0).toString(16)}"[-2..] for c in atob post.file.MD5).join('')
|
||||
board: (post) -> post.board.ID
|
||||
name: (post) -> post.file.name
|
||||
|
||||
@ -71,7 +71,7 @@ Volume =
|
||||
|
||||
wheel: (e) ->
|
||||
return if e.shiftKey or e.altKey or e.ctrlKey or e.metaKey
|
||||
return unless el = $ 'video:not([data-md5])', @
|
||||
return if not (el = $ 'video:not([data-md5])', @)
|
||||
return if el.muted or not $.hasAudio el
|
||||
volume = el.volume + 0.1
|
||||
volume *= 1.1 if e.deltaY < 0
|
||||
|
||||
@ -69,7 +69,7 @@ Embedding =
|
||||
$.on $('.close', Embedding.dialog), 'click', Embedding.closeFloat
|
||||
$.on $('.move', Embedding.dialog), 'mousedown', Embedding.dragEmbed
|
||||
$.on $('.jump', Embedding.dialog), 'click', ->
|
||||
Header.scrollTo Embedding.lastEmbed if doc.contains Embedding.lastEmbed
|
||||
(Header.scrollTo Embedding.lastEmbed if doc.contains Embedding.lastEmbed)
|
||||
$.add d.body, Embedding.dialog
|
||||
|
||||
closeFloat: ->
|
||||
@ -91,7 +91,7 @@ Embedding =
|
||||
|
||||
title: (data) ->
|
||||
{key, uid, options, link, post} = data
|
||||
return unless service = Embedding.types[key].title
|
||||
return if not (service = Embedding.types[key].title)
|
||||
$.addClass link, key.toLowerCase()
|
||||
if service.batchSize
|
||||
(service.queue or= []).push data
|
||||
@ -117,7 +117,7 @@ Embedding =
|
||||
click: (e) ->
|
||||
e.preventDefault()
|
||||
if Conf['Floating Embeds'] or $.hasClass(doc, 'catalog-mode')
|
||||
return unless div = Embedding.media.firstChild
|
||||
return if not (div = Embedding.media.firstChild)
|
||||
$.replace div, Embedding.cb.embed @
|
||||
Embedding.lastEmbed = Get.postFromNode(@).nodes.root
|
||||
$.rmClass Embedding.dialog, 'empty'
|
||||
|
||||
@ -24,7 +24,7 @@ ExpandComment =
|
||||
$.replace post.nodes.shortComment, post.nodes.longComment
|
||||
post.nodes.comment = post.nodes.longComment
|
||||
return
|
||||
return unless a = $ '.abbr > a', post.nodes.comment
|
||||
return if not (a = $ '.abbr > a', post.nodes.comment)
|
||||
a.textContent = "Post No.#{post} Loading..."
|
||||
$.cache "//a.4cdn.org#{a.pathname.split(/\/+/).splice(0,4).join('/')}.json", -> ExpandComment.parse @, a, post
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
ExpandThread =
|
||||
statuses: {}
|
||||
init: ->
|
||||
return unless g.VIEW is 'index' and Conf['Thread Expansion']
|
||||
return if not (g.VIEW is 'index' and Conf['Thread Expansion'])
|
||||
if Conf['JSON Index']
|
||||
$.on d, 'IndexRefreshInternal', @onIndexRefresh
|
||||
else
|
||||
@ -10,7 +10,7 @@ ExpandThread =
|
||||
cb: -> ExpandThread.setButton @
|
||||
|
||||
setButton: (thread) ->
|
||||
return unless thread.nodes.root and (a = $ '.summary', thread.nodes.root)
|
||||
return if not (thread.nodes.root and (a = $ '.summary', thread.nodes.root))
|
||||
a.textContent = Build.summaryText '+', a.textContent.match(/\d+/g)...
|
||||
a.style.cursor = 'pointer'
|
||||
$.on a, 'click', ExpandThread.cbToggle
|
||||
@ -35,7 +35,7 @@ ExpandThread =
|
||||
|
||||
toggle: (thread) ->
|
||||
threadRoot = thread.nodes.root
|
||||
return unless a = $ '.summary', threadRoot
|
||||
return if not (a = $ '.summary', threadRoot)
|
||||
if thread.ID of ExpandThread.statuses
|
||||
ExpandThread.contract thread, a, threadRoot
|
||||
else
|
||||
|
||||
@ -5,7 +5,7 @@ Flash =
|
||||
|
||||
initReady: ->
|
||||
if $.hasStorage
|
||||
$.global -> window.SWFEmbed.init() if JSON.parse(localStorage['4chan-settings'] or '{}').disableAll
|
||||
$.global -> (window.SWFEmbed.init() if JSON.parse(localStorage['4chan-settings'] or '{}').disableAll)
|
||||
else
|
||||
if g.VIEW is 'thread'
|
||||
$.global -> window.Main.tid = location.pathname.split(/\/+/)[3]
|
||||
|
||||
@ -4,8 +4,8 @@ Fourchan =
|
||||
|
||||
if g.BOARD.ID is 'g'
|
||||
$.on window, 'prettyprint:cb', (e) ->
|
||||
return unless post = g.posts[e.detail.ID]
|
||||
return unless pre = $$('.prettyprint', post.nodes.comment)[e.detail.i]
|
||||
return if not (post = g.posts[e.detail.ID])
|
||||
return if not (pre = $$('.prettyprint', post.nodes.comment)[e.detail.i])
|
||||
unless $.hasClass pre, 'prettyprinted'
|
||||
pre.innerHTML = e.detail.html
|
||||
$.addClass pre, 'prettyprinted'
|
||||
|
||||
@ -16,5 +16,5 @@ IDPostCount =
|
||||
{uniqueID} = Get.postFromNode(@).info
|
||||
n = 0
|
||||
IDPostCount.thread.posts.forEach (post) ->
|
||||
n++ if post.info.uniqueID is uniqueID
|
||||
(n++ if post.info.uniqueID is uniqueID)
|
||||
@title = "#{n} post#{if n is 1 then '' else 's'} by this ID"
|
||||
|
||||
@ -17,7 +17,7 @@ Keybinds =
|
||||
Conf[hotkey] = key
|
||||
|
||||
keydown: (e) ->
|
||||
return unless key = Keybinds.keyCode e
|
||||
return if not (key = Keybinds.keyCode e)
|
||||
{target} = e
|
||||
if target.nodeName in ['INPUT', 'TEXTAREA']
|
||||
return unless /(Esc|Alt|Ctrl|Meta|Shift\+\w{2,})/.test(key) and not /^Alt\+(\d|Up|Down|Left|Right)$/.test(key)
|
||||
@ -260,7 +260,7 @@ Keybinds =
|
||||
when 'code' then !!config.code_tags
|
||||
when 'math', 'eqn' then !!config.math_tags
|
||||
when 'sjis' then !!config.sjis_tags
|
||||
new Notice 'warning', "[#{tag}] tags are not supported on /#{g.BOARD}/.", 20 unless supported
|
||||
(new Notice 'warning', "[#{tag}] tags are not supported on /#{g.BOARD}/.", 20 unless supported)
|
||||
|
||||
value = ta.value
|
||||
selStart = ta.selectionStart
|
||||
@ -272,7 +272,7 @@ Keybinds =
|
||||
value[selEnd..]
|
||||
|
||||
# Move the caret to the end of the selection.
|
||||
range = "[#{tag}]".length + selEnd
|
||||
range = ("[#{tag}]").length + selEnd
|
||||
ta.setSelectionRange range, range
|
||||
|
||||
# Fire the 'input' event
|
||||
@ -314,7 +314,7 @@ Keybinds =
|
||||
'following'
|
||||
else
|
||||
'preceding'
|
||||
return unless next = $.x "#{axis}-sibling::div[contains(@class,'replyContainer') and not(@hidden) and not(child::div[@class='stub'])][1]/child::div[contains(@class,'reply')]", root
|
||||
return if not (next = $.x "#{axis}-sibling::div[contains(@class,'replyContainer') and not(@hidden) and not(child::div[@class='stub'])][1]/child::div[contains(@class,'reply')]", root)
|
||||
Header.scrollToIfNeeded next, delta is +1
|
||||
@focus next
|
||||
$.rmClass postEl, 'highlight'
|
||||
|
||||
@ -5,7 +5,7 @@ PSAHiding =
|
||||
$.one d, '4chanXInitFinished', @setup
|
||||
|
||||
setup: ->
|
||||
unless psa = PSAHiding.psa = $.id 'globalMessage'
|
||||
if not (psa = PSAHiding.psa = $.id 'globalMessage')
|
||||
$.rmClass doc, 'hide-announcement'
|
||||
return
|
||||
if (hr = $.id('globalToggle')?.previousElementSibling) and hr.nodeName is 'HR'
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
Report =
|
||||
init: ->
|
||||
return unless (match = location.search.match /\bno=(\d+)/)
|
||||
return if not (match = location.search.match /\bno=(\d+)/)
|
||||
Captcha.replace.init()
|
||||
@postID = +match[1]
|
||||
$.ready @ready
|
||||
@ -20,6 +20,6 @@ Report =
|
||||
Report.fit 'body'
|
||||
|
||||
fit: (selector) ->
|
||||
return unless (el = $ selector, doc) and getComputedStyle(el).visibility isnt 'hidden'
|
||||
return if not ((el = $ selector, doc) and getComputedStyle(el).visibility isnt 'hidden')
|
||||
dy = el.getBoundingClientRect().bottom - doc.clientHeight + 8
|
||||
window.resizeBy 0, dy if dy > 0
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
Favicon =
|
||||
init: ->
|
||||
$.asap (-> d.head and Favicon.el = $ 'link[rel="shortcut icon"]', d.head), Favicon.initAsap
|
||||
$.asap (-> d.head and (Favicon.el = $ 'link[rel="shortcut icon"]', d.head)), Favicon.initAsap
|
||||
|
||||
initAsap: ->
|
||||
Favicon.el.type = 'image/x-icon'
|
||||
|
||||
@ -60,7 +60,7 @@ ReplyPruning =
|
||||
@posts.forEach (post) ->
|
||||
if post.isReply
|
||||
ReplyPruning.total++
|
||||
ReplyPruning.totalFiles++ if post.file
|
||||
(ReplyPruning.totalFiles++ if post.file)
|
||||
|
||||
# If we're linked to a post that we would hide, don't hide the posts in the first place.
|
||||
# Also don't hide posts if we open the thread by a link to the OP.
|
||||
|
||||
@ -42,7 +42,7 @@ ThreadStats =
|
||||
@posts.forEach (post) ->
|
||||
postCount++
|
||||
fileCount++ if post.file
|
||||
ThreadStats.lastPost = post.info.date if ThreadStats.pageCountEl
|
||||
(ThreadStats.lastPost = post.info.date if ThreadStats.pageCountEl)
|
||||
ThreadStats.thread = @
|
||||
ThreadStats.fetchPage()
|
||||
ThreadStats.update postCount, fileCount, @ipCount
|
||||
|
||||
@ -32,7 +32,7 @@ ThreadUpdater =
|
||||
className: 'brackets-wrap updatelink'
|
||||
$.extend updateLink, <%= html('<a href="javascript:;">Update</a>') %>
|
||||
Main.ready ->
|
||||
$.add navLinksBot, [$.tn(' '), updateLink] if (navLinksBot = $ '.navLinksBot')
|
||||
($.add navLinksBot, [$.tn(' '), updateLink] if (navLinksBot = $ '.navLinksBot'))
|
||||
$.on updateLink.firstElementChild, 'click', @update
|
||||
|
||||
subEntries = []
|
||||
@ -77,7 +77,7 @@ ThreadUpdater =
|
||||
ThreadUpdater.fileIDs = []
|
||||
@posts.forEach (post) ->
|
||||
ThreadUpdater.postIDs.push post.ID
|
||||
ThreadUpdater.fileIDs.push post.ID if post.file
|
||||
(ThreadUpdater.fileIDs.push post.ID if post.file)
|
||||
|
||||
ThreadUpdater.cb.interval.call $.el 'input', value: Conf['Interval']
|
||||
|
||||
@ -238,7 +238,7 @@ ThreadUpdater =
|
||||
whenModified: 'ThreadUpdater'
|
||||
|
||||
updateThreadStatus: (type, status) ->
|
||||
return unless hasChanged = ThreadUpdater.thread["is#{type}"] isnt status
|
||||
return if not (hasChanged = ThreadUpdater.thread["is#{type}"] isnt status)
|
||||
ThreadUpdater.thread.setStatus type, status
|
||||
return if type is 'Closed' and ThreadUpdater.thread.isArchived
|
||||
change = if type is 'Sticky'
|
||||
@ -346,7 +346,7 @@ ThreadUpdater =
|
||||
Header.scrollTo firstPost if firstPost
|
||||
|
||||
# Update IP count in original post form.
|
||||
if OP.unique_ips? and ipCountEl = $.id('unique-ips')
|
||||
if OP.unique_ips? and (ipCountEl = $.id('unique-ips'))
|
||||
ipCountEl.textContent = OP.unique_ips
|
||||
ipCountEl.previousSibling.textContent = ipCountEl.previousSibling.textContent.replace(/\b(?:is|are)\b/, if OP.unique_ips is 1 then 'is' else 'are')
|
||||
ipCountEl.nextSibling.textContent = ipCountEl.nextSibling.textContent.replace(/\bposters?\b/, if OP.unique_ips is 1 then 'poster' else 'posters')
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
ThreadWatcher =
|
||||
init: ->
|
||||
return unless (@enabled = Conf['Thread Watcher'])
|
||||
return if not (@enabled = Conf['Thread Watcher'])
|
||||
|
||||
@shortcut = sc = $.el 'a',
|
||||
id: 'watcher-link'
|
||||
@ -335,7 +335,7 @@ ThreadWatcher =
|
||||
for post in [thread.OP, thread.OP.clones...]
|
||||
toggler = $ '.watch-thread-link', post.nodes.info
|
||||
ThreadWatcher.setToggler toggler, isWatched
|
||||
thread.catalogView.nodes.root.classList.toggle 'watched', isWatched if thread.catalogView
|
||||
(thread.catalogView.nodes.root.classList.toggle 'watched', isWatched if thread.catalogView)
|
||||
|
||||
if Conf['Pin Watched Threads']
|
||||
$.event 'SortIndex', {deferred: Conf['Index Mode'] isnt 'catalog'}
|
||||
@ -346,7 +346,7 @@ ThreadWatcher =
|
||||
return
|
||||
|
||||
update: (boardID, threadID, newData) ->
|
||||
return unless data = ThreadWatcher.db?.get {boardID, threadID}
|
||||
return if not (data = ThreadWatcher.db?.get {boardID, threadID})
|
||||
if newData.isDead and Conf['Auto Prune']
|
||||
ThreadWatcher.db.delete {boardID, threadID}
|
||||
ThreadWatcher.refresh()
|
||||
@ -354,7 +354,7 @@ ThreadWatcher =
|
||||
n = 0
|
||||
n++ for key, val of newData when data[key] isnt val
|
||||
return unless n
|
||||
return unless (data = ThreadWatcher.db.get {boardID, threadID})
|
||||
return if not (data = ThreadWatcher.db.get {boardID, threadID})
|
||||
ThreadWatcher.db.extend {boardID, threadID, val: newData}
|
||||
if line = $ "#watched-threads > [data-full-i-d='#{boardID}.#{threadID}']", ThreadWatcher.dialog
|
||||
newLine = ThreadWatcher.makeLine boardID, threadID, data
|
||||
@ -364,7 +364,7 @@ ThreadWatcher =
|
||||
ThreadWatcher.refresh()
|
||||
|
||||
set404: (boardID, threadID, cb) ->
|
||||
return cb() unless data = ThreadWatcher.db?.get {boardID, threadID}
|
||||
return cb() if not (data = ThreadWatcher.db?.get {boardID, threadID})
|
||||
if Conf['Auto Prune']
|
||||
ThreadWatcher.db.delete {boardID, threadID}
|
||||
return cb()
|
||||
|
||||
@ -185,7 +185,7 @@ Unread =
|
||||
return unless count
|
||||
Unread.updatePosition()
|
||||
Unread.saveLastReadPost()
|
||||
Unread.update() if e
|
||||
(Unread.update() if e)
|
||||
|
||||
updatePosition: ->
|
||||
while Unread.position and !Unread.posts.has Unread.position.ID
|
||||
|
||||
@ -26,7 +26,7 @@ Captcha.replace =
|
||||
$.onExists doc, 'iframe', Captcha.replace.iframe
|
||||
|
||||
noscript: ->
|
||||
return unless (original = $ '#g-recaptcha, #captchaContainerAlt') and (noscript = $ 'noscript')
|
||||
return if not ((original = $ '#g-recaptcha, #captchaContainerAlt') and (noscript = $ 'noscript'))
|
||||
span = $.el 'span',
|
||||
id: 'captcha-forced-noscript'
|
||||
$.replace noscript, span
|
||||
|
||||
@ -3,7 +3,7 @@ Captcha.v1 =
|
||||
|
||||
init: ->
|
||||
return if d.cookie.indexOf('pass_enabled=1') >= 0
|
||||
return unless @isEnabled = !!$ '#g-recaptcha, #captchaContainerAlt'
|
||||
return if not (@isEnabled = !!$ '#g-recaptcha, #captchaContainerAlt')
|
||||
|
||||
imgContainer = $.el 'div',
|
||||
className: 'captcha-img'
|
||||
@ -40,7 +40,7 @@ Captcha.v1 =
|
||||
|
||||
replace: ->
|
||||
return if @script
|
||||
unless @script = $ 'script[src="//www.google.com/recaptcha/api/js/recaptcha_ajax.js"]', d.head
|
||||
if not (@script = $ 'script[src="//www.google.com/recaptcha/api/js/recaptcha_ajax.js"]', d.head)
|
||||
@script = $.el 'script',
|
||||
src: '//www.google.com/recaptcha/api/js/recaptcha_ajax.js'
|
||||
$.add d.head, @script
|
||||
@ -66,7 +66,7 @@ Captcha.v1 =
|
||||
$.on field, 'keydown', (e) ->
|
||||
if e.keyCode is 8 and not field.value
|
||||
$.global -> window.Recaptcha.reload()
|
||||
field.focus() if location.hostname is 'sys.4chan.org'
|
||||
(field.focus() if location.hostname is 'sys.4chan.org')
|
||||
|
||||
$.global ->
|
||||
container = document.getElementById 'captchaContainerAlt'
|
||||
@ -113,7 +113,7 @@ Captcha.v1 =
|
||||
@nodes.input.focus()
|
||||
|
||||
afterSetup: ->
|
||||
return unless challenge = $.id 'recaptcha_challenge_field_holder'
|
||||
return if not (challenge = $.id 'recaptcha_challenge_field_holder')
|
||||
return if challenge is QR.captcha.nodes.challenge
|
||||
|
||||
setLifetime = (e) -> QR.captcha.lifetime = e.detail
|
||||
@ -192,7 +192,7 @@ Captcha.v1 =
|
||||
@nodes.img.src = @blank
|
||||
return
|
||||
return unless @nodes.challenge.firstChild
|
||||
return unless challenge_image = $.id 'recaptcha_challenge_image'
|
||||
return if not (challenge_image = $.id 'recaptcha_challenge_image')
|
||||
# -1 minute to give upload some time.
|
||||
@timeout = Date.now() + @lifetime * $.SECOND - $.MINUTE
|
||||
challenge = @nodes.challenge.firstChild.value
|
||||
|
||||
@ -3,7 +3,7 @@ Captcha.v2 =
|
||||
|
||||
init: ->
|
||||
return if d.cookie.indexOf('pass_enabled=1') >= 0
|
||||
return unless (@isEnabled = !!$ '#g-recaptcha, #captchaContainerAlt, #captcha-forced-noscript')
|
||||
return if not (@isEnabled = !!$ '#g-recaptcha, #captchaContainerAlt, #captcha-forced-noscript')
|
||||
|
||||
if (@noscript = Conf['Force Noscript Captcha'] or not Main.jsEnabled)
|
||||
$.addClass QR.nodes.el, 'noscript-captcha'
|
||||
|
||||
@ -4,7 +4,7 @@ PassLink =
|
||||
Main.ready @ready
|
||||
|
||||
ready: ->
|
||||
return unless (styleSelector = $.id 'styleSelector')
|
||||
return if not (styleSelector = $.id 'styleSelector')
|
||||
|
||||
passLink = $.el 'span',
|
||||
className: 'brackets-wrap pass-link-container'
|
||||
|
||||
@ -536,14 +536,14 @@ QR =
|
||||
i = 0
|
||||
save = -> QR.selected.save @
|
||||
while name = items[i++]
|
||||
continue unless node = nodes[name]
|
||||
continue if not (node = nodes[name])
|
||||
event = if node.nodeName is 'SELECT' then 'change' else 'input'
|
||||
$.on nodes[name], event, save
|
||||
|
||||
# XXX Blink and WebKit treat width and height of <textarea>s as min-width and min-height
|
||||
if $.engine is 'gecko' and Conf['Remember QR Size']
|
||||
$.get 'QR Size', '', (item) ->
|
||||
nodes.com.style.cssText = item['QR Size']
|
||||
(nodes.com.style.cssText = item['QR Size'])
|
||||
$.on nodes.com, 'mouseup', (e) ->
|
||||
return if e.button isnt 0
|
||||
$.set 'QR Size', @style.cssText
|
||||
@ -777,10 +777,11 @@ QR =
|
||||
|
||||
QR.cooldown.add threadID, postID
|
||||
|
||||
URL = if threadID is postID # new thread
|
||||
URL = if threadID is postID then ( # new thread
|
||||
"#{window.location.origin}/#{g.BOARD}/thread/#{threadID}"
|
||||
else if threadID isnt g.THREADID and lastPostToThread and Conf['Open Post in New Tab'] # replying from the index or a different thread
|
||||
) else if threadID isnt g.THREADID and lastPostToThread and Conf['Open Post in New Tab'] then ( # replying from the index or a different thread
|
||||
"#{window.location.origin}/#{g.BOARD}/thread/#{threadID}#p#{postID}"
|
||||
) else undefined
|
||||
|
||||
if URL
|
||||
open = if Conf['Open Post in New Tab'] or postsCount
|
||||
|
||||
@ -51,9 +51,10 @@ QR.oekaki =
|
||||
window.Tegaki.flatten().toBlob (file) ->
|
||||
source = "oekaki-#{Date.now()}"
|
||||
FCX.oekakiLatest = source
|
||||
document.dispatchEvent new CustomEvent 'QRSetFile',
|
||||
document.dispatchEvent new CustomEvent 'QRSetFile', {
|
||||
bubbles: true
|
||||
detail: {file, name: FCX.oekakiName, source}
|
||||
}
|
||||
if window.Tegaki
|
||||
document.querySelector('#qr .oekaki').hidden = false
|
||||
|
||||
@ -101,9 +102,10 @@ QR.oekaki =
|
||||
name = document.getElementById('qr-filename').value.replace(/\.\w+$/, '') + '.png'
|
||||
{source} = document.getElementById('file-n-submit').dataset
|
||||
error = (content) ->
|
||||
document.dispatchEvent new CustomEvent 'CreateNotification',
|
||||
document.dispatchEvent new CustomEvent 'CreateNotification', {
|
||||
bubbles: true
|
||||
detail: {type: 'warning', content, lifetime: 20}
|
||||
}
|
||||
cb = (e) ->
|
||||
document.removeEventListener 'QRFile', cb, false
|
||||
return error 'No file to edit.' unless e.detail
|
||||
|
||||
@ -13,7 +13,7 @@ QR.persona =
|
||||
|
||||
parseItem: (item) ->
|
||||
return if item[0] is '#'
|
||||
return unless match = item.match /(name|options|email|subject|password):"(.*)"/i
|
||||
return if not (match = item.match /(name|options|email|subject|password):"(.*)"/i)
|
||||
[match, type, val] = match
|
||||
|
||||
# Don't mix up item settings with val.
|
||||
|
||||
@ -16,7 +16,7 @@ QR.post = class
|
||||
$.on @nodes.rm, 'click', (e) => e.stopPropagation(); @rm()
|
||||
$.on @nodes.spoiler, 'change', (e) =>
|
||||
@spoiler = e.target.checked
|
||||
QR.nodes.spoiler.checked = @spoiler if @ is QR.selected
|
||||
(QR.nodes.spoiler.checked = @spoiler if @ is QR.selected)
|
||||
for label in $$ 'label', el
|
||||
$.on label, 'click', (e) -> e.stopPropagation()
|
||||
$.add QR.nodes.dumpList, el
|
||||
@ -53,7 +53,7 @@ QR.post = class
|
||||
else
|
||||
''
|
||||
|
||||
@load() if QR.selected is @ # load persona
|
||||
(@load() if QR.selected is @) # load persona
|
||||
@select() if select
|
||||
@unlock()
|
||||
# Post count temporarily off by 1 when called from QR.post.rm or QR.close
|
||||
@ -104,7 +104,7 @@ QR.post = class
|
||||
# Load this post's values.
|
||||
|
||||
for name in ['thread', 'name', 'email', 'sub', 'com', 'filename']
|
||||
continue unless node = QR.nodes[name]
|
||||
continue if not (node = QR.nodes[name])
|
||||
node.value = @[name] or node.dataset.default or ''
|
||||
|
||||
(if @thread isnt 'new' then $.addClass else $.rmClass) QR.nodes.el, 'reply-to-thread'
|
||||
@ -140,7 +140,7 @@ QR.post = class
|
||||
# Do this in case people use extensions
|
||||
# that do not trigger the `input` event.
|
||||
for name in ['thread', 'name', 'email', 'sub', 'com', 'filename', 'spoiler']
|
||||
continue unless node = QR.nodes[name]
|
||||
continue if not (node = QR.nodes[name])
|
||||
@save node
|
||||
return
|
||||
|
||||
@ -171,10 +171,10 @@ QR.post = class
|
||||
(@errors or= []).push div
|
||||
[rm, rmAll] = $$ 'a', div
|
||||
$.on div, 'click', =>
|
||||
@select() if @ in QR.posts
|
||||
(@select() if @ in QR.posts)
|
||||
$.on rm, 'click', (e) =>
|
||||
e.stopPropagation()
|
||||
@rm() if @ in QR.posts
|
||||
(@rm() if @ in QR.posts)
|
||||
$.on rmAll, 'click', QR.post.rmErrored
|
||||
QR.error div, true
|
||||
|
||||
|
||||
@ -26,7 +26,7 @@ QuoteBacklink =
|
||||
a = $.el 'a',
|
||||
href: Build.postURL @board.ID, @thread.ID, @ID
|
||||
className: if @isHidden then 'filtered backlink' else 'backlink'
|
||||
textContent: Conf['backlink'].replace(/%(?:id|%)/g, (x) => {'%id': @ID, '%%': '%'}[x])
|
||||
textContent: Conf['backlink'].replace(/%(?:id|%)/g, (x) => ({'%id': @ID, '%%': '%'})[x])
|
||||
$.add a, QuoteYou.mark.cloneNode(true) if markYours
|
||||
for quote in @quotes
|
||||
containers = [QuoteBacklink.getContainer quote]
|
||||
|
||||
@ -65,14 +65,16 @@ QuoteInline =
|
||||
$.addClass qroot, 'hasInline'
|
||||
new Fetcher boardID, threadID, postID, inline, quoter
|
||||
|
||||
return unless (post = g.posts["#{boardID}.#{postID}"]) and
|
||||
return if not (
|
||||
(post = g.posts["#{boardID}.#{postID}"]) and
|
||||
context.thread is post.thread
|
||||
)
|
||||
|
||||
# Hide forward post if it's a backlink of a post in this thread.
|
||||
# Will only unhide if there's no inlined backlinks of it anymore.
|
||||
if isBacklink and Conf['Forward Hiding']
|
||||
$.addClass post.nodes.root, 'forwarded'
|
||||
post.forwarded++ or post.forwarded = 1
|
||||
post.forwarded++ or (post.forwarded = 1)
|
||||
|
||||
# Decrease the unread count if this post
|
||||
# is in the array of unread posts.
|
||||
@ -91,7 +93,7 @@ QuoteInline =
|
||||
$.rmClass qroot, 'hasInline'
|
||||
|
||||
# Stop if it only contains text.
|
||||
return unless el = root.firstElementChild
|
||||
return if not (el = root.firstElementChild)
|
||||
|
||||
# Dereference clone.
|
||||
post = g.posts["#{boardID}.#{postID}"]
|
||||
|
||||
@ -43,7 +43,7 @@ QuotePreview =
|
||||
|
||||
mouseout: ->
|
||||
# Stop if it only contains text.
|
||||
return unless root = @el.firstElementChild
|
||||
return if not (root = @el.firstElementChild)
|
||||
|
||||
clone = Get.postFromRoot root
|
||||
post = clone.origin
|
||||
|
||||
@ -48,7 +48,7 @@ QuoteThreading =
|
||||
setThread: ->
|
||||
QuoteThreading.thread = @
|
||||
$.asap (-> !Conf['Thread Updater'] or $ '.navLinksBot > .updatelink'), ->
|
||||
$.add navLinksBot, [$.tn(' '), QuoteThreading.threadNewLink] if (navLinksBot = $ '.navLinksBot')
|
||||
($.add navLinksBot, [$.tn(' '), QuoteThreading.threadNewLink] if (navLinksBot = $ '.navLinksBot'))
|
||||
|
||||
node: ->
|
||||
return if @isFetchedQuote or @isClone or !@isReply
|
||||
@ -77,9 +77,11 @@ QuoteThreading =
|
||||
posts
|
||||
|
||||
insert: (post) ->
|
||||
return false unless Conf['Thread Quotes'] and
|
||||
return false if not (
|
||||
Conf['Thread Quotes'] and
|
||||
(parent = QuoteThreading.parent[post.fullID]) and
|
||||
!QuoteThreading.inserted[post.fullID]
|
||||
)
|
||||
|
||||
descendants = QuoteThreading.descendants post
|
||||
if !Unread.posts.has(parent.ID)
|
||||
|
||||
@ -8,7 +8,7 @@ QuoteYou =
|
||||
$.forceSync 'Remember Your Posts'
|
||||
if Conf['Remember Your Posts']
|
||||
{boardID, threadID, postID} = e.detail
|
||||
QuoteYou.db.set {boardID, threadID, postID, val: true}
|
||||
(QuoteYou.db.set {boardID, threadID, postID, val: true})
|
||||
|
||||
return unless g.VIEW in ['index', 'thread']
|
||||
|
||||
@ -49,7 +49,7 @@ QuoteYou =
|
||||
$.rmClass highlight, 'highlight' if highlight = $ '.highlight'
|
||||
|
||||
unless QuoteYou.lastRead and doc.contains(QuoteYou.lastRead) and $.hasClass(QuoteYou.lastRead, 'quotesYou')
|
||||
unless (post = QuoteYou.lastRead = $ '.quotesYou')
|
||||
if not (post = QuoteYou.lastRead = $ '.quotesYou')
|
||||
new Notice 'warning', 'No posts are currently quoting you, loser.', 20
|
||||
return
|
||||
return if QuoteYou.cb.scroll post
|
||||
|
||||
@ -22,7 +22,7 @@ Quotify =
|
||||
return
|
||||
|
||||
parseArchivelink: (link) ->
|
||||
return unless (m = link.pathname.match /^\/([^/]+)\/thread\/S?(\d+)\/?$/)
|
||||
return if not (m = link.pathname.match /^\/([^/]+)\/thread\/S?(\d+)\/?$/)
|
||||
return if link.hostname is 'boards.4chan.org'
|
||||
boardID = m[1]
|
||||
threadID = m[2]
|
||||
@ -43,7 +43,7 @@ Quotify =
|
||||
return
|
||||
|
||||
quote = deadlink.textContent
|
||||
return unless postID = quote.match(/\d+$/)?[0]
|
||||
return if not (postID = quote.match(/\d+$/)?[0])
|
||||
if postID[0] is '0'
|
||||
# Fix quotelinks that start with a `0`.
|
||||
Quotify.fixDeadlink deadlink
|
||||
|
||||
@ -98,7 +98,7 @@ class DataBoard
|
||||
@ajaxCleanParse boardID, e1.target.response, e2.target.response
|
||||
|
||||
ajaxCleanParse: (boardID, response1, response2) ->
|
||||
return unless (board = @data.boards[boardID])
|
||||
return if not (board = @data.boards[boardID])
|
||||
threads = {}
|
||||
if response1
|
||||
for page in response1
|
||||
|
||||
@ -92,7 +92,7 @@ class Fetcher
|
||||
|
||||
archivedPost: ->
|
||||
return false unless Conf['Resurrect Quotes']
|
||||
return false unless url = Redirect.to 'post', {@boardID, @postID}
|
||||
return false if not (url = Redirect.to 'post', {@boardID, @postID})
|
||||
archive = Redirect.data.post[@boardID]
|
||||
if /^https:\/\//.test(url) or location.protocol is 'http:'
|
||||
$.cache url, (e) =>
|
||||
|
||||
@ -14,7 +14,7 @@ class Post
|
||||
|
||||
@nodes = @parseNodes root
|
||||
|
||||
unless (@isReply = $.hasClass @nodes.post, 'reply')
|
||||
if not (@isReply = $.hasClass @nodes.post, 'reply')
|
||||
@thread.OP = @
|
||||
@thread.isArchived = !!$ '.archivedIcon', @nodes.info
|
||||
@thread.isSticky = !!$ '.stickyIcon', @nodes.info
|
||||
@ -164,8 +164,8 @@ class Post
|
||||
parseFile: ->
|
||||
{fileRoot} = @nodes
|
||||
return unless fileRoot
|
||||
return unless (link = $ '.fileText > a, .fileText-original > a', fileRoot)
|
||||
return unless (info = link.nextSibling?.textContent.match /\(([\d.]+ [KMG]?B).*\)/)
|
||||
return if not (link = $ '.fileText > a, .fileText-original > a', fileRoot)
|
||||
return if not (info = link.nextSibling?.textContent.match /\(([\d.]+ [KMG]?B).*\)/)
|
||||
fileText = fileRoot.firstElementChild
|
||||
@file =
|
||||
text: fileText
|
||||
@ -206,7 +206,7 @@ class Post
|
||||
$.rmClass @nodes.root, 'deleted-file'
|
||||
$.addClass @nodes.root, 'deleted-post'
|
||||
|
||||
unless (strong = $ 'strong.warning', @nodes.info)
|
||||
if not (strong = $ 'strong.warning', @nodes.info)
|
||||
strong = $.el 'strong',
|
||||
className: 'warning'
|
||||
$.after $('input', @nodes.info), strong
|
||||
|
||||
@ -26,7 +26,7 @@ class Thread
|
||||
|
||||
setPage: (pageNum) ->
|
||||
{info, reply} = @OP.nodes
|
||||
unless (icon = $ '.page-num', info)
|
||||
if not (icon = $ '.page-num', info)
|
||||
icon = $.el 'span', className: 'page-num'
|
||||
$.replace reply.parentNode.previousSibling, [$.tn(' '), icon, $.tn(' ')]
|
||||
icon.title = "This thread is on page #{pageNum} in the original index."
|
||||
|
||||
@ -122,9 +122,10 @@ Main =
|
||||
else if (match = search.match /\bres=(\d+)/)
|
||||
$.ready ->
|
||||
if Conf['404 Redirect'] and $.id('errmsg')?.textContent is 'Error: Specified thread does not exist.'
|
||||
Redirect.navigate 'thread',
|
||||
Redirect.navigate 'thread', {
|
||||
boardID: g.BOARD.ID
|
||||
postID: +match[1]
|
||||
}
|
||||
else if pathname[2] is 'post'
|
||||
PostSuccessful.init()
|
||||
return
|
||||
@ -132,9 +133,10 @@ Main =
|
||||
return unless pathname[2] and not /s\.jpg$/.test(pathname[2])
|
||||
$.asap (-> d.readyState isnt 'loading'), ->
|
||||
if Conf['404 Redirect'] and d.title in ['4chan - Temporarily Offline', '4chan - 404 Not Found']
|
||||
Redirect.navigate 'file',
|
||||
Redirect.navigate 'file', {
|
||||
boardID: g.BOARD.ID
|
||||
filename: pathname[pathname.length - 1]
|
||||
}
|
||||
else if video = $ 'video'
|
||||
if Conf['Volume in New Tab']
|
||||
Volume.setup video
|
||||
@ -197,7 +199,7 @@ Main =
|
||||
|
||||
keyboard = false
|
||||
$.on d, 'mousedown', -> keyboard = false
|
||||
$.on d, 'keydown', (e) -> keyboard = true if e.keyCode is 9 # tab
|
||||
$.on d, 'keydown', (e) -> (keyboard = true if e.keyCode is 9) # tab
|
||||
window.addEventListener 'focus', (-> doc.classList.toggle 'keyboard-focus', keyboard), true
|
||||
|
||||
Main.setClass()
|
||||
@ -236,9 +238,10 @@ Main =
|
||||
$.after $.id('fourchanx-css'), Main.bgColorStyle
|
||||
setStyle()
|
||||
return unless mainStyleSheet
|
||||
new MutationObserver(setStyle).observe mainStyleSheet,
|
||||
new MutationObserver(setStyle).observe mainStyleSheet, {
|
||||
attributes: true
|
||||
attributeFilter: ['href']
|
||||
}
|
||||
|
||||
initReady: ->
|
||||
# XXX Sometimes threads don't 404 but are left over as stubs containing one garbage reply post.
|
||||
@ -322,7 +325,7 @@ Main =
|
||||
i = 0
|
||||
cbs = Callbacks[klass]
|
||||
fn = ->
|
||||
return false unless node = nodes[i]
|
||||
return false if not (node = nodes[i])
|
||||
cbs.execute node
|
||||
++i % 25
|
||||
|
||||
@ -330,7 +333,7 @@ Main =
|
||||
while fn()
|
||||
continue
|
||||
unless nodes[i]
|
||||
cb() if cb
|
||||
(cb() if cb)
|
||||
return
|
||||
setTimeout softTask, 0
|
||||
|
||||
@ -353,10 +356,11 @@ Main =
|
||||
div = $.el 'div',
|
||||
<%= html('${errors.length} errors occurred.&{Main.reportLink(errors)} [<a href="javascript:;">show</a>]') %>
|
||||
$.on div.lastElementChild, 'click', ->
|
||||
[@textContent, logs.hidden] = if @textContent is 'show'
|
||||
[@textContent, logs.hidden] = if @textContent is 'show' then (
|
||||
['hide', false]
|
||||
else
|
||||
) else (
|
||||
['show', true]
|
||||
)
|
||||
|
||||
logs = $.el 'div',
|
||||
hidden: true
|
||||
@ -408,7 +412,7 @@ Main =
|
||||
|
||||
ready: (cb) ->
|
||||
$.ready ->
|
||||
cb() if Main.isThisPageLegit()
|
||||
(cb() if Main.isThisPageLegit())
|
||||
|
||||
features: [
|
||||
['Polyfill', Polyfill]
|
||||
|
||||
@ -4,10 +4,13 @@
|
||||
$ = (selector, root=d.body) ->
|
||||
root.querySelector selector
|
||||
|
||||
$.DAY = 24 *
|
||||
$.HOUR = 60 *
|
||||
$.MINUTE = 60 *
|
||||
$.DAY = 24 * (
|
||||
$.HOUR = 60 * (
|
||||
$.MINUTE = 60 * (
|
||||
$.SECOND = 1000
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
$.id = (id) ->
|
||||
d.getElementById id
|
||||
@ -60,7 +63,7 @@ $.ajax = do ->
|
||||
$.extend r, options
|
||||
$.extend r.upload, upCallbacks
|
||||
# connection error or content blocker
|
||||
$.on r, 'error', -> c.error "4chan X failed to load: #{url}" unless r.status
|
||||
$.on r, 'error', -> (c.error "4chan X failed to load: #{url}" unless r.status)
|
||||
r.send form
|
||||
catch err
|
||||
# XXX Some content blockers in Firefox (e.g. Adblock Plus and NoScript) throw an exception instead of simulating a connection error.
|
||||
@ -81,7 +84,7 @@ do ->
|
||||
return req
|
||||
rm = -> delete reqs[url]
|
||||
try
|
||||
return unless req = $.ajax url, options
|
||||
return if not (req = $.ajax url, options)
|
||||
catch err
|
||||
return
|
||||
$.on req, 'load', (e) ->
|
||||
@ -456,7 +459,7 @@ do ->
|
||||
items.sync[key] = val for key, val of data when not exceedsQuota(key, val)
|
||||
setSync()
|
||||
else
|
||||
chrome.storage.local.remove (key for key of data when key not of items.local)
|
||||
chrome.storage.local.remove (key for key of data when not (key of items.local))
|
||||
cb?()
|
||||
|
||||
setSync = $.debounce $.SECOND, ->
|
||||
@ -544,7 +547,7 @@ else if GM_deleteValue? or $.hasStorage
|
||||
|
||||
do ->
|
||||
onChange = ({key, newValue}) ->
|
||||
return unless cb = $.syncing[key]
|
||||
return if not (cb = $.syncing[key])
|
||||
if newValue?
|
||||
return if newValue is $.oldValue[key]
|
||||
$.oldValue[key] = newValue
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user