diff --git a/src/Filtering/Anonymize.coffee b/src/Filtering/Anonymize.coffee
index 2a3c211a4..56a6eef7c 100755
--- a/src/Filtering/Anonymize.coffee
+++ b/src/Filtering/Anonymize.coffee
@@ -1,6 +1,6 @@
Anonymize =
init: ->
- return if g.VIEW not in ['index', 'thread', 'archive'] or !Conf['Anonymize']
+ return unless g.VIEW in ['index', 'thread', 'archive'] and Conf['Anonymize']
return @archive() if g.VIEW is 'archive'
Post.callbacks.push
diff --git a/src/Filtering/Filter.coffee b/src/Filtering/Filter.coffee
index 0a33af9fd..0088446e9 100755
--- a/src/Filtering/Filter.coffee
+++ b/src/Filtering/Filter.coffee
@@ -1,7 +1,7 @@
Filter =
filters: {}
init: ->
- return if g.VIEW not in ['index', 'thread'] or !Conf['Filter']
+ return unless g.VIEW in ['index', 'thread'] and Conf['Filter']
unless Conf['Filtered Backlinks']
$.addClass doc, 'hide-backlinks'
@@ -100,10 +100,8 @@ Filter =
node: ->
return if @isClone or @isFetchedQuote
- for key of Filter.filters
- value = Filter[key] @
+ for key of Filter.filters when (value = Filter[key] @) isnt false
# Continue if there's nothing to filter (no tripcode for example).
- continue if value is false
for filter in Filter.filters[key] when result = filter value, @isReply
# Hide
@@ -171,7 +169,7 @@ Filter =
menu:
init: ->
- return if g.VIEW not in ['index', 'thread'] or !Conf['Menu'] or !Conf['Filter']
+ return unless g.VIEW in ['index', 'thread'] and Conf['Menu'] and Conf['Filter']
div = $.el 'div',
textContent: 'Filter'
diff --git a/src/Filtering/Recursive.coffee b/src/Filtering/Recursive.coffee
index 7567f2f61..8a8be01b3 100755
--- a/src/Filtering/Recursive.coffee
+++ b/src/Filtering/Recursive.coffee
@@ -22,10 +22,9 @@ Recursive =
rm: (recursive, post) ->
return unless obj = Recursive.recursives[post.fullID]
- for rec, i in obj.recursives
- if rec is recursive
- obj.recursives.splice i, 1
- obj.args.splice i, 1
+ for rec, i in obj.recursives when rec is recursive
+ obj.recursives.splice i, 1
+ obj.args.splice i, 1
return
apply: (recursive, post, args...) ->
diff --git a/src/General/Build.coffee b/src/General/Build.coffee
index bd9313124..ad60b2e53 100755
--- a/src/General/Build.coffee
+++ b/src/General/Build.coffee
@@ -1,13 +1,12 @@
Build =
staticPath: '//s.4cdn.org/image/'
gifIcon: if window.devicePixelRatio >= 2 then '@2x.gif' else '.gif'
- initPixelRatio: window.devicePixelRatio
spoilerRange: {}
unescape: (text) ->
return text unless text?
text.replace(/<[^>]*>/g, '').replace /&(amp|#039|quot|lt|gt);/g, (c) ->
{'&': '&', ''': "'", '"': '"', '<': '<', '>': '>'}[c]
- shortFilename: (filename, isReply) ->
+ shortFilename: (filename) ->
threshold = 30
ext = filename.match(/\.?[^\.]*$/)[0]
if filename.length - ext.length > threshold
@@ -15,8 +14,8 @@ Build =
else
filename
thumbRotate: do ->
- n = 0
- -> n = (n + 1) % 2
+ t = 0
+ -> t = (if t then 0 else 1)
sameThread: (boardID, threadID) ->
g.VIEW is 'thread' and g.BOARD.ID is boardID and g.THREADID is +threadID
postURL: (boardID, threadID, postID) ->
@@ -83,8 +82,7 @@ Build =
name or= ''
subject or= ''
isOP = postID is threadID
-
- retina = if Build.initPixelRatio >= 2 then '@2x' else ''
+ {staticPath, gifIcon} = Build
### Name Block ###
@@ -92,19 +90,19 @@ Build =
when 'admin', 'admin_highlight'
capcodeClass = ' capcodeAdmin'
capcodeStart = <%= html(' ## Admin') %>
- capcodeIcon = <%= html('
') %>
+ capcodeIcon = <%= html(' ') %>
when 'mod'
capcodeClass = ' capcodeMod'
capcodeStart = <%= html(' ## Mod') %>
- capcodeIcon = <%= html('
') %>
+ capcodeIcon = <%= html(' ') %>
when 'developer'
capcodeClass = ' capcodeDeveloper'
capcodeStart = <%= html(' ## Developer') %>
- capcodeIcon = <%= html('
') %>
+ capcodeIcon = <%= html(' ') %>
when 'manager'
capcodeClass = ' capcodeManager'
capcodeStart = <%= html(' ## Manager') %>
- capcodeIcon = <%= html('
') %>
+ capcodeIcon = <%= html(' ') %>
else
capcodeClass = ''
capcodeStart = <%= html('') %>
@@ -155,7 +153,7 @@ Build =
icons = for type in ['Sticky', 'Closed', 'Archived'] when o["is#{type}"] and !(type is 'Closed' and o.isArchived)
typeLC = type.toLowerCase()
- <%= html('
') %>
+ <%= html(' ') %>
replyLink = if isOP and g.VIEW is 'index'
<%= html(' [Reply]') %>
@@ -181,7 +179,7 @@ Build =
fileCont = if file?.isDeleted
<%= html(
'' +
- '
' +
+ '' +
''
) %>
else if file and boardID is 'f'
@@ -196,9 +194,9 @@ Build =
shortFilename = 'Spoiler Image'
if spoilerRange = Build.spoilerRange[boardID]
# Randomize the spoiler image.
- fileThumb = "//s.4cdn.org/image/spoiler-#{boardID}#{Math.floor 1 + spoilerRange * Math.random()}.png"
+ fileThumb = "#{staticPath}spoiler-#{boardID}#{Math.floor 1 + spoilerRange * Math.random()}.png"
else
- fileThumb = '//s.4cdn.org/image/spoiler.png'
+ fileThumb = "#{staticPath}spoiler.png"
file.twidth = file.theight = 100
else
shortFilename = Build.shortFilename file.name, !isOP
diff --git a/src/General/Config.coffee b/src/General/Config.coffee
index 22e8f798b..cf1a3c681 100755
--- a/src/General/Config.coffee
+++ b/src/General/Config.coffee
@@ -53,7 +53,7 @@ Config =
]
'Comment Expansion': [
true
- 'Add buttons to expand too long comments.'
+ 'Expand Comments that are too long to display on the index. Not applicable with JSON Navigation.'
]
'File Info Formatting': [
true
@@ -118,6 +118,11 @@ Config =
true
'Convert text into links where applicable.'
]
+ 'Link Title': [
+ true
+ 'Replace the link of a supported site with its actual title. Currently Supported: YouTube, Vimeo, SoundCloud, and Github gists'
+ 1
+ ]
'Embedding': [
true
'Embed supported services. Note: Some services don\'t work on HTTPS.'
@@ -133,11 +138,6 @@ Config =
'Embed content in a frame that remains in place when the page is scrolled.'
2
]
- 'Link Title': [
- true
- 'Replace the link of a supported site with its actual title. Currently Supported: YouTube, Vimeo, SoundCloud, and Github gists'
- 1
- ]
'Filtering':
'Anonymize': [
@@ -384,8 +384,8 @@ Config =
'All-in-one form to reply, create threads, automate dumping and more.'
]
'QR Shortcut': [
- true,
- 'Adds a small [QR] link in the header.'
+ true
+ 'Add a shortcut to the header to toggle the QR.'
1
]
'Persistent QR': [
@@ -598,7 +598,7 @@ Config =
]
'Auto Prune': [
false
- 'Automatically prune dead threads.'
+ 'Automatically remove dead threads.'
]
'Show Unread Count': [
true
diff --git a/src/General/Globals.coffee b/src/General/Globals.coffee
index 2f6033615..ad31a194a 100755
--- a/src/General/Globals.coffee
+++ b/src/General/Globals.coffee
@@ -9,6 +9,11 @@ g =
FAQ: '<%= meta.faq %>'
CHANGELOG: '<%= meta.repo %>blob/<%= meta.mainBranch %>/CHANGELOG.md'
boards: {}
-E = (text) ->
- (text+'').replace /[&"'<>]/g, (x) ->
- {'&': '&', "'": ''', '"': '"', '<': '<', '>': '>'}[x]
+
+E = do ->
+ str = {'&': '&', "'": ''', '"': '"', '<': '<', '>': '>'}
+ r = String::replace
+ regex = /[&"'<>]/g
+ fn = (x) ->
+ str[x]
+ (text) -> r.call text, regex, fn
diff --git a/src/General/Main.coffee b/src/General/Main.coffee
index a7ec5e25b..ee2fd9381 100755
--- a/src/General/Main.coffee
+++ b/src/General/Main.coffee
@@ -3,8 +3,8 @@ Main =
if location.hostname is 'www.google.com'
return $.ready -> Captcha.noscript.initFrame()
- g.threads = new SimpleDict
- g.posts = new SimpleDict
+ g.threads = new SimpleDict()
+ g.posts = new SimpleDict()
pathname = location.pathname.split '/'
g.BOARD = new Board pathname[1]
@@ -90,6 +90,7 @@ Main =
error: err
# finally
# c.timeEnd "#{name} initialization"
+
# c.timeEnd 'All initializations'
$.ready Main.initReady
@@ -163,19 +164,19 @@ Main =
Settings.open()
$.set 'previousversion', g.VERSION
- return unless Conf['Show Support Message']
- <% if (type === 'userscript') { %>
- GMver = GM_info.version.split '.'
- for v, i in "<%= meta.min.greasemonkey %>".split '.'
- continue if v is GMver[i]
- (v < GMver[i]) or new Notice 'warning', "Your version of Greasemonkey is outdated (v#{GM_info.version} instead of v<%= meta.min.greasemonkey %> minimum) and <%= meta.name %> may not operate correctly.", 30
- break
- <% } %>
+ if Conf['Show Support Message']
+ <% if (type === 'userscript') { %>
+ GMver = GM_info.version.split '.'
+ for v, i in "<%= meta.min.greasemonkey %>".split '.'
+ continue if v is GMver[i]
+ (v < GMver[i]) or new Notice 'warning', "Your version of Greasemonkey is outdated (v#{GM_info.version} instead of v<%= meta.min.greasemonkey %> minimum) and <%= meta.name %> may not operate correctly.", 30
+ break
+ <% } %>
- try
- localStorage.getItem '4chan-settings'
- catch err
- new Notice 'warning', 'Cookies need to be enabled on 4chan for <%= meta.name %> to operate properly.', 30
+ try
+ localStorage.getItem '4chan-settings'
+ catch err
+ new Notice 'warning', 'Cookies need to be enabled on 4chan for <%= meta.name %> to operate properly.', 30
initThread: ->
if board = $ '.board'
diff --git a/src/General/Settings.coffee b/src/General/Settings.coffee
index 1fc2db46f..c1c41311d 100755
--- a/src/General/Settings.coffee
+++ b/src/General/Settings.coffee
@@ -10,14 +10,16 @@ Settings =
Header.addShortcut link
- Settings.addSection 'Main', Settings.main
- Settings.addSection 'Filter', Settings.filter
- Settings.addSection 'Sauce', Settings.sauce
- Settings.addSection 'Advanced', Settings.advanced
- Settings.addSection 'Keybinds', Settings.keybinds
+ add = @addSection
+
+ add 'Main', @main
+ add 'Filter', @filter
+ add 'Sauce', @sauce
+ add 'Advanced', @advanced
+ add 'Keybinds', @keybinds
$.on d, 'AddSettingsSection', Settings.addSection
- $.on d, 'OpenSettings', (e) -> Settings.open e.detail
+ $.on d, 'OpenSettings', (e) -> Settings.open e.detail
if Conf['Disable Native Extension']
settings = JSON.parse(localStorage.getItem '4chan-settings') or {}
@@ -26,22 +28,22 @@ Settings =
localStorage.setItem '4chan-settings', JSON.stringify settings
open: (openSection) ->
- return if Settings.dialog
+ return if Settings.overlay
$.event 'CloseMenu'
- Settings.overlay = overlay = $.el 'div',
- id: 'overlay'
-
Settings.dialog = dialog = $.el 'div',
id: 'fourchanx-settings'
className: 'dialog'
$.extend dialog, <%= importHTML('Settings/Settings') %>
$('a[href$="/CHANGELOG.md"]', dialog).textContent = g.VERSION
- $.on $('.export', Settings.dialog), 'click', Settings.export
- $.on $('.import', Settings.dialog), 'click', Settings.import
- $.on $('.reset', Settings.dialog), 'click', Settings.reset
- $.on $('input', Settings.dialog), 'change', Settings.onImport
+ Settings.overlay = overlay = $.el 'div',
+ id: 'overlay'
+
+ $.on $('.export', dialog), 'click', Settings.export
+ $.on $('.import', dialog), 'click', Settings.import
+ $.on $('.reset', dialog), 'click', Settings.reset
+ $.on $('input', dialog), 'change', Settings.onImport
links = []
for section in Settings.sections
@@ -54,7 +56,7 @@ Settings =
sectionToOpen = link if section.title is openSection
links.pop()
$.add $('.sections-list', dialog), links
- (if sectionToOpen then sectionToOpen else links[0]).click()
+ (if sectionToOpen then sectionToOpen else links[0]).click() unless openSection is 'none'
$.on $('.close', dialog), 'click', Settings.close
$.on overlay, 'click', Settings.close
@@ -103,8 +105,9 @@ Settings =
div = $.el 'div',
<%= html(': ${description}') %>
input = $ 'input', div
- $.on input, 'change', $.cb.checked
- $.on input, 'change', -> @parentNode.parentNode.dataset.checked = @checked
+ $.on input, 'change', ->
+ @parentNode.parentNode.dataset.checked = @checked
+ $.cb.checked.call @
items[key] = Conf[key]
inputs[key] = input
level = arr[2] or 0
@@ -160,7 +163,7 @@ Settings =
<% } %>
a.click()
import: ->
- $('input', @parentNode).click()
+ $('input[type=file]', @parentNode).click()
onImport: ->
return unless file = @files[0]
@@ -305,17 +308,21 @@ Settings =
items = {}
inputs = {}
for name in ['boardnav', 'time', 'backlink', 'fileInfo', 'favicon', 'usercss']
- input = $ "[name=#{name}]", section
+ input = $ "[name='#{name}']", section
items[name] = Conf[name]
inputs[name] = input
- event = if name in ['favicon', 'usercss']
- 'change'
- else
- 'input'
- $.on input, event, $.cb.value
+ if name is 'usercss'
+ $.on input, 'change', $.cb.value
+ else if name is 'favicon'
+ $.on input, 'change', $.cb.value
+ $.on input, 'change', Settings[name]
+ else
+ $.on input, 'input', $.cb.value
+ $.on input, 'input', Settings[name]
# Quick Reply Personas
ta = $ '.personafield', section
+
$.get 'QR.personas', Conf['QR.personas'], (item) ->
ta.value = item['QR.personas']
$.on ta, 'change', $.cb.value
@@ -325,7 +332,6 @@ Settings =
input = inputs[key]
input.value = val
continue if key is 'usercss'
- $.on input, event, Settings[key]
Settings[key].call input
return
@@ -484,6 +490,7 @@ Settings =
inputs[key] = input
$.on input, 'keydown', Settings.keybind
$.add tbody, tr
+
$.get items, (items) ->
for key, val of items
inputs[key].value = val
diff --git a/src/General/UI.coffee b/src/General/UI.coffee
index b58f27fbe..8ef668b64 100755
--- a/src/General/UI.coffee
+++ b/src/General/UI.coffee
@@ -65,8 +65,7 @@ UI = do ->
$.addClass lastToggledButton, 'active'
- $.on d, 'click', @close
- $.on d, 'CloseMenu', @close
+ $.one d, 'click scroll CloseMenu', @close
$.add button, menu
# Position
@@ -121,7 +120,6 @@ UI = do ->
$.rmClass lastToggledButton, 'active'
currentMenu = null
lastToggledButton = null
- $.off d, 'click CloseMenu', @close
findNextEntry: (entry, direction) ->
entries = [entry.parentNode.children...]
@@ -162,6 +160,7 @@ UI = do ->
onFocus: (e) =>
e.stopPropagation()
@focus e.target
+
focus: (entry) ->
while focused = $.x 'parent::*/child::*[contains(@class,"focused")]', entry
$.rmClass focused, 'focused'
@@ -376,7 +375,6 @@ UI = do ->
$.add label, [input, $.tn " #{text}"]
label
-
return {
dialog: dialog
Menu: Menu
diff --git a/src/General/html/Features/Gallery.html b/src/General/html/Features/Gallery.html
index e8588d256..d52f129dd 100644
--- a/src/General/html/Features/Gallery.html
+++ b/src/General/html/Features/Gallery.html
@@ -6,7 +6,9 @@
×
- /
+
+ /
+