Merge tag '1.9.15.4' into noscript
4chan X v1.9.15.4. Conflicts: src/Posting/QR.captcha.coffee
This commit is contained in:
commit
77f3639772
51
CHANGELOG.md
51
CHANGELOG.md
@ -2,7 +2,58 @@ The attributions below are for work that has been incorporated into the script a
|
||||
|
||||
The links to individual versions below are to copies of the script with the update URL removed. If you want automatic updates, install the script from the links on the [main page](https://github.com/ccd0/4chan-x).
|
||||
|
||||
<!-- v1.9.15.x -->
|
||||
### v1.9.15.4
|
||||
*2014-12-08* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.4/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.4/builds/4chan-X-noupdate.crx "Chromium version")]
|
||||
|
||||
**ccd0**
|
||||
- Make `Catalog Links`, `Relative Post Dates`, and `Pin Watched Threads` off by default.
|
||||
|
||||
### v1.9.15.3
|
||||
*2014-12-08* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.3/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.3/builds/4chan-X-noupdate.crx "Chromium version")]
|
||||
|
||||
**ccd0**
|
||||
- Fix sounds sometimes playing for a short time before `Disable Autoplaying Sounds` halts them (as in 1.9.14.4).
|
||||
|
||||
### v1.9.15.2
|
||||
*2014-12-08* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.2/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.2/builds/4chan-X-noupdate.crx "Chromium version")]
|
||||
|
||||
**ccd0**
|
||||
- Add `Pin Watched Threads` setting to `Index Navigation` header submenu (default: checked), moving watched threads to the beginning of 4chan X's index/catalog.
|
||||
- `Alt+Click` in the 4chan X catalog watches/unwatches a thread.
|
||||
- Add a `Watch Thread`/`Unwatch Thread` item to the menu in the 4chan X catalog.
|
||||
|
||||
### v1.9.15.1
|
||||
*2014-12-07* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.1/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.1/builds/4chan-X-noupdate.crx "Chromium version")]
|
||||
|
||||
**ccd0**
|
||||
- Center the controls added to formerly autoplaying audio by `Disable Autoplaying Sounds` (as in v1.9.14.3).
|
||||
|
||||
### v1.9.15.0
|
||||
*2014-12-07* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.0/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.0/builds/4chan-X-noupdate.crx "Chromium version")]
|
||||
|
||||
Based on v1.9.14.2.
|
||||
|
||||
**MayhemYDG, Matěj Grabovský**
|
||||
- Quoting now also includes the spoiler and code tags.
|
||||
|
||||
**ccd0**
|
||||
- Quote the original URL of links rather than the title, and don't quote `(embed)`.
|
||||
- Bug fixes.
|
||||
|
||||
<!-- v1.9.14.x -->
|
||||
### v1.9.14.4
|
||||
*2014-12-08* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.4/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.4/builds/4chan-X-noupdate.crx "Chromium version")]
|
||||
|
||||
**ccd0**
|
||||
- Fix sounds sometimes playing for a short time before `Disable Autoplaying Sounds` halts them.
|
||||
|
||||
### v1.9.14.3
|
||||
*2014-12-07* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.3/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.3/builds/4chan-X-noupdate.crx "Chromium version")]
|
||||
|
||||
**ccd0**
|
||||
- Center the controls added to formerly autoplaying audio by `Disable Autoplaying Sounds`.
|
||||
|
||||
### v1.9.14.2
|
||||
*2014-12-04* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.2/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.2/builds/4chan-X-noupdate.crx "Chromium version")]
|
||||
|
||||
|
||||
@ -25,6 +25,10 @@ module.exports = (grunt) ->
|
||||
output = if parts2.length is 0 then '""' else parts2.join ' + '
|
||||
"(innerHTML: #{output})"
|
||||
|
||||
assert = (statement, objs...) ->
|
||||
return '' unless grunt.config('pkg').tests_enabled
|
||||
"throw new Error 'Assertion failed: ' + `#{JSON.stringify statement}` unless #{statement}"
|
||||
|
||||
# Project configuration.
|
||||
grunt.initConfig
|
||||
pkg: grunt.file.readJSON 'package.json'
|
||||
@ -35,6 +39,7 @@ module.exports = (grunt) ->
|
||||
pkg = grunt.config 'pkg'
|
||||
pkg.importHTML = importHTML
|
||||
pkg.html = html
|
||||
pkg.assert = assert
|
||||
pkg.tests_enabled or= false
|
||||
pkg
|
||||
enumerable: true
|
||||
|
||||
2
LICENSE
2
LICENSE
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 4chan X - Version 1.9.14.2
|
||||
* 4chan X - Version 1.9.15.4
|
||||
*
|
||||
* Licensed under the MIT license.
|
||||
* https://github.com/ccd0/4chan-x/blob/master/LICENSE
|
||||
|
||||
@ -39,6 +39,9 @@ If you want to install the current beta version but get updates from the stable
|
||||
## Security note
|
||||
4chan X currently shares your settings and post history between the HTTP and HTTPS versions of 4chan. If you are concerned about protecting your privacy against a man-in-the-middle attack, you should disable 4chan X on the HTTP version of 4chan and/or install [HTTPS Everywhere](https://www.eff.org/https-everywhere).
|
||||
|
||||
## Uninstalling
|
||||
4chan X disables the native extension, so if you uninstall 4chan X, you'll need to re-enable it. To do this, click the `[Settings]` link in the top right corner and uncheck "`Disable the native extension`" in the panel that appears.
|
||||
|
||||
## More information
|
||||
- [Source Code](https://github.com/ccd0/4chan-x)
|
||||
- [Changelog](https://github.com/ccd0/4chan-x/blob/master/CHANGELOG.md)
|
||||
|
||||
Binary file not shown.
@ -1,6 +1,6 @@
|
||||
// ==UserScript==
|
||||
// @name 4chan X beta
|
||||
// @version 1.9.14.2
|
||||
// @version 1.9.15.4
|
||||
// @minGMVer 1.14
|
||||
// @minFFVer 26
|
||||
// @namespace 4chan-X
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
@ -1,6 +1,6 @@
|
||||
// ==UserScript==
|
||||
// @name 4chan X
|
||||
// @version 1.9.14.2
|
||||
// @version 1.9.15.4
|
||||
// @minGMVer 1.14
|
||||
// @minFFVer 26
|
||||
// @namespace 4chan-X
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
|
||||
<app appid='lacclbnghgdicfifcamcmcnilckjamag'>
|
||||
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X-beta.crx' version='1.9.14.2' />
|
||||
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X-beta.crx' version='1.9.15.4' />
|
||||
</app>
|
||||
</gupdate>
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
|
||||
<app appid='lacclbnghgdicfifcamcmcnilckjamag'>
|
||||
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X.crx' version='1.9.14.2' />
|
||||
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X.crx' version='1.9.15.4' />
|
||||
</app>
|
||||
</gupdate>
|
||||
|
||||
|
||||
@ -47,6 +47,8 @@ Only the latest stable version of 4chan X is available.</p>
|
||||
<p>If you want to install the current beta version but get updates from the stable channel after that, install it from <a href="https://github.com/ccd0/4chan-x/raw/beta/builds/4chan-X.user.js">here</a> for Firefox or <a href="https://github.com/ccd0/4chan-x/raw/beta/builds/4chan-X.crx">here</a> for Chromium.</p>
|
||||
<h2 id="security-note">Security note</h2>
|
||||
<p>4chan X currently shares your settings and post history between the HTTP and HTTPS versions of 4chan. If you are concerned about protecting your privacy against a man-in-the-middle attack, you should disable 4chan X on the HTTP version of 4chan and/or install <a href="https://www.eff.org/https-everywhere">HTTPS Everywhere</a>.</p>
|
||||
<h2 id="uninstalling">Uninstalling</h2>
|
||||
<p>4chan X disables the native extension, so if you uninstall 4chan X, you'll need to re-enable it. To do this, click the <code>[Settings]</code> link in the top right corner and uncheck "<code>Disable the native extension</code>" in the panel that appears.</p>
|
||||
<h2 id="more-information">More information</h2>
|
||||
<ul>
|
||||
<li><a href="https://github.com/ccd0/4chan-x">Source Code</a></li>
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
"description": "Cross-browser userscript for maximum lurking on 4chan.",
|
||||
"meta": {
|
||||
"name": "4chan X",
|
||||
"version": "1.9.14.2",
|
||||
"version": "1.9.15.4",
|
||||
"repo": "https://github.com/ccd0/4chan-x/",
|
||||
"page": "https://github.com/ccd0/4chan-x",
|
||||
"downloads": "https://ccd0.github.io/4chan-x/builds/",
|
||||
|
||||
@ -14,7 +14,7 @@ Config =
|
||||
'Link to 4chan X\'s catalog instead of the native 4chan one.'
|
||||
]
|
||||
'Catalog Links': [
|
||||
true
|
||||
false
|
||||
'Add toggle link in header menu to turn Navigation links into links to each board\'s catalog.'
|
||||
]
|
||||
'QR Shortcut': [
|
||||
@ -46,7 +46,7 @@ Config =
|
||||
'Localize and format timestamps.'
|
||||
]
|
||||
'Relative Post Dates': [
|
||||
true
|
||||
false
|
||||
'Display dates like "3 minutes ago". Tooltip shows the timestamp.'
|
||||
]
|
||||
'Comment Expansion': [
|
||||
@ -589,6 +589,7 @@ http://iqdb.org/?url=%TURL
|
||||
'Index Sort': 'bump'
|
||||
'Index Size': 'small'
|
||||
'Show Replies': true
|
||||
'Pin Watched Threads': false
|
||||
'Anchor Hidden Threads': true
|
||||
'Refreshed Navigation': false
|
||||
|
||||
|
||||
@ -24,25 +24,27 @@ Index =
|
||||
Header.addShortcut @button, 1
|
||||
|
||||
repliesEntry = el: UI.checkbox 'Show Replies', ' Show replies'
|
||||
pinEntry = el: UI.checkbox 'Pin Watched Threads', ' Pin watched threads'
|
||||
anchorEntry = el: UI.checkbox 'Anchor Hidden Threads', ' Anchor hidden threads'
|
||||
refNavEntry = el: UI.checkbox 'Refreshed Navigation', ' Refreshed navigation'
|
||||
anchorEntry.el.title = 'Move hidden threads at the end of the index.'
|
||||
pinEntry.el.title = 'Move watched threads to the start of the index.'
|
||||
anchorEntry.el.title = 'Move hidden threads to the end of the index.'
|
||||
refNavEntry.el.title = 'Refresh index when navigating through pages.'
|
||||
for label in [repliesEntry, anchorEntry, refNavEntry]
|
||||
for label in [repliesEntry, pinEntry, anchorEntry, refNavEntry]
|
||||
input = label.el.firstChild
|
||||
{name} = input
|
||||
$.on input, 'change', $.cb.checked
|
||||
switch name
|
||||
when 'Show Replies'
|
||||
$.on input, 'change', @cb.replies
|
||||
when 'Anchor Hidden Threads'
|
||||
when 'Pin Watched Threads', 'Anchor Hidden Threads'
|
||||
$.on input, 'change', @cb.sort
|
||||
|
||||
Header.menu.addEntry
|
||||
el: $.el 'span',
|
||||
textContent: 'Index Navigation'
|
||||
order: 98
|
||||
subEntries: [repliesEntry, anchorEntry, refNavEntry]
|
||||
subEntries: [repliesEntry, pinEntry, anchorEntry, refNavEntry]
|
||||
|
||||
$.addClass doc, 'index-loading', "#{Conf['Index Mode'].replace /\ /g, '-'}-mode"
|
||||
@root = $.el 'div', className: 'board'
|
||||
@ -252,9 +254,9 @@ Index =
|
||||
1
|
||||
else
|
||||
+window.location.pathname.split('/')[2] or 1
|
||||
userPageNav: (page) ->
|
||||
userPageNav: (page, noRefresh) ->
|
||||
state = Index.pushState {page}
|
||||
if Conf['Refreshed Navigation']
|
||||
if Conf['Refreshed Navigation'] and !noRefresh
|
||||
Index.update state
|
||||
else
|
||||
Index.pageLoad state if state.page
|
||||
@ -542,7 +544,7 @@ Index =
|
||||
# Sticky threads
|
||||
Index.sortOnTop (thread) -> thread.isSticky
|
||||
# Highlighted threads
|
||||
Index.sortOnTop (thread) -> thread.isOnTop
|
||||
Index.sortOnTop (thread) -> thread.isOnTop or Conf['Pin Watched Threads'] and ThreadWatcher.isWatched thread
|
||||
# Non-hidden threads
|
||||
Index.sortOnTop((thread) -> !thread.isHidden) if Conf['Anchor Hidden Threads']
|
||||
|
||||
@ -561,6 +563,11 @@ Index =
|
||||
nodes = Index.buildCatalogViews()
|
||||
Index.sizeCatalogViews nodes
|
||||
else
|
||||
if Index.followedThreadID?
|
||||
i = 0
|
||||
i++ while Index.followedThreadID isnt Get.threadFromRoot(Index.sortedNodes[i]).ID
|
||||
page = i // Index.threadsNumPerPage + 1
|
||||
Index.pushState {page} if page isnt Index.getCurrentPage()
|
||||
nodes = Index.buildSinglePage Index.getCurrentPage()
|
||||
$.rmAll Index.root
|
||||
$.rmAll Header.hover
|
||||
@ -569,6 +576,8 @@ Index =
|
||||
else
|
||||
Index.buildReplies nodes if Conf['Show Replies']
|
||||
Index.buildStructure nodes
|
||||
if Index.followedThreadID? and (post = g.posts["#{g.BOARD}.#{Index.followedThreadID}"])
|
||||
Header.scrollTo post.nodes.root
|
||||
|
||||
buildSinglePage: (pageNum) ->
|
||||
nodesPerPage = Index.threadsNumPerPage
|
||||
|
||||
@ -103,7 +103,9 @@ hr + div.center:not(.ad-cnt):not(.topad):not(.middlead):not(.bottomad) {
|
||||
/* party hats */
|
||||
pointer-events: none;
|
||||
}
|
||||
.center > audio {
|
||||
|
||||
/* Anti-autoplay */
|
||||
audio.controls-added {
|
||||
display: block;
|
||||
margin: auto;
|
||||
}
|
||||
@ -888,6 +890,7 @@ span.hide-announcement {
|
||||
-webkit-align-self: stretch;
|
||||
align-self: stretch;
|
||||
}
|
||||
.catalog-thread.watched .werkTyme-filename,
|
||||
.filter-highlight .werkTyme-filename {
|
||||
border: 2px solid rgba(255, 0, 0, .5);
|
||||
}
|
||||
@ -909,6 +912,7 @@ span.hide-announcement {
|
||||
.filter-highlight > .reply {
|
||||
box-shadow: -5px 0 rgba(255, 0, 0, .5);
|
||||
}
|
||||
.catalog-thread.watched .catalog-thumb,
|
||||
.filter-highlight .catalog-thumb {
|
||||
border: 2px solid rgba(255, 0, 0, .5);
|
||||
}
|
||||
@ -918,6 +922,12 @@ span.hide-announcement {
|
||||
:root.reveal-spoilers s > a {
|
||||
color: white !important;
|
||||
}
|
||||
:root.reveal-spoilers .removed-spoiler::before {
|
||||
content: "[spoiler]";
|
||||
}
|
||||
:root.reveal-spoilers .removed-spoiler::after {
|
||||
content: "[/spoiler]";
|
||||
}
|
||||
|
||||
/* Thread & Reply Hiding */
|
||||
.hide-thread-button,
|
||||
|
||||
@ -10,20 +10,20 @@
|
||||
</div>
|
||||
<form>
|
||||
<div class=persona>
|
||||
<input name=name data-name=name list="list-name" placeholder=Name class=field size=1 tabindex=10>
|
||||
<input name=email data-name=email list="list-email" placeholder=Options class=field size=1 tabindex=20>
|
||||
<input name=sub data-name=sub list="list-sub" placeholder=Subject class=field size=1 tabindex=30>
|
||||
<input name=name data-name=name list="list-name" placeholder=Name class=field size=1>
|
||||
<input name=email data-name=email list="list-email" placeholder=Options class=field size=1>
|
||||
<input name=sub data-name=sub list="list-sub" placeholder=Subject class=field size=1>
|
||||
</div>
|
||||
<div class=textarea>
|
||||
<textarea data-name=com placeholder=Comment class=field tabindex=40></textarea>
|
||||
<textarea data-name=com placeholder=Comment class=field></textarea>
|
||||
<span id=char-count></span>
|
||||
</div>
|
||||
<div id=dump-list-container>
|
||||
<div id=dump-list></div>
|
||||
<a id=add-post href=javascript:; title="Add a post" tabindex=50>+</a>
|
||||
<a id=add-post href=javascript:; title="Add a post">+</a>
|
||||
</div>
|
||||
<div id=file-n-submit>
|
||||
<span id=qr-filename-container class=field tabindex=60>
|
||||
<span id=qr-filename-container class=field tabindex=0>
|
||||
<span id=qr-no-file>No selected file</span>
|
||||
<input id="qr-filename" data-name="filename" spellcheck="false">
|
||||
<span id=qr-extras-container>
|
||||
@ -33,9 +33,9 @@
|
||||
</span>
|
||||
</span>
|
||||
<label id=qr-spoiler-label>
|
||||
<input type=checkbox id=qr-file-spoiler title='Spoiler image' tabindex=70>
|
||||
<input type=checkbox id=qr-file-spoiler title='Spoiler image'>
|
||||
</label>
|
||||
<input type=submit tabindex=80>
|
||||
<input type=submit>
|
||||
</div>
|
||||
<input type=file multiple>
|
||||
</form>
|
||||
|
||||
@ -52,16 +52,20 @@ Linkify =
|
||||
|
||||
endNode = saved
|
||||
{data} = saved
|
||||
word += data
|
||||
{length} = data
|
||||
|
||||
if end = space.exec data
|
||||
# Set our snapshot and regex to start on this node at this position when the loop resumes
|
||||
word += data[...end.index]
|
||||
test.lastIndex = length = end.index
|
||||
i--
|
||||
break
|
||||
else
|
||||
{length} = data
|
||||
word += data
|
||||
|
||||
links.push Linkify.makeRange node, endNode, index, length if Linkify.regString.exec word
|
||||
if Linkify.regString.test word
|
||||
links.push Linkify.makeRange node, endNode, index, length
|
||||
<%= assert('word is links[links.length-1].toString()') %>
|
||||
|
||||
break unless test.lastIndex and node is endNode
|
||||
|
||||
@ -84,9 +88,9 @@ Linkify =
|
||||
[a-z\d%/]
|
||||
)
|
||||
| # This should account for virtually all links posted without http:
|
||||
[-a-z\d]+[.](
|
||||
([-a-z\d]+[.])+(
|
||||
aero|asia|biz|cat|com|coop|info|int|jobs|mobi|moe|museum|name|net|org|post|pro|tel|travel|xxx|edu|gov|mil|[a-z]{2}
|
||||
)([:/]|(?!.))
|
||||
)([:/]|(?![^\s'"]))
|
||||
| # IPv4 Addresses
|
||||
[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}
|
||||
| # E-mails
|
||||
@ -103,10 +107,9 @@ Linkify =
|
||||
text = range.toString()
|
||||
|
||||
# Clean start of range
|
||||
i = 0
|
||||
i++ while /[(\[{<>]/.test text.charAt i
|
||||
i = text.search Linkify.regString
|
||||
|
||||
if i
|
||||
if i > 0
|
||||
text = text.slice i
|
||||
i-- while range.startOffset + i >= range.startContainer.data.length
|
||||
|
||||
@ -237,9 +240,11 @@ Linkify =
|
||||
"#{status}'d"
|
||||
}"
|
||||
|
||||
link.dataset.original = link.textContent
|
||||
link.textContent = text
|
||||
for post2 in post.clones
|
||||
for link2 in $$ 'a.linkify', post2.nodes.comment when link2.href is link.href
|
||||
link2.dataset.original = link2.textContent
|
||||
link2.textContent = text
|
||||
return
|
||||
|
||||
|
||||
@ -1,10 +1,13 @@
|
||||
AntiAutoplay =
|
||||
init: ->
|
||||
return if !Conf['Disable Autoplaying Sounds']
|
||||
$.ready @ready
|
||||
@stop audio for audio in $$ 'audio[autoplay]', doc
|
||||
window.addEventListener 'loadstart', ((e) => @stop e.target), true
|
||||
|
||||
ready: ->
|
||||
for audio in $$ 'audio[autoplay]'
|
||||
audio.pause()
|
||||
audio.autoplay = false
|
||||
audio.controls = true
|
||||
stop: (audio) ->
|
||||
return unless audio.autoplay
|
||||
audio.pause()
|
||||
audio.autoplay = false
|
||||
return if audio.controls
|
||||
audio.controls = true
|
||||
$.addClass audio, 'controls-added'
|
||||
|
||||
@ -1,14 +1,10 @@
|
||||
RemoveSpoilers =
|
||||
init: ->
|
||||
if Conf['Reveal Spoilers'] and !Conf['Remove Spoilers']
|
||||
if Conf['Reveal Spoilers']
|
||||
$.addClass doc, 'reveal-spoilers'
|
||||
|
||||
return unless Conf['Remove Spoilers']
|
||||
|
||||
if Conf['Reveal Spoilers']
|
||||
@wrapper = (text) ->
|
||||
"[spoiler]#{text}[/spoiler]"
|
||||
|
||||
Post.callbacks.push
|
||||
name: 'Reveal Spoilers'
|
||||
cb: @node
|
||||
@ -16,11 +12,10 @@ RemoveSpoilers =
|
||||
name: 'Reveal Spoilers'
|
||||
cb: @node
|
||||
|
||||
wrapper: (text) ->
|
||||
text
|
||||
|
||||
node: (post) ->
|
||||
spoilers = $$ 's', @nodes.comment
|
||||
for spoiler in spoilers
|
||||
$.replace spoiler, $.tn RemoveSpoilers.wrapper spoiler.textContent
|
||||
span = $.el 'span', className: 'removed-spoiler'
|
||||
$.replace spoiler, span
|
||||
$.add span, [spoiler.childNodes...]
|
||||
return
|
||||
|
||||
@ -42,6 +42,29 @@ ThreadWatcher =
|
||||
Thread.callbacks.push
|
||||
name: 'Thread Watcher'
|
||||
cb: @node
|
||||
CatalogThread.callbacks.push
|
||||
name: 'Thread Watcher'
|
||||
cb: @catalogNode
|
||||
|
||||
if g.VIEW is 'index' and Conf['JSON Navigation'] and Conf['Menu'] and g.BOARD.ID isnt 'f'
|
||||
Menu.menu.addEntry
|
||||
el: $.el 'a', href: 'javascript:;'
|
||||
order: 6
|
||||
open: ({thread}) ->
|
||||
return false if Conf['Index Mode'] isnt 'catalog'
|
||||
@el.textContent = if ThreadWatcher.isWatched thread
|
||||
'Unwatch thread'
|
||||
else
|
||||
'Watch thread'
|
||||
$.off @el, 'click', @cb if @cb
|
||||
@cb = ->
|
||||
$.event 'CloseMenu'
|
||||
ThreadWatcher.toggle thread
|
||||
$.on @el, 'click', @cb
|
||||
true
|
||||
|
||||
isWatched: (thread) ->
|
||||
ThreadWatcher.db?.get {boardID: thread.board.ID, threadID: thread.ID}
|
||||
|
||||
node: ->
|
||||
toggler = $.el 'img',
|
||||
@ -49,6 +72,13 @@ ThreadWatcher =
|
||||
$.on toggler, 'click', ThreadWatcher.cb.toggle
|
||||
$.before $('input', @OP.nodes.post), toggler
|
||||
|
||||
catalogNode: ->
|
||||
$.addClass @nodes.root, 'watched' if ThreadWatcher.isWatched @thread
|
||||
$.on @nodes.thumb.parentNode, 'click', (e) =>
|
||||
return unless e.button is 0 and e.altKey
|
||||
ThreadWatcher.toggle @thread
|
||||
e.preventDefault()
|
||||
|
||||
ready: ->
|
||||
$.off d, '4chanXInitFinished', ThreadWatcher.ready
|
||||
return unless Main.isThisPageLegit()
|
||||
@ -83,7 +113,10 @@ ThreadWatcher =
|
||||
ThreadWatcher.refresh()
|
||||
$.event 'CloseMenu'
|
||||
toggle: ->
|
||||
ThreadWatcher.toggle Get.postFromNode(@).thread
|
||||
{thread} = Get.postFromNode @
|
||||
Index.followedThreadID = thread.ID
|
||||
ThreadWatcher.toggle thread
|
||||
delete Index.followedThreadID
|
||||
rm: ->
|
||||
[boardID, threadID] = @parentNode.dataset.fullID.split '.'
|
||||
ThreadWatcher.rm boardID, +threadID
|
||||
@ -240,14 +273,17 @@ ThreadWatcher =
|
||||
for threadID in threads.keys
|
||||
thread = threads[threadID]
|
||||
toggler = $ '.watch-thread-link', thread.OP.nodes.post
|
||||
watched = ThreadWatcher.db.get {boardID: thread.board.ID, threadID}
|
||||
helper = if watched then ['addClass', 'Unwatch'] else ['rmClass', 'Watch']
|
||||
helper = if ThreadWatcher.isWatched thread then ['addClass', 'Unwatch'] else ['rmClass', 'Watch']
|
||||
$[helper[0]] toggler, 'watched'
|
||||
$[helper[0]] thread.catalogView.nodes.root, 'watched' if thread.catalogView
|
||||
toggler.title = "#{helper[1]} Thread"
|
||||
|
||||
for refresher in ThreadWatcher.menu.refreshers
|
||||
refresher()
|
||||
return
|
||||
|
||||
if Index.nodes and Conf['Pin Watched Threads']
|
||||
Index.sort()
|
||||
Index.buildIndex()
|
||||
|
||||
toggle: (thread) ->
|
||||
boardID = thread.board.ID
|
||||
|
||||
@ -14,7 +14,6 @@ QR.captcha =
|
||||
title: 'Verification'
|
||||
autocomplete: 'off'
|
||||
spellcheck: false
|
||||
tabIndex: 45
|
||||
@nodes = {container, input}
|
||||
|
||||
$.on input, 'blur', QR.focusout
|
||||
|
||||
@ -213,12 +213,34 @@ QR =
|
||||
e?.preventDefault()
|
||||
return unless QR.postingIsEnabled
|
||||
|
||||
sel = d.getSelection()
|
||||
post = Get.postFromNode @
|
||||
text = ">>#{post}\n"
|
||||
if (s = sel.toString().trim()) and post is Get.postFromNode sel.anchorNode
|
||||
s = s.replace /\n/g, '\n>'
|
||||
text += ">#{s}\n"
|
||||
sel = d.getSelection()
|
||||
post = Get.postFromNode @
|
||||
text = ">>#{post}\n"
|
||||
if sel.toString().trim() and post is Get.postFromNode sel.anchorNode
|
||||
range = sel.getRangeAt 0
|
||||
frag = range.cloneContents()
|
||||
ancestor = range.commonAncestorContainer
|
||||
# Quoting the insides of a spoiler/code tag.
|
||||
if $.x 'ancestor-or-self::*[self::s or contains(@class,"removed-spoiler")]', ancestor
|
||||
$.prepend frag, $.tn '[spoiler]'
|
||||
$.add frag, $.tn '[/spoiler]'
|
||||
if insideCode = $.x 'ancestor-or-self::pre[contains(@class,"prettyprint")]', ancestor
|
||||
$.prepend frag, $.tn '[code]'
|
||||
$.add frag, $.tn '[/code]'
|
||||
for node in $$ (if insideCode then 'br' else '.prettyprint br'), frag
|
||||
$.replace node, $.tn '\n'
|
||||
for node in $$ 'br', frag
|
||||
$.replace node, $.tn '\n>' unless node is frag.lastChild
|
||||
for node in $$ 's, .removed-spoiler', frag
|
||||
$.replace node, [$.tn('[spoiler]'), node.childNodes..., $.tn '[/spoiler]']
|
||||
for node in $$ '.prettyprint', frag
|
||||
$.replace node, [$.tn('[code]'), node.childNodes..., $.tn '[/code]']
|
||||
for node in $$ '.linkify[data-original]', frag
|
||||
$.replace node, $.tn node.dataset.original
|
||||
for node in $$ '.embedder', frag
|
||||
$.rm node.previousSibling if node.previousSibling?.nodeValue is ' '
|
||||
$.rm node
|
||||
text += ">#{frag.textContent.trim()}\n"
|
||||
|
||||
QR.open()
|
||||
if QR.selected.isLocked
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user