Remove the 'Open Reply in New Tab' config and make it the default behavior.
Various QR fixes. Tiny styling adjustments. You can now create threads when outside of the index. Allow selection-to-quote to work on any text inside the quoted post, not just the comment. Close #789.
This commit is contained in:
parent
0f0d410209
commit
a9b427f0d2
272
4chan_x.user.js
272
4chan_x.user.js
File diff suppressed because one or more lines are too long
@ -5,8 +5,11 @@ alpha
|
|||||||
Access the list of boards directly from the Header.
|
Access the list of boards directly from the Header.
|
||||||
From the Header's menu, access to:
|
From the Header's menu, access to:
|
||||||
Settings
|
Settings
|
||||||
Quick Reply
|
Quick Reply shortcut
|
||||||
Can be auto-hidden.
|
Can be auto-hidden.
|
||||||
|
QR changes:
|
||||||
|
Creating threads outside of the index is now possible.
|
||||||
|
Selection-to-quote also applies to selected text inside the post, not just inside the comment.
|
||||||
Added touch and multi-touch support for dragging windows.
|
Added touch and multi-touch support for dragging windows.
|
||||||
The Thread Updater will pause when offline, and resume when online.
|
The Thread Updater will pause when offline, and resume when online.
|
||||||
Added Thread & Post Hiding in the Menu, with individual settings.
|
Added Thread & Post Hiding in the Menu, with individual settings.
|
||||||
|
|||||||
@ -3,6 +3,9 @@
|
|||||||
background-color: #D6DAF0;
|
background-color: #D6DAF0;
|
||||||
border-color: #B7C5D9;
|
border-color: #B7C5D9;
|
||||||
}
|
}
|
||||||
|
:root.burichan .field:focus {
|
||||||
|
border-color: #98E;
|
||||||
|
}
|
||||||
|
|
||||||
/* Header */
|
/* Header */
|
||||||
:root.burichan #header-bar {
|
:root.burichan #header-bar {
|
||||||
@ -19,6 +22,11 @@
|
|||||||
background-color: rgba(255, 255, 255, .14);
|
background-color: rgba(255, 255, 255, .14);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* QR */
|
||||||
|
:root.burichan .qrpreview {
|
||||||
|
background-color: rgba(0, 0, 0, .15);
|
||||||
|
}
|
||||||
|
|
||||||
/* Menu */
|
/* Menu */
|
||||||
:root.burichan .entry:not(:last-child) {
|
:root.burichan .entry:not(:last-child) {
|
||||||
border-bottom: 1px solid #B7C5D9;
|
border-bottom: 1px solid #B7C5D9;
|
||||||
|
|||||||
@ -3,6 +3,9 @@
|
|||||||
background-color: #F0E0D6;
|
background-color: #F0E0D6;
|
||||||
border-color: #D9BFB7;
|
border-color: #D9BFB7;
|
||||||
}
|
}
|
||||||
|
:root.futaba .field:focus {
|
||||||
|
border-color: #EA8;
|
||||||
|
}
|
||||||
|
|
||||||
/* Header */
|
/* Header */
|
||||||
:root.futaba #header-bar {
|
:root.futaba #header-bar {
|
||||||
@ -19,6 +22,11 @@
|
|||||||
background-color: rgba(255, 255, 255, .14);
|
background-color: rgba(255, 255, 255, .14);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* QR */
|
||||||
|
:root.futaba .qrpreview {
|
||||||
|
background-color: rgba(0, 0, 0, .15);
|
||||||
|
}
|
||||||
|
|
||||||
/* Menu */
|
/* Menu */
|
||||||
:root.futaba .entry:not(:last-child) {
|
:root.futaba .entry:not(:last-child) {
|
||||||
border-bottom: 1px solid #D9BFB7;
|
border-bottom: 1px solid #D9BFB7;
|
||||||
|
|||||||
@ -3,6 +3,9 @@
|
|||||||
background-color: #DDD;
|
background-color: #DDD;
|
||||||
border-color: #CCC;
|
border-color: #CCC;
|
||||||
}
|
}
|
||||||
|
:root.photon .field:focus {
|
||||||
|
border-color: #EA8;
|
||||||
|
}
|
||||||
|
|
||||||
/* Header */
|
/* Header */
|
||||||
:root.photon #header-bar {
|
:root.photon #header-bar {
|
||||||
@ -19,6 +22,11 @@
|
|||||||
background-color: rgba(255, 255, 255, .14);
|
background-color: rgba(255, 255, 255, .14);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* QR */
|
||||||
|
:root.photon .qrpreview {
|
||||||
|
background-color: rgba(0, 0, 0, .15);
|
||||||
|
}
|
||||||
|
|
||||||
/* Menu */
|
/* Menu */
|
||||||
:root.photon .entry:not(:last-child) {
|
:root.photon .entry:not(:last-child) {
|
||||||
border-bottom: 1px solid #CCC;
|
border-bottom: 1px solid #CCC;
|
||||||
|
|||||||
149
css/style.css
149
css/style.css
@ -5,6 +5,28 @@
|
|||||||
display: block;
|
display: block;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
.field {
|
||||||
|
border: 1px solid #CCC;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: #333;
|
||||||
|
font: 13px sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
padding: 2px 4px 3px;
|
||||||
|
outline: none;
|
||||||
|
-webkit-transition: color .25s, border-color .25s;
|
||||||
|
transition: color .25s, border-color .25s;
|
||||||
|
}
|
||||||
|
.field:-moz-placeholder,
|
||||||
|
.field:hover:-moz-placeholder {
|
||||||
|
color: #AAA !important;
|
||||||
|
}
|
||||||
|
.field:hover {
|
||||||
|
border-color: #999;
|
||||||
|
}
|
||||||
|
.field:hover, .field:focus {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
.move {
|
.move {
|
||||||
cursor: move;
|
cursor: move;
|
||||||
}
|
}
|
||||||
@ -79,21 +101,15 @@ a[href="javascript:;"] {
|
|||||||
border-width: 0 0 1px;
|
border-width: 0 0 1px;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
position: relative;
|
position: relative;
|
||||||
transition: all .1s ease-in-out;
|
|
||||||
-o-transition: all .1s ease-in-out;
|
|
||||||
-moz-transition: all .1s ease-in-out;
|
|
||||||
-webkit-transition: all .1s ease-in-out;
|
-webkit-transition: all .1s ease-in-out;
|
||||||
|
transition: all .1s ease-in-out;
|
||||||
}
|
}
|
||||||
#header-bar.autohide:not(:hover) {
|
#header-bar.autohide:not(:hover) {
|
||||||
margin-bottom: -1em;
|
margin-bottom: -1em;
|
||||||
transform: translateY(-100%);
|
|
||||||
-o-transform: translateY(-100%);
|
|
||||||
-moz-transform: translateY(-100%);
|
|
||||||
-webkit-transform: translateY(-100%);
|
-webkit-transform: translateY(-100%);
|
||||||
transition: all .75s .25s ease-in-out;
|
transform: translateY(-100%);
|
||||||
-o-transition: all .75s .25s ease-in-out;
|
|
||||||
-moz-transition: all .75s .25s ease-in-out;
|
|
||||||
-webkit-transition: all .75s .25s ease-in-out;
|
-webkit-transition: all .75s .25s ease-in-out;
|
||||||
|
transition: all .75s .25s ease-in-out;
|
||||||
}
|
}
|
||||||
#toggle-header-bar {
|
#toggle-header-bar {
|
||||||
cursor: n-resize;
|
cursor: n-resize;
|
||||||
@ -129,10 +145,8 @@ a[href="javascript:;"] {
|
|||||||
width: 500px;
|
width: 500px;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
transition: all .25s ease-in-out;
|
|
||||||
-o-transition: all .25s ease-in-out;
|
|
||||||
-moz-transition: all .25s ease-in-out;
|
|
||||||
-webkit-transition: all .25s ease-in-out;
|
-webkit-transition: all .25s ease-in-out;
|
||||||
|
transition: all .25s ease-in-out;
|
||||||
}
|
}
|
||||||
.notification.error {
|
.notification.error {
|
||||||
background-color: hsla(0, 100%, 40%, .9);
|
background-color: hsla(0, 100%, 40%, .9);
|
||||||
@ -154,6 +168,7 @@ a[href="javascript:;"] {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
.message {
|
.message {
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 4px 20px;
|
padding: 4px 20px;
|
||||||
max-height: 200px;
|
max-height: 200px;
|
||||||
@ -234,8 +249,8 @@ a[href="javascript:;"] {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
#ihover {
|
#ihover {
|
||||||
box-sizing: border-box;
|
|
||||||
-moz-box-sizing: border-box;
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
max-width: 75%;
|
max-width: 75%;
|
||||||
padding-bottom: 16px;
|
padding-bottom: 16px;
|
||||||
@ -270,11 +285,15 @@ a[href="javascript:;"] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* QR */
|
/* QR */
|
||||||
|
.hide-original-post-form #postForm,
|
||||||
|
.hide-original-post-form .postingMode {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
#qr > .move {
|
#qr > .move {
|
||||||
min-width: 300px;
|
min-width: 300px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-sizing: border-box;
|
|
||||||
-moz-box-sizing: border-box;
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
padding: 0 2px;
|
padding: 0 2px;
|
||||||
}
|
}
|
||||||
#qr > .move > span {
|
#qr > .move > span {
|
||||||
@ -283,15 +302,16 @@ a[href="javascript:;"] {
|
|||||||
#autohide, .close, #qr select, #dump, .remove, .captchaimg, #qr div.warning {
|
#autohide, .close, #qr select, #dump, .remove, .captchaimg, #qr div.warning {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
#qr select,
|
#qr select {
|
||||||
#qr > form {
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
#dump {
|
#dump {
|
||||||
background: -webkit-linear-gradient(#EEE, #CCC);
|
background: -webkit-linear-gradient(#EEE, #CCC);
|
||||||
background: -moz-linear-gradient(#EEE, #CCC);
|
|
||||||
background: -o-linear-gradient(#EEE, #CCC);
|
|
||||||
background: linear-gradient(#EEE, #CCC);
|
background: linear-gradient(#EEE, #CCC);
|
||||||
|
border: 1px solid #CCC;
|
||||||
|
margin: 0;
|
||||||
|
padding: 2px 4px 3px;
|
||||||
|
outline: none;
|
||||||
width: 10%;
|
width: 10%;
|
||||||
}
|
}
|
||||||
.gecko #dump {
|
.gecko #dump {
|
||||||
@ -299,14 +319,10 @@ a[href="javascript:;"] {
|
|||||||
}
|
}
|
||||||
#dump:hover, #dump:focus {
|
#dump:hover, #dump:focus {
|
||||||
background: -webkit-linear-gradient(#FFF, #DDD);
|
background: -webkit-linear-gradient(#FFF, #DDD);
|
||||||
background: -moz-linear-gradient(#FFF, #DDD);
|
|
||||||
background: -o-linear-gradient(#FFF, #DDD);
|
|
||||||
background: linear-gradient(#FFF, #DDD);
|
background: linear-gradient(#FFF, #DDD);
|
||||||
}
|
}
|
||||||
#dump:active, .dump #dump:not(:hover):not(:focus) {
|
#dump:active, .dump #dump:not(:hover):not(:focus) {
|
||||||
background: -webkit-linear-gradient(#CCC, #DDD);
|
background: -webkit-linear-gradient(#CCC, #DDD);
|
||||||
background: -moz-linear-gradient(#CCC, #DDD);
|
|
||||||
background: -o-linear-gradient(#CCC, #DDD);
|
|
||||||
background: linear-gradient(#CCC, #DDD);
|
background: linear-gradient(#CCC, #DDD);
|
||||||
}
|
}
|
||||||
#qr:not(.dump) #replies, .dump > form > label {
|
#qr:not(.dump) #replies, .dump > form > label {
|
||||||
@ -322,7 +338,7 @@ a[href="javascript:;"] {
|
|||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
#replies > div {
|
#replies > div {
|
||||||
counter-reset: thumbnails;
|
counter-reset: qrpreviews;
|
||||||
top: 0; right: 0; bottom: 0; left: 0;
|
top: 0; right: 0; bottom: 0; left: 0;
|
||||||
margin: 0; padding: 0;
|
margin: 0; padding: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -334,103 +350,72 @@ a[href="javascript:;"] {
|
|||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
.thumbnail {
|
.qrpreview {
|
||||||
background-color: rgba(0,0,0,.2) !important;
|
background-position: 50% 20%;
|
||||||
background-position: 50% 20% !important;
|
background-size: cover;
|
||||||
background-size: cover !important;
|
border: 1px solid #808080;
|
||||||
border: 1px solid #666;
|
color: #FFF !important;
|
||||||
box-sizing: border-box;
|
font-size: 12px;
|
||||||
-moz-box-sizing: border-box;
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
cursor: move;
|
cursor: move;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 90px; width: 90px;
|
height: 90px; width: 90px;
|
||||||
margin: 5px; padding: 2px;
|
margin: 5px; padding: 2px;
|
||||||
opacity: .5;
|
opacity: .6;
|
||||||
outline: none;
|
outline: none;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
text-shadow: 0 1px 1px #000;
|
text-shadow: 0 1px 1px #000;
|
||||||
-webkit-transition: opacity .25s ease-in-out;
|
-webkit-transition: opacity .25s ease-in-out;
|
||||||
-moz-transition: opacity .25s ease-in-out;
|
|
||||||
-o-transition: opacity .25s ease-in-out;
|
|
||||||
transition: opacity .25s ease-in-out;
|
transition: opacity .25s ease-in-out;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
.thumbnail:hover, .thumbnail:focus {
|
.qrpreview:hover, .qrpreview:focus {
|
||||||
opacity: .9;
|
opacity: .9;
|
||||||
|
color: #FFF !important;
|
||||||
}
|
}
|
||||||
.thumbnail#selected {
|
.qrpreview#selected {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.thumbnail::before {
|
.qrpreview::before {
|
||||||
counter-increment: thumbnails;
|
counter-increment: qrpreviews;
|
||||||
content: counter(thumbnails);
|
content: counter(qrpreviews);
|
||||||
color: #FFF;
|
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
padding: 3px;
|
text-shadow: 0 0 3px #000, 0 0 5px #000;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 3px; right: 3px;
|
||||||
right: 0;
|
|
||||||
text-shadow: 0 0 3px #000, 0 0 8px #000;
|
|
||||||
}
|
}
|
||||||
.thumbnail.drag {
|
.qrpreview.drag {
|
||||||
box-shadow: 0 0 10px rgba(0,0,0,.5);
|
border-color: red;
|
||||||
|
border-style: dashed;
|
||||||
}
|
}
|
||||||
.thumbnail.over {
|
.qrpreview.over {
|
||||||
border-color: #FFF;
|
border-color: #FFF;
|
||||||
}
|
border-style: dashed;
|
||||||
.thumbnail > span {
|
|
||||||
color: #FFF;
|
|
||||||
}
|
}
|
||||||
.remove {
|
.remove {
|
||||||
background: none;
|
color: #E00 !important;
|
||||||
color: #E00;
|
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
}
|
}
|
||||||
.remove:hover::after {
|
.remove:hover::after {
|
||||||
content: " Remove";
|
content: ' Remove';
|
||||||
}
|
}
|
||||||
.thumbnail > label {
|
.qrpreview > label {
|
||||||
background: rgba(0,0,0,.5);
|
background: rgba(0, 0, 0, .5);
|
||||||
color: #FFF;
|
|
||||||
right: 0; bottom: 0; left: 0;
|
right: 0; bottom: 0; left: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
.thumbnail > label > input {
|
.qrpreview > label > input {
|
||||||
margin: 0;
|
margin: 1px 0;
|
||||||
|
vertical-align: bottom;
|
||||||
}
|
}
|
||||||
#addReply {
|
#addReply {
|
||||||
color: #333;
|
|
||||||
font-size: 3.5em;
|
font-size: 3.5em;
|
||||||
line-height: 100px;
|
line-height: 100px;
|
||||||
}
|
}
|
||||||
#addReply:hover, #addReply:focus {
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
.field {
|
|
||||||
border: 1px solid #CCC;
|
|
||||||
box-sizing: border-box;
|
|
||||||
-moz-box-sizing: border-box;
|
|
||||||
color: #333;
|
|
||||||
font: 13px sans-serif;
|
|
||||||
margin: 0;
|
|
||||||
padding: 2px 4px 3px;
|
|
||||||
-webkit-transition: color .25s, border .25s;
|
|
||||||
-moz-transition: color .25s, border .25s;
|
|
||||||
-o-transition: color .25s, border .25s;
|
|
||||||
transition: color .25s, border .25s;
|
|
||||||
}
|
|
||||||
.field:-moz-placeholder,
|
|
||||||
.field:hover:-moz-placeholder {
|
|
||||||
color: #AAA;
|
|
||||||
}
|
|
||||||
.field:hover, .field:focus {
|
|
||||||
border-color: #999;
|
|
||||||
color: #000;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
#qr > form > div:first-child > .field:not(#dump) {
|
#qr > form > div:first-child > .field:not(#dump) {
|
||||||
width: 30%;
|
width: 30%;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,9 @@
|
|||||||
background-color: #282A2E;
|
background-color: #282A2E;
|
||||||
border-color: #111;
|
border-color: #111;
|
||||||
}
|
}
|
||||||
|
:root.tomorrow .field:focus {
|
||||||
|
border-color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
/* Header */
|
/* Header */
|
||||||
:root.tomorrow #header-bar {
|
:root.tomorrow #header-bar {
|
||||||
@ -19,6 +22,11 @@
|
|||||||
background-color: rgba(0, 0, 0, .14);
|
background-color: rgba(0, 0, 0, .14);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* QR */
|
||||||
|
:root.tomorrow .qrpreview {
|
||||||
|
background-color: rgba(255, 255, 255, .15);
|
||||||
|
}
|
||||||
|
|
||||||
/* Menu */
|
/* Menu */
|
||||||
:root.tomorrow .entry:not(:last-child) {
|
:root.tomorrow .entry:not(:last-child) {
|
||||||
border-bottom: 1px solid #111;
|
border-bottom: 1px solid #111;
|
||||||
|
|||||||
@ -3,6 +3,9 @@
|
|||||||
background-color: #D6DAF0;
|
background-color: #D6DAF0;
|
||||||
border-color: #B7C5D9;
|
border-color: #B7C5D9;
|
||||||
}
|
}
|
||||||
|
:root.yotsuba-b .field:focus {
|
||||||
|
border-color: #98E;
|
||||||
|
}
|
||||||
|
|
||||||
/* Header */
|
/* Header */
|
||||||
:root.yotsuba-b #header-bar {
|
:root.yotsuba-b #header-bar {
|
||||||
@ -19,6 +22,11 @@
|
|||||||
background-color: rgba(255, 255, 255, .14);
|
background-color: rgba(255, 255, 255, .14);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* QR */
|
||||||
|
:root.yotsuba-b .qrpreview {
|
||||||
|
background-color: rgba(0, 0, 0, .15);
|
||||||
|
}
|
||||||
|
|
||||||
/* Menu */
|
/* Menu */
|
||||||
:root.yotsuba-b .entry:not(:last-child) {
|
:root.yotsuba-b .entry:not(:last-child) {
|
||||||
border-bottom: 1px solid #B7C5D9;
|
border-bottom: 1px solid #B7C5D9;
|
||||||
|
|||||||
@ -3,6 +3,9 @@
|
|||||||
background-color: #F0E0D6;
|
background-color: #F0E0D6;
|
||||||
border-color: #D9BFB7;
|
border-color: #D9BFB7;
|
||||||
}
|
}
|
||||||
|
:root.yotsuba .field:focus {
|
||||||
|
border-color: #EA8;
|
||||||
|
}
|
||||||
|
|
||||||
/* Header */
|
/* Header */
|
||||||
:root.yotsuba #header-bar {
|
:root.yotsuba #header-bar {
|
||||||
@ -19,6 +22,11 @@
|
|||||||
background-color: rgba(255, 255, 255, .14);
|
background-color: rgba(255, 255, 255, .14);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* QR */
|
||||||
|
:root.yotsuba .qrpreview {
|
||||||
|
background-color: rgba(0, 0, 0, .15);
|
||||||
|
}
|
||||||
|
|
||||||
/* Menu */
|
/* Menu */
|
||||||
:root.yotsuba .entry:not(:last-child) {
|
:root.yotsuba .entry:not(:last-child) {
|
||||||
border-bottom: 1px solid #D9BFB7;
|
border-bottom: 1px solid #D9BFB7;
|
||||||
|
|||||||
@ -45,7 +45,6 @@ Config =
|
|||||||
'Quick Reply': [true, 'WMD.']
|
'Quick Reply': [true, 'WMD.']
|
||||||
'Persistent QR': [false, 'The Quick reply won\'t disappear after posting.']
|
'Persistent QR': [false, 'The Quick reply won\'t disappear after posting.']
|
||||||
'Auto Hide QR': [false, 'Automatically hide the quick reply when posting.']
|
'Auto Hide QR': [false, 'Automatically hide the quick reply when posting.']
|
||||||
'Open Reply in New Tab': [false, 'Open replies posted from the board pages in a new tab.']
|
|
||||||
'Remember Subject': [false, 'Remember the subject field, instead of resetting after posting.']
|
'Remember Subject': [false, 'Remember the subject field, instead of resetting after posting.']
|
||||||
'Remember Spoiler': [false, 'Remember the spoiler state, instead of resetting after posting.']
|
'Remember Spoiler': [false, 'Remember the spoiler state, instead of resetting after posting.']
|
||||||
'Hide Original Post Form': [true, 'Replace the normal post form with a shortcut to open the QR.']
|
'Hide Original Post Form': [true, 'Replace the normal post form with a shortcut to open the QR.']
|
||||||
|
|||||||
@ -762,38 +762,41 @@ Recursive =
|
|||||||
|
|
||||||
QR =
|
QR =
|
||||||
init: ->
|
init: ->
|
||||||
return unless Conf['Quick Reply']
|
return if g.VIEW is 'catalog' or !Conf['Quick Reply']
|
||||||
|
|
||||||
if Conf['Hide Original Post Form']
|
if Conf['Hide Original Post Form']
|
||||||
Main.css += """
|
$.addClass doc, 'hide-original-post-form'
|
||||||
#postForm, .postingMode {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
link = $.el 'a',
|
link = $.el 'a',
|
||||||
|
className: 'qr-shortcut'
|
||||||
textContent: 'Quick Reply'
|
textContent: 'Quick Reply'
|
||||||
href: 'javascript:;'
|
href: 'javascript:;'
|
||||||
$.on link, 'click', ->
|
$.on link, 'click', ->
|
||||||
Header.menu.close()
|
Header.menu.close()
|
||||||
QR.open()
|
QR.open()
|
||||||
|
if g.BOARD.ID is 'f'
|
||||||
|
if g.VIEW is 'index'
|
||||||
|
QR.threadSelector.value = '9999'
|
||||||
|
else if g.VIEW is 'thread'
|
||||||
|
QR.threadSelector.value = g.THREAD
|
||||||
|
else
|
||||||
|
QR.threadSelector.value = 'new'
|
||||||
|
$('textarea', QR.el).focus()
|
||||||
$.event 'AddMenuEntry',
|
$.event 'AddMenuEntry',
|
||||||
type: 'header'
|
type: 'header'
|
||||||
el: link
|
el: link
|
||||||
|
|
||||||
Post::callbacks.push
|
|
||||||
name: 'Quick Reply'
|
|
||||||
cb: @node
|
|
||||||
|
|
||||||
$.ready @readyInit
|
|
||||||
|
|
||||||
readyInit: ->
|
|
||||||
if Conf['Persistent QR']
|
|
||||||
QR.open()
|
|
||||||
QR.hide() if Conf['Auto Hide QR']
|
|
||||||
$.on d, 'dragover', QR.dragOver
|
$.on d, 'dragover', QR.dragOver
|
||||||
$.on d, 'drop', QR.dropFile
|
$.on d, 'drop', QR.dropFile
|
||||||
$.on d, 'dragstart dragend', QR.drag
|
$.on d, 'dragstart dragend', QR.drag
|
||||||
|
$.on d, '4chanXInitFinished', ->
|
||||||
|
return unless Conf['Persistent QR']
|
||||||
|
QR.open()
|
||||||
|
QR.hide() if Conf['Auto Hide QR']
|
||||||
|
|
||||||
|
Post::callbacks.push
|
||||||
|
name: 'Quick Reply'
|
||||||
|
cb: @node
|
||||||
|
|
||||||
node: ->
|
node: ->
|
||||||
$.on $('a[title="Quote this post"]', @nodes.info), 'click', QR.quote
|
$.on $('a[title="Quote this post"]', @nodes.info), 'click', QR.quote
|
||||||
@ -802,13 +805,14 @@ QR =
|
|||||||
if QR.el
|
if QR.el
|
||||||
QR.el.hidden = false
|
QR.el.hidden = false
|
||||||
QR.unhide()
|
QR.unhide()
|
||||||
else
|
return
|
||||||
try
|
try
|
||||||
QR.dialog()
|
QR.dialog()
|
||||||
catch err
|
catch err
|
||||||
Main.handleErrors
|
delete QR.el
|
||||||
message: 'Quick Reply dialog creation crashed.'
|
Main.handleErrors
|
||||||
error: err
|
message: 'Quick Reply dialog creation crashed.'
|
||||||
|
error: err
|
||||||
close: ->
|
close: ->
|
||||||
QR.el.hidden = true
|
QR.el.hidden = true
|
||||||
QR.abort()
|
QR.abort()
|
||||||
@ -821,7 +825,7 @@ QR =
|
|||||||
QR.resetFileInput()
|
QR.resetFileInput()
|
||||||
if not Conf['Remember Spoiler'] and (spoiler = $.id 'spoiler').checked
|
if not Conf['Remember Spoiler'] and (spoiler = $.id 'spoiler').checked
|
||||||
spoiler.click()
|
spoiler.click()
|
||||||
QR.cleanError()
|
QR.cleanNotification()
|
||||||
hide: ->
|
hide: ->
|
||||||
d.activeElement.blur()
|
d.activeElement.blur()
|
||||||
$.addClass QR.el, 'autohide'
|
$.addClass QR.el, 'autohide'
|
||||||
@ -830,7 +834,10 @@ QR =
|
|||||||
$.rmClass QR.el, 'autohide'
|
$.rmClass QR.el, 'autohide'
|
||||||
$.id('autohide').checked = false
|
$.id('autohide').checked = false
|
||||||
toggleHide: ->
|
toggleHide: ->
|
||||||
@checked and QR.hide() or QR.unhide()
|
if @checked
|
||||||
|
QR.hide()
|
||||||
|
else
|
||||||
|
QR.unhide()
|
||||||
|
|
||||||
error: (err) ->
|
error: (err) ->
|
||||||
QR.open()
|
QR.open()
|
||||||
@ -844,20 +851,20 @@ QR =
|
|||||||
$('[autocomplete]', QR.el).focus()
|
$('[autocomplete]', QR.el).focus()
|
||||||
alert el.textContent if d.hidden
|
alert el.textContent if d.hidden
|
||||||
QR.lastNotification = new Notification 'warning', el
|
QR.lastNotification = new Notification 'warning', el
|
||||||
cleanError: ->
|
cleanNotification: ->
|
||||||
QR.lastNotification?.close()
|
QR.lastNotification?.close()
|
||||||
delete QR.lastNotification
|
delete QR.lastNotification
|
||||||
|
|
||||||
status: (data={}) ->
|
status: (data={}) ->
|
||||||
return unless QR.el
|
return unless QR.el
|
||||||
if g.dead
|
if g.dead # XXX
|
||||||
value = 404
|
value = 404
|
||||||
disabled = true
|
disabled = true
|
||||||
QR.cooldown.auto = false
|
QR.cooldown.auto = false
|
||||||
value = data.progress or QR.cooldown.seconds or value
|
value = data.progress or QR.cooldown.seconds or value
|
||||||
{input} = QR.status
|
{input} = QR.status
|
||||||
input.value =
|
input.value =
|
||||||
if QR.cooldown.auto and Conf['Cooldown']
|
if QR.cooldown.auto
|
||||||
if value then "Auto #{value}" else 'Auto'
|
if value then "Auto #{value}" else 'Auto'
|
||||||
else
|
else
|
||||||
value or 'Submit'
|
value or 'Submit'
|
||||||
@ -865,7 +872,6 @@ QR =
|
|||||||
|
|
||||||
cooldown:
|
cooldown:
|
||||||
init: ->
|
init: ->
|
||||||
return unless Conf['Cooldown']
|
|
||||||
QR.cooldown.types =
|
QR.cooldown.types =
|
||||||
thread: switch g.BOARD
|
thread: switch g.BOARD
|
||||||
when 'q' then 86400
|
when 'q' then 86400
|
||||||
@ -883,12 +889,11 @@ QR =
|
|||||||
QR.cooldown.count()
|
QR.cooldown.count()
|
||||||
sync: (cooldowns) ->
|
sync: (cooldowns) ->
|
||||||
# Add each cooldowns, don't overwrite everything in case we
|
# Add each cooldowns, don't overwrite everything in case we
|
||||||
# still need to purge one in the current tab to auto-post.
|
# still need to prune one in the current tab to auto-post.
|
||||||
for id of cooldowns
|
for id of cooldowns
|
||||||
QR.cooldown.cooldowns[id] = cooldowns[id]
|
QR.cooldown.cooldowns[id] = cooldowns[id]
|
||||||
QR.cooldown.start()
|
QR.cooldown.start()
|
||||||
set: (data) ->
|
set: (data) ->
|
||||||
return unless Conf['Cooldown']
|
|
||||||
start = Date.now()
|
start = Date.now()
|
||||||
if data.delay
|
if data.delay
|
||||||
cooldown = delay: data.delay
|
cooldown = delay: data.delay
|
||||||
@ -926,7 +931,12 @@ QR =
|
|||||||
QR.status()
|
QR.status()
|
||||||
return
|
return
|
||||||
|
|
||||||
if (isReply = if g.REPLY then true else QR.threadSelector.value isnt 'new')
|
isReply =
|
||||||
|
if g.BOARD.ID is 'f' and g.VIEW is 'thread'
|
||||||
|
true
|
||||||
|
else
|
||||||
|
QR.threadSelector.value isnt 'new'
|
||||||
|
if isReply
|
||||||
post = QR.replies[0]
|
post = QR.replies[0]
|
||||||
isSage = /sage/i.test post.email
|
isSage = /sage/i.test post.email
|
||||||
hasFile = !!post.file
|
hasFile = !!post.file
|
||||||
@ -973,14 +983,15 @@ QR =
|
|||||||
e?.preventDefault()
|
e?.preventDefault()
|
||||||
QR.open()
|
QR.open()
|
||||||
ta = $ 'textarea', QR.el
|
ta = $ 'textarea', QR.el
|
||||||
unless g.REPLY or ta.value
|
if QR.threadSelector and !ta.value and g.BOARD.ID isnt 'f'
|
||||||
QR.threadSelector.value = $.x('ancestor::div[parent::div[@class="board"]]', @).id[1..]
|
QR.threadSelector.value = $.x('ancestor::div[parent::div[@class="board"]]', @).id[1..]
|
||||||
# Make sure we get the correct number, even with XXX censors
|
# Make sure we get the correct number, even with XXX censors
|
||||||
id = @previousSibling.hash[2..]
|
post = Get.postFromRoot $.x 'ancestor-or-self::div[contains(@class,"postContainer")][1]', @
|
||||||
text = ">>#{id}\n"
|
text = ">>#{post}\n"
|
||||||
|
|
||||||
sel = d.getSelection()
|
sel = d.getSelection()
|
||||||
if (s = sel.toString().trim()) and id is $.x('ancestor-or-self::blockquote', sel.anchorNode)?.id.match(/\d+$/)[0]
|
selectionRoot = $.x 'ancestor-or-self::div[contains(@class,"postContainer")][1]', sel.anchorNode
|
||||||
|
if (s = sel.toString().trim()) and post.nodes.root is selectionRoot
|
||||||
# XXX Opera doesn't retain `\n`s?
|
# XXX Opera doesn't retain `\n`s?
|
||||||
s = s.replace /\n/g, '\n>'
|
s = s.replace /\n/g, '\n>'
|
||||||
text += ">#{s}\n"
|
text += ">#{s}\n"
|
||||||
@ -1019,7 +1030,7 @@ QR =
|
|||||||
QR.fileInput.call e.dataTransfer
|
QR.fileInput.call e.dataTransfer
|
||||||
$.addClass QR.el, 'dump'
|
$.addClass QR.el, 'dump'
|
||||||
fileInput: ->
|
fileInput: ->
|
||||||
QR.cleanError()
|
QR.cleanNotification()
|
||||||
# Set or change current reply's file.
|
# Set or change current reply's file.
|
||||||
if @files.length is 1
|
if @files.length is 1
|
||||||
file = @files[0]
|
file = @files[0]
|
||||||
@ -1063,7 +1074,7 @@ QR =
|
|||||||
@com = null
|
@com = null
|
||||||
|
|
||||||
@el = $.el 'a',
|
@el = $.el 'a',
|
||||||
className: 'thumbnail'
|
className: 'qrpreview'
|
||||||
draggable: true
|
draggable: true
|
||||||
href: 'javascript:;'
|
href: 'javascript:;'
|
||||||
innerHTML: '<a class=remove>×</a><label hidden><input type=checkbox> Spoiler</label><span></span>'
|
innerHTML: '<a class=remove>×</a><label hidden><input type=checkbox> Spoiler</label><span></span>'
|
||||||
@ -1187,7 +1198,7 @@ QR =
|
|||||||
else if @el.id is 'selected'
|
else if @el.id is 'selected'
|
||||||
(QR.replies[index-1] or QR.replies[index+1]).select()
|
(QR.replies[index-1] or QR.replies[index+1]).select()
|
||||||
QR.replies.splice index, 1
|
QR.replies.splice index, 1
|
||||||
(window.URL or window.webkitURL).revokeObjectURL? @url
|
(window.URL or window.webkitURL)?.revokeObjectURL @url
|
||||||
|
|
||||||
captcha:
|
captcha:
|
||||||
init: ->
|
init: ->
|
||||||
@ -1235,9 +1246,8 @@ QR =
|
|||||||
@count captchas.length
|
@count captchas.length
|
||||||
@reload()
|
@reload()
|
||||||
load: ->
|
load: ->
|
||||||
# Timeout is available at RecaptchaState.timeout in seconds.
|
# -1 minute to give upload some time.
|
||||||
# We use 5-1 minutes to give upload some time.
|
@timeout = Date.now() + $.unsafeWindow.RecaptchaState.timeout * $.SECOND - $.MINUTE
|
||||||
@timeout = Date.now() + 4*$.MINUTE
|
|
||||||
challenge = @challenge.firstChild.value
|
challenge = @challenge.firstChild.value
|
||||||
@img.alt = challenge
|
@img.alt = challenge
|
||||||
@img.src = "//www.google.com/recaptcha/api/image?c=#{challenge}"
|
@img.src = "//www.google.com/recaptcha/api/image?c=#{challenge}"
|
||||||
@ -1252,8 +1262,8 @@ QR =
|
|||||||
"Verification (#{count} cached captchas)"
|
"Verification (#{count} cached captchas)"
|
||||||
@input.alt = count # For XTRM RICE.
|
@input.alt = count # For XTRM RICE.
|
||||||
reload: (focus) ->
|
reload: (focus) ->
|
||||||
# the "t" argument prevents the input from being focused
|
# the 't' argument prevents the input from being focused
|
||||||
$.globalEval 'javascript:Recaptcha.reload("t")'
|
$.unsafeWindow.Recaptcha.reload 'r'
|
||||||
# Focus if we meant to.
|
# Focus if we meant to.
|
||||||
QR.captcha.input.focus() if focus
|
QR.captcha.input.focus() if focus
|
||||||
keydown: (e) ->
|
keydown: (e) ->
|
||||||
@ -1267,23 +1277,16 @@ QR =
|
|||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
||||||
dialog: ->
|
dialog: ->
|
||||||
QR.el = UI.dialog 'qr', 'top:0;right:0;', '
|
QR.el = UI.dialog 'qr', 'top:0;right:0;', """
|
||||||
<div class=move>
|
<div class=move>Quick Reply <input type=checkbox id=autohide title=Auto-hide><span> <a class=close title=Close>×</a></span></div>
|
||||||
Quick Reply <input type=checkbox id=autohide title=Auto-hide>
|
<form>
|
||||||
<span> <a class=close title=Close>×</a></span>
|
<div class=persona><input id=dump type=button title='Dump list' value=+><input name=name title=Name placeholder=Name class=field size=1><input name=email title=E-mail placeholder=E-mail class=field size=1><input name=sub title=Subject placeholder=Subject class=field size=1></div>
|
||||||
</div>
|
<div id=replies><div id=repliesList><a id=addReply href=javascript:; title="Add a reply">+</a></div></div>
|
||||||
<form>
|
<div class=textarea><textarea name=com title=Comment placeholder=Comment class=field></textarea><span id=charCount></span></div>
|
||||||
<div><input id=dump type=button title="Dump list" value=+ class=field><input name=name title=Name placeholder=Name class=field size=1><input name=email title=E-mail placeholder=E-mail class=field size=1><input name=sub title=Subject placeholder=Subject class=field size=1></div>
|
<div><input type=file title="Shift+Click to remove the selected file." multiple size=16><input type=submit></div>
|
||||||
<div id=replies><div><a id=addReply href=javascript:; title="Add a reply">+</a></div></div>
|
<label id=spoilerLabel><input type=checkbox id=spoiler> Spoiler Image</label>
|
||||||
<div class=textarea><textarea name=com title=Comment placeholder=Comment class=field></textarea><span id=charCount></span></div>
|
</form>
|
||||||
<div><input type=file title="Shift+Click to remove the selected file." multiple size=16><input type=submit></div>
|
"""
|
||||||
<label id=spoilerLabel><input type=checkbox id=spoiler> Spoiler Image</label>
|
|
||||||
</form>'
|
|
||||||
|
|
||||||
if Conf['Remember QR size'] and $.engine is 'gecko'
|
|
||||||
$.on ta = $('textarea', QR.el), 'mouseup', ->
|
|
||||||
$.set 'QR.size', @style.cssText
|
|
||||||
ta.style.cssText = $.get 'QR.size', ''
|
|
||||||
|
|
||||||
# Allow only this board's supported files.
|
# Allow only this board's supported files.
|
||||||
mimeTypes = $('ul.rules').firstElementChild.textContent.trim().match(/: (.+)/)[1].toLowerCase().replace /\w+/g, (type) ->
|
mimeTypes = $('ul.rules').firstElementChild.textContent.trim().match(/: (.+)/)[1].toLowerCase().replace /\w+/g, (type) ->
|
||||||
@ -1310,21 +1313,24 @@ QR =
|
|||||||
QR.charaCounter = $ '#charCount', QR.el
|
QR.charaCounter = $ '#charCount', QR.el
|
||||||
ta = $ 'textarea', QR.el
|
ta = $ 'textarea', QR.el
|
||||||
|
|
||||||
unless g.REPLY
|
span = $('.move > span', QR.el)
|
||||||
# Make a list with visible threads and an option to create a new one.
|
|
||||||
|
# Make a list of visible threads.
|
||||||
|
if g.BOARD.ID is 'f'
|
||||||
|
if g.VIEW is 'index'
|
||||||
|
QR.threadSelector = $('select[name=filetag]').cloneNode true
|
||||||
|
else
|
||||||
|
QR.threadSelector = $.el 'select',
|
||||||
|
title: 'Create a new thread / Reply to a thread'
|
||||||
threads = '<option value=new>New thread</option>'
|
threads = '<option value=new>New thread</option>'
|
||||||
for thread in $$ '.thread'
|
for key, thread of g.BOARD.threads
|
||||||
id = thread.id[1..]
|
threads += "<option value=#{thread.ID}>Thread No.#{thread.ID}</option>"
|
||||||
threads += "<option value=#{id}>Thread #{id}</option>"
|
QR.threadSelector.innerHTML = threads
|
||||||
QR.threadSelector =
|
if g.VIEW is 'thread'
|
||||||
if g.BOARD is 'f'
|
QR.threadSelector.value = g.THREAD
|
||||||
$('select[name=filetag]').cloneNode true
|
if QR.threadSelector
|
||||||
else
|
$.prepend span, QR.threadSelector
|
||||||
$.el 'select'
|
$.on span, 'mousedown', (e) -> e.stopPropagation()
|
||||||
innerHTML: threads
|
|
||||||
title: 'Create a new thread / Reply to a thread'
|
|
||||||
$.prepend $('.move > span', QR.el), QR.threadSelector
|
|
||||||
$.on QR.threadSelector, 'mousedown', (e) -> e.stopPropagation()
|
|
||||||
$.on $('#autohide', QR.el), 'change', QR.toggleHide
|
$.on $('#autohide', QR.el), 'change', QR.toggleHide
|
||||||
$.on $('.close', QR.el), 'click', QR.close
|
$.on $('.close', QR.el), 'click', QR.close
|
||||||
$.on $('#dump', QR.el), 'click', -> QR.el.classList.toggle 'dump'
|
$.on $('#dump', QR.el), 'click', -> QR.el.classList.toggle 'dump'
|
||||||
@ -1366,20 +1372,20 @@ QR =
|
|||||||
QR.abort()
|
QR.abort()
|
||||||
|
|
||||||
reply = QR.replies[0]
|
reply = QR.replies[0]
|
||||||
if g.BOARD is 'f' and not g.REPLY
|
if g.BOARD.ID is 'f' and g.VIEW is 'index'
|
||||||
filetag = QR.threadSelector.value
|
filetag = QR.threadSelector.value
|
||||||
threadID = 'new'
|
threadID = 'new'
|
||||||
else
|
else
|
||||||
threadID = g.THREAD_ID or QR.threadSelector.value
|
threadID = QR.threadSelector.value
|
||||||
|
|
||||||
# prevent errors
|
# prevent errors
|
||||||
if threadID is 'new'
|
if threadID is 'new'
|
||||||
threadID = null
|
threadID = null
|
||||||
if g.BOARD in ['vg', 'q'] and !reply.sub
|
if g.BOARD.ID in ['vg', 'q'] and !reply.sub
|
||||||
err = 'New threads require a subject.'
|
err = 'New threads require a subject.'
|
||||||
else unless reply.file or textOnly = !!$ 'input[name=textonly]', $.id 'postForm'
|
else unless reply.file or textOnly = !!$ 'input[name=textonly]', $.id 'postForm'
|
||||||
err = 'No file selected.'
|
err = 'No file selected.'
|
||||||
else if g.BOARD is 'f' and filetag is '9999'
|
else if g.BOARD.ID is 'f' and filetag is '9999'
|
||||||
err = 'Invalid tag specified.'
|
err = 'Invalid tag specified.'
|
||||||
else unless reply.com or reply.file
|
else unless reply.com or reply.file
|
||||||
err = 'No file selected.'
|
err = 'No file selected.'
|
||||||
@ -1412,7 +1418,7 @@ QR =
|
|||||||
QR.status()
|
QR.status()
|
||||||
QR.error err
|
QR.error err
|
||||||
return
|
return
|
||||||
QR.cleanError()
|
QR.cleanNotification()
|
||||||
|
|
||||||
# Enable auto-posting if we have stuff to post, disable it otherwise.
|
# Enable auto-posting if we have stuff to post, disable it otherwise.
|
||||||
QR.cooldown.auto = QR.replies.length > 1
|
QR.cooldown.auto = QR.replies.length > 1
|
||||||
@ -1530,14 +1536,13 @@ QR =
|
|||||||
post: reply
|
post: reply
|
||||||
isReply: threadID isnt '0'
|
isReply: threadID isnt '0'
|
||||||
|
|
||||||
|
# Enable auto-posting if we have stuff to post, disable it otherwise.
|
||||||
|
QR.cooldown.auto = QR.replies.length > 1
|
||||||
|
|
||||||
if threadID is '0' # new thread
|
if threadID is '0' # new thread
|
||||||
# auto-noko
|
$.open "/#{g.BOARD}/res/#{postID}"
|
||||||
location.pathname = "/#{g.BOARD}/res/#{postID}"
|
else if g.VIEW is 'reply' and !QR.cooldown.auto # posting from the index
|
||||||
else
|
$.open "//boards.4chan.org/#{g.BOARD}/res/#{threadID}#p#{postID}"
|
||||||
# Enable auto-posting if we have stuff to post, disable it otherwise.
|
|
||||||
QR.cooldown.auto = QR.replies.length > 1
|
|
||||||
if Conf['Open Reply in New Tab'] and !g.REPLY and !QR.cooldown.auto
|
|
||||||
$.open "//boards.4chan.org/#{g.BOARD}/res/#{threadID}#p#{postID}"
|
|
||||||
|
|
||||||
if Conf['Persistent QR'] or QR.cooldown.auto
|
if Conf['Persistent QR'] or QR.cooldown.auto
|
||||||
reply.rm()
|
reply.rm()
|
||||||
@ -2092,7 +2097,7 @@ Build =
|
|||||||
'<br><em>' +
|
'<br><em>' +
|
||||||
"<a href=#{"/#{board}/res/#{threadID}#p#{postID}"}>No.</a>" +
|
"<a href=#{"/#{board}/res/#{threadID}#p#{postID}"}>No.</a>" +
|
||||||
"<a href='#{
|
"<a href='#{
|
||||||
if g.VIEW is 'thread' and g.THREAD is threadID
|
if g.VIEW is 'thread' and g.THREAD is +threadID
|
||||||
"javascript:quote(#{postID})"
|
"javascript:quote(#{postID})"
|
||||||
else
|
else
|
||||||
"/#{board}/res/#{threadID}#q#{postID}"
|
"/#{board}/res/#{threadID}#q#{postID}"
|
||||||
@ -2114,7 +2119,7 @@ Build =
|
|||||||
"<span class='postNum desktop'>" +
|
"<span class='postNum desktop'>" +
|
||||||
"<a href=#{"/#{board}/res/#{threadID}#p#{postID}"} title='Highlight this post'>No.</a>" +
|
"<a href=#{"/#{board}/res/#{threadID}#p#{postID}"} title='Highlight this post'>No.</a>" +
|
||||||
"<a href='#{
|
"<a href='#{
|
||||||
if g.VIEW is 'thread' and g.THREAD is threadID
|
if g.VIEW is 'thread' and g.THREAD is +threadID
|
||||||
"javascript:quote(#{postID})"
|
"javascript:quote(#{postID})"
|
||||||
else
|
else
|
||||||
"/#{board}/res/#{threadID}#q#{postID}"
|
"/#{board}/res/#{threadID}#q#{postID}"
|
||||||
|
|||||||
@ -148,10 +148,13 @@ class Post
|
|||||||
@kill() if that.isArchived
|
@kill() if that.isArchived
|
||||||
|
|
||||||
kill: (img) ->
|
kill: (img) ->
|
||||||
|
now = Date.now()
|
||||||
if @file and !@file.isDead
|
if @file and !@file.isDead
|
||||||
@file.isDead = true
|
@file.isDead = true
|
||||||
|
@file.timeOfDeath = now
|
||||||
return if img
|
return if img
|
||||||
@isDead = true
|
@isDead = true
|
||||||
|
@timeOfDeath = now
|
||||||
$.addClass @nodes.root, 'dead'
|
$.addClass @nodes.root, 'dead'
|
||||||
# XXX style dead posts.
|
# XXX style dead posts.
|
||||||
|
|
||||||
@ -325,21 +328,22 @@ Main =
|
|||||||
initStyle: ->
|
initStyle: ->
|
||||||
# disable the mobile layout
|
# disable the mobile layout
|
||||||
$('link[href*=mobile]', d.head)?.disabled = true
|
$('link[href*=mobile]', d.head)?.disabled = true
|
||||||
|
$.addClass doc, $.engine
|
||||||
|
$.addClass doc, 'fourchan-x'
|
||||||
$.addStyle Main.css
|
$.addStyle Main.css
|
||||||
|
|
||||||
style = null
|
style = 'yotsuba-b'
|
||||||
mainStyleSheet = $ 'link[title=switch]', d.head
|
mainStyleSheet = $ 'link[title=switch]', d.head
|
||||||
styleSheets = $$ 'link[rel="alternate stylesheet"]', d.head
|
styleSheets = $$ 'link[rel="alternate stylesheet"]', d.head
|
||||||
setStyle = ->
|
setStyle = ->
|
||||||
$.rmClass doc, style if style
|
$.rmClass doc, style
|
||||||
for styleSheet in styleSheets
|
for styleSheet in styleSheets
|
||||||
if styleSheet.href is mainStyleSheet.href
|
if styleSheet.href is mainStyleSheet.href
|
||||||
style = styleSheet.title.toLowerCase().replace('new', '').trim().replace /\s+/g, '-'
|
style = styleSheet.title.toLowerCase().replace('new', '').trim().replace /\s+/g, '-'
|
||||||
break
|
break
|
||||||
$.addClass doc, style
|
$.addClass doc, style
|
||||||
$.addClass doc, $.engine
|
|
||||||
$.addClass doc, 'fourchan-x'
|
|
||||||
setStyle()
|
setStyle()
|
||||||
|
return unless mainStyleSheet
|
||||||
if MutationObserver = window.MutationObserver or window.WebKitMutationObserver or window.OMutationObserver
|
if MutationObserver = window.MutationObserver or window.WebKitMutationObserver or window.OMutationObserver
|
||||||
observer = new MutationObserver setStyle
|
observer = new MutationObserver setStyle
|
||||||
observer.observe mainStyleSheet,
|
observer.observe mainStyleSheet,
|
||||||
@ -351,7 +355,7 @@ Main =
|
|||||||
|
|
||||||
initReady: ->
|
initReady: ->
|
||||||
unless $.hasClass doc, 'fourchan-x'
|
unless $.hasClass doc, 'fourchan-x'
|
||||||
# Something might go wrong!
|
# Something might have gone wrong!
|
||||||
Main.initStyle()
|
Main.initStyle()
|
||||||
|
|
||||||
if d.title is '4chan - 404 Not Found'
|
if d.title is '4chan - 404 Not Found'
|
||||||
@ -362,28 +366,31 @@ Main =
|
|||||||
postID: location.hash
|
postID: location.hash
|
||||||
return
|
return
|
||||||
|
|
||||||
threads = []
|
if board = $ '.board'
|
||||||
posts = []
|
threads = []
|
||||||
|
posts = []
|
||||||
|
|
||||||
for boardChild in $('.board').children
|
for boardChild in board.children
|
||||||
continue unless $.hasClass boardChild, 'thread'
|
continue unless $.hasClass boardChild, 'thread'
|
||||||
thread = new Thread boardChild.id[1..], g.BOARD
|
thread = new Thread boardChild.id[1..], g.BOARD
|
||||||
threads.push thread
|
threads.push thread
|
||||||
for threadChild in boardChild.children
|
for threadChild in boardChild.children
|
||||||
continue unless $.hasClass threadChild, 'postContainer'
|
continue unless $.hasClass threadChild, 'postContainer'
|
||||||
try
|
try
|
||||||
posts.push new Post threadChild, thread, g.BOARD
|
posts.push new Post threadChild, thread, g.BOARD
|
||||||
catch err
|
catch err
|
||||||
# Skip posts that we failed to parse.
|
# Skip posts that we failed to parse.
|
||||||
unless errors
|
unless errors
|
||||||
errors = []
|
errors = []
|
||||||
errors.push
|
errors.push
|
||||||
message: "Parsing of Post No.#{threadChild.id.match(/\d+/)} failed. Post will be skipped."
|
message: "Parsing of Post No.#{threadChild.id.match(/\d+/)} failed. Post will be skipped."
|
||||||
error: err
|
error: err
|
||||||
Main.handleErrors errors if errors
|
Main.handleErrors errors if errors
|
||||||
|
|
||||||
Main.callbackNodes Thread, threads
|
Main.callbackNodes Thread, threads
|
||||||
Main.callbackNodes Post, posts
|
Main.callbackNodes Post, posts
|
||||||
|
|
||||||
|
$.event '4chanXInitFinished'
|
||||||
|
|
||||||
callbackNodes: (klass, nodes) ->
|
callbackNodes: (klass, nodes) ->
|
||||||
# get the nodes' length only once
|
# get the nodes' length only once
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user