diff --git a/.gitignore b/.gitignore index ac98c1cf1..3a51caaee 100644 --- a/.gitignore +++ b/.gitignore @@ -2,9 +2,14 @@ node_modules/ *~ *.db tmp-crx/ -tmp-userjs/ tmp-userscript/ +<<<<<<< HEAD builds/4chan-X.zip Gruntfile.js builds/4chan-* -Gruntfile.js \ No newline at end of file +Gruntfile.js +======= +builds/4chan-X-Chrome.zip +builds/4chan-X-Opera.nex +Gruntfile.js +>>>>>>> v3 diff --git a/CHANGELOG.md b/CHANGELOG.md index bbfb84a2e..3eb279eb0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,10 @@ **MayhemYDG**: - Remove /s4s/ from warosu archive - Fix CAPTCHA duplication on the report page -- Small bug fixes +- Fix impossibility to create new threads when in dead threads. +- Drop Opera <15 support. +- Fix flag filtering on /sp/ and /int/. +- Minor fixes. **seaweedchan**: - Add `.active` class to `.menu-button` when clicked (and remove on menu close) @@ -9,6 +12,10 @@ - Revert Mayhem's updater changes which caused silly issues - Rename `Indicate Spoilers` to `Reveal Spoilers` - If `Reveal Spoilers` is enabled but `Remove Spoilers` is not, act as if the spoiler is hovered +- Add a new option to hide "4chan X has been updated to ____" notifications for those having issues with them. +- Update archives +- Add `.active` class to `.menu-button` when clicked (and remove on menu close) +- Move /v/ and /vg/ back to Foolz archive **Tracerneo**: - Add ID styling for IDs with black text diff --git a/Gruntfile.coffee b/Gruntfile.coffee index 5ce5194e8..d2950c045 100644 --- a/Gruntfile.coffee +++ b/Gruntfile.coffee @@ -183,7 +183,6 @@ module.exports = (grunt) -> grunt.registerTask 'release', [ 'default' 'compress:crx' - 'copy:opera' 'shell:commit' 'shell:push' ] diff --git a/LICENSE b/LICENSE index 7ad5610f4..db93e531a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ /* -* appchan x - Version 2.1.3 - 2013-07-07 +* appchan x - Version 2.1.3 - 2013-07-21 * * Licensed under the MIT license. * https://github.com/zixaphir/appchan-x/blob/master/LICENSE diff --git a/builds/4chan-X.js b/builds/4chan-X.js index d6558473e..c3ab52075 100644 --- a/builds/4chan-X.js +++ b/builds/4chan-X.js @@ -1,7 +1,7 @@ // Generated by CoffeeScript // ==UserScript== // @name 4chan X -// @version 1.2.17 +// @version 1.2.19 // @namespace 4chan-X // @description Cross-browser userscript for maximum lurking on 4chan. // @license MIT; https://github.com/seaweedchan/4chan-x/blob/master/LICENSE @@ -19,7 +19,7 @@ // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwAgMAAAAqbBEUAAAACVBMVEUAAGcAAABmzDNZt9VtAAAAAXRSTlMAQObYZgAAAHFJREFUKFOt0LENACEIBdBv4Qju4wgWanEj3D6OcIVMKaitYHEU/jwTCQj8W75kiVCSBvdQ5/AvfVHBin11BgdRq3ysBgfwBDRrj3MCIA+oAQaku/Q1cNctrAmyDl577tOThYt/Y1RBM4DgOHzM0HFTAyLukH/cmRnqAAAAAElFTkSuQmCC // ==/UserScript== /* -* 4chan X - Version 1.2.17 - 2013-06-18 +* 4chan X - Version 1.2.19 - 2013-07-15 * * Licensed under the MIT license. * https://github.com/seaweedchan/4chan-x/blob/master/LICENSE @@ -133,6 +133,7 @@ 'Index Navigation': [false, 'Add buttons to navigate between threads.'], 'Reply Navigation': [false, 'Add buttons to navigate to top / bottom of thread.'], 'Check for Updates': [true, 'Check for updated versions of 4chan X.'], + 'Show Updated Notifications': [true, 'Show notifications when 4chan X is successfully updated.'], 'Emoji': [false, 'Adds icons next to names for different emails'], 'Color User IDs': [false, 'Assign unique colors to user IDs on boards that use them'], 'Remove Spoilers': [false, 'Remove all spoilers in text.'], @@ -322,7 +323,7 @@ doc = d.documentElement; g = { - VERSION: '1.2.17', + VERSION: '1.2.19', NAMESPACE: '4chan X.', boards: {}, threads: {}, @@ -7954,7 +7955,7 @@ 'http': false, 'https': true, 'software': 'foolfuuka', - 'boards': ['a', 'co', 'gd', 'jp', 'm', 'q', 'sp', 'tg', 'tv', 'v', 'vg', 'vp', 'vr', 'wsg'], + 'boards': ['a', 'co', 'gd', 'jp', 'm', 'q', 'sp', 'tg', 'tv', 'vg', 'vp', 'vr', 'wsg'], 'files': ['a', 'gd', 'jp', 'm', 'q', 'tg', 'vg', 'vp', 'vr', 'wsg'] }, 'NSFW Foolz': { @@ -7988,25 +7989,17 @@ 'boards': ['c', 'w', 'wg'], 'files': ['c', 'w', 'wg'] }, - 'Love is Over': { - 'domain': 'loveisover.me', - 'http': true, - 'https': true, - 'software': 'foolfuuka', - 'boards': ['d', 'h', 'v'], - 'files': ['d', 'h', 'v'] - }, 'Foolz a Shit': { 'domain': 'archive.foolzashit.com', 'http': true, 'https': true, 'software': 'foolfuuka', - 'boards': ['adv', 'asp', 'cm', 'e', 'i', 'lgbt', 'n', 'o', 'p', 'pol', 's', 's4s', 't', 'trv', 'y'], - 'files': ['adv', 'asp', 'cm', 'e', 'i', 'lgbt', 'n', 'o', 'p', 's', 's4s', 't', 'trv', 'y'] + 'boards': ['adv', 'asp', 'cm', 'i', 'lgbt', 'n', 'o', 'p', 's4s', 't', 'trv'], + 'files': ['adv', 'asp', 'cm', 'i', 'lgbt', 'n', 'o', 'p', 's4s', 't', 'trv'] }, 'Install Gentoo': { 'domain': 'archive.installgentoo.net', - 'http': true, + 'http': false, 'https': true, 'software': 'fuuka', 'boards': ['diy', 'g', 'sci'], @@ -8026,14 +8019,6 @@ 'software': 'fuuka', 'boards': ['an', 'fit', 'k', 'mlp', 'r9k', 'toy'], 'files': ['an', 'k', 'toy'] - }, - 'warosu': { - 'domain': 'fuuka.warosu.org', - 'http': true, - 'https': true, - 'software': 'fuuka', - 'boards': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'tg', 'vr'], - 'files': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'vr'] } }, to: function(dest, data) { @@ -9526,7 +9511,9 @@ el = $.el('span', { innerHTML: "4chan X has been updated to version " + g.VERSION + "." }); - new Notification('info', el, 30); + if (Conf['Show Updated Notifications']) { + new Notification('info', el, 30); + } } else { $.on(d, '4chanXInitFinished', Settings.open); } @@ -10639,7 +10626,7 @@ } return Main.thisPageIsLegit; }, - css: "/* General */\n.dialog {\nbox-shadow: 0 1px 2px rgba(0, 0, 0, .15);\nborder: 1px solid;\ndisplay: block;\npadding: 0;\n}\n.captcha-img,\n.field {\nbackground-color: #FFF;\nborder: 1px solid #CCC;\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\ncolor: #333;\nfont: 13px sans-serif;\noutline: none;\ntransition: color .25s, border-color .25s;\ntransition: color .25s, border-color .25s;\n}\n.field::-moz-placeholder,\n.field:hover::-moz-placeholder {\ncolor: #AAA !important;\nfont-size: 13px !important;\nopacity: 1.0 !important;\n}\n.captch-img:hover,\n.field:hover {\nborder-color: #999;\n}\n.field:hover, .field:focus {\ncolor: #000;\n}\n.field[disabled] {\nbackground-color: #F2F2F2;\ncolor: #888;\n}\n.move {\ncursor: move;\noverflow: hidden;\n}\nlabel, .favicon {\ncursor: pointer;\n}\na[href=\"javascript:;\"] {\ntext-decoration: none;\n}\n.warning {\ncolor: red;\n}\n#boardNavDesktop {\ndisplay: none !important;\n}\na {\noutline: none !important;\n}\n\n/* 4chan style fixes */\n.opContainer, .op {\ndisplay: block !important;\noverflow: visible !important;\n}\n[hidden] {\ndisplay: none !important;\n}\n\n/* fixed, z-index */\n#overlay,\n#fourchanx-settings,\n#qp, #ihover,\n#navlinks, .fixed #header-bar,\n:root.float #updater,\n:root.float #thread-stats,\n#qr {\nposition: fixed;\n}\n#fourchanx-settings {\nz-index: 999;\n}\n#overlay {\nz-index: 900;\n}\n#notifications {\nz-index: 70;\n}\n#qp, #ihover {\nz-index: 60;\n}\n#menu {\nz-index: 50;\n}\n#navlinks, #updater, #thread-stats {\nz-index: 40;\n}\n.fixed #header-bar.autohide {\nz-index: 35;\n}\n#qr {\nz-index: 30;\n}\n#watcher {\nz-index: 8;\n}\n:root.fixed-watcher #watcher {\nz-index: 20;\n}\n.fixed #header-bar {\nz-index: 10;\n}\n/* Header */\n.fixed.top body {\npadding-top: 2em;\n}\n.fixed.bottom body {\npadding-bottom: 2em;\n}\n.fixed #header-bar {\nright: 0;\nleft: 0;\npadding: 3px 4px 4px;\n}\n.fixed.top #header-bar {\ntop: 0;\n}\n.fixed.bottom #header-bar {\nbottom: 0;\n}\n#header-bar {\nborder-width: 0;\ntransition: all .1s .05s ease-in-out;\n}\n:root.centered-links #shortcuts {\nwidth: 300px;\ntext-align: right;\n}\n:root.centered-links #header-bar {\ntext-align: center;\n}\n:root.centered-links #custom-board-list {\nposition: relative;\nleft: 150px;\n}\n.fixed.top #header-bar {\nborder-bottom-width: 1px;\n}\n.fixed.bottom #header-bar {\nbox-shadow: 0 -1px 2px rgba(0, 0, 0, .15);\nborder-top-width: 1px;\n}\n.fixed.bottom #header-bar .menu-button i {\nborder-top: none;\nborder-bottom: 6px solid;\n}\n#board-list {\ntext-align: center;\n}\n.fixed #header-bar.autohide:not(:hover) {\nbox-shadow: none;\ntransition: all .8s .6s cubic-bezier(.55, .055, .675, .19);\n}\n.fixed.top #header-bar.autohide:not(:hover) {\nmargin-bottom: -1em;\n-webkit-transform: translateY(-100%);\ntransform: translateY(-100%);\n}\n.fixed.bottom #header-bar.autohide:not(:hover) {\n-webkit-transform: translateY(100%);\ntransform: translateY(100%);\n}\n#scroll-marker {\nleft: 0;\nright: 0;\nheight: 10px;\nposition: absolute;\n}\n#header-bar #scroll-marker {\ndisplay: none;\n}\n.fixed #header-bar #scroll-marker {\ndisplay: block;\n}\n.fixed.top #header-bar #scroll-marker {\ntop: 100%;\n}\n.fixed.bottom #header-bar #scroll-marker {\nbottom: 100%;\n}\n#header-bar a:not(.entry):not(.close) {\ntext-decoration: none;\npadding: 1px;\n}\n#header-bar input {\nmargin: 0;\nvertical-align: bottom;\n}\n#shortcuts:empty {\ndisplay: none;\n}\n.brackets-wrap::before {\ncontent: \"\\00a0[\";\n}\n.brackets-wrap::after {\ncontent: \"]\\00a0\";\n}\n.disabled,\n.expand-all-shortcut {\nopacity: .45;\n}\n#shortcuts {\nfloat: right;\n}\n.shortcut {\nmargin-left: 3px;\n}\n#navbotright,\n#navtopright {\ndisplay: none;\n}\n#toggleMsgBtn {\ndisplay: none !important;\n}\n.current {\nfont-weight: bold;\n}\n/* 4chan X link brackets */\n.fourchanx-link::after {\ncontent: \"]\";\n}\n.fourchanx-link::before {\ncontent: \"[\";\n}\n/* Notifications */\n#notifications {\nposition: fixed;\ntop: 0;\nheight: 0;\ntext-align: center;\nright: 0;\nleft: 0;\ntransition: all .8s .6s cubic-bezier(.55, .055, .675, .19);\n}\n.fixed.top #header-bar #notifications {\nposition: absolute;\ntop: 100%;\n}\n.notification {\ncolor: #FFF;\nfont-weight: 700;\ntext-shadow: 0 1px 2px rgba(0, 0, 0, .5);\nbox-shadow: 0 1px 2px rgba(0, 0, 0, .15);\nborder-radius: 2px;\nmargin: 1px auto;\nwidth: 500px;\nmax-width: 100%;\nposition: relative;\ntransition: all .25s ease-in-out;\n}\n.notification.error {\nbackground-color: hsla(0, 100%, 38%, .9);\n}\n.notification.warning {\nbackground-color: hsla(36, 100%, 38%, .9);\n}\n.notification.info {\nbackground-color: hsla(200, 100%, 38%, .9);\n}\n.notification.success {\nbackground-color: hsla(104, 100%, 38%, .9);\n}\n.notification a {\ncolor: white;\n}\n.notification > .close {\npadding: 6px;\ntop: 0;\nright: 5px;\nposition: absolute;\n}\n.message {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\npadding: 6px 20px;\nmax-height: 200px;\nwidth: 100%;\noverflow: auto;\n}\n\n/* Settings */\n:root.fourchan-x body {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\n}\n#overlay {\nbackground-color: rgba(0, 0, 0, .5);\ntop: 0;\nleft: 0;\nheight: 100%;\nwidth: 100%;\n}\n#fourchanx-settings {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\nbox-shadow: 0 0 15px rgba(0, 0, 0, .15);\nheight: 600px;\nmin-height: 0;\nmax-height: 100%;\nwidth: 900px;\nmin-width: 0;\nmax-width: 100%;\nmargin: auto;\npadding: 3px;\ntop: 50%;\nleft: 50%;\n-moz-transform: translate(-50%, -50%);\n-webkit-transform: translate(-50%, -50%);\n-o-transform: translate(-50%, -50%);\ntransform: translate(-50%, -50%);\n}\n#fourchanx-settings > nav {\npadding: 2px 2px 0;\nheight: 15px;\n}\n#fourchanx-settings > nav a {\ntext-decoration: underline;\n}\n#fourchanx-settings > nav a.close {\ntext-decoration: none;\npadding: 2px;\n}\n.section-container {\noverflow: auto;\nposition: absolute;\ntop: 2.1em;\nright: 5px;\nbottom: 5px;\nleft: 5px;\npadding-right: 5px;\n}\n.sections-list {\npadding: 0 3px;\nfloat: left;\n}\n.credits {\nfloat: right;\n}\n.tab-selected {\nfont-weight: 700;\n}\n.section-sauce ul,\n.section-advanced ul {\nlist-style: none;\nmargin: 0;\n}\n.section-sauce ul {\npadding: 8px;\n}\n.section-advanced ul {\npadding: 0px;\n}\n.section-sauce li,\n.section-advanced li {\npadding-left: 4px;\n}\n.section-main label {\ntext-decoration: underline;\n}\n.section-filter ul {\npadding: 0;\n}\n.section-filter li {\nmargin: 10px 40px;\n}\n.section-filter textarea {\nheight: 500px;\n}\n.section-sauce textarea {\nheight: 350px;\n}\n.section-advanced .field[name=\"boardnav\"] {\nwidth: 100%;\n}\n.section-advanced textarea {\nheight: 150px;\n}\n.section-advanced .archive-cell {\nmin-width: 160px;\ntext-align: center;\n}\n.section-advanced #archive-board-select {\nposition: absolute;\n}\n.section-advanced .note {\nfont-size: 0.8em; \nfont-style: italic; \nmargin-left: 10px;\n}\n.section-advanced .note code {\nfont-style: normal;\nfont-size: 11px;\n}\n#fourchanx-settings fieldset {\nborder: 1px solid;\nborder-radius: 3px;\n}\n#fourchanx-settings legend {\nfont-weight: 700;\n}\n#fourchanx-settings textarea {\nfont-family: monospace;\nmin-width: 100%;\nmax-width: 100%;\n}\n#fourchanx-settings code {\ncolor: #000;\nbackground-color: #FFF;\npadding: 0 2px;\n}\n.unscroll {\noverflow: hidden;\n}\n\n/* Announcement Hiding */\n:root.hide-announcement #globalMessage {\ndisplay: none;\n}\na.hide-announcement {\nfloat: left;\n}\n\n/* Unread */\n#unread-line {\nmargin: 0;\nborder-color: rgb(255,0,0);\n}\n\n/* Thread Updater */\n#updater {\nbackground: none;\nborder: none;\nbox-shadow: none;\n}\n#updater > .move {\npadding: 5px 3px 0px;\nmargin-bottom: -3px;\n}\n#updater > div:last-child {\ntext-align: center;\n}\n#updater input[type=number] {\nwidth: 4em;\n}\n:root.float #updater {\npadding: 0px 3px;\n}\n.new {\ncolor: limegreen;\n}\n#update-status.new {\nmargin-right: 5px;\n}\n#update-timer {\ncursor: pointer;\n}\n\n/* Thread Watcher */\n#watcher {\nposition: absolute;\n}\n#watcher {\npadding-bottom: 3px;\noverflow: hidden;\nwhite-space: nowrap;\nmin-width: 120px;\nmax-height: 92%;\noverflow-y: auto;\n}\n:root.fixed-watcher #watcher {\nposition: fixed;\n}\n:root:not(.fixed-watcher) #watcher:not(:hover) {\nmax-height: 210px;\noverflow-y: hidden;\n}\n#watcher > .move {\npadding-top: 3px;\n}\n#watcher > div {\nmax-width: 250px;\noverflow: hidden;\npadding-left: 3px;\npadding-right: 3px;\ntext-overflow: ellipsis;\n}\n#watcher a {\ntext-decoration: none;\n}\n#watcher .move>.close {\nposition: absolute;\nright: 0px;\ntop: 0px;\npadding: 0px 4px;\n}\n.watch-thread-link {\npadding-top: 18px;\nwidth: 18px;\nheight: 0px;\ndisplay: inline-block;\nbackground-repeat: no-repeat;\nopacity: 0.2;\nposition: relative;\ntop: 1px;\n}\n.watch-thread-link.watched {\nopacity: 1;\n}\n\n/* Thread Stats */\n#thread-stats {\nbackground: none;\nborder: none;\nbox-shadow: none;\n}\n:root.float #post-count, :root.float #file-count {\npointer-events: none;\n}\n:root.float #thread-stats {\npadding: 0px 3px;\n}\n\n/* Quote */\n.deadlink {\ntext-decoration: none !important;\n}\n.backlink.deadlink:not(.forwardlink), .quotelink.deadlink:not(.forwardlink) {\ntext-decoration: underline !important;\n}\n.inlined {\nopacity: .5;\n}\n#qp input, .forwarded {\ndisplay: none;\n}\n.quotelink.forwardlink,\n.backlink.forwardlink {\ntext-decoration: none;\nborder-bottom: 1px dashed;\n}\n.filtered {\ntext-decoration: underline line-through;\n}\n:root.hide-backlinks .backlink.filtered {\ndisplay: none;\n}\n.inline {\nborder: 1px solid;\ndisplay: table;\nmargin: 2px 0;\n}\n.inline .post {\nborder: 0 !important;\nbackground-color: transparent !important;\ndisplay: table !important;\nmargin: 0 !important;\npadding: 1px 2px !important;\n}\n#qp > .opContainer::after {\ncontent: '';\nclear: both;\ndisplay: table;\n}\n#qp .post {\nborder: none;\nmargin: 0;\npadding: 2px 2px 5px;\n}\n#qp img {\nmax-height: 300px;\nmax-width: 500px;\nmax-height: 80vh;\nmax-width: 50vw;\n}\n.qphl {\noutline: 2px solid rgba(216, 94, 49, .7);\n}\n:root.highlight-own .yourPost>.reply,\n:root.highlight-you .quotesYou>.reply {\nborder-left: 2px solid rgba(221,0,0,.5);\n}\n/* Quote Threading */\n.threadContainer {\nmargin-left: 20px;\nborder-left: 1px solid rgba(128,128,128,.3);\n}\n.threadOP {\nclear: both;\n} \n\n/* File */\n.fileText:hover .fntrunc,\n.fileText:not(:hover) .fnfull,\n.expanded-image > .post > .file > .fileThumb > img[data-md5],\n:not(.expanded-image) > .post > .file > .fileThumb > .full-image {\ndisplay: none;\n}\n.expanding {\nopacity: .5;\n}\n:root.fit-height .full-image {\nmax-height: 100vh;\n}\n:root.fit-width .full-image {\nmax-width: 100%;\n}\n:root.gecko.fit-width .full-image,\n:root.presto.fit-width .full-image {\nwidth: 100%;\n}\n#ihover {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\nmax-height: 100%;\nmax-width: 75%;\npadding-bottom: 16px;\n}\n.fappeTyme .thread > .noFile,\n.fappeTyme .threadContainer > .noFile {\ndisplay: none;\n}\n\n/* Index/Reply Navigation */\n#navlinks {\nfont-size: 16px;\ntop: 25px;\nright: 10px;\n}\n\n/* Filter */\n.opContainer.filter-highlight {\nbox-shadow: inset 5px 0 rgba(255, 0, 0, .5);\n}\n.filter-highlight > .reply {\nbox-shadow: -5px 0 rgba(255, 0, 0, .5);\n}\n\n/* Spoiler text */\n:root.reveal-spoilers s {\ncolor: white !important;\n}\n\n/* Thread & Reply Hiding */\n.hide-thread-button,\n.hide-reply-button {\nfloat: left;\nmargin-right: 2px;\n}\n.stub ~ * {\ndisplay: none !important;\n}\n.stub input {\ndisplay: inline-block;\n}\n\n/* QR */\n:root.hide-original-post-form #postForm,\n:root.hide-original-post-form .postingMode,\n:root.hide-original-post-form #togglePostForm,\n#qr.autohide:not(.has-focus):not(:hover) > form,\n.postingMode ~ #qr select,\n#file-n-submit:not(.has-file) #qr-filerm {\ndisplay: none;\n}\n#qr select, #dump-button, .remove, .captcha-img {\ncursor: pointer;\n}\n#qr {\nz-index: 20;\nposition: fixed;\npadding: 1px;\nborder: 1px solid transparent;\nmin-width: 300px;\nborder-radius: 3px 3px 0 0;\n}\n#qrtab {\nborder-radius: 3px 3px 0 0;\n}\n#qrtab {\nmargin-bottom: 1px;\n}\n#qr .close {\nfloat: right;\npadding: 0 3px;\n}\n#qr .warning {\nmin-height: 1.6em;\nvertical-align: middle;\npadding: 0 1px;\nborder-width: 1px;\nborder-style: solid;\n}\n.qr-link-container {\ntext-align: center;\n}\n.persona {\nwidth: 248px;\nmax-width: 100%;\nmin-width: 100%;\n}\n#dump-button {\nwidth: 10%;\nmargin: 0;\nmargin-right: 4px;\nfont: 13px sans-serif;\npadding: 1px 0px 2px;\nopacity: 0.6;\n}\n.persona .field:not(#dump) {\nwidth: 95px;\nmin-width: 33.3%;\nmax-width: 33.3%;\n}\n#qr textarea.field {\nheight: 14.8em;\nmin-height: 9em;\n}\n#qr.has-captcha textarea.field {\nheight: 9em;\n}\ninput.field.tripped:not(:hover):not(:focus) {\ncolor: transparent !important; text-shadow: none !important;\n}\n#qr textarea {\nresize: both;\n}\n.captcha-img {\nmargin: 0px;\ntext-align: center;\nbackground-image: #fff;\nfont-size: 0px;\nmin-height: 59px;\nmin-width: 302px;\n}\n.captcha-input {\nwidth: 100%;\nmargin: 1px 0 0;\n}\n.captcha-input.error:focus {\nborder-color: rgb(255,0,0) !important;\n}\n.field {\n-moz-box-sizing: border-box;\nmargin: 0px;\npadding: 2px 4px 3px;\n}\n#qr textarea {\nmin-width: 100%;\n}\n#qr [type='submit'] {\nwidth: 25%;\nvertical-align: top;\n}\n:root.webkit #qr [type='submit'] {\nheight: 24px;\n}\n/* Fake File Input */\n#qr-filename,\n.has-file #qr-no-file {\ndisplay: none;\n}\n#qr-no-file,\n.has-file #qr-filename {\ndisplay: inline-block;\npadding: 0px 4px;\nmargin-bottom: 2px;\noverflow: hidden;\ntext-overflow: ellipsis;\nmax-width: 88%;\n}\n#qr-no-file {\ncolor: #AAA;\n}\n#qr-filename-container {\n-moz-box-sizing: border-box;\ndisplay: inline-block;\nposition: relative;\nwidth: 100px;\nmin-width: 74.6%;\nmax-width: 74.6%;\nmargin-right: 0.4%;\nmargin-top: 1px;\noverflow: hidden;\npadding: 2px 1px 0;\nheight: 22px;\n}\n#qr-filename-container:hover {\ncursor: text;\n}\n#qr-extras-container {\nposition: absolute;\nright: 0px;\n}\n#qr-filerm {\nmargin-right: 2px;\nz-index: 2;\n}\n#file-n-submit {\nheight: 23px;\n}\n#qr input[type=file] {\nvisibility: hidden;\nposition: absolute;\n}\n/* Thread Select / Spoiler Label */\n#qr select {\nfloat: right;\n}\n#qr.has-spoiler .has-file #qr-spoiler-label {\nwidth: 6.7%;\nmin-width: 6.7%;\nmax-width: 6.7%;\ndisplay: inline-block;\ntext-align: center;\nvertical-align: top;\n}\n#qr.has-spoiler #file-n-submit:not(.has-file) #qr-spoiler-label {\ndisplay: none;\n}\n#qr.has-spoiler .has-file #qr-filename-container {\nmax-width: 67.9%;\nmin-width: 67.9%;\n}\n#qr-spoiler-label input {\nposition: relative;\ntop: 3px;\n}\n/* Dumping UI */\n.dump #dump-list-container {\ndisplay: block;\n}\n#dump-list-container {\ndisplay: none;\nposition: relative;\noverflow-y: hidden;\nmargin-top: 1px;\n}\n#dump-list {\noverflow-x: auto;\noverflow-y: hidden;\nwhite-space: nowrap;\nwidth: 248px;\nmax-width: 100%;\nmin-width: 100%;\n}\n#dump-list:hover {\noverflow-x: auto;\n}\n.qr-preview {\n-moz-box-sizing: border-box;\ncounter-increment: thumbnails;\ncursor: move;\ndisplay: inline-block;\nheight: 90px;\nwidth: 90px;\npadding: 2px;\nopacity: .5;\noverflow: hidden;\nposition: relative;\ntext-shadow: 0 1px 1px #000;\n-moz-transition: opacity .25s ease-in-out;\nvertical-align: top;\nbackground-size: cover;\n}\n.qr-preview:hover,\n.qr-preview:focus {\nopacity: .9;\n}\n.qr-preview::before {\ncontent: counter(thumbnails);\ncolor: #fff;\nposition: absolute;\ntop: 3px;\nright: 3px;\ntext-shadow: 0 0 3px #000, 0 0 8px #000;\n}\n.qr-preview#selected {\nopacity: 1;\n}\n.qr-preview.drag {\nbox-shadow: 0 0 10px rgba(0,0,0,.5);\n}\n.qr-preview.over {\nborder-color: #fff;\n}\n.qr-preview > span {\ncolor: #fff;\n}\n.remove {\nbackground: none;\ncolor: #e00;\nfont-weight: 700;\npadding: 3px;\n}\na:only-of-type > .remove {\ndisplay: none;\n}\n.remove:hover::after {\ncontent: \" Remove\";\n}\n.qr-preview > label {\nbackground: rgba(0,0,0,.5);\ncolor: #fff;\nright: 0; bottom: 0; left: 0;\nposition: absolute;\ntext-align: center;\n}\n.qr-preview > label > input {\nmargin: 0;\n}\n#add-post {\ncursor: pointer;\nfont-size: 2em;\nposition: absolute;\ntop: 50%;\nright: 10px;\n-moz-transform: translateY(-50%);\n}\n.textarea {\nposition: relative;\n}\n:root.webkit .textarea {\nmargin-bottom: -2px;\n}\n#char-count {\ncolor: #000;\nbackground: hsla(0, 0%, 100%, .5);\nfont-size: 8pt;\nposition: absolute;\nbottom: 1px;\nright: 1px;\npointer-events: none;\n}\n\n/* Menu */\n.menu-button {\ndisplay: inline-block;\nposition: relative;\ncursor: pointer;\n}\n.menu-button i {\nborder-top: 6px solid;\nborder-right: 4px solid transparent;\nborder-left: 4px solid transparent;\ndisplay: inline-block;\nmargin: 2px;\nvertical-align: middle;\n}\n#menu {\nposition: fixed;\noutline: none;\n}\n.entry {\nborder-bottom: 1px solid rgba(0,0,0,.25);\ncursor: pointer;\ndisplay: block;\noutline: none;\npadding: 3px 7px;\nposition: relative;\ntext-decoration: none;\nwhite-space: nowrap;\n}\n.left>.entry.has-submenu {\npadding-right: 17px !important;\n}\n.entry:last-child {\nborder-bottom: 0;\n}\n.has-submenu::after {\ncontent: \"\";\nborder-left: .5em solid;\nborder-top: .3em solid transparent;\nborder-bottom: .3em solid transparent;\ndisplay: inline-block;\nmargin: .3em;\nposition: absolute;\nright: 3px;\n}\n.left .has-submenu::after {\nborder-left: 0;\nborder-right: .5em solid;\n}\n.submenu {\ndisplay: none;\nposition: absolute;\nleft: 100%;\ntop: -1px;\n}\n.focused .submenu {\ndisplay: block;\n}\n.imp-exp-result {\nposition: absolute;\ntext-align: center;\nmargin: auto;\nright: 0px;\nleft: 0px;\nwidth: 200px;\n}\n.export, .import {\ncursor: pointer;\ntext-decoration: none !important;\n}\n/* Link Title Favicons */\n.linkify.YouTube {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAYAAABr5z2BAAABIklEQVQoz53LvUrDUBjG8bOoOammSf1IoBSvoCB4JeIqOHgBLt6AIMRBBQelWurQ2kERnMRBsBUcIp5FJSBI5oQsJVkkUHh8W0o5nhaFHvjBgef/Mq+Q46RJBMkI/vE+aOus956tnEswIZe1LV0QyJ5sE2GzgZfVMtRNIdiDpccEssdlB1mW4bvTwdvWJtRdErM7U+8S/FJykCRJX5qm+KpVce8UMNLRLbulz4iSjTAMh6Iowsd5BeNadp3nUF0VlxAEwZBotXC0Usa4ll3meZdA1iguwvf9vpvDA2wvmKgYGtSud8suDB4TyGr2PF49D/vra9jRZ1BVdknMzgwuCGSnZEObwu6sBnVTCHZiaC7BhFx2PKdxUidiAH/4lLo9Mv0DELVs9qsOHXwAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.Vimeo {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAASJJREFUOE9jYAAC7ln7/pODQXrBmq333PvPu/YaSRikB6QXbACpmmHqsRoAMll7+20UQ0H8tmuv/pdffPFfZtNNuByGASBFIPDh5x+4IV6HHoDFYGDJgw+YBoBMBUkgA5BtIKduuvvy//svX+FSB+88wTTAc+/t/83bj/0HScLA5BPXwc7lKJ36f+L6XXDxhUfOYxrAPWUnWKFp9UQUm3iWQxSDXAEDSX3zcIcB96wD/x+8eA1XDNKMHAYg20GW4Y0FkCIYAAUqzEBQOIBciRzlWKMxZelOlMCEcVxq+jHSC1YDJPs3YBgA8jey0/F6ARRwsFAHORukmat9NdbUijMpg/wKcrJodDFOzSBXwA3Alh9AToZFI7a8Asu98BxJbnYGAJb5vYLDANzSAAAAAElFTkSuQmCC') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.SoundCloud {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABsklEQVQ4y5WTy2pUQRCGv2rbzDjJeAlIBmOyipGIIJqFEBDElwh4yULGeRFXPoEIBl/AvQ/gC2RnxCAoxijiwks852S6+3dxzslcHJCpTXVX11/Xv0097gLPgVNMJxnQNfX4zsqleWbnpoMf/oa9d988MM9MC/rp+E0a+A0dsVobMNMCOO8B6McRoABJI+A6gJmN3D2A8jgEBCEkSEMBrcrsDAzDWWn3AjgKFaDMmgRqniGFgsaDp1jrLOngDf1XT1D+A1dFc4MKAkkiCVKjjVu7g9+4Rzx4i1u6hjXbuMWr0O5QPNvCu7IaCZwEKQukLGDrm5x8uI0tr6MkiGlkiv7yLfzN+6S5i6QsIMABkEfcxhbWWYMkVAOjxvYAjc3HNHrbKI9VBQBFwF25XQKSBjqIf1YBuAurEMrczgDygD6/x2LCpFLXLUyQ+PoldphhBhYfIX09XU1+Flaukz7uYqs3SHs7cG4BmTsmkBUF9mmXEwa28BNLPaQPLepuNcbGSWQquQC2/Kdcox1FUGkcB0ykck1nA2+wTzMs8stGnP4rbWGw74EuS/GFQWfK7/wF6P4F7fzIAYkdmdEAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.audio {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAitJREFUOE9jYCAWKJWwavr0KyXWb/FIbDtUFFyzJx6nVofE2Xo5nXsj0rqPNSR0nVkR2Hjmgmfd+U9Otdf+m5Vf/6+SfeU/R9ChVVgNYDRtlfJuuPA/rPfe/4QpD/6nznj0P27Kw/9unff/69Xf+69c/+C/SO7N/0z+OAxgMmmRCe++/r9i3ev/KWvf/vdY8PK/bt/9/wrNV3/IN5y/IVt1YqNg4pGTTP4HsbuA2bhZ2qvpyn+xjIObxAp3VwqlrgngLFyryVy5nhPmZJHANS2cwYexG8BmVC/pWn3hP4NZlzWuQDJI3dIiFnUUuwEsQAOcq87jNcC7fHeLUtJxHF4AGmBWeAavAWH1+1rUUk7giAWjOknllON4DXAs2NEiG4/DBQxAF/CFHfrPYI4jDFSLuJVjNrUJhB/B7gIGo1pJRt99GAZYJK7wLJ1z7Xzl4vu/7aqv/GRBj0bjqAX2qb0nJ7mXH17C4HcUxQA+hymWtSue/C5a9up/9Ozn/7Vr7v1nRY7GqMb91T3b3v6vWvPmf/S0p/9ZQk+DDLCBRSOz06Jqk+o7/21nvfqvsebDf7kZL/5zBaxphkezd+OFn7HzXvz3Wvjmv9a8N//5Ek//ZTBpVYUrMG2X5wjcdl68+uI/wa5Lr3hSNjczGFeywOVZ/bbcVGp//F9izfv/Ql03f3P4LC/HSEQquYwMFnUCDJ7dzBhyjGZNQpye89M5gpfnMvtNUyE2h4PUAQBovvT7lyNljwAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.LiveLeak {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAydJREFUOE9Nk1tIk2EYx79NyUNqTk0o6KYrnZeChodLDxfeZpCbJk4RXU5Nm7tYRYhiYXbQlaeGutyW2gxtpB1RIyKDEjKwA6Ti2dR5KNDn+fq/S6TBj/f93r3P732e53s/qfnkSdej4GB2SBLbwf+jmB+gUMgOheLg/z7EdCUnO6Ref392SpK8Hyh3I+gBwBo7lUp2xcbyQEoKD6alyQOpqd754/h4FjJXZCRJTl9ftmEzoK5/wdQJxPgkLY2WV1dpc2uLtnZ2eHNnhza3t2nd46GhjAzuValY6jx0iIfS03msoIDuQ9COQCtoUSjohU5HuwgaN5loeXycd3d3aW9vzwvW2K5SkdTi58fvzGb+3tdHFggA3QONEAzn59PvjQ1yqNX0zenkvX0B4ffWaGRraChJd/385JGqKvlzTw/fRqOaIGkEd1DjU52O/3g83BkTw5MOh7yJuUCUM2o0yi2hoSw1IIOhykr+YLNRHYKu4XQvyKA/N5c8yMCCDD7Z7bz26xcJ1rH2rKKCG0UJdRAMlJbyG6uVrkJQjWAB5tSbk0Nr2HwDgvcQiIYur6zQyvo6ucvLueHIEZKuQPBQr+dXra1kRuqXEOwFArtWSytra1QdFUVjNhvPLS3R3OIiLUDUD0F1WBhJJtwDW2Ehu5uaqBICI4IFlRB0QLCEzaboaHrd0cHzCBYsIIuesjK+LAQXkEFrXh676uupGCWcR6AeghLQptGQONUAwfOuLp6Zn6eZuTmaXVig7pISrhI90ENgQbdHhoep32JhFzLpu3WLio8epUYIfs7OUjF6UKJW88XERLqYkEBNej11oG8XhCAvMFAuOn5cNiclsTkhQTbhmpri4lgbEMANWi1DwC/xit3t7bK7rY0Fo4OD3G4wyEURESzloAdnceezlErK8vH5N4KzPj50PTOTfkxP0+THj/RlYoInJyZI8HVqim5qNFwQHk7SucBAPo2PKRMNPLM/4pnFszYkhJsNBu6uqWFHba1sr61lQSveQFZQkFx07BhJmhMnrLn4NLMPH/aSExR0QDbmWhwgyEapwDvXoDxdWBiXnjrV/Bdm2kYUxLwmEgAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.Vocaroo {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAw9JREFUOE9jYMABuMwYmCyTJKUCGlSnFSy02TTzeOyCiQcDViX26qVz2TAyYtWmEMwuoZ3M7V40LcB79pHkc0svpvzY8jD//87nxf+3Pyn8v/ZO8v+VNyP/2mZJumI1QCWSI8232Hjumitlfw5+qPp/9l8TCt76JP//xkdx/wsXWCzjtWFkwTCkbWFe9plPk/+ga4Txz/xt/D/hkN//gMXif21a+NbyWjIwoRiy6GDT5rP/mlFsPfyp5n/NpOj/22+0gMUXXIz/H7hC/L/bFKFbPDZMrHAD5H35OPt2J9zacDv/f3V7xv9FhwrBGubsT/1//Pjx/1GJ/mD+/nfl/1v3Ovy3KRJNQbHdOlXCvOO03/+pm1P/v3v37n90hhtYw9HPtf8Xb2v937cmHswHeWPRxYj/LvkK3igGKARwicTO07118H3V/5kbi/4vPZMJtK3s/6YH2f+Pfq1B8VbjWrdnMu5s4nAD9CNFhKwz5DTUvLl419zKvAcLtG1P84BRl/b/5M/6/6f/NPzf/qzo84yj0Uus0xUU4Zor54bm9+4OfZG02OCuoAMTb9ZkC9ull1Nvrr2Z+XvRpaRfc65H/68F+jl9svEhzyLFWoccWVc+eyTHq/twydjlKRln7jX9bNMkMJnbhoFRL1xCqmKx6/yi2fYXa/c5/e846PV/5fW0/7OPx/yfcjzop34ulxdGGvDuU8mMXaX507lBuiN6ueadmQeT/p/93vf/1O+G//sP5fw/eL3o/5JLif8zVxs+Tlir9S26UyeFQQvJGBE7FvaFZ9LfN+1y+WjbItSb3GmXvXd15v8zroH/HxgE/D+aGPx/18vi/z07PeZNPRKxe/Kh0Ae8toxscCO4zBkYXArk9C1SxJUYjBkYPPIVtbbuTftz3cz//2O9wP/75iSAXdO72/dt2HL5F6YlfBW4MiJYXMiBiW3t7azHBx+V/t89N+H/8a+1//e9K/9attDp5LQjYX8SuvVL8RoAkmxa65299Erq1FnHo0qrl7t4BddriIs4MrM3rfWcFd+pGwVSAwBZ0bKP8yrZPAAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.pastebin {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAtZJREFUOE+NU91LWmEc7sJtQew/2MUY7INg7CLY3W5GMHazyzEQo9UmfYxZTbAiVlgRqLMSZ+XnDC3z2+Y0+8JGakKZTtR0Tl2wtgtLLQh29cz3ZZ3h3Q68vOc95zzP73l+z+/U1f292O09DRxubxOH23P//1bvtQts3dPnry7LZnXJhcUl5Avf8dHtwY+fv2AyW5DOfIXFakMm+w0G4wISyRRm55TQG0y/Wzv6mikJ52Xf9TmVBoFAAD6fDwqFAqFQCJubmzCbzZiensbp6SmkUikikQi0Wi0kEgm6ewVaStDCfXPDandifn6egoaGhrCzswO1Wg2Hw4HBwUGk02kIBAL4/X4IhUJMTk6ii8dfYggy2RwymQzOz88Rj8dRLpexv7+PSqWCYDCIQqGAra0tJBIJrK2t0XdVAjNDEIl+wfj4OEqlEq2wt7dHrchkMmrBYDCAz+fTIjweD7FYrJbgIJOlgLOzM8jlcip1eXmZ2rFarVAqlRCLxcjlchCJRFRljYJYPAG32418Pg+n04lsNouVlRUcHh7C4/FQIOlHNBqlezgcJgQWxkIgGMbExASVNjY2hvX1dVo9mUzS5wREFLhcLrqTcw2B//M2RkdHodPp4PV6oVKpqH+SCom3v7+fNnF4eJiJusbCJ6+PviSyScakiaR5RIHRaKQpmEwmbAdCeD8zB6vdhebHT8SMhcUlC83bbrdTJRsbG3RwiCVCRNJJpDIoVeNNJJJQzKryV+rrmxiCtyNCCmaz2VhdXQWXy6XDpNfrodFoYLXZUTw+pk222Z3lW3ca26rgSwzBwqIZAwMDlITMAVEwNTVFR5fEJpK8Qyp1AJvDVbrTeLenCmxgfiZ22+urCtWHyu7uLp2wVCpFKx0dHaFYLOLk5KT6Y9kgk89kb95ubK0BX7A8a+1qannRLeW0daj/rU51S3tn9dypfvDw0QiLxbpX/Z7FVK7e/AEj4Wf24/2f5AAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.gist {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAk1JREFUeNqUkzuIE1EUhv955MnsbB6r4kYQLUQQFncV3SnCIqJsoWGDYOGjsIiCtY2Kla1sjLBIsFFcXJC1kaSwENQmXUQSRSUSjCQSTCbkbR4z47lXEgtBNwcu3DNzvvO8R8jlcj7LshKmaWqYQERRTAmCcEru9/sJr9er0QF92BJMAVGr1TQ6CeZAc7lcGAwGkyQAxpTLZU0eDoc8crfbRTgcRjAYRCQSYSmi1WpxY7fbjU6ng1gshmaziXg8zhnGIpVKWbquW9ls1mLZsaMoiqWq6lgnBxY55He/328Vi0XOMFZmqVMD4fF4QBAajcY48khY9JE4HA4enTGMFVkaTHmy+ZzD/5NSqYSNB484w1h55ODO3TVu4FXcWDywl24Cmp0e1WBhyuWELAtIf/qKUrWOONmev3Lpt4NRCXq1gplpBS/v3cDc0nGg9h1o1ZkfwO4Atu1B8cM7HLt8k37V/y5B2b4bJxf2Y+7oEbyJrkMvUjki0YYJ03LidfQxAt4dOHdCw5RdGZcgGobBlQtnV/BDr1GfDai7ZiHZZRi9PoY/e5SCCTUwC9gk1GmMh5YWOcNYkR4Sv1y9uAJbYB82N57h4OnDmN7phjQ0qUkWRJuB+TMaPn/5iFfvv+Ha7eucYey4iWw8q6tRJJNJ3Fp7ClUawEkViBTfkCR0YUNTVHD/4Tpm/P4/U2CeKpUKfD4fJDIMhUKEhP45St50XedZyLQY6Xw+v8AUemVb2oNqtYpCocCWKi2TLLfb7ReZTGZ+kmUi7i2VvfxLgAEAZChMriPcl+IAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.image {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAs5JREFUOE+lk/tvi1EYx98/xT8gW4REIpGFMEQWl2FiM9ZMZhm2xRAyOsmujFFmdFRHu0tWm87UypxStr69zPauN5e5rHVp3IYhbOvHy+wHEQlxkm+ek+d8nm9OznkeSfrfldmgJC7QyUlTymsJTfuTZ25z4HdWYwyLreYhtpgekGPw0+kKvo1Eo+IXRSIiEhkWZuc9tqnsJD9EqTUopCxjSGTpB0iueczSo1HyW8cpsExQ1DbxI2pt45j9cXpexul4FEd79RnZphAa/SD7WvuFtO6UItbU9LC+YQxNI2w0wwYT5LRAdhOU3oBTIXC9gXP3oUSGgz2vST3gYHejR0jptT1C332f8yrUEYHrz8CgxDnpm6DKCUfc0KnmXa/AEVPPwnDcD0cvetA2uYRk67Ive/lpjO7YBO1PPuF8Df3vwf4cbNE4tqdw7YVq8HYyHx6FvhE1hkMEg8HDUqvFkjT4aIjMqkqyqkswDSrcfBfH+Q561YLAZ/B+BLda6FXlU/cPv0AoEPhuoP1h4Av7Wbh9E/Py15NWWUjeSR3nZDfeN+N0DY9hG/7K1eGP3P0S5/EYRFUF/IOTBrUXHPm9fT6mr1xEwupkZqxbzLyiDJYUZ5NSnkdqdSHpxyrYdFpPgdmAsdfJwPMI/Yr65bf7tZLGGBQ7DNdJWFtIYvoOZmbuZE7OXpIKKli86zAr9p9gTVktWTVnKTI2U95uRWe3U2IJUDbVB5p6hVm5x5m9Vc/cnedZUNzC8lILaQesZBy6hEZ3maKzgvJWFzVWD9XtXvVGQbSWASFtMATVRlJIKbOTWtlJXaeXepuPM1f6MNp9GLt8mLvvYLmp0OhQ2Fwvk6m7xaqDTvY0eYWUVtcnllXfYlGpnfklVuraHHg8HjxuN+6fktUHlWWZPaZeUo/ILK0UKttBcbNbSB9GP0yLxWJJUxoZGUn80zD9C/vXQ/4NHY10h3M1zmQAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.InstallGentoo {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAklJREFUOE9jYEAAASBTCorZkcSRmTjVCDLziCwG4hfM3EIvGNm44oC6WNEM4WXi5FsEkmfhFX3BxMmfAJSHW9Qr55Px3aZp3X/btq3/hQydPzKysMcCFbBBDeFj4uBdqBJR/gskb1W34j+PmulLoJwbzBJJoMm7dNO7/ntMP/XfpW/v//SKvk+7tl7fvXfTpx5pCdWVSiHFv1wnHQbLi9sE/Wdk5SwBauaCGQB3gUPb5v+7Lr/8/+fvr/9fv/z+f+Pyr/9bV735l9Wy/79Dx/b/Nk0bsLoAHgbeAVHv/v77/f8f0IB7N7+cu3DuecK54z9+7lzz639e9pK/7HwSWMMA5BJwCJeXtOm/fvVj1fcfv369f//92cN7X6ZcPvf9x6Htv//vXP3r/+T245UEYgpskPTNq08LgN749/PH7/93rv/6f/rw7//nj//4f+bU0zQcUQwWBkdVbGz62y+fv3wHeeXrlz//H9798//qpY//M3KqfzGxc8djiWKwZnBUuWQ2/fr46fv/P39+///x/ff/d69//z97+s7fyMb5/+y7d2GLYriDZikFF/1qXXXj/4Pbv/8/f/jn/5MH316/eP6jVlBAaIt6VO1/jxmn/zv27P7Pp2HxEajLD90ra9Sj6/979O37X73w0n+vqOL/0lJyMVBFq0EGgDSD0oKAlu1/oHg4ugGzVCKqfouYuL1Xj676Iajr8AnJFricGqYc3Bw+Zi6BVUxsXLHAdL6QiYMPFNrwpIxHDsUhgtAMAopKDjQn4pPDF7P45QC4hSmc1eX8WgAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n\n/* General */\n:root.yotsuba .dialog {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.yotsuba .field:focus {\nborder-color: #EA8;\n}\n\n/* Header */\n:root.yotsuba #header-bar, :root.yotsuba #notifications {\nfont-size: 9pt;\ncolor: #B86;\n}\n:root.yotsuba #header-bar a, :root.yotsuba #notifications a {\ncolor: #800000;\n}\n\n/* Settings */\n:root.yotsuba #fourchanx-settings fieldset {\nborder-color: #D9BFB7;\n}\n\n/* Quote */\n:root.yotsuba .backlink.deadlink {\ncolor: #00E !important;\n}\n:root.yotsuba .inline {\nborder-color: #D9BFB7;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.yotsuba #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.yotsuba .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.yotsuba #menu {\ncolor: #800000;\n}\n:root.yotsuba .entry {\nborder-bottom: 1px solid #D9BFB7;\nfont-size: 10pt;\n}\n:root.yotsuba .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.yotsuba .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.yotsuba-b .dialog {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.yotsuba-b .field:focus {\nborder-color: #98E;\n}\n\n/* Header */\n:root.yotsuba-b #header-bar, :root.yotsuba-b #notifications {\nfont-size: 9pt;\ncolor: #89A;\n}\n:root.yotsuba-b #header-bar a, :root.yotsuba-b #notifications a {\ncolor: #34345C;\n}\n\n/* Settings */\n:root.yotsuba-b #fourchanx-settings fieldset {\nborder-color: #B7C5D9;\n}\n\n/* Quote */\n:root.yotsuba-b .backlink.deadlink {\ncolor: #34345C !important;\n}\n:root.yotsuba-b .inline {\nborder-color: #B7C5D9;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.yotsuba-b #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.yotsuba-b .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.yotsuba-b #menu {\ncolor: #000;\n}\n:root.yotsuba-b .entry {\nborder-bottom: 1px solid #B7C5D9;\nfont-size: 10pt;\n}\n:root.yotsuba-b .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.yotsuba-b .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.futaba .dialog {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.futaba .field:focus {\nborder-color: #EA8;\n}\n\n/* Header */\n:root.futaba #header-bar, :root.futaba #notifications {\nfont-size: 11pt;\ncolor: #B86;\n}\n:root.futaba #header-bar a, :root.futaba #notifications a {\ncolor: #800000;\n}\n\n/* Settings */\n:root.futaba #fourchanx-settings fieldset {\nborder-color: #D9BFB7;\n}\n\n/* Quote */\n:root.futaba .backlink.deadlink {\ncolor: #00E !important;\n}\n:root.futaba .inline {\nborder-color: #D9BFB7;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.futaba #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.futaba .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.futaba #menu {\ncolor: #800000;\n}\n:root.futaba .entry {\nborder-bottom: 1px solid #D9BFB7;\nfont-size: 12pt;\n}\n:root.futaba .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.futaba .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.burichan .dialog {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.burichan .field:focus {\nborder-color: #98E;\n}\n\n/* Header */\n:root.burichan #header-bar, :root.burichan #header-bar #notifications {\nfont-size: 11pt;\ncolor: #89A;\n}\n:root.burichan #header-bar a, :root.burichan #header-bar #notifications a {\ncolor: #34345C;\n}\n\n/* Settings */\n:root.burichan #fourchanx-settings fieldset {\nborder-color: #B7C5D9;\n}\n\n/* Quote */\n:root.burichan .backlink.deadlink {\ncolor: #34345C !important;\n}\n:root.burichan .inline {\nborder-color: #B7C5D9;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.burichan #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.burichan .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.burichan #menu {\ncolor: #000000;\n}\n:root.burichan .entry {\nborder-bottom: 1px solid #B7C5D9;\nfont-size: 12pt;\n}\n:root.burichan .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.burichan .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.tomorrow .dialog {\nbackground-color: #282A2E;\nborder-color: #111;\n}\n\n/* Header */\n:root.tomorrow #header-bar, :root.tomorrow #notifications {\nfont-size: 9pt;\ncolor: #C5C8C6;\n}\n:root.tomorrow #header-bar a, :root.tomorrow #notifications a {\ncolor: #81A2BE;\n}\n\n/* Settings */\n:root.tomorrow #fourchanx-settings fieldset {\nborder-color: #111;\n}\n\n/* Quote */\n:root.tomorrow .backlink.deadlink {\ncolor: #81A2BE !important;\n}\n:root.tomorrow .inline {\nborder-color: #111;\nbackground-color: rgba(0, 0, 0, .14);\n}\n\n/* QR */\n.tomorrow #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #282A2E;\nborder-color: #111;\n}\n:root.tomorrow .qr-preview {\nbackground-color: rgba(255, 255, 255, .15);\n}\n:root.tomorrow #qr .field {\nbackground-color: rgb(26, 27, 29);\ncolor: rgb(197,200,198);\nborder-color: rgb(40, 41, 42);\n}\n:root.tomorrow #qr .field:focus {\nborder-color: rgb(129, 162, 190) !important;\nbackground-color: rgb(30,32,36);\n}\n\n/* Menu */\n:root.tomorrow #menu {\ncolor: #C5C8C6;\n}\n:root.tomorrow .entry {\nborder-bottom: 1px solid #111;\nfont-size: 10pt;\n}\n:root.tomorrow .focused.entry {\nbackground: rgba(0, 0, 0, .33);\n}\n\n/* Watcher Favicon */\n:root.tomorrow .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.photon .dialog {\nbackground-color: #DDD;\nborder-color: #CCC;\n}\n:root.photon .field:focus {\nborder-color: #EA8;\n}\n\n/* Header */\n:root.photon #header-bar, :root.photon #notifications {\nfont-size: 9pt;\ncolor: #333;\n}\n:root.photon #header-bar a, :root.photon #notifications a {\ncolor: #FF6600;\n}\n\n/* Settings */\n:root.photon #fourchanx-settings fieldset {\nborder-color: #CCC;\n}\n\n/* Quote */\n:root.photon .backlink.deadlink {\ncolor: #F60 !important;\n}\n:root.photon .inline {\nborder-color: #CCC;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.photon #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #DDD;\nborder-color: #CCC;\n}\n:root.photon .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.photon #menu {\ncolor: #333;\n}\n:root.photon .entry {\nborder-bottom: 1px solid #CCC;\nfont-size: 10pt;\n}\n:root.photon .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.photon .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n" + css: "/* General */\n.dialog {\nbox-shadow: 0 1px 2px rgba(0, 0, 0, .15);\nborder: 1px solid;\ndisplay: block;\npadding: 0;\n}\n.captcha-img,\n.field {\nbackground-color: #FFF;\nborder: 1px solid #CCC;\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\ncolor: #333;\nfont: 13px sans-serif;\noutline: none;\ntransition: color .25s, border-color .25s;\ntransition: color .25s, border-color .25s;\n}\n.field::-moz-placeholder,\n.field:hover::-moz-placeholder {\ncolor: #AAA !important;\nfont-size: 13px !important;\nopacity: 1.0 !important;\n}\n.captch-img:hover,\n.field:hover {\nborder-color: #999;\n}\n.field:hover, .field:focus {\ncolor: #000;\n}\n.field[disabled] {\nbackground-color: #F2F2F2;\ncolor: #888;\n}\n.move {\ncursor: move;\noverflow: hidden;\n}\nlabel, .favicon {\ncursor: pointer;\n}\na[href=\"javascript:;\"] {\ntext-decoration: none;\n}\n.warning {\ncolor: red;\n}\n#boardNavDesktop {\ndisplay: none !important;\n}\na {\noutline: none !important;\n}\n\n/* 4chan style fixes */\n.opContainer, .op {\ndisplay: block !important;\noverflow: visible !important;\n}\n[hidden] {\ndisplay: none !important;\n}\n\n/* fixed, z-index */\n#overlay,\n#fourchanx-settings,\n#qp, #ihover,\n#navlinks, .fixed #header-bar,\n:root.float #updater,\n:root.float #thread-stats,\n#qr {\nposition: fixed;\n}\n#fourchanx-settings {\nz-index: 999;\n}\n#overlay {\nz-index: 900;\n}\n#notifications {\nz-index: 70;\n}\n#qp, #ihover {\nz-index: 60;\n}\n#menu {\nz-index: 50;\n}\n#navlinks, #updater, #thread-stats {\nz-index: 40;\n}\n.fixed #header-bar.autohide {\nz-index: 35;\n}\n#qr {\nz-index: 30;\n}\n#watcher {\nz-index: 8;\n}\n:root.fixed-watcher #watcher {\nz-index: 20;\n}\n.fixed #header-bar {\nz-index: 10;\n}\n/* Header */\n.fixed.top body {\npadding-top: 2em;\n}\n.fixed.bottom body {\npadding-bottom: 2em;\n}\n.fixed #header-bar {\nright: 0;\nleft: 0;\npadding: 3px 4px 4px;\n}\n.fixed.top #header-bar {\ntop: 0;\n}\n.fixed.bottom #header-bar {\nbottom: 0;\n}\n#header-bar {\nborder-width: 0;\ntransition: all .1s .05s ease-in-out;\n}\n:root.centered-links #shortcuts {\nwidth: 300px;\ntext-align: right;\n}\n:root.centered-links #header-bar {\ntext-align: center;\n}\n:root.centered-links #custom-board-list {\nposition: relative;\nleft: 150px;\n}\n.fixed.top #header-bar {\nborder-bottom-width: 1px;\n}\n.fixed.bottom #header-bar {\nbox-shadow: 0 -1px 2px rgba(0, 0, 0, .15);\nborder-top-width: 1px;\n}\n.fixed.bottom #header-bar .menu-button i {\nborder-top: none;\nborder-bottom: 6px solid;\n}\n#board-list {\ntext-align: center;\n}\n.fixed #header-bar.autohide:not(:hover) {\nbox-shadow: none;\ntransition: all .8s .6s cubic-bezier(.55, .055, .675, .19);\n}\n.fixed.top #header-bar.autohide:not(:hover) {\nmargin-bottom: -1em;\n-webkit-transform: translateY(-100%);\ntransform: translateY(-100%);\n}\n.fixed.bottom #header-bar.autohide:not(:hover) {\n-webkit-transform: translateY(100%);\ntransform: translateY(100%);\n}\n#scroll-marker {\nleft: 0;\nright: 0;\nheight: 10px;\nposition: absolute;\n}\n:root:not(.autohide) #scroll-marker {\npointer-events: none;\n}\n#header-bar #scroll-marker {\ndisplay: none;\n}\n.fixed #header-bar #scroll-marker {\ndisplay: block;\n}\n.fixed.top #header-bar #scroll-marker {\ntop: 100%;\n}\n.fixed.bottom #header-bar #scroll-marker {\nbottom: 100%;\n}\n#header-bar a:not(.entry):not(.close) {\ntext-decoration: none;\npadding: 1px;\n}\n#header-bar input {\nmargin: 0;\nvertical-align: bottom;\n}\n#shortcuts:empty {\ndisplay: none;\n}\n.brackets-wrap::before {\ncontent: \"\\00a0[\";\n}\n.brackets-wrap::after {\ncontent: \"]\\00a0\";\n}\n.disabled,\n.expand-all-shortcut {\nopacity: .45;\n}\n#shortcuts {\nfloat: right;\n}\n.shortcut {\nmargin-left: 3px;\n}\n#navbotright,\n#navtopright {\ndisplay: none;\n}\n#toggleMsgBtn {\ndisplay: none !important;\n}\n.current {\nfont-weight: bold;\n}\n/* 4chan X link brackets */\n.fourchanx-link::after {\ncontent: \"]\";\n}\n.fourchanx-link::before {\ncontent: \"[\";\n}\n/* Notifications */\n#notifications {\nposition: fixed;\ntop: 0;\nheight: 0;\ntext-align: center;\nright: 0;\nleft: 0;\ntransition: all .8s .6s cubic-bezier(.55, .055, .675, .19);\n}\n.fixed.top #header-bar #notifications {\nposition: absolute;\ntop: 100%;\n}\n.notification {\ncolor: #FFF;\nfont-weight: 700;\ntext-shadow: 0 1px 2px rgba(0, 0, 0, .5);\nbox-shadow: 0 1px 2px rgba(0, 0, 0, .15);\nborder-radius: 2px;\nmargin: 1px auto;\nwidth: 500px;\nmax-width: 100%;\nposition: relative;\ntransition: all .25s ease-in-out;\n}\n.notification.error {\nbackground-color: hsla(0, 100%, 38%, .9);\n}\n.notification.warning {\nbackground-color: hsla(36, 100%, 38%, .9);\n}\n.notification.info {\nbackground-color: hsla(200, 100%, 38%, .9);\n}\n.notification.success {\nbackground-color: hsla(104, 100%, 38%, .9);\n}\n.notification a {\ncolor: white;\n}\n.notification > .close {\npadding: 6px;\ntop: 0;\nright: 5px;\nposition: absolute;\n}\n.message {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\npadding: 6px 20px;\nmax-height: 200px;\nwidth: 100%;\noverflow: auto;\n}\n\n/* Settings */\n:root.fourchan-x body {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\n}\n#overlay {\nbackground-color: rgba(0, 0, 0, .5);\ntop: 0;\nleft: 0;\nheight: 100%;\nwidth: 100%;\n}\n#fourchanx-settings {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\nbox-shadow: 0 0 15px rgba(0, 0, 0, .15);\nheight: 600px;\nmin-height: 0;\nmax-height: 100%;\nwidth: 900px;\nmin-width: 0;\nmax-width: 100%;\nmargin: auto;\npadding: 3px;\ntop: 50%;\nleft: 50%;\n-moz-transform: translate(-50%, -50%);\n-webkit-transform: translate(-50%, -50%);\n-o-transform: translate(-50%, -50%);\ntransform: translate(-50%, -50%);\n}\n#fourchanx-settings > nav {\npadding: 2px 2px 0;\nheight: 15px;\n}\n#fourchanx-settings > nav a {\ntext-decoration: underline;\n}\n#fourchanx-settings > nav a.close {\ntext-decoration: none;\npadding: 2px;\n}\n.section-container {\noverflow: auto;\nposition: absolute;\ntop: 2.1em;\nright: 5px;\nbottom: 5px;\nleft: 5px;\npadding-right: 5px;\n}\n.sections-list {\npadding: 0 3px;\nfloat: left;\n}\n.credits {\nfloat: right;\n}\n.tab-selected {\nfont-weight: 700;\n}\n.section-sauce ul,\n.section-advanced ul {\nlist-style: none;\nmargin: 0;\n}\n.section-sauce ul {\npadding: 8px;\n}\n.section-advanced ul {\npadding: 0px;\n}\n.section-sauce li,\n.section-advanced li {\npadding-left: 4px;\n}\n.section-main label {\ntext-decoration: underline;\n}\n.section-filter ul {\npadding: 0;\n}\n.section-filter li {\nmargin: 10px 40px;\n}\n.section-filter textarea {\nheight: 500px;\n}\n.section-sauce textarea {\nheight: 350px;\n}\n.section-advanced .field[name=\"boardnav\"] {\nwidth: 100%;\n}\n.section-advanced textarea {\nheight: 150px;\n}\n.section-advanced .archive-cell {\nmin-width: 160px;\ntext-align: center;\n}\n.section-advanced #archive-board-select {\nposition: absolute;\n}\n.section-advanced .note {\nfont-size: 0.8em; \nfont-style: italic; \nmargin-left: 10px;\n}\n.section-advanced .note code {\nfont-style: normal;\nfont-size: 11px;\n}\n#fourchanx-settings fieldset {\nborder: 1px solid;\nborder-radius: 3px;\n}\n#fourchanx-settings legend {\nfont-weight: 700;\n}\n#fourchanx-settings textarea {\nfont-family: monospace;\nmin-width: 100%;\nmax-width: 100%;\n}\n#fourchanx-settings code {\ncolor: #000;\nbackground-color: #FFF;\npadding: 0 2px;\n}\n.unscroll {\noverflow: hidden;\n}\n\n/* Announcement Hiding */\n:root.hide-announcement #globalMessage {\ndisplay: none;\n}\na.hide-announcement {\nfloat: left;\n}\n\n/* Unread */\n#unread-line {\nmargin: 0;\nborder-color: rgb(255,0,0);\n}\n\n/* Thread Updater */\n#updater {\nbackground: none;\nborder: none;\nbox-shadow: none;\n}\n#updater > .move {\npadding: 5px 3px 0px;\nmargin-bottom: -3px;\n}\n#updater > div:last-child {\ntext-align: center;\n}\n#updater input[type=number] {\nwidth: 4em;\n}\n:root.float #updater {\npadding: 0px 3px;\n}\n.new {\ncolor: limegreen;\n}\n#update-status.new {\nmargin-right: 5px;\n}\n#update-timer {\ncursor: pointer;\n}\n\n/* Thread Watcher */\n#watcher {\nposition: absolute;\n}\n#watcher {\npadding-bottom: 3px;\noverflow: hidden;\nwhite-space: nowrap;\nmin-width: 120px;\nmax-height: 92%;\noverflow-y: auto;\n}\n:root.fixed-watcher #watcher {\nposition: fixed;\n}\n:root:not(.fixed-watcher) #watcher:not(:hover) {\nmax-height: 210px;\noverflow-y: hidden;\n}\n#watcher > .move {\npadding-top: 3px;\n}\n#watcher > div {\nmax-width: 250px;\noverflow: hidden;\npadding-left: 3px;\npadding-right: 3px;\ntext-overflow: ellipsis;\n}\n#watcher a {\ntext-decoration: none;\n}\n#watcher .move>.close {\nposition: absolute;\nright: 0px;\ntop: 0px;\npadding: 0px 4px;\n}\n.watch-thread-link {\npadding-top: 18px;\nwidth: 18px;\nheight: 0px;\ndisplay: inline-block;\nbackground-repeat: no-repeat;\nopacity: 0.2;\nposition: relative;\ntop: 1px;\n}\n.watch-thread-link.watched {\nopacity: 1;\n}\n\n/* Thread Stats */\n#thread-stats {\nbackground: none;\nborder: none;\nbox-shadow: none;\n}\n:root.float #post-count, :root.float #file-count {\npointer-events: none;\n}\n:root.float #thread-stats {\npadding: 0px 3px;\n}\n\n/* Quote */\n.deadlink {\ntext-decoration: none !important;\n}\n.backlink.deadlink:not(.forwardlink), .quotelink.deadlink:not(.forwardlink) {\ntext-decoration: underline !important;\n}\n.inlined {\nopacity: .5;\n}\n#qp input, .forwarded {\ndisplay: none;\n}\n.quotelink.forwardlink,\n.backlink.forwardlink {\ntext-decoration: none;\nborder-bottom: 1px dashed;\n}\n.filtered {\ntext-decoration: underline line-through;\n}\n:root.hide-backlinks .backlink.filtered {\ndisplay: none;\n}\n.inline {\nborder: 1px solid;\ndisplay: table;\nmargin: 2px 0;\n}\n.inline .post {\nborder: 0 !important;\nbackground-color: transparent !important;\ndisplay: table !important;\nmargin: 0 !important;\npadding: 1px 2px !important;\n}\n#qp > .opContainer::after {\ncontent: '';\nclear: both;\ndisplay: table;\n}\n#qp .post {\nborder: none;\nmargin: 0;\npadding: 2px 2px 5px;\n}\n#qp img {\nmax-height: 300px;\nmax-width: 500px;\nmax-height: 80vh;\nmax-width: 50vw;\n}\n.qphl {\noutline: 2px solid rgba(216, 94, 49, .7);\n}\n:root.highlight-own .yourPost>.reply,\n:root.highlight-you .quotesYou>.reply {\nborder-left: 2px solid rgba(221,0,0,.5);\n}\n/* Quote Threading */\n.threadContainer {\nmargin-left: 20px;\nborder-left: 1px solid rgba(128,128,128,.3);\n}\n.threadOP {\nclear: both;\n} \n\n/* File */\n.fileText:hover .fntrunc,\n.fileText:not(:hover) .fnfull,\n.expanded-image > .post > .file > .fileThumb > img[data-md5],\n:not(.expanded-image) > .post > .file > .fileThumb > .full-image {\ndisplay: none;\n}\n.expanding {\nopacity: .5;\n}\n:root.fit-height .full-image {\nmax-height: 100vh;\n}\n:root.fit-width .full-image {\nmax-width: 100%;\n}\n:root.gecko.fit-width .full-image,\n:root.presto.fit-width .full-image {\nwidth: 100%;\n}\n#ihover {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\nmax-height: 100%;\nmax-width: 75%;\npadding-bottom: 16px;\n}\n.fappeTyme .thread > .noFile,\n.fappeTyme .threadContainer > .noFile {\ndisplay: none;\n}\n\n/* Index/Reply Navigation */\n#navlinks {\nfont-size: 16px;\ntop: 25px;\nright: 10px;\n}\n\n/* Filter */\n.opContainer.filter-highlight {\nbox-shadow: inset 5px 0 rgba(255, 0, 0, .5);\n}\n.filter-highlight > .reply {\nbox-shadow: -5px 0 rgba(255, 0, 0, .5);\n}\n\n/* Spoiler text */\n:root.reveal-spoilers s {\ncolor: white !important;\n}\n\n/* Thread & Reply Hiding */\n.hide-thread-button,\n.hide-reply-button {\nfloat: left;\nmargin-right: 2px;\n}\n.stub ~ * {\ndisplay: none !important;\n}\n.stub input {\ndisplay: inline-block;\n}\n\n/* QR */\n:root.hide-original-post-form #postForm,\n:root.hide-original-post-form .postingMode,\n:root.hide-original-post-form #togglePostForm,\n#qr.autohide:not(.has-focus):not(:hover) > form,\n.postingMode ~ #qr select,\n#file-n-submit:not(.has-file) #qr-filerm {\ndisplay: none;\n}\n#qr select, #dump-button, .remove, .captcha-img {\ncursor: pointer;\n}\n#qr {\nz-index: 20;\nposition: fixed;\npadding: 1px;\nborder: 1px solid transparent;\nmin-width: 300px;\nborder-radius: 3px 3px 0 0;\n}\n#qrtab {\nborder-radius: 3px 3px 0 0;\n}\n#qrtab {\nmargin-bottom: 1px;\n}\n#qr .close {\nfloat: right;\npadding: 0 3px;\n}\n#qr .warning {\nmin-height: 1.6em;\nvertical-align: middle;\npadding: 0 1px;\nborder-width: 1px;\nborder-style: solid;\n}\n.qr-link-container {\ntext-align: center;\n}\n.persona {\nwidth: 248px;\nmax-width: 100%;\nmin-width: 100%;\n}\n#dump-button {\nwidth: 10%;\nmargin: 0;\nmargin-right: 4px;\nfont: 13px sans-serif;\npadding: 1px 0px 2px;\nopacity: 0.6;\n}\n.persona .field:not(#dump) {\nwidth: 95px;\nmin-width: 33.3%;\nmax-width: 33.3%;\n}\n#qr textarea.field {\nheight: 14.8em;\nmin-height: 9em;\n}\n#qr.has-captcha textarea.field {\nheight: 9em;\n}\ninput.field.tripped:not(:hover):not(:focus) {\ncolor: transparent !important; text-shadow: none !important;\n}\n#qr textarea {\nresize: both;\n}\n.captcha-img {\nmargin: 0px;\ntext-align: center;\nbackground-image: #fff;\nfont-size: 0px;\nmin-height: 59px;\nmin-width: 302px;\n}\n.captcha-input {\nwidth: 100%;\nmargin: 1px 0 0;\n}\n.captcha-input.error:focus {\nborder-color: rgb(255,0,0) !important;\n}\n.field {\n-moz-box-sizing: border-box;\nmargin: 0px;\npadding: 2px 4px 3px;\n}\n#qr textarea {\nmin-width: 100%;\n}\n#qr [type='submit'] {\nwidth: 25%;\nvertical-align: top;\n}\n:root.webkit #qr [type='submit'] {\nheight: 24px;\n}\n/* Fake File Input */\n#qr-filename,\n.has-file #qr-no-file {\ndisplay: none;\n}\n#qr-no-file,\n.has-file #qr-filename {\ndisplay: inline-block;\npadding: 0px 4px;\nmargin-bottom: 2px;\noverflow: hidden;\ntext-overflow: ellipsis;\nmax-width: 88%;\n}\n#qr-no-file {\ncolor: #AAA;\n}\n#qr-filename-container {\n-moz-box-sizing: border-box;\ndisplay: inline-block;\nposition: relative;\nwidth: 100px;\nmin-width: 74.6%;\nmax-width: 74.6%;\nmargin-right: 0.4%;\nmargin-top: 1px;\noverflow: hidden;\npadding: 2px 1px 0;\nheight: 22px;\n}\n#qr-filename-container:hover {\ncursor: text;\n}\n#qr-extras-container {\nposition: absolute;\nright: 0px;\n}\n#qr-filerm {\nmargin-right: 2px;\nz-index: 2;\n}\n#file-n-submit {\nheight: 23px;\n}\n#qr input[type=file] {\nvisibility: hidden;\nposition: absolute;\n}\n/* Thread Select / Spoiler Label */\n#qr select {\nfloat: right;\n}\n#qr.has-spoiler .has-file #qr-spoiler-label {\nwidth: 6.7%;\nmin-width: 6.7%;\nmax-width: 6.7%;\ndisplay: inline-block;\ntext-align: center;\nvertical-align: top;\n}\n#qr.has-spoiler #file-n-submit:not(.has-file) #qr-spoiler-label {\ndisplay: none;\n}\n#qr.has-spoiler .has-file #qr-filename-container {\nmax-width: 67.9%;\nmin-width: 67.9%;\n}\n#qr-spoiler-label input {\nposition: relative;\ntop: 3px;\n}\n/* Dumping UI */\n.dump #dump-list-container {\ndisplay: block;\n}\n#dump-list-container {\ndisplay: none;\nposition: relative;\noverflow-y: hidden;\nmargin-top: 1px;\n}\n#dump-list {\noverflow-x: auto;\noverflow-y: hidden;\nwhite-space: nowrap;\nwidth: 248px;\nmax-width: 100%;\nmin-width: 100%;\n}\n#dump-list:hover {\noverflow-x: auto;\n}\n.qr-preview {\n-moz-box-sizing: border-box;\ncounter-increment: thumbnails;\ncursor: move;\ndisplay: inline-block;\nheight: 90px;\nwidth: 90px;\npadding: 2px;\nopacity: .5;\noverflow: hidden;\nposition: relative;\ntext-shadow: 0 1px 1px #000;\n-moz-transition: opacity .25s ease-in-out;\nvertical-align: top;\nbackground-size: cover;\n}\n.qr-preview:hover,\n.qr-preview:focus {\nopacity: .9;\n}\n.qr-preview::before {\ncontent: counter(thumbnails);\ncolor: #fff;\nposition: absolute;\ntop: 3px;\nright: 3px;\ntext-shadow: 0 0 3px #000, 0 0 8px #000;\n}\n.qr-preview#selected {\nopacity: 1;\n}\n.qr-preview.drag {\nbox-shadow: 0 0 10px rgba(0,0,0,.5);\n}\n.qr-preview.over {\nborder-color: #fff;\n}\n.qr-preview > span {\ncolor: #fff;\n}\n.remove {\nbackground: none;\ncolor: #e00;\nfont-weight: 700;\npadding: 3px;\n}\na:only-of-type > .remove {\ndisplay: none;\n}\n.remove:hover::after {\ncontent: \" Remove\";\n}\n.qr-preview > label {\nbackground: rgba(0,0,0,.5);\ncolor: #fff;\nright: 0; bottom: 0; left: 0;\nposition: absolute;\ntext-align: center;\n}\n.qr-preview > label > input {\nmargin: 0;\n}\n#add-post {\ncursor: pointer;\nfont-size: 2em;\nposition: absolute;\ntop: 50%;\nright: 10px;\n-moz-transform: translateY(-50%);\n}\n.textarea {\nposition: relative;\n}\n:root.webkit .textarea {\nmargin-bottom: -2px;\n}\n#char-count {\ncolor: #000;\nbackground: hsla(0, 0%, 100%, .5);\nfont-size: 8pt;\nposition: absolute;\nbottom: 1px;\nright: 1px;\npointer-events: none;\n}\n\n/* Menu */\n.menu-button {\ndisplay: inline-block;\nposition: relative;\ncursor: pointer;\n}\n.menu-button i {\nborder-top: 6px solid;\nborder-right: 4px solid transparent;\nborder-left: 4px solid transparent;\ndisplay: inline-block;\nmargin: 2px;\nvertical-align: middle;\n}\n#menu {\nposition: fixed;\noutline: none;\n}\n.entry {\nborder-bottom: 1px solid rgba(0,0,0,.25);\ncursor: pointer;\ndisplay: block;\noutline: none;\npadding: 3px 7px;\nposition: relative;\ntext-decoration: none;\nwhite-space: nowrap;\n}\n.left>.entry.has-submenu {\npadding-right: 17px !important;\n}\n.entry:last-child {\nborder-bottom: 0;\n}\n.has-submenu::after {\ncontent: \"\";\nborder-left: .5em solid;\nborder-top: .3em solid transparent;\nborder-bottom: .3em solid transparent;\ndisplay: inline-block;\nmargin: .3em;\nposition: absolute;\nright: 3px;\n}\n.left .has-submenu::after {\nborder-left: 0;\nborder-right: .5em solid;\n}\n.submenu {\ndisplay: none;\nposition: absolute;\nleft: 100%;\ntop: -1px;\n}\n.focused .submenu {\ndisplay: block;\n}\n.imp-exp-result {\nposition: absolute;\ntext-align: center;\nmargin: auto;\nright: 0px;\nleft: 0px;\nwidth: 200px;\n}\n.export, .import {\ncursor: pointer;\ntext-decoration: none !important;\n}\n/* Link Title Favicons */\n.linkify.YouTube {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAYAAABr5z2BAAABIklEQVQoz53LvUrDUBjG8bOoOammSf1IoBSvoCB4JeIqOHgBLt6AIMRBBQelWurQ2kERnMRBsBUcIp5FJSBI5oQsJVkkUHh8W0o5nhaFHvjBgef/Mq+Q46RJBMkI/vE+aOus956tnEswIZe1LV0QyJ5sE2GzgZfVMtRNIdiDpccEssdlB1mW4bvTwdvWJtRdErM7U+8S/FJykCRJX5qm+KpVce8UMNLRLbulz4iSjTAMh6Iowsd5BeNadp3nUF0VlxAEwZBotXC0Usa4ll3meZdA1iguwvf9vpvDA2wvmKgYGtSud8suDB4TyGr2PF49D/vra9jRZ1BVdknMzgwuCGSnZEObwu6sBnVTCHZiaC7BhFx2PKdxUidiAH/4lLo9Mv0DELVs9qsOHXwAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.Vimeo {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAASJJREFUOE9jYAAC7ln7/pODQXrBmq333PvPu/YaSRikB6QXbACpmmHqsRoAMll7+20UQ0H8tmuv/pdffPFfZtNNuByGASBFIPDh5x+4IV6HHoDFYGDJgw+YBoBMBUkgA5BtIKduuvvy//svX+FSB+88wTTAc+/t/83bj/0HScLA5BPXwc7lKJ36f+L6XXDxhUfOYxrAPWUnWKFp9UQUm3iWQxSDXAEDSX3zcIcB96wD/x+8eA1XDNKMHAYg20GW4Y0FkCIYAAUqzEBQOIBciRzlWKMxZelOlMCEcVxq+jHSC1YDJPs3YBgA8jey0/F6ARRwsFAHORukmat9NdbUijMpg/wKcrJodDFOzSBXwA3Alh9AToZFI7a8Asu98BxJbnYGAJb5vYLDANzSAAAAAElFTkSuQmCC') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.SoundCloud {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABsklEQVQ4y5WTy2pUQRCGv2rbzDjJeAlIBmOyipGIIJqFEBDElwh4yULGeRFXPoEIBl/AvQ/gC2RnxCAoxijiwks852S6+3dxzslcHJCpTXVX11/Xv0097gLPgVNMJxnQNfX4zsqleWbnpoMf/oa9d988MM9MC/rp+E0a+A0dsVobMNMCOO8B6McRoABJI+A6gJmN3D2A8jgEBCEkSEMBrcrsDAzDWWn3AjgKFaDMmgRqniGFgsaDp1jrLOngDf1XT1D+A1dFc4MKAkkiCVKjjVu7g9+4Rzx4i1u6hjXbuMWr0O5QPNvCu7IaCZwEKQukLGDrm5x8uI0tr6MkiGlkiv7yLfzN+6S5i6QsIMABkEfcxhbWWYMkVAOjxvYAjc3HNHrbKI9VBQBFwF25XQKSBjqIf1YBuAurEMrczgDygD6/x2LCpFLXLUyQ+PoldphhBhYfIX09XU1+Flaukz7uYqs3SHs7cG4BmTsmkBUF9mmXEwa28BNLPaQPLepuNcbGSWQquQC2/Kdcox1FUGkcB0ykck1nA2+wTzMs8stGnP4rbWGw74EuS/GFQWfK7/wF6P4F7fzIAYkdmdEAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.audio {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAitJREFUOE9jYCAWKJWwavr0KyXWb/FIbDtUFFyzJx6nVofE2Xo5nXsj0rqPNSR0nVkR2Hjmgmfd+U9Otdf+m5Vf/6+SfeU/R9ChVVgNYDRtlfJuuPA/rPfe/4QpD/6nznj0P27Kw/9unff/69Xf+69c/+C/SO7N/0z+OAxgMmmRCe++/r9i3ev/KWvf/vdY8PK/bt/9/wrNV3/IN5y/IVt1YqNg4pGTTP4HsbuA2bhZ2qvpyn+xjIObxAp3VwqlrgngLFyryVy5nhPmZJHANS2cwYexG8BmVC/pWn3hP4NZlzWuQDJI3dIiFnUUuwEsQAOcq87jNcC7fHeLUtJxHF4AGmBWeAavAWH1+1rUUk7giAWjOknllON4DXAs2NEiG4/DBQxAF/CFHfrPYI4jDFSLuJVjNrUJhB/B7gIGo1pJRt99GAZYJK7wLJ1z7Xzl4vu/7aqv/GRBj0bjqAX2qb0nJ7mXH17C4HcUxQA+hymWtSue/C5a9up/9Ozn/7Vr7v1nRY7GqMb91T3b3v6vWvPmf/S0p/9ZQk+DDLCBRSOz06Jqk+o7/21nvfqvsebDf7kZL/5zBaxphkezd+OFn7HzXvz3Wvjmv9a8N//5Ek//ZTBpVYUrMG2X5wjcdl68+uI/wa5Lr3hSNjczGFeywOVZ/bbcVGp//F9izfv/Ql03f3P4LC/HSEQquYwMFnUCDJ7dzBhyjGZNQpye89M5gpfnMvtNUyE2h4PUAQBovvT7lyNljwAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.LiveLeak {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAydJREFUOE9Nk1tIk2EYx79NyUNqTk0o6KYrnZeChodLDxfeZpCbJk4RXU5Nm7tYRYhiYXbQlaeGutyW2gxtpB1RIyKDEjKwA6Ti2dR5KNDn+fq/S6TBj/f93r3P732e53s/qfnkSdej4GB2SBLbwf+jmB+gUMgOheLg/z7EdCUnO6Ref392SpK8Hyh3I+gBwBo7lUp2xcbyQEoKD6alyQOpqd754/h4FjJXZCRJTl9ftmEzoK5/wdQJxPgkLY2WV1dpc2uLtnZ2eHNnhza3t2nd46GhjAzuValY6jx0iIfS03msoIDuQ9COQCtoUSjohU5HuwgaN5loeXycd3d3aW9vzwvW2K5SkdTi58fvzGb+3tdHFggA3QONEAzn59PvjQ1yqNX0zenkvX0B4ffWaGRraChJd/385JGqKvlzTw/fRqOaIGkEd1DjU52O/3g83BkTw5MOh7yJuUCUM2o0yi2hoSw1IIOhykr+YLNRHYKu4XQvyKA/N5c8yMCCDD7Z7bz26xcJ1rH2rKKCG0UJdRAMlJbyG6uVrkJQjWAB5tSbk0Nr2HwDgvcQiIYur6zQyvo6ucvLueHIEZKuQPBQr+dXra1kRuqXEOwFArtWSytra1QdFUVjNhvPLS3R3OIiLUDUD0F1WBhJJtwDW2Ehu5uaqBICI4IFlRB0QLCEzaboaHrd0cHzCBYsIIuesjK+LAQXkEFrXh676uupGCWcR6AeghLQptGQONUAwfOuLp6Zn6eZuTmaXVig7pISrhI90ENgQbdHhoep32JhFzLpu3WLio8epUYIfs7OUjF6UKJW88XERLqYkEBNej11oG8XhCAvMFAuOn5cNiclsTkhQTbhmpri4lgbEMANWi1DwC/xit3t7bK7rY0Fo4OD3G4wyEURESzloAdnceezlErK8vH5N4KzPj50PTOTfkxP0+THj/RlYoInJyZI8HVqim5qNFwQHk7SucBAPo2PKRMNPLM/4pnFszYkhJsNBu6uqWFHba1sr61lQSveQFZQkFx07BhJmhMnrLn4NLMPH/aSExR0QDbmWhwgyEapwDvXoDxdWBiXnjrV/Bdm2kYUxLwmEgAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.Vocaroo {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAw9JREFUOE9jYMABuMwYmCyTJKUCGlSnFSy02TTzeOyCiQcDViX26qVz2TAyYtWmEMwuoZ3M7V40LcB79pHkc0svpvzY8jD//87nxf+3Pyn8v/ZO8v+VNyP/2mZJumI1QCWSI8232Hjumitlfw5+qPp/9l8TCt76JP//xkdx/wsXWCzjtWFkwTCkbWFe9plPk/+ga4Txz/xt/D/hkN//gMXif21a+NbyWjIwoRiy6GDT5rP/mlFsPfyp5n/NpOj/22+0gMUXXIz/H7hC/L/bFKFbPDZMrHAD5H35OPt2J9zacDv/f3V7xv9FhwrBGubsT/1//Pjx/1GJ/mD+/nfl/1v3Ovy3KRJNQbHdOlXCvOO03/+pm1P/v3v37n90hhtYw9HPtf8Xb2v937cmHswHeWPRxYj/LvkK3igGKARwicTO07118H3V/5kbi/4vPZMJtK3s/6YH2f+Pfq1B8VbjWrdnMu5s4nAD9CNFhKwz5DTUvLl419zKvAcLtG1P84BRl/b/5M/6/6f/NPzf/qzo84yj0Uus0xUU4Zor54bm9+4OfZG02OCuoAMTb9ZkC9ull1Nvrr2Z+XvRpaRfc65H/68F+jl9svEhzyLFWoccWVc+eyTHq/twydjlKRln7jX9bNMkMJnbhoFRL1xCqmKx6/yi2fYXa/c5/e846PV/5fW0/7OPx/yfcjzop34ulxdGGvDuU8mMXaX507lBuiN6ueadmQeT/p/93vf/1O+G//sP5fw/eL3o/5JLif8zVxs+Tlir9S26UyeFQQvJGBE7FvaFZ9LfN+1y+WjbItSb3GmXvXd15v8zroH/HxgE/D+aGPx/18vi/z07PeZNPRKxe/Kh0Ae8toxscCO4zBkYXArk9C1SxJUYjBkYPPIVtbbuTftz3cz//2O9wP/75iSAXdO72/dt2HL5F6YlfBW4MiJYXMiBiW3t7azHBx+V/t89N+H/8a+1//e9K/9attDp5LQjYX8SuvVL8RoAkmxa65299Erq1FnHo0qrl7t4BddriIs4MrM3rfWcFd+pGwVSAwBZ0bKP8yrZPAAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.pastebin {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAtZJREFUOE+NU91LWmEc7sJtQew/2MUY7INg7CLY3W5GMHazyzEQo9UmfYxZTbAiVlgRqLMSZ+XnDC3z2+Y0+8JGakKZTtR0Tl2wtgtLLQh29cz3ZZ3h3Q68vOc95zzP73l+z+/U1f292O09DRxubxOH23P//1bvtQts3dPnry7LZnXJhcUl5Avf8dHtwY+fv2AyW5DOfIXFakMm+w0G4wISyRRm55TQG0y/Wzv6mikJ52Xf9TmVBoFAAD6fDwqFAqFQCJubmzCbzZiensbp6SmkUikikQi0Wi0kEgm6ewVaStDCfXPDandifn6egoaGhrCzswO1Wg2Hw4HBwUGk02kIBAL4/X4IhUJMTk6ii8dfYggy2RwymQzOz88Rj8dRLpexv7+PSqWCYDCIQqGAra0tJBIJrK2t0XdVAjNDEIl+wfj4OEqlEq2wt7dHrchkMmrBYDCAz+fTIjweD7FYrJbgIJOlgLOzM8jlcip1eXmZ2rFarVAqlRCLxcjlchCJRFRljYJYPAG32418Pg+n04lsNouVlRUcHh7C4/FQIOlHNBqlezgcJgQWxkIgGMbExASVNjY2hvX1dVo9mUzS5wREFLhcLrqTcw2B//M2RkdHodPp4PV6oVKpqH+SCom3v7+fNnF4eJiJusbCJ6+PviSyScakiaR5RIHRaKQpmEwmbAdCeD8zB6vdhebHT8SMhcUlC83bbrdTJRsbG3RwiCVCRNJJpDIoVeNNJJJQzKryV+rrmxiCtyNCCmaz2VhdXQWXy6XDpNfrodFoYLXZUTw+pk222Z3lW3ca26rgSwzBwqIZAwMDlITMAVEwNTVFR5fEJpK8Qyp1AJvDVbrTeLenCmxgfiZ22+urCtWHyu7uLp2wVCpFKx0dHaFYLOLk5KT6Y9kgk89kb95ubK0BX7A8a+1qannRLeW0daj/rU51S3tn9dypfvDw0QiLxbpX/Z7FVK7e/AEj4Wf24/2f5AAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.gist {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAk1JREFUeNqUkzuIE1EUhv955MnsbB6r4kYQLUQQFncV3SnCIqJsoWGDYOGjsIiCtY2Kla1sjLBIsFFcXJC1kaSwENQmXUQSRSUSjCQSTCbkbR4z47lXEgtBNwcu3DNzvvO8R8jlcj7LshKmaWqYQERRTAmCcEru9/sJr9er0QF92BJMAVGr1TQ6CeZAc7lcGAwGkyQAxpTLZU0eDoc8crfbRTgcRjAYRCQSYSmi1WpxY7fbjU6ng1gshmaziXg8zhnGIpVKWbquW9ls1mLZsaMoiqWq6lgnBxY55He/328Vi0XOMFZmqVMD4fF4QBAajcY48khY9JE4HA4enTGMFVkaTHmy+ZzD/5NSqYSNB484w1h55ODO3TVu4FXcWDywl24Cmp0e1WBhyuWELAtIf/qKUrWOONmev3Lpt4NRCXq1gplpBS/v3cDc0nGg9h1o1ZkfwO4Atu1B8cM7HLt8k37V/y5B2b4bJxf2Y+7oEbyJrkMvUjki0YYJ03LidfQxAt4dOHdCw5RdGZcgGobBlQtnV/BDr1GfDai7ZiHZZRi9PoY/e5SCCTUwC9gk1GmMh5YWOcNYkR4Sv1y9uAJbYB82N57h4OnDmN7phjQ0qUkWRJuB+TMaPn/5iFfvv+Ha7eucYey4iWw8q6tRJJNJ3Fp7ClUawEkViBTfkCR0YUNTVHD/4Tpm/P4/U2CeKpUKfD4fJDIMhUKEhP45St50XedZyLQY6Xw+v8AUemVb2oNqtYpCocCWKi2TLLfb7ReZTGZ+kmUi7i2VvfxLgAEAZChMriPcl+IAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.image {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAs5JREFUOE+lk/tvi1EYx98/xT8gW4REIpGFMEQWl2FiM9ZMZhm2xRAyOsmujFFmdFRHu0tWm87UypxStr69zPauN5e5rHVp3IYhbOvHy+wHEQlxkm+ek+d8nm9OznkeSfrfldmgJC7QyUlTymsJTfuTZ25z4HdWYwyLreYhtpgekGPw0+kKvo1Eo+IXRSIiEhkWZuc9tqnsJD9EqTUopCxjSGTpB0iueczSo1HyW8cpsExQ1DbxI2pt45j9cXpexul4FEd79RnZphAa/SD7WvuFtO6UItbU9LC+YQxNI2w0wwYT5LRAdhOU3oBTIXC9gXP3oUSGgz2vST3gYHejR0jptT1C332f8yrUEYHrz8CgxDnpm6DKCUfc0KnmXa/AEVPPwnDcD0cvetA2uYRk67Ive/lpjO7YBO1PPuF8Df3vwf4cbNE4tqdw7YVq8HYyHx6FvhE1hkMEg8HDUqvFkjT4aIjMqkqyqkswDSrcfBfH+Q561YLAZ/B+BLda6FXlU/cPv0AoEPhuoP1h4Av7Wbh9E/Py15NWWUjeSR3nZDfeN+N0DY9hG/7K1eGP3P0S5/EYRFUF/IOTBrUXHPm9fT6mr1xEwupkZqxbzLyiDJYUZ5NSnkdqdSHpxyrYdFpPgdmAsdfJwPMI/Yr65bf7tZLGGBQ7DNdJWFtIYvoOZmbuZE7OXpIKKli86zAr9p9gTVktWTVnKTI2U95uRWe3U2IJUDbVB5p6hVm5x5m9Vc/cnedZUNzC8lILaQesZBy6hEZ3maKzgvJWFzVWD9XtXvVGQbSWASFtMATVRlJIKbOTWtlJXaeXepuPM1f6MNp9GLt8mLvvYLmp0OhQ2Fwvk6m7xaqDTvY0eYWUVtcnllXfYlGpnfklVuraHHg8HjxuN+6fktUHlWWZPaZeUo/ILK0UKttBcbNbSB9GP0yLxWJJUxoZGUn80zD9C/vXQ/4NHY10h3M1zmQAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.InstallGentoo {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAklJREFUOE9jYEAAASBTCorZkcSRmTjVCDLziCwG4hfM3EIvGNm44oC6WNEM4WXi5FsEkmfhFX3BxMmfAJSHW9Qr55Px3aZp3X/btq3/hQydPzKysMcCFbBBDeFj4uBdqBJR/gskb1W34j+PmulLoJwbzBJJoMm7dNO7/ntMP/XfpW/v//SKvk+7tl7fvXfTpx5pCdWVSiHFv1wnHQbLi9sE/Wdk5SwBauaCGQB3gUPb5v+7Lr/8/+fvr/9fv/z+f+Pyr/9bV735l9Wy/79Dx/b/Nk0bsLoAHgbeAVHv/v77/f8f0IB7N7+cu3DuecK54z9+7lzz639e9pK/7HwSWMMA5BJwCJeXtOm/fvVj1fcfv369f//92cN7X6ZcPvf9x6Htv//vXP3r/+T245UEYgpskPTNq08LgN749/PH7/93rv/6f/rw7//nj//4f+bU0zQcUQwWBkdVbGz62y+fv3wHeeXrlz//H9798//qpY//M3KqfzGxc8djiWKwZnBUuWQ2/fr46fv/P39+///x/ff/d69//z97+s7fyMb5/+y7d2GLYriDZikFF/1qXXXj/4Pbv/8/f/jn/5MH316/eP6jVlBAaIt6VO1/jxmn/zv27P7Pp2HxEajLD90ra9Sj6/979O37X73w0n+vqOL/0lJyMVBFq0EGgDSD0oKAlu1/oHg4ugGzVCKqfouYuL1Xj676Iajr8AnJFricGqYc3Bw+Zi6BVUxsXLHAdL6QiYMPFNrwpIxHDsUhgtAMAopKDjQn4pPDF7P45QC4hSmc1eX8WgAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n\n/* General */\n:root.yotsuba .dialog {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.yotsuba .field:focus {\nborder-color: #EA8;\n}\n\n/* Header */\n:root.yotsuba #header-bar, :root.yotsuba #notifications {\nfont-size: 9pt;\ncolor: #B86;\n}\n:root.yotsuba #header-bar a, :root.yotsuba #notifications a {\ncolor: #800000;\n}\n\n/* Settings */\n:root.yotsuba #fourchanx-settings fieldset {\nborder-color: #D9BFB7;\n}\n\n/* Quote */\n:root.yotsuba .backlink.deadlink {\ncolor: #00E !important;\n}\n:root.yotsuba .inline {\nborder-color: #D9BFB7;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.yotsuba #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.yotsuba .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.yotsuba #menu {\ncolor: #800000;\n}\n:root.yotsuba .entry {\nborder-bottom: 1px solid #D9BFB7;\nfont-size: 10pt;\n}\n:root.yotsuba .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.yotsuba .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.yotsuba-b .dialog {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.yotsuba-b .field:focus {\nborder-color: #98E;\n}\n\n/* Header */\n:root.yotsuba-b #header-bar, :root.yotsuba-b #notifications {\nfont-size: 9pt;\ncolor: #89A;\n}\n:root.yotsuba-b #header-bar a, :root.yotsuba-b #notifications a {\ncolor: #34345C;\n}\n\n/* Settings */\n:root.yotsuba-b #fourchanx-settings fieldset {\nborder-color: #B7C5D9;\n}\n\n/* Quote */\n:root.yotsuba-b .backlink.deadlink {\ncolor: #34345C !important;\n}\n:root.yotsuba-b .inline {\nborder-color: #B7C5D9;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.yotsuba-b #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.yotsuba-b .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.yotsuba-b #menu {\ncolor: #000;\n}\n:root.yotsuba-b .entry {\nborder-bottom: 1px solid #B7C5D9;\nfont-size: 10pt;\n}\n:root.yotsuba-b .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.yotsuba-b .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.futaba .dialog {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.futaba .field:focus {\nborder-color: #EA8;\n}\n\n/* Header */\n:root.futaba #header-bar, :root.futaba #notifications {\nfont-size: 11pt;\ncolor: #B86;\n}\n:root.futaba #header-bar a, :root.futaba #notifications a {\ncolor: #800000;\n}\n\n/* Settings */\n:root.futaba #fourchanx-settings fieldset {\nborder-color: #D9BFB7;\n}\n\n/* Quote */\n:root.futaba .backlink.deadlink {\ncolor: #00E !important;\n}\n:root.futaba .inline {\nborder-color: #D9BFB7;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.futaba #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.futaba .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.futaba #menu {\ncolor: #800000;\n}\n:root.futaba .entry {\nborder-bottom: 1px solid #D9BFB7;\nfont-size: 12pt;\n}\n:root.futaba .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.futaba .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.burichan .dialog {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.burichan .field:focus {\nborder-color: #98E;\n}\n\n/* Header */\n:root.burichan #header-bar, :root.burichan #header-bar #notifications {\nfont-size: 11pt;\ncolor: #89A;\n}\n:root.burichan #header-bar a, :root.burichan #header-bar #notifications a {\ncolor: #34345C;\n}\n\n/* Settings */\n:root.burichan #fourchanx-settings fieldset {\nborder-color: #B7C5D9;\n}\n\n/* Quote */\n:root.burichan .backlink.deadlink {\ncolor: #34345C !important;\n}\n:root.burichan .inline {\nborder-color: #B7C5D9;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.burichan #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.burichan .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.burichan #menu {\ncolor: #000000;\n}\n:root.burichan .entry {\nborder-bottom: 1px solid #B7C5D9;\nfont-size: 12pt;\n}\n:root.burichan .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.burichan .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.tomorrow .dialog {\nbackground-color: #282A2E;\nborder-color: #111;\n}\n\n/* Header */\n:root.tomorrow #header-bar, :root.tomorrow #notifications {\nfont-size: 9pt;\ncolor: #C5C8C6;\n}\n:root.tomorrow #header-bar a, :root.tomorrow #notifications a {\ncolor: #81A2BE;\n}\n\n/* Settings */\n:root.tomorrow #fourchanx-settings fieldset {\nborder-color: #111;\n}\n\n/* Quote */\n:root.tomorrow .backlink.deadlink {\ncolor: #81A2BE !important;\n}\n:root.tomorrow .inline {\nborder-color: #111;\nbackground-color: rgba(0, 0, 0, .14);\n}\n\n/* QR */\n.tomorrow #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #282A2E;\nborder-color: #111;\n}\n:root.tomorrow .qr-preview {\nbackground-color: rgba(255, 255, 255, .15);\n}\n:root.tomorrow #qr .field {\nbackground-color: rgb(26, 27, 29);\ncolor: rgb(197,200,198);\nborder-color: rgb(40, 41, 42);\n}\n:root.tomorrow #qr .field:focus {\nborder-color: rgb(129, 162, 190) !important;\nbackground-color: rgb(30,32,36);\n}\n\n/* Menu */\n:root.tomorrow #menu {\ncolor: #C5C8C6;\n}\n:root.tomorrow .entry {\nborder-bottom: 1px solid #111;\nfont-size: 10pt;\n}\n:root.tomorrow .focused.entry {\nbackground: rgba(0, 0, 0, .33);\n}\n\n/* Watcher Favicon */\n:root.tomorrow .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.photon .dialog {\nbackground-color: #DDD;\nborder-color: #CCC;\n}\n:root.photon .field:focus {\nborder-color: #EA8;\n}\n\n/* Header */\n:root.photon #header-bar, :root.photon #notifications {\nfont-size: 9pt;\ncolor: #333;\n}\n:root.photon #header-bar a, :root.photon #notifications a {\ncolor: #FF6600;\n}\n\n/* Settings */\n:root.photon #fourchanx-settings fieldset {\nborder-color: #CCC;\n}\n\n/* Quote */\n:root.photon .backlink.deadlink {\ncolor: #F60 !important;\n}\n:root.photon .inline {\nborder-color: #CCC;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.photon #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #DDD;\nborder-color: #CCC;\n}\n:root.photon .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.photon #menu {\ncolor: #333;\n}\n:root.photon .entry {\nborder-bottom: 1px solid #CCC;\nfont-size: 10pt;\n}\n:root.photon .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.photon .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n" }; Main.init(); diff --git a/builds/4chan-X.meta.js b/builds/4chan-X.meta.js index fe446724a..83b98d198 100644 --- a/builds/4chan-X.meta.js +++ b/builds/4chan-X.meta.js @@ -1,6 +1,6 @@ // ==UserScript== // @name 4chan X -// @version 1.2.17 +// @version 1.2.19 // @namespace 4chan-X // @description Cross-browser userscript for maximum lurking on 4chan. // @license MIT; https://github.com/seaweedchan/4chan-x/blob/master/LICENSE diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index 12a7be632..dbc3073e5 100644 --- a/builds/4chan-X.user.js +++ b/builds/4chan-X.user.js @@ -1,7 +1,7 @@ // Generated by CoffeeScript // ==UserScript== // @name 4chan X -// @version 1.2.17 +// @version 1.2.19 // @namespace 4chan-X // @description Cross-browser userscript for maximum lurking on 4chan. // @license MIT; https://github.com/seaweedchan/4chan-x/blob/master/LICENSE @@ -19,7 +19,7 @@ // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwAgMAAAAqbBEUAAAACVBMVEUAAGcAAABmzDNZt9VtAAAAAXRSTlMAQObYZgAAAHFJREFUKFOt0LENACEIBdBv4Qju4wgWanEj3D6OcIVMKaitYHEU/jwTCQj8W75kiVCSBvdQ5/AvfVHBin11BgdRq3ysBgfwBDRrj3MCIA+oAQaku/Q1cNctrAmyDl577tOThYt/Y1RBM4DgOHzM0HFTAyLukH/cmRnqAAAAAElFTkSuQmCC // ==/UserScript== /* -* 4chan X - Version 1.2.17 - 2013-06-18 +* 4chan X - Version 1.2.19 - 2013-07-21 * * Licensed under the MIT license. * https://github.com/seaweedchan/4chan-x/blob/master/LICENSE @@ -133,6 +133,7 @@ 'Index Navigation': [false, 'Add buttons to navigate between threads.'], 'Reply Navigation': [false, 'Add buttons to navigate to top / bottom of thread.'], 'Check for Updates': [true, 'Check for updated versions of 4chan X.'], + 'Show Updated Notifications': [true, 'Show notifications when 4chan X is successfully updated.'], 'Emoji': [false, 'Adds icons next to names for different emails'], 'Color User IDs': [false, 'Assign unique colors to user IDs on boards that use them'], 'Remove Spoilers': [false, 'Remove all spoilers in text.'], @@ -319,7 +320,7 @@ doc = d.documentElement; g = { - VERSION: '1.2.17', + VERSION: '1.2.19', NAMESPACE: '4chan X.', boards: {}, threads: {}, @@ -406,9 +407,9 @@ }; $.ready = function(fc) { - var cb, _ref; + var cb; - if ((_ref = d.readyState) === 'interactive' || _ref === 'complete') { + if (d.readyState !== 'loading') { $.queueTask(fc); return; } @@ -674,9 +675,9 @@ }; $.open = function(URL) { - return GM_openInTab(($.el('a', { - href: URL - })).href); + return $.open = function(URL) { + return GM_openInTab(URL); + }; }; $.debounce = function(wait, fn) { @@ -754,21 +755,6 @@ return (value < min ? min : value > max ? max : value); }; - $.syncing = {}; - - $.sync = (function() { - window.addEventListener('storage', function(e) { - var cb; - - if (cb = $.syncing[e.key]) { - return cb(JSON.parse(e.newValue)); - } - }, false); - return function(key, cb) { - return $.syncing[g.NAMESPACE + key] = cb; - }; - })(); - $.item = function(key, val) { var item; @@ -777,6 +763,21 @@ return item; }; + $.syncing = {}; + + $.sync = (function() { + $.on(window, 'storage', function(e) { + var cb; + + if (cb = $.syncing[e.key]) { + return cb(JSON.parse(e.newValue)); + } + }); + return function(key, cb) { + return $.syncing[g.NAMESPACE + key] = cb; + }; + })(); + $["delete"] = function(keys) { var key, _i, _len; @@ -866,8 +867,8 @@ }; function Thread(ID, board) { + this.ID = ID; this.board = board; - this.ID = +ID; this.fullID = "" + this.board + "." + this.ID; this.posts = {}; g.threads[this.fullID] = board.threads[this] = this; @@ -890,7 +891,7 @@ }; function Post(root, thread, board, that) { - var alt, anchor, capcode, date, email, file, fileInfo, flag, info, name, post, size, subject, thumb, tripcode, uniqueID, unit; + var capcode, date, email, flag, info, name, post, subject, tripcode, uniqueID; this.thread = thread; this.board = board; @@ -909,6 +910,11 @@ quotelinks: [], backlinks: info.getElementsByClassName('backlink') }; + if (!(this.isReply = $.hasClass(post, 'reply'))) { + this.thread.OP = this; + this.thread.isSticky = !!$('.stickyIcon', info); + this.thread.isClosed = !!$('.closedIcon', info); + } this.info = {}; if (subject = $('.subject', info)) { this.nodes.subject = subject; @@ -934,7 +940,7 @@ this.nodes.capcode = capcode; this.info.capcode = capcode.textContent.replace('## ', ''); } - if (flag = $('.countryFlag', info)) { + if (flag = $('.flag, .countryFlag', info)) { this.nodes.flag = flag; this.info.flag = flag.title; } @@ -951,36 +957,7 @@ } this.parseComment(); this.parseQuotes(); - if ((file = $('.file', post)) && (thumb = $('img[data-md5]', file))) { - alt = thumb.alt; - anchor = thumb.parentNode; - fileInfo = file.firstElementChild; - this.file = { - info: fileInfo, - text: fileInfo.firstElementChild, - thumb: thumb, - URL: anchor.href, - size: alt.match(/[\d.]+\s\w+/)[0], - MD5: thumb.dataset.md5, - isSpoiler: $.hasClass(anchor, 'imgspoiler') - }; - size = +this.file.size.match(/[\d.]+/)[0]; - unit = ['B', 'KB', 'MB', 'GB'].indexOf(this.file.size.match(/\w+$/)[0]); - while (unit-- > 0) { - size *= 1024; - } - this.file.sizeInBytes = size; - this.file.thumbURL = that.isArchived ? thumb.src : "" + location.protocol + "//thumbs.4chan.org/" + board + "/thumb/" + (this.file.URL.match(/(\d+)\./)[1]) + "s.jpg"; - this.file.name = $('span[title]', fileInfo).title.replace(/%22/g, '"'); - if (this.file.isImage = /(jpg|png|gif)$/i.test(this.file.name)) { - this.file.dimensions = this.file.text.textContent.match(/\d+x\d+/)[0]; - } - } - if (!(this.isReply = $.hasClass(post, 'reply'))) { - this.thread.OP = this; - this.thread.isSticky = !!$('.stickyIcon', this.nodes.info); - this.thread.isClosed = !!$('.closedIcon', this.nodes.info); - } + this.parseFile(that); this.clones = []; g.posts[this.fullID] = thread.posts[this] = board.posts[this] = this; if (that.isArchived) { @@ -989,7 +966,7 @@ } Post.prototype.parseComment = function() { - var bq, data, i, node, nodes, text, _i, _len, _ref; + var bq, i, node, nodes, text, _i, _len, _ref; bq = this.nodes.comment.cloneNode(true); _ref = $$('.abbr, .capcodeReplies, .exif, b', bq); @@ -1001,7 +978,7 @@ nodes = d.evaluate('.//br|.//text()', bq, null, 7, null); i = 0; while (i < nodes.snapshotLength) { - text.push((data = nodes.snapshotItem(i++).data) ? data : '\n'); + text.push(nodes.snapshotItem(i++).data || '\n'); } return this.info.comment = text.join('').trim().replace(/\s+$/gm, ''); }; @@ -1025,7 +1002,7 @@ continue; } this.nodes.quotelinks.push(quotelink); - if (quotelink.parentNode.parentNode.className === 'capcodeReplies') { + if (!this.isReply && $.hasClass(quotelink.parentNode.parentNode, 'capcodeReplies')) { continue; } quotes["" + (pathname.split('/')[1]) + "." + hash.slice(2)] = true; @@ -1036,6 +1013,37 @@ return this.quotes = Object.keys(quotes); }; + Post.prototype.parseFile = function(that) { + var alt, anchor, fileEl, fileInfo, size, thumb, unit; + + if (!((fileEl = $('.file', this.nodes.post)) && (thumb = $('img[data-md5]', fileEl)))) { + return; + } + alt = thumb.alt; + anchor = thumb.parentNode; + fileInfo = fileEl.firstElementChild; + this.file = { + info: fileInfo, + text: fileInfo.firstElementChild, + thumb: thumb, + URL: anchor.href, + size: alt.match(/[\d.]+\s\w+/)[0], + MD5: thumb.dataset.md5, + isSpoiler: $.hasClass(anchor, 'imgspoiler') + }; + size = +this.file.size.match(/[\d.]+/)[0]; + unit = ['B', 'KB', 'MB', 'GB'].indexOf(this.file.size.match(/\w+$/)[0]); + while (unit-- > 0) { + size *= 1024; + } + this.file.sizeInBytes = size; + this.file.thumbURL = that.isArchived ? thumb.src : "" + location.protocol + "//thumbs.4chan.org/" + this.board + "/thumb/" + (this.file.URL.match(/(\d+)\./)[1]) + "s.jpg"; + this.file.name = $('span[title]', fileInfo).title; + if (this.file.isImage = /(jpg|png|gif)$/i.test(this.file.name)) { + return this.file.dimensions = this.file.text.textContent.match(/\d+x\d+/)[0]; + } + }; + Post.prototype.kill = function(file, now) { var clone, quotelink, strong, _i, _j, _len, _len1, _ref, _ref1; @@ -1126,7 +1134,7 @@ _ref = this.clones.slice(index); for (_i = 0, _len = _ref.length; _i < _len; _i++) { clone = _ref[_i]; - clone.nodes.root.setAttribute('data-clone', index++); + clone.nodes.root.dataset.clone = index++; } }; @@ -1138,7 +1146,7 @@ __extends(Clone, _super); function Clone(origin, context) { - var file, index, info, inline, inlined, key, nodes, post, root, val, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3; + var file, info, inline, inlined, key, nodes, post, root, val, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3; this.origin = origin; this.context = context; @@ -1214,8 +1222,7 @@ this.isDead = true; } this.isClone = true; - index = origin.clones.push(this) - 1; - root.setAttribute('data-clone', index); + root.dataset.clone = origin.clones.push(this) - 1; } return Clone; @@ -1537,9 +1544,7 @@ return; } $.asap((function() { - var _ref; - - return $.id('boardNavMobile') || ((_ref = d.readyState) === 'interactive' || _ref === 'complete'); + return $.id('boardNavMobile') || d.readyState !== 'loading'; }), Header.setBoardList); $.prepend(d.body, _this.bar); $.add(d.body, Header.hover); @@ -1609,7 +1614,7 @@ if (!text) { return; } - as = $$('#full-board-list a', Header.bar); + as = $$('#full-board-list a[title]', Header.bar); nodes = text.match(/[\w@]+((-(all|title|replace|full|index|catalog|url:"[^"]+[^"]"|text:"[^"]+")|\,"[^"]+[^"]"))*|[^\w@]+/g).map(function(t) { var a, board, m, _i, _len; @@ -1640,7 +1645,7 @@ a = a.cloneNode(true); a.textContent = /-title/.test(t) || /-replace/.test(t) && $.hasClass(a, 'current') ? a.title : /-full/.test(t) ? "/" + board + "/ - " + a.title : (m = t.match(/-text:"(.+)"/)) ? m[1] : a.textContent; if (m = t.match(/-(index|catalog)/)) { - a.setAttribute('data-only', m[1]); + a.dataset.only = m[1]; a.href = "//boards.4chan.org/" + board + "/"; if (m[1] === 'catalog') { a.href += 'catalog'; @@ -1907,7 +1912,7 @@ capcodeStart = ''; capcode = ''; } - flag = flagCode ? ("  + flagCode + ") : ''; + flag = !flagCode ? '' : boardID === 'pol' ? "  + flagCode + " : " "; if (file != null ? file.isDeleted : void 0) { fileHTML = isOP ? ("
") + ("File deleted.") + "
" : ("
") + ("File deleted.") + "
"; } else if (file) { @@ -1996,11 +2001,11 @@ postFromNode: function(root) { return Get.postFromRoot($.x('ancestor::div[contains(@class,"postContainer")][1]', root)); }, - contextFromLink: function(quotelink) { + contextFromNode: function(quotelink) { return Get.postFromRoot($.x('ancestor::div[parent::div[@class="thread"]][1]', quotelink)); }, postDataFromLink: function(link) { - var boardID, path, postID, threadID; + var boardID, path, postID, threadID, _ref; if (link.hostname === 'boards.4chan.org') { path = link.pathname.split('/'); @@ -2008,9 +2013,8 @@ threadID = path[3]; postID = link.hash.slice(2); } else { - boardID = link.dataset.boardid; - threadID = link.dataset.threadid || 0; - postID = link.dataset.postid; + _ref = link.dataset, boardID = _ref.boardID, threadID = _ref.threadID, postID = _ref.postID; + threadID || (threadID = 0); } return { boardID: boardID, @@ -2182,7 +2186,7 @@ } }); comment = bq.innerHTML.replace(/(^|>)(>[^<$]*)(<|$)/g, '$1$2$3').replace(/((>){2}(>\/[a-z\d]+\/)?\d+)/g, '$1'); - threadID = data.thread_num; + threadID = +data.thread_num; o = { postID: "" + postID, threadID: "" + threadID, @@ -2617,7 +2621,13 @@ if ($.x('ancestor::div[contains(@class,"inline")][1]', root)) { $.on(d, 'keydown', o.hoverend); } - return $.on(root, 'mousemove', o.hover); + $.on(root, 'mousemove', o.hover); + o.workaround = function(e) { + if (!root.contains(e.target)) { + return o.hoverend(); + } + }; + return $.on(doc, 'mousemove', o.workaround); }; hover = function(e) { var clientX, clientY, height, left, right, style, top, _ref; @@ -2641,6 +2651,7 @@ $.off(this.root, this.endEvents, this.hoverend); $.off(d, 'keydown', this.hoverend); $.off(this.root, 'mousemove', this.hover); + $.off(doc, 'mousemove', this.workaround); if (this.cb) { return this.cb.call(this); } @@ -2926,7 +2937,7 @@ href: 'javascript:;', textContent: text }); - el.setAttribute('data-type', type); + el.dataset.type = type; $.on(el, 'click', Filter.menu.makeFilter); return { el: el, @@ -3520,7 +3531,7 @@ innerHTML: " " + (type === 'hide' ? '-' : '+') + " ", href: 'javascript:;' }); - a.setAttribute('data-fullid', thread.fullID); + a.dataset.fullID = thread.fullID; $.on(a, 'click', ThreadHiding.toggle); return a; }, @@ -3548,7 +3559,7 @@ }, toggle: function(thread) { if (!(thread instanceof Thread)) { - thread = g.threads[this.dataset.fullid]; + thread = g.threads[this.dataset.fullID]; } if (thread.isHidden) { ThreadHiding.show(thread); @@ -3775,7 +3786,7 @@ } e.preventDefault(); _ref = Get.postDataFromLink(this), boardID = _ref.boardID, threadID = _ref.threadID, postID = _ref.postID; - context = Get.contextFromLink(this); + context = Get.contextFromNode(this); if ($.hasClass(this, 'inlined')) { QuoteInline.rm(this, boardID, threadID, postID, context); } else { @@ -3924,7 +3935,7 @@ className: 'dialog' }); $.add(Header.hover, qp); - Get.postClone(boardID, threadID, postID, qp, Get.contextFromLink(this)); + Get.postClone(boardID, threadID, postID, qp, Get.contextFromNode(this)); UI.hover({ root: this, el: qp, @@ -4248,9 +4259,11 @@ target: '_blank', textContent: "" + quote + "\u00A0(Dead)" }); - a.setAttribute('data-boardid', boardID); - a.setAttribute('data-threadid', post.thread.ID); - a.setAttribute('data-postid', postID); + $.extend(a.dataset, { + boardID: boardID, + threadID: post.thread.ID, + postID: postID + }); } } else if (redirect = Redirect.to('thread', { boardID: boardID, @@ -4268,8 +4281,10 @@ postID: postID })) { $.addClass(a, 'quotelink'); - a.setAttribute('data-boardid', boardID); - a.setAttribute('data-postid', postID); + $.extend(a.dataset, { + boardID: boardID, + postID: postID + }); } } if (!this.quotes.contains(quoteID)) { @@ -4743,7 +4758,7 @@ } }, close: function() { - var i, _i, _len, _ref; + var post, _i, _len, _ref; if (QR.req) { QR.abort(); @@ -4759,10 +4774,10 @@ if (Conf['QR Shortcut']) { $.toggleClass($('.qr-shortcut'), 'disabled'); } - _ref = QR.posts; + _ref = QR.posts.splice(0, QR.posts.length, new QR.post(true)); for (_i = 0, _len = _ref.length; _i < _len; _i++) { - i = _ref[_i]; - QR.posts[0].rm(); + post = _ref[_i]; + post["delete"](); } QR.cooldown.auto = false; return QR.status(); @@ -4828,12 +4843,13 @@ return QR.notifications = []; }, status: function() { - var disabled, status, value; + var disabled, status, thread, value; if (!QR.nodes) { return; } - if (g.DEAD) { + thread = QR.posts[0].thread; + if (thread !== 'new' && g.threads["" + g.BOARD + "." + thread].isDead) { value = 404; disabled = true; QR.cooldown.auto = false; @@ -5087,7 +5103,7 @@ } }, quote: function(e) { - var OP, caretPos, com, index, post, range, s, sel, selectionRoot, text, thread, _ref; + var caretPos, com, index, post, range, s, sel, text, thread, _ref; if (e != null) { e.preventDefault(); @@ -5096,11 +5112,9 @@ return; } sel = d.getSelection(); - selectionRoot = $.x('ancestor::div[contains(@class,"postContainer")][1]', sel.anchorNode); post = Get.postFromNode(this); - OP = Get.contextFromLink(this).thread.OP; text = ">>" + post + "\n"; - if ((s = sel.toString().trim()) && post.nodes.root === selectionRoot) { + if ((s = sel.toString().trim()) && post === Get.postFromNode(sel.anchorNode)) { s = s.replace(/\n/g, '\n>'); text += ">" + s + "\n"; } @@ -5113,7 +5127,7 @@ } _ref = QR.nodes, com = _ref.com, thread = _ref.thread; if (!com.value) { - thread.value = OP.ID; + thread.value = Get.contextFromNode(this).thread; } caretPos = com.selectionStart; com.value = com.value.slice(0, caretPos) + text + com.value.slice(com.selectionEnd); @@ -5186,7 +5200,7 @@ fileInput: function(files) { var file, length, max, post, _i, _len; - if (this instanceof Element) { + if (files instanceof Event) { files = __slice.call(this.files); QR.nodes.fileInput.value = null; } @@ -5295,7 +5309,7 @@ _Class.prototype.rm = function() { var index; - $.rm(this.nodes.el); + this["delete"](); index = QR.posts.indexOf(this); if (QR.posts.length === 1) { new QR.post(true); @@ -5304,9 +5318,11 @@ (QR.posts[index - 1] || QR.posts[index + 1]).select(); } QR.posts.splice(index, 1); - if (!window.URL) { - return; - } + return QR.status(); + }; + + _Class.prototype["delete"] = function() { + $.rm(this.nodes.el); return URL.revokeObjectURL(this.URL); }; @@ -5365,21 +5381,23 @@ }; _Class.prototype.save = function(input) { - var value, _ref; + var name, _ref; if (input.type === 'checkbox') { this.spoiler = input.checked; return; } - value = input.value; - this[input.dataset.name] = value; - if (input.nodeName !== 'TEXTAREA') { - return; - } - this.nodes.span.textContent = value; - QR.characterCount(); - if (QR.cooldown.auto && this === QR.posts[0] && (0 < (_ref = QR.cooldown.seconds) && _ref <= 5)) { - return QR.cooldown.auto = false; + name = input.dataset.name; + this[name] = input.value; + switch (name) { + case 'thread': + return QR.status(); + case 'com': + this.nodes.span.textContent = this.com; + QR.characterCount(); + if (QR.cooldown.auto && this === QR.posts[0] && (0 < (_ref = QR.cooldown.seconds) && _ref <= 5)) { + return QR.cooldown.auto = false; + } } }; @@ -5403,9 +5421,7 @@ if (QR.spoiler) { this.nodes.label.hidden = false; } - if (window.URL) { - URL.revokeObjectURL(this.URL); - } + URL.revokeObjectURL(this.URL); this.showFileData(); if (!/^image/.test(file.type)) { this.nodes.el.style.backgroundImage = null; @@ -5414,22 +5430,10 @@ return this.setThumbnail(); }; - _Class.prototype.setThumbnail = function(fileURL) { - var img, reader, + _Class.prototype.setThumbnail = function() { + var fileURL, img, _this = this; - if (!window.URL) { - if (!fileURL) { - reader = new FileReader(); - reader.onload = function(e) { - return _this.setThumbnail(e.target.result); - }; - reader.readAsDataURL(this.file); - return; - } - } else { - fileURL = URL.createObjectURL(this.file); - } img = $.el('img'); img.onload = function() { var applyBlob, cv, data, height, i, l, s, ui8a, width, _i; @@ -5440,9 +5444,7 @@ } height = img.height, width = img.width; if (height < s || width < s) { - if (window.URL) { - _this.URL = fileURL; - } + _this.URL = fileURL; _this.nodes.el.style.backgroundImage = "url(" + _this.URL + ")"; return; } @@ -5457,11 +5459,6 @@ cv.height = img.height = height; cv.width = img.width = width; cv.getContext('2d').drawImage(img, 0, 0, width, height); - if (!window.URL) { - _this.nodes.el.style.backgroundImage = "url(" + (cv.toDataURL()) + ")"; - delete _this.URL; - return; - } URL.revokeObjectURL(fileURL); applyBlob = function(blob) { _this.URL = URL.createObjectURL(blob); @@ -5481,6 +5478,7 @@ type: 'image/png' })); }; + fileURL = URL.createObjectURL(this.file); return img.src = fileURL; }; @@ -5493,9 +5491,6 @@ this.nodes.label.hidden = true; } this.showFileData(); - if (!window.URL) { - return; - } return URL.revokeObjectURL(this.URL); }; @@ -5556,12 +5551,11 @@ _Class.prototype.drop = function() { var el, index, newIndex, oldIndex, post; - el = $('.drag', this.parentNode); - $.rmClass(el, 'drag'); $.rmClass(this, 'over'); if (!this.draggable) { return; } + el = $('.drag', this.parentNode); index = function(el) { return __slice.call(el.parentNode.children).indexOf(el); }; @@ -5569,7 +5563,8 @@ newIndex = index(this); (oldIndex < newIndex ? $.after : $.before)(this, el); post = QR.posts.splice(oldIndex, 1)[0]; - return QR.posts.splice(newIndex, 0, post); + QR.posts.splice(newIndex, 0, post); + return QR.status(); }; return _Class; @@ -5588,7 +5583,7 @@ }), this.ready.bind(this)); }, ready: function() { - var imgContainer, input, observer, setLifetime, + var imgContainer, input, setLifetime, _this = this; setLifetime = function(e) { @@ -5614,14 +5609,9 @@ img: imgContainer.firstChild, input: input }; - if (window.MutationObserver) { - observer = new MutationObserver(this.load.bind(this)); - observer.observe(this.nodes.challenge, { - childList: true - }); - } else { - $.on(this.nodes.challenge, 'DOMNodeInserted', this.load.bind(this)); - } + new MutationObserver(this.load.bind(this)).observe(this.nodes.challenge, { + childList: true + }); $.on(imgContainer, 'click', this.reload.bind(this)); $.on(input, 'keydown', this.keydown.bind(this)); $.on(input, 'focus', function() { @@ -5630,8 +5620,11 @@ $.on(input, 'blur', function() { return $.rmClass(QR.nodes.el, 'focus'); }); - $.get('captchas', [], function(item) { - return _this.sync(item['captchas']); + $.get('captchas', [], function(_arg) { + var captchas; + + captchas = _arg.captchas; + return _this.sync(captchas); }); $.sync('captchas', this.sync); this.reload(); @@ -5641,7 +5634,7 @@ return $.after(QR.nodes.com.parentNode, [imgContainer, input]); }, sync: function(captchas) { - this.captchas = captchas; + QR.captcha.captchas = captchas; return QR.captcha.count(); }, getOne: function() { @@ -5790,7 +5783,6 @@ QR.mimeTypes = mimeTypes.split(', '); QR.mimeTypes.push(''); nodes.fileInput.max = $('input[name=MAX_FILE_SIZE]').value; - nodes.fileInput.accept = "text/*, " + mimeTypes; QR.spoiler = !!$('input[name=spoiler]'); if (QR.spoiler) { $.addClass(QR.nodes.el, 'has-spoiler'); @@ -6058,16 +6050,12 @@ post: post, isReply: isReply }); - if (threadID === postID) { - URL = "/" + g.BOARD + "/res/" + threadID; - } else if (g.VIEW === 'index' && !QR.cooldown.auto && Conf['Open Post in New Tab']) { - URL = "/" + g.BOARD + "/res/" + threadID + "#p" + postID; - } + URL = threadID === postID ? "/" + g.BOARD + "/res/" + threadID : g.VIEW === 'index' && !QR.cooldown.auto && Conf['Open Post in New Tab'] ? "/" + g.BOARD + "/res/" + threadID + "#p" + postID : void 0; if (URL) { if (Conf['Open Post in New Tab']) { - $.open("/" + g.BOARD + "/res/" + threadID); + $.open(URL); } else { - window.location = "/" + g.BOARD + "/res/" + threadID; + window.location = URL; } } return QR.status(); @@ -6421,7 +6409,7 @@ id: 'ihover', src: post.file.URL }); - el.setAttribute('data-fullid', post.fullID); + el.dataset.fullID = post.fullID; $.add(Header.hover, el); UI.hover({ root: this, @@ -6441,7 +6429,7 @@ if (!doc.contains(this)) { return; } - post = g.posts[this.dataset.fullid]; + post = g.posts[this.dataset.fullID]; src = this.src.split('/'); if (src[2] === 'images.4chan.org') { URL = Redirect.to('file', { @@ -6571,6 +6559,74 @@ } }; + Sauce = { + init: function() { + var err, link, links, _i, _len, _ref; + + if (g.VIEW === 'catalog' || !Conf['Sauce']) { + return; + } + links = []; + _ref = Conf['sauces'].split('\n'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + link = _ref[_i]; + try { + if (link[0] !== '#') { + links.push(this.createSauceLink(link.trim())); + } + } catch (_error) { + err = _error; + } + } + if (!links.length) { + return; + } + this.links = links; + this.link = $.el('a', { + target: '_blank' + }); + return Post.prototype.callbacks.push({ + name: 'Sauce', + cb: this.node + }); + }, + createSauceLink: function(link) { + var m, text; + + link = link.replace(/%(T?URL|MD5|board)/ig, function(parameter) { + switch (parameter) { + case '%TURL': + return "' + encodeURIComponent(post.file.thumbURL) + '"; + case '%URL': + return "' + encodeURIComponent(post.file.URL) + '"; + case '%MD5': + return "' + encodeURIComponent(post.file.MD5) + '"; + case '%board': + return "' + encodeURIComponent(post.board) + '"; + default: + return parameter; + } + }); + text = (m = link.match(/;text:(.+)$/)) ? m[1] : link.match(/(\w+)\.\w+\//)[1]; + link = link.replace(/;text:.+$/, ''); + return Function('post', 'a', "a.href = '" + link + "';\na.textContent = '" + text + "';\nreturn a;"); + }, + node: function() { + var link, nodes, _i, _len, _ref; + + if (this.isClone || !this.file) { + return; + } + nodes = []; + _ref = Sauce.links; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + link = _ref[_i]; + nodes.push($.tn('\u00A0'), link(this, Sauce.link.cloneNode(true))); + } + return $.add(this.file.info, nodes); + } + }; + ArchiveLink = { init: function() { var div, entry, type, _i, _len, _ref; @@ -6711,8 +6767,8 @@ return; } $.off(this, 'click', DeleteLink["delete"]); - this.textContent = "Deleting " + this.textContent + "..."; fileOnly = $.hasClass(this, 'delete-file'); + this.textContent = "Deleting " + (fileOnly ? 'file' : 'post') + "..."; form = { mode: 'usrdel', onlyimgdel: fileOnly, @@ -6832,39 +6888,29 @@ node: function() { var button; - button = Menu.makeButton(this); if (this.isClone) { - $.replace($('.menu-button', this.nodes.info), button); - return; + button = $('.menu-button', this.nodes.info); + } else { + button = Menu.makeButton(this); + $.add(this.nodes.info, [$.tn('\u00A0'), button]); } - return $.add(this.nodes.info, [$.tn('\u00A0'), button]); + return $.on(button, 'click', Menu.toggle); }, makeButton: (function() { var a; a = null; - return function(post) { - var clone; - + return function() { a || (a = $.el('a', { className: 'menu-button fourchanx-link', innerHTML: '', href: 'javascript:;' })); - clone = a.cloneNode(true); - clone.setAttribute('data-postid', post.fullID); - if (post.isClone) { - clone.setAttribute('data-clone', true); - } - $.on(clone, 'click', Menu.toggle); - return clone; + return a.cloneNode(true); }; })(), toggle: function(e) { - var post; - - post = this.dataset.clone ? Get.postFromNode(this) : g.posts[this.dataset.postid]; - return Menu.menu.toggle(e, this, post); + return Menu.menu.toggle(e, this, Get.postFromNode(this)); } }; @@ -7285,7 +7331,7 @@ This saves bandwidth for both the user and the servers and avoid unnecessary computation. */ - _ref = [0, 304].contains(req.status) ? [null, null] : ["" + req.statusText + " (" + req.status + ")", 'warning'], text = _ref[0], klass = _ref[1]; + _ref = req.status === 304 ? [null, null] : ["" + req.statusText + " (" + req.status + ")", 'warning'], text = _ref[0], klass = _ref[1]; ThreadUpdater.set('status', text, klass); } if (ThreadUpdater.postID) { @@ -7703,23 +7749,21 @@ } }, scroll: function() { - var checkPosition, hash, onload, post, posts, prevID, root; + var checkPosition, hash, onload, post, posts, root; if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) { return; } if (Unread.posts.length) { - prevID = 0; - while (root = $.x('preceding-sibling::div[contains(@class,"postContainer")][1]', Unread.posts[0].nodes.root)) { - post = Get.postFromRoot(root); - if (prevID === post.ID) { - break; - } - prevID = post.ID; - if (!post.isHidden) { + post = Unread.posts[0]; + while (root = $.x('preceding-sibling::div[contains(@class,"replyContainer")][1]', post.nodes.root)) { + if (!(post = Get.postFromRoot(root)).isHidden) { break; } } + if (!root) { + return; + } onload = function() { if (checkPosition(root)) { return root.scrollIntoView(false); @@ -7904,7 +7948,7 @@ post: {}, file: {}, init: function() { - var archive, arr, boardID, data, id, name, type, _i, _len, _ref, _ref1, _ref2, _ref3; + var archive, arr, boardID, data, id, name, type, _ref, _ref1, _ref2, _results; _ref = Conf['selectedArchives']; for (boardID in _ref) { @@ -7925,22 +7969,32 @@ } } _ref2 = Redirect.archives; + _results = []; for (name in _ref2) { archive = _ref2[name]; - _ref3 = archive.boards; - for (_i = 0, _len = _ref3.length; _i < _len; _i++) { - boardID = _ref3[_i]; - if (!(boardID in Redirect.thread)) { - Redirect.thread[boardID] = archive; + _results.push((function() { + var _i, _len, _ref3, _results1; + + _ref3 = archive.boards; + _results1 = []; + for (_i = 0, _len = _ref3.length; _i < _len; _i++) { + boardID = _ref3[_i]; + if (!(boardID in Redirect.thread)) { + Redirect.thread[boardID] = archive; + } + if (!(boardID in Redirect.post || archive.software !== 'foolfuuka')) { + Redirect.post[boardID] = archive; + } + if (!(boardID in Redirect.file || !archive.files.contains(boardID))) { + _results1.push(Redirect.file[boardID] = archive); + } else { + _results1.push(void 0); + } } - if (!(boardID in Redirect.post || archive.software !== 'foolfuuka')) { - Redirect.post[boardID] = archive; - } - if (!(boardID in Redirect.file || !archive.files.contains(boardID))) { - Redirect.file[boardID] = archive; - } - } + return _results1; + })()); } + return _results; }, archives: { 'Foolz': { @@ -7948,7 +8002,7 @@ 'http': false, 'https': true, 'software': 'foolfuuka', - 'boards': ['a', 'co', 'gd', 'jp', 'm', 'q', 'sp', 'tg', 'tv', 'v', 'vg', 'vp', 'vr', 'wsg'], + 'boards': ['a', 'co', 'gd', 'jp', 'm', 'q', 'sp', 'tg', 'tv', 'vg', 'vp', 'vr', 'wsg'], 'files': ['a', 'gd', 'jp', 'm', 'q', 'tg', 'vg', 'vp', 'vr', 'wsg'] }, 'NSFW Foolz': { @@ -7982,25 +8036,17 @@ 'boards': ['c', 'w', 'wg'], 'files': ['c', 'w', 'wg'] }, - 'Love is Over': { - 'domain': 'loveisover.me', - 'http': true, - 'https': true, - 'software': 'foolfuuka', - 'boards': ['d', 'h', 'v'], - 'files': ['d', 'h', 'v'] - }, 'Foolz a Shit': { 'domain': 'archive.foolzashit.com', 'http': true, 'https': true, 'software': 'foolfuuka', - 'boards': ['adv', 'asp', 'cm', 'e', 'i', 'lgbt', 'n', 'o', 'p', 'pol', 's', 's4s', 't', 'trv', 'y'], - 'files': ['adv', 'asp', 'cm', 'e', 'i', 'lgbt', 'n', 'o', 'p', 's', 's4s', 't', 'trv', 'y'] + 'boards': ['adv', 'asp', 'cm', 'i', 'lgbt', 'n', 'o', 'p', 's4s', 't', 'trv'], + 'files': ['adv', 'asp', 'cm', 'i', 'lgbt', 'n', 'o', 'p', 's4s', 't', 'trv'] }, 'Install Gentoo': { 'domain': 'archive.installgentoo.net', - 'http': true, + 'http': false, 'https': true, 'software': 'fuuka', 'boards': ['diy', 'g', 'sci'], @@ -8028,6 +8074,14 @@ 'software': 'fuuka', 'boards': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'tg', 'vr'], 'files': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'vr'] + }, + 'worldathleticproject': { + 'domain': 'fuuka.worldathleticproject.org', + 'http': true, + 'https': true, + 'software': 'foolfuuka', + 'boards': ['e', 'h', 'p', 's', 'u'], + 'files': ['e', 'h', 'p', 's', 'u'] } }, to: function(dest, data) { @@ -8899,13 +8953,13 @@ } break; case Conf['Next thread']: - if (g.VIEW === 'thread') { + if (g.VIEW !== 'index') { return; } Nav.scroll(+1); break; case Conf['Previous thread']: - if (g.VIEW === 'thread') { + if (g.VIEW !== 'index') { return; } Nav.scroll(-1); @@ -9177,10 +9231,9 @@ _ref = Nav.getThread(true), threads = _ref[0], thread = _ref[1], i = _ref[2], rect = _ref[3], topMargin = _ref[4]; top = rect.top - topMargin; - if (!((delta === -1 && Math.ceil(top) < 0) || (delta === +1 && top > 1))) { - i += delta; + if ((delta === -1 && top > -5) || (delta === +1 && top < 5)) { + top = ((_ref1 = threads[i + delta]) != null ? _ref1.getBoundingClientRect().top : void 0) - topMargin; } - top = ((_ref1 = threads[i]) != null ? _ref1.getBoundingClientRect().top : void 0) - topMargin; return window.scrollBy(0, top); } }; @@ -9327,76 +9380,6 @@ } }; - Sauce = { - init: function() { - var err, link, links, _i, _len, _ref; - - if (g.VIEW === 'catalog' || !Conf['Sauce']) { - return; - } - links = []; - _ref = Conf['sauces'].split('\n'); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - link = _ref[_i]; - if (link[0] === '#') { - continue; - } - try { - links.push(this.createSauceLink(link.trim())); - } catch (_error) { - err = _error; - continue; - } - } - if (!links.length) { - return; - } - this.links = links; - this.link = $.el('a', { - target: '_blank' - }); - return Post.prototype.callbacks.push({ - name: 'Sauce', - cb: this.node - }); - }, - createSauceLink: function(link) { - var m, text; - - link = link.replace(/%(T?URL|MD5|board)/ig, function(parameter) { - switch (parameter) { - case '%TURL': - return "' + encodeURIComponent(post.file.thumbURL) + '"; - case '%URL': - return "' + encodeURIComponent(post.file.URL) + '"; - case '%MD5': - return "' + encodeURIComponent(post.file.MD5) + '"; - case '%board': - return "' + encodeURIComponent(post.board) + '"; - default: - return parameter; - } - }); - text = (m = link.match(/;text:(.+)$/)) ? m[1] : link.match(/(\w+)\.\w+\//)[1]; - link = link.replace(/;text:.+$/, ''); - return Function('post', 'a', "a.href = '" + link + "';\na.textContent = '" + text + "';\nreturn a;"); - }, - node: function() { - var link, nodes, _i, _len, _ref; - - if (this.isClone || !this.file) { - return; - } - nodes = []; - _ref = Sauce.links; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - link = _ref[_i]; - nodes.push($.tn('\u00A0'), link(this, Sauce.link.cloneNode(true))); - } - return $.add(this.file.info, nodes); - } - }; - Time = { init: function() { if (g.VIEW === 'catalog' || !Conf['Time Formatting']) { @@ -9520,7 +9503,9 @@ el = $.el('span', { innerHTML: "4chan X has been updated to version " + g.VERSION + "." }); - new Notification('info', el, 30); + if (Conf['Show Updated Notifications']) { + new Notification('info', el, 30); + } } else { $.on(d, '4chanXInitFinished', Settings.open); } @@ -9905,7 +9890,7 @@ $.add(div, ta); return; } - return div.innerHTML = "
Filter is disabled.

\nUse regular expressions, one per line.
\nLines starting with a # will be ignored.
\nFor example, /weeaboo/i will filter posts containing the string `weeaboo`, case-insensitive.
\nMD5 filtering uses exact string matching, not regular expressions.\n

"; + return div.innerHTML = "
Filter is disabled.

\nUse regular expressions, one per line.
\nLines starting with a # will be ignored.
\nFor example, /weeaboo/i will filter posts containing the string `weeaboo`, case-insensitive.
\nMD5 filtering uses exact string matching, not regular expressions.\n

"; }, sauce: function(section) { var ta; @@ -10190,9 +10175,7 @@ $.get(Conf, Main.initFeatures); $.on(d, '4chanMainInit', Main.initStyle); return $.asap((function() { - var _ref; - - return d.head && $('link[rel="shortcut icon"]', d.head) || ((_ref = d.readyState) === 'interactive' || _ref === 'complete'); + return d.head && $('link[rel="shortcut icon"]', d.head) || d.readyState !== 'loading'; }), Main.initStyle); }, initFeatures: function(items) { @@ -10318,7 +10301,7 @@ return $.ready(Main.initReady); }, initStyle: function() { - var mainStyleSheet, observer, setStyle, style, styleSheets, _ref; + var mainStyleSheet, setStyle, style, styleSheets, _ref; $.off(d, '4chanMainInit', Main.initStyle); if (!Main.isThisPageLegit() || $.hasClass(doc, 'fourchan-x')) { @@ -10355,18 +10338,13 @@ if (!mainStyleSheet) { return; } - if (window.MutationObserver) { - observer = new MutationObserver(setStyle); - return observer.observe(mainStyleSheet, { - attributes: true, - attributeFilter: ['href'] - }); - } else { - return $.on(mainStyleSheet, 'DOMAttrModified', setStyle); - } + return new MutationObserver(setStyle).observe(mainStyleSheet, { + attributes: true, + attributeFilter: ['href'] + }); }, initReady: function() { - var board, boardChild, err, errors, href, passLink, posts, styleSelector, thread, threadChild, threads, _i, _j, _len, _len1, _ref, _ref1; + var board, err, errors, href, passLink, postRoot, posts, styleSelector, thread, threadRoot, threads, _i, _j, _len, _len1, _ref, _ref1; if (d.title === '4chan - 404 Not Found') { if (Conf['404 Redirect'] && g.VIEW === 'thread') { @@ -10385,29 +10363,23 @@ if (board = $('.board')) { threads = []; posts = []; - _ref = board.children; + _ref = $$('.board > .thread', board); for (_i = 0, _len = _ref.length; _i < _len; _i++) { - boardChild = _ref[_i]; - if (!$.hasClass(boardChild, 'thread')) { - continue; - } - thread = new Thread(boardChild.id.slice(1), g.BOARD); + threadRoot = _ref[_i]; + thread = new Thread(+threadRoot.id.slice(1), g.BOARD); threads.push(thread); - _ref1 = boardChild.children; + _ref1 = $$('.thread > .postContainer', threadRoot); for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - threadChild = _ref1[_j]; - if (!$.hasClass(threadChild, 'postContainer')) { - continue; - } + postRoot = _ref1[_j]; try { - posts.push(new Post(threadChild, thread, g.BOARD)); + posts.push(new Post(postRoot, thread, g.BOARD)); } catch (_error) { err = _error; if (!errors) { errors = []; } errors.push({ - message: "Parsing of Post No." + (threadChild.id.match(/\d+/)) + " failed. Post will be skipped.", + message: "Parsing of Post No." + (postRoot.id.match(/\d+/)) + " failed. Post will be skipped.", error: err }); } @@ -10631,11 +10603,11 @@ var _ref; if (!('thisPageIsLegit' in Main)) { - Main.thisPageIsLegit = location.hostname === 'boards.4chan.org' && !$('link[href*="favicon-status.ico"]', d.head) && ((_ref = d.title) !== '4chan - Temporarily Offline' && _ref !== '4chan - Error'); + Main.thisPageIsLegit = location.hostname === 'boards.4chan.org' && !$('link[href*="favicon-status.ico"]', d.head) && ((_ref = d.title) !== '4chan - Temporarily Offline' && _ref !== '4chan - Error' && _ref !== '504 Gateway Time-out'); } return Main.thisPageIsLegit; }, - css: "/* General */\n.dialog {\nbox-shadow: 0 1px 2px rgba(0, 0, 0, .15);\nborder: 1px solid;\ndisplay: block;\npadding: 0;\n}\n.captcha-img,\n.field {\nbackground-color: #FFF;\nborder: 1px solid #CCC;\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\ncolor: #333;\nfont: 13px sans-serif;\noutline: none;\ntransition: color .25s, border-color .25s;\ntransition: color .25s, border-color .25s;\n}\n.field::-moz-placeholder,\n.field:hover::-moz-placeholder {\ncolor: #AAA !important;\nfont-size: 13px !important;\nopacity: 1.0 !important;\n}\n.captch-img:hover,\n.field:hover {\nborder-color: #999;\n}\n.field:hover, .field:focus {\ncolor: #000;\n}\n.field[disabled] {\nbackground-color: #F2F2F2;\ncolor: #888;\n}\n.move {\ncursor: move;\noverflow: hidden;\n}\nlabel, .favicon {\ncursor: pointer;\n}\na[href=\"javascript:;\"] {\ntext-decoration: none;\n}\n.warning {\ncolor: red;\n}\n#boardNavDesktop {\ndisplay: none !important;\n}\na {\noutline: none !important;\n}\n\n/* 4chan style fixes */\n.opContainer, .op {\ndisplay: block !important;\noverflow: visible !important;\n}\n[hidden] {\ndisplay: none !important;\n}\n\n/* fixed, z-index */\n#overlay,\n#fourchanx-settings,\n#qp, #ihover,\n#navlinks, .fixed #header-bar,\n:root.float #updater,\n:root.float #thread-stats,\n#qr {\nposition: fixed;\n}\n#fourchanx-settings {\nz-index: 999;\n}\n#overlay {\nz-index: 900;\n}\n#notifications {\nz-index: 70;\n}\n#qp, #ihover {\nz-index: 60;\n}\n#menu {\nz-index: 50;\n}\n#navlinks, #updater, #thread-stats {\nz-index: 40;\n}\n.fixed #header-bar.autohide {\nz-index: 35;\n}\n#qr {\nz-index: 30;\n}\n#watcher {\nz-index: 8;\n}\n:root.fixed-watcher #watcher {\nz-index: 20;\n}\n.fixed #header-bar {\nz-index: 10;\n}\n/* Header */\n.fixed.top body {\npadding-top: 2em;\n}\n.fixed.bottom body {\npadding-bottom: 2em;\n}\n.fixed #header-bar {\nright: 0;\nleft: 0;\npadding: 3px 4px 4px;\n}\n.fixed.top #header-bar {\ntop: 0;\n}\n.fixed.bottom #header-bar {\nbottom: 0;\n}\n#header-bar {\nborder-width: 0;\ntransition: all .1s .05s ease-in-out;\n}\n:root.centered-links #shortcuts {\nwidth: 300px;\ntext-align: right;\n}\n:root.centered-links #header-bar {\ntext-align: center;\n}\n:root.centered-links #custom-board-list {\nposition: relative;\nleft: 150px;\n}\n.fixed.top #header-bar {\nborder-bottom-width: 1px;\n}\n.fixed.bottom #header-bar {\nbox-shadow: 0 -1px 2px rgba(0, 0, 0, .15);\nborder-top-width: 1px;\n}\n.fixed.bottom #header-bar .menu-button i {\nborder-top: none;\nborder-bottom: 6px solid;\n}\n#board-list {\ntext-align: center;\n}\n.fixed #header-bar.autohide:not(:hover) {\nbox-shadow: none;\ntransition: all .8s .6s cubic-bezier(.55, .055, .675, .19);\n}\n.fixed.top #header-bar.autohide:not(:hover) {\nmargin-bottom: -1em;\n-webkit-transform: translateY(-100%);\ntransform: translateY(-100%);\n}\n.fixed.bottom #header-bar.autohide:not(:hover) {\n-webkit-transform: translateY(100%);\ntransform: translateY(100%);\n}\n#scroll-marker {\nleft: 0;\nright: 0;\nheight: 10px;\nposition: absolute;\n}\n#header-bar #scroll-marker {\ndisplay: none;\n}\n.fixed #header-bar #scroll-marker {\ndisplay: block;\n}\n.fixed.top #header-bar #scroll-marker {\ntop: 100%;\n}\n.fixed.bottom #header-bar #scroll-marker {\nbottom: 100%;\n}\n#header-bar a:not(.entry):not(.close) {\ntext-decoration: none;\npadding: 1px;\n}\n#header-bar input {\nmargin: 0;\nvertical-align: bottom;\n}\n#shortcuts:empty {\ndisplay: none;\n}\n.brackets-wrap::before {\ncontent: \"\\00a0[\";\n}\n.brackets-wrap::after {\ncontent: \"]\\00a0\";\n}\n.disabled,\n.expand-all-shortcut {\nopacity: .45;\n}\n#shortcuts {\nfloat: right;\n}\n.shortcut {\nmargin-left: 3px;\n}\n#navbotright,\n#navtopright {\ndisplay: none;\n}\n#toggleMsgBtn {\ndisplay: none !important;\n}\n.current {\nfont-weight: bold;\n}\n/* 4chan X link brackets */\n.fourchanx-link::after {\ncontent: \"]\";\n}\n.fourchanx-link::before {\ncontent: \"[\";\n}\n/* Notifications */\n#notifications {\nposition: fixed;\ntop: 0;\nheight: 0;\ntext-align: center;\nright: 0;\nleft: 0;\ntransition: all .8s .6s cubic-bezier(.55, .055, .675, .19);\n}\n.fixed.top #header-bar #notifications {\nposition: absolute;\ntop: 100%;\n}\n.notification {\ncolor: #FFF;\nfont-weight: 700;\ntext-shadow: 0 1px 2px rgba(0, 0, 0, .5);\nbox-shadow: 0 1px 2px rgba(0, 0, 0, .15);\nborder-radius: 2px;\nmargin: 1px auto;\nwidth: 500px;\nmax-width: 100%;\nposition: relative;\ntransition: all .25s ease-in-out;\n}\n.notification.error {\nbackground-color: hsla(0, 100%, 38%, .9);\n}\n.notification.warning {\nbackground-color: hsla(36, 100%, 38%, .9);\n}\n.notification.info {\nbackground-color: hsla(200, 100%, 38%, .9);\n}\n.notification.success {\nbackground-color: hsla(104, 100%, 38%, .9);\n}\n.notification a {\ncolor: white;\n}\n.notification > .close {\npadding: 6px;\ntop: 0;\nright: 5px;\nposition: absolute;\n}\n.message {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\npadding: 6px 20px;\nmax-height: 200px;\nwidth: 100%;\noverflow: auto;\n}\n\n/* Settings */\n:root.fourchan-x body {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\n}\n#overlay {\nbackground-color: rgba(0, 0, 0, .5);\ntop: 0;\nleft: 0;\nheight: 100%;\nwidth: 100%;\n}\n#fourchanx-settings {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\nbox-shadow: 0 0 15px rgba(0, 0, 0, .15);\nheight: 600px;\nmin-height: 0;\nmax-height: 100%;\nwidth: 900px;\nmin-width: 0;\nmax-width: 100%;\nmargin: auto;\npadding: 3px;\ntop: 50%;\nleft: 50%;\n-moz-transform: translate(-50%, -50%);\n-webkit-transform: translate(-50%, -50%);\n-o-transform: translate(-50%, -50%);\ntransform: translate(-50%, -50%);\n}\n#fourchanx-settings > nav {\npadding: 2px 2px 0;\nheight: 15px;\n}\n#fourchanx-settings > nav a {\ntext-decoration: underline;\n}\n#fourchanx-settings > nav a.close {\ntext-decoration: none;\npadding: 2px;\n}\n.section-container {\noverflow: auto;\nposition: absolute;\ntop: 2.1em;\nright: 5px;\nbottom: 5px;\nleft: 5px;\npadding-right: 5px;\n}\n.sections-list {\npadding: 0 3px;\nfloat: left;\n}\n.credits {\nfloat: right;\n}\n.tab-selected {\nfont-weight: 700;\n}\n.section-sauce ul,\n.section-advanced ul {\nlist-style: none;\nmargin: 0;\n}\n.section-sauce ul {\npadding: 8px;\n}\n.section-advanced ul {\npadding: 0px;\n}\n.section-sauce li,\n.section-advanced li {\npadding-left: 4px;\n}\n.section-main label {\ntext-decoration: underline;\n}\n.section-filter ul {\npadding: 0;\n}\n.section-filter li {\nmargin: 10px 40px;\n}\n.section-filter textarea {\nheight: 500px;\n}\n.section-sauce textarea {\nheight: 350px;\n}\n.section-advanced .field[name=\"boardnav\"] {\nwidth: 100%;\n}\n.section-advanced textarea {\nheight: 150px;\n}\n.section-advanced .archive-cell {\nmin-width: 160px;\ntext-align: center;\n}\n.section-advanced #archive-board-select {\nposition: absolute;\n}\n.section-advanced .note {\nfont-size: 0.8em; \nfont-style: italic; \nmargin-left: 10px;\n}\n.section-advanced .note code {\nfont-style: normal;\nfont-size: 11px;\n}\n#fourchanx-settings fieldset {\nborder: 1px solid;\nborder-radius: 3px;\n}\n#fourchanx-settings legend {\nfont-weight: 700;\n}\n#fourchanx-settings textarea {\nfont-family: monospace;\nmin-width: 100%;\nmax-width: 100%;\n}\n#fourchanx-settings code {\ncolor: #000;\nbackground-color: #FFF;\npadding: 0 2px;\n}\n.unscroll {\noverflow: hidden;\n}\n\n/* Announcement Hiding */\n:root.hide-announcement #globalMessage {\ndisplay: none;\n}\na.hide-announcement {\nfloat: left;\n}\n\n/* Unread */\n#unread-line {\nmargin: 0;\nborder-color: rgb(255,0,0);\n}\n\n/* Thread Updater */\n#updater {\nbackground: none;\nborder: none;\nbox-shadow: none;\n}\n#updater > .move {\npadding: 5px 3px 0px;\nmargin-bottom: -3px;\n}\n#updater > div:last-child {\ntext-align: center;\n}\n#updater input[type=number] {\nwidth: 4em;\n}\n:root.float #updater {\npadding: 0px 3px;\n}\n.new {\ncolor: limegreen;\n}\n#update-status.new {\nmargin-right: 5px;\n}\n#update-timer {\ncursor: pointer;\n}\n\n/* Thread Watcher */\n#watcher {\nposition: absolute;\n}\n#watcher {\npadding-bottom: 3px;\noverflow: hidden;\nwhite-space: nowrap;\nmin-width: 120px;\nmax-height: 92%;\noverflow-y: auto;\n}\n:root.fixed-watcher #watcher {\nposition: fixed;\n}\n:root:not(.fixed-watcher) #watcher:not(:hover) {\nmax-height: 210px;\noverflow-y: hidden;\n}\n#watcher > .move {\npadding-top: 3px;\n}\n#watcher > div {\nmax-width: 250px;\noverflow: hidden;\npadding-left: 3px;\npadding-right: 3px;\ntext-overflow: ellipsis;\n}\n#watcher a {\ntext-decoration: none;\n}\n#watcher .move>.close {\nposition: absolute;\nright: 0px;\ntop: 0px;\npadding: 0px 4px;\n}\n.watch-thread-link {\npadding-top: 18px;\nwidth: 18px;\nheight: 0px;\ndisplay: inline-block;\nbackground-repeat: no-repeat;\nopacity: 0.2;\nposition: relative;\ntop: 1px;\n}\n.watch-thread-link.watched {\nopacity: 1;\n}\n\n/* Thread Stats */\n#thread-stats {\nbackground: none;\nborder: none;\nbox-shadow: none;\n}\n:root.float #post-count, :root.float #file-count {\npointer-events: none;\n}\n:root.float #thread-stats {\npadding: 0px 3px;\n}\n\n/* Quote */\n.deadlink {\ntext-decoration: none !important;\n}\n.backlink.deadlink:not(.forwardlink), .quotelink.deadlink:not(.forwardlink) {\ntext-decoration: underline !important;\n}\n.inlined {\nopacity: .5;\n}\n#qp input, .forwarded {\ndisplay: none;\n}\n.quotelink.forwardlink,\n.backlink.forwardlink {\ntext-decoration: none;\nborder-bottom: 1px dashed;\n}\n.filtered {\ntext-decoration: underline line-through;\n}\n:root.hide-backlinks .backlink.filtered {\ndisplay: none;\n}\n.inline {\nborder: 1px solid;\ndisplay: table;\nmargin: 2px 0;\n}\n.inline .post {\nborder: 0 !important;\nbackground-color: transparent !important;\ndisplay: table !important;\nmargin: 0 !important;\npadding: 1px 2px !important;\n}\n#qp > .opContainer::after {\ncontent: '';\nclear: both;\ndisplay: table;\n}\n#qp .post {\nborder: none;\nmargin: 0;\npadding: 2px 2px 5px;\n}\n#qp img {\nmax-height: 300px;\nmax-width: 500px;\nmax-height: 80vh;\nmax-width: 50vw;\n}\n.qphl {\noutline: 2px solid rgba(216, 94, 49, .7);\n}\n:root.highlight-own .yourPost>.reply,\n:root.highlight-you .quotesYou>.reply {\nborder-left: 2px solid rgba(221,0,0,.5);\n}\n/* Quote Threading */\n.threadContainer {\nmargin-left: 20px;\nborder-left: 1px solid rgba(128,128,128,.3);\n}\n.threadOP {\nclear: both;\n} \n\n/* File */\n.fileText:hover .fntrunc,\n.fileText:not(:hover) .fnfull,\n.expanded-image > .post > .file > .fileThumb > img[data-md5],\n:not(.expanded-image) > .post > .file > .fileThumb > .full-image {\ndisplay: none;\n}\n.expanding {\nopacity: .5;\n}\n:root.fit-height .full-image {\nmax-height: 100vh;\n}\n:root.fit-width .full-image {\nmax-width: 100%;\n}\n:root.gecko.fit-width .full-image,\n:root.presto.fit-width .full-image {\nwidth: 100%;\n}\n#ihover {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\nmax-height: 100%;\nmax-width: 75%;\npadding-bottom: 16px;\n}\n.fappeTyme .thread > .noFile,\n.fappeTyme .threadContainer > .noFile {\ndisplay: none;\n}\n\n/* Index/Reply Navigation */\n#navlinks {\nfont-size: 16px;\ntop: 25px;\nright: 10px;\n}\n\n/* Filter */\n.opContainer.filter-highlight {\nbox-shadow: inset 5px 0 rgba(255, 0, 0, .5);\n}\n.filter-highlight > .reply {\nbox-shadow: -5px 0 rgba(255, 0, 0, .5);\n}\n\n/* Spoiler text */\n:root.reveal-spoilers s {\ncolor: white !important;\n}\n\n/* Thread & Reply Hiding */\n.hide-thread-button,\n.hide-reply-button {\nfloat: left;\nmargin-right: 2px;\n}\n.stub ~ * {\ndisplay: none !important;\n}\n.stub input {\ndisplay: inline-block;\n}\n\n/* QR */\n:root.hide-original-post-form #postForm,\n:root.hide-original-post-form .postingMode,\n:root.hide-original-post-form #togglePostForm,\n#qr.autohide:not(.has-focus):not(:hover) > form,\n.postingMode ~ #qr select,\n#file-n-submit:not(.has-file) #qr-filerm {\ndisplay: none;\n}\n#qr select, #dump-button, .remove, .captcha-img {\ncursor: pointer;\n}\n#qr {\nz-index: 20;\nposition: fixed;\npadding: 1px;\nborder: 1px solid transparent;\nmin-width: 300px;\nborder-radius: 3px 3px 0 0;\n}\n#qrtab {\nborder-radius: 3px 3px 0 0;\n}\n#qrtab {\nmargin-bottom: 1px;\n}\n#qr .close {\nfloat: right;\npadding: 0 3px;\n}\n#qr .warning {\nmin-height: 1.6em;\nvertical-align: middle;\npadding: 0 1px;\nborder-width: 1px;\nborder-style: solid;\n}\n.qr-link-container {\ntext-align: center;\n}\n.persona {\nwidth: 248px;\nmax-width: 100%;\nmin-width: 100%;\n}\n#dump-button {\nwidth: 10%;\nmargin: 0;\nmargin-right: 4px;\nfont: 13px sans-serif;\npadding: 1px 0px 2px;\nopacity: 0.6;\n}\n.persona .field:not(#dump) {\nwidth: 95px;\nmin-width: 33.3%;\nmax-width: 33.3%;\n}\n#qr textarea.field {\nheight: 14.8em;\nmin-height: 9em;\n}\n#qr.has-captcha textarea.field {\nheight: 9em;\n}\ninput.field.tripped:not(:hover):not(:focus) {\ncolor: transparent !important; text-shadow: none !important;\n}\n#qr textarea {\nresize: both;\n}\n.captcha-img {\nmargin: 0px;\ntext-align: center;\nbackground-image: #fff;\nfont-size: 0px;\nmin-height: 59px;\nmin-width: 302px;\n}\n.captcha-input {\nwidth: 100%;\nmargin: 1px 0 0;\n}\n.captcha-input.error:focus {\nborder-color: rgb(255,0,0) !important;\n}\n.field {\n-moz-box-sizing: border-box;\nmargin: 0px;\npadding: 2px 4px 3px;\n}\n#qr textarea {\nmin-width: 100%;\n}\n#qr [type='submit'] {\nwidth: 25%;\nvertical-align: top;\n}\n:root.webkit #qr [type='submit'] {\nheight: 24px;\n}\n/* Fake File Input */\n#qr-filename,\n.has-file #qr-no-file {\ndisplay: none;\n}\n#qr-no-file,\n.has-file #qr-filename {\ndisplay: inline-block;\npadding: 0px 4px;\nmargin-bottom: 2px;\noverflow: hidden;\ntext-overflow: ellipsis;\nmax-width: 88%;\n}\n#qr-no-file {\ncolor: #AAA;\n}\n#qr-filename-container {\n-moz-box-sizing: border-box;\ndisplay: inline-block;\nposition: relative;\nwidth: 100px;\nmin-width: 74.6%;\nmax-width: 74.6%;\nmargin-right: 0.4%;\nmargin-top: 1px;\noverflow: hidden;\npadding: 2px 1px 0;\nheight: 22px;\n}\n#qr-filename-container:hover {\ncursor: text;\n}\n#qr-extras-container {\nposition: absolute;\nright: 0px;\n}\n#qr-filerm {\nmargin-right: 2px;\nz-index: 2;\n}\n#file-n-submit {\nheight: 23px;\n}\n#qr input[type=file] {\nvisibility: hidden;\nposition: absolute;\n}\n/* Thread Select / Spoiler Label */\n#qr select {\nfloat: right;\n}\n#qr.has-spoiler .has-file #qr-spoiler-label {\nwidth: 6.7%;\nmin-width: 6.7%;\nmax-width: 6.7%;\ndisplay: inline-block;\ntext-align: center;\nvertical-align: top;\n}\n#qr.has-spoiler #file-n-submit:not(.has-file) #qr-spoiler-label {\ndisplay: none;\n}\n#qr.has-spoiler .has-file #qr-filename-container {\nmax-width: 67.9%;\nmin-width: 67.9%;\n}\n#qr-spoiler-label input {\nposition: relative;\ntop: 3px;\n}\n/* Dumping UI */\n.dump #dump-list-container {\ndisplay: block;\n}\n#dump-list-container {\ndisplay: none;\nposition: relative;\noverflow-y: hidden;\nmargin-top: 1px;\n}\n#dump-list {\noverflow-x: auto;\noverflow-y: hidden;\nwhite-space: nowrap;\nwidth: 248px;\nmax-width: 100%;\nmin-width: 100%;\n}\n#dump-list:hover {\noverflow-x: auto;\n}\n.qr-preview {\n-moz-box-sizing: border-box;\ncounter-increment: thumbnails;\ncursor: move;\ndisplay: inline-block;\nheight: 90px;\nwidth: 90px;\npadding: 2px;\nopacity: .5;\noverflow: hidden;\nposition: relative;\ntext-shadow: 0 1px 1px #000;\n-moz-transition: opacity .25s ease-in-out;\nvertical-align: top;\nbackground-size: cover;\n}\n.qr-preview:hover,\n.qr-preview:focus {\nopacity: .9;\n}\n.qr-preview::before {\ncontent: counter(thumbnails);\ncolor: #fff;\nposition: absolute;\ntop: 3px;\nright: 3px;\ntext-shadow: 0 0 3px #000, 0 0 8px #000;\n}\n.qr-preview#selected {\nopacity: 1;\n}\n.qr-preview.drag {\nbox-shadow: 0 0 10px rgba(0,0,0,.5);\n}\n.qr-preview.over {\nborder-color: #fff;\n}\n.qr-preview > span {\ncolor: #fff;\n}\n.remove {\nbackground: none;\ncolor: #e00;\nfont-weight: 700;\npadding: 3px;\n}\na:only-of-type > .remove {\ndisplay: none;\n}\n.remove:hover::after {\ncontent: \" Remove\";\n}\n.qr-preview > label {\nbackground: rgba(0,0,0,.5);\ncolor: #fff;\nright: 0; bottom: 0; left: 0;\nposition: absolute;\ntext-align: center;\n}\n.qr-preview > label > input {\nmargin: 0;\n}\n#add-post {\ncursor: pointer;\nfont-size: 2em;\nposition: absolute;\ntop: 50%;\nright: 10px;\n-moz-transform: translateY(-50%);\n}\n.textarea {\nposition: relative;\n}\n:root.webkit .textarea {\nmargin-bottom: -2px;\n}\n#char-count {\ncolor: #000;\nbackground: hsla(0, 0%, 100%, .5);\nfont-size: 8pt;\nposition: absolute;\nbottom: 1px;\nright: 1px;\npointer-events: none;\n}\n\n/* Menu */\n.menu-button {\ndisplay: inline-block;\nposition: relative;\ncursor: pointer;\n}\n.menu-button i {\nborder-top: 6px solid;\nborder-right: 4px solid transparent;\nborder-left: 4px solid transparent;\ndisplay: inline-block;\nmargin: 2px;\nvertical-align: middle;\n}\n#menu {\nposition: fixed;\noutline: none;\n}\n.entry {\nborder-bottom: 1px solid rgba(0,0,0,.25);\ncursor: pointer;\ndisplay: block;\noutline: none;\npadding: 3px 7px;\nposition: relative;\ntext-decoration: none;\nwhite-space: nowrap;\n}\n.left>.entry.has-submenu {\npadding-right: 17px !important;\n}\n.entry:last-child {\nborder-bottom: 0;\n}\n.has-submenu::after {\ncontent: \"\";\nborder-left: .5em solid;\nborder-top: .3em solid transparent;\nborder-bottom: .3em solid transparent;\ndisplay: inline-block;\nmargin: .3em;\nposition: absolute;\nright: 3px;\n}\n.left .has-submenu::after {\nborder-left: 0;\nborder-right: .5em solid;\n}\n.submenu {\ndisplay: none;\nposition: absolute;\nleft: 100%;\ntop: -1px;\n}\n.focused .submenu {\ndisplay: block;\n}\n.imp-exp-result {\nposition: absolute;\ntext-align: center;\nmargin: auto;\nright: 0px;\nleft: 0px;\nwidth: 200px;\n}\n.export, .import {\ncursor: pointer;\ntext-decoration: none !important;\n}\n/* Link Title Favicons */\n.linkify.YouTube {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAYAAABr5z2BAAABIklEQVQoz53LvUrDUBjG8bOoOammSf1IoBSvoCB4JeIqOHgBLt6AIMRBBQelWurQ2kERnMRBsBUcIp5FJSBI5oQsJVkkUHh8W0o5nhaFHvjBgef/Mq+Q46RJBMkI/vE+aOus956tnEswIZe1LV0QyJ5sE2GzgZfVMtRNIdiDpccEssdlB1mW4bvTwdvWJtRdErM7U+8S/FJykCRJX5qm+KpVce8UMNLRLbulz4iSjTAMh6Iowsd5BeNadp3nUF0VlxAEwZBotXC0Usa4ll3meZdA1iguwvf9vpvDA2wvmKgYGtSud8suDB4TyGr2PF49D/vra9jRZ1BVdknMzgwuCGSnZEObwu6sBnVTCHZiaC7BhFx2PKdxUidiAH/4lLo9Mv0DELVs9qsOHXwAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.Vimeo {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAASJJREFUOE9jYAAC7ln7/pODQXrBmq333PvPu/YaSRikB6QXbACpmmHqsRoAMll7+20UQ0H8tmuv/pdffPFfZtNNuByGASBFIPDh5x+4IV6HHoDFYGDJgw+YBoBMBUkgA5BtIKduuvvy//svX+FSB+88wTTAc+/t/83bj/0HScLA5BPXwc7lKJ36f+L6XXDxhUfOYxrAPWUnWKFp9UQUm3iWQxSDXAEDSX3zcIcB96wD/x+8eA1XDNKMHAYg20GW4Y0FkCIYAAUqzEBQOIBciRzlWKMxZelOlMCEcVxq+jHSC1YDJPs3YBgA8jey0/F6ARRwsFAHORukmat9NdbUijMpg/wKcrJodDFOzSBXwA3Alh9AToZFI7a8Asu98BxJbnYGAJb5vYLDANzSAAAAAElFTkSuQmCC') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.SoundCloud {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABsklEQVQ4y5WTy2pUQRCGv2rbzDjJeAlIBmOyipGIIJqFEBDElwh4yULGeRFXPoEIBl/AvQ/gC2RnxCAoxijiwks852S6+3dxzslcHJCpTXVX11/Xv0097gLPgVNMJxnQNfX4zsqleWbnpoMf/oa9d988MM9MC/rp+E0a+A0dsVobMNMCOO8B6McRoABJI+A6gJmN3D2A8jgEBCEkSEMBrcrsDAzDWWn3AjgKFaDMmgRqniGFgsaDp1jrLOngDf1XT1D+A1dFc4MKAkkiCVKjjVu7g9+4Rzx4i1u6hjXbuMWr0O5QPNvCu7IaCZwEKQukLGDrm5x8uI0tr6MkiGlkiv7yLfzN+6S5i6QsIMABkEfcxhbWWYMkVAOjxvYAjc3HNHrbKI9VBQBFwF25XQKSBjqIf1YBuAurEMrczgDygD6/x2LCpFLXLUyQ+PoldphhBhYfIX09XU1+Flaukz7uYqs3SHs7cG4BmTsmkBUF9mmXEwa28BNLPaQPLepuNcbGSWQquQC2/Kdcox1FUGkcB0ykck1nA2+wTzMs8stGnP4rbWGw74EuS/GFQWfK7/wF6P4F7fzIAYkdmdEAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.audio {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAitJREFUOE9jYCAWKJWwavr0KyXWb/FIbDtUFFyzJx6nVofE2Xo5nXsj0rqPNSR0nVkR2Hjmgmfd+U9Otdf+m5Vf/6+SfeU/R9ChVVgNYDRtlfJuuPA/rPfe/4QpD/6nznj0P27Kw/9unff/69Xf+69c/+C/SO7N/0z+OAxgMmmRCe++/r9i3ev/KWvf/vdY8PK/bt/9/wrNV3/IN5y/IVt1YqNg4pGTTP4HsbuA2bhZ2qvpyn+xjIObxAp3VwqlrgngLFyryVy5nhPmZJHANS2cwYexG8BmVC/pWn3hP4NZlzWuQDJI3dIiFnUUuwEsQAOcq87jNcC7fHeLUtJxHF4AGmBWeAavAWH1+1rUUk7giAWjOknllON4DXAs2NEiG4/DBQxAF/CFHfrPYI4jDFSLuJVjNrUJhB/B7gIGo1pJRt99GAZYJK7wLJ1z7Xzl4vu/7aqv/GRBj0bjqAX2qb0nJ7mXH17C4HcUxQA+hymWtSue/C5a9up/9Ozn/7Vr7v1nRY7GqMb91T3b3v6vWvPmf/S0p/9ZQk+DDLCBRSOz06Jqk+o7/21nvfqvsebDf7kZL/5zBaxphkezd+OFn7HzXvz3Wvjmv9a8N//5Ek//ZTBpVYUrMG2X5wjcdl68+uI/wa5Lr3hSNjczGFeywOVZ/bbcVGp//F9izfv/Ql03f3P4LC/HSEQquYwMFnUCDJ7dzBhyjGZNQpye89M5gpfnMvtNUyE2h4PUAQBovvT7lyNljwAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.LiveLeak {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAydJREFUOE9Nk1tIk2EYx79NyUNqTk0o6KYrnZeChodLDxfeZpCbJk4RXU5Nm7tYRYhiYXbQlaeGutyW2gxtpB1RIyKDEjKwA6Ti2dR5KNDn+fq/S6TBj/f93r3P732e53s/qfnkSdej4GB2SBLbwf+jmB+gUMgOheLg/z7EdCUnO6Ref392SpK8Hyh3I+gBwBo7lUp2xcbyQEoKD6alyQOpqd754/h4FjJXZCRJTl9ftmEzoK5/wdQJxPgkLY2WV1dpc2uLtnZ2eHNnhza3t2nd46GhjAzuValY6jx0iIfS03msoIDuQ9COQCtoUSjohU5HuwgaN5loeXycd3d3aW9vzwvW2K5SkdTi58fvzGb+3tdHFggA3QONEAzn59PvjQ1yqNX0zenkvX0B4ffWaGRraChJd/385JGqKvlzTw/fRqOaIGkEd1DjU52O/3g83BkTw5MOh7yJuUCUM2o0yi2hoSw1IIOhykr+YLNRHYKu4XQvyKA/N5c8yMCCDD7Z7bz26xcJ1rH2rKKCG0UJdRAMlJbyG6uVrkJQjWAB5tSbk0Nr2HwDgvcQiIYur6zQyvo6ucvLueHIEZKuQPBQr+dXra1kRuqXEOwFArtWSytra1QdFUVjNhvPLS3R3OIiLUDUD0F1WBhJJtwDW2Ehu5uaqBICI4IFlRB0QLCEzaboaHrd0cHzCBYsIIuesjK+LAQXkEFrXh676uupGCWcR6AeghLQptGQONUAwfOuLp6Zn6eZuTmaXVig7pISrhI90ENgQbdHhoep32JhFzLpu3WLio8epUYIfs7OUjF6UKJW88XERLqYkEBNej11oG8XhCAvMFAuOn5cNiclsTkhQTbhmpri4lgbEMANWi1DwC/xit3t7bK7rY0Fo4OD3G4wyEURESzloAdnceezlErK8vH5N4KzPj50PTOTfkxP0+THj/RlYoInJyZI8HVqim5qNFwQHk7SucBAPo2PKRMNPLM/4pnFszYkhJsNBu6uqWFHba1sr61lQSveQFZQkFx07BhJmhMnrLn4NLMPH/aSExR0QDbmWhwgyEapwDvXoDxdWBiXnjrV/Bdm2kYUxLwmEgAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.Vocaroo {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAw9JREFUOE9jYMABuMwYmCyTJKUCGlSnFSy02TTzeOyCiQcDViX26qVz2TAyYtWmEMwuoZ3M7V40LcB79pHkc0svpvzY8jD//87nxf+3Pyn8v/ZO8v+VNyP/2mZJumI1QCWSI8232Hjumitlfw5+qPp/9l8TCt76JP//xkdx/wsXWCzjtWFkwTCkbWFe9plPk/+ga4Txz/xt/D/hkN//gMXif21a+NbyWjIwoRiy6GDT5rP/mlFsPfyp5n/NpOj/22+0gMUXXIz/H7hC/L/bFKFbPDZMrHAD5H35OPt2J9zacDv/f3V7xv9FhwrBGubsT/1//Pjx/1GJ/mD+/nfl/1v3Ovy3KRJNQbHdOlXCvOO03/+pm1P/v3v37n90hhtYw9HPtf8Xb2v937cmHswHeWPRxYj/LvkK3igGKARwicTO07118H3V/5kbi/4vPZMJtK3s/6YH2f+Pfq1B8VbjWrdnMu5s4nAD9CNFhKwz5DTUvLl419zKvAcLtG1P84BRl/b/5M/6/6f/NPzf/qzo84yj0Uus0xUU4Zor54bm9+4OfZG02OCuoAMTb9ZkC9ull1Nvrr2Z+XvRpaRfc65H/68F+jl9svEhzyLFWoccWVc+eyTHq/twydjlKRln7jX9bNMkMJnbhoFRL1xCqmKx6/yi2fYXa/c5/e846PV/5fW0/7OPx/yfcjzop34ulxdGGvDuU8mMXaX507lBuiN6ueadmQeT/p/93vf/1O+G//sP5fw/eL3o/5JLif8zVxs+Tlir9S26UyeFQQvJGBE7FvaFZ9LfN+1y+WjbItSb3GmXvXd15v8zroH/HxgE/D+aGPx/18vi/z07PeZNPRKxe/Kh0Ae8toxscCO4zBkYXArk9C1SxJUYjBkYPPIVtbbuTftz3cz//2O9wP/75iSAXdO72/dt2HL5F6YlfBW4MiJYXMiBiW3t7azHBx+V/t89N+H/8a+1//e9K/9attDp5LQjYX8SuvVL8RoAkmxa65299Erq1FnHo0qrl7t4BddriIs4MrM3rfWcFd+pGwVSAwBZ0bKP8yrZPAAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.pastebin {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAtZJREFUOE+NU91LWmEc7sJtQew/2MUY7INg7CLY3W5GMHazyzEQo9UmfYxZTbAiVlgRqLMSZ+XnDC3z2+Y0+8JGakKZTtR0Tl2wtgtLLQh29cz3ZZ3h3Q68vOc95zzP73l+z+/U1f292O09DRxubxOH23P//1bvtQts3dPnry7LZnXJhcUl5Avf8dHtwY+fv2AyW5DOfIXFakMm+w0G4wISyRRm55TQG0y/Wzv6mikJ52Xf9TmVBoFAAD6fDwqFAqFQCJubmzCbzZiensbp6SmkUikikQi0Wi0kEgm6ewVaStDCfXPDandifn6egoaGhrCzswO1Wg2Hw4HBwUGk02kIBAL4/X4IhUJMTk6ii8dfYggy2RwymQzOz88Rj8dRLpexv7+PSqWCYDCIQqGAra0tJBIJrK2t0XdVAjNDEIl+wfj4OEqlEq2wt7dHrchkMmrBYDCAz+fTIjweD7FYrJbgIJOlgLOzM8jlcip1eXmZ2rFarVAqlRCLxcjlchCJRFRljYJYPAG32418Pg+n04lsNouVlRUcHh7C4/FQIOlHNBqlezgcJgQWxkIgGMbExASVNjY2hvX1dVo9mUzS5wREFLhcLrqTcw2B//M2RkdHodPp4PV6oVKpqH+SCom3v7+fNnF4eJiJusbCJ6+PviSyScakiaR5RIHRaKQpmEwmbAdCeD8zB6vdhebHT8SMhcUlC83bbrdTJRsbG3RwiCVCRNJJpDIoVeNNJJJQzKryV+rrmxiCtyNCCmaz2VhdXQWXy6XDpNfrodFoYLXZUTw+pk222Z3lW3ca26rgSwzBwqIZAwMDlITMAVEwNTVFR5fEJpK8Qyp1AJvDVbrTeLenCmxgfiZ22+urCtWHyu7uLp2wVCpFKx0dHaFYLOLk5KT6Y9kgk89kb95ubK0BX7A8a+1qannRLeW0daj/rU51S3tn9dypfvDw0QiLxbpX/Z7FVK7e/AEj4Wf24/2f5AAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.gist {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAk1JREFUeNqUkzuIE1EUhv955MnsbB6r4kYQLUQQFncV3SnCIqJsoWGDYOGjsIiCtY2Kla1sjLBIsFFcXJC1kaSwENQmXUQSRSUSjCQSTCbkbR4z47lXEgtBNwcu3DNzvvO8R8jlcj7LshKmaWqYQERRTAmCcEru9/sJr9er0QF92BJMAVGr1TQ6CeZAc7lcGAwGkyQAxpTLZU0eDoc8crfbRTgcRjAYRCQSYSmi1WpxY7fbjU6ng1gshmaziXg8zhnGIpVKWbquW9ls1mLZsaMoiqWq6lgnBxY55He/328Vi0XOMFZmqVMD4fF4QBAajcY48khY9JE4HA4enTGMFVkaTHmy+ZzD/5NSqYSNB484w1h55ODO3TVu4FXcWDywl24Cmp0e1WBhyuWELAtIf/qKUrWOONmev3Lpt4NRCXq1gplpBS/v3cDc0nGg9h1o1ZkfwO4Atu1B8cM7HLt8k37V/y5B2b4bJxf2Y+7oEbyJrkMvUjki0YYJ03LidfQxAt4dOHdCw5RdGZcgGobBlQtnV/BDr1GfDai7ZiHZZRi9PoY/e5SCCTUwC9gk1GmMh5YWOcNYkR4Sv1y9uAJbYB82N57h4OnDmN7phjQ0qUkWRJuB+TMaPn/5iFfvv+Ha7eucYey4iWw8q6tRJJNJ3Fp7ClUawEkViBTfkCR0YUNTVHD/4Tpm/P4/U2CeKpUKfD4fJDIMhUKEhP45St50XedZyLQY6Xw+v8AUemVb2oNqtYpCocCWKi2TLLfb7ReZTGZ+kmUi7i2VvfxLgAEAZChMriPcl+IAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.image {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAs5JREFUOE+lk/tvi1EYx98/xT8gW4REIpGFMEQWl2FiM9ZMZhm2xRAyOsmujFFmdFRHu0tWm87UypxStr69zPauN5e5rHVp3IYhbOvHy+wHEQlxkm+ek+d8nm9OznkeSfrfldmgJC7QyUlTymsJTfuTZ25z4HdWYwyLreYhtpgekGPw0+kKvo1Eo+IXRSIiEhkWZuc9tqnsJD9EqTUopCxjSGTpB0iueczSo1HyW8cpsExQ1DbxI2pt45j9cXpexul4FEd79RnZphAa/SD7WvuFtO6UItbU9LC+YQxNI2w0wwYT5LRAdhOU3oBTIXC9gXP3oUSGgz2vST3gYHejR0jptT1C332f8yrUEYHrz8CgxDnpm6DKCUfc0KnmXa/AEVPPwnDcD0cvetA2uYRk67Ive/lpjO7YBO1PPuF8Df3vwf4cbNE4tqdw7YVq8HYyHx6FvhE1hkMEg8HDUqvFkjT4aIjMqkqyqkswDSrcfBfH+Q561YLAZ/B+BLda6FXlU/cPv0AoEPhuoP1h4Av7Wbh9E/Py15NWWUjeSR3nZDfeN+N0DY9hG/7K1eGP3P0S5/EYRFUF/IOTBrUXHPm9fT6mr1xEwupkZqxbzLyiDJYUZ5NSnkdqdSHpxyrYdFpPgdmAsdfJwPMI/Yr65bf7tZLGGBQ7DNdJWFtIYvoOZmbuZE7OXpIKKli86zAr9p9gTVktWTVnKTI2U95uRWe3U2IJUDbVB5p6hVm5x5m9Vc/cnedZUNzC8lILaQesZBy6hEZ3maKzgvJWFzVWD9XtXvVGQbSWASFtMATVRlJIKbOTWtlJXaeXepuPM1f6MNp9GLt8mLvvYLmp0OhQ2Fwvk6m7xaqDTvY0eYWUVtcnllXfYlGpnfklVuraHHg8HjxuN+6fktUHlWWZPaZeUo/ILK0UKttBcbNbSB9GP0yLxWJJUxoZGUn80zD9C/vXQ/4NHY10h3M1zmQAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.InstallGentoo {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAklJREFUOE9jYEAAASBTCorZkcSRmTjVCDLziCwG4hfM3EIvGNm44oC6WNEM4WXi5FsEkmfhFX3BxMmfAJSHW9Qr55Px3aZp3X/btq3/hQydPzKysMcCFbBBDeFj4uBdqBJR/gskb1W34j+PmulLoJwbzBJJoMm7dNO7/ntMP/XfpW/v//SKvk+7tl7fvXfTpx5pCdWVSiHFv1wnHQbLi9sE/Wdk5SwBauaCGQB3gUPb5v+7Lr/8/+fvr/9fv/z+f+Pyr/9bV735l9Wy/79Dx/b/Nk0bsLoAHgbeAVHv/v77/f8f0IB7N7+cu3DuecK54z9+7lzz639e9pK/7HwSWMMA5BJwCJeXtOm/fvVj1fcfv369f//92cN7X6ZcPvf9x6Htv//vXP3r/+T245UEYgpskPTNq08LgN749/PH7/93rv/6f/rw7//nj//4f+bU0zQcUQwWBkdVbGz62y+fv3wHeeXrlz//H9798//qpY//M3KqfzGxc8djiWKwZnBUuWQ2/fr46fv/P39+///x/ff/d69//z97+s7fyMb5/+y7d2GLYriDZikFF/1qXXXj/4Pbv/8/f/jn/5MH316/eP6jVlBAaIt6VO1/jxmn/zv27P7Pp2HxEajLD90ra9Sj6/979O37X73w0n+vqOL/0lJyMVBFq0EGgDSD0oKAlu1/oHg4ugGzVCKqfouYuL1Xj676Iajr8AnJFricGqYc3Bw+Zi6BVUxsXLHAdL6QiYMPFNrwpIxHDsUhgtAMAopKDjQn4pPDF7P45QC4hSmc1eX8WgAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n\n/* General */\n:root.yotsuba .dialog {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.yotsuba .field:focus {\nborder-color: #EA8;\n}\n\n/* Header */\n:root.yotsuba #header-bar, :root.yotsuba #notifications {\nfont-size: 9pt;\ncolor: #B86;\n}\n:root.yotsuba #header-bar a, :root.yotsuba #notifications a {\ncolor: #800000;\n}\n\n/* Settings */\n:root.yotsuba #fourchanx-settings fieldset {\nborder-color: #D9BFB7;\n}\n\n/* Quote */\n:root.yotsuba .backlink.deadlink {\ncolor: #00E !important;\n}\n:root.yotsuba .inline {\nborder-color: #D9BFB7;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.yotsuba #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.yotsuba .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.yotsuba #menu {\ncolor: #800000;\n}\n:root.yotsuba .entry {\nborder-bottom: 1px solid #D9BFB7;\nfont-size: 10pt;\n}\n:root.yotsuba .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.yotsuba .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.yotsuba-b .dialog {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.yotsuba-b .field:focus {\nborder-color: #98E;\n}\n\n/* Header */\n:root.yotsuba-b #header-bar, :root.yotsuba-b #notifications {\nfont-size: 9pt;\ncolor: #89A;\n}\n:root.yotsuba-b #header-bar a, :root.yotsuba-b #notifications a {\ncolor: #34345C;\n}\n\n/* Settings */\n:root.yotsuba-b #fourchanx-settings fieldset {\nborder-color: #B7C5D9;\n}\n\n/* Quote */\n:root.yotsuba-b .backlink.deadlink {\ncolor: #34345C !important;\n}\n:root.yotsuba-b .inline {\nborder-color: #B7C5D9;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.yotsuba-b #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.yotsuba-b .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.yotsuba-b #menu {\ncolor: #000;\n}\n:root.yotsuba-b .entry {\nborder-bottom: 1px solid #B7C5D9;\nfont-size: 10pt;\n}\n:root.yotsuba-b .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.yotsuba-b .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.futaba .dialog {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.futaba .field:focus {\nborder-color: #EA8;\n}\n\n/* Header */\n:root.futaba #header-bar, :root.futaba #notifications {\nfont-size: 11pt;\ncolor: #B86;\n}\n:root.futaba #header-bar a, :root.futaba #notifications a {\ncolor: #800000;\n}\n\n/* Settings */\n:root.futaba #fourchanx-settings fieldset {\nborder-color: #D9BFB7;\n}\n\n/* Quote */\n:root.futaba .backlink.deadlink {\ncolor: #00E !important;\n}\n:root.futaba .inline {\nborder-color: #D9BFB7;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.futaba #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.futaba .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.futaba #menu {\ncolor: #800000;\n}\n:root.futaba .entry {\nborder-bottom: 1px solid #D9BFB7;\nfont-size: 12pt;\n}\n:root.futaba .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.futaba .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.burichan .dialog {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.burichan .field:focus {\nborder-color: #98E;\n}\n\n/* Header */\n:root.burichan #header-bar, :root.burichan #header-bar #notifications {\nfont-size: 11pt;\ncolor: #89A;\n}\n:root.burichan #header-bar a, :root.burichan #header-bar #notifications a {\ncolor: #34345C;\n}\n\n/* Settings */\n:root.burichan #fourchanx-settings fieldset {\nborder-color: #B7C5D9;\n}\n\n/* Quote */\n:root.burichan .backlink.deadlink {\ncolor: #34345C !important;\n}\n:root.burichan .inline {\nborder-color: #B7C5D9;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.burichan #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.burichan .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.burichan #menu {\ncolor: #000000;\n}\n:root.burichan .entry {\nborder-bottom: 1px solid #B7C5D9;\nfont-size: 12pt;\n}\n:root.burichan .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.burichan .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.tomorrow .dialog {\nbackground-color: #282A2E;\nborder-color: #111;\n}\n\n/* Header */\n:root.tomorrow #header-bar, :root.tomorrow #notifications {\nfont-size: 9pt;\ncolor: #C5C8C6;\n}\n:root.tomorrow #header-bar a, :root.tomorrow #notifications a {\ncolor: #81A2BE;\n}\n\n/* Settings */\n:root.tomorrow #fourchanx-settings fieldset {\nborder-color: #111;\n}\n\n/* Quote */\n:root.tomorrow .backlink.deadlink {\ncolor: #81A2BE !important;\n}\n:root.tomorrow .inline {\nborder-color: #111;\nbackground-color: rgba(0, 0, 0, .14);\n}\n\n/* QR */\n.tomorrow #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #282A2E;\nborder-color: #111;\n}\n:root.tomorrow .qr-preview {\nbackground-color: rgba(255, 255, 255, .15);\n}\n:root.tomorrow #qr .field {\nbackground-color: rgb(26, 27, 29);\ncolor: rgb(197,200,198);\nborder-color: rgb(40, 41, 42);\n}\n:root.tomorrow #qr .field:focus {\nborder-color: rgb(129, 162, 190) !important;\nbackground-color: rgb(30,32,36);\n}\n\n/* Menu */\n:root.tomorrow #menu {\ncolor: #C5C8C6;\n}\n:root.tomorrow .entry {\nborder-bottom: 1px solid #111;\nfont-size: 10pt;\n}\n:root.tomorrow .focused.entry {\nbackground: rgba(0, 0, 0, .33);\n}\n\n/* Watcher Favicon */\n:root.tomorrow .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.photon .dialog {\nbackground-color: #DDD;\nborder-color: #CCC;\n}\n:root.photon .field:focus {\nborder-color: #EA8;\n}\n\n/* Header */\n:root.photon #header-bar, :root.photon #notifications {\nfont-size: 9pt;\ncolor: #333;\n}\n:root.photon #header-bar a, :root.photon #notifications a {\ncolor: #FF6600;\n}\n\n/* Settings */\n:root.photon #fourchanx-settings fieldset {\nborder-color: #CCC;\n}\n\n/* Quote */\n:root.photon .backlink.deadlink {\ncolor: #F60 !important;\n}\n:root.photon .inline {\nborder-color: #CCC;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.photon #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #DDD;\nborder-color: #CCC;\n}\n:root.photon .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.photon #menu {\ncolor: #333;\n}\n:root.photon .entry {\nborder-bottom: 1px solid #CCC;\nfont-size: 10pt;\n}\n:root.photon .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.photon .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n" + css: "/* General */\n.dialog {\nbox-shadow: 0 1px 2px rgba(0, 0, 0, .15);\nborder: 1px solid;\ndisplay: block;\npadding: 0;\n}\n.captcha-img,\n.field {\nbackground-color: #FFF;\nborder: 1px solid #CCC;\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\ncolor: #333;\nfont: 13px sans-serif;\noutline: none;\ntransition: color .25s, border-color .25s;\ntransition: color .25s, border-color .25s;\n}\n.field::-moz-placeholder,\n.field:hover::-moz-placeholder {\ncolor: #AAA !important;\nfont-size: 13px !important;\nopacity: 1.0 !important;\n}\n.captch-img:hover,\n.field:hover {\nborder-color: #999;\n}\n.field:hover, .field:focus {\ncolor: #000;\n}\n.field[disabled] {\nbackground-color: #F2F2F2;\ncolor: #888;\n}\n.move {\ncursor: move;\noverflow: hidden;\n}\nlabel, .favicon {\ncursor: pointer;\n}\na[href=\"javascript:;\"] {\ntext-decoration: none;\n}\n.warning {\ncolor: red;\n}\n#boardNavDesktop {\ndisplay: none !important;\n}\na {\noutline: none !important;\n}\n\n/* 4chan style fixes */\n.opContainer, .op {\ndisplay: block !important;\noverflow: visible !important;\n}\n[hidden] {\ndisplay: none !important;\n}\n\n/* fixed, z-index */\n#overlay,\n#fourchanx-settings,\n#qp, #ihover,\n#navlinks, .fixed #header-bar,\n:root.float #updater,\n:root.float #thread-stats,\n#qr {\nposition: fixed;\n}\n#fourchanx-settings {\nz-index: 999;\n}\n#overlay {\nz-index: 900;\n}\n#notifications {\nz-index: 70;\n}\n#qp, #ihover {\nz-index: 60;\n}\n#menu {\nz-index: 50;\n}\n#navlinks, #updater, #thread-stats {\nz-index: 40;\n}\n.fixed #header-bar.autohide {\nz-index: 35;\n}\n#qr {\nz-index: 30;\n}\n#watcher {\nz-index: 8;\n}\n:root.fixed-watcher #watcher {\nz-index: 20;\n}\n.fixed #header-bar {\nz-index: 10;\n}\n/* Header */\n.fixed.top body {\npadding-top: 2em;\n}\n.fixed.bottom body {\npadding-bottom: 2em;\n}\n.fixed #header-bar {\nright: 0;\nleft: 0;\npadding: 3px 4px 4px;\n}\n.fixed.top #header-bar {\ntop: 0;\n}\n.fixed.bottom #header-bar {\nbottom: 0;\n}\n#header-bar {\nborder-width: 0;\ntransition: all .1s .05s ease-in-out;\n}\n:root.centered-links #shortcuts {\nwidth: 300px;\ntext-align: right;\n}\n:root.centered-links #header-bar {\ntext-align: center;\n}\n:root.centered-links #custom-board-list {\nposition: relative;\nleft: 150px;\n}\n.fixed.top #header-bar {\nborder-bottom-width: 1px;\n}\n.fixed.bottom #header-bar {\nbox-shadow: 0 -1px 2px rgba(0, 0, 0, .15);\nborder-top-width: 1px;\n}\n.fixed.bottom #header-bar .menu-button i {\nborder-top: none;\nborder-bottom: 6px solid;\n}\n#board-list {\ntext-align: center;\n}\n.fixed #header-bar.autohide:not(:hover) {\nbox-shadow: none;\ntransition: all .8s .6s cubic-bezier(.55, .055, .675, .19);\n}\n.fixed.top #header-bar.autohide:not(:hover) {\nmargin-bottom: -1em;\n-webkit-transform: translateY(-100%);\ntransform: translateY(-100%);\n}\n.fixed.bottom #header-bar.autohide:not(:hover) {\n-webkit-transform: translateY(100%);\ntransform: translateY(100%);\n}\n#scroll-marker {\nleft: 0;\nright: 0;\nheight: 10px;\nposition: absolute;\n}\n:root:not(.autohide) #scroll-marker {\npointer-events: none;\n}\n#header-bar #scroll-marker {\ndisplay: none;\n}\n.fixed #header-bar #scroll-marker {\ndisplay: block;\n}\n.fixed.top #header-bar #scroll-marker {\ntop: 100%;\n}\n.fixed.bottom #header-bar #scroll-marker {\nbottom: 100%;\n}\n#header-bar a:not(.entry):not(.close) {\ntext-decoration: none;\npadding: 1px;\n}\n#header-bar input {\nmargin: 0;\nvertical-align: bottom;\n}\n#shortcuts:empty {\ndisplay: none;\n}\n.brackets-wrap::before {\ncontent: \"\\00a0[\";\n}\n.brackets-wrap::after {\ncontent: \"]\\00a0\";\n}\n.disabled,\n.expand-all-shortcut {\nopacity: .45;\n}\n#shortcuts {\nfloat: right;\n}\n.shortcut {\nmargin-left: 3px;\n}\n#navbotright,\n#navtopright {\ndisplay: none;\n}\n#toggleMsgBtn {\ndisplay: none !important;\n}\n.current {\nfont-weight: bold;\n}\n/* 4chan X link brackets */\n.fourchanx-link::after {\ncontent: \"]\";\n}\n.fourchanx-link::before {\ncontent: \"[\";\n}\n/* Notifications */\n#notifications {\nposition: fixed;\ntop: 0;\nheight: 0;\ntext-align: center;\nright: 0;\nleft: 0;\ntransition: all .8s .6s cubic-bezier(.55, .055, .675, .19);\n}\n.fixed.top #header-bar #notifications {\nposition: absolute;\ntop: 100%;\n}\n.notification {\ncolor: #FFF;\nfont-weight: 700;\ntext-shadow: 0 1px 2px rgba(0, 0, 0, .5);\nbox-shadow: 0 1px 2px rgba(0, 0, 0, .15);\nborder-radius: 2px;\nmargin: 1px auto;\nwidth: 500px;\nmax-width: 100%;\nposition: relative;\ntransition: all .25s ease-in-out;\n}\n.notification.error {\nbackground-color: hsla(0, 100%, 38%, .9);\n}\n.notification.warning {\nbackground-color: hsla(36, 100%, 38%, .9);\n}\n.notification.info {\nbackground-color: hsla(200, 100%, 38%, .9);\n}\n.notification.success {\nbackground-color: hsla(104, 100%, 38%, .9);\n}\n.notification a {\ncolor: white;\n}\n.notification > .close {\npadding: 6px;\ntop: 0;\nright: 5px;\nposition: absolute;\n}\n.message {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\npadding: 6px 20px;\nmax-height: 200px;\nwidth: 100%;\noverflow: auto;\n}\n\n/* Settings */\n:root.fourchan-x body {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\n}\n#overlay {\nbackground-color: rgba(0, 0, 0, .5);\ntop: 0;\nleft: 0;\nheight: 100%;\nwidth: 100%;\n}\n#fourchanx-settings {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\nbox-shadow: 0 0 15px rgba(0, 0, 0, .15);\nheight: 600px;\nmax-height: 100%;\nwidth: 900px;\nmax-width: 100%;\nmargin: auto;\npadding: 3px;\ntop: 50%;\nleft: 50%;\n-moz-transform: translate(-50%, -50%);\n-webkit-transform: translate(-50%, -50%);\ntransform: translate(-50%, -50%);\n}\n#fourchanx-settings > nav {\npadding: 2px 2px 0;\nheight: 15px;\n}\n#fourchanx-settings > nav a {\ntext-decoration: underline;\n}\n#fourchanx-settings > nav a.close {\ntext-decoration: none;\npadding: 2px;\n}\n.section-container {\noverflow: auto;\nposition: absolute;\ntop: 2.1em;\nright: 5px;\nbottom: 5px;\nleft: 5px;\npadding-right: 5px;\n}\n.sections-list {\npadding: 0 3px;\nfloat: left;\n}\n.credits {\nfloat: right;\n}\n.tab-selected {\nfont-weight: 700;\n}\n.section-sauce ul,\n.section-advanced ul {\nlist-style: none;\nmargin: 0;\n}\n.section-sauce ul {\npadding: 8px;\n}\n.section-advanced ul {\npadding: 0px;\n}\n.section-sauce li,\n.section-advanced li {\npadding-left: 4px;\n}\n.section-main label {\ntext-decoration: underline;\n}\n.section-filter ul {\npadding: 0;\n}\n.section-filter li {\nmargin: 10px 40px;\n}\n.section-filter textarea {\nheight: 500px;\n}\n.section-sauce textarea {\nheight: 350px;\n}\n.section-advanced .field[name=\"boardnav\"] {\nwidth: 100%;\n}\n.section-advanced textarea {\nheight: 150px;\n}\n.section-advanced .archive-cell {\nmin-width: 160px;\ntext-align: center;\n}\n.section-advanced #archive-board-select {\nposition: absolute;\n}\n.section-advanced .note {\nfont-size: 0.8em;\nfont-style: italic;\nmargin-left: 10px;\n}\n.section-advanced .note code {\nfont-style: normal;\nfont-size: 11px;\n}\n.section-keybinds .field {\nfont-family: monospace;\n} \n#fourchanx-settings fieldset {\nborder: 1px solid;\nborder-radius: 3px;\n}\n#fourchanx-settings legend {\nfont-weight: 700;\n}\n#fourchanx-settings textarea {\nfont-family: monospace;\nmin-width: 100%;\nmax-width: 100%;\n}\n#fourchanx-settings code {\ncolor: #000;\nbackground-color: #FFF;\npadding: 0 2px;\n}\n.unscroll {\noverflow: hidden;\n}\n\n/* Announcement Hiding */\n:root.hide-announcement #globalMessage {\ndisplay: none;\n}\na.hide-announcement {\nfloat: left;\n}\n\n/* Unread */\n#unread-line {\nmargin: 0;\nborder-color: rgb(255,0,0);\n}\n\n/* Thread Updater */\n#updater {\nbackground: none;\nborder: none;\nbox-shadow: none;\n}\n#updater > .move {\npadding: 5px 3px 0px;\nmargin-bottom: -3px;\n}\n#updater > div:last-child {\ntext-align: center;\n}\n#updater input[type=number] {\nwidth: 4em;\n}\n:root.float #updater {\npadding: 0px 3px;\n}\n.new {\ncolor: limegreen;\n}\n#update-status.new {\nmargin-right: 5px;\n}\n#update-timer {\ncursor: pointer;\n}\n\n/* Thread Watcher */\n#watcher {\nposition: absolute;\n}\n#watcher {\npadding-bottom: 3px;\noverflow: hidden;\nwhite-space: nowrap;\nmin-width: 120px;\nmax-height: 92%;\noverflow-y: auto;\n}\n:root.fixed-watcher #watcher {\nposition: fixed;\n}\n:root:not(.fixed-watcher) #watcher:not(:hover) {\nmax-height: 210px;\noverflow-y: hidden;\n}\n#watcher > .move {\npadding-top: 3px;\n}\n#watcher > div {\nmax-width: 250px;\noverflow: hidden;\npadding-left: 3px;\npadding-right: 3px;\ntext-overflow: ellipsis;\n}\n#watcher a {\ntext-decoration: none;\n}\n#watcher .move>.close {\nposition: absolute;\nright: 0px;\ntop: 0px;\npadding: 0px 4px;\n}\n.watch-thread-link {\npadding-top: 18px;\nwidth: 18px;\nheight: 0px;\ndisplay: inline-block;\nbackground-repeat: no-repeat;\nopacity: 0.2;\nposition: relative;\ntop: 1px;\n}\n.watch-thread-link.watched {\nopacity: 1;\n}\n\n/* Thread Stats */\n#thread-stats {\nbackground: none;\nborder: none;\nbox-shadow: none;\n}\n:root.float #post-count, :root.float #file-count {\npointer-events: none;\n}\n:root.float #thread-stats {\npadding: 0px 3px;\n}\n\n/* Quote */\n.deadlink {\ntext-decoration: none !important;\n}\n.backlink.deadlink:not(.forwardlink),\n.quotelink.deadlink:not(.forwardlink) {\ntext-decoration: underline !important;\n}\n.inlined {\nopacity: .5;\n}\n#qp input, .forwarded {\ndisplay: none;\n}\n.quotelink.forwardlink,\n.backlink.forwardlink {\ntext-decoration: none;\nborder-bottom: 1px dashed;\n}\n.filtered {\ntext-decoration: underline line-through;\n}\n:root.hide-backlinks .backlink.filtered {\ndisplay: none;\n}\n.inline {\nborder: 1px solid;\ndisplay: table;\nmargin: 2px 0;\n}\n.inline .post {\nborder: 0 !important;\nbackground-color: transparent !important;\ndisplay: table !important;\nmargin: 0 !important;\npadding: 1px 2px !important;\n}\n#qp > .opContainer::after {\ncontent: '';\nclear: both;\ndisplay: table;\n}\n#qp .post {\nborder: none;\nmargin: 0;\npadding: 2px 2px 5px;\n}\n#qp img {\nmax-height: 80vh;\nmax-width: 50vw;\n}\n.qphl {\noutline: 2px solid rgba(216, 94, 49, .7);\n}\n:root.highlight-own .yourPost>.reply,\n:root.highlight-you .quotesYou>.reply {\nborder-left: 2px solid rgba(221,0,0,.5);\n}\n/* Quote Threading */\n.threadContainer {\nmargin-left: 20px;\nborder-left: 1px solid rgba(128,128,128,.3);\n}\n.threadOP {\nclear: both;\n} \n\n/* File */\n.fileText:hover .fntrunc,\n.fileText:not(:hover) .fnfull,\n.expanded-image > .post > .file > .fileThumb > img[data-md5],\n:not(.expanded-image) > .post > .file > .fileThumb > .full-image {\ndisplay: none;\n}\n.expanding {\nopacity: .5;\n}\n:root.fit-height .full-image {\nmax-height: 100vh;\n}\n:root.fit-width .full-image {\nmax-width: 100%;\n}\n:root.gecko.fit-width .full-image {\nwidth: 100%;\n}\n#ihover {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\nmax-height: 100%;\nmax-width: 75%;\npadding-bottom: 16px;\n}\n.fappeTyme .thread > .noFile,\n.fappeTyme .threadContainer > .noFile {\ndisplay: none;\n}\n\n/* Index/Reply Navigation */\n#navlinks {\nfont-size: 16px;\ntop: 25px;\nright: 10px;\n}\n\n/* Filter */\n.opContainer.filter-highlight {\nbox-shadow: inset 5px 0 rgba(255, 0, 0, .5);\n}\n.filter-highlight > .reply {\nbox-shadow: -5px 0 rgba(255, 0, 0, .5);\n}\n\n/* Spoiler text */\n:root.reveal-spoilers s {\ncolor: white !important;\n}\n\n/* Thread & Reply Hiding */\n.hide-thread-button,\n.hide-reply-button {\nfloat: left;\nmargin-right: 2px;\n}\n.stub ~ * {\ndisplay: none !important;\n}\n.stub input {\ndisplay: inline-block;\n}\n\n/* QR */\n:root.hide-original-post-form #postForm,\n:root.hide-original-post-form .postingMode,\n:root.hide-original-post-form #togglePostForm,\n#qr.autohide:not(.has-focus):not(:hover) > form,\n.postingMode ~ #qr select,\n#file-n-submit:not(.has-file) #qr-filerm {\ndisplay: none;\n}\n#qr select,\n#dump-button,\n.remove,\n.captcha-img {\ncursor: pointer;\n}\n#qr {\nz-index: 20;\nposition: fixed;\npadding: 1px;\nborder: 1px solid transparent;\nmin-width: 300px;\nborder-radius: 3px 3px 0 0;\n}\n#qrtab {\nborder-radius: 3px 3px 0 0;\n}\n#qrtab {\nmargin-bottom: 1px;\n}\n#qr .close {\nfloat: right;\npadding: 0 3px;\n}\n#qr .warning {\nmin-height: 1.6em;\nvertical-align: middle;\npadding: 0 1px;\nborder-width: 1px;\nborder-style: solid;\n}\n.qr-link-container {\ntext-align: center;\n}\n.persona {\nwidth: 248px;\nmax-width: 100%;\nmin-width: 100%;\n}\n#dump-button {\nwidth: 10%;\nmargin: 0;\nmargin-right: 4px;\nfont: 13px sans-serif;\npadding: 1px 0px 2px;\nopacity: 0.6;\n}\n.persona .field:not(#dump) {\nwidth: 95px;\nmin-width: 33.3%;\nmax-width: 33.3%;\n}\n#qr textarea.field {\nheight: 14.8em;\nmin-height: 9em;\n}\n#qr.has-captcha textarea.field {\nheight: 9em;\n}\ninput.field.tripped:not(:hover):not(:focus) {\ncolor: transparent !important;\ntext-shadow: none !important;\n}\n#qr textarea {\nresize: both;\n}\n.captcha-img {\nmargin: 0px;\ntext-align: center;\nbackground-image: #fff;\nfont-size: 0px;\nmin-height: 59px;\nmin-width: 302px;\n}\n.captcha-input {\nwidth: 100%;\nmargin: 1px 0 0;\n}\n.captcha-input.error:focus {\nborder-color: rgb(255,0,0) !important;\n}\n.field {\n-moz-box-sizing: border-box;\nmargin: 0px;\npadding: 2px 4px 3px;\n}\n#qr textarea {\nmin-width: 100%;\n}\n#qr [type='submit'] {\nwidth: 25%;\nvertical-align: top;\n}\n:root.webkit #qr [type='submit'] {\nheight: 24px;\n}\n/* Fake File Input */\n#qr-filename,\n.has-file #qr-no-file {\ndisplay: none;\n}\n#qr-no-file,\n.has-file #qr-filename {\ndisplay: inline-block;\npadding: 0px 4px;\nmargin-bottom: 2px;\noverflow: hidden;\ntext-overflow: ellipsis;\nmax-width: 88%;\n}\n#qr-no-file {\ncolor: #AAA;\n}\n#qr-filename-container {\n-moz-box-sizing: border-box;\ndisplay: inline-block;\nposition: relative;\nwidth: 100px;\nmin-width: 74.6%;\nmax-width: 74.6%;\nmargin-right: 0.4%;\nmargin-top: 1px;\noverflow: hidden;\npadding: 2px 1px 0;\nheight: 22px;\n}\n#qr-filename-container:hover {\ncursor: text;\n}\n#qr-extras-container {\nposition: absolute;\nright: 0px;\n}\n#qr-filerm {\nmargin-right: 2px;\nz-index: 2;\n}\n#file-n-submit {\nheight: 23px;\n}\n#qr input[type=file] {\nvisibility: hidden;\nposition: absolute;\n}\n/* Thread Select / Spoiler Label */\n#qr select {\nfloat: right;\n}\n#qr.has-spoiler .has-file #qr-spoiler-label {\nwidth: 6.7%;\nmin-width: 6.7%;\nmax-width: 6.7%;\ndisplay: inline-block;\ntext-align: center;\nvertical-align: top;\n}\n#qr.has-spoiler #file-n-submit:not(.has-file) #qr-spoiler-label {\ndisplay: none;\n}\n#qr.has-spoiler .has-file #qr-filename-container {\nmax-width: 67.9%;\nmin-width: 67.9%;\n}\n#qr-spoiler-label input {\nposition: relative;\ntop: 3px;\n}\n/* Dumping UI */\n.dump #dump-list-container {\ndisplay: block;\n}\n#dump-list-container {\ndisplay: none;\nposition: relative;\noverflow-y: hidden;\nmargin-top: 1px;\n}\n#dump-list {\noverflow-x: auto;\noverflow-y: hidden;\nwhite-space: nowrap;\nwidth: 248px;\nmax-width: 100%;\nmin-width: 100%;\n}\n#dump-list:hover {\noverflow-x: auto;\n}\n.qr-preview {\n-moz-box-sizing: border-box;\ncounter-increment: thumbnails;\ncursor: move;\ndisplay: inline-block;\nheight: 90px;\nwidth: 90px;\npadding: 2px;\nopacity: .5;\noverflow: hidden;\nposition: relative;\ntext-shadow: 0 1px 1px #000;\n-moz-transition: opacity .25s ease-in-out;\nvertical-align: top;\nbackground-size: cover;\n}\n.qr-preview:hover,\n.qr-preview:focus {\nopacity: .9;\n}\n.qr-preview::before {\ncontent: counter(thumbnails);\ncolor: #fff;\nposition: absolute;\ntop: 3px;\nright: 3px;\ntext-shadow: 0 0 3px #000, 0 0 8px #000;\n}\n.qr-preview#selected {\nopacity: 1;\n}\n.qr-preview.drag {\nbox-shadow: 0 0 10px rgba(0,0,0,.5);\n}\n.qr-preview.over {\nborder-color: #fff;\n}\n.qr-preview > span {\ncolor: #fff;\n}\n.remove {\nbackground: none;\ncolor: #e00;\nfont-weight: 700;\npadding: 3px;\n}\na:only-of-type > .remove {\ndisplay: none;\n}\n.remove:hover::after {\ncontent: \" Remove\";\n}\n.qr-preview > label {\nbackground: rgba(0,0,0,.5);\ncolor: #fff;\nright: 0;\nbottom: 0;\nleft: 0;\nposition: absolute;\ntext-align: center;\n}\n.qr-preview > label > input {\nmargin: 0;\n}\n#add-post {\ncursor: pointer;\nfont-size: 2em;\nposition: absolute;\ntop: 50%;\nright: 10px;\n-moz-transform: translateY(-50%);\n}\n.textarea {\nposition: relative;\n}\n:root.webkit .textarea {\nmargin-bottom: -2px;\n}\n#char-count {\ncolor: #000;\nbackground: hsla(0, 0%, 100%, .5);\nfont-size: 8pt;\nposition: absolute;\nbottom: 1px;\nright: 1px;\npointer-events: none;\n}\n\n/* Menu */\n.menu-button {\ndisplay: inline-block;\nposition: relative;\ncursor: pointer;\n}\n.menu-button i {\nborder-top: 6px solid;\nborder-right: 4px solid transparent;\nborder-left: 4px solid transparent;\ndisplay: inline-block;\nmargin: 2px;\nvertical-align: middle;\n}\n#menu {\nposition: fixed;\noutline: none;\n}\n.entry {\nborder-bottom: 1px solid rgba(0,0,0,.25);\ncursor: pointer;\ndisplay: block;\noutline: none;\npadding: 3px 7px;\nposition: relative;\ntext-decoration: none;\nwhite-space: nowrap;\n}\n.left>.entry.has-submenu {\npadding-right: 17px !important;\n}\n.entry:last-child {\nborder-bottom: 0;\n}\n.has-submenu::after {\ncontent: \"\";\nborder-left: .5em solid;\nborder-top: .3em solid transparent;\nborder-bottom: .3em solid transparent;\ndisplay: inline-block;\nmargin: .3em;\nposition: absolute;\nright: 3px;\n}\n.left .has-submenu::after {\nborder-left: 0;\nborder-right: .5em solid;\n}\n.submenu {\ndisplay: none;\nposition: absolute;\nleft: 100%;\ntop: -1px;\n}\n.focused .submenu {\ndisplay: block;\n}\n.imp-exp-result {\nposition: absolute;\ntext-align: center;\nmargin: auto;\nright: 0px;\nleft: 0px;\nwidth: 200px;\n}\n.export, .import {\ncursor: pointer;\ntext-decoration: none !important;\n}\n/* Link Title Favicons */\n.linkify.YouTube {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAYAAABr5z2BAAABIklEQVQoz53LvUrDUBjG8bOoOammSf1IoBSvoCB4JeIqOHgBLt6AIMRBBQelWurQ2kERnMRBsBUcIp5FJSBI5oQsJVkkUHh8W0o5nhaFHvjBgef/Mq+Q46RJBMkI/vE+aOus956tnEswIZe1LV0QyJ5sE2GzgZfVMtRNIdiDpccEssdlB1mW4bvTwdvWJtRdErM7U+8S/FJykCRJX5qm+KpVce8UMNLRLbulz4iSjTAMh6Iowsd5BeNadp3nUF0VlxAEwZBotXC0Usa4ll3meZdA1iguwvf9vpvDA2wvmKgYGtSud8suDB4TyGr2PF49D/vra9jRZ1BVdknMzgwuCGSnZEObwu6sBnVTCHZiaC7BhFx2PKdxUidiAH/4lLo9Mv0DELVs9qsOHXwAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.Vimeo {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAASJJREFUOE9jYAAC7ln7/pODQXrBmq333PvPu/YaSRikB6QXbACpmmHqsRoAMll7+20UQ0H8tmuv/pdffPFfZtNNuByGASBFIPDh5x+4IV6HHoDFYGDJgw+YBoBMBUkgA5BtIKduuvvy//svX+FSB+88wTTAc+/t/83bj/0HScLA5BPXwc7lKJ36f+L6XXDxhUfOYxrAPWUnWKFp9UQUm3iWQxSDXAEDSX3zcIcB96wD/x+8eA1XDNKMHAYg20GW4Y0FkCIYAAUqzEBQOIBciRzlWKMxZelOlMCEcVxq+jHSC1YDJPs3YBgA8jey0/F6ARRwsFAHORukmat9NdbUijMpg/wKcrJodDFOzSBXwA3Alh9AToZFI7a8Asu98BxJbnYGAJb5vYLDANzSAAAAAElFTkSuQmCC') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.SoundCloud {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABsklEQVQ4y5WTy2pUQRCGv2rbzDjJeAlIBmOyipGIIJqFEBDElwh4yULGeRFXPoEIBl/AvQ/gC2RnxCAoxijiwks852S6+3dxzslcHJCpTXVX11/Xv0097gLPgVNMJxnQNfX4zsqleWbnpoMf/oa9d988MM9MC/rp+E0a+A0dsVobMNMCOO8B6McRoABJI+A6gJmN3D2A8jgEBCEkSEMBrcrsDAzDWWn3AjgKFaDMmgRqniGFgsaDp1jrLOngDf1XT1D+A1dFc4MKAkkiCVKjjVu7g9+4Rzx4i1u6hjXbuMWr0O5QPNvCu7IaCZwEKQukLGDrm5x8uI0tr6MkiGlkiv7yLfzN+6S5i6QsIMABkEfcxhbWWYMkVAOjxvYAjc3HNHrbKI9VBQBFwF25XQKSBjqIf1YBuAurEMrczgDygD6/x2LCpFLXLUyQ+PoldphhBhYfIX09XU1+Flaukz7uYqs3SHs7cG4BmTsmkBUF9mmXEwa28BNLPaQPLepuNcbGSWQquQC2/Kdcox1FUGkcB0ykck1nA2+wTzMs8stGnP4rbWGw74EuS/GFQWfK7/wF6P4F7fzIAYkdmdEAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.audio {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAitJREFUOE9jYCAWKJWwavr0KyXWb/FIbDtUFFyzJx6nVofE2Xo5nXsj0rqPNSR0nVkR2Hjmgmfd+U9Otdf+m5Vf/6+SfeU/R9ChVVgNYDRtlfJuuPA/rPfe/4QpD/6nznj0P27Kw/9unff/69Xf+69c/+C/SO7N/0z+OAxgMmmRCe++/r9i3ev/KWvf/vdY8PK/bt/9/wrNV3/IN5y/IVt1YqNg4pGTTP4HsbuA2bhZ2qvpyn+xjIObxAp3VwqlrgngLFyryVy5nhPmZJHANS2cwYexG8BmVC/pWn3hP4NZlzWuQDJI3dIiFnUUuwEsQAOcq87jNcC7fHeLUtJxHF4AGmBWeAavAWH1+1rUUk7giAWjOknllON4DXAs2NEiG4/DBQxAF/CFHfrPYI4jDFSLuJVjNrUJhB/B7gIGo1pJRt99GAZYJK7wLJ1z7Xzl4vu/7aqv/GRBj0bjqAX2qb0nJ7mXH17C4HcUxQA+hymWtSue/C5a9up/9Ozn/7Vr7v1nRY7GqMb91T3b3v6vWvPmf/S0p/9ZQk+DDLCBRSOz06Jqk+o7/21nvfqvsebDf7kZL/5zBaxphkezd+OFn7HzXvz3Wvjmv9a8N//5Ek//ZTBpVYUrMG2X5wjcdl68+uI/wa5Lr3hSNjczGFeywOVZ/bbcVGp//F9izfv/Ql03f3P4LC/HSEQquYwMFnUCDJ7dzBhyjGZNQpye89M5gpfnMvtNUyE2h4PUAQBovvT7lyNljwAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.LiveLeak {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAydJREFUOE9Nk1tIk2EYx79NyUNqTk0o6KYrnZeChodLDxfeZpCbJk4RXU5Nm7tYRYhiYXbQlaeGutyW2gxtpB1RIyKDEjKwA6Ti2dR5KNDn+fq/S6TBj/f93r3P732e53s/qfnkSdej4GB2SBLbwf+jmB+gUMgOheLg/z7EdCUnO6Ref392SpK8Hyh3I+gBwBo7lUp2xcbyQEoKD6alyQOpqd754/h4FjJXZCRJTl9ftmEzoK5/wdQJxPgkLY2WV1dpc2uLtnZ2eHNnhza3t2nd46GhjAzuValY6jx0iIfS03msoIDuQ9COQCtoUSjohU5HuwgaN5loeXycd3d3aW9vzwvW2K5SkdTi58fvzGb+3tdHFggA3QONEAzn59PvjQ1yqNX0zenkvX0B4ffWaGRraChJd/385JGqKvlzTw/fRqOaIGkEd1DjU52O/3g83BkTw5MOh7yJuUCUM2o0yi2hoSw1IIOhykr+YLNRHYKu4XQvyKA/N5c8yMCCDD7Z7bz26xcJ1rH2rKKCG0UJdRAMlJbyG6uVrkJQjWAB5tSbk0Nr2HwDgvcQiIYur6zQyvo6ucvLueHIEZKuQPBQr+dXra1kRuqXEOwFArtWSytra1QdFUVjNhvPLS3R3OIiLUDUD0F1WBhJJtwDW2Ehu5uaqBICI4IFlRB0QLCEzaboaHrd0cHzCBYsIIuesjK+LAQXkEFrXh676uupGCWcR6AeghLQptGQONUAwfOuLp6Zn6eZuTmaXVig7pISrhI90ENgQbdHhoep32JhFzLpu3WLio8epUYIfs7OUjF6UKJW88XERLqYkEBNej11oG8XhCAvMFAuOn5cNiclsTkhQTbhmpri4lgbEMANWi1DwC/xit3t7bK7rY0Fo4OD3G4wyEURESzloAdnceezlErK8vH5N4KzPj50PTOTfkxP0+THj/RlYoInJyZI8HVqim5qNFwQHk7SucBAPo2PKRMNPLM/4pnFszYkhJsNBu6uqWFHba1sr61lQSveQFZQkFx07BhJmhMnrLn4NLMPH/aSExR0QDbmWhwgyEapwDvXoDxdWBiXnjrV/Bdm2kYUxLwmEgAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.Vocaroo {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAw9JREFUOE9jYMABuMwYmCyTJKUCGlSnFSy02TTzeOyCiQcDViX26qVz2TAyYtWmEMwuoZ3M7V40LcB79pHkc0svpvzY8jD//87nxf+3Pyn8v/ZO8v+VNyP/2mZJumI1QCWSI8232Hjumitlfw5+qPp/9l8TCt76JP//xkdx/wsXWCzjtWFkwTCkbWFe9plPk/+ga4Txz/xt/D/hkN//gMXif21a+NbyWjIwoRiy6GDT5rP/mlFsPfyp5n/NpOj/22+0gMUXXIz/H7hC/L/bFKFbPDZMrHAD5H35OPt2J9zacDv/f3V7xv9FhwrBGubsT/1//Pjx/1GJ/mD+/nfl/1v3Ovy3KRJNQbHdOlXCvOO03/+pm1P/v3v37n90hhtYw9HPtf8Xb2v937cmHswHeWPRxYj/LvkK3igGKARwicTO07118H3V/5kbi/4vPZMJtK3s/6YH2f+Pfq1B8VbjWrdnMu5s4nAD9CNFhKwz5DTUvLl419zKvAcLtG1P84BRl/b/5M/6/6f/NPzf/qzo84yj0Uus0xUU4Zor54bm9+4OfZG02OCuoAMTb9ZkC9ull1Nvrr2Z+XvRpaRfc65H/68F+jl9svEhzyLFWoccWVc+eyTHq/twydjlKRln7jX9bNMkMJnbhoFRL1xCqmKx6/yi2fYXa/c5/e846PV/5fW0/7OPx/yfcjzop34ulxdGGvDuU8mMXaX507lBuiN6ueadmQeT/p/93vf/1O+G//sP5fw/eL3o/5JLif8zVxs+Tlir9S26UyeFQQvJGBE7FvaFZ9LfN+1y+WjbItSb3GmXvXd15v8zroH/HxgE/D+aGPx/18vi/z07PeZNPRKxe/Kh0Ae8toxscCO4zBkYXArk9C1SxJUYjBkYPPIVtbbuTftz3cz//2O9wP/75iSAXdO72/dt2HL5F6YlfBW4MiJYXMiBiW3t7azHBx+V/t89N+H/8a+1//e9K/9attDp5LQjYX8SuvVL8RoAkmxa65299Erq1FnHo0qrl7t4BddriIs4MrM3rfWcFd+pGwVSAwBZ0bKP8yrZPAAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.pastebin {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAtZJREFUOE+NU91LWmEc7sJtQew/2MUY7INg7CLY3W5GMHazyzEQo9UmfYxZTbAiVlgRqLMSZ+XnDC3z2+Y0+8JGakKZTtR0Tl2wtgtLLQh29cz3ZZ3h3Q68vOc95zzP73l+z+/U1f292O09DRxubxOH23P//1bvtQts3dPnry7LZnXJhcUl5Avf8dHtwY+fv2AyW5DOfIXFakMm+w0G4wISyRRm55TQG0y/Wzv6mikJ52Xf9TmVBoFAAD6fDwqFAqFQCJubmzCbzZiensbp6SmkUikikQi0Wi0kEgm6ewVaStDCfXPDandifn6egoaGhrCzswO1Wg2Hw4HBwUGk02kIBAL4/X4IhUJMTk6ii8dfYggy2RwymQzOz88Rj8dRLpexv7+PSqWCYDCIQqGAra0tJBIJrK2t0XdVAjNDEIl+wfj4OEqlEq2wt7dHrchkMmrBYDCAz+fTIjweD7FYrJbgIJOlgLOzM8jlcip1eXmZ2rFarVAqlRCLxcjlchCJRFRljYJYPAG32418Pg+n04lsNouVlRUcHh7C4/FQIOlHNBqlezgcJgQWxkIgGMbExASVNjY2hvX1dVo9mUzS5wREFLhcLrqTcw2B//M2RkdHodPp4PV6oVKpqH+SCom3v7+fNnF4eJiJusbCJ6+PviSyScakiaR5RIHRaKQpmEwmbAdCeD8zB6vdhebHT8SMhcUlC83bbrdTJRsbG3RwiCVCRNJJpDIoVeNNJJJQzKryV+rrmxiCtyNCCmaz2VhdXQWXy6XDpNfrodFoYLXZUTw+pk222Z3lW3ca26rgSwzBwqIZAwMDlITMAVEwNTVFR5fEJpK8Qyp1AJvDVbrTeLenCmxgfiZ22+urCtWHyu7uLp2wVCpFKx0dHaFYLOLk5KT6Y9kgk89kb95ubK0BX7A8a+1qannRLeW0daj/rU51S3tn9dypfvDw0QiLxbpX/Z7FVK7e/AEj4Wf24/2f5AAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.gist {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAk1JREFUeNqUkzuIE1EUhv955MnsbB6r4kYQLUQQFncV3SnCIqJsoWGDYOGjsIiCtY2Kla1sjLBIsFFcXJC1kaSwENQmXUQSRSUSjCQSTCbkbR4z47lXEgtBNwcu3DNzvvO8R8jlcj7LshKmaWqYQERRTAmCcEru9/sJr9er0QF92BJMAVGr1TQ6CeZAc7lcGAwGkyQAxpTLZU0eDoc8crfbRTgcRjAYRCQSYSmi1WpxY7fbjU6ng1gshmaziXg8zhnGIpVKWbquW9ls1mLZsaMoiqWq6lgnBxY55He/328Vi0XOMFZmqVMD4fF4QBAajcY48khY9JE4HA4enTGMFVkaTHmy+ZzD/5NSqYSNB484w1h55ODO3TVu4FXcWDywl24Cmp0e1WBhyuWELAtIf/qKUrWOONmev3Lpt4NRCXq1gplpBS/v3cDc0nGg9h1o1ZkfwO4Atu1B8cM7HLt8k37V/y5B2b4bJxf2Y+7oEbyJrkMvUjki0YYJ03LidfQxAt4dOHdCw5RdGZcgGobBlQtnV/BDr1GfDai7ZiHZZRi9PoY/e5SCCTUwC9gk1GmMh5YWOcNYkR4Sv1y9uAJbYB82N57h4OnDmN7phjQ0qUkWRJuB+TMaPn/5iFfvv+Ha7eucYey4iWw8q6tRJJNJ3Fp7ClUawEkViBTfkCR0YUNTVHD/4Tpm/P4/U2CeKpUKfD4fJDIMhUKEhP45St50XedZyLQY6Xw+v8AUemVb2oNqtYpCocCWKi2TLLfb7ReZTGZ+kmUi7i2VvfxLgAEAZChMriPcl+IAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.image {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAs5JREFUOE+lk/tvi1EYx98/xT8gW4REIpGFMEQWl2FiM9ZMZhm2xRAyOsmujFFmdFRHu0tWm87UypxStr69zPauN5e5rHVp3IYhbOvHy+wHEQlxkm+ek+d8nm9OznkeSfrfldmgJC7QyUlTymsJTfuTZ25z4HdWYwyLreYhtpgekGPw0+kKvo1Eo+IXRSIiEhkWZuc9tqnsJD9EqTUopCxjSGTpB0iueczSo1HyW8cpsExQ1DbxI2pt45j9cXpexul4FEd79RnZphAa/SD7WvuFtO6UItbU9LC+YQxNI2w0wwYT5LRAdhOU3oBTIXC9gXP3oUSGgz2vST3gYHejR0jptT1C332f8yrUEYHrz8CgxDnpm6DKCUfc0KnmXa/AEVPPwnDcD0cvetA2uYRk67Ive/lpjO7YBO1PPuF8Df3vwf4cbNE4tqdw7YVq8HYyHx6FvhE1hkMEg8HDUqvFkjT4aIjMqkqyqkswDSrcfBfH+Q561YLAZ/B+BLda6FXlU/cPv0AoEPhuoP1h4Av7Wbh9E/Py15NWWUjeSR3nZDfeN+N0DY9hG/7K1eGP3P0S5/EYRFUF/IOTBrUXHPm9fT6mr1xEwupkZqxbzLyiDJYUZ5NSnkdqdSHpxyrYdFpPgdmAsdfJwPMI/Yr65bf7tZLGGBQ7DNdJWFtIYvoOZmbuZE7OXpIKKli86zAr9p9gTVktWTVnKTI2U95uRWe3U2IJUDbVB5p6hVm5x5m9Vc/cnedZUNzC8lILaQesZBy6hEZ3maKzgvJWFzVWD9XtXvVGQbSWASFtMATVRlJIKbOTWtlJXaeXepuPM1f6MNp9GLt8mLvvYLmp0OhQ2Fwvk6m7xaqDTvY0eYWUVtcnllXfYlGpnfklVuraHHg8HjxuN+6fktUHlWWZPaZeUo/ILK0UKttBcbNbSB9GP0yLxWJJUxoZGUn80zD9C/vXQ/4NHY10h3M1zmQAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.InstallGentoo {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAklJREFUOE9jYEAAASBTCorZkcSRmTjVCDLziCwG4hfM3EIvGNm44oC6WNEM4WXi5FsEkmfhFX3BxMmfAJSHW9Qr55Px3aZp3X/btq3/hQydPzKysMcCFbBBDeFj4uBdqBJR/gskb1W34j+PmulLoJwbzBJJoMm7dNO7/ntMP/XfpW/v//SKvk+7tl7fvXfTpx5pCdWVSiHFv1wnHQbLi9sE/Wdk5SwBauaCGQB3gUPb5v+7Lr/8/+fvr/9fv/z+f+Pyr/9bV735l9Wy/79Dx/b/Nk0bsLoAHgbeAVHv/v77/f8f0IB7N7+cu3DuecK54z9+7lzz639e9pK/7HwSWMMA5BJwCJeXtOm/fvVj1fcfv369f//92cN7X6ZcPvf9x6Htv//vXP3r/+T245UEYgpskPTNq08LgN749/PH7/93rv/6f/rw7//nj//4f+bU0zQcUQwWBkdVbGz62y+fv3wHeeXrlz//H9798//qpY//M3KqfzGxc8djiWKwZnBUuWQ2/fr46fv/P39+///x/ff/d69//z97+s7fyMb5/+y7d2GLYriDZikFF/1qXXXj/4Pbv/8/f/jn/5MH316/eP6jVlBAaIt6VO1/jxmn/zv27P7Pp2HxEajLD90ra9Sj6/979O37X73w0n+vqOL/0lJyMVBFq0EGgDSD0oKAlu1/oHg4ugGzVCKqfouYuL1Xj676Iajr8AnJFricGqYc3Bw+Zi6BVUxsXLHAdL6QiYMPFNrwpIxHDsUhgtAMAopKDjQn4pPDF7P45QC4hSmc1eX8WgAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n\n/* General */\n:root.yotsuba .dialog {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.yotsuba .field:focus {\nborder-color: #EA8;\n}\n\n/* Header */\n:root.yotsuba #header-bar, :root.yotsuba #notifications {\nfont-size: 9pt;\ncolor: #B86;\n}\n:root.yotsuba #header-bar a, :root.yotsuba #notifications a {\ncolor: #800000;\n}\n\n/* Settings */\n:root.yotsuba #fourchanx-settings fieldset {\nborder-color: #D9BFB7;\n}\n\n/* Quote */\n:root.yotsuba .backlink.deadlink {\ncolor: #00E !important;\n}\n:root.yotsuba .inline {\nborder-color: #D9BFB7;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.yotsuba #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.yotsuba .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.yotsuba #menu {\ncolor: #800000;\n}\n:root.yotsuba .entry {\nborder-bottom: 1px solid #D9BFB7;\nfont-size: 10pt;\n}\n:root.yotsuba .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.yotsuba .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.yotsuba-b .dialog {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.yotsuba-b .field:focus {\nborder-color: #98E;\n}\n\n/* Header */\n:root.yotsuba-b #header-bar, :root.yotsuba-b #notifications {\nfont-size: 9pt;\ncolor: #89A;\n}\n:root.yotsuba-b #header-bar a, :root.yotsuba-b #notifications a {\ncolor: #34345C;\n}\n\n/* Settings */\n:root.yotsuba-b #fourchanx-settings fieldset {\nborder-color: #B7C5D9;\n}\n\n/* Quote */\n:root.yotsuba-b .backlink.deadlink {\ncolor: #34345C !important;\n}\n:root.yotsuba-b .inline {\nborder-color: #B7C5D9;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.yotsuba-b #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.yotsuba-b .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.yotsuba-b #menu {\ncolor: #000;\n}\n:root.yotsuba-b .entry {\nborder-bottom: 1px solid #B7C5D9;\nfont-size: 10pt;\n}\n:root.yotsuba-b .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.yotsuba-b .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.futaba .dialog {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.futaba .field:focus {\nborder-color: #EA8;\n}\n\n/* Header */\n:root.futaba #header-bar, :root.futaba #notifications {\nfont-size: 11pt;\ncolor: #B86;\n}\n:root.futaba #header-bar a, :root.futaba #notifications a {\ncolor: #800000;\n}\n\n/* Settings */\n:root.futaba #fourchanx-settings fieldset {\nborder-color: #D9BFB7;\n}\n\n/* Quote */\n:root.futaba .backlink.deadlink {\ncolor: #00E !important;\n}\n:root.futaba .inline {\nborder-color: #D9BFB7;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.futaba #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.futaba .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.futaba #menu {\ncolor: #800000;\n}\n:root.futaba .entry {\nborder-bottom: 1px solid #D9BFB7;\nfont-size: 12pt;\n}\n:root.futaba .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.futaba .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.burichan .dialog {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.burichan .field:focus {\nborder-color: #98E;\n}\n\n/* Header */\n:root.burichan #header-bar, :root.burichan #header-bar #notifications {\nfont-size: 11pt;\ncolor: #89A;\n}\n:root.burichan #header-bar a, :root.burichan #header-bar #notifications a {\ncolor: #34345C;\n}\n\n/* Settings */\n:root.burichan #fourchanx-settings fieldset {\nborder-color: #B7C5D9;\n}\n\n/* Quote */\n:root.burichan .backlink.deadlink {\ncolor: #34345C !important;\n}\n:root.burichan .inline {\nborder-color: #B7C5D9;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.burichan #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.burichan .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.burichan #menu {\ncolor: #000000;\n}\n:root.burichan .entry {\nborder-bottom: 1px solid #B7C5D9;\nfont-size: 12pt;\n}\n:root.burichan .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.burichan .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.tomorrow .dialog {\nbackground-color: #282A2E;\nborder-color: #111;\n}\n\n/* Header */\n:root.tomorrow #header-bar, :root.tomorrow #notifications {\nfont-size: 9pt;\ncolor: #C5C8C6;\n}\n:root.tomorrow #header-bar a, :root.tomorrow #notifications a {\ncolor: #81A2BE;\n}\n\n/* Settings */\n:root.tomorrow #fourchanx-settings fieldset {\nborder-color: #111;\n}\n\n/* Quote */\n:root.tomorrow .backlink.deadlink {\ncolor: #81A2BE !important;\n}\n:root.tomorrow .inline {\nborder-color: #111;\nbackground-color: rgba(0, 0, 0, .14);\n}\n\n/* QR */\n.tomorrow #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #282A2E;\nborder-color: #111;\n}\n:root.tomorrow .qr-preview {\nbackground-color: rgba(255, 255, 255, .15);\n}\n:root.tomorrow #qr .field {\nbackground-color: rgb(26, 27, 29);\ncolor: rgb(197,200,198);\nborder-color: rgb(40, 41, 42);\n}\n:root.tomorrow #qr .field:focus {\nborder-color: rgb(129, 162, 190) !important;\nbackground-color: rgb(30,32,36);\n}\n\n/* Menu */\n:root.tomorrow #menu {\ncolor: #C5C8C6;\n}\n:root.tomorrow .entry {\nborder-bottom: 1px solid #111;\nfont-size: 10pt;\n}\n:root.tomorrow .focused.entry {\nbackground: rgba(0, 0, 0, .33);\n}\n\n/* Watcher Favicon */\n:root.tomorrow .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.photon .dialog {\nbackground-color: #DDD;\nborder-color: #CCC;\n}\n:root.photon .field:focus {\nborder-color: #EA8;\n}\n\n/* Header */\n:root.photon #header-bar, :root.photon #notifications {\nfont-size: 9pt;\ncolor: #333;\n}\n:root.photon #header-bar a, :root.photon #notifications a {\ncolor: #FF6600;\n}\n\n/* Settings */\n:root.photon #fourchanx-settings fieldset {\nborder-color: #CCC;\n}\n\n/* Quote */\n:root.photon .backlink.deadlink {\ncolor: #F60 !important;\n}\n:root.photon .inline {\nborder-color: #CCC;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.photon #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #DDD;\nborder-color: #CCC;\n}\n:root.photon .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.photon #menu {\ncolor: #333;\n}\n:root.photon .entry {\nborder-bottom: 1px solid #CCC;\nfont-size: 10pt;\n}\n:root.photon .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.photon .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n" }; Main.init(); diff --git a/builds/appchan-x.user.js b/builds/appchan-x.user.js index 52da11896..a5b5d4fac 100644 --- a/builds/appchan-x.user.js +++ b/builds/appchan-x.user.js @@ -18,7 +18,7 @@ // ==/UserScript== /* -* appchan x - Version 2.1.3 - 2013-07-07 +* appchan x - Version 2.1.3 - 2013-07-21 * * Licensed under the MIT license. * https://github.com/zixaphir/appchan-x/blob/master/LICENSE @@ -2765,9 +2765,9 @@ }; $.ready = function(fc) { - var cb, _ref; + var cb; - if ((_ref = d.readyState) === 'interactive' || _ref === 'complete') { + if (d.readyState !== 'loading') { $.queueTask(fc); return; } @@ -3033,9 +3033,9 @@ }; $.open = function(URL) { - return GM_openInTab(($.el('a', { - href: URL - })).href); + return $.open = function(URL) { + return GM_openInTab(URL); + }; }; $.debounce = function(wait, fn) { @@ -3113,21 +3113,6 @@ return (value < min ? min : value > max ? max : value); }; - $.syncing = {}; - - $.sync = (function() { - window.addEventListener('storage', function(e) { - var cb; - - if (cb = $.syncing[e.key]) { - return cb(JSON.parse(e.newValue)); - } - }, false); - return function(key, cb) { - return $.syncing[g.NAMESPACE + key] = cb; - }; - })(); - $.item = function(key, val) { var item; @@ -3136,6 +3121,21 @@ return item; }; + $.syncing = {}; + + $.sync = (function() { + $.on(window, 'storage', function(e) { + var cb; + + if (cb = $.syncing[e.key]) { + return cb(JSON.parse(e.newValue)); + } + }); + return function(key, cb) { + return $.syncing[g.NAMESPACE + key] = cb; + }; + })(); + $["delete"] = function(keys) { var key, _i, _len; @@ -3225,8 +3225,8 @@ }; function Thread(ID, board) { + this.ID = ID; this.board = board; - this.ID = +ID; this.fullID = "" + this.board + "." + this.ID; this.posts = {}; g.threads[this.fullID] = board.threads[this] = this; @@ -3249,7 +3249,7 @@ }; function Post(root, thread, board, that) { - var alt, anchor, capcode, date, email, file, fileInfo, flag, info, name, post, size, subject, thumb, tripcode, uniqueID, unit; + var capcode, date, email, flag, info, name, post, subject, tripcode, uniqueID; this.thread = thread; this.board = board; @@ -3268,6 +3268,11 @@ quotelinks: [], backlinks: info.getElementsByClassName('backlink') }; + if (!(this.isReply = $.hasClass(post, 'reply'))) { + this.thread.OP = this; + this.thread.isSticky = !!$('.stickyIcon', info); + this.thread.isClosed = !!$('.closedIcon', info); + } this.info = {}; if (subject = $('.subject', info)) { this.nodes.subject = subject; @@ -3293,7 +3298,7 @@ this.nodes.capcode = capcode; this.info.capcode = capcode.textContent.replace('## ', ''); } - if (flag = $('.countryFlag', info)) { + if (flag = $('.flag, .countryFlag', info)) { this.nodes.flag = flag; this.info.flag = flag.title; } @@ -3308,36 +3313,7 @@ }); this.parseComment(); this.parseQuotes(); - if ((file = $('.file', post)) && (thumb = $('img[data-md5]', file))) { - alt = thumb.alt; - anchor = thumb.parentNode; - fileInfo = file.firstElementChild; - this.file = { - info: fileInfo, - text: fileInfo.firstElementChild, - thumb: thumb, - URL: anchor.href, - size: alt.match(/[\d.]+\s\w+/)[0], - MD5: thumb.dataset.md5, - isSpoiler: $.hasClass(anchor, 'imgspoiler') - }; - size = +this.file.size.match(/[\d.]+/)[0]; - unit = ['B', 'KB', 'MB', 'GB'].indexOf(this.file.size.match(/\w+$/)[0]); - while (unit-- > 0) { - size *= 1024; - } - this.file.sizeInBytes = size; - this.file.thumbURL = that.isArchived ? thumb.src : "" + location.protocol + "//thumbs.4chan.org/" + board + "/thumb/" + (this.file.URL.match(/(\d+)\./)[1]) + "s.jpg"; - this.file.name = $('span[title]', fileInfo).title.replace(/%22/g, '"'); - if (this.file.isImage = /(jpg|png|gif)$/i.test(this.file.name)) { - this.file.dimensions = this.file.text.textContent.match(/\d+x\d+/)[0]; - } - } - if (!(this.isReply = $.hasClass(post, 'reply'))) { - this.thread.OP = this; - this.thread.isSticky = !!$('.stickyIcon', this.nodes.info); - this.thread.isClosed = !!$('.closedIcon', this.nodes.info); - } + this.parseFile(that); this.clones = []; g.posts[this.fullID] = thread.posts[this] = board.posts[this] = this; if (that.isArchived) { @@ -3346,7 +3322,7 @@ } Post.prototype.parseComment = function() { - var bq, data, i, node, nodes, text, _i, _len, _ref; + var bq, i, node, nodes, text, _i, _len, _ref; bq = this.nodes.comment.cloneNode(true); _ref = $$('.abbr, .capcodeReplies, .exif, b', bq); @@ -3358,7 +3334,7 @@ nodes = d.evaluate('.//br|.//text()', bq, null, 7, null); i = 0; while (i < nodes.snapshotLength) { - text.push((data = nodes.snapshotItem(i++).data) ? data : '\n'); + text.push(nodes.snapshotItem(i++).data || '\n'); } return this.info.comment = text.join('').trim().replace(/\s+$/gm, ''); }; @@ -3382,7 +3358,7 @@ continue; } this.nodes.quotelinks.push(quotelink); - if (quotelink.parentNode.parentNode.className === 'capcodeReplies') { + if (!this.isReply && $.hasClass(quotelink.parentNode.parentNode, 'capcodeReplies')) { continue; } quotes["" + (pathname.split('/')[1]) + "." + hash.slice(2)] = true; @@ -3393,6 +3369,37 @@ return this.quotes = Object.keys(quotes); }; + Post.prototype.parseFile = function(that) { + var alt, anchor, fileEl, fileInfo, size, thumb, unit; + + if (!((fileEl = $('.file', this.nodes.post)) && (thumb = $('img[data-md5]', fileEl)))) { + return; + } + alt = thumb.alt; + anchor = thumb.parentNode; + fileInfo = fileEl.firstElementChild; + this.file = { + info: fileInfo, + text: fileInfo.firstElementChild, + thumb: thumb, + URL: anchor.href, + size: alt.match(/[\d.]+\s\w+/)[0], + MD5: thumb.dataset.md5, + isSpoiler: $.hasClass(anchor, 'imgspoiler') + }; + size = +this.file.size.match(/[\d.]+/)[0]; + unit = ['B', 'KB', 'MB', 'GB'].indexOf(this.file.size.match(/\w+$/)[0]); + while (unit-- > 0) { + size *= 1024; + } + this.file.sizeInBytes = size; + this.file.thumbURL = that.isArchived ? thumb.src : "" + location.protocol + "//thumbs.4chan.org/" + this.board + "/thumb/" + (this.file.URL.match(/(\d+)\./)[1]) + "s.jpg"; + this.file.name = $('span[title]', fileInfo).title; + if (this.file.isImage = /(jpg|png|gif)$/i.test(this.file.name)) { + return this.file.dimensions = this.file.text.textContent.match(/\d+x\d+/)[0]; + } + }; + Post.prototype.kill = function(file, now) { var clone, quotelink, strong, _i, _j, _len, _len1, _ref, _ref1; @@ -3483,7 +3490,7 @@ _ref = this.clones.slice(index); for (_i = 0, _len = _ref.length; _i < _len; _i++) { clone = _ref[_i]; - clone.nodes.root.setAttribute('data-clone', index++); + clone.nodes.root.dataset.clone = index++; } }; @@ -3495,7 +3502,7 @@ __extends(Clone, _super); function Clone(origin, context) { - var file, index, info, inline, inlined, key, nodes, post, root, val, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3; + var file, info, inline, inlined, key, nodes, post, root, val, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3; this.origin = origin; this.context = context; @@ -3571,8 +3578,7 @@ this.isDead = true; } this.isClone = true; - index = origin.clones.push(this) - 1; - root.setAttribute('data-clone', index); + root.dataset.clone = origin.clones.push(this) - 1; } return Clone; @@ -3876,10 +3882,8 @@ return; } $.asap((function() { - var _ref; - - return $.id('boardNavMobile') || ((_ref = d.readyState) === 'interactive' || _ref === 'complete'); - }), _this.setBoardList); + return $.id('boardNavMobile') || d.readyState !== 'loading'; + }), Header.setBoardList); $.prepend(d.body, _this.bar); $.add(d.body, Header.hover); return _this.setBarPosition(Conf['Bottom Header']); @@ -3933,7 +3937,7 @@ if (!text) { return; } - as = $$('#full-board-list a', Header.bar); + as = $$('#full-board-list a[title]', Header.bar); nodes = text.match(/[\w@]+((-(all|title|replace|full|index|catalog|url:"[^"]+[^"]"|text:"[^"]+")|\,"[^"]+[^"]"))*|[^\w@]+/g).map(function(t) { var a, board, m, _i, _len; @@ -3964,7 +3968,7 @@ a = a.cloneNode(true); a.textContent = /-title/.test(t) || /-replace/.test(t) && $.hasClass(a, 'current') ? a.title : /-full/.test(t) ? "/" + board + "/ - " + a.title : (m = t.match(/-text:"(.+)"/)) ? m[1] : a.textContent; if (m = t.match(/-(index|catalog)/)) { - a.setAttribute('data-only', m[1]); + a.dataset.only = m[1]; a.href = "//boards.4chan.org/" + board + "/"; if (m[1] === 'catalog') { a.href += 'catalog'; @@ -4203,7 +4207,7 @@ capcodeStart = ''; capcode = ''; } - flag = flagCode ? ("  + flagCode + ") : ''; + flag = !flagCode ? '' : boardID === 'pol' ? "  + flagCode + " : " "; if (file != null ? file.isDeleted : void 0) { fileHTML = isOP ? ("
") + ("File deleted.") + "
" : ("
") + ("File deleted.") + "
"; } else if (file) { @@ -4292,11 +4296,11 @@ postFromNode: function(root) { return Get.postFromRoot($.x('ancestor::div[contains(@class,"postContainer")][1]', root)); }, - contextFromLink: function(quotelink) { + contextFromNode: function(quotelink) { return Get.postFromRoot($.x('ancestor::div[parent::div[@class="thread"]][1]', quotelink)); }, postDataFromLink: function(link) { - var boardID, path, postID, threadID; + var boardID, path, postID, threadID, _ref; if (link.hostname === 'boards.4chan.org') { path = link.pathname.split('/'); @@ -4304,9 +4308,8 @@ threadID = path[3]; postID = link.hash.slice(2); } else { - boardID = link.dataset.boardid; - threadID = link.dataset.threadid || 0; - postID = link.dataset.postid; + _ref = link.dataset, boardID = _ref.boardID, threadID = _ref.threadID, postID = _ref.postID; + threadID || (threadID = 0); } return { boardID: boardID, @@ -4478,7 +4481,7 @@ } }); comment = bq.innerHTML.replace(/(^|>)(>[^<$]*)(<|$)/g, '$1$2$3').replace(/((>){2}(>\/[a-z\d]+\/)?\d+)/g, '$1'); - threadID = data.thread_num; + threadID = +data.thread_num; o = { postID: "" + postID, threadID: "" + threadID, @@ -4905,7 +4908,13 @@ if ($.x('ancestor::div[contains(@class,"inline")][1]', root)) { $.on(d, 'keydown', o.hoverend); } - return $.on(root, 'mousemove', o.hover); + $.on(root, 'mousemove', o.hover); + o.workaround = function(e) { + if (!root.contains(e.target)) { + return o.hoverend(); + } + }; + return $.on(doc, 'mousemove', o.workaround); }; hover = function(e) { var clientX, clientY, height, left, right, style, top, _ref; @@ -4929,6 +4938,7 @@ $.off(this.root, this.endEvents, this.hoverend); $.off(d, 'keydown', this.hoverend); $.off(this.root, 'mousemove', this.hover); + $.off(doc, 'mousemove', this.workaround); if (this.cb) { return this.cb.call(this); } @@ -5214,7 +5224,7 @@ href: 'javascript:;', textContent: text }); - el.setAttribute('data-type', type); + el.dataset.type = type; $.on(el, 'click', Filter.menu.makeFilter); return { el: el, @@ -5808,7 +5818,7 @@ innerHTML: " " + (type === 'hide' ? '-' : '+') + " ", href: 'javascript:;' }); - a.setAttribute('data-fullid', thread.fullID); + a.dataset.fullID = thread.fullID; $.on(a, 'click', ThreadHiding.toggle); return a; }, @@ -5836,7 +5846,7 @@ }, toggle: function(thread) { if (!(thread instanceof Thread)) { - thread = g.threads[this.dataset.fullid]; + thread = g.threads[this.dataset.fullID]; } if (thread.isHidden) { ThreadHiding.show(thread); @@ -6067,7 +6077,7 @@ } e.preventDefault(); _ref = Get.postDataFromLink(this), boardID = _ref.boardID, threadID = _ref.threadID, postID = _ref.postID; - context = Get.contextFromLink(this); + context = Get.contextFromNode(this); if ($.hasClass(this, 'inlined')) { QuoteInline.rm(this, boardID, threadID, postID, context); } else { @@ -6216,7 +6226,7 @@ className: 'dialog' }); $.add(Header.hover, qp); - Get.postClone(boardID, threadID, postID, qp, Get.contextFromLink(this)); + Get.postClone(boardID, threadID, postID, qp, Get.contextFromNode(this)); UI.hover({ root: this, el: qp, @@ -6540,9 +6550,11 @@ target: '_blank', textContent: "" + quote + "\u00A0(Dead)" }); - a.setAttribute('data-boardid', boardID); - a.setAttribute('data-threadid', post.thread.ID); - a.setAttribute('data-postid', postID); + $.extend(a.dataset, { + boardID: boardID, + threadID: post.thread.ID, + postID: postID + }); } } else if (redirect = Redirect.to('thread', { boardID: boardID, @@ -6560,8 +6572,10 @@ postID: postID })) { $.addClass(a, 'quotelink'); - a.setAttribute('data-boardid', boardID); - a.setAttribute('data-postid', postID); + $.extend(a.dataset, { + boardID: boardID, + postID: postID + }); } } if (!this.quotes.contains(quoteID)) { @@ -7027,7 +7041,7 @@ } }, close: function() { - var i, _i, _len, _ref; + var post, _i, _len, _ref; if (QR.req) { QR.abort(); @@ -7043,10 +7057,10 @@ if (Conf['QR Shortcut']) { $.toggleClass($('.qr-shortcut'), 'disabled'); } - _ref = QR.posts; + _ref = QR.posts.splice(0, QR.posts.length, new QR.post(true)); for (_i = 0, _len = _ref.length; _i < _len; _i++) { - i = _ref[_i]; - QR.posts[0].rm(); + post = _ref[_i]; + post["delete"](); } QR.cooldown.auto = false; return QR.status(); @@ -7112,12 +7126,13 @@ return QR.notifications = []; }, status: function() { - var disabled, status, value; + var disabled, status, thread, value; if (!QR.nodes) { return; } - if (g.DEAD) { + thread = QR.posts[0].thread; + if (thread !== 'new' && g.threads["" + g.BOARD + "." + thread].isDead) { value = 404; disabled = true; QR.cooldown.auto = false; @@ -7371,7 +7386,7 @@ } }, quote: function(e) { - var OP, caretPos, com, index, post, range, s, sel, selectionRoot, text, thread, _ref; + var caretPos, com, index, post, range, s, sel, text, thread, _ref; if (e != null) { e.preventDefault(); @@ -7380,11 +7395,9 @@ return; } sel = d.getSelection(); - selectionRoot = $.x('ancestor::div[contains(@class,"postContainer")][1]', sel.anchorNode); post = Get.postFromNode(this); - OP = Get.contextFromLink(this).thread.OP; text = ">>" + post + "\n"; - if ((s = sel.toString().trim()) && post.nodes.root === selectionRoot) { + if ((s = sel.toString().trim()) && post === Get.postFromNode(sel.anchorNode)) { s = s.replace(/\n/g, '\n>'); text += ">" + s + "\n"; } @@ -7397,7 +7410,7 @@ } _ref = QR.nodes, com = _ref.com, thread = _ref.thread; if (!com.value) { - thread.value = OP.ID; + thread.value = Get.contextFromNode(this).thread; } thread.nextElementSibling.firstElementChild.textContent = thread.options[thread.selectedIndex].textContent; caretPos = com.selectionStart; @@ -7469,7 +7482,7 @@ fileInput: function(files) { var file, length, max, post, _i, _len; - if (this instanceof Element) { + if (files instanceof Event) { files = __slice.call(this.files); QR.nodes.fileInput.value = null; } @@ -7578,7 +7591,7 @@ _Class.prototype.rm = function() { var index; - $.rm(this.nodes.el); + this["delete"](); index = QR.posts.indexOf(this); if (QR.posts.length === 1) { new QR.post(true); @@ -7587,9 +7600,11 @@ (QR.posts[index - 1] || QR.posts[index + 1]).select(); } QR.posts.splice(index, 1); - if (!window.URL) { - return; - } + return QR.status(); + }; + + _Class.prototype["delete"] = function() { + $.rm(this.nodes.el); return URL.revokeObjectURL(this.URL); }; @@ -7649,21 +7664,23 @@ }; _Class.prototype.save = function(input) { - var value, _ref; + var name, _ref; if (input.type === 'checkbox') { this.spoiler = input.checked; return; } - value = input.value; - this[input.dataset.name] = value; - if (input.nodeName !== 'TEXTAREA') { - return; - } - this.nodes.span.textContent = value; - QR.characterCount(); - if (QR.cooldown.auto && this === QR.posts[0] && (0 < (_ref = QR.cooldown.seconds) && _ref <= 5)) { - return QR.cooldown.auto = false; + name = input.dataset.name; + this[name] = input.value; + switch (name) { + case 'thread': + return QR.status(); + case 'com': + this.nodes.span.textContent = this.com; + QR.characterCount(); + if (QR.cooldown.auto && this === QR.posts[0] && (0 < (_ref = QR.cooldown.seconds) && _ref <= 5)) { + return QR.cooldown.auto = false; + } } }; @@ -7687,9 +7704,7 @@ if (QR.spoiler) { this.nodes.label.hidden = false; } - if (window.URL) { - URL.revokeObjectURL(this.URL); - } + URL.revokeObjectURL(this.URL); this.showFileData(); if (!/^image/.test(file.type)) { this.nodes.el.style.backgroundImage = null; @@ -7698,22 +7713,10 @@ return this.setThumbnail(); }; - _Class.prototype.setThumbnail = function(fileURL) { - var img, reader, + _Class.prototype.setThumbnail = function() { + var fileURL, img, _this = this; - if (!window.URL) { - if (!fileURL) { - reader = new FileReader(); - reader.onload = function(e) { - return _this.setThumbnail(e.target.result); - }; - reader.readAsDataURL(this.file); - return; - } - } else { - fileURL = URL.createObjectURL(this.file); - } img = $.el('img'); img.onload = function() { var applyBlob, cv, data, height, i, l, s, ui8a, width, _i; @@ -7724,9 +7727,7 @@ } height = img.height, width = img.width; if (height < s || width < s) { - if (window.URL) { - _this.URL = fileURL; - } + _this.URL = fileURL; _this.nodes.el.style.backgroundImage = "url(" + _this.URL + ")"; return; } @@ -7741,11 +7742,6 @@ cv.height = img.height = height; cv.width = img.width = width; cv.getContext('2d').drawImage(img, 0, 0, width, height); - if (!window.URL) { - _this.nodes.el.style.backgroundImage = "url(" + (cv.toDataURL()) + ")"; - delete _this.URL; - return; - } URL.revokeObjectURL(fileURL); applyBlob = function(blob) { _this.URL = URL.createObjectURL(blob); @@ -7765,6 +7761,7 @@ type: 'image/png' })); }; + fileURL = URL.createObjectURL(this.file); return img.src = fileURL; }; @@ -7777,9 +7774,6 @@ this.nodes.label.hidden = true; } this.showFileData(); - if (!window.URL) { - return; - } return URL.revokeObjectURL(this.URL); }; @@ -7840,12 +7834,11 @@ _Class.prototype.drop = function() { var el, index, newIndex, oldIndex, post; - el = $('.drag', this.parentNode); - $.rmClass(el, 'drag'); $.rmClass(this, 'over'); if (!this.draggable) { return; } + el = $('.drag', this.parentNode); index = function(el) { return __slice.call(el.parentNode.children).indexOf(el); }; @@ -7853,7 +7846,8 @@ newIndex = index(this); (oldIndex < newIndex ? $.after : $.before)(this, el); post = QR.posts.splice(oldIndex, 1)[0]; - return QR.posts.splice(newIndex, 0, post); + QR.posts.splice(newIndex, 0, post); + return QR.status(); }; return _Class; @@ -7872,7 +7866,7 @@ }), this.ready.bind(this)); }, ready: function() { - var imgContainer, input, observer, setLifetime, + var imgContainer, input, setLifetime, _this = this; setLifetime = function(e) { @@ -7898,14 +7892,9 @@ img: imgContainer.firstChild, input: input }; - if (window.MutationObserver) { - observer = new MutationObserver(this.load.bind(this)); - observer.observe(this.nodes.challenge, { - childList: true - }); - } else { - $.on(this.nodes.challenge, 'DOMNodeInserted', this.load.bind(this)); - } + new MutationObserver(this.load.bind(this)).observe(this.nodes.challenge, { + childList: true + }); $.on(imgContainer, 'click', this.reload.bind(this)); $.on(input, 'keydown', this.keydown.bind(this)); $.on(input, 'focus', function() { @@ -7914,8 +7903,11 @@ $.on(input, 'blur', function() { return $.rmClass(QR.nodes.el, 'focus'); }); - $.get('captchas', [], function(item) { - return _this.sync(item['captchas']); + $.get('captchas', [], function(_arg) { + var captchas; + + captchas = _arg.captchas; + return _this.sync(captchas); }); $.sync('captchas', this.sync); this.reload(); @@ -7925,7 +7917,7 @@ return $.after(QR.nodes.dumpList.parentElement, [imgContainer, input]); }, sync: function(captchas) { - this.captchas = captchas; + QR.captcha.captchas = captchas; return QR.captcha.count(); }, getOne: function() { @@ -8076,7 +8068,6 @@ QR.mimeTypes = mimeTypes.split(', '); QR.mimeTypes.push(''); nodes.fileInput.max = $('input[name=MAX_FILE_SIZE]').value; - nodes.fileInput.accept = "text/*, " + mimeTypes; QR.spoiler = !!$('input[name=spoiler]'); if (QR.spoiler) { $.addClass(QR.nodes.el, 'has-spoiler'); @@ -8364,16 +8355,12 @@ post: post, isReply: isReply }); - if (threadID === postID) { - URL = "/" + g.BOARD + "/res/" + threadID; - } else if (g.VIEW === 'index' && !QR.cooldown.auto && Conf['Open Post in New Tab']) { - URL = "/" + g.BOARD + "/res/" + threadID + "#p" + postID; - } + URL = threadID === postID ? "/" + g.BOARD + "/res/" + threadID : g.VIEW === 'index' && !QR.cooldown.auto && Conf['Open Post in New Tab'] ? "/" + g.BOARD + "/res/" + threadID + "#p" + postID : void 0; if (URL) { if (Conf['Open Post in New Tab']) { - $.open("/" + g.BOARD + "/res/" + threadID); + $.open(URL); } else { - window.location = "/" + g.BOARD + "/res/" + threadID; + window.location = URL; } } return QR.status(); @@ -8750,7 +8737,7 @@ id: 'ihover', src: post.file.URL }); - el.setAttribute('data-fullid', post.fullID); + el.dataset.fullID = post.fullID; $.add(Header.hover, el); UI.hover({ root: this, @@ -8770,7 +8757,7 @@ if (!doc.contains(this)) { return; } - post = g.posts[this.dataset.fullid]; + post = g.posts[this.dataset.fullID]; src = this.src.split('/'); if (src[2] === 'images.4chan.org') { URL = Redirect.to('file', { @@ -8900,6 +8887,78 @@ } }; + Sauce = { + init: function() { + var err, link, links, _i, _len, _ref; + + if (g.VIEW === 'catalog' || !Conf['Sauce']) { + return; + } + links = []; + _ref = Conf['sauces'].split('\n'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + link = _ref[_i]; + try { + if (link[0] !== '#') { + links.push(this.createSauceLink(link.trim())); + } + } catch (_error) { + err = _error; + } + } + if (!links.length) { + return; + } + this.links = links; + this.link = $.el('a', { + target: '_blank' + }); + return Post.prototype.callbacks.push({ + name: 'Sauce', + cb: this.node + }); + }, + createSauceLink: function(link) { + var m, text; + + link = link.replace(/(%(T?URL|MD5|board)|\$[1-4])/ig, function(parameter) { + switch (parameter) { + case '%TURL': + case '$1': + return "' + encodeURIComponent(post.file.thumbURL) + '"; + case '%URL': + case '$2': + return "' + encodeURIComponent(post.file.URL) + '"; + case '%MD5': + case '$3': + return "' + encodeURIComponent(post.file.MD5) + '"; + case '%board': + case '$4': + return "' + encodeURIComponent(post.board) + '"; + default: + return parameter; + } + }); + text = (m = link.match(/;text:(.+)$/)) ? m[1] : link.match(/(\w+)\.\w+\//)[1]; + link = link.replace(/;text:.+$/, ''); + return Function('post', 'a', "a.href = '" + link + "';\na.textContent = '" + text + "';\nreturn a;"); + }, + node: function() { + var link, nodes, _i, _len, _ref; + + if (this.isClone || !this.file) { + return; + } + nodes = []; + _ref = Sauce.links; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + link = _ref[_i]; + nodes.push($.tn('\u00A0'), link(this, Sauce.link.cloneNode(true))); + } + return $.add(this.file.info, nodes); + } + }; + ArchiveLink = { init: function() { var div, entry, type, _i, _len, _ref; @@ -9040,8 +9099,8 @@ return; } $.off(this, 'click', DeleteLink["delete"]); - this.textContent = "Deleting " + this.textContent + "..."; fileOnly = $.hasClass(this, 'delete-file'); + this.textContent = "Deleting " + (fileOnly ? 'file' : 'post') + "..."; form = { mode: 'usrdel', onlyimgdel: fileOnly, @@ -9161,39 +9220,29 @@ node: function() { var button; - button = Menu.makeButton(this); if (this.isClone) { - $.replace($('.menu-button', this.nodes.info), button); - return; + button = $('.menu-button', this.nodes.info); + } else { + button = Menu.makeButton(this); + $.add(this.nodes.info, [$.tn('\u00A0'), button]); } - return $.add(this.nodes.info, [$.tn('\u00A0'), button]); + return $.on(button, 'click', Menu.toggle); }, makeButton: (function() { var a; a = null; - return function(post) { - var clone; - + return function() { a || (a = $.el('a', { className: 'menu-button brackets-wrap', innerHTML: '', href: 'javascript:;' })); - clone = a.cloneNode(true); - clone.setAttribute('data-postid', post.fullID); - if (post.isClone) { - clone.setAttribute('data-clone', true); - } - $.on(clone, 'click', Menu.toggle); - return clone; + return a.cloneNode(true); }; })(), toggle: function(e) { - var post; - - post = this.dataset.clone ? Get.postFromNode(this) : g.posts[this.dataset.postid]; - return Menu.menu.toggle(e, this, post); + return Menu.menu.toggle(e, this, Get.postFromNode(this)); } }; @@ -9626,7 +9675,7 @@ This saves bandwidth for both the user and the servers and avoid unnecessary computation. */ - _ref = [0, 304].contains(req.status) ? [null, null] : ["" + req.statusText + " (" + req.status + ")", 'warning'], text = _ref[0], klass = _ref[1]; + _ref = req.status === 304 ? [null, null] : ["" + req.statusText + " (" + req.status + ")", 'warning'], text = _ref[0], klass = _ref[1]; ThreadUpdater.set('status', text, klass); } if (ThreadUpdater.postID) { @@ -10023,23 +10072,21 @@ } }, scroll: function() { - var checkPosition, hash, onload, post, posts, prevID, root; + var checkPosition, hash, onload, post, posts, root; if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) { return; } if (Unread.posts.length) { - prevID = 0; - while (root = $.x('preceding-sibling::div[contains(@class,"postContainer")][1]', Unread.posts[0].nodes.root)) { - post = Get.postFromRoot(root); - if (prevID === post.ID) { - break; - } - prevID = post.ID; - if (!post.isHidden) { + post = Unread.posts[0]; + while (root = $.x('preceding-sibling::div[contains(@class,"replyContainer")][1]', post.nodes.root)) { + if (!(post = Get.postFromRoot(root)).isHidden) { break; } } + if (!root) { + return; + } onload = function() { if (checkPosition(root)) { return root.scrollIntoView(false); @@ -10224,7 +10271,7 @@ post: {}, file: {}, init: function() { - var archive, arr, boardID, data, id, name, type, _i, _len, _ref, _ref1, _ref2, _ref3; + var archive, arr, boardID, data, id, name, type, _ref, _ref1, _ref2, _results; _ref = Conf['selectedArchives']; for (boardID in _ref) { @@ -10245,22 +10292,32 @@ } } _ref2 = Redirect.archives; + _results = []; for (name in _ref2) { archive = _ref2[name]; - _ref3 = archive.boards; - for (_i = 0, _len = _ref3.length; _i < _len; _i++) { - boardID = _ref3[_i]; - if (!(boardID in Redirect.thread)) { - Redirect.thread[boardID] = archive; + _results.push((function() { + var _i, _len, _ref3, _results1; + + _ref3 = archive.boards; + _results1 = []; + for (_i = 0, _len = _ref3.length; _i < _len; _i++) { + boardID = _ref3[_i]; + if (!(boardID in Redirect.thread)) { + Redirect.thread[boardID] = archive; + } + if (!(boardID in Redirect.post || archive.software !== 'foolfuuka')) { + Redirect.post[boardID] = archive; + } + if (!(boardID in Redirect.file || !archive.files.contains(boardID))) { + _results1.push(Redirect.file[boardID] = archive); + } else { + _results1.push(void 0); + } } - if (!(boardID in Redirect.post || archive.software !== 'foolfuuka')) { - Redirect.post[boardID] = archive; - } - if (!(boardID in Redirect.file || !archive.files.contains(boardID))) { - Redirect.file[boardID] = archive; - } - } + return _results1; + })()); } + return _results; }, archives: { 'Foolz': { @@ -10268,7 +10325,7 @@ 'http': false, 'https': true, 'software': 'foolfuuka', - 'boards': ['a', 'co', 'gd', 'jp', 'm', 'q', 'sp', 'tg', 'tv', 'v', 'vg', 'vp', 'vr', 'wsg'], + 'boards': ['a', 'co', 'gd', 'jp', 'm', 'q', 'sp', 'tg', 'tv', 'vg', 'vp', 'vr', 'wsg'], 'files': ['a', 'gd', 'jp', 'm', 'q', 'tg', 'vg', 'vp', 'vr', 'wsg'] }, 'NSFW Foolz': { @@ -10302,25 +10359,17 @@ 'boards': ['c', 'w', 'wg'], 'files': ['c', 'w', 'wg'] }, - 'Love is Over': { - 'domain': 'loveisover.me', - 'http': true, - 'https': true, - 'software': 'foolfuuka', - 'boards': ['d', 'h', 'v'], - 'files': ['d', 'h', 'v'] - }, 'Foolz a Shit': { 'domain': 'archive.foolzashit.com', 'http': true, 'https': true, 'software': 'foolfuuka', - 'boards': ['adv', 'asp', 'cm', 'e', 'i', 'lgbt', 'n', 'o', 'p', 'pol', 's', 's4s', 't', 'trv', 'y'], - 'files': ['adv', 'asp', 'cm', 'e', 'i', 'lgbt', 'n', 'o', 'p', 's', 's4s', 't', 'trv', 'y'] + 'boards': ['adv', 'asp', 'cm', 'i', 'lgbt', 'n', 'o', 'p', 's4s', 't', 'trv'], + 'files': ['adv', 'asp', 'cm', 'i', 'lgbt', 'n', 'o', 'p', 's4s', 't', 'trv'] }, 'Install Gentoo': { 'domain': 'archive.installgentoo.net', - 'http': true, + 'http': false, 'https': true, 'software': 'fuuka', 'boards': ['diy', 'g', 'sci'], @@ -10348,6 +10397,14 @@ 'software': 'fuuka', 'boards': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'tg', 'vr'], 'files': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'vr'] + }, + 'worldathleticproject': { + 'domain': 'fuuka.worldathleticproject.org', + 'http': true, + 'https': true, + 'software': 'foolfuuka', + 'boards': ['e', 'h', 'p', 's', 'u'], + 'files': ['e', 'h', 'p', 's', 'u'] } }, to: function(dest, data) { @@ -12732,13 +12789,13 @@ } break; case Conf['Next thread']: - if (g.VIEW === 'thread') { + if (g.VIEW !== 'index') { return; } Nav.scroll(+1); break; case Conf['Previous thread']: - if (g.VIEW === 'thread') { + if (g.VIEW !== 'index') { return; } Nav.scroll(-1); @@ -13008,10 +13065,9 @@ _ref = Nav.getThread(true), threads = _ref[0], thread = _ref[1], i = _ref[2], rect = _ref[3], topMargin = _ref[4]; top = rect.top - topMargin; - if (!((delta === -1 && Math.ceil(top) < 0) || (delta === +1 && top > 1))) { - i += delta; + if ((delta === -1 && top > -5) || (delta === +1 && top < 5)) { + top = ((_ref1 = threads[i + delta]) != null ? _ref1.getBoundingClientRect().top : void 0) - topMargin; } - top = ((_ref1 = threads[i]) != null ? _ref1.getBoundingClientRect().top : void 0) - topMargin; return window.scrollBy(0, top); } }; @@ -13158,80 +13214,6 @@ } }; - Sauce = { - init: function() { - var err, link, links, _i, _len, _ref; - - if (g.VIEW === 'catalog' || !Conf['Sauce']) { - return; - } - links = []; - _ref = Conf['sauces'].split('\n'); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - link = _ref[_i]; - if (link[0] === '#') { - continue; - } - try { - links.push(this.createSauceLink(link.trim())); - } catch (_error) { - err = _error; - continue; - } - } - if (!links.length) { - return; - } - this.links = links; - this.link = $.el('a', { - target: '_blank' - }); - return Post.prototype.callbacks.push({ - name: 'Sauce', - cb: this.node - }); - }, - createSauceLink: function(link) { - var m, text; - - link = link.replace(/(%(T?URL|MD5|board)|\$[1-4])/ig, function(parameter) { - switch (parameter) { - case '%TURL': - case '$1': - return "' + encodeURIComponent(post.file.thumbURL) + '"; - case '%URL': - case '$2': - return "' + encodeURIComponent(post.file.URL) + '"; - case '%MD5': - case '$3': - return "' + encodeURIComponent(post.file.MD5) + '"; - case '%board': - case '$4': - return "' + encodeURIComponent(post.board) + '"; - default: - return parameter; - } - }); - text = (m = link.match(/;text:(.+)$/)) ? m[1] : link.match(/(\w+)\.\w+\//)[1]; - link = link.replace(/;text:.+$/, ''); - return Function('post', 'a', "a.href = '" + link + "';\na.textContent = '" + text + "';\nreturn a;"); - }, - node: function() { - var link, nodes, _i, _len, _ref; - - if (this.isClone || !this.file) { - return; - } - nodes = []; - _ref = Sauce.links; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - link = _ref[_i]; - nodes.push($.tn('\u00A0'), link(this, Sauce.link.cloneNode(true))); - } - return $.add(this.file.info, nodes); - } - }; - Time = { init: function() { if (g.VIEW === 'catalog' || !Conf['Time Formatting']) { @@ -13364,7 +13346,9 @@ el = $.el('span', { innerHTML: "appchan x has been updated to version " + g.VERSION + "." }); - new Notification('info', el, 30); + if (Conf['Show Updated Notifications']) { + new Notification('info', el, 30); + } } else { $.on(d, '4chanXInitFinished', Settings.open); } @@ -13679,7 +13663,7 @@ $.add(div, ta); return; } - return div.innerHTML = "
Filter is disabled.

\nUse regular expressions, one per line.
\nLines starting with a # will be ignored.
\nFor example, /weeaboo/i will filter posts containing the string `weeaboo`, case-insensitive.
\nMD5 filtering uses exact string matching, not regular expressions.\n

"; + return div.innerHTML = "
Filter is disabled.

\nUse regular expressions, one per line.
\nLines starting with a # will be ignored.
\nFor example, /weeaboo/i will filter posts containing the string `weeaboo`, case-insensitive.
\nMD5 filtering uses exact string matching, not regular expressions.\n

"; }, sauce: function(section) { var ta; @@ -14686,7 +14670,7 @@ return $.ready(Main.initReady); }, initReady: function() { - var board, boardChild, err, errors, href, passLink, posts, styleSelector, thread, threadChild, threads, _i, _j, _len, _len1, _ref, _ref1; + var board, err, errors, href, passLink, postRoot, posts, styleSelector, thread, threadRoot, threads, _i, _j, _len, _len1, _ref, _ref1; if (d.title === '4chan - 404 Not Found') { if (Conf['404 Redirect'] && g.VIEW === 'thread') { @@ -14702,29 +14686,23 @@ if (board = $('.board')) { threads = []; posts = []; - _ref = board.children; + _ref = $$('.board > .thread', board); for (_i = 0, _len = _ref.length; _i < _len; _i++) { - boardChild = _ref[_i]; - if (!$.hasClass(boardChild, 'thread')) { - continue; - } - thread = new Thread(boardChild.id.slice(1), g.BOARD); + threadRoot = _ref[_i]; + thread = new Thread(+threadRoot.id.slice(1), g.BOARD); threads.push(thread); - _ref1 = boardChild.children; + _ref1 = $$('.thread > .postContainer', threadRoot); for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - threadChild = _ref1[_j]; - if (!$.hasClass(threadChild, 'postContainer')) { - continue; - } + postRoot = _ref1[_j]; try { - posts.push(new Post(threadChild, thread, g.BOARD)); + posts.push(new Post(postRoot, thread, g.BOARD)); } catch (_error) { err = _error; if (!errors) { errors = []; } errors.push({ - message: "Parsing of Post No." + (threadChild.id.match(/\d+/)) + " failed. Post will be skipped.", + message: "Parsing of Post No." + (postRoot.id.match(/\d+/)) + " failed. Post will be skipped.", error: err }); } @@ -14948,7 +14926,7 @@ var _ref; if (!('thisPageIsLegit' in Main)) { - Main.thisPageIsLegit = location.hostname === 'boards.4chan.org' && !$('link[href*="favicon-status.ico"]', d.head) && ((_ref = d.title) !== '4chan - Temporarily Offline' && _ref !== '4chan - Error'); + Main.thisPageIsLegit = location.hostname === 'boards.4chan.org' && !$('link[href*="favicon-status.ico"]', d.head) && ((_ref = d.title) !== '4chan - Temporarily Offline' && _ref !== '4chan - Error' && _ref !== '504 Gateway Time-out'); } return Main.thisPageIsLegit; } diff --git a/builds/crx/manifest.json b/builds/crx/manifest.json index 3fd59e461..a9ea47022 100644 --- a/builds/crx/manifest.json +++ b/builds/crx/manifest.json @@ -16,6 +16,7 @@ }], "homepage_url": "http://zixaphir.github.com/appchan-x/", "minimum_chrome_version": "24", + "minimum_opera_version": "15", "permissions": [ "storage" ] diff --git a/builds/crx/script.js b/builds/crx/script.js index e420a7671..d7948d42d 100644 --- a/builds/crx/script.js +++ b/builds/crx/script.js @@ -1,6 +1,6 @@ // Generated by CoffeeScript /* -* appchan x - Version 2.1.3 - 2013-07-07 +* appchan x - Version 2.1.3 - 2013-07-21 * * Licensed under the MIT license. * https://github.com/zixaphir/appchan-x/blob/master/LICENSE @@ -2746,9 +2746,9 @@ }; $.ready = function(fc) { - var cb, _ref; + var cb; - if ((_ref = d.readyState) === 'interactive' || _ref === 'complete') { + if (d.readyState !== 'loading') { $.queueTask(fc); return; } @@ -3092,6 +3092,14 @@ return (value < min ? min : value > max ? max : value); }; + $.item = function(key, val) { + var item; + + item = {}; + item[key] = val; + return item; + }; + $.syncing = {}; $.sync = (function() { @@ -3109,14 +3117,6 @@ }; })(); - $.item = function(key, val) { - var item; - - item = {}; - item[key] = val; - return item; - }; - $.localKeys = ['name', 'uniqueID', 'tripcode', 'capcode', 'email', 'subject', 'comment', 'flag', 'filename', 'dimensions', 'filesize', 'MD5', 'usercss']; $["delete"] = function(keys) { @@ -3232,8 +3232,8 @@ }; function Thread(ID, board) { + this.ID = ID; this.board = board; - this.ID = +ID; this.fullID = "" + this.board + "." + this.ID; this.posts = {}; g.threads[this.fullID] = board.threads[this] = this; @@ -3256,7 +3256,7 @@ }; function Post(root, thread, board, that) { - var alt, anchor, capcode, date, email, file, fileInfo, flag, info, name, post, size, subject, thumb, tripcode, uniqueID, unit; + var capcode, date, email, flag, info, name, post, subject, tripcode, uniqueID; this.thread = thread; this.board = board; @@ -3275,6 +3275,11 @@ quotelinks: [], backlinks: info.getElementsByClassName('backlink') }; + if (!(this.isReply = $.hasClass(post, 'reply'))) { + this.thread.OP = this; + this.thread.isSticky = !!$('.stickyIcon', info); + this.thread.isClosed = !!$('.closedIcon', info); + } this.info = {}; if (subject = $('.subject', info)) { this.nodes.subject = subject; @@ -3300,7 +3305,7 @@ this.nodes.capcode = capcode; this.info.capcode = capcode.textContent.replace('## ', ''); } - if (flag = $('.countryFlag', info)) { + if (flag = $('.flag, .countryFlag', info)) { this.nodes.flag = flag; this.info.flag = flag.title; } @@ -3315,36 +3320,7 @@ }); this.parseComment(); this.parseQuotes(); - if ((file = $('.file', post)) && (thumb = $('img[data-md5]', file))) { - alt = thumb.alt; - anchor = thumb.parentNode; - fileInfo = file.firstElementChild; - this.file = { - info: fileInfo, - text: fileInfo.firstElementChild, - thumb: thumb, - URL: anchor.href, - size: alt.match(/[\d.]+\s\w+/)[0], - MD5: thumb.dataset.md5, - isSpoiler: $.hasClass(anchor, 'imgspoiler') - }; - size = +this.file.size.match(/[\d.]+/)[0]; - unit = ['B', 'KB', 'MB', 'GB'].indexOf(this.file.size.match(/\w+$/)[0]); - while (unit-- > 0) { - size *= 1024; - } - this.file.sizeInBytes = size; - this.file.thumbURL = that.isArchived ? thumb.src : "" + location.protocol + "//thumbs.4chan.org/" + board + "/thumb/" + (this.file.URL.match(/(\d+)\./)[1]) + "s.jpg"; - this.file.name = $('span[title]', fileInfo).title.replace(/%22/g, '"'); - if (this.file.isImage = /(jpg|png|gif)$/i.test(this.file.name)) { - this.file.dimensions = this.file.text.textContent.match(/\d+x\d+/)[0]; - } - } - if (!(this.isReply = $.hasClass(post, 'reply'))) { - this.thread.OP = this; - this.thread.isSticky = !!$('.stickyIcon', this.nodes.info); - this.thread.isClosed = !!$('.closedIcon', this.nodes.info); - } + this.parseFile(that); this.clones = []; g.posts[this.fullID] = thread.posts[this] = board.posts[this] = this; if (that.isArchived) { @@ -3353,7 +3329,7 @@ } Post.prototype.parseComment = function() { - var bq, data, i, node, nodes, text, _i, _len, _ref; + var bq, i, node, nodes, text, _i, _len, _ref; bq = this.nodes.comment.cloneNode(true); _ref = $$('.abbr, .capcodeReplies, .exif, b', bq); @@ -3365,7 +3341,7 @@ nodes = d.evaluate('.//br|.//text()', bq, null, 7, null); i = 0; while (i < nodes.snapshotLength) { - text.push((data = nodes.snapshotItem(i++).data) ? data : '\n'); + text.push(nodes.snapshotItem(i++).data || '\n'); } return this.info.comment = text.join('').trim().replace(/\s+$/gm, ''); }; @@ -3389,7 +3365,7 @@ continue; } this.nodes.quotelinks.push(quotelink); - if (quotelink.parentNode.parentNode.className === 'capcodeReplies') { + if (!this.isReply && $.hasClass(quotelink.parentNode.parentNode, 'capcodeReplies')) { continue; } quotes["" + (pathname.split('/')[1]) + "." + hash.slice(2)] = true; @@ -3400,6 +3376,38 @@ return this.quotes = Object.keys(quotes); }; + Post.prototype.parseFile = function(that) { + var alt, anchor, fileEl, fileInfo, size, thumb, unit; + + if (!((fileEl = $('.file', this.nodes.post)) && (thumb = $('img[data-md5]', fileEl)))) { + return; + } + alt = thumb.alt; + anchor = thumb.parentNode; + fileInfo = fileEl.firstElementChild; + this.file = { + info: fileInfo, + text: fileInfo.firstElementChild, + thumb: thumb, + URL: anchor.href, + size: alt.match(/[\d.]+\s\w+/)[0], + MD5: thumb.dataset.md5, + isSpoiler: $.hasClass(anchor, 'imgspoiler') + }; + size = +this.file.size.match(/[\d.]+/)[0]; + unit = ['B', 'KB', 'MB', 'GB'].indexOf(this.file.size.match(/\w+$/)[0]); + while (unit-- > 0) { + size *= 1024; + } + this.file.sizeInBytes = size; + this.file.thumbURL = that.isArchived ? thumb.src : "" + location.protocol + "//thumbs.4chan.org/" + this.board + "/thumb/" + (this.file.URL.match(/(\d+)\./)[1]) + "s.jpg"; + this.file.name = $('span[title]', fileInfo).title; + this.file.name = this.file.name.replace(/%22/g, '"'); + if (this.file.isImage = /(jpg|png|gif)$/i.test(this.file.name)) { + return this.file.dimensions = this.file.text.textContent.match(/\d+x\d+/)[0]; + } + }; + Post.prototype.kill = function(file, now) { var clone, quotelink, strong, _i, _j, _len, _len1, _ref, _ref1; @@ -3490,7 +3498,7 @@ _ref = this.clones.slice(index); for (_i = 0, _len = _ref.length; _i < _len; _i++) { clone = _ref[_i]; - clone.nodes.root.setAttribute('data-clone', index++); + clone.nodes.root.dataset.clone = index++; } }; @@ -3502,7 +3510,7 @@ __extends(Clone, _super); function Clone(origin, context) { - var file, index, info, inline, inlined, key, nodes, post, root, val, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3; + var file, info, inline, inlined, key, nodes, post, root, val, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3; this.origin = origin; this.context = context; @@ -3578,8 +3586,7 @@ this.isDead = true; } this.isClone = true; - index = origin.clones.push(this) - 1; - root.setAttribute('data-clone', index); + root.dataset.clone = origin.clones.push(this) - 1; } return Clone; @@ -3883,10 +3890,8 @@ return; } $.asap((function() { - var _ref; - - return $.id('boardNavMobile') || ((_ref = d.readyState) === 'interactive' || _ref === 'complete'); - }), _this.setBoardList); + return $.id('boardNavMobile') || d.readyState !== 'loading'; + }), Header.setBoardList); $.prepend(d.body, _this.bar); $.add(d.body, Header.hover); return _this.setBarPosition(Conf['Bottom Header']); @@ -3940,7 +3945,7 @@ if (!text) { return; } - as = $$('#full-board-list a', Header.bar); + as = $$('#full-board-list a[title]', Header.bar); nodes = text.match(/[\w@]+((-(all|title|replace|full|index|catalog|url:"[^"]+[^"]"|text:"[^"]+")|\,"[^"]+[^"]"))*|[^\w@]+/g).map(function(t) { var a, board, m, _i, _len; @@ -3971,7 +3976,7 @@ a = a.cloneNode(true); a.textContent = /-title/.test(t) || /-replace/.test(t) && $.hasClass(a, 'current') ? a.title : /-full/.test(t) ? "/" + board + "/ - " + a.title : (m = t.match(/-text:"(.+)"/)) ? m[1] : a.textContent; if (m = t.match(/-(index|catalog)/)) { - a.setAttribute('data-only', m[1]); + a.dataset.only = m[1]; a.href = "//boards.4chan.org/" + board + "/"; if (m[1] === 'catalog') { a.href += 'catalog'; @@ -4210,7 +4215,7 @@ capcodeStart = ''; capcode = ''; } - flag = flagCode ? ("  + flagCode + ") : ''; + flag = !flagCode ? '' : boardID === 'pol' ? "  + flagCode + " : " "; if (file != null ? file.isDeleted : void 0) { fileHTML = isOP ? ("
") + ("File deleted.") + "
" : ("
") + ("File deleted.") + "
"; } else if (file) { @@ -4299,11 +4304,11 @@ postFromNode: function(root) { return Get.postFromRoot($.x('ancestor::div[contains(@class,"postContainer")][1]', root)); }, - contextFromLink: function(quotelink) { + contextFromNode: function(quotelink) { return Get.postFromRoot($.x('ancestor::div[parent::div[@class="thread"]][1]', quotelink)); }, postDataFromLink: function(link) { - var boardID, path, postID, threadID; + var boardID, path, postID, threadID, _ref; if (link.hostname === 'boards.4chan.org') { path = link.pathname.split('/'); @@ -4311,9 +4316,8 @@ threadID = path[3]; postID = link.hash.slice(2); } else { - boardID = link.dataset.boardid; - threadID = link.dataset.threadid || 0; - postID = link.dataset.postid; + _ref = link.dataset, boardID = _ref.boardID, threadID = _ref.threadID, postID = _ref.postID; + threadID || (threadID = 0); } return { boardID: boardID, @@ -4485,7 +4489,7 @@ } }); comment = bq.innerHTML.replace(/(^|>)(>[^<$]*)(<|$)/g, '$1$2$3').replace(/((>){2}(>\/[a-z\d]+\/)?\d+)/g, '$1'); - threadID = data.thread_num; + threadID = +data.thread_num; o = { postID: "" + postID, threadID: "" + threadID, @@ -5221,7 +5225,7 @@ href: 'javascript:;', textContent: text }); - el.setAttribute('data-type', type); + el.dataset.type = type; $.on(el, 'click', Filter.menu.makeFilter); return { el: el, @@ -5815,7 +5819,7 @@ innerHTML: " " + (type === 'hide' ? '-' : '+') + " ", href: 'javascript:;' }); - a.setAttribute('data-fullid', thread.fullID); + a.dataset.fullID = thread.fullID; $.on(a, 'click', ThreadHiding.toggle); return a; }, @@ -5843,7 +5847,7 @@ }, toggle: function(thread) { if (!(thread instanceof Thread)) { - thread = g.threads[this.dataset.fullid]; + thread = g.threads[this.dataset.fullID]; } if (thread.isHidden) { ThreadHiding.show(thread); @@ -6074,7 +6078,7 @@ } e.preventDefault(); _ref = Get.postDataFromLink(this), boardID = _ref.boardID, threadID = _ref.threadID, postID = _ref.postID; - context = Get.contextFromLink(this); + context = Get.contextFromNode(this); if ($.hasClass(this, 'inlined')) { QuoteInline.rm(this, boardID, threadID, postID, context); } else { @@ -6223,7 +6227,7 @@ className: 'dialog' }); $.add(Header.hover, qp); - Get.postClone(boardID, threadID, postID, qp, Get.contextFromLink(this)); + Get.postClone(boardID, threadID, postID, qp, Get.contextFromNode(this)); UI.hover({ root: this, el: qp, @@ -6547,9 +6551,11 @@ target: '_blank', textContent: "" + quote + "\u00A0(Dead)" }); - a.setAttribute('data-boardid', boardID); - a.setAttribute('data-threadid', post.thread.ID); - a.setAttribute('data-postid', postID); + $.extend(a.dataset, { + boardID: boardID, + threadID: post.thread.ID, + postID: postID + }); } } else if (redirect = Redirect.to('thread', { boardID: boardID, @@ -6567,8 +6573,10 @@ postID: postID })) { $.addClass(a, 'quotelink'); - a.setAttribute('data-boardid', boardID); - a.setAttribute('data-postid', postID); + $.extend(a.dataset, { + boardID: boardID, + postID: postID + }); } } if (!this.quotes.contains(quoteID)) { @@ -7035,7 +7043,7 @@ } }, close: function() { - var i, _i, _len, _ref; + var post, _i, _len, _ref; if (QR.req) { QR.abort(); @@ -7051,10 +7059,10 @@ if (Conf['QR Shortcut']) { $.toggleClass($('.qr-shortcut'), 'disabled'); } - _ref = QR.posts; + _ref = QR.posts.splice(0, QR.posts.length, new QR.post(true)); for (_i = 0, _len = _ref.length; _i < _len; _i++) { - i = _ref[_i]; - QR.posts[0].rm(); + post = _ref[_i]; + post["delete"](); } QR.cooldown.auto = false; return QR.status(); @@ -7120,12 +7128,13 @@ return QR.notifications = []; }, status: function() { - var disabled, status, value; + var disabled, status, thread, value; if (!QR.nodes) { return; } - if (g.DEAD) { + thread = QR.posts[0].thread; + if (thread !== 'new' && g.threads["" + g.BOARD + "." + thread].isDead) { value = 404; disabled = true; QR.cooldown.auto = false; @@ -7379,7 +7388,7 @@ } }, quote: function(e) { - var OP, caretPos, com, index, post, range, s, sel, selectionRoot, text, thread, _ref; + var caretPos, com, index, post, range, s, sel, text, thread, _ref; if (e != null) { e.preventDefault(); @@ -7388,11 +7397,9 @@ return; } sel = d.getSelection(); - selectionRoot = $.x('ancestor::div[contains(@class,"postContainer")][1]', sel.anchorNode); post = Get.postFromNode(this); - OP = Get.contextFromLink(this).thread.OP; text = ">>" + post + "\n"; - if ((s = sel.toString().trim()) && post.nodes.root === selectionRoot) { + if ((s = sel.toString().trim()) && post === Get.postFromNode(sel.anchorNode)) { s = s.replace(/\n/g, '\n>'); text += ">" + s + "\n"; } @@ -7405,7 +7412,7 @@ } _ref = QR.nodes, com = _ref.com, thread = _ref.thread; if (!com.value) { - thread.value = OP.ID; + thread.value = Get.contextFromNode(this).thread; } thread.nextElementSibling.firstElementChild.textContent = thread.options[thread.selectedIndex].textContent; caretPos = com.selectionStart; @@ -7477,7 +7484,7 @@ fileInput: function(files) { var file, length, max, post, _i, _len; - if (this instanceof Element) { + if (files instanceof Event) { files = __slice.call(this.files); QR.nodes.fileInput.value = null; } @@ -7580,7 +7587,7 @@ _Class.prototype.rm = function() { var index; - $.rm(this.nodes.el); + this["delete"](); index = QR.posts.indexOf(this); if (QR.posts.length === 1) { new QR.post(true); @@ -7589,9 +7596,11 @@ (QR.posts[index - 1] || QR.posts[index + 1]).select(); } QR.posts.splice(index, 1); - if (!window.URL) { - return; - } + return QR.status(); + }; + + _Class.prototype["delete"] = function() { + $.rm(this.nodes.el); return URL.revokeObjectURL(this.URL); }; @@ -7651,21 +7660,23 @@ }; _Class.prototype.save = function(input) { - var value, _ref; + var name, _ref; if (input.type === 'checkbox') { this.spoiler = input.checked; return; } - value = input.value; - this[input.dataset.name] = value; - if (input.nodeName !== 'TEXTAREA') { - return; - } - this.nodes.span.textContent = value; - QR.characterCount(); - if (QR.cooldown.auto && this === QR.posts[0] && (0 < (_ref = QR.cooldown.seconds) && _ref <= 5)) { - return QR.cooldown.auto = false; + name = input.dataset.name; + this[name] = input.value; + switch (name) { + case 'thread': + return QR.status(); + case 'com': + this.nodes.span.textContent = this.com; + QR.characterCount(); + if (QR.cooldown.auto && this === QR.posts[0] && (0 < (_ref = QR.cooldown.seconds) && _ref <= 5)) { + return QR.cooldown.auto = false; + } } }; @@ -7689,9 +7700,7 @@ if (QR.spoiler) { this.nodes.label.hidden = false; } - if (window.URL) { - URL.revokeObjectURL(this.URL); - } + URL.revokeObjectURL(this.URL); this.showFileData(); if (!/^image/.test(file.type)) { this.nodes.el.style.backgroundImage = null; @@ -7700,22 +7709,10 @@ return this.setThumbnail(); }; - _Class.prototype.setThumbnail = function(fileURL) { - var img, reader, + _Class.prototype.setThumbnail = function() { + var fileURL, img, _this = this; - if (!window.URL) { - if (!fileURL) { - reader = new FileReader(); - reader.onload = function(e) { - return _this.setThumbnail(e.target.result); - }; - reader.readAsDataURL(this.file); - return; - } - } else { - fileURL = URL.createObjectURL(this.file); - } img = $.el('img'); img.onload = function() { var applyBlob, cv, data, height, i, l, s, ui8a, width, _i; @@ -7726,9 +7723,7 @@ } height = img.height, width = img.width; if (height < s || width < s) { - if (window.URL) { - _this.URL = fileURL; - } + _this.URL = fileURL; _this.nodes.el.style.backgroundImage = "url(" + _this.URL + ")"; return; } @@ -7743,11 +7738,6 @@ cv.height = img.height = height; cv.width = img.width = width; cv.getContext('2d').drawImage(img, 0, 0, width, height); - if (!window.URL) { - _this.nodes.el.style.backgroundImage = "url(" + (cv.toDataURL()) + ")"; - delete _this.URL; - return; - } URL.revokeObjectURL(fileURL); applyBlob = function(blob) { _this.URL = URL.createObjectURL(blob); @@ -7767,6 +7757,7 @@ type: 'image/png' })); }; + fileURL = URL.createObjectURL(this.file); return img.src = fileURL; }; @@ -7779,9 +7770,6 @@ this.nodes.label.hidden = true; } this.showFileData(); - if (!window.URL) { - return; - } return URL.revokeObjectURL(this.URL); }; @@ -7842,12 +7830,11 @@ _Class.prototype.drop = function() { var el, index, newIndex, oldIndex, post; - el = $('.drag', this.parentNode); - $.rmClass(el, 'drag'); $.rmClass(this, 'over'); if (!this.draggable) { return; } + el = $('.drag', this.parentNode); index = function(el) { return __slice.call(el.parentNode.children).indexOf(el); }; @@ -7855,7 +7842,8 @@ newIndex = index(this); (oldIndex < newIndex ? $.after : $.before)(this, el); post = QR.posts.splice(oldIndex, 1)[0]; - return QR.posts.splice(newIndex, 0, post); + QR.posts.splice(newIndex, 0, post); + return QR.status(); }; return _Class; @@ -7874,7 +7862,7 @@ }), this.ready.bind(this)); }, ready: function() { - var imgContainer, input, observer, setLifetime, + var imgContainer, input, setLifetime, _this = this; setLifetime = function(e) { @@ -7900,14 +7888,9 @@ img: imgContainer.firstChild, input: input }; - if (window.MutationObserver) { - observer = new MutationObserver(this.load.bind(this)); - observer.observe(this.nodes.challenge, { - childList: true - }); - } else { - $.on(this.nodes.challenge, 'DOMNodeInserted', this.load.bind(this)); - } + new MutationObserver(this.load.bind(this)).observe(this.nodes.challenge, { + childList: true + }); $.on(imgContainer, 'click', this.reload.bind(this)); $.on(input, 'keydown', this.keydown.bind(this)); $.on(input, 'focus', function() { @@ -7916,8 +7899,11 @@ $.on(input, 'blur', function() { return $.rmClass(QR.nodes.el, 'focus'); }); - $.get('captchas', [], function(item) { - return _this.sync(item['captchas']); + $.get('captchas', [], function(_arg) { + var captchas; + + captchas = _arg.captchas; + return _this.sync(captchas); }); $.sync('captchas', this.sync); this.reload(); @@ -7925,7 +7911,7 @@ return $.after(QR.nodes.dumpList.parentElement, [imgContainer, input]); }, sync: function(captchas) { - this.captchas = captchas; + QR.captcha.captchas = captchas; return QR.captcha.count(); }, getOne: function() { @@ -8076,7 +8062,6 @@ QR.mimeTypes = mimeTypes.split(', '); QR.mimeTypes.push(''); nodes.fileInput.max = $('input[name=MAX_FILE_SIZE]').value; - nodes.fileInput.accept = "text/*, " + mimeTypes; QR.spoiler = !!$('input[name=spoiler]'); if (QR.spoiler) { $.addClass(QR.nodes.el, 'has-spoiler'); @@ -8347,16 +8332,12 @@ post: post, isReply: isReply }); - if (threadID === postID) { - URL = "/" + g.BOARD + "/res/" + threadID; - } else if (g.VIEW === 'index' && !QR.cooldown.auto && Conf['Open Post in New Tab']) { - URL = "/" + g.BOARD + "/res/" + threadID + "#p" + postID; - } + URL = threadID === postID ? "/" + g.BOARD + "/res/" + threadID : g.VIEW === 'index' && !QR.cooldown.auto && Conf['Open Post in New Tab'] ? "/" + g.BOARD + "/res/" + threadID + "#p" + postID : void 0; if (URL) { if (Conf['Open Post in New Tab']) { - $.open("/" + g.BOARD + "/res/" + threadID); + $.open(URL); } else { - window.location = "/" + g.BOARD + "/res/" + threadID; + window.location = URL; } } return QR.status(); @@ -8733,7 +8714,7 @@ id: 'ihover', src: post.file.URL }); - el.setAttribute('data-fullid', post.fullID); + el.dataset.fullID = post.fullID; $.add(Header.hover, el); UI.hover({ root: this, @@ -8753,7 +8734,7 @@ if (!doc.contains(this)) { return; } - post = g.posts[this.dataset.fullid]; + post = g.posts[this.dataset.fullID]; src = this.src.split('/'); if (src[2] === 'images.4chan.org') { URL = Redirect.to('file', { @@ -8883,6 +8864,78 @@ } }; + Sauce = { + init: function() { + var err, link, links, _i, _len, _ref; + + if (g.VIEW === 'catalog' || !Conf['Sauce']) { + return; + } + links = []; + _ref = Conf['sauces'].split('\n'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + link = _ref[_i]; + try { + if (link[0] !== '#') { + links.push(this.createSauceLink(link.trim())); + } + } catch (_error) { + err = _error; + } + } + if (!links.length) { + return; + } + this.links = links; + this.link = $.el('a', { + target: '_blank' + }); + return Post.prototype.callbacks.push({ + name: 'Sauce', + cb: this.node + }); + }, + createSauceLink: function(link) { + var m, text; + + link = link.replace(/(%(T?URL|MD5|board)|\$[1-4])/ig, function(parameter) { + switch (parameter) { + case '%TURL': + case '$1': + return "' + encodeURIComponent(post.file.thumbURL) + '"; + case '%URL': + case '$2': + return "' + encodeURIComponent(post.file.URL) + '"; + case '%MD5': + case '$3': + return "' + encodeURIComponent(post.file.MD5) + '"; + case '%board': + case '$4': + return "' + encodeURIComponent(post.board) + '"; + default: + return parameter; + } + }); + text = (m = link.match(/;text:(.+)$/)) ? m[1] : link.match(/(\w+)\.\w+\//)[1]; + link = link.replace(/;text:.+$/, ''); + return Function('post', 'a', "a.href = '" + link + "';\na.textContent = '" + text + "';\nreturn a;"); + }, + node: function() { + var link, nodes, _i, _len, _ref; + + if (this.isClone || !this.file) { + return; + } + nodes = []; + _ref = Sauce.links; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + link = _ref[_i]; + nodes.push($.tn('\u00A0'), link(this, Sauce.link.cloneNode(true))); + } + return $.add(this.file.info, nodes); + } + }; + ArchiveLink = { init: function() { var div, entry, type, _i, _len, _ref; @@ -9023,8 +9076,8 @@ return; } $.off(this, 'click', DeleteLink["delete"]); - this.textContent = "Deleting " + this.textContent + "..."; fileOnly = $.hasClass(this, 'delete-file'); + this.textContent = "Deleting " + (fileOnly ? 'file' : 'post') + "..."; form = { mode: 'usrdel', onlyimgdel: fileOnly, @@ -9144,39 +9197,29 @@ node: function() { var button; - button = Menu.makeButton(this); if (this.isClone) { - $.replace($('.menu-button', this.nodes.info), button); - return; + button = $('.menu-button', this.nodes.info); + } else { + button = Menu.makeButton(this); + $.add(this.nodes.info, [$.tn('\u00A0'), button]); } - return $.add(this.nodes.info, [$.tn('\u00A0'), button]); + return $.on(button, 'click', Menu.toggle); }, makeButton: (function() { var a; a = null; - return function(post) { - var clone; - + return function() { a || (a = $.el('a', { className: 'menu-button brackets-wrap', innerHTML: '', href: 'javascript:;' })); - clone = a.cloneNode(true); - clone.setAttribute('data-postid', post.fullID); - if (post.isClone) { - clone.setAttribute('data-clone', true); - } - $.on(clone, 'click', Menu.toggle); - return clone; + return a.cloneNode(true); }; })(), toggle: function(e) { - var post; - - post = this.dataset.clone ? Get.postFromNode(this) : g.posts[this.dataset.postid]; - return Menu.menu.toggle(e, this, post); + return Menu.menu.toggle(e, this, Get.postFromNode(this)); } }; @@ -9609,7 +9652,7 @@ This saves bandwidth for both the user and the servers and avoid unnecessary computation. */ - _ref = [0, 304].contains(req.status) ? [null, null] : ["" + req.statusText + " (" + req.status + ")", 'warning'], text = _ref[0], klass = _ref[1]; + _ref = req.status === 304 ? [null, null] : ["" + req.statusText + " (" + req.status + ")", 'warning'], text = _ref[0], klass = _ref[1]; ThreadUpdater.set('status', text, klass); } if (ThreadUpdater.postID) { @@ -10006,23 +10049,21 @@ } }, scroll: function() { - var checkPosition, hash, onload, post, posts, prevID, root; + var checkPosition, hash, onload, post, posts, root; if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) { return; } if (Unread.posts.length) { - prevID = 0; - while (root = $.x('preceding-sibling::div[contains(@class,"postContainer")][1]', Unread.posts[0].nodes.root)) { - post = Get.postFromRoot(root); - if (prevID === post.ID) { - break; - } - prevID = post.ID; - if (!post.isHidden) { + post = Unread.posts[0]; + while (root = $.x('preceding-sibling::div[contains(@class,"replyContainer")][1]', post.nodes.root)) { + if (!(post = Get.postFromRoot(root)).isHidden) { break; } } + if (!root) { + return; + } onload = function() { if (checkPosition(root)) { return root.scrollIntoView(false); @@ -10212,7 +10253,7 @@ post: {}, file: {}, init: function() { - var archive, arr, boardID, data, id, name, type, _i, _len, _ref, _ref1, _ref2, _ref3; + var archive, arr, boardID, data, id, name, type, _ref, _ref1, _ref2, _results; _ref = Conf['selectedArchives']; for (boardID in _ref) { @@ -10233,22 +10274,32 @@ } } _ref2 = Redirect.archives; + _results = []; for (name in _ref2) { archive = _ref2[name]; - _ref3 = archive.boards; - for (_i = 0, _len = _ref3.length; _i < _len; _i++) { - boardID = _ref3[_i]; - if (!(boardID in Redirect.thread)) { - Redirect.thread[boardID] = archive; + _results.push((function() { + var _i, _len, _ref3, _results1; + + _ref3 = archive.boards; + _results1 = []; + for (_i = 0, _len = _ref3.length; _i < _len; _i++) { + boardID = _ref3[_i]; + if (!(boardID in Redirect.thread)) { + Redirect.thread[boardID] = archive; + } + if (!(boardID in Redirect.post || archive.software !== 'foolfuuka')) { + Redirect.post[boardID] = archive; + } + if (!(boardID in Redirect.file || !archive.files.contains(boardID))) { + _results1.push(Redirect.file[boardID] = archive); + } else { + _results1.push(void 0); + } } - if (!(boardID in Redirect.post || archive.software !== 'foolfuuka')) { - Redirect.post[boardID] = archive; - } - if (!(boardID in Redirect.file || !archive.files.contains(boardID))) { - Redirect.file[boardID] = archive; - } - } + return _results1; + })()); } + return _results; }, archives: { 'Foolz': { @@ -10256,7 +10307,7 @@ 'http': false, 'https': true, 'software': 'foolfuuka', - 'boards': ['a', 'co', 'gd', 'jp', 'm', 'q', 'sp', 'tg', 'tv', 'v', 'vg', 'vp', 'vr', 'wsg'], + 'boards': ['a', 'co', 'gd', 'jp', 'm', 'q', 'sp', 'tg', 'tv', 'vg', 'vp', 'vr', 'wsg'], 'files': ['a', 'gd', 'jp', 'm', 'q', 'tg', 'vg', 'vp', 'vr', 'wsg'] }, 'NSFW Foolz': { @@ -10290,25 +10341,17 @@ 'boards': ['c', 'w', 'wg'], 'files': ['c', 'w', 'wg'] }, - 'Love is Over': { - 'domain': 'loveisover.me', - 'http': true, - 'https': true, - 'software': 'foolfuuka', - 'boards': ['d', 'h', 'v'], - 'files': ['d', 'h', 'v'] - }, 'Foolz a Shit': { 'domain': 'archive.foolzashit.com', 'http': true, 'https': true, 'software': 'foolfuuka', - 'boards': ['adv', 'asp', 'cm', 'e', 'i', 'lgbt', 'n', 'o', 'p', 'pol', 's', 's4s', 't', 'trv', 'y'], - 'files': ['adv', 'asp', 'cm', 'e', 'i', 'lgbt', 'n', 'o', 'p', 's', 's4s', 't', 'trv', 'y'] + 'boards': ['adv', 'asp', 'cm', 'i', 'lgbt', 'n', 'o', 'p', 's4s', 't', 'trv'], + 'files': ['adv', 'asp', 'cm', 'i', 'lgbt', 'n', 'o', 'p', 's4s', 't', 'trv'] }, 'Install Gentoo': { 'domain': 'archive.installgentoo.net', - 'http': true, + 'http': false, 'https': true, 'software': 'fuuka', 'boards': ['diy', 'g', 'sci'], @@ -10336,6 +10379,14 @@ 'software': 'fuuka', 'boards': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'tg', 'vr'], 'files': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'vr'] + }, + 'worldathleticproject': { + 'domain': 'fuuka.worldathleticproject.org', + 'http': true, + 'https': true, + 'software': 'foolfuuka', + 'boards': ['e', 'h', 'p', 's', 'u'], + 'files': ['e', 'h', 'p', 's', 'u'] } }, to: function(dest, data) { @@ -12721,13 +12772,13 @@ } break; case Conf['Next thread']: - if (g.VIEW === 'thread') { + if (g.VIEW !== 'index') { return; } Nav.scroll(+1); break; case Conf['Previous thread']: - if (g.VIEW === 'thread') { + if (g.VIEW !== 'index') { return; } Nav.scroll(-1); @@ -12997,10 +13048,9 @@ _ref = Nav.getThread(true), threads = _ref[0], thread = _ref[1], i = _ref[2], rect = _ref[3], topMargin = _ref[4]; top = rect.top - topMargin; - if (!((delta === -1 && Math.ceil(top) < 0) || (delta === +1 && top > 1))) { - i += delta; + if ((delta === -1 && top > -5) || (delta === +1 && top < 5)) { + top = ((_ref1 = threads[i + delta]) != null ? _ref1.getBoundingClientRect().top : void 0) - topMargin; } - top = ((_ref1 = threads[i]) != null ? _ref1.getBoundingClientRect().top : void 0) - topMargin; return window.scrollBy(0, top); } }; @@ -13147,80 +13197,6 @@ } }; - Sauce = { - init: function() { - var err, link, links, _i, _len, _ref; - - if (g.VIEW === 'catalog' || !Conf['Sauce']) { - return; - } - links = []; - _ref = Conf['sauces'].split('\n'); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - link = _ref[_i]; - if (link[0] === '#') { - continue; - } - try { - links.push(this.createSauceLink(link.trim())); - } catch (_error) { - err = _error; - continue; - } - } - if (!links.length) { - return; - } - this.links = links; - this.link = $.el('a', { - target: '_blank' - }); - return Post.prototype.callbacks.push({ - name: 'Sauce', - cb: this.node - }); - }, - createSauceLink: function(link) { - var m, text; - - link = link.replace(/(%(T?URL|MD5|board)|\$[1-4])/ig, function(parameter) { - switch (parameter) { - case '%TURL': - case '$1': - return "' + encodeURIComponent(post.file.thumbURL) + '"; - case '%URL': - case '$2': - return "' + encodeURIComponent(post.file.URL) + '"; - case '%MD5': - case '$3': - return "' + encodeURIComponent(post.file.MD5) + '"; - case '%board': - case '$4': - return "' + encodeURIComponent(post.board) + '"; - default: - return parameter; - } - }); - text = (m = link.match(/;text:(.+)$/)) ? m[1] : link.match(/(\w+)\.\w+\//)[1]; - link = link.replace(/;text:.+$/, ''); - return Function('post', 'a', "a.href = '" + link + "';\na.textContent = '" + text + "';\nreturn a;"); - }, - node: function() { - var link, nodes, _i, _len, _ref; - - if (this.isClone || !this.file) { - return; - } - nodes = []; - _ref = Sauce.links; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - link = _ref[_i]; - nodes.push($.tn('\u00A0'), link(this, Sauce.link.cloneNode(true))); - } - return $.add(this.file.info, nodes); - } - }; - Time = { init: function() { if (g.VIEW === 'catalog' || !Conf['Time Formatting']) { @@ -13353,7 +13329,9 @@ el = $.el('span', { innerHTML: "appchan x has been updated to version " + g.VERSION + "." }); - new Notification('info', el, 30); + if (Conf['Show Updated Notifications']) { + new Notification('info', el, 30); + } } else { $.on(d, '4chanXInitFinished', Settings.open); } @@ -13666,7 +13644,7 @@ $.add(div, ta); return; } - return div.innerHTML = "
Filter is disabled.

\nUse regular expressions, one per line.
\nLines starting with a # will be ignored.
\nFor example, /weeaboo/i will filter posts containing the string `weeaboo`, case-insensitive.
\nMD5 filtering uses exact string matching, not regular expressions.\n

"; + return div.innerHTML = "
Filter is disabled.

\nUse regular expressions, one per line.
\nLines starting with a # will be ignored.
\nFor example, /weeaboo/i will filter posts containing the string `weeaboo`, case-insensitive.
\nMD5 filtering uses exact string matching, not regular expressions.\n

"; }, sauce: function(section) { var ta; @@ -14667,7 +14645,7 @@ return $.ready(Main.initReady); }, initReady: function() { - var board, boardChild, err, errors, href, passLink, posts, styleSelector, thread, threadChild, threads, _i, _j, _len, _len1, _ref, _ref1; + var board, err, errors, href, passLink, postRoot, posts, styleSelector, thread, threadRoot, threads, _i, _j, _len, _len1, _ref, _ref1; if (d.title === '4chan - 404 Not Found') { if (Conf['404 Redirect'] && g.VIEW === 'thread') { @@ -14683,29 +14661,23 @@ if (board = $('.board')) { threads = []; posts = []; - _ref = board.children; + _ref = $$('.board > .thread', board); for (_i = 0, _len = _ref.length; _i < _len; _i++) { - boardChild = _ref[_i]; - if (!$.hasClass(boardChild, 'thread')) { - continue; - } - thread = new Thread(boardChild.id.slice(1), g.BOARD); + threadRoot = _ref[_i]; + thread = new Thread(+threadRoot.id.slice(1), g.BOARD); threads.push(thread); - _ref1 = boardChild.children; + _ref1 = $$('.thread > .postContainer', threadRoot); for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - threadChild = _ref1[_j]; - if (!$.hasClass(threadChild, 'postContainer')) { - continue; - } + postRoot = _ref1[_j]; try { - posts.push(new Post(threadChild, thread, g.BOARD)); + posts.push(new Post(postRoot, thread, g.BOARD)); } catch (_error) { err = _error; if (!errors) { errors = []; } errors.push({ - message: "Parsing of Post No." + (threadChild.id.match(/\d+/)) + " failed. Post will be skipped.", + message: "Parsing of Post No." + (postRoot.id.match(/\d+/)) + " failed. Post will be skipped.", error: err }); } @@ -14893,7 +14865,7 @@ var _ref; if (!('thisPageIsLegit' in Main)) { - Main.thisPageIsLegit = location.hostname === 'boards.4chan.org' && !$('link[href*="favicon-status.ico"]', d.head) && ((_ref = d.title) !== '4chan - Temporarily Offline' && _ref !== '4chan - Error'); + Main.thisPageIsLegit = location.hostname === 'boards.4chan.org' && !$('link[href*="favicon-status.ico"]', d.head) && ((_ref = d.title) !== '4chan - Temporarily Offline' && _ref !== '4chan - Error' && _ref !== '504 Gateway Time-out'); } return Main.thisPageIsLegit; } diff --git a/html/Monitoring/ThreadStats.html b/html/Monitoring/ThreadStats.html new file mode 100644 index 000000000..f6d932e43 --- /dev/null +++ b/html/Monitoring/ThreadStats.html @@ -0,0 +1,3 @@ +
+ ... / ... / ... +
diff --git a/html/Posting/QR.html b/html/Posting/QR.html new file mode 100644 index 000000000..b34fb36b3 --- /dev/null +++ b/html/Posting/QR.html @@ -0,0 +1,38 @@ +
+ + + + × +
+
+
+ + + + +
+
+
+ + +
+
+ + +
+
+ + + + No selected file + + + × + +
+ +
+ + + diff --git a/package.json b/package.json index d5631b88a..21b0900d3 100644 --- a/package.json +++ b/package.json @@ -20,15 +20,15 @@ }, "devDependencies": { "grunt": "~0.4.1", - "grunt-bump": "~0.0.2", - "grunt-concurrent": "~0.2.0", - "grunt-contrib-clean": "~0.4.1", + "grunt-bump": "~0.0.11", + "grunt-concurrent": "~0.3.0", + "grunt-contrib-clean": "~0.5.0", "grunt-contrib-coffee": "~0.7.0", - "grunt-contrib-compress": "~0.5.1", + "grunt-contrib-compress": "~0.5.2", "grunt-contrib-concat": "~0.3.0", "grunt-contrib-copy": "~0.4.1", - "grunt-contrib-watch": "~0.4.4", - "grunt-shell": "~0.2.2" + "grunt-contrib-watch": "~0.5.0", + "grunt-shell": "~0.3.1" }, "repository": { "type": "git", diff --git a/src/Archive/Redirect.coffee b/src/Archive/Redirect.coffee index e9b5256b5..8cbdb0ff5 100644 --- a/src/Archive/Redirect.coffee +++ b/src/Archive/Redirect.coffee @@ -21,7 +21,6 @@ Redirect = Redirect.post[boardID] = archive unless boardID of Redirect.file or !archive.files.contains boardID Redirect.file[boardID] = archive - return archives: 'Foolz': @@ -29,7 +28,7 @@ Redirect = 'http': false 'https': true 'software': 'foolfuuka' - 'boards': ['a', 'co', 'gd', 'jp', 'm', 'q', 'sp', 'tg', 'tv', 'v', 'vg', 'vp', 'vr', 'wsg'] + 'boards': ['a', 'co', 'gd', 'jp', 'm', 'q', 'sp', 'tg', 'tv', 'vg', 'vp', 'vr', 'wsg'] 'files': ['a', 'gd', 'jp', 'm', 'q', 'tg', 'vg', 'vp', 'vr', 'wsg'] 'NSFW Foolz': @@ -63,25 +62,17 @@ Redirect = 'boards': ['c', 'w', 'wg'] 'files': ['c', 'w', 'wg'] - 'Love is Over': - 'domain': 'loveisover.me' - 'http': true - 'https': true - 'software': 'foolfuuka' - 'boards': ['d', 'h', 'v'] - 'files': ['d', 'h', 'v'] - 'Foolz a Shit': 'domain': 'archive.foolzashit.com' 'http': true 'https': true 'software': 'foolfuuka' - 'boards': ['adv', 'asp', 'cm', 'e', 'i', 'lgbt', 'n', 'o', 'p', 'pol', 's', 's4s', 't', 'trv', 'y'] - 'files': ['adv', 'asp', 'cm', 'e', 'i', 'lgbt', 'n', 'o', 'p', 's', 's4s', 't', 'trv', 'y'] + 'boards': ['adv', 'asp', 'cm', 'i', 'lgbt', 'n', 'o', 'p', 's4s', 't', 'trv'] + 'files': ['adv', 'asp', 'cm', 'i', 'lgbt', 'n', 'o', 'p', 's4s', 't', 'trv'] 'Install Gentoo': 'domain': 'archive.installgentoo.net' - 'http': true + 'http': false 'https': true 'software': 'fuuka' 'boards': ['diy', 'g', 'sci'] @@ -109,6 +100,14 @@ Redirect = 'software': 'fuuka' 'boards': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'tg', 'vr'] 'files': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'vr'] + + 'worldathleticproject': + 'domain': 'fuuka.worldathleticproject.org' + 'http': true + 'https': true + 'software': 'foolfuuka' + 'boards': ['e', 'h', 'p', 's', 'u'] + 'files': ['e', 'h', 'p', 's', 'u'] to: (dest, data) -> archive = (if dest is 'search' then Redirect.thread else Redirect[dest])[data.boardID] diff --git a/src/Filtering/Filter.coffee b/src/Filtering/Filter.coffee index ca11455cb..3da882a11 100644 --- a/src/Filtering/Filter.coffee +++ b/src/Filtering/Filter.coffee @@ -209,7 +209,7 @@ Filter = el = $.el 'a', href: 'javascript:;' textContent: text - el.setAttribute 'data-type', type + el.dataset.type = type $.on el, 'click', Filter.menu.makeFilter return { diff --git a/src/Filtering/ThreadHiding.coffee b/src/Filtering/ThreadHiding.coffee index ef7e09108..977f0d1a7 100644 --- a/src/Filtering/ThreadHiding.coffee +++ b/src/Filtering/ThreadHiding.coffee @@ -113,7 +113,7 @@ ThreadHiding = className: "#{type}-thread-button" innerHTML: " #{if type is 'hide' then '-' else '+'} " href: 'javascript:;' - a.setAttribute 'data-fullid', thread.fullID + a.dataset.fullID = thread.fullID $.on a, 'click', ThreadHiding.toggle a @@ -134,7 +134,7 @@ ThreadHiding = toggle: (thread) -> unless thread instanceof Thread - thread = g.threads[@dataset.fullid] + thread = g.threads[@dataset.fullID] if thread.isHidden ThreadHiding.show thread else diff --git a/src/General/Build.coffee b/src/General/Build.coffee index 6d87269a1..4f4453e6d 100644 --- a/src/General/Build.coffee +++ b/src/General/Build.coffee @@ -108,12 +108,12 @@ Build = capcodeStart = '' capcode = '' - flag = - if flagCode - " #{flagCode}" - else - '' + flag = unless flagCode + '' + else if boardID is 'pol' + " #{flagCode}" + else + " " if file?.isDeleted fileHTML = if isOP diff --git a/src/General/Get.coffee b/src/General/Get.coffee index a66bce292..a5c1a54c1 100644 --- a/src/General/Get.coffee +++ b/src/General/Get.coffee @@ -19,7 +19,7 @@ Get = if index then post.clones[index] else post postFromNode: (root) -> Get.postFromRoot $.x 'ancestor::div[contains(@class,"postContainer")][1]', root - contextFromLink: (quotelink) -> + contextFromNode: (quotelink) -> Get.postFromRoot $.x 'ancestor::div[parent::div[@class="thread"]][1]', quotelink postDataFromLink: (link) -> if link.hostname is 'boards.4chan.org' @@ -28,9 +28,8 @@ Get = threadID = path[3] postID = link.hash[2..] else # resurrected quote - boardID = link.dataset.boardid - threadID = link.dataset.threadid or 0 - postID = link.dataset.postid + {boardID, threadID, postID} = link.dataset + threadID or= 0 return { boardID: boardID threadID: +threadID @@ -185,7 +184,7 @@ Get = # quotes .replace /((>){2}(>\/[a-z\d]+\/)?\d+)/g, '$1' - threadID = data.thread_num + threadID = +data.thread_num o = # id postID: "#{postID}" diff --git a/src/General/Globals.coffee b/src/General/Globals.coffee index 0cd9e06a3..268183158 100644 --- a/src/General/Globals.coffee +++ b/src/General/Globals.coffee @@ -1,6 +1,7 @@ -editTheme = {} # Currently editted theme. -editMascot = {} # Which mascot we're editting. -userNavigation = {} # ... + +editTheme = {} +editMascot = {} +userNavigation = {} Conf = {} c = console d = document @@ -3074,4 +3075,4 @@ textarea, border: 1px solid #111 !important; background-color: #933; } -""" \ No newline at end of file +""" diff --git a/src/General/Header.coffee b/src/General/Header.coffee index cb2ba7aa7..33b3b1da7 100644 --- a/src/General/Header.coffee +++ b/src/General/Header.coffee @@ -55,7 +55,7 @@ Header = return unless Main.isThisPageLegit() # Wait for #boardNavMobile instead of #boardNavDesktop, # it might be incomplete otherwise. - $.asap (-> $.id('boardNavMobile') or d.readyState in ['interactive', 'complete']), @setBoardList + $.asap (-> $.id('boardNavMobile') or d.readyState isnt 'loading'), Header.setBoardList $.prepend d.body, @bar $.add d.body, Header.hover @setBarPosition Conf['Bottom Header'] @@ -106,7 +106,7 @@ Header = list = $ '#custom-board-list', Header.bar $.rmAll list return unless text - as = $$('#full-board-list a', Header.bar) + as = $$ '#full-board-list a[title]', Header.bar nodes = text.match(/[\w@]+((-(all|title|replace|full|index|catalog|url:"[^"]+[^"]"|text:"[^"]+")|\,"[^"]+[^"]"))*|[^\w@]+/g).map (t) -> if /^[^\w@]/.test t return $.tn t @@ -141,7 +141,7 @@ Header = a.textContent if m = t.match /-(index|catalog)/ - a.setAttribute 'data-only', m[1] + a.dataset.only = m[1] a.href = "//boards.4chan.org/#{board}/" if m[1] is 'catalog' a.href += 'catalog' diff --git a/src/General/Main.coffee b/src/General/Main.coffee index 9e72326c1..dbd263591 100644 --- a/src/General/Main.coffee +++ b/src/General/Main.coffee @@ -191,20 +191,18 @@ Main = threads = [] posts = [] - for boardChild in board.children - continue unless $.hasClass boardChild, 'thread' - thread = new Thread boardChild.id[1..], g.BOARD + for threadRoot in $$ '.board > .thread', board + thread = new Thread +threadRoot.id[1..], g.BOARD threads.push thread - for threadChild in boardChild.children - continue unless $.hasClass threadChild, 'postContainer' + for postRoot in $$ '.thread > .postContainer', threadRoot try - posts.push new Post threadChild, thread, g.BOARD + posts.push new Post postRoot, thread, g.BOARD catch err # Skip posts that we failed to parse. unless errors errors = [] errors.push - message: "Parsing of Post No.#{threadChild.id.match(/\d+/)} failed. Post will be skipped." + message: "Parsing of Post No.#{postRoot.id.match(/\d+/)} failed. Post will be skipped." error: err Main.handleErrors errors if errors @@ -372,7 +370,7 @@ Main = unless 'thisPageIsLegit' of Main Main.thisPageIsLegit = location.hostname is 'boards.4chan.org' and !$('link[href*="favicon-status.ico"]', d.head) and - d.title not in ['4chan - Temporarily Offline', '4chan - Error'] + d.title not in ['4chan - Temporarily Offline', '4chan - Error', '504 Gateway Time-out'] Main.thisPageIsLegit Main.init() diff --git a/src/General/Settings.coffee b/src/General/Settings.coffee index ba214d8f8..d43d3438e 100644 --- a/src/General/Settings.coffee +++ b/src/General/Settings.coffee @@ -24,7 +24,8 @@ Settings = changelog = '<%= meta.repo %>blob/<%= meta.mainBranch %>/CHANGELOG.md' el = $.el 'span', innerHTML: "<%= meta.name %> has been updated to version #{g.VERSION}." - new Notification 'info', el, 30 + if Conf['Show Updated Notifications'] + new Notification 'info', el, 30 else $.on d, '4chanXInitFinished', Settings.open $.set @@ -427,7 +428,6 @@ Settings = usercss: -> CustomCSS.update() - keybinds: (section) -> section.innerHTML = """ <%= grunt.file.read('src/General/html/Settings/Keybinds.html').replace(/>\s+<').trim() %> diff --git a/src/General/UI.coffee b/src/General/UI.coffee index 5a83b28dc..91beaa2c4 100644 --- a/src/General/UI.coffee +++ b/src/General/UI.coffee @@ -303,13 +303,13 @@ UI = do -> hoverstart = ({root, el, latestEvent, endEvents, asapTest, cb, close}) -> o = { - root: root - el: el - style: el.style - cb: cb + root + el + style: el.style + cb close: close - endEvents: endEvents - latestEvent: latestEvent + endEvents + latestEvent clientHeight: doc.clientHeight clientWidth: doc.clientWidth } @@ -325,6 +325,11 @@ UI = do -> if $.x 'ancestor::div[contains(@class,"inline")][1]', root $.on d, 'keydown', o.hoverend $.on root, 'mousemove', o.hover + <% if (type === 'userscript') { %> + # Workaround for https://github.com/MayhemYDG/4chan-x/issues/377 + o.workaround = (e) -> o.hoverend() unless root.contains e.target + $.on doc, 'mousemove', o.workaround + <% } %> hover = (e) -> @latestEvent = e @@ -355,6 +360,10 @@ UI = do -> $.off @root, @endEvents, @hoverend $.off d, 'keydown', @hoverend $.off @root, 'mousemove', @hover + <% if (type === 'userscript') { %> + # Workaround for https://github.com/MayhemYDG/4chan-x/issues/377 + $.off doc, 'mousemove', @workaround + <% } %> @cb.call @ if @cb diff --git a/src/General/css/style.css b/src/General/css/style.css new file mode 100644 index 000000000..6d418f4d1 --- /dev/null +++ b/src/General/css/style.css @@ -0,0 +1,1057 @@ +/* General */ +.dialog { + box-shadow: 0 1px 2px rgba(0, 0, 0, .15); + border: 1px solid; + display: block; + padding: 0; +} +.captcha-img, +.field { + background-color: #FFF; + border: 1px solid #CCC; + -moz-box-sizing: border-box; + box-sizing: border-box; + color: #333; + font: 13px sans-serif; + outline: none; + transition: color .25s, border-color .25s; + transition: color .25s, border-color .25s; +} +.field::-moz-placeholder, +.field:hover::-moz-placeholder { + color: #AAA !important; + font-size: 13px !important; + opacity: 1.0 !important; +} +.captch-img:hover, +.field:hover { + border-color: #999; +} +.field:hover, .field:focus { + color: #000; +} +.field[disabled] { + background-color: #F2F2F2; + color: #888; +} +.move { + cursor: move; + overflow: hidden; +} +label, .favicon { + cursor: pointer; +} +a[href="javascript:;"] { + text-decoration: none; +} +.warning { + color: red; +} +#boardNavDesktop { + display: none !important; +} +a { + outline: none !important; +} + +/* 4chan style fixes */ +.opContainer, .op { + display: block !important; + overflow: visible !important; +} +[hidden] { + display: none !important; +} + +/* fixed, z-index */ +#overlay, +#fourchanx-settings, +#qp, #ihover, +#navlinks, .fixed #header-bar, +:root.float #updater, +:root.float #thread-stats, +#qr { + position: fixed; +} +#fourchanx-settings { + z-index: 999; +} +#overlay { + z-index: 900; +} +#notifications { + z-index: 70; +} +#qp, #ihover { + z-index: 60; +} +#menu { + z-index: 50; +} +#navlinks, #updater, #thread-stats { + z-index: 40; +} +.fixed #header-bar.autohide { + z-index: 35; +} +#qr { + z-index: 30; +} +#watcher { + z-index: 8; +} +:root.fixed-watcher #watcher { + z-index: 20; +} +.fixed #header-bar { + z-index: 10; +} +/* Header */ +.fixed.top body { + padding-top: 2em; +} +.fixed.bottom body { + padding-bottom: 2em; +} +.fixed #header-bar { + right: 0; + left: 0; + padding: 3px 4px 4px; +} +.fixed.top #header-bar { + top: 0; +} +.fixed.bottom #header-bar { + bottom: 0; +} +#header-bar { + border-width: 0; + transition: all .1s .05s ease-in-out; +} +:root.centered-links #shortcuts { + width: 300px; + text-align: right; +} +:root.centered-links #header-bar { + text-align: center; +} +:root.centered-links #custom-board-list { + position: relative; + left: 150px; +} +.fixed.top #header-bar { + border-bottom-width: 1px; +} +.fixed.bottom #header-bar { + box-shadow: 0 -1px 2px rgba(0, 0, 0, .15); + border-top-width: 1px; +} +.fixed.bottom #header-bar .menu-button i { + border-top: none; + border-bottom: 6px solid; +} +#board-list { + text-align: center; +} +.fixed #header-bar.autohide:not(:hover) { + box-shadow: none; + transition: all .8s .6s cubic-bezier(.55, .055, .675, .19); +} +.fixed.top #header-bar.autohide:not(:hover) { + margin-bottom: -1em; + -webkit-transform: translateY(-100%); + transform: translateY(-100%); +} +.fixed.bottom #header-bar.autohide:not(:hover) { + -webkit-transform: translateY(100%); + transform: translateY(100%); +} +#scroll-marker { + left: 0; + right: 0; + height: 10px; + position: absolute; +} +:root:not(.autohide) #scroll-marker { + pointer-events: none; +} +#header-bar #scroll-marker { + display: none; +} +.fixed #header-bar #scroll-marker { + display: block; +} +.fixed.top #header-bar #scroll-marker { + top: 100%; +} +.fixed.bottom #header-bar #scroll-marker { + bottom: 100%; +} +#header-bar a:not(.entry):not(.close) { + text-decoration: none; + padding: 1px; +} +#header-bar input { + margin: 0; + vertical-align: bottom; +} +#shortcuts:empty { + display: none; +} +.brackets-wrap::before { + content: "\\00a0["; +} +.brackets-wrap::after { + content: "]\\00a0"; +} +.disabled, +.expand-all-shortcut { + opacity: .45; +} +#shortcuts { + float: right; +} +.shortcut { + margin-left: 3px; +} +#navbotright, +#navtopright { + display: none; +} +#toggleMsgBtn { + display: none !important; +} +.current { + font-weight: bold; +} +/* 4chan X link brackets */ +.fourchanx-link::after { + content: "]"; +} +.fourchanx-link::before { + content: "["; +} +/* Notifications */ +#notifications { + position: fixed; + top: 0; + height: 0; + text-align: center; + right: 0; + left: 0; + transition: all .8s .6s cubic-bezier(.55, .055, .675, .19); +} +.fixed.top #header-bar #notifications { + position: absolute; + top: 100%; +} +.notification { + color: #FFF; + font-weight: 700; + text-shadow: 0 1px 2px rgba(0, 0, 0, .5); + box-shadow: 0 1px 2px rgba(0, 0, 0, .15); + border-radius: 2px; + margin: 1px auto; + width: 500px; + max-width: 100%; + position: relative; + transition: all .25s ease-in-out; +} +.notification.error { + background-color: hsla(0, 100%, 38%, .9); +} +.notification.warning { + background-color: hsla(36, 100%, 38%, .9); +} +.notification.info { + background-color: hsla(200, 100%, 38%, .9); +} +.notification.success { + background-color: hsla(104, 100%, 38%, .9); +} +.notification a { + color: white; +} +.notification > .close { + padding: 6px; + top: 0; + right: 5px; + position: absolute; +} +.message { + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 6px 20px; + max-height: 200px; + width: 100%; + overflow: auto; +} + +/* Settings */ +:root.fourchan-x body { + -moz-box-sizing: border-box; + box-sizing: border-box; +} +#overlay { + background-color: rgba(0, 0, 0, .5); + top: 0; + left: 0; + height: 100%; + width: 100%; +} +#fourchanx-settings { + -moz-box-sizing: border-box; + box-sizing: border-box; + box-shadow: 0 0 15px rgba(0, 0, 0, .15); + height: 600px; + max-height: 100%; + width: 900px; + max-width: 100%; + margin: auto; + padding: 3px; + top: 50%; + left: 50%; + -moz-transform: translate(-50%, -50%); + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); +} +#fourchanx-settings > nav { + padding: 2px 2px 0; + height: 15px; +} +#fourchanx-settings > nav a { + text-decoration: underline; +} +#fourchanx-settings > nav a.close { + text-decoration: none; + padding: 2px; +} +.section-container { + overflow: auto; + position: absolute; + top: 2.1em; + right: 5px; + bottom: 5px; + left: 5px; + padding-right: 5px; +} +.sections-list { + padding: 0 3px; + float: left; +} +.credits { + float: right; +} +.tab-selected { + font-weight: 700; +} +.section-sauce ul, +.section-advanced ul { + list-style: none; + margin: 0; +} +.section-sauce ul { + padding: 8px; +} +.section-advanced ul { + padding: 0px; +} +.section-sauce li, +.section-advanced li { + padding-left: 4px; +} +.section-main label { + text-decoration: underline; +} +.section-filter ul { + padding: 0; +} +.section-filter li { + margin: 10px 40px; +} +.section-filter textarea { + height: 500px; +} +.section-sauce textarea { + height: 350px; +} +.section-advanced .field[name="boardnav"] { + width: 100%; +} +.section-advanced textarea { + height: 150px; +} +.section-advanced .archive-cell { + min-width: 160px; + text-align: center; +} +.section-advanced #archive-board-select { + position: absolute; +} +.section-advanced .note { + font-size: 0.8em; + font-style: italic; + margin-left: 10px; +} +.section-advanced .note code { + font-style: normal; + font-size: 11px; +} +.section-keybinds .field { + font-family: monospace; +} +#fourchanx-settings fieldset { + border: 1px solid; + border-radius: 3px; +} +#fourchanx-settings legend { + font-weight: 700; +} +#fourchanx-settings textarea { + font-family: monospace; + min-width: 100%; + max-width: 100%; +} +#fourchanx-settings code { + color: #000; + background-color: #FFF; + padding: 0 2px; +} +.unscroll { + overflow: hidden; +} + +/* Announcement Hiding */ +:root.hide-announcement #globalMessage { + display: none; +} +a.hide-announcement { + float: left; +} + +/* Unread */ +#unread-line { + margin: 0; + border-color: rgb(255,0,0); +} + +/* Thread Updater */ +#updater { + background: none; + border: none; + box-shadow: none; +} +#updater > .move { + padding: 5px 3px 0px; + margin-bottom: -3px; +} +#updater > div:last-child { + text-align: center; +} +#updater input[type=number] { + width: 4em; +} +:root.float #updater { + padding: 0px 3px; +} +.new { + color: limegreen; +} +#update-status.new { + margin-right: 5px; +} +#update-timer { + cursor: pointer; +} + +/* Thread Watcher */ +#watcher { + position: absolute; +} +#watcher { + padding-bottom: 3px; + overflow: hidden; + white-space: nowrap; + min-width: 120px; + max-height: 92%; + overflow-y: auto; +} +:root.fixed-watcher #watcher { + position: fixed; +} +:root:not(.fixed-watcher) #watcher:not(:hover) { + max-height: 210px; + overflow-y: hidden; +} +#watcher > .move { + padding-top: 3px; +} +#watcher > div { + max-width: 250px; + overflow: hidden; + padding-left: 3px; + padding-right: 3px; + text-overflow: ellipsis; +} +#watcher a { + text-decoration: none; +} +#watcher .move>.close { + position: absolute; + right: 0px; + top: 0px; + padding: 0px 4px; +} +.watch-thread-link { + padding-top: 18px; + width: 18px; + height: 0px; + display: inline-block; + background-repeat: no-repeat; + opacity: 0.2; + position: relative; + top: 1px; +} +.watch-thread-link.watched { + opacity: 1; +} + +/* Thread Stats */ +#thread-stats { + background: none; + border: none; + box-shadow: none; +} +:root.float #post-count, :root.float #file-count { + pointer-events: none; +} +:root.float #thread-stats { + padding: 0px 3px; +} + +/* Quote */ +.deadlink { + text-decoration: none !important; +} +.backlink.deadlink:not(.forwardlink), +.quotelink.deadlink:not(.forwardlink) { + text-decoration: underline !important; +} +.inlined { + opacity: .5; +} +#qp input, .forwarded { + display: none; +} +.quotelink.forwardlink, +.backlink.forwardlink { + text-decoration: none; + border-bottom: 1px dashed; +} +.filtered { + text-decoration: underline line-through; +} +:root.hide-backlinks .backlink.filtered { + display: none; +} +.inline { + border: 1px solid; + display: table; + margin: 2px 0; +} +.inline .post { + border: 0 !important; + background-color: transparent !important; + display: table !important; + margin: 0 !important; + padding: 1px 2px !important; +} +#qp > .opContainer::after { + content: ''; + clear: both; + display: table; +} +#qp .post { + border: none; + margin: 0; + padding: 2px 2px 5px; +} +#qp img { + max-height: 80vh; + max-width: 50vw; +} +.qphl { + outline: 2px solid rgba(216, 94, 49, .7); +} +:root.highlight-own .yourPost>.reply, +:root.highlight-you .quotesYou>.reply { + border-left: 2px solid rgba(221,0,0,.5); +} +/* Quote Threading */ +.threadContainer { + margin-left: 20px; + border-left: 1px solid rgba(128,128,128,.3); +} +.threadOP { + clear: both; +} + +/* File */ +.fileText:hover .fntrunc, +.fileText:not(:hover) .fnfull, +.expanded-image > .post > .file > .fileThumb > img[data-md5], +:not(.expanded-image) > .post > .file > .fileThumb > .full-image { + display: none; +} +.expanding { + opacity: .5; +} +:root.fit-height .full-image { + max-height: 100vh; +} +:root.fit-width .full-image { + max-width: 100%; +} +:root.gecko.fit-width .full-image { + width: 100%; +} +#ihover { + -moz-box-sizing: border-box; + box-sizing: border-box; + max-height: 100%; + max-width: 75%; + padding-bottom: 16px; +} +.fappeTyme .thread > .noFile, +.fappeTyme .threadContainer > .noFile { + display: none; +} + +/* Index/Reply Navigation */ +#navlinks { + font-size: 16px; + top: 25px; + right: 10px; +} + +/* Filter */ +.opContainer.filter-highlight { + box-shadow: inset 5px 0 rgba(255, 0, 0, .5); +} +.filter-highlight > .reply { + box-shadow: -5px 0 rgba(255, 0, 0, .5); +} + +/* Spoiler text */ +:root.reveal-spoilers s { + color: white !important; +} + +/* Thread & Reply Hiding */ +.hide-thread-button, +.hide-reply-button { + float: left; + margin-right: 2px; +} +.stub ~ * { + display: none !important; +} +.stub input { + display: inline-block; +} + +/* QR */ +:root.hide-original-post-form #postForm, +:root.hide-original-post-form .postingMode, +:root.hide-original-post-form #togglePostForm, +#qr.autohide:not(.has-focus):not(:hover) > form, +.postingMode ~ #qr select, +#file-n-submit:not(.has-file) #qr-filerm { + display: none; +} +#qr select, +#dump-button, +.remove, +.captcha-img { + cursor: pointer; +} +#qr { + z-index: 20; + position: fixed; + padding: 1px; + border: 1px solid transparent; + min-width: 300px; + border-radius: 3px 3px 0 0; +} +#qrtab { + border-radius: 3px 3px 0 0; +} +#qrtab { + margin-bottom: 1px; +} +#qr .close { + float: right; + padding: 0 3px; +} +#qr .warning { + min-height: 1.6em; + vertical-align: middle; + padding: 0 1px; + border-width: 1px; + border-style: solid; +} +.qr-link-container { + text-align: center; +} +.persona { + width: 248px; + max-width: 100%; + min-width: 100%; +} +#dump-button { + width: 10%; + margin: 0; + margin-right: 4px; + font: 13px sans-serif; + padding: 1px 0px 2px; + opacity: 0.6; +} +.persona .field:not(#dump) { + width: 95px; + min-width: 33.3%; + max-width: 33.3%; +} +#qr textarea.field { + height: 14.8em; + min-height: 9em; +} +#qr.has-captcha textarea.field { + height: 9em; +} +input.field.tripped:not(:hover):not(:focus) { + color: transparent !important; + text-shadow: none !important; +} +#qr textarea { + resize: both; +} +.captcha-img { + margin: 0px; + text-align: center; + background-image: #fff; + font-size: 0px; + min-height: 59px; + min-width: 302px; +} +.captcha-input { + width: 100%; + margin: 1px 0 0; +} +.captcha-input.error:focus { + border-color: rgb(255,0,0) !important; +} +.field { + -moz-box-sizing: border-box; + margin: 0px; + padding: 2px 4px 3px; +} +#qr textarea { + min-width: 100%; +} +#qr [type='submit'] { + width: 25%; + vertical-align: top; +} +:root.webkit #qr [type='submit'] { + height: 24px; +} +/* Fake File Input */ +#qr-filename, +.has-file #qr-no-file { + display: none; +} +#qr-no-file, +.has-file #qr-filename { + display: inline-block; + padding: 0px 4px; + margin-bottom: 2px; + overflow: hidden; + text-overflow: ellipsis; + max-width: 88%; +} +#qr-no-file { + color: #AAA; +} +#qr-filename-container { + -moz-box-sizing: border-box; + display: inline-block; + position: relative; + width: 100px; + min-width: 74.6%; + max-width: 74.6%; + margin-right: 0.4%; + margin-top: 1px; + overflow: hidden; + padding: 2px 1px 0; + height: 22px; +} +#qr-filename-container:hover { + cursor: text; +} +#qr-extras-container { + position: absolute; + right: 0px; +} +#qr-filerm { + margin-right: 2px; + z-index: 2; +} +#file-n-submit { + height: 23px; +} +#qr input[type=file] { + visibility: hidden; + position: absolute; +} +/* Thread Select / Spoiler Label */ +#qr select { + float: right; +} +#qr.has-spoiler .has-file #qr-spoiler-label { + width: 6.7%; + min-width: 6.7%; + max-width: 6.7%; + display: inline-block; + text-align: center; + vertical-align: top; +} +#qr.has-spoiler #file-n-submit:not(.has-file) #qr-spoiler-label { + display: none; +} +#qr.has-spoiler .has-file #qr-filename-container { + max-width: 67.9%; + min-width: 67.9%; +} +#qr-spoiler-label input { + position: relative; + top: 3px; +} +/* Dumping UI */ +.dump #dump-list-container { + display: block; +} +#dump-list-container { + display: none; + position: relative; + overflow-y: hidden; + margin-top: 1px; +} +#dump-list { + overflow-x: auto; + overflow-y: hidden; + white-space: nowrap; + width: 248px; + max-width: 100%; + min-width: 100%; +} +#dump-list:hover { + overflow-x: auto; +} +.qr-preview { + -moz-box-sizing: border-box; + counter-increment: thumbnails; + cursor: move; + display: inline-block; + height: 90px; + width: 90px; + padding: 2px; + opacity: .5; + overflow: hidden; + position: relative; + text-shadow: 0 1px 1px #000; + -moz-transition: opacity .25s ease-in-out; + vertical-align: top; + background-size: cover; +} +.qr-preview:hover, +.qr-preview:focus { + opacity: .9; +} +.qr-preview::before { + content: counter(thumbnails); + color: #fff; + position: absolute; + top: 3px; + right: 3px; + text-shadow: 0 0 3px #000, 0 0 8px #000; +} +.qr-preview#selected { + opacity: 1; +} +.qr-preview.drag { + box-shadow: 0 0 10px rgba(0,0,0,.5); +} +.qr-preview.over { + border-color: #fff; +} +.qr-preview > span { + color: #fff; +} +.remove { + background: none; + color: #e00; + font-weight: 700; + padding: 3px; +} +a:only-of-type > .remove { + display: none; +} +.remove:hover::after { + content: " Remove"; +} +.qr-preview > label { + background: rgba(0,0,0,.5); + color: #fff; + right: 0; + bottom: 0; + left: 0; + position: absolute; + text-align: center; +} +.qr-preview > label > input { + margin: 0; +} +#add-post { + cursor: pointer; + font-size: 2em; + position: absolute; + top: 50%; + right: 10px; + -moz-transform: translateY(-50%); +} +.textarea { + position: relative; +} +:root.webkit .textarea { + margin-bottom: -2px; +} +#char-count { + color: #000; + background: hsla(0, 0%, 100%, .5); + font-size: 8pt; + position: absolute; + bottom: 1px; + right: 1px; + pointer-events: none; +} + +/* Menu */ +.menu-button { + display: inline-block; + position: relative; + cursor: pointer; +} +.menu-button i { + border-top: 6px solid; + border-right: 4px solid transparent; + border-left: 4px solid transparent; + display: inline-block; + margin: 2px; + vertical-align: middle; +} +#menu { + position: fixed; + outline: none; +} +.entry { + border-bottom: 1px solid rgba(0,0,0,.25); + cursor: pointer; + display: block; + outline: none; + padding: 3px 7px; + position: relative; + text-decoration: none; + white-space: nowrap; +} +.left>.entry.has-submenu { + padding-right: 17px !important; +} +.entry:last-child { + border-bottom: 0; +} +.has-submenu::after { + content: ""; + border-left: .5em solid; + border-top: .3em solid transparent; + border-bottom: .3em solid transparent; + display: inline-block; + margin: .3em; + position: absolute; + right: 3px; +} +.left .has-submenu::after { + border-left: 0; + border-right: .5em solid; +} +.submenu { + display: none; + position: absolute; + left: 100%; + top: -1px; +} +.focused .submenu { + display: block; +} +.imp-exp-result { + position: absolute; + text-align: center; + margin: auto; + right: 0px; + left: 0px; + width: 200px; +} +.export, .import { + cursor: pointer; + text-decoration: none !important; +} +/* Link Title Favicons */ +.linkify.YouTube { + background: transparent url('data:image/png;base64,<%= grunt.file.read("src/General/img/links/youtube.png", {encoding: "base64"}) %>') center left no-repeat!important; + padding-left: 18px; +} +.linkify.Vimeo { + background: transparent url('data:image/png;base64,<%= grunt.file.read("src/General/img/links/vimeo.png", {encoding: "base64"}) %>') center left no-repeat!important; + padding-left: 18px; +} +.linkify.SoundCloud { + background: transparent url('data:image/png;base64,<%= grunt.file.read("src/General/img/links/soundcloud.png", {encoding: "base64"}) %>') center left no-repeat!important; + padding-left: 18px; +} +.linkify.audio { + background: transparent url('data:image/png;base64,<%= grunt.file.read("src/General/img/links/audio.png", {encoding: "base64"}) %>') center left no-repeat!important; + padding-left: 18px; +} +.linkify.LiveLeak { + background: transparent url('data:image/png;base64,<%= grunt.file.read("src/General/img/links/liveleak.png", {encoding: "base64"}) %>') center left no-repeat!important; + padding-left: 18px; +} +.linkify.Vocaroo { + background: transparent url('data:image/png;base64,<%= grunt.file.read("src/General/img/links/vocaroo.png", {encoding: "base64"}) %>') center left no-repeat!important; + padding-left: 18px; +} +.linkify.pastebin { + background: transparent url('data:image/png;base64,<%= grunt.file.read("src/General/img/links/pastebin.png", {encoding: "base64"}) %>') center left no-repeat!important; + padding-left: 18px; +} +.linkify.gist { + background: transparent url('data:image/png;base64,<%= grunt.file.read("src/General/img/links/gist.png", {encoding: "base64"}) %>') center left no-repeat!important; + padding-left: 18px; +} +.linkify.image { + background: transparent url('data:image/png;base64,<%= grunt.file.read("src/General/img/links/image.png", {encoding: "base64"}) %>') center left no-repeat!important; + padding-left: 18px; +} +.linkify.InstallGentoo { + background: transparent url('data:image/png;base64,<%= grunt.file.read("src/General/img/links/installgentoo.png", {encoding: "base64"}) %>') center left no-repeat!important; + padding-left: 18px; +} diff --git a/src/General/html/Settings/Filter-guide.html b/src/General/html/Settings/Filter-guide.html index 3e50d37e3..3e78003d2 100644 --- a/src/General/html/Settings/Filter-guide.html +++ b/src/General/html/Settings/Filter-guide.html @@ -1,6 +1,6 @@
Filter is disabled.

- Use regular expressions, one per line.
+ Use regular expressions, one per line.
Lines starting with a # will be ignored.
For example, /weeaboo/i will filter posts containing the string `weeaboo`, case-insensitive.
MD5 filtering uses exact string matching, not regular expressions. @@ -26,4 +26,4 @@ Highlighted OPs will have their threads put on top of board pages by default.
For example: top:yes; or top:no;. - \ No newline at end of file + diff --git a/src/General/lib/$.coffee b/src/General/lib/$.coffee index b64dfab69..c9d50c4ff 100644 --- a/src/General/lib/$.coffee +++ b/src/General/lib/$.coffee @@ -49,7 +49,7 @@ $.id = (id) -> d.getElementById id $.ready = (fc) -> - if d.readyState in ['interactive', 'complete'] + unless d.readyState is 'loading' $.queueTask fc return cb = -> @@ -221,9 +221,7 @@ $.event = (event, detail, root=d) -> $.open = (URL) -> <% if (type === 'userscript') { %> - # XXX fix GM opening file://// for protocol-less URLs. - # https://github.com/greasemonkey/greasemonkey/issues/1719 - GM_openInTab ($.el 'a', href: URL).href + $.open = (URL) -> GM_openInTab URL <% } else { %> window.open URL, '_blank' <% } %> @@ -298,29 +296,21 @@ $.minmax = (value, min, max) -> value ) -$.syncing = {} +$.item = (key, val) -> + item = {} + item[key] = val + item -$.sync = do -> +$.syncing = {} <% if (type === 'crx') { %> +$.sync = do -> chrome.storage.onChanged.addListener (changes) -> for key of changes if cb = $.syncing[key] cb changes[key].newValue return (key, cb) -> $.syncing[key] = cb -<% } else { %> - window.addEventListener 'storage', (e) -> - if cb = $.syncing[e.key] - cb JSON.parse e.newValue - , false - (key, cb) -> $.syncing[g.NAMESPACE + key] = cb -<% } %> -$.item = (key, val) -> - item = {} - item[key] = val - item -<% if (type === 'crx') { %> $.localKeys = [ # filters 'name', @@ -372,6 +362,7 @@ $.get = (key, val, cb) -> if syncItems count++ chrome.storage.sync.get syncItems, done + $.set = do -> items = {} localItems = {} @@ -397,8 +388,13 @@ $.set = do -> set() <% } else { %> - # http://wiki.greasespot.net/Main_Page +$.sync = do -> + $.on window, 'storage', (e) -> + if cb = $.syncing[e.key] + cb JSON.parse e.newValue + (key, cb) -> $.syncing[g.NAMESPACE + key] = cb + $.delete = (keys) -> unless keys instanceof Array keys = [keys] diff --git a/src/General/lib/clone.class b/src/General/lib/clone.class index d05541491..547afe1db 100644 --- a/src/General/lib/clone.class +++ b/src/General/lib/clone.class @@ -59,5 +59,4 @@ class Clone extends Post @isDead = true if origin.isDead @isClone = true - index = origin.clones.push(@) - 1 - root.setAttribute 'data-clone', index \ No newline at end of file + root.dataset.clone = origin.clones.push(@) - 1 diff --git a/src/General/lib/post.class b/src/General/lib/post.class index e9b573aed..9a37e4c8a 100644 --- a/src/General/lib/post.class +++ b/src/General/lib/post.class @@ -16,29 +16,34 @@ class Post quotelinks: [] backlinks: info.getElementsByClassName 'backlink' + unless @isReply = $.hasClass post, 'reply' + @thread.OP = @ + @thread.isSticky = !!$ '.stickyIcon', info + @thread.isClosed = !!$ '.closedIcon', info + @info = {} - if subject = $ '.subject', info + if subject = $ '.subject', info @nodes.subject = subject @info.subject = subject.textContent - if name = $ '.name', info + if name = $ '.name', info @nodes.name = name @info.name = name.textContent - if email = $ '.useremail', info + if email = $ '.useremail', info @nodes.email = email @info.email = decodeURIComponent email.href[7..] - if tripcode = $ '.postertrip', info + if tripcode = $ '.postertrip', info @nodes.tripcode = tripcode @info.tripcode = tripcode.textContent - if uniqueID = $ '.posteruid', info + if uniqueID = $ '.posteruid', info @nodes.uniqueID = uniqueID @info.uniqueID = uniqueID.firstElementChild.textContent - if capcode = $ '.capcode.hand', info + if capcode = $ '.capcode.hand', info @nodes.capcode = capcode @info.capcode = capcode.textContent.replace '## ', '' - if flag = $ '.countryFlag', info + if flag = $ '.flag, .countryFlag', info @nodes.flag = flag @info.flag = flag.title - if date = $ '.dateTime', info + if date = $ '.dateTime', info @nodes.date = date @info.date = new Date date.dataset.utc * 1000 @info.yours = QR.db.get @@ -48,43 +53,7 @@ class Post @parseComment() @parseQuotes() - - if (file = $ '.file', post) and thumb = $ 'img[data-md5]', file - # Supports JPG/PNG/GIF/PDF. - # Flash files are not supported. - alt = thumb.alt - anchor = thumb.parentNode - fileInfo = file.firstElementChild - @file = - info: fileInfo - text: fileInfo.firstElementChild - thumb: thumb - URL: anchor.href - size: alt.match(/[\d.]+\s\w+/)[0] - MD5: thumb.dataset.md5 - isSpoiler: $.hasClass anchor, 'imgspoiler' - size = +@file.size.match(/[\d.]+/)[0] - unit = ['B', 'KB', 'MB', 'GB'].indexOf @file.size.match(/\w+$/)[0] - size *= 1024 while unit-- > 0 - @file.sizeInBytes = size - @file.thumbURL = - if that.isArchived - thumb.src - else - "#{location.protocol}//thumbs.4chan.org/#{board}/thumb/#{@file.URL.match(/(\d+)\./)[1]}s.jpg" - # replace %22 with quotes, see: - # crbug.com/81193 - # webk.it/62107 - # https://www.w3.org/Bugs/Public/show_bug.cgi?id=16909 - # http://www.whatwg.org/specs/web-apps/current-work/#multipart-form-data - @file.name = $('span[title]', fileInfo).title.replace /%22/g, '"' - if @file.isImage = /(jpg|png|gif)$/i.test @file.name - @file.dimensions = @file.text.textContent.match(/\d+x\d+/)[0] - - unless @isReply = $.hasClass post, 'reply' - @thread.OP = @ - @thread.isSticky = !!$ '.stickyIcon', @nodes.info - @thread.isClosed = !!$ '.closedIcon', @nodes.info + @parseFile(that) @clones = [] g.posts[@fullID] = thread.posts[@] = board.posts[@] = @ @@ -108,18 +77,18 @@ class Post nodes = d.evaluate './/br|.//text()', bq, null, 7, null i = 0 while i < nodes.snapshotLength - text.push if data = nodes.snapshotItem(i++).data then data else '\n' + text.push nodes.snapshotItem(i++).data or '\n' @info.comment = text.join('').trim().replace /\s+$/gm, '' parseQuotes: -> quotes = {} for quotelink in $$ '.quotelink', @nodes.comment # Don't add board links. (>>>/b/) - hash = quotelink.hash + {hash} = quotelink continue unless hash # Don't add catalog links. (>>>/b/catalog or >>>/b/search) - pathname = quotelink.pathname + {pathname} = quotelink continue if /catalog$/.test pathname # Don't add rules links. (>>>/a/rules) @@ -128,14 +97,49 @@ class Post @nodes.quotelinks.push quotelink - # Don't count capcode replies as quotes. (Admin/Mod/Dev Replies: ...) - continue if quotelink.parentNode.parentNode.className is 'capcodeReplies' + # Don't count capcode replies as quotes in OPs. (Admin/Mod/Dev Replies: ...) + continue if !@isReply and $.hasClass quotelink.parentNode.parentNode, 'capcodeReplies' # Basically, only add quotes that link to posts on an imageboard. quotes["#{pathname.split('/')[1]}.#{hash[2..]}"] = true return if @isClone @quotes = Object.keys quotes + parseFile: (that) -> + return unless (fileEl = $ '.file', @nodes.post) and thumb = $ 'img[data-md5]', fileEl + # Supports JPG/PNG/GIF/PDF. + # Flash files are not supported. + alt = thumb.alt + anchor = thumb.parentNode + fileInfo = fileEl.firstElementChild + @file = + info: fileInfo + text: fileInfo.firstElementChild + thumb: thumb + URL: anchor.href + size: alt.match(/[\d.]+\s\w+/)[0] + MD5: thumb.dataset.md5 + isSpoiler: $.hasClass anchor, 'imgspoiler' + size = +@file.size.match(/[\d.]+/)[0] + unit = ['B', 'KB', 'MB', 'GB'].indexOf @file.size.match(/\w+$/)[0] + size *= 1024 while unit-- > 0 + @file.sizeInBytes = size + @file.thumbURL = if that.isArchived + thumb.src + else + "#{location.protocol}//thumbs.4chan.org/#{@board}/thumb/#{@file.URL.match(/(\d+)\./)[1]}s.jpg" + @file.name = $('span[title]', fileInfo).title + <% if (type === 'crx') { %> + # replace %22 with quotes, see: + # crbug.com/81193 + # webk.it/62107 + # https://www.w3.org/Bugs/Public/show_bug.cgi?id=16909 + # http://www.whatwg.org/specs/web-apps/current-work/#multipart-form-data + @file.name = @file.name.replace /%22/g, '"' + <% } %> + if @file.isImage = /(jpg|png|gif)$/i.test @file.name + @file.dimensions = @file.text.textContent.match(/\d+x\d+/)[0] + kill: (file, now) -> now or= new Date() if file @@ -190,10 +194,12 @@ class Post quotelink.textContent = quotelink.textContent.replace '\u00A0(Dead)', '' $.rmClass quotelink, 'deadlink' return + addClone: (context) -> new Clone @, context + rmClone: (index) -> @clones.splice index, 1 for clone in @clones[index..] - clone.nodes.root.setAttribute 'data-clone', index++ - return \ No newline at end of file + clone.nodes.root.dataset.clone = index++ + return diff --git a/src/General/lib/thread.class b/src/General/lib/thread.class index e8027a1c4..57d82a316 100644 --- a/src/General/lib/thread.class +++ b/src/General/lib/thread.class @@ -2,8 +2,7 @@ class Thread callbacks: [] toString: -> @ID - constructor: (ID, @board) -> - @ID = +ID + constructor: (@ID, @board) -> @fullID = "#{@board}.#{@ID}" @posts = {} @@ -11,4 +10,4 @@ class Thread kill: -> @isDead = true - @timeOfDeath = Date.now() \ No newline at end of file + @timeOfDeath = Date.now() diff --git a/src/General/meta/manifest.json b/src/General/meta/manifest.json index b8d3ec605..926312c26 100644 --- a/src/General/meta/manifest.json +++ b/src/General/meta/manifest.json @@ -16,6 +16,7 @@ }], "homepage_url": "<%= meta.page %>", "minimum_chrome_version": "24", + "minimum_opera_version": "15", "permissions": [ "storage" ] diff --git a/src/Images/ImageHover.coffee b/src/Images/ImageHover.coffee index 082aa4625..5356f50c3 100644 --- a/src/Images/ImageHover.coffee +++ b/src/Images/ImageHover.coffee @@ -13,7 +13,7 @@ ImageHover = el = $.el 'img', id: 'ihover' src: post.file.URL - el.setAttribute 'data-fullid', post.fullID + el.dataset.fullID = post.fullID $.add Header.hover, el UI.hover root: @ @@ -24,7 +24,7 @@ ImageHover = $.on el, 'error', ImageHover.error error: -> return unless doc.contains @ - post = g.posts[@dataset.fullid] + post = g.posts[@dataset.fullID] src = @src.split '/' if src[2] is 'images.4chan.org' @@ -48,4 +48,4 @@ ImageHover = post.kill() else if postObj.filedeleted clearTimeout timeoutID - post.kill true \ No newline at end of file + post.kill true diff --git a/src/Miscellaneous/Sauce.coffee b/src/Images/Sauce.coffee similarity index 93% rename from src/Miscellaneous/Sauce.coffee rename to src/Images/Sauce.coffee index 916c178f9..bc585c101 100644 --- a/src/Miscellaneous/Sauce.coffee +++ b/src/Images/Sauce.coffee @@ -4,12 +4,10 @@ Sauce = links = [] for link in Conf['sauces'].split '\n' - continue if link[0] is '#' try - links.push @createSauceLink link.trim() + links.push @createSauceLink link.trim() if link[0] isnt '#' catch err # Don't add random text plz. - continue return unless links.length @links = links @link = $.el 'a', target: '_blank' diff --git a/src/Menu/DeleteLink.coffee b/src/Menu/DeleteLink.coffee index 9427d4076..7f71d7f6e 100644 --- a/src/Menu/DeleteLink.coffee +++ b/src/Menu/DeleteLink.coffee @@ -44,9 +44,8 @@ DeleteLink = return if DeleteLink.cooldown.counting is post $.off @, 'click', DeleteLink.delete - @textContent = "Deleting #{@textContent}..." - fileOnly = $.hasClass @, 'delete-file' + @textContent = "Deleting #{if fileOnly then 'file' else 'post'}..." form = mode: 'usrdel' diff --git a/src/Menu/Menu.coffee b/src/Menu/Menu.coffee index a73addfc3..4b207550b 100644 --- a/src/Menu/Menu.coffee +++ b/src/Menu/Menu.coffee @@ -8,29 +8,21 @@ Menu = cb: @node node: -> - button = Menu.makeButton @ if @isClone - $.replace $('.menu-button', @nodes.info), button - return - $.add @nodes.info, [$.tn('\u00A0'), button] + button = $ '.menu-button', @nodes.info + else + button = Menu.makeButton @ + $.add @nodes.info, [$.tn('\u00A0'), button] + $.on button, 'click', Menu.toggle makeButton: do -> a = null - (post) -> + -> a or= $.el 'a', className: 'menu-button brackets-wrap' innerHTML: '' href: 'javascript:;' - clone = a.cloneNode true - clone.setAttribute 'data-postid', post.fullID - clone.setAttribute 'data-clone', true if post.isClone - $.on clone, 'click', Menu.toggle - clone + a.cloneNode true toggle: (e) -> - post = - if @dataset.clone - Get.postFromNode @ - else - g.posts[@dataset.postid] - Menu.menu.toggle e, @, post \ No newline at end of file + Menu.menu.toggle e, @, Get.postFromNode @ diff --git a/src/Miscellaneous/Keybinds.coffee b/src/Miscellaneous/Keybinds.coffee index 8df604b83..0e2aa52c0 100644 --- a/src/Miscellaneous/Keybinds.coffee +++ b/src/Miscellaneous/Keybinds.coffee @@ -93,10 +93,10 @@ Keybinds = window.location = "/#{g.BOARD}/catalog" # Thread Navigation when Conf['Next thread'] - return if g.VIEW is 'thread' + return if g.VIEW isnt 'index' Nav.scroll +1 when Conf['Previous thread'] - return if g.VIEW is 'thread' + return if g.VIEW isnt 'index' Nav.scroll -1 when Conf['Expand thread'] ExpandThread.toggle thread diff --git a/src/Miscellaneous/Nav.coffee b/src/Miscellaneous/Nav.coffee index eb1a261f9..71dafa8af 100644 --- a/src/Miscellaneous/Nav.coffee +++ b/src/Miscellaneous/Nav.coffee @@ -58,8 +58,7 @@ Nav = # unless we're not at the beginning of the current thread # (and thus wanting to move to beginning) # or we're above the first thread and don't want to skip it - unless (delta is -1 and Math.ceil(top) < 0) or (delta is +1 and top > 1) - i += delta + if (delta is -1 and top > -5) or (delta is +1 and top < 5) + top = threads[i + delta]?.getBoundingClientRect().top - topMargin - top = threads[i]?.getBoundingClientRect().top - topMargin window.scrollBy 0, top diff --git a/src/Monitoring/ThreadUpdater.coffee b/src/Monitoring/ThreadUpdater.coffee index 7f2c5312a..3444cb377 100644 --- a/src/Monitoring/ThreadUpdater.coffee +++ b/src/Monitoring/ThreadUpdater.coffee @@ -158,8 +158,7 @@ ThreadUpdater = By sending the `If-Modified-Since` header we get a proper status code, and no response. This saves bandwidth for both the user and the servers and avoid unnecessary computation. ### - # XXX 304 -> 0 in Opera - [text, klass] = if [0, 304].contains req.status + [text, klass] = if req.status is 304 [null, null] else ["#{req.statusText} (#{req.status})", 'warning'] diff --git a/src/Monitoring/Unread.coffee b/src/Monitoring/Unread.coffee index 547d9a577..dd2b5347b 100644 --- a/src/Monitoring/Unread.coffee +++ b/src/Monitoring/Unread.coffee @@ -36,13 +36,11 @@ Unread = # Let the header's onload callback handle it. return if (hash = location.hash.match /\d+/) and hash[0] of Unread.thread.posts if Unread.posts.length - # Scroll to before the first unread post. - prevID = 0 - while root = $.x 'preceding-sibling::div[contains(@class,"postContainer")][1]', Unread.posts[0].nodes.root - post = Get.postFromRoot root - break if prevID is post.ID - prevID = post.ID - break unless post.isHidden + # Scroll to a non-hidden, non-OP post that's before the first unread post. + post = Unread.posts[0] + while root = $.x 'preceding-sibling::div[contains(@class,"replyContainer")][1]', post.nodes.root + break unless (post = Get.postFromRoot root).isHidden + return unless root onload = -> root.scrollIntoView false if checkPosition root else # Scroll to the last read post. @@ -188,9 +186,7 @@ Unread = else Favicon.default - <% if (type !== 'crx') { %> + <% if (type === 'userscript') { %> # `favicon.href = href` doesn't work on Firefox. - # `favicon.href = href` isn't enough on Opera. - # Opera won't always update the favicon if the href didn't change. $.add d.head, Favicon.el <% } %> diff --git a/src/Posting/QuickReply.coffee b/src/Posting/QuickReply.coffee index 2c7443bdf..04dfb3039 100644 --- a/src/Posting/QuickReply.coffee +++ b/src/Posting/QuickReply.coffee @@ -97,8 +97,8 @@ QR = $.rmClass QR.captcha.nodes.input, 'error' if Conf['QR Shortcut'] $.toggleClass $('.qr-shortcut'), 'disabled' - for i in QR.posts - QR.posts[0].rm() + for post in QR.posts.splice 0, QR.posts.length, new QR.post true + post.delete() QR.cooldown.auto = false QR.status() @@ -152,7 +152,8 @@ QR = status: -> return unless QR.nodes - if g.DEAD + {thread} = QR.posts[0] + if thread isnt 'new' and g.threads["#{g.BOARD}.#{thread}"].isDead value = 404 disabled = true QR.cooldown.auto = false @@ -373,14 +374,10 @@ QR = e?.preventDefault() return unless QR.postingIsEnabled - sel = d.getSelection() - selectionRoot = $.x 'ancestor::div[contains(@class,"postContainer")][1]', sel.anchorNode - post = Get.postFromNode @ - {OP} = Get.contextFromLink(@).thread - - text = ">>#{post}\n" - if (s = sel.toString().trim()) and post.nodes.root is selectionRoot - # XXX Opera doesn't retain `\n`s? + 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" @@ -391,7 +388,7 @@ QR = $.addClass QR.nodes.el, 'dump' QR.cooldown.auto = true {com, thread} = QR.nodes - thread.value = OP.ID unless com.value + thread.value = Get.contextFromNode(@).thread unless com.value thread.nextElementSibling.firstElementChild.textContent = thread.options[thread.selectedIndex].textContent caretPos = com.selectionStart @@ -449,7 +446,7 @@ QR = QR.nodes.fileInput.click() fileInput: (files) -> - if @ instanceof Element #or files instanceof Event # file input + if files instanceof Event # file input files = [@files...] QR.nodes.fileInput.value = null # Don't hold the files from being modified on windows {length} = files @@ -506,7 +503,7 @@ QR = for elm in $$ '*', el $.on elm, 'blur', QR.focusout $.on elm, 'focus', QR.focusin - <% } %> + <% } %> $.on el, 'click', @select.bind @ $.on @nodes.rm, 'click', (e) => e.stopPropagation(); @rm() $.on @nodes.label, 'click', (e) => e.stopPropagation() @@ -555,7 +552,7 @@ QR = @unlock() rm: -> - $.rm @nodes.el + @delete() index = QR.posts.indexOf @ if QR.posts.length is 1 new QR.post true @@ -563,7 +560,9 @@ QR = else if @ is QR.selected (QR.posts[index-1] or QR.posts[index+1]).select() QR.posts.splice index, 1 - return unless window.URL + QR.status() + delete: -> + $.rm @nodes.el URL.revokeObjectURL @URL lock: (lock=true) -> @@ -608,15 +607,18 @@ QR = if input.type is 'checkbox' @spoiler = input.checked return - {value} = input - @[input.dataset.name] = value - return if input.nodeName isnt 'TEXTAREA' - @nodes.span.textContent = value - QR.characterCount() - # Disable auto-posting if you're typing in the first post - # during the last 5 seconds of the cooldown. - if QR.cooldown.auto and @ is QR.posts[0] and 0 < QR.cooldown.seconds <= 5 - QR.cooldown.auto = false + {name} = input.dataset + @[name] = input.value + switch name + when 'thread' + QR.status() + when 'com' + @nodes.span.textContent = @com + QR.characterCount() + # Disable auto-posting if you're typing in the first post + # during the last 5 seconds of the cooldown. + if QR.cooldown.auto and @ is QR.posts[0] and 0 < QR.cooldown.seconds <= 5 + QR.cooldown.auto = false forceSave: -> return unless @ is QR.selected @@ -630,26 +632,15 @@ QR = @filename = "#{file.name} (#{$.bytesToString file.size})" @nodes.el.title = @filename @nodes.label.hidden = false if QR.spoiler - URL.revokeObjectURL @URL if window.URL + URL.revokeObjectURL @URL @showFileData() unless /^image/.test file.type @nodes.el.style.backgroundImage = null return @setThumbnail() - setThumbnail: (fileURL) -> - # XXX Opera does not support blob URL + setThumbnail: -> # Create a redimensioned thumbnail. - unless window.URL - unless fileURL - reader = new FileReader() - reader.onload = (e) => - @setThumbnail e.target.result - reader.readAsDataURL @file - return - else - fileURL = URL.createObjectURL @file - img = $.el 'img' img.onload = => @@ -661,7 +652,7 @@ QR = s *= 3 if @file.type is 'image/gif' # let them animate {height, width} = img if height < s or width < s - @URL = fileURL if window.URL + @URL = fileURL @nodes.el.style.backgroundImage = "url(#{@URL})" return if height <= width @@ -674,10 +665,6 @@ QR = cv.height = img.height = height cv.width = img.width = width cv.getContext('2d').drawImage img, 0, 0, width, height - unless window.URL - @nodes.el.style.backgroundImage = "url(#{cv.toDataURL()})" - delete @URL - return URL.revokeObjectURL fileURL applyBlob = (blob) => @URL = URL.createObjectURL blob @@ -695,6 +682,7 @@ QR = applyBlob new Blob [ui8a], type: 'image/png' + fileURL = URL.createObjectURL @file img.src = fileURL rmFile: -> @@ -704,7 +692,6 @@ QR = @nodes.el.style.backgroundImage = null @nodes.label.hidden = true if QR.spoiler @showFileData() - return unless window.URL URL.revokeObjectURL @URL showFileData: -> @@ -729,33 +716,26 @@ QR = @nodes.span.textContent = @com reader.readAsText file - dragStart: -> - $.addClass @, 'drag' - - dragEnd: -> - $.rmClass @, 'drag' - - dragEnter: -> - $.addClass @, 'over' - - dragLeave: -> - $.rmClass @, 'over' + dragStart: -> $.addClass @, 'drag' + dragEnd: -> $.rmClass @, 'drag' + dragEnter: -> $.addClass @, 'over' + dragLeave: -> $.rmClass @, 'over' dragOver: (e) -> e.preventDefault() e.dataTransfer.dropEffect = 'move' drop: -> - el = $ '.drag', @parentNode - $.rmClass el, 'drag' # Opera doesn't fire dragEnd if we drop it on something else - $.rmClass @, 'over' + $.rmClass @, 'over' return unless @draggable + el = $ '.drag', @parentNode index = (el) -> [el.parentNode.children...].indexOf el oldIndex = index el newIndex = index @ (if oldIndex < newIndex then $.after else $.before) @, el post = QR.posts.splice(oldIndex, 1)[0] QR.posts.splice newIndex, 0, post + QR.status() captcha: init: -> @@ -784,20 +764,17 @@ QR = img: imgContainer.firstChild input: input - if window.MutationObserver - observer = new MutationObserver @load.bind @ - observer.observe @nodes.challenge, - childList: true - else - $.on @nodes.challenge, 'DOMNodeInserted', @load.bind @ + new MutationObserver(@load.bind @).observe @nodes.challenge, + childList: true $.on imgContainer, 'click', @reload.bind @ $.on input, 'keydown', @keydown.bind @ $.on input, 'focus', -> $.addClass QR.nodes.el, 'focus' $.on input, 'blur', -> $.rmClass QR.nodes.el, 'focus' - $.get 'captchas', [], (item) => - @sync item['captchas'] + $.get 'captchas', [], ({captchas}) => + @sync captchas + $.sync 'captchas', @sync # start with an uncached captcha @reload() @@ -806,12 +783,13 @@ QR = # XXX Firefox lacks focusin/focusout support. $.on input, 'blur', QR.focusout $.on input, 'focus', QR.focusin - <% } %> + <% } %> $.addClass QR.nodes.el, 'has-captcha' $.after QR.nodes.dumpList.parentElement, [imgContainer, input] - sync: (@captchas) -> + sync: (captchas) -> + QR.captcha.captchas = captchas QR.captcha.count() getOne: -> @@ -931,10 +909,6 @@ QR = # Add empty mimeType to avoid errors with URLs selected in Window's file dialog. QR.mimeTypes.push '' nodes.fileInput.max = $('input[name=MAX_FILE_SIZE]').value - <% if (type !== 'userjs') { %> - # Opera's accept attribute is fucked up - nodes.fileInput.accept = "text/*, #{mimeTypes}" - <% } %> QR.spoiler = !!$ 'input[name=spoiler]' if QR.spoiler @@ -969,7 +943,7 @@ QR = for elm in $$ '*', QR.nodes.el $.on elm, 'blur', QR.focusout $.on elm, 'focus', QR.focusin - <% } %> + <% } %> $.on dialog, 'focusin', QR.focusin $.on dialog, 'focusout', QR.focusout $.on nodes.autohide, 'change', QR.toggleHide @@ -1133,11 +1107,6 @@ QR = QR.status() response: -> - <% if (type === 'userjs') { %> - # The upload.onload callback is not called - # or at least not in time with Opera. - QR.req.upload.onload() - <% } %> {req} = QR delete QR.req @@ -1229,15 +1198,15 @@ QR = QR.cooldown.set {req, post, isReply} - if threadID is postID # new thread - URL = "/#{g.BOARD}/res/#{threadID}" + URL = if threadID is postID # new thread + "/#{g.BOARD}/res/#{threadID}" else if g.VIEW is 'index' and !QR.cooldown.auto and Conf['Open Post in New Tab'] # replying from the index - URL = "/#{g.BOARD}/res/#{threadID}#p#{postID}" + "/#{g.BOARD}/res/#{threadID}#p#{postID}" if URL if Conf['Open Post in New Tab'] - $.open "/#{g.BOARD}/res/#{threadID}" + $.open URL else - window.location = "/#{g.BOARD}/res/#{threadID}" + window.location = URL QR.status() diff --git a/src/Quotelinks/QuoteInline.coffee b/src/Quotelinks/QuoteInline.coffee index 4ea6b3b43..723f0c53b 100644 --- a/src/Quotelinks/QuoteInline.coffee +++ b/src/Quotelinks/QuoteInline.coffee @@ -35,7 +35,7 @@ QuoteInline = return if e.shiftKey or e.altKey or e.ctrlKey or e.metaKey or e.button isnt 0 e.preventDefault() {boardID, threadID, postID} = Get.postDataFromLink @ - context = Get.contextFromLink @ + context = Get.contextFromNode @ if $.hasClass @, 'inlined' QuoteInline.rm @, boardID, threadID, postID, context else @@ -107,4 +107,4 @@ QuoteInline = {boardID, threadID, postID} = Get.postDataFromLink inlined QuoteInline.rm inlined, boardID, threadID, postID, context $.rmClass inlined, 'inlined' - return \ No newline at end of file + return diff --git a/src/Quotelinks/QuotePreview.coffee b/src/Quotelinks/QuotePreview.coffee index 7615cf759..15fd65f64 100644 --- a/src/Quotelinks/QuotePreview.coffee +++ b/src/Quotelinks/QuotePreview.coffee @@ -22,8 +22,9 @@ QuotePreview = qp = $.el 'div', id: 'qp' className: 'dialog' + $.add Header.hover, qp - Get.postClone boardID, threadID, postID, qp, Get.contextFromLink @ + Get.postClone boardID, threadID, postID, qp, Get.contextFromNode @ UI.hover root: @ diff --git a/src/Quotelinks/Quotify.coffee b/src/Quotelinks/Quotify.coffee index b537a7ae2..524f74f6c 100644 --- a/src/Quotelinks/Quotify.coffee +++ b/src/Quotelinks/Quotify.coffee @@ -21,6 +21,9 @@ Quotify = if deadlink.parentNode.className is 'prettyprint' # Don't quotify deadlinks inside code tags, # un-`span` them. + # This won't be necessary once 4chan + # stops quotifying inside code tags: + # https://github.com/4chan/4chan-JS/issues/77 $.replace deadlink, [deadlink.childNodes...] return @@ -48,9 +51,8 @@ Quotify = target: '_blank' textContent: "#{quote}\u00A0(Dead)" - a.setAttribute 'data-boardid', boardID - a.setAttribute 'data-threadid', post.thread.ID - a.setAttribute 'data-postid', postID + $.extend a.dataset, {boardID, threadID: post.thread.ID, postID} + else if redirect = Redirect.to 'thread', {boardID, threadID: 0, postID} # Replace the .deadlink span if we can redirect. a = $.el 'a', @@ -60,9 +62,8 @@ Quotify = textContent: "#{quote}\u00A0(Dead)" if Redirect.to 'post', {boardID, postID} # Make it function as a normal quote if we can fetch the post. - $.addClass a, 'quotelink' - a.setAttribute 'data-boardid', boardID - a.setAttribute 'data-postid', postID + $.addClass a, 'quotelink' + $.extend a.dataset, {boardID, postID} unless @quotes.contains quoteID @quotes.push quoteID @@ -73,4 +74,4 @@ Quotify = $.replace deadlink, a if $.hasClass a, 'quotelink' - @nodes.quotelinks.push a \ No newline at end of file + @nodes.quotelinks.push a