Merge from Appchan X: Whitespace and other changes not affecting compiled script.
This commit is contained in:
parent
1b7cc5270c
commit
8df52a0b24
@ -58,6 +58,7 @@ Redirect =
|
|||||||
protocol = Redirect.protocol archive
|
protocol = Redirect.protocol archive
|
||||||
URL = new String "#{protocol}#{archive.domain}/_/api/chan/post/?board=#{boardID}&num=#{postID}"
|
URL = new String "#{protocol}#{archive.domain}/_/api/chan/post/?board=#{boardID}&num=#{postID}"
|
||||||
return '' unless Redirect.securityCheck URL
|
return '' unless Redirect.securityCheck URL
|
||||||
|
|
||||||
URL.archive = archive
|
URL.archive = archive
|
||||||
URL
|
URL
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@ Anonymize =
|
|||||||
Post.callbacks.push
|
Post.callbacks.push
|
||||||
name: 'Anonymize'
|
name: 'Anonymize'
|
||||||
cb: @node
|
cb: @node
|
||||||
|
|
||||||
node: ->
|
node: ->
|
||||||
return if @info.capcode or @isClone
|
return if @info.capcode or @isClone
|
||||||
{name, tripcode, email} = @nodes
|
{name, tripcode, email} = @nodes
|
||||||
@ -17,6 +18,7 @@ Anonymize =
|
|||||||
if @info.email
|
if @info.email
|
||||||
$.replace email, name
|
$.replace email, name
|
||||||
delete @nodes.email
|
delete @nodes.email
|
||||||
|
|
||||||
archive: ->
|
archive: ->
|
||||||
$.ready ->
|
$.ready ->
|
||||||
name.textContent = 'Anonymous' for name in $$ '.name'
|
name.textContent = 'Anonymous' for name in $$ '.name'
|
||||||
|
|||||||
@ -84,11 +84,13 @@ Filter =
|
|||||||
(value) -> regexp is value
|
(value) -> regexp is value
|
||||||
else
|
else
|
||||||
(value) -> regexp.test value
|
(value) -> regexp.test value
|
||||||
|
|
||||||
settings =
|
settings =
|
||||||
hide: !hl
|
hide: !hl
|
||||||
stub: stub
|
stub: stub
|
||||||
class: hl
|
class: hl
|
||||||
top: top
|
top: top
|
||||||
|
|
||||||
(value, isReply) ->
|
(value, isReply) ->
|
||||||
if isReply and op is 'only' or !isReply and op is 'no'
|
if isReply and op is 'only' or !isReply and op is 'no'
|
||||||
return false
|
return false
|
||||||
@ -103,10 +105,7 @@ Filter =
|
|||||||
# Continue if there's nothing to filter (no tripcode for example).
|
# Continue if there's nothing to filter (no tripcode for example).
|
||||||
continue if value is false
|
continue if value is false
|
||||||
|
|
||||||
for filter in Filter.filters[key]
|
for filter in Filter.filters[key] when result = filter value, @isReply
|
||||||
unless result = filter value, @isReply
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Hide
|
# Hide
|
||||||
if result.hide
|
if result.hide
|
||||||
if @isReply
|
if @isReply
|
||||||
|
|||||||
@ -12,12 +12,14 @@ PostHiding =
|
|||||||
|
|
||||||
node: ->
|
node: ->
|
||||||
return if !@isReply or @isClone or @isFetchedQuote
|
return if !@isReply or @isClone or @isFetchedQuote
|
||||||
|
|
||||||
if data = PostHiding.db.get {boardID: @board.ID, threadID: @thread.ID, postID: @ID}
|
if data = PostHiding.db.get {boardID: @board.ID, threadID: @thread.ID, postID: @ID}
|
||||||
if data.thisPost
|
if data.thisPost
|
||||||
PostHiding.hide @, data.makeStub, data.hideRecursively
|
PostHiding.hide @, data.makeStub, data.hideRecursively
|
||||||
else
|
else
|
||||||
Recursive.apply PostHiding.hide, @, data.makeStub, true
|
Recursive.apply PostHiding.hide, @, data.makeStub, true
|
||||||
Recursive.add PostHiding.hide, @, data.makeStub, true
|
Recursive.add PostHiding.hide, @, data.makeStub, true
|
||||||
|
|
||||||
return unless Conf['Reply Hiding Buttons']
|
return unless Conf['Reply Hiding Buttons']
|
||||||
sideArrows = $('.sideArrows', @nodes.root)
|
sideArrows = $('.sideArrows', @nodes.root)
|
||||||
$.replace sideArrows.firstChild, PostHiding.makeButton @, 'hide'
|
$.replace sideArrows.firstChild, PostHiding.makeButton @, 'hide'
|
||||||
|
|||||||
@ -1,18 +1,16 @@
|
|||||||
Recursive =
|
Recursive =
|
||||||
recursives: {}
|
recursives: {}
|
||||||
init: ->
|
init: ->
|
||||||
return if g.VIEW not in ['index', 'thread']
|
return unless g.VIEW in ['index', 'thread']
|
||||||
|
|
||||||
Post.callbacks.push
|
Post.callbacks.push
|
||||||
name: 'Recursive'
|
name: 'Recursive'
|
||||||
cb: @node
|
cb: @node
|
||||||
|
|
||||||
node: ->
|
node: ->
|
||||||
return if @isClone or @isFetchedQuote
|
return if @isClone or @isFetchedQuote
|
||||||
for quote in @quotes
|
for quote in @quotes when obj = Recursive.recursives[quote]
|
||||||
if obj = Recursive.recursives[quote]
|
for recursive, i in obj.recursives
|
||||||
for recursive, i in obj.recursives
|
recursive @, obj.args[i]...
|
||||||
recursive @, obj.args[i]...
|
|
||||||
return
|
return
|
||||||
|
|
||||||
add: (recursive, post, args...) ->
|
add: (recursive, post, args...) ->
|
||||||
|
|||||||
@ -334,6 +334,7 @@ Build =
|
|||||||
|
|
||||||
root = $.el 'div',
|
root = $.el 'div',
|
||||||
className: 'catalog-thread'
|
className: 'catalog-thread'
|
||||||
|
|
||||||
$.extend root, <%= html(
|
$.extend root, <%= html(
|
||||||
'<a href="/${thread.board}/thread/${thread.ID}">' +
|
'<a href="/${thread.board}/thread/${thread.ID}">' +
|
||||||
'&{thumb}' +
|
'&{thumb}' +
|
||||||
@ -352,12 +353,15 @@ Build =
|
|||||||
for quote in $$ '.quotelink', root.lastElementChild
|
for quote in $$ '.quotelink', root.lastElementChild
|
||||||
href = quote.getAttribute 'href'
|
href = quote.getAttribute 'href'
|
||||||
quote.href = "/#{thread.board}/thread/#{thread.ID}" + href if href[0] is '#'
|
quote.href = "/#{thread.board}/thread/#{thread.ID}" + href if href[0] is '#'
|
||||||
|
|
||||||
for exif in $$ '.abbr, .exif', root.lastElementChild
|
for exif in $$ '.abbr, .exif', root.lastElementChild
|
||||||
$.rm exif
|
$.rm exif
|
||||||
|
|
||||||
for pp in $$ '.prettyprint', root.lastElementChild
|
for pp in $$ '.prettyprint', root.lastElementChild
|
||||||
cc = $.el 'span', className: 'catalog-code'
|
cc = $.el 'span', className: 'catalog-code'
|
||||||
$.add cc, [pp.childNodes...]
|
$.add cc, [pp.childNodes...]
|
||||||
$.replace pp, cc
|
$.replace pp, cc
|
||||||
|
|
||||||
for br in $$ 'br', root.lastElementChild when br.previousSibling?.nodeName is 'BR'
|
for br in $$ 'br', root.lastElementChild when br.previousSibling?.nodeName is 'BR'
|
||||||
$.rm br
|
$.rm br
|
||||||
|
|
||||||
@ -366,6 +370,7 @@ Build =
|
|||||||
src: "#{staticPath}sticky#{gifIcon}"
|
src: "#{staticPath}sticky#{gifIcon}"
|
||||||
className: 'stickyIcon'
|
className: 'stickyIcon'
|
||||||
title: 'Sticky'
|
title: 'Sticky'
|
||||||
|
|
||||||
if thread.isClosed
|
if thread.isClosed
|
||||||
$.add $('.catalog-icons', root), $.el 'img',
|
$.add $('.catalog-icons', root), $.el 'img',
|
||||||
src: "#{staticPath}closed#{gifIcon}"
|
src: "#{staticPath}closed#{gifIcon}"
|
||||||
@ -374,6 +379,7 @@ Build =
|
|||||||
|
|
||||||
if data.bumplimit
|
if data.bumplimit
|
||||||
$.addClass $('.post-count', root), 'warning'
|
$.addClass $('.post-count', root), 'warning'
|
||||||
|
|
||||||
if data.imagelimit
|
if data.imagelimit
|
||||||
$.addClass $('.file-count', root), 'warning'
|
$.addClass $('.file-count', root), 'warning'
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
Config =
|
Config =
|
||||||
main:
|
main:
|
||||||
'Miscellaneous':
|
'Miscellaneous':
|
||||||
'JSON Navigation' : [
|
'JSON Navigation': [
|
||||||
true
|
true
|
||||||
'Replace the original board index with one supporting searching, sorting, infinite scrolling, and a catalog mode.'
|
'Replace the original board index with one supporting searching, sorting, infinite scrolling, and a catalog mode.'
|
||||||
]
|
]
|
||||||
@ -112,6 +112,7 @@ Config =
|
|||||||
true
|
true
|
||||||
'<%= meta.name %> is NOT designed to work with the native extension.'
|
'<%= meta.name %> is NOT designed to work with the native extension.'
|
||||||
]
|
]
|
||||||
|
|
||||||
'Linkification':
|
'Linkification':
|
||||||
'Linkify': [
|
'Linkify': [
|
||||||
true
|
true
|
||||||
@ -587,69 +588,69 @@ Config =
|
|||||||
|
|
||||||
filter:
|
filter:
|
||||||
name: """
|
name: """
|
||||||
# Filter any namefags:
|
# Filter any namefags:
|
||||||
#/^(?!Anonymous$)/
|
#/^(?!Anonymous$)/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
uniqueID: """
|
uniqueID: """
|
||||||
# Filter a specific ID:
|
# Filter a specific ID:
|
||||||
#/Txhvk1Tl/
|
#/Txhvk1Tl/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
tripcode: """
|
tripcode: """
|
||||||
# Filter any tripfag
|
# Filter any tripfag
|
||||||
#/^!/
|
#/^!/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
capcode: """
|
capcode: """
|
||||||
# Set a custom class for mods:
|
# Set a custom class for mods:
|
||||||
#/Mod$/;highlight:mod;op:yes
|
#/Mod$/;highlight:mod;op:yes
|
||||||
# Set a custom class for moot:
|
# Set a custom class for moot:
|
||||||
#/Admin$/;highlight:moot;op:yes
|
#/Admin$/;highlight:moot;op:yes
|
||||||
"""
|
"""
|
||||||
|
|
||||||
subject: """
|
subject: """
|
||||||
# Filter Generals on /v/:
|
# Filter Generals on /v/:
|
||||||
#/general/i;boards:v;op:only
|
#/general/i;boards:v;op:only
|
||||||
"""
|
"""
|
||||||
|
|
||||||
comment: """
|
comment: """
|
||||||
# Filter Stallman copypasta on /g/:
|
# Filter Stallman copypasta on /g/:
|
||||||
#/what you\'re refer+ing to as linux/i;boards:g
|
#/what you\'re refer+ing to as linux/i;boards:g
|
||||||
"""
|
"""
|
||||||
|
|
||||||
flag: ''
|
flag: ''
|
||||||
filename: ''
|
filename: ''
|
||||||
dimensions: """
|
dimensions: """
|
||||||
# Highlight potential wallpapers:
|
# Highlight potential wallpapers:
|
||||||
#/1920x1080/;op:yes;highlight;top:no;boards:w,wg
|
#/1920x1080/;op:yes;highlight;top:no;boards:w,wg
|
||||||
"""
|
"""
|
||||||
|
|
||||||
filesize: ''
|
filesize: ''
|
||||||
|
|
||||||
MD5: ''
|
MD5: ''
|
||||||
|
|
||||||
sauces: """
|
sauces: """
|
||||||
https://www.google.com/searchbyimage?image_url=%TURL
|
https://www.google.com/searchbyimage?image_url=%TURL
|
||||||
http://iqdb.org/?url=%TURL
|
http://iqdb.org/?url=%TURL
|
||||||
#//tineye.com/search?url=%TURL
|
#//tineye.com/search?url=%TURL
|
||||||
#//saucenao.com/search.php?url=%TURL
|
#//saucenao.com/search.php?url=%TURL
|
||||||
#http://3d.iqdb.org/?url=%TURL
|
#http://3d.iqdb.org/?url=%TURL
|
||||||
#http://regex.info/exif.cgi?imgurl=%URL
|
#http://regex.info/exif.cgi?imgurl=%URL
|
||||||
# uploaders:
|
# uploaders:
|
||||||
#//imgur.com/upload?url=%URL;text:Upload to imgur
|
#//imgur.com/upload?url=%URL;text:Upload to imgur
|
||||||
# "View Same" in archives:
|
# "View Same" in archives:
|
||||||
#https://archive.moe/_/search/image/%MD5/;text:View same on archive.moe
|
#https://archive.moe/_/search/image/%MD5/;text:View same on archive.moe
|
||||||
#https://archive.moe/%board/search/image/%MD5/;text:View same on archive.moe/%board/;boards:<%=
|
#https://archive.moe/%board/search/image/%MD5/;text:View same on archive.moe/%board/;boards:<%=
|
||||||
grunt.file.readJSON('src/Archive/archives.json').filter(function(x) {return x.uid === 0})[0].files.join(',')
|
grunt.file.readJSON('src/Archive/archives.json').filter(function(x) {return x.uid === 0})[0].files.join(',')
|
||||||
%>
|
%>
|
||||||
#https://rbt.asia/%board/image/%MD5;text:View same on RBT /%board/;boards:<%=
|
#https://rbt.asia/%board/image/%MD5;text:View same on RBT /%board/;boards:<%=
|
||||||
grunt.file.readJSON('src/Archive/archives.json').filter(function(x) {return x.uid === 8})[0].files.join(',')
|
grunt.file.readJSON('src/Archive/archives.json').filter(function(x) {return x.uid === 8})[0].files.join(',')
|
||||||
%>
|
%>
|
||||||
# Search with full image only for image file types:
|
# Search with full image only for image file types:
|
||||||
#https://www.google.com/searchbyimage?image_url=%URL;types:gif,jpg,png
|
#https://www.google.com/searchbyimage?image_url=%URL;types:gif,jpg,png
|
||||||
#https://www.google.com/searchbyimage?image_url=%TURL;types:webm,pdf
|
#https://www.google.com/searchbyimage?image_url=%TURL;types:webm,pdf
|
||||||
"""
|
"""
|
||||||
|
|
||||||
FappeT:
|
FappeT:
|
||||||
werk: false
|
werk: false
|
||||||
@ -678,29 +679,29 @@ http://iqdb.org/?url=%TURL
|
|||||||
'Custom Board Navigation': true
|
'Custom Board Navigation': true
|
||||||
|
|
||||||
boardnav: """
|
boardnav: """
|
||||||
[ toggle-all ]
|
[ toggle-all ]
|
||||||
a-replace
|
a-replace
|
||||||
c-replace
|
c-replace
|
||||||
g-replace
|
g-replace
|
||||||
k-replace
|
k-replace
|
||||||
v-replace
|
v-replace
|
||||||
vg-replace
|
vg-replace
|
||||||
vr-replace
|
vr-replace
|
||||||
ck-replace
|
ck-replace
|
||||||
co-replace
|
co-replace
|
||||||
fit-replace
|
fit-replace
|
||||||
jp-replace
|
jp-replace
|
||||||
mu-replace
|
mu-replace
|
||||||
sp-replace
|
sp-replace
|
||||||
tv-replace
|
tv-replace
|
||||||
vp-replace
|
vp-replace
|
||||||
[external-text:"FAQ","<%= meta.faq %>"]
|
[external-text:"FAQ","<%= meta.faq %>"]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
QR:
|
QR:
|
||||||
'QR.personas': """
|
'QR.personas': """
|
||||||
#options:"sage";boards:jp;always
|
#options:"sage";boards:jp;always
|
||||||
"""
|
"""
|
||||||
|
|
||||||
time: '%m/%d/%y(%a)%H:%M:%S'
|
time: '%m/%d/%y(%a)%H:%M:%S'
|
||||||
|
|
||||||
|
|||||||
@ -51,7 +51,7 @@ Get =
|
|||||||
# get all their backlinks.
|
# get all their backlinks.
|
||||||
posts.forEach (qPost) ->
|
posts.forEach (qPost) ->
|
||||||
if fullID in qPost.quotes
|
if fullID in qPost.quotes
|
||||||
handleQuotes qPost, 'quotelinks'
|
handleQuotes qPost, 'quotelinks'
|
||||||
|
|
||||||
# Second:
|
# Second:
|
||||||
# If we have quote backlinks:
|
# If we have quote backlinks:
|
||||||
@ -66,10 +66,12 @@ Get =
|
|||||||
quotelinks.filter (quotelink) ->
|
quotelinks.filter (quotelink) ->
|
||||||
{boardID, postID} = Get.postDataFromLink quotelink
|
{boardID, postID} = Get.postDataFromLink quotelink
|
||||||
boardID is post.board.ID and postID is post.ID
|
boardID is post.board.ID and postID is post.ID
|
||||||
|
|
||||||
scriptData: ->
|
scriptData: ->
|
||||||
for script in $$ 'script:not([src])', d.head
|
for script in $$ 'script:not([src])', d.head
|
||||||
return script.textContent if /\bcooldowns *=/.test script.textContent
|
return script.textContent if /\bcooldowns *=/.test script.textContent
|
||||||
''
|
''
|
||||||
|
|
||||||
postClone: (boardID, threadID, postID, root, context) ->
|
postClone: (boardID, threadID, postID, root, context) ->
|
||||||
if post = g.posts["#{boardID}.#{postID}"]
|
if post = g.posts["#{boardID}.#{postID}"]
|
||||||
Get.insert post, root, context
|
Get.insert post, root, context
|
||||||
@ -81,6 +83,7 @@ Get =
|
|||||||
Get.fetchedPost @, boardID, threadID, postID, root, context
|
Get.fetchedPost @, boardID, threadID, postID, root, context
|
||||||
else
|
else
|
||||||
Get.archivedPost boardID, postID, root, context
|
Get.archivedPost boardID, postID, root, context
|
||||||
|
|
||||||
insert: (post, root, context) ->
|
insert: (post, root, context) ->
|
||||||
# Stop here if the container has been removed while loading.
|
# Stop here if the container has been removed while loading.
|
||||||
return unless root.parentNode
|
return unless root.parentNode
|
||||||
@ -95,6 +98,7 @@ Get =
|
|||||||
$.rmAll root
|
$.rmAll root
|
||||||
$.add root, nodes.root
|
$.add root, nodes.root
|
||||||
$.event 'PostsInserted'
|
$.event 'PostsInserted'
|
||||||
|
|
||||||
fetchedPost: (req, boardID, threadID, postID, root, context) ->
|
fetchedPost: (req, boardID, threadID, postID, root, context) ->
|
||||||
# In case of multiple callbacks for the same request,
|
# In case of multiple callbacks for the same request,
|
||||||
# don't parse the same original post more than once.
|
# don't parse the same original post more than once.
|
||||||
@ -127,6 +131,7 @@ Get =
|
|||||||
$.cache api, ->
|
$.cache api, ->
|
||||||
Get.fetchedPost @, boardID, threadID, postID, root, context
|
Get.fetchedPost @, boardID, threadID, postID, root, context
|
||||||
return
|
return
|
||||||
|
|
||||||
# The post can be deleted by the time we check a quote.
|
# The post can be deleted by the time we check a quote.
|
||||||
unless Get.archivedPost boardID, postID, root, context
|
unless Get.archivedPost boardID, postID, root, context
|
||||||
$.addClass root, 'warning'
|
$.addClass root, 'warning'
|
||||||
@ -141,6 +146,7 @@ Get =
|
|||||||
post.isFetchedQuote = true
|
post.isFetchedQuote = true
|
||||||
Main.callbackNodes Post, [post]
|
Main.callbackNodes Post, [post]
|
||||||
Get.insert post, root, context
|
Get.insert post, root, context
|
||||||
|
|
||||||
archivedPost: (boardID, postID, root, context) ->
|
archivedPost: (boardID, postID, root, context) ->
|
||||||
return false unless Conf['Resurrect Quotes']
|
return false unless Conf['Resurrect Quotes']
|
||||||
return false unless url = Redirect.to 'post', {boardID, postID}
|
return false unless url = Redirect.to 'post', {boardID, postID}
|
||||||
@ -161,6 +167,7 @@ Get =
|
|||||||
Get.parseArchivedPost response, boardID, postID, root, context
|
Get.parseArchivedPost response, boardID, postID, root, context
|
||||||
return true
|
return true
|
||||||
return false
|
return false
|
||||||
|
|
||||||
parseArchivedPost: (data, boardID, postID, root, context) ->
|
parseArchivedPost: (data, boardID, postID, root, context) ->
|
||||||
# In case of multiple callbacks for the same request,
|
# In case of multiple callbacks for the same request,
|
||||||
# don't parse the same original post more than once.
|
# don't parse the same original post more than once.
|
||||||
|
|||||||
@ -143,7 +143,10 @@ Header =
|
|||||||
$.extend boardList, <%= html(
|
$.extend boardList, <%= html(
|
||||||
'<span id="custom-board-list"></span>' +
|
'<span id="custom-board-list"></span>' +
|
||||||
'<span id="full-board-list" hidden>' +
|
'<span id="full-board-list" hidden>' +
|
||||||
'<span class="hide-board-list-container brackets-wrap"><a href="javascript:;" class="hide-board-list-button"> - </a></span> ' +
|
'<span class="hide-board-list-container brackets-wrap">' +
|
||||||
|
'<a href="javascript:;" class="hide-board-list-button"> - </a>' +
|
||||||
|
'</span>' +
|
||||||
|
' ' +
|
||||||
'<span class="boardList"></span>' +
|
'<span class="boardList"></span>' +
|
||||||
'</span>'
|
'</span>'
|
||||||
) %>
|
) %>
|
||||||
@ -185,11 +188,13 @@ Header =
|
|||||||
nodes = boardnav.match(/[\w@]+(-(all|title|replace|full|index|catalog|archive|expired|text:"[^"]+"(,"[^"]+")?))*|[^\w@]+/g).map (t) ->
|
nodes = boardnav.match(/[\w@]+(-(all|title|replace|full|index|catalog|archive|expired|text:"[^"]+"(,"[^"]+")?))*|[^\w@]+/g).map (t) ->
|
||||||
if /^[^\w@]/.test t
|
if /^[^\w@]/.test t
|
||||||
return $.tn t
|
return $.tn t
|
||||||
|
|
||||||
text = url = null
|
text = url = null
|
||||||
t = t.replace /-text:"([^"]+)"(?:,"([^"]+)")?/g, (m0, m1, m2) ->
|
t = t.replace /-text:"([^"]+)"(?:,"([^"]+)")?/g, (m0, m1, m2) ->
|
||||||
text = m1
|
text = m1
|
||||||
url = m2
|
url = m2
|
||||||
''
|
''
|
||||||
|
|
||||||
if /^toggle-all/.test t
|
if /^toggle-all/.test t
|
||||||
a = $.el 'a',
|
a = $.el 'a',
|
||||||
className: 'show-board-list-button'
|
className: 'show-board-list-button'
|
||||||
@ -197,12 +202,14 @@ Header =
|
|||||||
href: 'javascript:;'
|
href: 'javascript:;'
|
||||||
$.on a, 'click', Header.toggleBoardList
|
$.on a, 'click', Header.toggleBoardList
|
||||||
return a
|
return a
|
||||||
|
|
||||||
if /^external/.test t
|
if /^external/.test t
|
||||||
a = $.el 'a',
|
a = $.el 'a',
|
||||||
href: url or 'javascript:;'
|
href: url or 'javascript:;'
|
||||||
textContent: text or '+'
|
textContent: text or '+'
|
||||||
className: 'external'
|
className: 'external'
|
||||||
return a
|
return a
|
||||||
|
|
||||||
boardID = if /^current/.test t
|
boardID = if /^current/.test t
|
||||||
g.BOARD.ID
|
g.BOARD.ID
|
||||||
else
|
else
|
||||||
@ -411,7 +418,6 @@ Header =
|
|||||||
hash = @location.hash[1..]
|
hash = @location.hash[1..]
|
||||||
return unless /^p\d+$/.test(hash) and post = $.id hash
|
return unless /^p\d+$/.test(hash) and post = $.id hash
|
||||||
return if (Get.postFromRoot post).isHidden
|
return if (Get.postFromRoot post).isHidden
|
||||||
|
|
||||||
Header.scrollTo post
|
Header.scrollTo post
|
||||||
|
|
||||||
scrollTo: (root, down, needed) ->
|
scrollTo: (root, down, needed) ->
|
||||||
@ -451,10 +457,12 @@ Header =
|
|||||||
headRect = Header.toggle.getBoundingClientRect()
|
headRect = Header.toggle.getBoundingClientRect()
|
||||||
bottom -= clientHeight - headRect.bottom + headRect.height
|
bottom -= clientHeight - headRect.bottom + headRect.height
|
||||||
bottom
|
bottom
|
||||||
|
|
||||||
isNodeVisible: (node) ->
|
isNodeVisible: (node) ->
|
||||||
return false if d.hidden or !doc.contains node
|
return false if d.hidden or !doc.contains node
|
||||||
{height} = node.getBoundingClientRect()
|
{height} = node.getBoundingClientRect()
|
||||||
Header.getTopOf(node) + height >= 0 and Header.getBottomOf(node) + height >= 0
|
Header.getTopOf(node) + height >= 0 and Header.getBottomOf(node) + height >= 0
|
||||||
|
|
||||||
isHidden: ->
|
isHidden: ->
|
||||||
{top} = Header.bar.getBoundingClientRect()
|
{top} = Header.bar.getBoundingClientRect()
|
||||||
if Conf['Bottom header']
|
if Conf['Bottom header']
|
||||||
|
|||||||
@ -161,6 +161,7 @@ Index =
|
|||||||
|
|
||||||
catalogNode: ->
|
catalogNode: ->
|
||||||
$.on @nodes.thumb.parentNode, 'click', Index.onClick
|
$.on @nodes.thumb.parentNode, 'click', Index.onClick
|
||||||
|
|
||||||
onClick: (e) ->
|
onClick: (e) ->
|
||||||
return if e.button isnt 0
|
return if e.button isnt 0
|
||||||
thread = g.threads[@parentNode.dataset.fullID]
|
thread = g.threads[@parentNode.dataset.fullID]
|
||||||
@ -169,6 +170,7 @@ Index =
|
|||||||
else
|
else
|
||||||
return
|
return
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
||||||
toggleHide: (thread) ->
|
toggleHide: (thread) ->
|
||||||
$.rm thread.catalogView.nodes.root
|
$.rm thread.catalogView.nodes.root
|
||||||
if Index.showHiddenThreads
|
if Index.showHiddenThreads
|
||||||
@ -178,6 +180,7 @@ Index =
|
|||||||
else
|
else
|
||||||
ThreadHiding.hide thread
|
ThreadHiding.hide thread
|
||||||
ThreadHiding.saveHiddenState thread
|
ThreadHiding.saveHiddenState thread
|
||||||
|
|
||||||
cycleSortType: ->
|
cycleSortType: ->
|
||||||
types = [Index.selectSort.options...].filter (option) -> !option.disabled
|
types = [Index.selectSort.options...].filter (option) -> !option.disabled
|
||||||
for type, i in types
|
for type, i in types
|
||||||
@ -193,15 +196,18 @@ Index =
|
|||||||
'Show'
|
'Show'
|
||||||
Index.sort()
|
Index.sort()
|
||||||
Index.buildIndex()
|
Index.buildIndex()
|
||||||
|
|
||||||
mode: ->
|
mode: ->
|
||||||
mode = @value
|
mode = @value
|
||||||
unless mode is 'catalog'
|
unless mode is 'catalog'
|
||||||
Conf['Previous Index Mode'] = mode
|
Conf['Previous Index Mode'] = mode
|
||||||
$.set 'Previous Index Mode', mode
|
$.set 'Previous Index Mode', mode
|
||||||
Index.pageLoad Index.pushState {mode}
|
Index.pageLoad Index.pushState {mode}
|
||||||
|
|
||||||
sort: ->
|
sort: ->
|
||||||
Index.sort()
|
Index.sort()
|
||||||
Index.buildIndex()
|
Index.buildIndex()
|
||||||
|
|
||||||
size: (e) ->
|
size: (e) ->
|
||||||
if Conf['Index Mode'] isnt 'catalog'
|
if Conf['Index Mode'] isnt 'catalog'
|
||||||
$.rmClass Index.root, 'catalog-small'
|
$.rmClass Index.root, 'catalog-small'
|
||||||
@ -213,10 +219,12 @@ Index =
|
|||||||
$.addClass Index.root, 'catalog-large'
|
$.addClass Index.root, 'catalog-large'
|
||||||
$.rmClass Index.root, 'catalog-small'
|
$.rmClass Index.root, 'catalog-small'
|
||||||
Index.buildIndex() if e
|
Index.buildIndex() if e
|
||||||
|
|
||||||
replies: ->
|
replies: ->
|
||||||
Index.buildThreads()
|
Index.buildThreads()
|
||||||
Index.sort()
|
Index.sort()
|
||||||
Index.buildIndex()
|
Index.buildIndex()
|
||||||
|
|
||||||
popstate: (e) ->
|
popstate: (e) ->
|
||||||
if e?.state
|
if e?.state
|
||||||
{search, mode} = e.state
|
{search, mode} = e.state
|
||||||
@ -236,6 +244,7 @@ Index =
|
|||||||
scroll: true
|
scroll: true
|
||||||
if state.command
|
if state.command
|
||||||
Index[if Conf['Refreshed Navigation'] then 'update' else 'pageLoad'] state
|
Index[if Conf['Refreshed Navigation'] then 'update' else 'pageLoad'] state
|
||||||
|
|
||||||
pageNav: (e) ->
|
pageNav: (e) ->
|
||||||
return if e.shiftKey or e.altKey or e.ctrlKey or e.metaKey or e.button isnt 0
|
return if e.shiftKey or e.altKey or e.ctrlKey or e.metaKey or e.button isnt 0
|
||||||
switch e.target.nodeName
|
switch e.target.nodeName
|
||||||
@ -249,6 +258,7 @@ Index =
|
|||||||
return if a.textContent is 'Catalog'
|
return if a.textContent is 'Catalog'
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
Index.userPageNav +a.pathname.split('/')[2] or 1
|
Index.userPageNav +a.pathname.split('/')[2] or 1
|
||||||
|
|
||||||
frontPage: (e) ->
|
frontPage: (e) ->
|
||||||
return if e.shiftKey or e.altKey or e.ctrlKey or e.metaKey or e.button isnt 0
|
return if e.shiftKey or e.altKey or e.ctrlKey or e.metaKey or e.button isnt 0
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
@ -262,12 +272,14 @@ Index =
|
|||||||
1
|
1
|
||||||
else
|
else
|
||||||
+window.location.pathname.split('/')[2] or 1
|
+window.location.pathname.split('/')[2] or 1
|
||||||
|
|
||||||
userPageNav: (page, noRefresh) ->
|
userPageNav: (page, noRefresh) ->
|
||||||
state = Index.pushState {page, scroll: true}
|
state = Index.pushState {page, scroll: true}
|
||||||
if Conf['Refreshed Navigation'] and !noRefresh
|
if Conf['Refreshed Navigation'] and !noRefresh
|
||||||
Index.update state
|
Index.update state
|
||||||
else
|
else
|
||||||
Index.pageLoad state if state.page
|
Index.pageLoad state if state.page
|
||||||
|
|
||||||
pushState: (state) ->
|
pushState: (state) ->
|
||||||
{pathname, hash} = location
|
{pathname, hash} = location
|
||||||
pageBeforeSearch = history.state?.oldpage
|
pageBeforeSearch = history.state?.oldpage
|
||||||
@ -309,6 +321,7 @@ Index =
|
|||||||
oldpage: pageBeforeSearch
|
oldpage: pageBeforeSearch
|
||||||
, '', pathname + hash
|
, '', pathname + hash
|
||||||
state
|
state
|
||||||
|
|
||||||
pageLoad: ({sort, search, mode, scroll}) ->
|
pageLoad: ({sort, search, mode, scroll}) ->
|
||||||
if sort or search?
|
if sort or search?
|
||||||
Index.sort()
|
Index.sort()
|
||||||
@ -318,6 +331,7 @@ Index =
|
|||||||
Index.buildIndex()
|
Index.buildIndex()
|
||||||
Index.setPage()
|
Index.setPage()
|
||||||
Index.scrollToIndex() if scroll
|
Index.scrollToIndex() if scroll
|
||||||
|
|
||||||
applyMode: ->
|
applyMode: ->
|
||||||
for mode in ['paged', 'infinite', 'all pages', 'catalog']
|
for mode in ['paged', 'infinite', 'all pages', 'catalog']
|
||||||
$[if mode is Conf['Index Mode'] then 'addClass' else 'rmClass'] doc, "#{mode.replace /\ /g, '-'}-mode"
|
$[if mode is Conf['Index Mode'] then 'addClass' else 'rmClass'] doc, "#{mode.replace /\ /g, '-'}-mode"
|
||||||
@ -331,8 +345,10 @@ Index =
|
|||||||
Math.ceil Index.sortedNodes.length / Index.threadsNumPerPage
|
Math.ceil Index.sortedNodes.length / Index.threadsNumPerPage
|
||||||
else
|
else
|
||||||
Index.pagesNum
|
Index.pagesNum
|
||||||
|
|
||||||
getMaxPageNum: ->
|
getMaxPageNum: ->
|
||||||
Math.max 1, Index.getPagesNum()
|
Math.max 1, Index.getPagesNum()
|
||||||
|
|
||||||
buildPagelist: ->
|
buildPagelist: ->
|
||||||
pagesRoot = $ '.pages', Index.pagelist
|
pagesRoot = $ '.pages', Index.pagelist
|
||||||
maxPageNum = Index.getMaxPageNum()
|
maxPageNum = Index.getMaxPageNum()
|
||||||
@ -345,10 +361,12 @@ Index =
|
|||||||
nodes.push $.tn('['), a, $.tn '] '
|
nodes.push $.tn('['), a, $.tn '] '
|
||||||
$.rmAll pagesRoot
|
$.rmAll pagesRoot
|
||||||
$.add pagesRoot, nodes
|
$.add pagesRoot, nodes
|
||||||
|
|
||||||
setPage: ->
|
setPage: ->
|
||||||
pageNum = Index.getCurrentPage()
|
pageNum = Index.getCurrentPage()
|
||||||
maxPageNum = Index.getMaxPageNum()
|
maxPageNum = Index.getMaxPageNum()
|
||||||
pagesRoot = $ '.pages', Index.pagelist
|
pagesRoot = $ '.pages', Index.pagelist
|
||||||
|
|
||||||
# Previous/Next buttons
|
# Previous/Next buttons
|
||||||
prev = pagesRoot.previousSibling.firstChild
|
prev = pagesRoot.previousSibling.firstChild
|
||||||
next = pagesRoot.nextSibling.firstChild
|
next = pagesRoot.nextSibling.firstChild
|
||||||
@ -358,12 +376,14 @@ Index =
|
|||||||
href = Math.min pageNum + 1, maxPageNum
|
href = Math.min pageNum + 1, maxPageNum
|
||||||
next.href = if href is 1 then './' else href
|
next.href = if href is 1 then './' else href
|
||||||
next.firstChild.disabled = href is pageNum
|
next.firstChild.disabled = href is pageNum
|
||||||
|
|
||||||
# <strong> current page
|
# <strong> current page
|
||||||
if strong = $ 'strong', pagesRoot
|
if strong = $ 'strong', pagesRoot
|
||||||
return if +strong.textContent is pageNum
|
return if +strong.textContent is pageNum
|
||||||
$.replace strong, strong.firstChild
|
$.replace strong, strong.firstChild
|
||||||
else
|
else
|
||||||
strong = $.el 'strong'
|
strong = $.el 'strong'
|
||||||
|
|
||||||
a = pagesRoot.children[pageNum - 1]
|
a = pagesRoot.children[pageNum - 1]
|
||||||
$.before a, strong
|
$.before a, strong
|
||||||
$.add strong, a
|
$.add strong, a
|
||||||
|
|||||||
@ -33,10 +33,13 @@ Main =
|
|||||||
else # string or number
|
else # string or number
|
||||||
Conf[parent] = obj
|
Conf[parent] = obj
|
||||||
return
|
return
|
||||||
|
|
||||||
flatten null, Config
|
flatten null, Config
|
||||||
|
|
||||||
for db in DataBoard.keys
|
for db in DataBoard.keys
|
||||||
Conf[db] = boards: {}
|
Conf[db] = boards: {}
|
||||||
Conf['selectedArchives'] = {}
|
Conf['selectedArchives'] = {}
|
||||||
|
|
||||||
$.get Conf, (items) ->
|
$.get Conf, (items) ->
|
||||||
$.extend Conf, items
|
$.extend Conf, items
|
||||||
$.asap (-> doc = d.documentElement), Main.initFeatures
|
$.asap (-> doc = d.documentElement), Main.initFeatures
|
||||||
@ -71,7 +74,7 @@ Main =
|
|||||||
pathname = location.pathname.split '/'
|
pathname = location.pathname.split '/'
|
||||||
if pathname[2] isnt 'thread' or pathname.length > 4
|
if pathname[2] isnt 'thread' or pathname.length > 4
|
||||||
pathname[2] = 'thread'
|
pathname[2] = 'thread'
|
||||||
history.replaceState null, '', pathname.slice(0,4).join('/') + location.hash
|
history.replaceState null, '', pathname[0...4].join('/') + location.hash
|
||||||
|
|
||||||
# c.time 'All initializations'
|
# c.time 'All initializations'
|
||||||
for [name, feature] in Main.features
|
for [name, feature] in Main.features
|
||||||
|
|||||||
@ -73,11 +73,13 @@ Settings =
|
|||||||
delete Settings.dialog
|
delete Settings.dialog
|
||||||
|
|
||||||
sections: []
|
sections: []
|
||||||
|
|
||||||
addSection: (title, open) ->
|
addSection: (title, open) ->
|
||||||
if typeof title isnt 'string'
|
if typeof title isnt 'string'
|
||||||
{title, open} = title.detail
|
{title, open} = title.detail
|
||||||
hyphenatedTitle = title.toLowerCase().replace /\s+/g, '-'
|
hyphenatedTitle = title.toLowerCase().replace /\s+/g, '-'
|
||||||
Settings.sections.push {title, hyphenatedTitle, open}
|
Settings.sections.push {title, hyphenatedTitle, open}
|
||||||
|
|
||||||
openSection: ->
|
openSection: ->
|
||||||
if selected = $ '.tab-selected', Settings.dialog
|
if selected = $ '.tab-selected', Settings.dialog
|
||||||
$.rmClass selected, 'tab-selected'
|
$.rmClass selected, 'tab-selected'
|
||||||
@ -142,12 +144,14 @@ Settings =
|
|||||||
localStorage.removeItem "4chan-hide-t-#{boardID}"
|
localStorage.removeItem "4chan-hide-t-#{boardID}"
|
||||||
$.delete ['hiddenThreads', 'hiddenPosts']
|
$.delete ['hiddenThreads', 'hiddenPosts']
|
||||||
$.after $('input[name="Stubs"]', section).parentNode.parentNode, div
|
$.after $('input[name="Stubs"]', section).parentNode.parentNode, div
|
||||||
|
|
||||||
export: ->
|
export: ->
|
||||||
# Make sure to export the most recent data.
|
# Make sure to export the most recent data.
|
||||||
$.get Conf, (Conf) ->
|
$.get Conf, (Conf) ->
|
||||||
# XXX don't export archives.
|
# XXX don't export archives.
|
||||||
delete Conf['archives']
|
delete Conf['archives']
|
||||||
Settings.downloadExport {version: g.VERSION, date: Date.now(), Conf}
|
Settings.downloadExport {version: g.VERSION, date: Date.now(), Conf}
|
||||||
|
|
||||||
downloadExport: (data) ->
|
downloadExport: (data) ->
|
||||||
a = $.el 'a',
|
a = $.el 'a',
|
||||||
download: "<%= meta.name %> v#{g.VERSION}-#{data.date}.json"
|
download: "<%= meta.name %> v#{g.VERSION}-#{data.date}.json"
|
||||||
@ -160,12 +164,14 @@ Settings =
|
|||||||
a.click()
|
a.click()
|
||||||
import: ->
|
import: ->
|
||||||
$('input', @parentNode).click()
|
$('input', @parentNode).click()
|
||||||
|
|
||||||
onImport: ->
|
onImport: ->
|
||||||
return unless file = @files[0]
|
return unless file = @files[0]
|
||||||
output = $('.imp-exp-result')
|
output = $('.imp-exp-result')
|
||||||
unless confirm 'Your current settings will be entirely overwritten, are you sure?'
|
unless confirm 'Your current settings will be entirely overwritten, are you sure?'
|
||||||
output.textContent = 'Import aborted.'
|
output.textContent = 'Import aborted.'
|
||||||
return
|
return
|
||||||
|
|
||||||
reader = new FileReader()
|
reader = new FileReader()
|
||||||
reader.onload = (e) ->
|
reader.onload = (e) ->
|
||||||
try
|
try
|
||||||
@ -176,6 +182,7 @@ Settings =
|
|||||||
output.textContent = 'Import failed due to an error.'
|
output.textContent = 'Import failed due to an error.'
|
||||||
c.error err.stack
|
c.error err.stack
|
||||||
reader.readAsText file
|
reader.readAsText file
|
||||||
|
|
||||||
loadSettings: (data) ->
|
loadSettings: (data) ->
|
||||||
version = data.version.split '.'
|
version = data.version.split '.'
|
||||||
if version[0] is '2'
|
if version[0] is '2'
|
||||||
@ -259,6 +266,7 @@ Settings =
|
|||||||
data.Conf['watchedThreads'] = boards: ThreadWatcher.convert data.Conf['WatchedThreads']
|
data.Conf['watchedThreads'] = boards: ThreadWatcher.convert data.Conf['WatchedThreads']
|
||||||
delete data.Conf['WatchedThreads']
|
delete data.Conf['WatchedThreads']
|
||||||
$.clear -> $.set data.Conf
|
$.clear -> $.set data.Conf
|
||||||
|
|
||||||
reset: ->
|
reset: ->
|
||||||
if confirm 'Your current settings will be entirely wiped, are you sure?'
|
if confirm 'Your current settings will be entirely wiped, are you sure?'
|
||||||
$.clear -> window.location.reload() if confirm 'Reset successful. Reload now?'
|
$.clear -> window.location.reload() if confirm 'Reset successful. Reload now?'
|
||||||
@ -326,9 +334,11 @@ Settings =
|
|||||||
|
|
||||||
interval = $ 'input[name="Interval"]', section
|
interval = $ 'input[name="Interval"]', section
|
||||||
customCSS = $ 'input[name="Custom CSS"]', section
|
customCSS = $ 'input[name="Custom CSS"]', section
|
||||||
|
|
||||||
interval.value = Conf['Interval']
|
interval.value = Conf['Interval']
|
||||||
customCSS.checked = Conf['Custom CSS']
|
customCSS.checked = Conf['Custom CSS']
|
||||||
inputs['usercss'].disabled = !Conf['Custom CSS']
|
inputs['usercss'].disabled = !Conf['Custom CSS']
|
||||||
|
|
||||||
$.on interval, 'change', ThreadUpdater.cb.interval
|
$.on interval, 'change', ThreadUpdater.cb.interval
|
||||||
$.on customCSS, 'change', Settings.togglecss
|
$.on customCSS, 'change', Settings.togglecss
|
||||||
$.on $('#apply-css', section), 'click', Settings.usercss
|
$.on $('#apply-css', section), 'click', Settings.usercss
|
||||||
@ -421,10 +431,13 @@ Settings =
|
|||||||
|
|
||||||
boardnav: ->
|
boardnav: ->
|
||||||
Header.generateBoardList @value
|
Header.generateBoardList @value
|
||||||
|
|
||||||
time: ->
|
time: ->
|
||||||
@nextElementSibling.textContent = Time.format @value, new Date()
|
@nextElementSibling.textContent = Time.format @value, new Date()
|
||||||
|
|
||||||
backlink: ->
|
backlink: ->
|
||||||
@nextElementSibling.textContent = @value.replace /%(?:id|%)/g, (x) -> {'%id': '123456789', '%%': '%'}[x]
|
@nextElementSibling.textContent = @value.replace /%(?:id|%)/g, (x) -> {'%id': '123456789', '%%': '%'}[x]
|
||||||
|
|
||||||
fileInfo: ->
|
fileInfo: ->
|
||||||
data =
|
data =
|
||||||
isReply: true
|
isReply: true
|
||||||
@ -437,6 +450,7 @@ Settings =
|
|||||||
isImage: true
|
isImage: true
|
||||||
isSpoiler: true
|
isSpoiler: true
|
||||||
FileInfo.format @value, data, @nextElementSibling
|
FileInfo.format @value, data, @nextElementSibling
|
||||||
|
|
||||||
favicon: ->
|
favicon: ->
|
||||||
Favicon.switch()
|
Favicon.switch()
|
||||||
Unread.update() if g.VIEW is 'thread' and Conf['Unread Favicon']
|
Unread.update() if g.VIEW is 'thread' and Conf['Unread Favicon']
|
||||||
@ -445,12 +459,14 @@ Settings =
|
|||||||
img[1].src = Favicon.unreadSFW
|
img[1].src = Favicon.unreadSFW
|
||||||
img[2].src = Favicon.unreadNSFW
|
img[2].src = Favicon.unreadNSFW
|
||||||
img[3].src = Favicon.unreadDead
|
img[3].src = Favicon.unreadDead
|
||||||
|
|
||||||
togglecss: ->
|
togglecss: ->
|
||||||
if $('textarea[name=usercss]', $.x 'ancestor::fieldset[1]', @).disabled = !@checked
|
if $('textarea[name=usercss]', $.x 'ancestor::fieldset[1]', @).disabled = !@checked
|
||||||
CustomCSS.rmStyle()
|
CustomCSS.rmStyle()
|
||||||
else
|
else
|
||||||
CustomCSS.addStyle()
|
CustomCSS.addStyle()
|
||||||
$.cb.checked.call @
|
$.cb.checked.call @
|
||||||
|
|
||||||
usercss: ->
|
usercss: ->
|
||||||
CustomCSS.update()
|
CustomCSS.update()
|
||||||
|
|
||||||
@ -475,6 +491,7 @@ Settings =
|
|||||||
for key, val of items
|
for key, val of items
|
||||||
inputs[key].value = val
|
inputs[key].value = val
|
||||||
return
|
return
|
||||||
|
|
||||||
keybind: (e) ->
|
keybind: (e) ->
|
||||||
return if e.keyCode is 9 # tab
|
return if e.keyCode is 9 # tab
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|||||||
@ -328,6 +328,7 @@ UI = do ->
|
|||||||
if $.x 'ancestor::div[contains(@class,"inline")][1]', root
|
if $.x 'ancestor::div[contains(@class,"inline")][1]', root
|
||||||
$.on d, 'keydown', o.hoverend
|
$.on d, 'keydown', o.hoverend
|
||||||
$.on root, 'mousemove', o.hover
|
$.on root, 'mousemove', o.hover
|
||||||
|
|
||||||
<% if (type === 'userscript') { %>
|
<% if (type === 'userscript') { %>
|
||||||
# Workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=674955
|
# Workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=674955
|
||||||
o.workaround = (e) -> o.hoverend(e) unless root.contains e.target
|
o.workaround = (e) -> o.hoverend(e) unless root.contains e.target
|
||||||
|
|||||||
@ -443,6 +443,7 @@ do ->
|
|||||||
delete $.oldValue[key]
|
delete $.oldValue[key]
|
||||||
cb undefined, key
|
cb undefined, key
|
||||||
$.on window, 'storage', ({key}) -> onChange key
|
$.on window, 'storage', ({key}) -> onChange key
|
||||||
|
|
||||||
$.forceSync = (key) ->
|
$.forceSync = (key) ->
|
||||||
# Storage events don't work across origins
|
# Storage events don't work across origins
|
||||||
# e.g. http://boards.4chan.org and https://boards.4chan.org
|
# e.g. http://boards.4chan.org and https://boards.4chan.org
|
||||||
@ -482,6 +483,7 @@ $.set = do ->
|
|||||||
$.oldValue[key] = val
|
$.oldValue[key] = val
|
||||||
# for `storage` events
|
# for `storage` events
|
||||||
localStorage.setItem key, val
|
localStorage.setItem key, val
|
||||||
|
|
||||||
(keys, val) ->
|
(keys, val) ->
|
||||||
if typeof keys is 'string'
|
if typeof keys is 'string'
|
||||||
set keys, val
|
set keys, val
|
||||||
|
|||||||
@ -62,7 +62,7 @@ class RandomAccessList
|
|||||||
|
|
||||||
shift: ->
|
shift: ->
|
||||||
@rm @first.ID
|
@rm @first.ID
|
||||||
|
|
||||||
order: ->
|
order: ->
|
||||||
order = [item = @first]
|
order = [item = @first]
|
||||||
order.push item while item = item.next
|
order.push item while item = item.next
|
||||||
|
|||||||
@ -28,6 +28,7 @@ class Thread
|
|||||||
icon.title = "This thread is on page #{pageNum} in the original index."
|
icon.title = "This thread is on page #{pageNum} in the original index."
|
||||||
icon.textContent = "[#{pageNum}]"
|
icon.textContent = "[#{pageNum}]"
|
||||||
@catalogView.nodes.pageCount.textContent = pageNum if @catalogView
|
@catalogView.nodes.pageCount.textContent = pageNum if @catalogView
|
||||||
|
|
||||||
setCount: (type, count, reachedLimit) ->
|
setCount: (type, count, reachedLimit) ->
|
||||||
return unless @catalogView
|
return unless @catalogView
|
||||||
el = @catalogView.nodes["#{type}Count"]
|
el = @catalogView.nodes["#{type}Count"]
|
||||||
@ -47,6 +48,7 @@ class Thread
|
|||||||
typeLC = type.toLowerCase()
|
typeLC = type.toLowerCase()
|
||||||
icon = $ ".#{typeLC}Icon", @OP.nodes.info
|
icon = $ ".#{typeLC}Icon", @OP.nodes.info
|
||||||
return if !!icon is status
|
return if !!icon is status
|
||||||
|
|
||||||
unless status
|
unless status
|
||||||
$.rm icon.previousSibling
|
$.rm icon.previousSibling
|
||||||
$.rm icon
|
$.rm icon
|
||||||
@ -57,6 +59,7 @@ class Thread
|
|||||||
alt: type
|
alt: type
|
||||||
title: type
|
title: type
|
||||||
className: "#{typeLC}Icon retina"
|
className: "#{typeLC}Icon retina"
|
||||||
|
|
||||||
root = if type isnt 'Sticky' and @isSticky
|
root = if type isnt 'Sticky' and @isSticky
|
||||||
$ '.stickyIcon', @OP.nodes.info
|
$ '.stickyIcon', @OP.nodes.info
|
||||||
else
|
else
|
||||||
|
|||||||
@ -78,6 +78,7 @@ Gallery =
|
|||||||
|
|
||||||
$.on d, 'keydown', cb.keybinds
|
$.on d, 'keydown', cb.keybinds
|
||||||
$.off d, 'keydown', Keybinds.keydown if Conf['Keybinds']
|
$.off d, 'keydown', Keybinds.keydown if Conf['Keybinds']
|
||||||
|
|
||||||
for file in $$ '.post .file' when !$ '.fileDeletedRes, .fileDeleted', file
|
for file in $$ '.post .file' when !$ '.fileDeletedRes, .fileDeleted', file
|
||||||
post = Get.postFromNode file
|
post = Get.postFromNode file
|
||||||
Gallery.generateThumb post
|
Gallery.generateThumb post
|
||||||
@ -87,6 +88,7 @@ Gallery =
|
|||||||
if Header.getTopOf(candidate) + candidate.getBoundingClientRect().height >= 0
|
if Header.getTopOf(candidate) + candidate.getBoundingClientRect().height >= 0
|
||||||
image = candidate
|
image = candidate
|
||||||
$.addClass doc, 'gallery-open'
|
$.addClass doc, 'gallery-open'
|
||||||
|
|
||||||
$.add d.body, dialog
|
$.add d.body, dialog
|
||||||
|
|
||||||
nodes.thumbs.scrollTop = 0
|
nodes.thumbs.scrollTop = 0
|
||||||
@ -103,6 +105,7 @@ Gallery =
|
|||||||
return if post.isClone or post.isHidden
|
return if post.isClone or post.isHidden
|
||||||
return unless post.file and (post.file.isImage or post.file.isVideo or Conf['PDF in Gallery'])
|
return unless post.file and (post.file.isImage or post.file.isVideo or Conf['PDF in Gallery'])
|
||||||
return if Gallery.fullIDs[post.fullID]
|
return if Gallery.fullIDs[post.fullID]
|
||||||
|
|
||||||
Gallery.fullIDs[post.fullID] = true
|
Gallery.fullIDs[post.fullID] = true
|
||||||
|
|
||||||
thumb = $.el 'a',
|
thumb = $.el 'a',
|
||||||
@ -110,13 +113,14 @@ Gallery =
|
|||||||
href: post.file.URL
|
href: post.file.URL
|
||||||
target: '_blank'
|
target: '_blank'
|
||||||
title: post.file.name
|
title: post.file.name
|
||||||
thumb.dataset.id = Gallery.images.length
|
|
||||||
|
thumb.dataset.id = Gallery.images.length
|
||||||
thumb.dataset.post = post.fullID
|
thumb.dataset.post = post.fullID
|
||||||
|
|
||||||
thumbImg = post.file.thumb.cloneNode false
|
thumbImg = post.file.thumb.cloneNode false
|
||||||
thumbImg.style.cssText = ''
|
thumbImg.style.cssText = ''
|
||||||
$.add thumb, thumbImg
|
$.add thumb, thumbImg
|
||||||
|
|
||||||
$.on thumb, 'click', Gallery.cb.open
|
$.on thumb, 'click', Gallery.cb.open
|
||||||
|
|
||||||
Gallery.images.push thumb
|
Gallery.images.push thumb
|
||||||
@ -135,6 +139,7 @@ Gallery =
|
|||||||
elType = 'img'
|
elType = 'img'
|
||||||
elType = 'video' if /\.webm$/.test(thumb.href)
|
elType = 'video' if /\.webm$/.test(thumb.href)
|
||||||
elType = 'iframe' if /\.pdf$/.test(thumb.href)
|
elType = 'iframe' if /\.pdf$/.test(thumb.href)
|
||||||
|
|
||||||
$[if elType is 'iframe' then 'addClass' else 'rmClass'] doc, 'gal-pdf'
|
$[if elType is 'iframe' then 'addClass' else 'rmClass'] doc, 'gal-pdf'
|
||||||
file = $.el elType,
|
file = $.el elType,
|
||||||
title: name.download = name.textContent = thumb.title
|
title: name.download = name.textContent = thumb.title
|
||||||
@ -142,7 +147,7 @@ Gallery =
|
|||||||
Gallery.error file, thumb
|
Gallery.error file, thumb
|
||||||
file.src = name.href = thumb.href
|
file.src = name.href = thumb.href
|
||||||
|
|
||||||
$.extend file.dataset, thumb.dataset
|
$.extend file.dataset, thumb.dataset
|
||||||
nodes.current.pause?() unless nodes.current.error
|
nodes.current.pause?() unless nodes.current.error
|
||||||
$.replace nodes.current, file
|
$.replace nodes.current, file
|
||||||
if elType is 'video'
|
if elType is 'video'
|
||||||
@ -242,10 +247,12 @@ Gallery =
|
|||||||
Gallery.cb.open.call(
|
Gallery.cb.open.call(
|
||||||
Gallery.images[+Gallery.nodes.current.dataset.id + 1] or Gallery.images[0]
|
Gallery.images[+Gallery.nodes.current.dataset.id + 1] or Gallery.images[0]
|
||||||
)
|
)
|
||||||
|
|
||||||
click: (e) ->
|
click: (e) ->
|
||||||
return if ImageCommon.onControls e
|
return if ImageCommon.onControls e
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
Gallery.cb.advance()
|
Gallery.cb.advance()
|
||||||
|
|
||||||
advance: -> if Gallery.nodes.current.paused then Gallery.nodes.current.play() else Gallery.cb.next()
|
advance: -> if Gallery.nodes.current.paused then Gallery.nodes.current.play() else Gallery.cb.next()
|
||||||
toggle: -> (if Gallery.nodes then Gallery.cb.close else Gallery.build)()
|
toggle: -> (if Gallery.nodes then Gallery.cb.close else Gallery.build)()
|
||||||
blank: (e) -> Gallery.cb.close() if e.target is @
|
blank: (e) -> Gallery.cb.close() if e.target is @
|
||||||
|
|||||||
@ -7,6 +7,7 @@ ImageExpand =
|
|||||||
textContent: 'EAI'
|
textContent: 'EAI'
|
||||||
title: 'Expand All Images'
|
title: 'Expand All Images'
|
||||||
href: 'javascript:;'
|
href: 'javascript:;'
|
||||||
|
|
||||||
$.on @EAI, 'click', @cb.toggleAll
|
$.on @EAI, 'click', @cb.toggleAll
|
||||||
Header.addShortcut @EAI, 3
|
Header.addShortcut @EAI, 3
|
||||||
$.on d, 'scroll visibilitychange', @cb.playVideos
|
$.on d, 'scroll visibilitychange', @cb.playVideos
|
||||||
@ -18,14 +19,17 @@ ImageExpand =
|
|||||||
node: ->
|
node: ->
|
||||||
return unless @file and (@file.isImage or @file.isVideo)
|
return unless @file and (@file.isImage or @file.isVideo)
|
||||||
$.on @file.thumb.parentNode, 'click', ImageExpand.cb.toggle
|
$.on @file.thumb.parentNode, 'click', ImageExpand.cb.toggle
|
||||||
|
|
||||||
if @isClone
|
if @isClone
|
||||||
if @file.isExpanding
|
if @file.isExpanding
|
||||||
# If we clone a post where the image is still loading,
|
# If we clone a post where the image is still loading,
|
||||||
# make it loading in the clone too.
|
# make it loading in the clone too.
|
||||||
ImageExpand.contract @
|
ImageExpand.contract @
|
||||||
ImageExpand.expand @
|
ImageExpand.expand @
|
||||||
|
|
||||||
else if @file.isExpanded and @file.isVideo
|
else if @file.isExpanded and @file.isVideo
|
||||||
ImageExpand.setupVideo @, !@origin.file.fullImage?.paused or @origin.file.wasPlaying, @file.fullImage.controls
|
ImageExpand.setupVideo @, !@origin.file.fullImage?.paused or @origin.file.wasPlaying, @file.fullImage.controls
|
||||||
|
|
||||||
else if ImageExpand.on and !@isHidden and !@isFetchedQuote and
|
else if ImageExpand.on and !@isHidden and !@isFetchedQuote and
|
||||||
(Conf['Expand spoilers'] or !@file.isSpoiler) and
|
(Conf['Expand spoilers'] or !@file.isSpoiler) and
|
||||||
(Conf['Expand videos'] or !@file.isVideo)
|
(Conf['Expand videos'] or !@file.isVideo)
|
||||||
@ -247,7 +251,7 @@ ImageExpand =
|
|||||||
|
|
||||||
el = $.el 'span',
|
el = $.el 'span',
|
||||||
textContent: 'Image Expansion'
|
textContent: 'Image Expansion'
|
||||||
className: 'image-expansion-link'
|
className: 'image-expansion-link'
|
||||||
|
|
||||||
{createSubEntry} = ImageExpand.menu
|
{createSubEntry} = ImageExpand.menu
|
||||||
subEntries = []
|
subEntries = []
|
||||||
|
|||||||
@ -9,13 +9,16 @@ ImageHover =
|
|||||||
CatalogThread.callbacks.push
|
CatalogThread.callbacks.push
|
||||||
name: 'Catalog Image Hover'
|
name: 'Catalog Image Hover'
|
||||||
cb: @catalogNode
|
cb: @catalogNode
|
||||||
|
|
||||||
node: ->
|
node: ->
|
||||||
return unless @file and (@file.isImage or @file.isVideo)
|
return unless @file and (@file.isImage or @file.isVideo)
|
||||||
$.on @file.thumb, 'mouseover', ImageHover.mouseover @
|
$.on @file.thumb, 'mouseover', ImageHover.mouseover @
|
||||||
|
|
||||||
catalogNode: ->
|
catalogNode: ->
|
||||||
{file} = @thread.OP
|
{file} = @thread.OP
|
||||||
return unless file and (file.isImage or file.isVideo)
|
return unless file and (file.isImage or file.isVideo)
|
||||||
$.on @nodes.thumb, 'mouseover', ImageHover.mouseover @thread.OP
|
$.on @nodes.thumb, 'mouseover', ImageHover.mouseover @thread.OP
|
||||||
|
|
||||||
mouseover: (post) -> (e) ->
|
mouseover: (post) -> (e) ->
|
||||||
return unless doc.contains @
|
return unless doc.contains @
|
||||||
{file} = post
|
{file} = post
|
||||||
@ -30,6 +33,7 @@ ImageHover =
|
|||||||
el.dataset.fullID = post.fullID
|
el.dataset.fullID = post.fullID
|
||||||
$.on el, 'error', error
|
$.on el, 'error', error
|
||||||
el.src = file.URL
|
el.src = file.URL
|
||||||
|
|
||||||
if Conf['Restart when Opened']
|
if Conf['Restart when Opened']
|
||||||
ImageCommon.rewind el
|
ImageCommon.rewind el
|
||||||
ImageCommon.rewind @
|
ImageCommon.rewind @
|
||||||
@ -46,7 +50,7 @@ ImageHover =
|
|||||||
maxWidth = Math.max left, doc.clientWidth - right
|
maxWidth = Math.max left, doc.clientWidth - right
|
||||||
maxHeight = doc.clientHeight - padding
|
maxHeight = doc.clientHeight - padding
|
||||||
scale = Math.min 1, maxWidth / width, maxHeight / height
|
scale = Math.min 1, maxWidth / width, maxHeight / height
|
||||||
el.style.maxWidth = "#{scale * width}px"
|
el.style.maxWidth = "#{scale * width}px"
|
||||||
el.style.maxHeight = "#{scale * height}px"
|
el.style.maxHeight = "#{scale * height}px"
|
||||||
UI.hover
|
UI.hover
|
||||||
root: @
|
root: @
|
||||||
@ -62,6 +66,7 @@ ImageHover =
|
|||||||
el.pause() if isVideo
|
el.pause() if isVideo
|
||||||
$.rm el
|
$.rm el
|
||||||
el.removeAttribute 'style'
|
el.removeAttribute 'style'
|
||||||
|
|
||||||
error: (post) -> ->
|
error: (post) -> ->
|
||||||
return if ImageCommon.decodeError @, post
|
return if ImageCommon.decodeError @, post
|
||||||
ImageCommon.error @, post, 3 * $.SECOND, (URL) =>
|
ImageCommon.error @, post, 3 * $.SECOND, (URL) =>
|
||||||
|
|||||||
@ -75,6 +75,7 @@ ImageLoader =
|
|||||||
if !chrome?
|
if !chrome?
|
||||||
$.on thumb, 'loadeddata', -> @removeAttribute 'poster'
|
$.on thumb, 'loadeddata', -> @removeAttribute 'poster'
|
||||||
return
|
return
|
||||||
|
|
||||||
el = $.el if isImage then 'img' else 'video'
|
el = $.el if isImage then 'img' else 'video'
|
||||||
if replace and isImage
|
if replace and isImage
|
||||||
$.on el, 'load', ->
|
$.on el, 'load', ->
|
||||||
|
|||||||
@ -40,7 +40,7 @@ Sauce =
|
|||||||
type
|
type
|
||||||
ext = post.file.URL.match(/\.([^\.]*)$/)?[1] or ''
|
ext = post.file.URL.match(/\.([^\.]*)$/)?[1] or ''
|
||||||
return null unless !parts['boards'] or post.board.ID in parts['boards'].split ','
|
return null unless !parts['boards'] or post.board.ID in parts['boards'].split ','
|
||||||
return null unless !parts['types'] or ext in parts['types'].split ','
|
return null unless !parts['types'] or ext in parts['types'].split ','
|
||||||
a = Sauce.link.cloneNode true
|
a = Sauce.link.cloneNode true
|
||||||
a.href = parts['url']
|
a.href = parts['url']
|
||||||
a.textContent = parts['text']
|
a.textContent = parts['text']
|
||||||
@ -49,8 +49,7 @@ Sauce =
|
|||||||
node: ->
|
node: ->
|
||||||
return if @isClone or !@file
|
return if @isClone or !@file
|
||||||
nodes = []
|
nodes = []
|
||||||
for link in Sauce.links
|
for link in Sauce.links when node = Sauce.createSauceLink link, @
|
||||||
if node = Sauce.createSauceLink link, @
|
# \u00A0 is nbsp
|
||||||
# \u00A0 is nbsp
|
nodes.push $.tn('\u00A0'), node
|
||||||
nodes.push $.tn('\u00A0'), node
|
|
||||||
$.add @file.text, nodes
|
$.add @file.text, nodes
|
||||||
|
|||||||
@ -5,12 +5,14 @@ Menu =
|
|||||||
@button = $.el 'a',
|
@button = $.el 'a',
|
||||||
className: 'menu-button'
|
className: 'menu-button'
|
||||||
href: 'javascript:;'
|
href: 'javascript:;'
|
||||||
|
|
||||||
$.extend @button, <%= html('<i class="fa fa-angle-down"></i>') %>
|
$.extend @button, <%= html('<i class="fa fa-angle-down"></i>') %>
|
||||||
|
|
||||||
@menu = new UI.Menu 'post'
|
@menu = new UI.Menu 'post'
|
||||||
Post.callbacks.push
|
Post.callbacks.push
|
||||||
name: 'Menu'
|
name: 'Menu'
|
||||||
cb: @node
|
cb: @node
|
||||||
|
|
||||||
CatalogThread.callbacks.push
|
CatalogThread.callbacks.push
|
||||||
name: 'Menu'
|
name: 'Menu'
|
||||||
cb: @catalogNode
|
cb: @catalogNode
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
PSAHiding =
|
PSAHiding =
|
||||||
init: ->
|
init: ->
|
||||||
return if !Conf['Announcement Hiding']
|
return unless Conf['Announcement Hiding']
|
||||||
$.addClass doc, 'hide-announcement'
|
$.addClass doc, 'hide-announcement'
|
||||||
$.one d, '4chanXInitFinished', @setup
|
$.one d, '4chanXInitFinished', @setup
|
||||||
|
|
||||||
@ -24,7 +24,9 @@ PSAHiding =
|
|||||||
PSAHiding.btn = btn = $.el 'span',
|
PSAHiding.btn = btn = $.el 'span',
|
||||||
title: 'Mark announcement as read and hide.'
|
title: 'Mark announcement as read and hide.'
|
||||||
className: 'hide-announcement'
|
className: 'hide-announcement'
|
||||||
|
|
||||||
$.extend btn, <%= html('[<a href="javascript:;">Dismiss</a>]') %>
|
$.extend btn, <%= html('[<a href="javascript:;">Dismiss</a>]') %>
|
||||||
|
|
||||||
$.on btn, 'click', PSAHiding.toggle
|
$.on btn, 'click', PSAHiding.toggle
|
||||||
|
|
||||||
$.get 'hiddenPSA', 0, ({hiddenPSA}) ->
|
$.get 'hiddenPSA', 0, ({hiddenPSA}) ->
|
||||||
@ -33,6 +35,7 @@ PSAHiding =
|
|||||||
$.rmClass doc, 'hide-announcement'
|
$.rmClass doc, 'hide-announcement'
|
||||||
|
|
||||||
$.sync 'hiddenPSA', PSAHiding.sync
|
$.sync 'hiddenPSA', PSAHiding.sync
|
||||||
|
|
||||||
toggle: (e) ->
|
toggle: (e) ->
|
||||||
if $.hasClass @, 'hide-announcement'
|
if $.hasClass @, 'hide-announcement'
|
||||||
UTC = +$.id('globalMessage').dataset.utc
|
UTC = +$.id('globalMessage').dataset.utc
|
||||||
@ -41,6 +44,7 @@ PSAHiding =
|
|||||||
$.event 'CloseMenu'
|
$.event 'CloseMenu'
|
||||||
$.delete 'hiddenPSA'
|
$.delete 'hiddenPSA'
|
||||||
PSAHiding.sync UTC
|
PSAHiding.sync UTC
|
||||||
|
|
||||||
sync: (UTC) ->
|
sync: (UTC) ->
|
||||||
{psa} = PSAHiding
|
{psa} = PSAHiding
|
||||||
PSAHiding.hidden = PSAHiding.btn.hidden = UTC? and UTC >= +psa.dataset.utc
|
PSAHiding.hidden = PSAHiding.btn.hidden = UTC? and UTC >= +psa.dataset.utc
|
||||||
|
|||||||
@ -55,7 +55,7 @@ Banner =
|
|||||||
i = Math.floor(Banner.choices.length * Math.random())
|
i = Math.floor(Banner.choices.length * Math.random())
|
||||||
banner = Banner.choices.splice i, 1
|
banner = Banner.choices.splice i, 1
|
||||||
$('img', @parentNode).src = "//s.4cdn.org/image/title/#{banner}"
|
$('img', @parentNode).src = "//s.4cdn.org/image/title/#{banner}"
|
||||||
|
|
||||||
click: (e) ->
|
click: (e) ->
|
||||||
if e.ctrlKey or e.metaKey
|
if e.ctrlKey or e.metaKey
|
||||||
@contentEditable = true
|
@contentEditable = true
|
||||||
|
|||||||
@ -2,12 +2,15 @@ CustomCSS =
|
|||||||
init: ->
|
init: ->
|
||||||
return unless Conf['Custom CSS']
|
return unless Conf['Custom CSS']
|
||||||
@addStyle()
|
@addStyle()
|
||||||
|
|
||||||
addStyle: ->
|
addStyle: ->
|
||||||
@style = $.addStyle Conf['usercss'], 'custom-css', -> $.id 'fourchanx-css'
|
@style = $.addStyle Conf['usercss'], 'custom-css', -> $.id 'fourchanx-css'
|
||||||
|
|
||||||
rmStyle: ->
|
rmStyle: ->
|
||||||
if @style
|
if @style
|
||||||
$.rm @style
|
$.rm @style
|
||||||
delete @style
|
delete @style
|
||||||
|
|
||||||
update: ->
|
update: ->
|
||||||
unless @style
|
unless @style
|
||||||
@addStyle()
|
@addStyle()
|
||||||
|
|||||||
@ -12,10 +12,13 @@ ExpandComment =
|
|||||||
node: ->
|
node: ->
|
||||||
if a = $ '.abbr > a:not([onclick])', @nodes.comment
|
if a = $ '.abbr > a:not([onclick])', @nodes.comment
|
||||||
$.on a, 'click', ExpandComment.cb
|
$.on a, 'click', ExpandComment.cb
|
||||||
|
|
||||||
callbacks: []
|
callbacks: []
|
||||||
|
|
||||||
cb: (e) ->
|
cb: (e) ->
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
ExpandComment.expand Get.postFromNode @
|
ExpandComment.expand Get.postFromNode @
|
||||||
|
|
||||||
expand: (post) ->
|
expand: (post) ->
|
||||||
if post.nodes.longComment and !post.nodes.longComment.parentNode
|
if post.nodes.longComment and !post.nodes.longComment.parentNode
|
||||||
$.replace post.nodes.shortComment, post.nodes.longComment
|
$.replace post.nodes.shortComment, post.nodes.longComment
|
||||||
@ -24,12 +27,14 @@ ExpandComment =
|
|||||||
return unless a = $ '.abbr > a', post.nodes.comment
|
return unless a = $ '.abbr > a', post.nodes.comment
|
||||||
a.textContent = "Post No.#{post} Loading..."
|
a.textContent = "Post No.#{post} Loading..."
|
||||||
$.cache "//a.4cdn.org#{a.pathname.split('/').splice(0,4).join('/')}.json", -> ExpandComment.parse @, a, post
|
$.cache "//a.4cdn.org#{a.pathname.split('/').splice(0,4).join('/')}.json", -> ExpandComment.parse @, a, post
|
||||||
|
|
||||||
contract: (post) ->
|
contract: (post) ->
|
||||||
return unless post.nodes.shortComment
|
return unless post.nodes.shortComment
|
||||||
a = $ '.abbr > a', post.nodes.shortComment
|
a = $ '.abbr > a', post.nodes.shortComment
|
||||||
a.textContent = 'here'
|
a.textContent = 'here'
|
||||||
$.replace post.nodes.longComment, post.nodes.shortComment
|
$.replace post.nodes.longComment, post.nodes.shortComment
|
||||||
post.nodes.comment = post.nodes.shortComment
|
post.nodes.comment = post.nodes.shortComment
|
||||||
|
|
||||||
parse: (req, a, post) ->
|
parse: (req, a, post) ->
|
||||||
{status} = req
|
{status} = req
|
||||||
unless status in [200, 304]
|
unless status in [200, 304]
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
Fourchan =
|
Fourchan =
|
||||||
init: ->
|
init: ->
|
||||||
return if g.VIEW not in ['index', 'thread']
|
return unless g.VIEW in ['index', 'thread']
|
||||||
|
|
||||||
if g.BOARD.ID is 'g'
|
if g.BOARD.ID is 'g'
|
||||||
$.globalEval '''
|
$.globalEval '''
|
||||||
|
|||||||
@ -12,6 +12,8 @@ IDColor =
|
|||||||
span = $ '.hand', @nodes.uniqueID
|
span = $ '.hand', @nodes.uniqueID
|
||||||
return unless span and span.nodeName is 'SPAN'
|
return unless span and span.nodeName is 'SPAN'
|
||||||
rgb = IDColor.compute uid
|
rgb = IDColor.compute uid
|
||||||
|
|
||||||
|
# Style the damn node.
|
||||||
{style} = span
|
{style} = span
|
||||||
style.color = rgb[3]
|
style.color = rgb[3]
|
||||||
style.backgroundColor = "rgb(#{rgb[0]},#{rgb[1]},#{rgb[2]})"
|
style.backgroundColor = "rgb(#{rgb[0]},#{rgb[1]},#{rgb[2]})"
|
||||||
@ -21,16 +23,24 @@ IDColor =
|
|||||||
compute: (uid) ->
|
compute: (uid) ->
|
||||||
return IDColor.ids[uid] if IDColor.ids[uid]
|
return IDColor.ids[uid] if IDColor.ids[uid]
|
||||||
|
|
||||||
|
# Convert chars to integers, bitshift and math to create a larger integer
|
||||||
|
# Create a nice string of binary
|
||||||
hash = IDColor.hash uid
|
hash = IDColor.hash uid
|
||||||
|
|
||||||
|
# Convert binary string to numerical values with bitshift and '&' truncation.
|
||||||
rgb = [
|
rgb = [
|
||||||
(hash >> 24) & 0xFF
|
(hash >> 24) & 0xFF
|
||||||
(hash >> 16) & 0xFF
|
(hash >> 16) & 0xFF
|
||||||
(hash >> 8) & 0xFF
|
(hash >> 8) & 0xFF
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Weight color luminance values, assign a font color that should be readable.
|
||||||
rgb[3] = if (rgb[0] * 0.299 + rgb[1] * 0.587 + rgb[2] * 0.114) > 125
|
rgb[3] = if (rgb[0] * 0.299 + rgb[1] * 0.587 + rgb[2] * 0.114) > 125
|
||||||
'#000'
|
'#000'
|
||||||
else
|
else
|
||||||
'#fff'
|
'#fff'
|
||||||
|
|
||||||
|
# Cache.
|
||||||
@ids[uid] = rgb
|
@ids[uid] = rgb
|
||||||
|
|
||||||
hash: (uid) ->
|
hash: (uid) ->
|
||||||
@ -38,4 +48,4 @@ IDColor =
|
|||||||
i = 0
|
i = 0
|
||||||
while i < 8
|
while i < 8
|
||||||
msg = (msg << 5) - msg + uid.charCodeAt i++
|
msg = (msg << 5) - msg + uid.charCodeAt i++
|
||||||
msg
|
msg
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
IDHighlight =
|
IDHighlight =
|
||||||
init: ->
|
init: ->
|
||||||
return if g.VIEW not in ['index', 'thread']
|
return unless g.VIEW in ['index', 'thread']
|
||||||
|
|
||||||
Post.callbacks.push
|
Post.callbacks.push
|
||||||
name: 'Highlight by User ID'
|
name: 'Highlight by User ID'
|
||||||
|
|||||||
@ -56,16 +56,16 @@ Keybinds =
|
|||||||
else
|
else
|
||||||
return
|
return
|
||||||
when Conf['Spoiler tags']
|
when Conf['Spoiler tags']
|
||||||
return if target.nodeName isnt 'TEXTAREA'
|
return unless target.nodeName is 'TEXTAREA'
|
||||||
Keybinds.tags 'spoiler', target
|
Keybinds.tags 'spoiler', target
|
||||||
when Conf['Code tags']
|
when Conf['Code tags']
|
||||||
return if target.nodeName isnt 'TEXTAREA'
|
return unless target.nodeName is 'TEXTAREA'
|
||||||
Keybinds.tags 'code', target
|
Keybinds.tags 'code', target
|
||||||
when Conf['Eqn tags']
|
when Conf['Eqn tags']
|
||||||
return if target.nodeName isnt 'TEXTAREA'
|
return unless target.nodeName is 'TEXTAREA'
|
||||||
Keybinds.tags 'eqn', target
|
Keybinds.tags 'eqn', target
|
||||||
when Conf['Math tags']
|
when Conf['Math tags']
|
||||||
return if target.nodeName isnt 'TEXTAREA'
|
return unless target.nodeName is 'TEXTAREA'
|
||||||
Keybinds.tags 'math', target
|
Keybinds.tags 'math', target
|
||||||
when Conf['Toggle sage']
|
when Conf['Toggle sage']
|
||||||
return unless QR.nodes and !QR.nodes.el.hidden
|
return unless QR.nodes and !QR.nodes.el.hidden
|
||||||
|
|||||||
@ -62,7 +62,9 @@ Nav =
|
|||||||
# Add extra space to the end of the page if necessary so that all threads can be selected by keybinds.
|
# Add extra space to the end of the page if necessary so that all threads can be selected by keybinds.
|
||||||
extra = Header.getTopOf(thread) + doc.clientHeight - d.body.getBoundingClientRect().bottom
|
extra = Header.getTopOf(thread) + doc.clientHeight - d.body.getBoundingClientRect().bottom
|
||||||
d.body.style.marginBottom = "#{extra}px" if extra > 0
|
d.body.style.marginBottom = "#{extra}px" if extra > 0
|
||||||
|
|
||||||
Header.scrollTo thread
|
Header.scrollTo thread
|
||||||
|
|
||||||
if extra > 0 and !Nav.haveExtra
|
if extra > 0 and !Nav.haveExtra
|
||||||
Nav.haveExtra = true
|
Nav.haveExtra = true
|
||||||
$.on d, 'scroll', Nav.removeExtra
|
$.on d, 'scroll', Nav.removeExtra
|
||||||
|
|||||||
@ -8,9 +8,11 @@ RemoveSpoilers =
|
|||||||
Post.callbacks.push
|
Post.callbacks.push
|
||||||
name: 'Reveal Spoilers'
|
name: 'Reveal Spoilers'
|
||||||
cb: @node
|
cb: @node
|
||||||
|
|
||||||
CatalogThread.callbacks.push
|
CatalogThread.callbacks.push
|
||||||
name: 'Reveal Spoilers'
|
name: 'Reveal Spoilers'
|
||||||
cb: @node
|
cb: @node
|
||||||
|
|
||||||
if g.VIEW is 'archive'
|
if g.VIEW is 'archive'
|
||||||
$.ready -> RemoveSpoilers.unspoiler $.id 'arc-list'
|
$.ready -> RemoveSpoilers.unspoiler $.id 'arc-list'
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@ Time =
|
|||||||
Post.callbacks.push
|
Post.callbacks.push
|
||||||
name: 'Time Formatting'
|
name: 'Time Formatting'
|
||||||
cb: @node
|
cb: @node
|
||||||
|
|
||||||
node: ->
|
node: ->
|
||||||
return if @isClone
|
return if @isClone
|
||||||
@nodes.date.textContent = Time.format Conf['time'], @info.date
|
@nodes.date.textContent = Time.format Conf['time'], @info.date
|
||||||
@ -14,6 +15,7 @@ Time =
|
|||||||
Time.formatters[c].call(date)
|
Time.formatters[c].call(date)
|
||||||
else
|
else
|
||||||
s
|
s
|
||||||
|
|
||||||
day: [
|
day: [
|
||||||
'Sunday'
|
'Sunday'
|
||||||
'Monday'
|
'Monday'
|
||||||
@ -23,6 +25,7 @@ Time =
|
|||||||
'Friday'
|
'Friday'
|
||||||
'Saturday'
|
'Saturday'
|
||||||
]
|
]
|
||||||
|
|
||||||
month: [
|
month: [
|
||||||
'January'
|
'January'
|
||||||
'February'
|
'February'
|
||||||
@ -37,7 +40,9 @@ Time =
|
|||||||
'November'
|
'November'
|
||||||
'December'
|
'December'
|
||||||
]
|
]
|
||||||
|
|
||||||
zeroPad: (n) -> if n < 10 then "0#{n}" else n
|
zeroPad: (n) -> if n < 10 then "0#{n}" else n
|
||||||
|
|
||||||
formatters:
|
formatters:
|
||||||
a: -> Time.day[@getDay()][...3]
|
a: -> Time.day[@getDay()][...3]
|
||||||
A: -> Time.day[@getDay()]
|
A: -> Time.day[@getDay()]
|
||||||
|
|||||||
@ -18,6 +18,7 @@ ThreadStats =
|
|||||||
$.extend sc, statsHTML
|
$.extend sc, statsHTML
|
||||||
$.ready ->
|
$.ready ->
|
||||||
Header.addShortcut sc
|
Header.addShortcut sc
|
||||||
|
|
||||||
else
|
else
|
||||||
@dialog = sc = UI.dialog 'thread-stats', 'bottom: 0px; right: 0px;',
|
@dialog = sc = UI.dialog 'thread-stats', 'bottom: 0px; right: 0px;',
|
||||||
<%= html('<div class="move" title="${statsTitle}">&{statsHTML}</div>') %>
|
<%= html('<div class="move" title="${statsTitle}">&{statsHTML}</div>') %>
|
||||||
|
|||||||
@ -8,7 +8,7 @@ ThreadUpdater =
|
|||||||
$.extend sc, <%= html('<span id="update-status"></span><span id="update-timer" title="Update now"></span>') %>
|
$.extend sc, <%= html('<span id="update-status"></span><span id="update-timer" title="Update now"></span>') %>
|
||||||
$.ready ->
|
$.ready ->
|
||||||
Header.addShortcut sc
|
Header.addShortcut sc
|
||||||
else
|
else
|
||||||
@dialog = sc = UI.dialog 'updater', 'bottom: 0px; left: 0px;',
|
@dialog = sc = UI.dialog 'updater', 'bottom: 0px; left: 0px;',
|
||||||
<%= html('<div class="move"></div><span id="update-status"></span><span id="update-timer" title="Update now"></span>') %>
|
<%= html('<div class="move"></div><span id="update-status"></span><span id="update-timer" title="Update now"></span>') %>
|
||||||
$.addClass doc, 'float'
|
$.addClass doc, 'float'
|
||||||
@ -176,7 +176,7 @@ ThreadUpdater =
|
|||||||
|
|
||||||
setInterval: ->
|
setInterval: ->
|
||||||
i = ThreadUpdater.interval + 1
|
i = ThreadUpdater.interval + 1
|
||||||
|
|
||||||
if Conf['Optional Increase']
|
if Conf['Optional Increase']
|
||||||
# Lower the max refresh rate limit on visible tabs.
|
# Lower the max refresh rate limit on visible tabs.
|
||||||
cur = ThreadUpdater.outdateCount or 1
|
cur = ThreadUpdater.outdateCount or 1
|
||||||
|
|||||||
@ -11,10 +11,10 @@ ThreadWatcher =
|
|||||||
|
|
||||||
@db = new DataBoard 'watchedThreads', @refresh, true
|
@db = new DataBoard 'watchedThreads', @refresh, true
|
||||||
@dialog = UI.dialog 'thread-watcher', 'top: 50px; left: 0px;', <%= importHTML('Monitoring/ThreadWatcher') %>
|
@dialog = UI.dialog 'thread-watcher', 'top: 50px; left: 0px;', <%= importHTML('Monitoring/ThreadWatcher') %>
|
||||||
|
|
||||||
@status = $ '#watcher-status', @dialog
|
@status = $ '#watcher-status', @dialog
|
||||||
@list = @dialog.lastElementChild
|
@list = @dialog.lastElementChild
|
||||||
@refreshButton = $ '.move > .refresh', @dialog
|
@refreshButton = $ '.move > .refresh', @dialog
|
||||||
|
|
||||||
@unreaddb = Unread.db or new DataBoard 'lastReadPosts'
|
@unreaddb = Unread.db or new DataBoard 'lastReadPosts'
|
||||||
|
|
||||||
$.on d, 'QRPostSuccessful', @cb.post
|
$.on d, 'QRPostSuccessful', @cb.post
|
||||||
@ -23,6 +23,7 @@ ThreadWatcher =
|
|||||||
$.on $('.move > .close', @dialog), 'click', @toggleWatcher
|
$.on $('.move > .close', @dialog), 'click', @toggleWatcher
|
||||||
|
|
||||||
$.on d, '4chanXInitFinished', @ready
|
$.on d, '4chanXInitFinished', @ready
|
||||||
|
|
||||||
switch g.VIEW
|
switch g.VIEW
|
||||||
when 'index'
|
when 'index'
|
||||||
$.on d, 'IndexRefresh', @cb.onIndexRefresh
|
$.on d, 'IndexRefresh', @cb.onIndexRefresh
|
||||||
@ -147,6 +148,7 @@ ThreadWatcher =
|
|||||||
fetchCount:
|
fetchCount:
|
||||||
fetched: 0
|
fetched: 0
|
||||||
fetching: 0
|
fetching: 0
|
||||||
|
|
||||||
fetchAuto: ->
|
fetchAuto: ->
|
||||||
clearTimeout ThreadWatcher.timeout
|
clearTimeout ThreadWatcher.timeout
|
||||||
return unless Conf['Auto Update Thread Watcher']
|
return unless Conf['Auto Update Thread Watcher']
|
||||||
@ -158,6 +160,7 @@ ThreadWatcher =
|
|||||||
ThreadWatcher.fetchAllStatus()
|
ThreadWatcher.fetchAllStatus()
|
||||||
db.save()
|
db.save()
|
||||||
ThreadWatcher.timeout = setTimeout ThreadWatcher.fetchAuto, interval
|
ThreadWatcher.timeout = setTimeout ThreadWatcher.fetchAuto, interval
|
||||||
|
|
||||||
fetchAllStatus: ->
|
fetchAllStatus: ->
|
||||||
ThreadWatcher.db.forceSync()
|
ThreadWatcher.db.forceSync()
|
||||||
ThreadWatcher.unreaddb.forceSync()
|
ThreadWatcher.unreaddb.forceSync()
|
||||||
@ -166,6 +169,7 @@ ThreadWatcher =
|
|||||||
for thread in threads
|
for thread in threads
|
||||||
ThreadWatcher.fetchStatus thread
|
ThreadWatcher.fetchStatus thread
|
||||||
return
|
return
|
||||||
|
|
||||||
fetchStatus: (thread) ->
|
fetchStatus: (thread) ->
|
||||||
{boardID, threadID, data} = thread
|
{boardID, threadID, data} = thread
|
||||||
return if data.isDead and !Conf['Show Unread Count']
|
return if data.isDead and !Conf['Show Unread Count']
|
||||||
@ -177,6 +181,7 @@ ThreadWatcher =
|
|||||||
$.ajax "//a.4cdn.org/#{boardID}/thread/#{threadID}.json",
|
$.ajax "//a.4cdn.org/#{boardID}/thread/#{threadID}.json",
|
||||||
onloadend: ->
|
onloadend: ->
|
||||||
ThreadWatcher.parseStatus.call @, thread
|
ThreadWatcher.parseStatus.call @, thread
|
||||||
|
|
||||||
parseStatus: ({boardID, threadID, data}) ->
|
parseStatus: ({boardID, threadID, data}) ->
|
||||||
{fetchCount} = ThreadWatcher
|
{fetchCount} = ThreadWatcher
|
||||||
fetchCount.fetched++
|
fetchCount.fetched++
|
||||||
@ -233,6 +238,7 @@ ThreadWatcher =
|
|||||||
delete data.unread
|
delete data.unread
|
||||||
delete data.quotingYou
|
delete data.quotingYou
|
||||||
ThreadWatcher.db.set {boardID, threadID, val: data}
|
ThreadWatcher.db.set {boardID, threadID, val: data}
|
||||||
|
|
||||||
ThreadWatcher.refresh()
|
ThreadWatcher.refresh()
|
||||||
|
|
||||||
getAll: ->
|
getAll: ->
|
||||||
@ -269,8 +275,8 @@ ThreadWatcher =
|
|||||||
div = $.el 'div'
|
div = $.el 'div'
|
||||||
fullID = "#{boardID}.#{threadID}"
|
fullID = "#{boardID}.#{threadID}"
|
||||||
div.dataset.fullID = fullID
|
div.dataset.fullID = fullID
|
||||||
$.addClass div, 'current' if g.VIEW is 'thread' and fullID is "#{g.BOARD}.#{g.THREADID}"
|
$.addClass div, 'current' if g.VIEW is 'thread' and fullID is "#{g.BOARD}.#{g.THREADID}"
|
||||||
$.addClass div, 'dead-thread' if data.isDead
|
$.addClass div, 'dead-thread' if data.isDead
|
||||||
if Conf['Show Unread Count']
|
if Conf['Show Unread Count']
|
||||||
$.addClass div, 'replies-unread' if data.unread
|
$.addClass div, 'replies-unread' if data.unread
|
||||||
$.addClass div, 'replies-quoting-you' if data.quotingYou
|
$.addClass div, 'replies-quoting-you' if data.quotingYou
|
||||||
@ -336,6 +342,7 @@ ThreadWatcher =
|
|||||||
ThreadWatcher.rm boardID, threadID
|
ThreadWatcher.rm boardID, threadID
|
||||||
else
|
else
|
||||||
ThreadWatcher.add thread
|
ThreadWatcher.add thread
|
||||||
|
|
||||||
add: (thread) ->
|
add: (thread) ->
|
||||||
data = {}
|
data = {}
|
||||||
boardID = thread.board.ID
|
boardID = thread.board.ID
|
||||||
@ -350,6 +357,7 @@ ThreadWatcher =
|
|||||||
ThreadWatcher.refresh()
|
ThreadWatcher.refresh()
|
||||||
if Conf['Show Unread Count']
|
if Conf['Show Unread Count']
|
||||||
ThreadWatcher.fetchStatus {boardID, threadID, data}
|
ThreadWatcher.fetchStatus {boardID, threadID, data}
|
||||||
|
|
||||||
rm: (boardID, threadID) ->
|
rm: (boardID, threadID) ->
|
||||||
ThreadWatcher.db.delete {boardID, threadID}
|
ThreadWatcher.db.delete {boardID, threadID}
|
||||||
ThreadWatcher.refresh()
|
ThreadWatcher.refresh()
|
||||||
@ -423,6 +431,7 @@ ThreadWatcher =
|
|||||||
@refreshers.push refresh.bind entry if refresh
|
@refreshers.push refresh.bind entry if refresh
|
||||||
@menu.addEntry entry
|
@menu.addEntry entry
|
||||||
return
|
return
|
||||||
|
|
||||||
createSubEntry: (name, desc) ->
|
createSubEntry: (name, desc) ->
|
||||||
entry =
|
entry =
|
||||||
type: 'thread watcher'
|
type: 'thread watcher'
|
||||||
@ -430,6 +439,6 @@ ThreadWatcher =
|
|||||||
entry.el.title = desc
|
entry.el.title = desc
|
||||||
input = entry.el.firstElementChild
|
input = entry.el.firstElementChild
|
||||||
$.on input, 'change', $.cb.checked
|
$.on input, 'change', $.cb.checked
|
||||||
$.on input, 'change', ThreadWatcher.refresh if name in ['Current Board', 'Show Unread Count']
|
$.on input, 'change', ThreadWatcher.refresh if name in ['Current Board', 'Show Unread Count']
|
||||||
$.on input, 'change', ThreadWatcher.fetchAuto if name in ['Show Unread Count', 'Auto Update Thread Watcher']
|
$.on input, 'change', ThreadWatcher.fetchAuto if name in ['Show Unread Count', 'Auto Update Thread Watcher']
|
||||||
entry
|
entry
|
||||||
|
|||||||
@ -20,6 +20,7 @@ Unread =
|
|||||||
Thread.callbacks.push
|
Thread.callbacks.push
|
||||||
name: 'Unread'
|
name: 'Unread'
|
||||||
cb: @node
|
cb: @node
|
||||||
|
|
||||||
Post.callbacks.push
|
Post.callbacks.push
|
||||||
name: 'Unread'
|
name: 'Unread'
|
||||||
cb: @addPost
|
cb: @addPost
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
Captcha.noscript =
|
Captcha.noscript =
|
||||||
lifetime: 2 * $.MINUTE
|
lifetime: 2 * $.MINUTE
|
||||||
iframeURL: '//www.google.com/recaptcha/api/fallback?k=<%= meta.recaptchaKey %>'
|
iframeURL: '//www.google.com/recaptcha/api/fallback?k=<%= meta.recaptchaKey %>'
|
||||||
|
|
||||||
init: ->
|
init: ->
|
||||||
|
|||||||
@ -113,6 +113,7 @@ QR =
|
|||||||
return
|
return
|
||||||
if Conf['QR Shortcut']
|
if Conf['QR Shortcut']
|
||||||
$.rmClass $('.qr-shortcut'), 'disabled'
|
$.rmClass $('.qr-shortcut'), 'disabled'
|
||||||
|
|
||||||
close: ->
|
close: ->
|
||||||
if QR.req
|
if QR.req
|
||||||
QR.abort()
|
QR.abort()
|
||||||
@ -129,6 +130,7 @@ QR =
|
|||||||
QR.cooldown.auto = false
|
QR.cooldown.auto = false
|
||||||
QR.status()
|
QR.status()
|
||||||
QR.captcha.destroy()
|
QR.captcha.destroy()
|
||||||
|
|
||||||
focus: ->
|
focus: ->
|
||||||
$.queueTask ->
|
$.queueTask ->
|
||||||
return unless QR.nodes
|
return unless QR.nodes
|
||||||
@ -142,18 +144,22 @@ QR =
|
|||||||
$.on d, 'scroll', QR.scrollLock
|
$.on d, 'scroll', QR.scrollLock
|
||||||
else
|
else
|
||||||
$.off d, 'scroll', QR.scrollLock
|
$.off d, 'scroll', QR.scrollLock
|
||||||
|
|
||||||
scrollLock: (e) ->
|
scrollLock: (e) ->
|
||||||
if d.activeElement and QR.nodes.el.contains(d.activeElement) and d.activeElement.nodeName is 'IFRAME'
|
if d.activeElement and QR.nodes.el.contains(d.activeElement) and d.activeElement.nodeName is 'IFRAME'
|
||||||
window.scroll window.scrollX, QR.scrollY
|
window.scroll window.scrollX, QR.scrollY
|
||||||
else
|
else
|
||||||
$.off d, 'scroll', QR.scrollLock
|
$.off d, 'scroll', QR.scrollLock
|
||||||
|
|
||||||
hide: ->
|
hide: ->
|
||||||
d.activeElement.blur()
|
d.activeElement.blur()
|
||||||
$.addClass QR.nodes.el, 'autohide'
|
$.addClass QR.nodes.el, 'autohide'
|
||||||
QR.nodes.autohide.checked = true
|
QR.nodes.autohide.checked = true
|
||||||
|
|
||||||
unhide: ->
|
unhide: ->
|
||||||
$.rmClass QR.nodes.el, 'autohide'
|
$.rmClass QR.nodes.el, 'autohide'
|
||||||
QR.nodes.autohide.checked = false
|
QR.nodes.autohide.checked = false
|
||||||
|
|
||||||
toggleHide: ->
|
toggleHide: ->
|
||||||
if @checked
|
if @checked
|
||||||
QR.hide()
|
QR.hide()
|
||||||
@ -195,6 +201,7 @@ QR =
|
|||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
notifications: []
|
notifications: []
|
||||||
|
|
||||||
cleanNotifications: ->
|
cleanNotifications: ->
|
||||||
for notification in QR.notifications
|
for notification in QR.notifications
|
||||||
notification.close()
|
notification.close()
|
||||||
@ -449,7 +456,8 @@ QR =
|
|||||||
|
|
||||||
dialog: ->
|
dialog: ->
|
||||||
QR.nodes = nodes =
|
QR.nodes = nodes =
|
||||||
el: dialog = UI.dialog 'qr', 'top: 50px; right: 0px;', <%= importHTML('Features/QuickReply') %>
|
el: dialog = UI.dialog 'qr', 'top: 50px; right: 0px;',
|
||||||
|
<%= importHTML('Features/QuickReply') %>
|
||||||
|
|
||||||
setNode = (name, query) ->
|
setNode = (name, query) ->
|
||||||
nodes[name] = $ query, dialog
|
nodes[name] = $ query, dialog
|
||||||
@ -478,7 +486,7 @@ QR =
|
|||||||
setNode 'spoilerPar', '#qr-spoiler-label'
|
setNode 'spoilerPar', '#qr-spoiler-label'
|
||||||
setNode 'status', '[type=submit]'
|
setNode 'status', '[type=submit]'
|
||||||
setNode 'fileInput', '[type=file]'
|
setNode 'fileInput', '[type=file]'
|
||||||
|
|
||||||
rules = $('ul.rules').textContent.trim()
|
rules = $('ul.rules').textContent.trim()
|
||||||
match_min = rules.match(/.+smaller than (\d+)x(\d+).+/)
|
match_min = rules.match(/.+smaller than (\d+)x(\d+).+/)
|
||||||
match_max = rules.match(/.+greater than (\d+)x(\d+).+/)
|
match_max = rules.match(/.+greater than (\d+)x(\d+).+/)
|
||||||
@ -516,7 +524,9 @@ QR =
|
|||||||
nodes.spoiler.parentElement.hidden = true
|
nodes.spoiler.parentElement.hidden = true
|
||||||
|
|
||||||
if g.BOARD.ID is 'f' and g.VIEW isnt 'thread'
|
if g.BOARD.ID is 'f' and g.VIEW isnt 'thread'
|
||||||
nodes.flashTag = $.el 'select', name: 'filetag'
|
nodes.flashTag = $.el 'select',
|
||||||
|
name: 'filetag'
|
||||||
|
|
||||||
$.extend nodes.flashTag, <%= html(
|
$.extend nodes.flashTag, <%= html(
|
||||||
'<option value="0">Hentai</option>' +
|
'<option value="0">Hentai</option>' +
|
||||||
'<option value="6">Porn</option>' +
|
'<option value="6">Porn</option>' +
|
||||||
@ -526,6 +536,7 @@ QR =
|
|||||||
'<option value="5">Loop</option>' +
|
'<option value="5">Loop</option>' +
|
||||||
'<option value="4" selected>Other</option>'
|
'<option value="4" selected>Other</option>'
|
||||||
) %>
|
) %>
|
||||||
|
|
||||||
nodes.flashTag.dataset.default = '4'
|
nodes.flashTag.dataset.default = '4'
|
||||||
$.add nodes.form, nodes.flashTag
|
$.add nodes.form, nodes.flashTag
|
||||||
|
|
||||||
@ -537,8 +548,8 @@ QR =
|
|||||||
$.on nodes.urlButton, 'click', QR.handleUrl
|
$.on nodes.urlButton, 'click', QR.handleUrl
|
||||||
$.on nodes.addPost, 'click', -> new QR.post true
|
$.on nodes.addPost, 'click', -> new QR.post true
|
||||||
$.on nodes.form, 'submit', QR.submit
|
$.on nodes.form, 'submit', QR.submit
|
||||||
$.on nodes.fileRM, 'click', -> QR.selected.rmFile()
|
$.on nodes.fileRM, 'click', -> QR.selected.rmFile()
|
||||||
$.on nodes.fileExtras, 'click', (e) -> e.stopPropagation()
|
$.on nodes.fileExtras, 'click', (e) -> e.stopPropagation()
|
||||||
$.on nodes.spoiler, 'change', -> QR.selected.nodes.spoiler.click()
|
$.on nodes.spoiler, 'change', -> QR.selected.nodes.spoiler.click()
|
||||||
$.on nodes.fileInput, 'change', QR.handleFiles
|
$.on nodes.fileInput, 'change', QR.handleFiles
|
||||||
|
|
||||||
@ -566,6 +577,7 @@ QR =
|
|||||||
QR.status()
|
QR.status()
|
||||||
QR.cooldown.init()
|
QR.cooldown.init()
|
||||||
QR.captcha.init()
|
QR.captcha.init()
|
||||||
|
|
||||||
$.add d.body, dialog
|
$.add d.body, dialog
|
||||||
QR.captcha.setup()
|
QR.captcha.setup()
|
||||||
|
|
||||||
@ -798,7 +810,7 @@ QR =
|
|||||||
QR.close()
|
QR.close()
|
||||||
else
|
else
|
||||||
post.rm()
|
post.rm()
|
||||||
QR.captcha.setup (d.activeElement is QR.nodes.status)
|
QR.captcha.setup(d.activeElement is QR.nodes.status)
|
||||||
|
|
||||||
QR.cooldown.add req.uploadEndTime, threadID, postID
|
QR.cooldown.add req.uploadEndTime, threadID, postID
|
||||||
|
|
||||||
@ -806,6 +818,7 @@ QR =
|
|||||||
"#{window.location.origin}/#{g.BOARD}/thread/#{threadID}"
|
"#{window.location.origin}/#{g.BOARD}/thread/#{threadID}"
|
||||||
else if g.VIEW is 'index' and !QR.cooldown.auto and Conf['Open Post in New Tab'] # replying from the index
|
else if g.VIEW is 'index' and !QR.cooldown.auto and Conf['Open Post in New Tab'] # replying from the index
|
||||||
"#{window.location.origin}/#{g.BOARD}/thread/#{threadID}#p#{postID}"
|
"#{window.location.origin}/#{g.BOARD}/thread/#{threadID}#p#{postID}"
|
||||||
|
|
||||||
if URL
|
if URL
|
||||||
if Conf['Open Post in New Tab'] or postsCount
|
if Conf['Open Post in New Tab'] or postsCount
|
||||||
$.open URL
|
$.open URL
|
||||||
|
|||||||
@ -71,6 +71,7 @@ QR.post = class
|
|||||||
(QR.posts[index-1] or QR.posts[index+1]).select()
|
(QR.posts[index-1] or QR.posts[index+1]).select()
|
||||||
QR.posts.splice index, 1
|
QR.posts.splice index, 1
|
||||||
QR.status()
|
QR.status()
|
||||||
|
|
||||||
delete: ->
|
delete: ->
|
||||||
$.rm @nodes.el
|
$.rm @nodes.el
|
||||||
URL.revokeObjectURL @URL
|
URL.revokeObjectURL @URL
|
||||||
@ -103,10 +104,13 @@ QR.post = class
|
|||||||
|
|
||||||
load: ->
|
load: ->
|
||||||
# Load this post's values.
|
# Load this post's values.
|
||||||
|
|
||||||
for name in ['thread', 'name', 'email', 'sub', 'com', 'filename']
|
for name in ['thread', 'name', 'email', 'sub', 'com', 'filename']
|
||||||
continue unless node = QR.nodes[name]
|
continue unless node = QR.nodes[name]
|
||||||
node.value = @[name] or node.dataset.default or null
|
node.value = @[name] or node.dataset.default or null
|
||||||
|
|
||||||
(if @thread isnt 'new' then $.addClass else $.rmClass) QR.nodes.el, 'reply-to-thread'
|
(if @thread isnt 'new' then $.addClass else $.rmClass) QR.nodes.el, 'reply-to-thread'
|
||||||
|
|
||||||
@showFileData()
|
@showFileData()
|
||||||
QR.characterCount()
|
QR.characterCount()
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@ QuoteThreading =
|
|||||||
@enabled = true
|
@enabled = true
|
||||||
@controls = $.el 'span',
|
@controls = $.el 'span',
|
||||||
<%= html('<label><input id="threadingControl" type="checkbox" checked> Threading</label>') %>
|
<%= html('<label><input id="threadingControl" type="checkbox" checked> Threading</label>') %>
|
||||||
|
|
||||||
@threadNewLink = $.el 'span',
|
@threadNewLink = $.el 'span',
|
||||||
className: 'brackets-wrap threadnewlink'
|
className: 'brackets-wrap threadnewlink'
|
||||||
hidden: true
|
hidden: true
|
||||||
@ -27,6 +28,7 @@ QuoteThreading =
|
|||||||
Thread.callbacks.push
|
Thread.callbacks.push
|
||||||
name: 'Quote Threading'
|
name: 'Quote Threading'
|
||||||
cb: @setThread
|
cb: @setThread
|
||||||
|
|
||||||
Post.callbacks.push
|
Post.callbacks.push
|
||||||
name: 'Quote Threading'
|
name: 'Quote Threading'
|
||||||
cb: @node
|
cb: @node
|
||||||
|
|||||||
@ -55,7 +55,6 @@ Quotify =
|
|||||||
className: 'quotelink deadlink'
|
className: 'quotelink deadlink'
|
||||||
target: '_blank'
|
target: '_blank'
|
||||||
textContent: "#{quote}\u00A0(Dead)"
|
textContent: "#{quote}\u00A0(Dead)"
|
||||||
|
|
||||||
$.extend a.dataset, {boardID, threadID: post.thread.ID, postID}
|
$.extend a.dataset, {boardID, threadID: post.thread.ID, postID}
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user