From a30a5927c8cd3b6ebdeac99fb7f28764bf383d42 Mon Sep 17 00:00:00 2001 From: Jordan Bates Date: Tue, 28 May 2013 12:40:42 -0700 Subject: [PATCH] Opera 15 extension --- .gitignore | 3 +- Gruntfile.coffee | 30 +- builds/4chan-X.zip | Bin 0 -> 122177 bytes builds/opera/icon128.png | Bin 0 -> 196 bytes builds/opera/icon16.png | Bin 0 -> 157 bytes builds/opera/icon48.png | Bin 0 -> 204 bytes builds/opera/manifest.json | 21 + builds/opera/script.js | 10613 ++++++++++++++++++++++++++ src/General/meta/operamanifest.json | 21 + 9 files changed, 10686 insertions(+), 2 deletions(-) create mode 100644 builds/4chan-X.zip create mode 100644 builds/opera/icon128.png create mode 100644 builds/opera/icon16.png create mode 100644 builds/opera/icon48.png create mode 100644 builds/opera/manifest.json create mode 100644 builds/opera/script.js create mode 100644 src/General/meta/operamanifest.json diff --git a/.gitignore b/.gitignore index 9751307ac..d084b239e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,6 @@ node_modules/ tmp-crx/ tmp-userjs/ tmp-userscript/ -builds/4chan-X.zip +builds/4chan-X-Chrome.zip +builds/4chan-X-Opera.zip Gruntfile.js \ No newline at end of file diff --git a/Gruntfile.coffee b/Gruntfile.coffee index 13c2febbe..25707b158 100644 --- a/Gruntfile.coffee +++ b/Gruntfile.coffee @@ -54,6 +54,16 @@ module.exports = (grunt) -> 'tmp-<%= pkg.type %>/script.js' ] + opera: + options: concatOptions + files: + 'builds/opera/manifest.json': 'src/General/meta/operamanifest.json' + 'builds/opera/script.js': [ + 'src/General/meta/botproc.js' + 'src/General/meta/banner.js' + 'tmp-<%= pkg.type %>/script.js' + ] + userjs: options: concatOptions src: [ @@ -91,6 +101,7 @@ module.exports = (grunt) -> build: [ 'concat:meta' 'build-crx' + 'build-opera' 'build-userjs' 'build-userscript' ] @@ -124,12 +135,20 @@ module.exports = (grunt) -> compress: crx: options: - archive: 'builds/4chan-X.zip' + archive: 'builds/4chan-X-Chrome.zip' level: 9 pretty: true expand: true cwd: 'builds/crx/' src: '**' + opera: + options: + archive: 'builds/4chan-X-Opera.zip' + level: 9 + pretty: true + expand: true + cwd: 'builds/opera/' + src: '**' clean: builds: 'builds' @@ -168,6 +187,14 @@ module.exports = (grunt) -> 'clean:tmpcrx' ] + grunt.registerTask 'build-opera', [ + 'set-build:crx' + 'concat:coffee' + 'coffee:script' + 'concat:opera' + 'clean:tmpcrx' + ] + grunt.registerTask 'build-userjs', [ 'set-build:userjs' 'concat:coffee' @@ -187,6 +214,7 @@ module.exports = (grunt) -> grunt.registerTask 'release', [ 'default' 'compress:crx' + 'compress:opera' 'shell:commit' 'shell:push' ] diff --git a/builds/4chan-X.zip b/builds/4chan-X.zip new file mode 100644 index 0000000000000000000000000000000000000000..83a41d73174341e3aa09ecf32c3f3571b78239e4 GIT binary patch literal 122177 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 z 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 literal 0 HcmV?d00001 diff --git a/builds/opera/icon16.png b/builds/opera/icon16.png new file mode 100644 index 0000000000000000000000000000000000000000..a1d2a71e8d6bd5c277ffb3bc328a2f3422125f70 GIT binary patch literal 157 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9oB=)|t_%$6KxWz*s?OP}IZk2rQvoXB$oY4FIJ-^KlvWGt+ub|aObH&<(LXm$q z!kip`qW7hA225i69`O8wer@2vuG&&I_Q2IOYuMO7u$W}`7c(jFuV7?bvipl^!FAm= xoSXRKs^49n+}d5A9O7u)@W7(x%!R^WW~Fx%>hH{yd +* http://zixaphir.github.io/appchan-x/ +* 4chan x Copyright © 2009-2011 James Campos +* https://github.com/aeosynth/4chan-x +* 4chan x Copyright © 2012-2013 Nicolas Stepien +* https://4chan-x.just-believe.in/ +* 4chan x Copyright © 2013-2013 Jordan Bates +* http://seaweedchan.github.io/4chan-x/ +* 4chan x Copyright © 2012-2013 ihavenoface +* http://ihavenoface.github.io/4chan-x/ +* 4chan SS Copyright © 2011-2013 Ahodesuka +* https://github.com/ahodesuka/4chan-Style-Script/ +* +* Permission is hereby granted, free of charge, to any person +* obtaining a copy of this software and associated documentation +* files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, +* copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following +* conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Contributors: +* aeosynth +* mayhemydg +* noface +* !K.WeEabo0o +* blaise +* that4chanwolf +* desuwa +* seaweed +* e000 +* ahodesuka +* Shou +* ferongr +* xat +* Ongpot +* thisisanon +* Anonymous +* Seiba +* herpaderpderp +* WakiMiko +* btmcsweeney +* AppleBloom +* detharonil +* +* All the people who've taken the time to write bug reports. +* +* Thank you. +*/ + +/* +* Contains data from external sources: +* +* audio/beep.wav from http://freesound.org/people/pierrecartoons1979/sounds/90112/ +* cc-by-nc-3.0 +* +* 4chan/4chan-JS (https://github.com/4chan/4chan-JS) +* Copyright (c) 2012-2013, 4chan LLC +* All rights reserved. +* +* license: https://github.com/4chan/4chan-JS/blob/master/LICENSE +* +* Linkify: (http://userscripts.org/scripts/show/1352) +* Copyright (c) 2011, Anthony Lieuallen +* All rights reserved. +* Originally written by Anthony Lieuallen of http://arantius.com/ +* Licensed for unlimited modification and redistribution as long as +* this notice is kept intact. +* +* license: http://userscripts.org/scripts/review/1352 +* +*/ +(function() { + var $, $$, Anonymize, ArchiveLink, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DataBoards, DeleteLink, DownloadLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Fourchan, Get, Header, IDColor, ImageExpand, ImageHover, ImageLoader, Keybinds, Linkify, Main, Menu, Nav, Notification, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Sauce, Settings, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, g, + __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, + __slice = [].slice, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, + __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + + Config = { + main: { + 'Miscellaneous': { + 'Catalog Links': [true, 'Add toggle link in header menu to turn Navigation links into links to each board\'s catalog.'], + 'External Catalog': [false, 'Link to external catalog instead of the internal one.'], + 'QR Shortcut': [false, 'Adds a small [QR] link in the header.'], + 'Announcement Hiding': [true, 'Add button to hide 4chan announcements.'], + '404 Redirect': [true, 'Redirect dead threads and images.'], + 'Keybinds': [true, 'Bind actions to keyboard shortcuts.'], + 'Time Formatting': [true, 'Localize and format timestamps.'], + 'Relative Post Dates': [false, 'Display dates like "3 minutes ago". Tooltip shows the timestamp.'], + 'File Info Formatting': [true, 'Reformat the file information.'], + 'Comment Expansion': [true, 'Add buttons to expand long comments.'], + 'Thread Expansion': [true, 'Add buttons to expand threads.'], + '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.'], + '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.'], + 'Indicate Spoilers': [false, 'Indicate spoilers if Remove Spoilers is enabled.'] + }, + 'Linkification': { + 'Linkify': [true, 'Convert text into links where applicable.'], + 'Allow False Positives': [false, 'Linkify everything, allowing more false positives but reducing missed links'], + 'Embedding': [true, 'Embed supported services.'], + 'Auto-embed': [false, 'Auto-embed Linkify Embeds.'], + 'Link Title': [true, 'Replace the link of a supported site with its actual title. Currently Supported: YouTube, Vimeo, SoundCloud, and Github gists'] + }, + 'Filtering': { + 'Anonymize': [false, 'Make everyone Anonymous.'], + 'Filter': [true, 'Self-moderation placebo.'], + 'Recursive Hiding': [true, 'Hide replies of hidden posts, recursively.'], + 'Thread Hiding Buttons': [true, 'Add buttons to hide entire threads.'], + 'Reply Hiding Buttons': [true, 'Add buttons to hide single replies.'], + 'Filtered Backlinks': [true, 'When enabled, shows backlinks to filtered posts with a line-through decoration. Otherwise, hides the backlinks.'], + 'Stubs': [true, 'Show stubs of hidden threads / replies.'] + }, + 'Images': { + 'Image Expansion': [true, 'Expand images.'], + 'Image Hover': [false, 'Show full image on mouseover.'], + 'Sauce': [true, 'Add sauce links to images.'], + 'Reveal Spoilers': [false, 'Reveal spoiler thumbnails.'], + 'Replace GIF': [false, 'Replace thumbnail of gifs with its actual image.'], + 'Replace PNG': [false, 'Replace pngs.'], + 'Replace JPG': [false, 'Replace jpgs.'], + 'Image Prefetching': [false, 'Preload images'], + 'Fappe Tyme': [false, 'Hide posts without images. *hint* *hint*'] + }, + 'Menu': { + 'Menu': [true, 'Add a drop-down menu to posts.'], + 'Report Link': [true, 'Add a report link to the menu.'], + 'Thread Hiding Link': [true, 'Add a link to hide entire threads.'], + 'Reply Hiding Link': [true, 'Add a link to hide single replies.'], + 'Delete Link': [true, 'Add post and image deletion links to the menu.'], + 'Download Link': [true, 'Add a download with original filename link to the menu. Chrome-only currently.'], + 'Archive Link': [true, 'Add an archive link to the menu.'] + }, + 'Monitoring': { + 'Thread Updater': [true, 'Fetch and insert new replies. Has more options in its own dialog.'], + 'Unread Count': [true, 'Show the unread posts count in the tab title.'], + 'Hide Unread Count at (0)': [false, 'Hide the unread posts count in the tab title when it reaches 0.'], + 'Unread Favicon': [true, 'Show a different favicon when there are unread posts.'], + 'Unread Line': [true, 'Show a line to distinguish read posts from unread ones.'], + 'Scroll to Last Read Post': [true, 'Scroll back to the last read post when reopening a thread.'], + 'Thread Excerpt': [true, 'Show an excerpt of the thread in the tab title.'], + 'Thread Stats': [true, 'Display reply and image count.'], + 'Page Count in Stats': [false, 'Display the page count in the thread stats as well.'], + 'Updater and Stats in Header': [true, 'Places the thread updater and thread stats in the header instead of floating them.'], + 'Thread Watcher': [true, 'Bookmark threads.'], + 'Toggleable Thread Watcher': [false, 'Adds a shortcut for the thread watcher, hides the watcher by default, and makes it scroll with the page.'], + 'Auto Watch': [true, 'Automatically watch threads you start.'], + 'Auto Watch Reply': [false, 'Automatically watch threads you reply to.'] + }, + 'Posting': { + 'Quick Reply': [true, 'All-in-one form to reply, create threads, automate dumping and more.'], + 'Persistent QR': [false, 'The Quick reply won\'t disappear after posting.'], + 'Auto Hide QR': [false, 'Automatically hide the quick reply when posting.'], + 'Open Post in New Tab': [true, 'Open new threads or replies to a thread from the index in a new tab.'], + 'Remember Subject': [false, 'Remember the subject field, instead of resetting after posting.'], + 'Remember Spoiler': [false, 'Remember the spoiler state, instead of resetting after posting.'], + 'Hide Original Post Form': [true, 'Hide the normal post form.'], + 'Cooldown': [true, 'Indicate the remaining time before posting again.'], + 'Cooldown Prediction': [true, 'Decrease the cooldown time by taking into account upload speed. Disable it if it\'s inaccurate for you.'], + 'Posting Success Notifications': [true, 'Show notifications on successful post creation or file uploading.'], + 'Captcha Warning Notifications': [true, 'When disabled, shows a red border on the CAPTCHA input until a key is pressed instead of a notification.'] + }, + 'Quote Links': { + 'Quote Backlinks': [true, 'Add quote backlinks.'], + 'OP Backlinks': [true, 'Add backlinks to the OP.'], + 'Quote Inlining': [true, 'Inline quoted post on click.'], + 'Quote Hash Navigation': [false, 'Include an extra link after quotes for autoscrolling to quoted posts.'], + 'Forward Hiding': [true, 'Hide original posts of inlined backlinks.'], + 'Quote Previewing': [true, 'Show quoted post on hover.'], + 'Quote Highlighting': [true, 'Highlight the previewed post.'], + 'Resurrect Quotes': [true, 'Link dead quotes to the archives.'], + 'Mark Quotes of You': [true, 'Add \'(You)\' to quotes linking to your posts.'], + 'Quoted Title': [false, 'Change the page title to reflect you\'ve been quoted.'], + 'Highlight Posts Quoting You': [false, 'Highlights any posts that contain a quote to your post.'], + 'Highlight Own Posts': [false, 'Highlights own posts if Mark Quotes of You is enabled.'], + 'Mark OP Quotes': [true, 'Add \'(OP)\' to OP quotes.'], + 'Mark Cross-thread Quotes': [true, 'Add \'(Cross-thread)\' to cross-threads quotes.'], + 'Quote Threading': [false, 'Thread conversations'] + } + }, + imageExpansion: { + 'Fit width': [true, ''], + 'Fit height': [false, ''], + 'Expand spoilers': [true, 'Expand all images along with spoilers.'], + 'Expand from here': [true, 'Expand all images only from current position to thread end.'], + 'Advance on contract': [false, 'Advance to next post when contracting an expanded image.'] + }, + filter: { + name: "# Filter any namefags:\n#/^(?!Anonymous$)/", + uniqueID: "# Filter a specific ID:\n#/Txhvk1Tl/", + tripcode: "# Filter any tripfag\n#/^!/", + capcode: "# Set a custom class for mods:\n#/Mod$/;highlight:mod;op:yes\n# Set a custom class for moot:\n#/Admin$/;highlight:moot;op:yes", + email: "# Filter any e-mails that are not `sage` on /a/ and /jp/:\n#/^(?!sage$)/;boards:a,jp", + subject: "# Filter Generals on /v/:\n#/general/i;boards:v;op:only", + comment: "# Filter Stallman copypasta on /g/:\n#/what you\'re refer+ing to as linux/i;boards:g", + flag: '', + filename: '', + dimensions: "# Highlight potential wallpapers:\n#/1920x1080/;op:yes;highlight;top:no;boards:w,wg", + filesize: '', + MD5: '' + }, + sauces: "https://www.google.com/searchbyimage?image_url=%TURL\nhttp://iqdb.org/?url=%TURL\n#//tineye.com/search?url=%TURL\n#http://saucenao.com/search.php?url=%TURL\n#http://3d.iqdb.org/?url=%TURL\n#http://regex.info/exif.cgi?imgurl=%URL\n# uploaders:\n#http://imgur.com/upload?url=%URL;text:Upload to imgur\n#http://ompldr.org/upload?url1=%URL;text:Upload to ompldr\n# \"View Same\" in archives:\n#//archive.foolz.us/_/search/image/%MD5/;text:View same on foolz\n#//archive.foolz.us/%board/search/image/%MD5/;text:View same on foolz /%board/\n#//archive.installgentoo.net/%board/image/%MD5;text:View same on installgentoo /%board/", + 'sageEmoji': '4chan SS', + 'emojiPos': 'before', + 'Custom CSS': false, + Header: { + 'Fixed Header': true, + 'Header auto-hide': false, + 'Bottom Header': false, + 'Centered links': false, + 'Header catalog links': false, + 'Bottom Board List': true, + 'Custom Board Navigation': true + }, + boardnav: "[ toggle-all ]\n[current-title]\n[external-text:\"FAQ\",\"https://github.com/seaweedchan/4chan-x/wiki/Frequently-Asked-Questions\"]", + QR: { + 'QR.personas': "#email:\"sage\";boards:jp;always" + }, + time: '%m/%d/%y(%a)%H:%M:%S', + backlink: '>>%id', + fileInfo: '%L (%p%s, %r)', + favicon: 'ferongr', + usercss: '', + hotkeys: { + 'Toggle board list': ['Ctrl+b', 'Toggle the full board list.'], + 'Toggle header': ['Shift+h', 'Toggle the auto-hide option of the header.'], + 'Open empty QR': ['i', 'Open QR without post number inserted.'], + 'Open QR': ['Shift+i', 'Open QR with post number inserted.'], + 'Open settings': ['Alt+o', 'Open Settings.'], + 'Close': ['Esc', 'Close Settings, Notifications or QR.'], + 'Spoiler tags': ['Ctrl+s', 'Insert spoiler tags.'], + 'Code tags': ['Alt+c', 'Insert code tags.'], + 'Eqn tags': ['Alt+e', 'Insert eqn tags.'], + 'Math tags': ['Alt+m', 'Insert math tags.'], + 'Toggle sage': ['Alt+s', 'Toggle sage in email field'], + 'Submit QR': ['Ctrl+Enter', 'Submit post.'], + 'Watch': ['w', 'Watch thread.'], + 'Update': ['r', 'Update the thread now.'], + 'Expand image': ['Shift+e', 'Expand selected image.'], + 'Expand images': ['e', 'Expand all images.'], + 'fappeTyme': ['f', 'Fappe Tyme.'], + 'Front page': ['0', 'Jump to page 0.'], + 'Open front page': ['Shift+0', 'Open page 0 in a new tab.'], + 'Next page': ['Shift+Right', 'Jump to the next page.'], + 'Previous page': ['Shift+Left', 'Jump to the previous page.'], + 'Open catalog': ['Shift+c', 'Open the catalog of the current board'], + 'Next thread': ['Shift+Down', 'See next thread.'], + 'Previous thread': ['Shift+Up', 'See previous thread.'], + 'Expand thread': ['Ctrl+e', 'Expand thread.'], + 'Open thread': ['o', 'Open thread in current tab.'], + 'Open thread tab': ['Shift+o', 'Open thread in new tab.'], + 'Next reply': ['j', 'Select next reply.'], + 'Previous reply': ['k', 'Select previous reply.'], + 'Hide': ['x', 'Hide thread.'] + }, + updater: { + checkbox: { + 'Beep': [false, 'Beep on new post to completely read thread.'], + 'Auto Scroll': [false, 'Scroll updated posts into view. Only enabled at bottom of page.'], + 'Bottom Scroll': [false, 'Always scroll to the bottom, not the first new post. Useful for event threads.'], + 'Scroll BG': [false, 'Auto-scroll background tabs.'], + 'Auto Update': [true, 'Automatically fetch new posts.'], + 'Optional Increase': [false, 'Increase the intervals between updates on threads without new posts.'] + }, + 'Interval': 30 + } + }; + + Conf = {}; + + c = console; + + d = document; + + doc = d.documentElement; + + g = { + VERSION: '1.2.13', + NAMESPACE: '4chan X.', + boards: {}, + threads: {}, + posts: {} + }; + + String.prototype.capitalize = function() { + return this.charAt(0).toUpperCase() + this.slice(1); + }; + + String.prototype.contains = function(string) { + return this.indexOf(string) > -1; + }; + + Array.prototype.add = function(object, position) { + var keep; + + keep = this.slice(position); + this.length = position; + this.push(object); + return this.pushArrays(keep); + }; + + Array.prototype.contains = function(object) { + return this.indexOf(object) > -1; + }; + + Array.prototype.indexOf = function(object) { + var i; + + i = this.length; + while (i--) { + if (this[i] === object) { + return i; + } + } + return i; + }; + + Array.prototype.pushArrays = function() { + var arg, args, _i, _len; + + args = arguments; + for (_i = 0, _len = args.length; _i < _len; _i++) { + arg = args[_i]; + this.push.apply(this, arg); + } + return this; + }; + + Array.prototype.remove = function(object) { + var index; + + if ((index = this.indexOf(object)) > -1) { + return this.splice(index, 1); + } else { + return false; + } + }; + + $ = function(selector, root) { + if (root == null) { + root = d.body; + } + return root.querySelector(selector); + }; + + $.extend = function(object, properties) { + var key, val; + + for (key in properties) { + val = properties[key]; + if (!properties.hasOwnProperty(key)) { + continue; + } + object[key] = val; + } + }; + + $.DAY = 24 * ($.HOUR = 60 * ($.MINUTE = 60 * ($.SECOND = 1000))); + + $.id = function(id) { + return d.getElementById(id); + }; + + $.ready = function(fc) { + var cb, _ref; + + if ((_ref = d.readyState) === 'interactive' || _ref === 'complete') { + $.queueTask(fc); + return; + } + cb = function() { + $.off(d, 'DOMContentLoaded', cb); + return fc(); + }; + return $.on(d, 'DOMContentLoaded', cb); + }; + + $.formData = function(form) { + var fd, key, val; + + if (form instanceof HTMLFormElement) { + return new FormData(form); + } + fd = new FormData(); + for (key in form) { + val = form[key]; + if (!val) { + continue; + } + if (val.size && val.name) { + fd.append(key, val, val.name); + } else { + fd.append(key, val); + } + } + return fd; + }; + + $.ajax = function(url, callbacks, opts) { + var cred, err, form, headers, key, r, sync, type, upCallbacks, val; + + if (opts == null) { + opts = {}; + } + type = opts.type, cred = opts.cred, headers = opts.headers, upCallbacks = opts.upCallbacks, form = opts.form, sync = opts.sync; + r = new XMLHttpRequest(); + r.overrideMimeType('text/html'); + type || (type = form && 'post' || 'get'); + r.open(type, url, !sync); + for (key in headers) { + val = headers[key]; + r.setRequestHeader(key, val); + } + $.extend(r, callbacks); + $.extend(r.upload, upCallbacks); + try { + r.withCredentials = cred; + } catch (_error) { + err = _error; + } + r.send(form); + return r; + }; + + $.cache = (function() { + var reqs; + + reqs = {}; + return function(url, cb) { + var err, req, rm; + + if (req = reqs[url]) { + if (req.readyState === 4) { + cb.call(req, req.evt); + } else { + req.callbacks.push(cb); + } + return; + } + rm = function() { + return delete reqs[url]; + }; + try { + req = $.ajax(url, { + onload: function(e) { + var _i, _len, _ref; + + _ref = this.callbacks; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + cb = _ref[_i]; + cb.call(this, e); + } + this.evt = e; + return delete this.callbacks; + }, + onabort: rm, + onerror: rm + }); + } catch (_error) { + err = _error; + return; + } + req.callbacks = [cb]; + return reqs[url] = req; + }; + })(); + + $.cb = { + checked: function() { + $.set(this.name, this.checked); + return Conf[this.name] = this.checked; + }, + value: function() { + $.set(this.name, this.value.trim()); + return Conf[this.name] = this.value; + } + }; + + $.asap = function(test, cb) { + if (test()) { + return cb(); + } else { + return setTimeout($.asap, 25, test, cb); + } + }; + + $.addStyle = function(css, id) { + var style; + + style = $.el('style', { + id: id, + textContent: css + }); + $.asap((function() { + return d.head; + }), function() { + return $.add(d.head, style); + }); + return style; + }; + + $.x = function(path, root) { + root || (root = d.body); + return d.evaluate(path, root, null, 8, null).singleNodeValue; + }; + + $.X = function(path, root) { + root || (root = d.body); + return d.evaluate(path, root, null, 6, null); + }; + + $.addClass = function(el, className) { + return el.classList.add(className); + }; + + $.rmClass = function(el, className) { + return el.classList.remove(className); + }; + + $.toggleClass = function(el, className) { + return el.classList.toggle(className); + }; + + $.hasClass = function(el, className) { + return el.classList.contains(className); + }; + + $.rm = (function() { + if ('remove' in Element.prototype) { + return function(el) { + return el.remove(); + }; + } else { + return function(el) { + var _ref; + + return (_ref = el.parentNode) != null ? _ref.removeChild(el) : void 0; + }; + } + })(); + + $.rmAll = function(root) { + var node; + + while (node = root.firstChild) { + root.removeChild(node); + } + }; + + $.tn = function(s) { + return d.createTextNode(s); + }; + + $.frag = function() { + return d.createDocumentFragment(); + }; + + $.nodes = function(nodes) { + var frag, node, _i, _len; + + if (!(nodes instanceof Array)) { + return nodes; + } + frag = $.frag(); + for (_i = 0, _len = nodes.length; _i < _len; _i++) { + node = nodes[_i]; + frag.appendChild(node); + } + return frag; + }; + + $.add = function(parent, el) { + return parent.appendChild($.nodes(el)); + }; + + $.prepend = function(parent, el) { + return parent.insertBefore($.nodes(el), parent.firstChild); + }; + + $.after = function(root, el) { + return root.parentNode.insertBefore($.nodes(el), root.nextSibling); + }; + + $.before = function(root, el) { + return root.parentNode.insertBefore($.nodes(el), root); + }; + + $.replace = function(root, el) { + return root.parentNode.replaceChild($.nodes(el), root); + }; + + $.el = function(tag, properties) { + var el; + + el = d.createElement(tag); + if (properties) { + $.extend(el, properties); + } + return el; + }; + + $.on = function(el, events, handler) { + var event, _i, _len, _ref; + + _ref = events.split(' '); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + event = _ref[_i]; + el.addEventListener(event, handler, false); + } + }; + + $.off = function(el, events, handler) { + var event, _i, _len, _ref; + + _ref = events.split(' '); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + event = _ref[_i]; + el.removeEventListener(event, handler, false); + } + }; + + $.event = function(event, detail, root) { + if (root == null) { + root = d; + } + return root.dispatchEvent(new CustomEvent(event, { + bubbles: true, + detail: detail + })); + }; + + $.open = function(URL) { + return window.open(URL, '_blank'); + }; + + $.debounce = function(wait, fn) { + var args, exec, lastCall, that, timeout; + + lastCall = 0; + timeout = null; + that = null; + args = null; + exec = function() { + lastCall = Date.now(); + return fn.apply(that, args); + }; + return function() { + args = arguments; + that = this; + if (lastCall < Date.now() - wait) { + return exec(); + } + clearTimeout(timeout); + return timeout = setTimeout(exec, wait); + }; + }; + + $.queueTask = (function() { + var execTask, taskChannel, taskQueue; + + taskQueue = []; + execTask = function() { + var args, func, task; + + task = taskQueue.shift(); + func = task[0]; + args = Array.prototype.slice.call(task, 1); + return func.apply(func, args); + }; + if (window.MessageChannel) { + taskChannel = new MessageChannel(); + taskChannel.port1.onmessage = execTask; + return function() { + taskQueue.push(arguments); + return taskChannel.port2.postMessage(null); + }; + } else { + return function() { + taskQueue.push(arguments); + return setTimeout(execTask, 0); + }; + } + })(); + + $.globalEval = function(code) { + var script; + + script = $.el('script', { + textContent: code + }); + $.add(d.head || doc, script); + return $.rm(script); + }; + + $.bytesToString = function(size) { + var unit; + + unit = 0; + while (size >= 1024) { + size /= 1024; + unit++; + } + size = unit > 1 ? Math.round(size * 100) / 100 : Math.round(size); + return "" + size + " " + ['B', 'KB', 'MB', 'GB'][unit]; + }; + + $.minmax = function(value, min, max) { + return (value < min ? min : value > max ? max : value); + }; + + $.syncing = {}; + + $.sync = (function() { + chrome.storage.onChanged.addListener(function(changes) { + var cb, key; + + for (key in changes) { + if (cb = $.syncing[key]) { + cb(changes[key].newValue); + } + } + }); + return function(key, cb) { + return $.syncing[key] = cb; + }; + })(); + + $.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) { + return chrome.storage.sync.remove(keys); + }; + + $.get = function(key, val, cb) { + var count, done, items, localItems, syncItems; + + if (typeof cb === 'function') { + items = $.item(key, val); + } else { + items = key; + cb = val; + } + localItems = null; + syncItems = null; + for (key in items) { + val = items[key]; + if (__indexOf.call($.localKeys, key) >= 0) { + (localItems || (localItems = {}))[key] = val; + } else { + (syncItems || (syncItems = {}))[key] = val; + } + } + items = {}; + count = 0; + done = function(item) { + $.extend(items, item); + if (!--count) { + return cb(items); + } + }; + if (localItems) { + count++; + chrome.storage.local.get(localItems, done); + } + if (syncItems) { + count++; + return chrome.storage.sync.get(syncItems, done); + } + }; + + $.set = (function() { + var items, localItems, set; + + items = {}; + localItems = {}; + set = $.debounce($.SECOND, function() { + var err, key, _i, _len, _ref; + + _ref = $.localKeys; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + key = _ref[_i]; + if (key in items) { + (localItems || (localItems = {}))[key] = items[key]; + delete items[key]; + } + } + try { + chrome.storage.local.set(localItems); + chrome.storage.sync.set(items); + items = {}; + return localItems = {}; + } catch (_error) { + err = _error; + return c.error(err.stack); + } + }); + return function(key, val) { + if (typeof key === 'string') { + items[key] = val; + } else { + $.extend(items, key); + } + return set(); + }; + })(); + + $$ = function(selector, root) { + if (root == null) { + root = d.body; + } + return __slice.call(root.querySelectorAll(selector)); + }; + + Board = (function() { + Board.prototype.toString = function() { + return this.ID; + }; + + function Board(ID) { + this.ID = ID; + this.threads = {}; + this.posts = {}; + g.boards[this] = this; + } + + return Board; + + })(); + + Thread = (function() { + Thread.prototype.callbacks = []; + + Thread.prototype.toString = function() { + return this.ID; + }; + + function Thread(ID, board) { + this.board = board; + this.ID = +ID; + this.fullID = "" + this.board + "." + this.ID; + this.posts = {}; + g.threads[this.fullID] = board.threads[this] = this; + } + + Thread.prototype.kill = function() { + this.isDead = true; + return this.timeOfDeath = Date.now(); + }; + + return Thread; + + })(); + + Post = (function() { + Post.prototype.callbacks = []; + + Post.prototype.toString = function() { + return this.ID; + }; + + function Post(root, thread, board, that) { + var alt, anchor, capcode, date, email, file, fileInfo, flag, info, name, post, size, subject, thumb, tripcode, uniqueID, unit; + + this.thread = thread; + this.board = board; + if (that == null) { + that = {}; + } + this.ID = +root.id.slice(2); + this.fullID = "" + this.board + "." + this.ID; + post = $('.post', root); + info = $('.postInfo', post); + this.nodes = { + root: root, + post: post, + info: info, + comment: $('.postMessage', post), + quotelinks: [], + backlinks: info.getElementsByClassName('backlink') + }; + this.info = {}; + if (subject = $('.subject', info)) { + this.nodes.subject = subject; + this.info.subject = subject.textContent; + } + if (name = $('.name', info)) { + this.nodes.name = name; + this.info.name = name.textContent; + } + if (email = $('.useremail', info)) { + this.nodes.email = email; + this.info.email = decodeURIComponent(email.href.slice(7)); + } + if (tripcode = $('.postertrip', info)) { + this.nodes.tripcode = tripcode; + this.info.tripcode = tripcode.textContent; + } + if (uniqueID = $('.posteruid', info)) { + this.nodes.uniqueID = uniqueID; + this.info.uniqueID = uniqueID.firstElementChild.textContent; + } + if (capcode = $('.capcode.hand', info)) { + this.nodes.capcode = capcode; + this.info.capcode = capcode.textContent.replace('## ', ''); + } + if (flag = $('.countryFlag', info)) { + this.nodes.flag = flag; + this.info.flag = flag.title; + } + if (date = $('.dateTime', info)) { + this.nodes.date = date; + this.info.date = new Date(date.dataset.utc * 1000); + } + if (Conf['Quick Reply']) { + this.info.yours = QR.db.get({ + boardID: this.board, + threadID: this.thread, + postID: this.ID + }); + } + 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.clones = []; + g.posts[this.fullID] = thread.posts[this] = board.posts[this] = this; + if (that.isArchived) { + this.kill(); + } + } + + Post.prototype.parseComment = function() { + var bq, data, i, node, nodes, text, _i, _len, _ref; + + bq = this.nodes.comment.cloneNode(true); + _ref = $$('.abbr, .capcodeReplies, .exif, b', bq); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + node = _ref[_i]; + $.rm(node); + } + text = []; + nodes = d.evaluate('.//br|.//text()', bq, null, 7, null); + i = 0; + while (i < nodes.snapshotLength) { + text.push((data = nodes.snapshotItem(i++).data) ? data : '\n'); + } + return this.info.comment = text.join('').trim().replace(/\s+$/gm, ''); + }; + + Post.prototype.parseQuotes = function() { + var hash, pathname, quotelink, quotes, _i, _len, _ref; + + quotes = {}; + _ref = $$('.quotelink', this.nodes.comment); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + quotelink = _ref[_i]; + hash = quotelink.hash; + if (!hash) { + continue; + } + pathname = quotelink.pathname; + if (/catalog$/.test(pathname)) { + continue; + } + if (quotelink.hostname !== 'boards.4chan.org') { + continue; + } + this.nodes.quotelinks.push(quotelink); + if (quotelink.parentNode.parentNode.className === 'capcodeReplies') { + continue; + } + quotes["" + (pathname.split('/')[1]) + "." + hash.slice(2)] = true; + } + if (this.isClone) { + return; + } + return this.quotes = Object.keys(quotes); + }; + + Post.prototype.kill = function(file, now) { + var clone, quotelink, strong, _i, _j, _len, _len1, _ref, _ref1; + + now || (now = new Date()); + if (file) { + if (this.file.isDead) { + return; + } + this.file.isDead = true; + this.file.timeOfDeath = now; + $.addClass(this.nodes.root, 'deleted-file'); + } else { + if (this.isDead) { + return; + } + this.isDead = true; + this.timeOfDeath = now; + $.addClass(this.nodes.root, 'deleted-post'); + } + if (!(strong = $('strong.warning', this.nodes.info))) { + strong = $.el('strong', { + className: 'warning', + textContent: this.isReply ? '[Deleted]' : '[Dead]' + }); + $.after($('input', this.nodes.info), strong); + } + strong.textContent = file ? '[File deleted]' : '[Deleted]'; + if (this.isClone) { + return; + } + _ref = this.clones; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + clone = _ref[_i]; + clone.kill(file, now); + } + if (file) { + return; + } + _ref1 = Get.allQuotelinksLinkingTo(this); + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + quotelink = _ref1[_j]; + if ($.hasClass(quotelink, 'deadlink')) { + continue; + } + $.add(quotelink, $.tn('\u00A0(Dead)')); + $.addClass(quotelink, 'deadlink'); + } + }; + + Post.prototype.resurrect = function() { + var clone, quotelink, strong, _i, _j, _len, _len1, _ref, _ref1; + + delete this.isDead; + delete this.timeOfDeath; + $.rmClass(this.nodes.root, 'deleted-post'); + strong = $('strong.warning', this.nodes.info); + if (this.file && this.file.isDead) { + strong.textContent = '[File deleted]'; + } else { + $.rm(strong); + } + if (this.isClone) { + return; + } + _ref = this.clones; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + clone = _ref[_i]; + clone.resurrect(); + } + _ref1 = Get.allQuotelinksLinkingTo(this); + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + quotelink = _ref1[_j]; + if ($.hasClass(quotelink, 'deadlink')) { + quotelink.textContent = quotelink.textContent.replace('\u00A0(Dead)', ''); + $.rmClass(quotelink, 'deadlink'); + } + } + }; + + Post.prototype.addClone = function(context) { + return new Clone(this, context); + }; + + Post.prototype.rmClone = function(index) { + var clone, _i, _len, _ref; + + this.clones.splice(index, 1); + _ref = this.clones.slice(index); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + clone = _ref[_i]; + clone.nodes.root.setAttribute('data-clone', index++); + } + }; + + return Post; + + })(); + + Clone = (function(_super) { + __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; + + this.origin = origin; + this.context = context; + _ref = ['ID', 'fullID', 'board', 'thread', 'info', 'quotes', 'isReply']; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + key = _ref[_i]; + this[key] = origin[key]; + } + nodes = origin.nodes; + root = nodes.root.cloneNode(true); + post = $('.post', root); + info = $('.postInfo', post); + this.nodes = { + root: root, + post: post, + info: info, + comment: $('.postMessage', post), + quotelinks: [], + backlinks: info.getElementsByClassName('backlink') + }; + _ref1 = $$('.inline', post); + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + inline = _ref1[_j]; + $.rm(inline); + } + _ref2 = $$('.inlined', post); + for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { + inlined = _ref2[_k]; + $.rmClass(inlined, 'inlined'); + } + root.hidden = false; + $.rmClass(root, 'forwarded'); + $.rmClass(post, 'highlight'); + if (nodes.subject) { + this.nodes.subject = $('.subject', info); + } + if (nodes.name) { + this.nodes.name = $('.name', info); + } + if (nodes.email) { + this.nodes.email = $('.useremail', info); + } + if (nodes.tripcode) { + this.nodes.tripcode = $('.postertrip', info); + } + if (nodes.uniqueID) { + this.nodes.uniqueID = $('.posteruid', info); + } + if (nodes.capcode) { + this.nodes.capcode = $('.capcode', info); + } + if (nodes.flag) { + this.nodes.flag = $('.countryFlag', info); + } + if (nodes.date) { + this.nodes.date = $('.dateTime', info); + } + this.parseQuotes(); + if (origin.file) { + this.file = {}; + _ref3 = origin.file; + for (key in _ref3) { + val = _ref3[key]; + this.file[key] = val; + } + file = $('.file', post); + this.file.info = file.firstElementChild; + this.file.text = this.file.info.firstElementChild; + this.file.thumb = $('img[data-md5]', file); + this.file.fullImage = $('.full-image', file); + } + if (origin.isDead) { + this.isDead = true; + } + this.isClone = true; + index = origin.clones.push(this) - 1; + root.setAttribute('data-clone', index); + } + + return Clone; + + })(Post); + + DataBoards = ['hiddenThreads', 'hiddenPosts', 'lastReadPosts', 'yourPosts']; + + DataBoard = (function() { + function DataBoard(key, sync) { + var init, + _this = this; + + this.key = key; + this.data = Conf[key]; + $.sync(key, this.onSync.bind(this)); + this.clean(); + if (!sync) { + return; + } + init = function() { + $.off(d, '4chanXInitFinished', init); + return _this.sync = sync; + }; + $.on(d, '4chanXInitFinished', init); + } + + DataBoard.prototype["delete"] = function(_arg) { + var boardID, postID, threadID; + + boardID = _arg.boardID, threadID = _arg.threadID, postID = _arg.postID; + if (postID) { + delete this.data.boards[boardID][threadID][postID]; + this.deleteIfEmpty({ + boardID: boardID, + threadID: threadID + }); + } else if (threadID) { + delete this.data.boards[boardID][threadID]; + this.deleteIfEmpty({ + boardID: boardID + }); + } else { + delete this.data.boards[boardID]; + } + return $.set(this.key, this.data); + }; + + DataBoard.prototype.deleteIfEmpty = function(_arg) { + var boardID, threadID; + + boardID = _arg.boardID, threadID = _arg.threadID; + if (threadID) { + if (!Object.keys(this.data.boards[boardID][threadID]).length) { + delete this.data.boards[boardID][threadID]; + return this.deleteIfEmpty({ + boardID: boardID + }); + } + } else if (!Object.keys(this.data.boards[boardID]).length) { + return delete this.data.boards[boardID]; + } + }; + + DataBoard.prototype.set = function(_arg) { + var boardID, postID, threadID, val, _base, _base1, _base2; + + boardID = _arg.boardID, threadID = _arg.threadID, postID = _arg.postID, val = _arg.val; + if (postID) { + ((_base = ((_base1 = this.data.boards)[boardID] || (_base1[boardID] = {})))[threadID] || (_base[threadID] = {}))[postID] = val; + } else if (threadID) { + ((_base2 = this.data.boards)[boardID] || (_base2[boardID] = {}))[threadID] = val; + } else { + this.data.boards[boardID] = val; + } + return $.set(this.key, this.data); + }; + + DataBoard.prototype.get = function(_arg) { + var ID, board, boardID, defaultValue, postID, thread, threadID, val, _i, _len; + + boardID = _arg.boardID, threadID = _arg.threadID, postID = _arg.postID, defaultValue = _arg.defaultValue; + if (board = this.data.boards[boardID]) { + if (!threadID) { + if (postID) { + for (thread = _i = 0, _len = board.length; _i < _len; thread = ++_i) { + ID = board[thread]; + if (postID in thread) { + val = thread[postID]; + break; + } + } + } else { + val = board; + } + } else if (thread = board[threadID]) { + val = postID ? thread[postID] : thread; + } + } + return val || defaultValue; + }; + + DataBoard.prototype.clean = function() { + var boardID, now, val, _ref; + + _ref = this.data.boards; + for (boardID in _ref) { + val = _ref[boardID]; + if (typeof this.data.boards[boardID] !== 'object') { + delete this.data.boards[boardID]; + } else { + this.deleteIfEmpty({ + boardID: boardID + }); + } + } + now = Date.now(); + if ((this.data.lastChecked || 0) < now - 2 * $.HOUR) { + this.data.lastChecked = now; + for (boardID in this.data.boards) { + this.ajaxClean(boardID); + } + } + return $.set(this.key, this.data); + }; + + DataBoard.prototype.ajaxClean = function(boardID) { + var _this = this; + + return $.cache("//api.4chan.org/" + boardID + "/threads.json", function(e) { + var board, page, thread, threads, _i, _j, _len, _len1, _ref, _ref1; + + if (e.target.status === 404) { + _this["delete"](boardID); + } else if (e.target.status === 200) { + board = _this.data.boards[boardID]; + threads = {}; + _ref = JSON.parse(e.target.response); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + page = _ref[_i]; + _ref1 = page.threads; + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + thread = _ref1[_j]; + if (thread.no in board) { + threads[thread.no] = board[thread.no]; + } + } + } + _this.data.boards[boardID] = threads; + _this.deleteIfEmpty({ + boardID: boardID + }); + } + return $.set(_this.key, _this.data); + }); + }; + + DataBoard.prototype.onSync = function(data) { + this.data = data || { + boards: {} + }; + return typeof this.sync === "function" ? this.sync() : void 0; + }; + + return DataBoard; + + })(); + + Notification = (function() { + function Notification(type, content, timeout) { + this.timeout = timeout; + this.close = __bind(this.close, this); + this.add = __bind(this.add, this); + this.el = $.el('div', { + innerHTML: '×
' + }); + this.el.style.opacity = 0; + this.setType(type); + $.on(this.el.firstElementChild, 'click', this.close); + if (typeof content === 'string') { + content = $.tn(content); + } + $.add(this.el.lastElementChild, content); + $.ready(this.add); + } + + Notification.prototype.setType = function(type) { + return this.el.className = "notification " + type; + }; + + Notification.prototype.add = function() { + if (d.hidden) { + $.on(d, 'visibilitychange', this.add); + return; + } + $.off(d, 'visibilitychange', this.add); + $.add($.id('notifications'), this.el); + this.el.clientHeight; + this.el.style.opacity = 1; + if (this.timeout) { + return setTimeout(this.close, this.timeout * $.SECOND); + } + }; + + Notification.prototype.close = function() { + return $.rm(this.el); + }; + + return Notification; + + })(); + + Polyfill = { + init: function() { + return Polyfill.visibility(); + }, + visibility: function() { + if (!('webkitHidden' in document)) { + return; + } + Object.defineProperties(HTMLDocument.prototype, { + visibilityState: { + get: function() { + return this.webkitVisibilityState; + } + }, + hidden: { + get: function() { + return this.webkitHidden; + } + } + }); + return $.on(d, 'webkitvisibilitychange', function() { + return $.event('visibilitychange'); + }); + } + }; + + Header = { + init: function() { + var barFixedToggler, barPositionToggler, customNavToggler, editCustomNav, footerToggler, headerToggler, linkJustifyToggler, + _this = this; + + this.menu = new UI.Menu('header'); + this.menuButton = $.el('span', { + className: 'menu-button', + innerHTML: '' + }); + barFixedToggler = $.el('label', { + innerHTML: ' Fixed Header' + }); + headerToggler = $.el('label', { + innerHTML: ' Auto-hide header' + }); + barPositionToggler = $.el('label', { + innerHTML: ' Bottom header' + }); + linkJustifyToggler = $.el('label', { + innerHTML: " Centered links" + }); + customNavToggler = $.el('label', { + innerHTML: ' Custom board navigation' + }); + footerToggler = $.el('label', { + innerHTML: " Hide bottom board list" + }); + editCustomNav = $.el('a', { + textContent: 'Edit custom board navigation', + href: 'javascript:;' + }); + this.barFixedToggler = barFixedToggler.firstElementChild; + this.barPositionToggler = barPositionToggler.firstElementChild; + this.linkJustifyToggler = linkJustifyToggler.firstElementChild; + this.headerToggler = headerToggler.firstElementChild; + this.footerToggler = footerToggler.firstElementChild; + this.customNavToggler = customNavToggler.firstElementChild; + $.on(this.menuButton, 'click', this.menuToggle); + $.on(this.barFixedToggler, 'change', this.toggleBarFixed); + $.on(this.barPositionToggler, 'change', this.toggleBarPosition); + $.on(this.linkJustifyToggler, 'change', this.toggleLinkJustify); + $.on(this.headerToggler, 'change', this.toggleBarVisibility); + $.on(this.footerToggler, 'change', this.toggleFooterVisibility); + $.on(this.customNavToggler, 'change', this.toggleCustomNav); + $.on(editCustomNav, 'click', this.editCustomNav); + this.setBarFixed(Conf['Fixed Header']); + this.setBarVisibility(Conf['Header auto-hide']); + this.setLinkJustify(Conf['Centered links']); + $.sync('Fixed Header', Header.setBarFixed); + $.sync('Bottom Header', Header.setBarPosition); + $.sync('Header auto-hide', Header.setBarVisibility); + $.sync('Centered links', Header.setLinkJustify); + this.addShortcut(Header.menuButton); + $.event('AddMenuEntry', { + type: 'header', + el: $.el('span', { + textContent: 'Header' + }), + order: 107, + subEntries: [ + { + el: barFixedToggler + }, { + el: headerToggler + }, { + el: barPositionToggler + }, { + el: linkJustifyToggler + }, { + el: footerToggler + }, { + el: customNavToggler + }, { + el: editCustomNav + } + ] + }); + $.on(window, 'load hashchange', Header.hashScroll); + $.on(d, 'CreateNotification', this.createNotification); + $.asap((function() { + return d.body; + }), function() { + if (!Main.isThisPageLegit()) { + return; + } + $.asap((function() { + var _ref; + + return $.id('boardNavMobile') || ((_ref = d.readyState) === 'interactive' || _ref === 'complete'); + }), Header.setBoardList); + $.prepend(d.body, _this.bar); + $.add(d.body, Header.hover); + return _this.setBarPosition(Conf['Bottom Header']); + }); + return $.ready(function() { + var a, cs; + + _this.footer = $.id('boardNavDesktopFoot'); + if (a = $("a[href*='/" + g.BOARD + "/']", $.id('boardNavDesktopFoot'))) { + a.className = 'current'; + } + cs = $.el('a', { + id: 'settingsWindowLink', + href: 'javascript:;', + textContent: 'Catalog Settings' + }); + if (g.VIEW === 'catalog') { + _this.addShortcut(cs); + } + Header.setFooterVisibility(Conf['Bottom Board List']); + return $.sync('Bottom Board List', Header.setFooterVisibility); + }); + }, + bar: $.el('div', { + id: 'header-bar' + }), + notify: $.el('div', { + id: 'notifications' + }), + shortcuts: $.el('span', { + id: 'shortcuts' + }), + hover: $.el('div', { + id: 'hoverUI' + }), + toggle: $.el('div', { + id: 'scroll-marker' + }), + setBoardList: function() { + var a, boardList, btn, fourchannav, fullBoardList; + + fourchannav = $.id('boardNavDesktop'); + if (a = $("a[href*='/" + g.BOARD + "/']", fourchannav)) { + a.className = 'current'; + } + boardList = $.el('span', { + id: 'board-list', + innerHTML: "" + }); + fullBoardList = $('#full-board-list', boardList); + btn = $('.hide-board-list-button', fullBoardList); + $.on(btn, 'click', Header.toggleBoardList); + $.rm($('#navtopright', fullBoardList)); + $.add(boardList, fullBoardList); + $.add(Header.bar, [boardList, Header.shortcuts, Header.notify, Header.toggle]); + Header.setCustomNav(Conf['Custom Board Navigation']); + Header.generateBoardList(Conf['boardnav'].replace(/(\r\n|\n|\r)/g, ' ')); + $.sync('Custom Board Navigation', Header.setCustomNav); + return $.sync('boardnav', Header.generateBoardList); + }, + generateBoardList: function(text) { + var as, list, nodes; + + list = $('#custom-board-list', Header.bar); + $.rmAll(list); + if (!text) { + return; + } + as = $$('#full-board-list a', 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; + + if (/^[^\w@]/.test(t)) { + return $.tn(t); + } + if (/^toggle-all/.test(t)) { + a = $.el('a', { + className: 'show-board-list-button', + textContent: (t.match(/-text:"(.+)"/) || [null, '+'])[1], + href: 'javascript:;' + }); + $.on(a, 'click', Header.toggleBoardList); + return a; + } + if (/^external/.test(t)) { + a = $.el('a', { + href: (t.match(/\,"(.+)"/) || [null, '+'])[1], + textContent: (t.match(/-text:"(.+)"\,/) || [null, '+'])[1], + className: 'external' + }); + return a; + } + board = /^current/.test(t) ? g.BOARD.ID : t.match(/^[^-]+/)[0]; + for (_i = 0, _len = as.length; _i < _len; _i++) { + a = as[_i]; + if (a.textContent === board) { + 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.href = "//boards.4chan.org/" + board + "/"; + if (m[1] === 'catalog') { + a.href += 'catalog'; + $.addClass(a, 'catalog'); + } + } + if (board === '@') { + $.addClass(a, 'navSmall'); + } + return a; + } + } + return $.tn(t); + }); + return $.add(list, nodes); + }, + toggleBoardList: function() { + var bar, custom, full, showBoardList; + + bar = Header.bar; + custom = $('#custom-board-list', bar); + full = $('#full-board-list', bar); + showBoardList = !full.hidden; + custom.hidden = !showBoardList; + return full.hidden = showBoardList; + }, + setBarPosition: function(bottom) { + Header.barPositionToggler.checked = bottom; + if (bottom) { + $.rmClass(doc, 'top'); + $.addClass(doc, 'bottom'); + return $.after(Header.bar, Header.notify); + } else { + $.rmClass(doc, 'bottom'); + $.addClass(doc, 'top'); + return $.add(Header.bar, Header.notify); + } + }, + setLinkJustify: function(centered) { + Header.linkJustifyToggler.checked = centered; + if (centered) { + return $.addClass(doc, 'centered-links'); + } else { + return $.rmClass(doc, 'centered-links'); + } + }, + toggleBarPosition: function() { + $.event('CloseMenu'); + Header.setBarPosition(this.checked); + Conf['Bottom Header'] = this.checked; + return $.set('Bottom Header', this.checked); + }, + toggleLinkJustify: function() { + var centered; + + $.event('CloseMenu'); + centered = this.nodeName === 'INPUT' ? this.checked : void 0; + Header.setLinkJustify(centered); + return $.set('Centered links', centered); + }, + setBarFixed: function(fixed) { + Header.barFixedToggler.checked = fixed; + if (fixed) { + $.addClass(doc, 'fixed'); + return $.addClass(Header.bar, 'dialog'); + } else { + $.rmClass(doc, 'fixed'); + return $.rmClass(Header.bar, 'dialog'); + } + }, + toggleBarFixed: function() { + $.event('CloseMenu'); + Header.setBarFixed(this.checked); + Conf['Fixed Header'] = this.checked; + return $.set('Fixed Header', this.checked); + }, + setBarVisibility: function(hide) { + Header.headerToggler.checked = hide; + $.event('CloseMenu'); + (hide ? $.addClass : $.rmClass)(Header.bar, 'autohide'); + return (hide ? $.addClass : $.rmClass)(doc, 'autohide'); + }, + toggleBarVisibility: function(e) { + var hide, message; + + if (e.type === 'mousedown' && e.button !== 0) { + return; + } + hide = this.nodeName === 'INPUT' ? this.checked : !$.hasClass(Header.bar, 'autohide'); + Conf['Header auto-hide'] = hide; + $.set('Header auto-hide', hide); + Header.setBarVisibility(hide); + message = hide ? 'The header bar will automatically hide itself.' : 'The header bar will remain visible.'; + return new Notification('info', message, 2); + }, + setFooterVisibility: function(hide) { + Header.footerToggler.checked = hide; + return Header.footer.hidden = hide; + }, + toggleFooterVisibility: function() { + var hide, message; + + $.event('CloseMenu'); + hide = this.nodeName === 'INPUT' ? this.checked : !!Header.footer.hidden; + Header.setFooterVisibility(hide); + $.set('Bottom Board List', hide); + message = hide ? 'The bottom navigation will now be hidden.' : 'The bottom navigation will remain visible.'; + return new Notification('info', message, 2); + }, + setCustomNav: function(show) { + var btn, cust, full, _ref; + + Header.customNavToggler.checked = show; + cust = $('#custom-board-list', Header.bar); + full = $('#full-board-list', Header.bar); + btn = $('.hide-board-list-button', full); + return _ref = show ? [false, true] : [true, false], cust.hidden = _ref[0], full.hidden = _ref[1], _ref; + }, + toggleCustomNav: function() { + $.cb.checked.call(this); + return Header.setCustomNav(this.checked); + }, + editCustomNav: function() { + var settings; + + Settings.open('Advanced'); + settings = $.id('fourchanx-settings'); + return $('input[name=boardnav]', settings).focus(); + }, + hashScroll: function() { + var hash, post; + + if (!((hash = this.location.hash) && (post = $.id(hash.slice(1))))) { + return; + } + if ((Get.postFromRoot(post)).isHidden) { + return; + } + return Header.scrollToPost(post); + }, + scrollToPost: function(post) { + var headRect, top; + + top = post.getBoundingClientRect().top; + if (Conf['Fixed Header'] && !Conf['Bottom Header']) { + headRect = Header.bar.getBoundingClientRect(); + top += -headRect.top - headRect.height; + } + return d.body.scrollTop += top; + }, + addShortcut: function(el) { + var shortcut; + + shortcut = $.el('span', { + className: 'shortcut fourchanx-link' + }); + $.add(shortcut, el); + return $.prepend(Header.shortcuts, shortcut); + }, + menuToggle: function(e) { + return Header.menu.toggle(e, this, g); + }, + createNotification: function(e) { + var cb, content, lifetime, notif, type, _ref; + + _ref = e.detail, type = _ref.type, content = _ref.content, lifetime = _ref.lifetime, cb = _ref.cb; + notif = new Notification(type, content, lifetime); + if (cb) { + return cb(notif); + } + } + }; + + Build = { + spoilerRange: {}, + shortFilename: function(filename, isReply) { + var threshold; + + threshold = isReply ? 30 : 40; + if (filename.length - 4 > threshold) { + return "" + filename.slice(0, threshold - 5) + "(...)." + filename.slice(-3); + } else { + return filename; + } + }, + postFromObject: function(data, boardID) { + var o; + + o = { + postID: data.no, + threadID: data.resto || data.no, + boardID: boardID, + name: data.name, + capcode: data.capcode, + tripcode: data.trip, + uniqueID: data.id, + email: data.email ? encodeURI(data.email.replace(/"/g, '"')) : '', + subject: data.sub, + flagCode: data.country, + flagName: data.country_name, + date: data.now, + dateUTC: data.time, + comment: data.com, + isSticky: !!data.sticky, + isClosed: !!data.closed + }; + if (data.ext || data.filedeleted) { + o.file = { + name: data.filename + data.ext, + timestamp: "" + data.tim + data.ext, + url: boardID === 'f' ? "//images.4channel.org/" + boardID + "/src/" + data.filename + data.ext : "//images.4chan.org/" + boardID + "/src/" + data.tim + data.ext, + height: data.h, + width: data.w, + MD5: data.md5, + size: data.fsize, + turl: "//thumbs.4chan.org/" + boardID + "/thumb/" + data.tim + "s.jpg", + theight: data.tn_h, + twidth: data.tn_w, + isSpoiler: !!data.spoiler, + isDeleted: !!data.filedeleted + }; + } + return Build.post(o); + }, + post: function(o, isArchived) { + /* + This function contains code from 4chan-JS (https://github.com/4chan/4chan-JS). + @license: https://github.com/4chan/4chan-JS/blob/master/LICENSE + */ + + var a, boardID, capcode, capcodeClass, capcodeStart, closed, comment, container, date, dateUTC, email, emailEnd, emailStart, ext, file, fileDims, fileHTML, fileHtml, fileInfo, fileSize, fileThumb, filename, flag, flagCode, flagName, href, imgSrc, isClosed, isOP, isSticky, name, postID, quote, shortFilename, spoilerRange, staticPath, sticky, subject, threadID, tripcode, uniqueID, userID, _i, _len, _ref; + + postID = o.postID, threadID = o.threadID, boardID = o.boardID, name = o.name, capcode = o.capcode, tripcode = o.tripcode, uniqueID = o.uniqueID, email = o.email, subject = o.subject, flagCode = o.flagCode, flagName = o.flagName, date = o.date, dateUTC = o.dateUTC, isSticky = o.isSticky, isClosed = o.isClosed, comment = o.comment, file = o.file; + isOP = postID === threadID; + staticPath = '//static.4chan.org/image/'; + if (email) { + emailStart = ''; + emailEnd = ''; + } else { + emailStart = ''; + emailEnd = ''; + } + subject = "" + (subject || '') + ""; + userID = !capcode && uniqueID ? (" (ID: ") + ("" + uniqueID + ") ") : ''; + switch (capcode) { + case 'admin': + case 'admin_highlight': + capcodeClass = " capcodeAdmin"; + capcodeStart = " ## Admin"; + capcode = (" "; + break; + case 'mod': + capcodeClass = " capcodeMod"; + capcodeStart = " ## Mod"; + capcode = (" "; + break; + case 'developer': + capcodeClass = " capcodeDeveloper"; + capcodeStart = " ## Developer"; + capcode = (" "; + break; + default: + capcodeClass = ''; + capcodeStart = ''; + capcode = ''; + } + flag = flagCode ? ("  + flagCode + ") : ''; + if (file != null ? file.isDeleted : void 0) { + fileHtml = isOP ? ("
") + ("File deleted.") + "
" : ("
") + ("File deleted.") + "
"; + } else if (file) { + ext = file.name.slice(-3); + if (!file.twidth && !file.theight && ext === 'gif') { + file.twidth = file.width; + file.theight = file.height; + } + fileSize = $.bytesToString(file.size); + fileThumb = file.turl; + if (file.isSpoiler) { + fileSize = "Spoiler Image, " + fileSize; + if (!isArchived) { + fileThumb = "" + staticPath + "spoiler"; + if (spoilerRange = Build.spoilerRange[boardID]) { + fileThumb += ("-" + boardID) + Math.floor(1 + spoilerRange * Math.random()); + } + fileThumb += '.png'; + file.twidth = file.theight = 100; + } + } + imgSrc = boardID === 'f' ? '' : ("") + ("" + fileSize + "") + ""; + a = $.el('a', { + innerHTML: file.name + }); + filename = a.textContent.replace(/%22/g, '"'); + a.textContent = Build.shortFilename(filename); + shortFilename = a.innerHTML; + a.textContent = filename; + filename = a.innerHTML.replace(/'/g, '''); + fileDims = ext === 'pdf' ? 'PDF' : "" + file.width + "x" + file.height; + fileInfo = ("File: " + file.timestamp + "") + ("-(" + fileSize + ", " + fileDims + (file.isSpoiler ? '' : ", " + shortFilename + "")) + ")"; + fileHTML = "
" + fileInfo + "
" + imgSrc + "
"; + } else { + fileHTML = ''; + } + tripcode = tripcode ? " " + tripcode + "" : ''; + sticky = isSticky ? " Sticky" : ''; + closed = isClosed ? " Closed" : ''; + container = $.el('div', { + id: "pc" + postID, + className: "postContainer " + (isOP ? 'op' : 'reply') + "Container", + innerHTML: (isOP ? '' : "
>>
") + ("
") + ("' + (isOP ? fileHTML : '') + ("' + (isOP ? '' : fileHTML) + ("
" + (comment || '') + "
") + '
' + }); + _ref = $$('.quotelink', container); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + quote = _ref[_i]; + href = quote.getAttribute('href'); + if (href[0] === '/') { + continue; + } + quote.href = "/" + boardID + "/res/" + href; + } + return container; + } + }; + + Get = { + threadExcerpt: function(thread) { + var OP, excerpt, _ref; + + OP = thread.OP; + excerpt = ((_ref = OP.info.subject) != null ? _ref.trim() : void 0) || OP.info.comment.replace(/\n+/g, ' // ') || Conf['Anonymize'] && 'Anonymous' || $('.nameBlock', OP.nodes.info).textContent.trim(); + if (excerpt.length > 70) { + excerpt = "" + excerpt.slice(0, 67) + "..."; + } + return "/" + thread.board + "/ - " + excerpt; + }, + threadFromRoot: function(root) { + return g.threads["" + g.BOARD + "." + root.id.slice(1)]; + }, + postFromRoot: function(root) { + var boardID, index, link, post, postID; + + link = $('a[title="Highlight this post"]', root); + boardID = link.pathname.split('/')[1]; + postID = link.hash.slice(2); + index = root.dataset.clone; + post = g.posts["" + boardID + "." + postID]; + if (index) { + return post.clones[index]; + } else { + return post; + } + }, + postFromNode: function(root) { + return Get.postFromRoot($.x('ancestor::div[contains(@class,"postContainer")][1]', root)); + }, + contextFromLink: function(quotelink) { + return Get.postFromRoot($.x('ancestor::div[parent::div[@class="thread"]][1]', quotelink)); + }, + postDataFromLink: function(link) { + var boardID, path, postID, threadID; + + if (link.hostname === 'boards.4chan.org') { + path = link.pathname.split('/'); + boardID = path[1]; + threadID = path[3]; + postID = link.hash.slice(2); + } else { + boardID = link.dataset.boardid; + threadID = link.dataset.threadid || 0; + postID = link.dataset.postid; + } + return { + boardID: boardID, + threadID: +threadID, + postID: +postID + }; + }, + allQuotelinksLinkingTo: function(post) { + var ID, quote, quotedPost, quotelinks, quoterPost, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3; + + quotelinks = []; + _ref = g.posts; + for (ID in _ref) { + quoterPost = _ref[ID]; + if (quoterPost.quotes.contains(post.fullID)) { + _ref1 = [quoterPost].concat(quoterPost.clones); + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + quoterPost = _ref1[_i]; + quotelinks.push.apply(quotelinks, quoterPost.nodes.quotelinks); + } + } + } + if (Conf['Quote Backlinks']) { + _ref2 = post.quotes; + for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { + quote = _ref2[_j]; + if (!(quotedPost = g.posts[quote])) { + continue; + } + _ref3 = [quotedPost].concat(quotedPost.clones); + for (_k = 0, _len2 = _ref3.length; _k < _len2; _k++) { + quotedPost = _ref3[_k]; + quotelinks.push.apply(quotelinks, __slice.call(quotedPost.nodes.backlinks)); + } + } + } + return quotelinks.filter(function(quotelink) { + var boardID, postID, _ref4; + + _ref4 = Get.postDataFromLink(quotelink), boardID = _ref4.boardID, postID = _ref4.postID; + return boardID === post.board.ID && postID === post.ID; + }); + }, + postClone: function(boardID, threadID, postID, root, context) { + var post, url; + + if (post = g.posts["" + boardID + "." + postID]) { + Get.insert(post, root, context); + return; + } + root.textContent = "Loading post No." + postID + "..."; + if (threadID) { + return $.cache("//api.4chan.org/" + boardID + "/res/" + threadID + ".json", function() { + return Get.fetchedPost(this, boardID, threadID, postID, root, context); + }); + } else if (url = Redirect.to('post', { + boardID: boardID, + postID: postID + })) { + return $.cache(url, function() { + return Get.archivedPost(this, boardID, postID, root, context); + }); + } + }, + insert: function(post, root, context) { + var clone, nodes; + + if (!root.parentNode) { + return; + } + clone = post.addClone(context); + Main.callbackNodes(Clone, [clone]); + nodes = clone.nodes; + $.rmAll(nodes.root); + $.add(nodes.root, nodes.post); + $.rmAll(root); + return $.add(root, nodes.root); + }, + fetchedPost: function(req, boardID, threadID, postID, root, context) { + var board, post, posts, status, thread, url, _i, _len; + + if (post = g.posts["" + boardID + "." + postID]) { + Get.insert(post, root, context); + return; + } + status = req.status; + if (![200, 304].contains(status)) { + if (url = Redirect.to('post', { + boardID: boardID, + postID: postID + })) { + $.cache(url, function() { + return Get.archivedPost(this, boardID, postID, root, context); + }); + } else { + $.addClass(root, 'warning'); + root.textContent = status === 404 ? "Thread No." + threadID + " 404'd." : "Error " + req.statusText + " (" + req.status + ")."; + } + return; + } + posts = JSON.parse(req.response).posts; + Build.spoilerRange[boardID] = posts[0].custom_spoiler; + for (_i = 0, _len = posts.length; _i < _len; _i++) { + post = posts[_i]; + if (post.no === postID) { + break; + } + if (post.no > postID) { + if (url = Redirect.to('post', { + boardID: boardID, + postID: postID + })) { + $.cache(url, function() { + return Get.archivedPost(this, boardID, postID, root, context); + }); + } else { + $.addClass(root, 'warning'); + root.textContent = "Post No." + postID + " was not found."; + } + return; + } + } + board = g.boards[boardID] || new Board(boardID); + thread = g.threads["" + boardID + "." + threadID] || new Thread(threadID, board); + post = new Post(Build.postFromObject(post, boardID), thread, board); + Main.callbackNodes(Post, [post]); + return Get.insert(post, root, context); + }, + archivedPost: function(req, boardID, postID, root, context) { + var board, bq, comment, data, o, post, thread, threadID, _ref; + + if (post = g.posts["" + boardID + "." + postID]) { + Get.insert(post, root, context); + return; + } + data = JSON.parse(req.response); + if (data.error) { + $.addClass(root, 'warning'); + root.textContent = data.error; + return; + } + bq = $.el('blockquote', { + textContent: data.comment + }); + bq.innerHTML = bq.innerHTML.replace(/\n|\[\/?b\]|\[\/?spoiler\]|\[\/?code\]|\[\/?moot\]|\[\/?banned\]/g, function(text) { + switch (text) { + case '\n': + return '
'; + case '[b]': + return ''; + case '[/b]': + return ''; + case '[spoiler]': + return ''; + case '[/spoiler]': + return ''; + case '[code]': + return '
';
+          case '[/code]':
+            return '
'; + case '[moot]': + return '
'; + case '[/moot]': + return '
'; + case '[banned]': + return ''; + case '[/banned]': + return ''; + } + }); + comment = bq.innerHTML.replace(/(^|>)(>[^<$]*)(<|$)/g, '$1$2$3').replace(/((>){2}(>\/[a-z\d]+\/)?\d+)/g, '$1'); + threadID = data.thread_num; + o = { + postID: "" + postID, + threadID: "" + threadID, + boardID: boardID, + name: data.name_processed, + capcode: (function() { + switch (data.capcode) { + case 'M': + return 'mod'; + case 'A': + return 'admin'; + case 'D': + return 'developer'; + } + })(), + tripcode: data.trip, + uniqueID: data.poster_hash, + email: data.email ? encodeURI(data.email) : '', + subject: data.title_processed, + flagCode: data.poster_country, + flagName: data.poster_country_name_processed, + date: data.fourchan_date, + dateUTC: data.timestamp, + comment: comment + }; + if ((_ref = data.media) != null ? _ref.media_filename : void 0) { + o.file = { + name: data.media.media_filename_processed, + timestamp: data.media.media_orig, + url: data.media.media_link || data.media.remote_media_link, + height: data.media.media_h, + width: data.media.media_w, + MD5: data.media.media_hash, + size: data.media.media_size, + turl: data.media.thumb_link || ("//thumbs.4chan.org/" + boardID + "/thumb/" + data.media.preview_orig), + theight: data.media.preview_h, + twidth: data.media.preview_w, + isSpoiler: data.media.spoiler === '1' + }; + } + board = g.boards[boardID] || new Board(boardID); + thread = g.threads["" + boardID + "." + threadID] || new Thread(threadID, board); + post = new Post(Build.post(o, true), thread, board, { + isArchived: true + }); + Main.callbackNodes(Post, [post]); + return Get.insert(post, root, context); + } + }; + + UI = (function() { + var Menu, dialog, drag, dragend, dragstart, hover, hoverend, hoverstart, touchend, touchmove; + + dialog = function(id, position, html) { + var child, el, move, _i, _len, _ref; + + el = $.el('div', { + className: 'dialog', + innerHTML: html, + id: id + }); + el.style.cssText = position; + $.get("" + id + ".position", position, function(item) { + return el.style.cssText = item["" + id + ".position"]; + }); + move = $('.move', el); + $.on(move, 'touchstart mousedown', dragstart); + _ref = move.children; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + child = _ref[_i]; + if (!child.tagName) { + continue; + } + $.on(child, 'touchstart mousedown', function(e) { + return e.stopPropagation(); + }); + } + return el; + }; + Menu = (function() { + var close, currentMenu, lastToggledButton; + + currentMenu = null; + + lastToggledButton = null; + + function Menu(type) { + this.type = type; + $.on(d, 'AddMenuEntry', this.addEntry.bind(this)); + this.close = close.bind(this); + this.entries = []; + } + + Menu.prototype.makeMenu = function() { + var menu; + + menu = $.el('div', { + className: 'dialog', + id: 'menu', + tabIndex: 0 + }); + $.on(menu, 'click', function(e) { + return e.stopPropagation(); + }); + $.on(menu, 'keydown', this.keybinds.bind(this)); + return menu; + }; + + Menu.prototype.toggle = function(e, button, data) { + var previousButton; + + e.preventDefault(); + e.stopPropagation(); + if (currentMenu) { + previousButton = lastToggledButton; + this.close(); + if (previousButton === button) { + return; + } + } + if (!this.entries.length) { + return; + } + return this.open(button, data); + }; + + Menu.prototype.open = function(button, data) { + var bLeft, bRect, bTop, bottom, cHeight, cWidth, entry, left, mRect, menu, right, style, top, _i, _len, _ref, _ref1, _ref2; + + menu = this.makeMenu(); + currentMenu = menu; + lastToggledButton = button; + this.entries.sort(function(first, second) { + return first.order - second.order; + }); + _ref = this.entries; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + entry = _ref[_i]; + this.insertEntry(entry, menu, data); + } + $.on(d, 'click', this.close); + $.on(d, 'CloseMenu', this.close); + $.add(Header.hover, menu); + mRect = menu.getBoundingClientRect(); + bRect = button.getBoundingClientRect(); + bTop = doc.scrollTop + d.body.scrollTop + bRect.top; + bLeft = doc.scrollLeft + d.body.scrollLeft + bRect.left; + cHeight = doc.clientHeight; + cWidth = doc.clientWidth; + _ref1 = bRect.top + bRect.height + mRect.height < cHeight ? [bRect.bottom, null] : [null, cHeight - bRect.top], top = _ref1[0], bottom = _ref1[1]; + _ref2 = bRect.left + mRect.width < cWidth ? [bRect.left, null] : [null, cWidth - bRect.right], left = _ref2[0], right = _ref2[1]; + style = menu.style; + style.top = "" + top + "px"; + style.right = "" + right + "px"; + style.bottom = "" + bottom + "px"; + style.left = "" + left + "px"; + if (right) { + $.addClass(menu, 'left'); + } + entry = $('.entry', menu); + this.focus(entry); + return menu.focus(); + }; + + Menu.prototype.insertEntry = function(entry, parent, data) { + var subEntry, submenu, _i, _len, _ref; + + if (typeof entry.open === 'function') { + if (!entry.open(data)) { + return; + } + } + $.add(parent, entry.el); + if (!entry.subEntries) { + return; + } + if (submenu = $('.submenu', entry.el)) { + $.rm(submenu); + } + submenu = $.el('div', { + className: 'dialog submenu' + }); + _ref = entry.subEntries; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + subEntry = _ref[_i]; + this.insertEntry(subEntry, submenu, data); + } + $.add(entry.el, submenu); + }; + + close = function() { + $.rm(currentMenu); + currentMenu = null; + lastToggledButton = null; + return $.off(d, 'click CloseMenu', this.close); + }; + + Menu.prototype.findNextEntry = function(entry, direction) { + var entries; + + entries = __slice.call(entry.parentNode.children); + entries.sort(function(first, second) { + return +(first.style.order || first.style.webkitOrder) - +(second.style.order || second.style.webkitOrder); + }); + return entries[entries.indexOf(entry) + direction]; + }; + + Menu.prototype.keybinds = function(e) { + var entry, next, nextPrev, subEntry, submenu; + + entry = $('.focused', currentMenu); + while (subEntry = $('.focused', entry)) { + entry = subEntry; + } + switch (e.keyCode) { + case 27: + lastToggledButton.focus(); + this.close(); + break; + case 13: + case 32: + entry.click(); + break; + case 38: + if (next = this.findNextEntry(entry, -1)) { + this.focus(next); + } + break; + case 40: + if (next = this.findNextEntry(entry, +1)) { + this.focus(next); + } + break; + case 39: + if ((submenu = $('.submenu', entry)) && (next = submenu.firstElementChild)) { + while (nextPrev = this.findNextEntry(next, -1)) { + next = nextPrev; + } + this.focus(next); + } + break; + case 37: + if (next = $.x('parent::*[contains(@class,"submenu")]/parent::*', entry)) { + this.focus(next); + } + break; + default: + return; + } + e.preventDefault(); + return e.stopPropagation(); + }; + + Menu.prototype.focus = function(entry) { + var bottom, cHeight, cWidth, eRect, focused, left, right, sRect, style, submenu, top, _i, _len, _ref, _ref1, _ref2; + + while (focused = $.x('parent::*/child::*[contains(@class,"focused")]', entry)) { + $.rmClass(focused, 'focused'); + } + _ref = $$('.focused', entry); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + focused = _ref[_i]; + $.rmClass(focused, 'focused'); + } + $.addClass(entry, 'focused'); + if (!(submenu = $('.submenu', entry))) { + return; + } + sRect = submenu.getBoundingClientRect(); + eRect = entry.getBoundingClientRect(); + cHeight = doc.clientHeight; + cWidth = doc.clientWidth; + _ref1 = eRect.top + sRect.height < cHeight ? ['0px', 'auto'] : ['auto', '0px'], top = _ref1[0], bottom = _ref1[1]; + _ref2 = eRect.right + sRect.width < cWidth ? ['100%', 'auto'] : ['auto', '100%'], left = _ref2[0], right = _ref2[1]; + style = submenu.style; + style.top = top; + style.bottom = bottom; + style.left = left; + return style.right = right; + }; + + Menu.prototype.addEntry = function(e) { + var entry; + + entry = e.detail; + if (entry.type !== this.type) { + return; + } + this.parseEntry(entry); + return this.entries.push(entry); + }; + + Menu.prototype.parseEntry = function(entry) { + var el, style, subEntries, subEntry, _i, _len; + + el = entry.el, subEntries = entry.subEntries; + $.addClass(el, 'entry'); + $.on(el, 'focus mouseover', (function(e) { + e.stopPropagation(); + return this.focus(el); + }).bind(this)); + style = el.style; + style.webkitOrder = style.order = entry.order || 100; + if (!subEntries) { + return; + } + $.addClass(el, 'has-submenu'); + for (_i = 0, _len = subEntries.length; _i < _len; _i++) { + subEntry = subEntries[_i]; + this.parseEntry(subEntry); + } + }; + + return Menu; + + })(); + dragstart = function(e) { + var el, isTouching, o, rect, screenHeight, screenWidth, _ref; + + if (e.type === 'mousedown' && e.button !== 0) { + return; + } + e.preventDefault(); + if (isTouching = e.type === 'touchstart') { + e = e.changedTouches[e.changedTouches.length - 1]; + } + el = $.x('ancestor::div[contains(@class,"dialog")][1]', this); + rect = el.getBoundingClientRect(); + screenHeight = doc.clientHeight; + screenWidth = doc.clientWidth; + o = { + id: el.id, + style: el.style, + dx: e.clientX - rect.left, + dy: e.clientY - rect.top, + height: screenHeight - rect.height, + width: screenWidth - rect.width, + screenHeight: screenHeight, + screenWidth: screenWidth, + isTouching: isTouching + }; + _ref = Conf['Header auto-hide'] || !Conf['Fixed Header'] ? [0, 0] : Conf['Bottom Header'] ? [0, Header.bar.getBoundingClientRect().height] : [Header.bar.getBoundingClientRect().height, 0], o.topBorder = _ref[0], o.bottomBorder = _ref[1]; + if (isTouching) { + o.identifier = e.identifier; + o.move = touchmove.bind(o); + o.up = touchend.bind(o); + $.on(d, 'touchmove', o.move); + return $.on(d, 'touchend touchcancel', o.up); + } else { + o.move = drag.bind(o); + o.up = dragend.bind(o); + $.on(d, 'mousemove', o.move); + return $.on(d, 'mouseup', o.up); + } + }; + touchmove = function(e) { + var touch, _i, _len, _ref; + + _ref = e.changedTouches; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + touch = _ref[_i]; + if (touch.identifier === this.identifier) { + drag.call(this, touch); + return; + } + } + }; + drag = function(e) { + var bottom, clientX, clientY, left, right, style, top; + + clientX = e.clientX, clientY = e.clientY; + left = clientX - this.dx; + left = left < 10 ? 0 : this.width - left < 10 ? null : left / this.screenWidth * 100 + '%'; + top = clientY - this.dy; + top = top < (10 + this.topBorder) ? this.topBorder + 'px' : this.height - top < (10 + this.bottomBorder) ? null : top / this.screenHeight * 100 + '%'; + right = left === null ? 0 : null; + bottom = top === null ? this.bottomBorder + 'px' : null; + style = this.style; + style.left = left; + style.right = right; + style.top = top; + return style.bottom = bottom; + }; + touchend = function(e) { + var touch, _i, _len, _ref; + + _ref = e.changedTouches; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + touch = _ref[_i]; + if (touch.identifier === this.identifier) { + dragend.call(this); + return; + } + } + }; + dragend = function() { + if (this.isTouching) { + $.off(d, 'touchmove', this.move); + $.off(d, 'touchend touchcancel', this.up); + } else { + $.off(d, 'mousemove', this.move); + $.off(d, 'mouseup', this.up); + } + return $.set("" + this.id + ".position", this.style.cssText); + }; + hoverstart = function(_arg) { + var asapTest, cb, el, endEvents, latestEvent, o, root; + + root = _arg.root, el = _arg.el, latestEvent = _arg.latestEvent, endEvents = _arg.endEvents, asapTest = _arg.asapTest, cb = _arg.cb; + o = { + root: root, + el: el, + style: el.style, + cb: cb, + endEvents: endEvents, + latestEvent: latestEvent, + clientHeight: doc.clientHeight, + clientWidth: doc.clientWidth + }; + o.hover = hover.bind(o); + o.hoverend = hoverend.bind(o); + $.asap(function() { + return !el.parentNode || asapTest(); + }, function() { + if (el.parentNode) { + return o.hover(o.latestEvent); + } + }); + $.on(root, endEvents, o.hoverend); + if ($.x('ancestor::div[contains(@class,"inline")][1]', root)) { + $.on(d, 'keydown', o.hoverend); + } + return $.on(root, 'mousemove', o.hover); + }; + hover = function(e) { + var clientX, clientY, height, left, right, style, top, _ref; + + this.latestEvent = e; + height = this.el.offsetHeight; + clientX = e.clientX, clientY = e.clientY; + top = clientY - 120; + top = this.clientHeight <= height || top <= 0 ? 0 : top + height >= this.clientHeight ? this.clientHeight - height : top; + _ref = clientX <= this.clientWidth - 400 ? [clientX + 45 + 'px', null] : [null, this.clientWidth - clientX + 45 + 'px'], left = _ref[0], right = _ref[1]; + style = this.style; + style.top = top + 'px'; + style.left = left; + return style.right = right; + }; + hoverend = function(e) { + if (e.type === 'keydown' && e.keyCode !== 13 || e.target.nodeName === "TEXTAREA") { + return; + } + $.rm(this.el); + $.off(this.root, this.endEvents, this.hoverend); + $.off(d, 'keydown', this.hoverend); + $.off(this.root, 'mousemove', this.hover); + if (this.cb) { + return this.cb.call(this); + } + }; + return { + dialog: dialog, + Menu: Menu, + hover: hoverstart + }; + })(); + + Anonymize = { + init: function() { + if (g.VIEW === 'catalog' || !Conf['Anonymize']) { + return; + } + return Post.prototype.callbacks.push({ + name: 'Anonymize', + cb: this.node + }); + }, + node: function() { + var email, name, tripcode, _ref; + + if (this.info.capcode || this.isClone) { + return; + } + _ref = this.nodes, name = _ref.name, tripcode = _ref.tripcode, email = _ref.email; + if (this.info.name !== 'Anonymous') { + name.textContent = 'Anonymous'; + } + if (tripcode) { + $.rm(tripcode); + delete this.nodes.tripcode; + } + if (this.info.email) { + if (/sage/i.test(this.info.email)) { + return email.href = 'mailto:sage'; + } else { + $.replace(email, name); + return delete this.nodes.email; + } + } + } + }; + + Filter = { + filters: {}, + init: function() { + var boards, err, filter, hl, key, op, regexp, stub, top, _i, _len, _ref, _ref1, _ref2, _ref3, _ref4; + + if (g.VIEW === 'catalog' || !Conf['Filter']) { + return; + } + if (!Conf['Filtered Backlinks']) { + $.addClass(doc, 'hide-backlinks'); + } + for (key in Config.filter) { + this.filters[key] = []; + if (Conf[key] === void 0) { + $["delete"](key); + continue; + } + _ref = Conf[key].split('\n'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + filter = _ref[_i]; + if (filter[0] === '#') { + continue; + } + if (!(regexp = filter.match(/\/(.+)\/(\w*)/))) { + continue; + } + filter = filter.replace(regexp[0], ''); + boards = ((_ref1 = filter.match(/boards:([^;]+)/)) != null ? _ref1[1].toLowerCase() : void 0) || 'global'; + if (boards !== 'global' && !(boards.split(',')).contains(g.BOARD.ID)) { + continue; + } + if (['uniqueID', 'MD5'].contains(key)) { + regexp = regexp[1]; + } else { + try { + regexp = RegExp(regexp[1], regexp[2]); + } catch (_error) { + err = _error; + new Notification('warning', err.message, 60); + continue; + } + } + op = ((_ref2 = filter.match(/[^t]op:(yes|no|only)/)) != null ? _ref2[1] : void 0) || 'yes'; + stub = (function() { + var _ref3; + + switch ((_ref3 = filter.match(/stub:(yes|no)/)) != null ? _ref3[1] : void 0) { + case 'yes': + return true; + case 'no': + return false; + default: + return Conf['Stubs']; + } + })(); + if (hl = /highlight/.test(filter)) { + hl = ((_ref3 = filter.match(/highlight:(\w+)/)) != null ? _ref3[1] : void 0) || 'filter-highlight'; + top = ((_ref4 = filter.match(/top:(yes|no)/)) != null ? _ref4[1] : void 0) || 'yes'; + top = top === 'yes'; + } + this.filters[key].push(this.createFilter(regexp, op, stub, hl, top)); + } + if (!this.filters[key].length) { + delete this.filters[key]; + } + } + if (!Object.keys(this.filters).length) { + return; + } + return Post.prototype.callbacks.push({ + name: 'Filter', + cb: this.node + }); + }, + createFilter: function(regexp, op, stub, hl, top) { + var settings, test; + + test = typeof regexp === 'string' ? function(value) { + return regexp === value; + } : function(value) { + return regexp.test(value); + }; + settings = { + hide: !hl, + stub: stub, + "class": hl, + top: top + }; + return function(value, isReply) { + if (isReply && op === 'only' || !isReply && op === 'no') { + return false; + } + if (!test(value)) { + return false; + } + return settings; + }; + }, + node: function() { + var filter, firstThread, key, result, thisThread, value, _i, _len, _ref; + + if (this.isClone) { + return; + } + for (key in Filter.filters) { + value = Filter[key](this); + if (value === false) { + continue; + } + _ref = Filter.filters[key]; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + filter = _ref[_i]; + if (!(result = filter(value, this.isReply))) { + continue; + } + if (result.hide) { + if (this.isReply) { + PostHiding.hide(this, result.stub); + } else if (g.VIEW === 'index') { + ThreadHiding.hide(this.thread, result.stub); + } else { + continue; + } + return; + } + $.addClass(this.nodes.root, result["class"]); + if (!this.isReply && result.top && g.VIEW === 'index') { + thisThread = this.nodes.root.parentNode; + if (firstThread = $('div[class="postContainer opContainer"]')) { + if (firstThread !== this.nodes.root) { + $.before(firstThread.parentNode, [thisThread, thisThread.nextElementSibling]); + } + } + } + } + } + }, + name: function(post) { + if ('name' in post.info) { + return post.info.name; + } + return false; + }, + uniqueID: function(post) { + if ('uniqueID' in post.info) { + return post.info.uniqueID; + } + return false; + }, + tripcode: function(post) { + if ('tripcode' in post.info) { + return post.info.tripcode; + } + return false; + }, + capcode: function(post) { + if ('capcode' in post.info) { + return post.info.capcode; + } + return false; + }, + email: function(post) { + if ('email' in post.info) { + return post.info.email; + } + return false; + }, + subject: function(post) { + if ('subject' in post.info) { + return post.info.subject || false; + } + return false; + }, + comment: function(post) { + if ('comment' in post.info) { + return post.info.comment; + } + return false; + }, + flag: function(post) { + if ('flag' in post.info) { + return post.info.flag; + } + return false; + }, + filename: function(post) { + if (post.file) { + return post.file.name; + } + return false; + }, + dimensions: function(post) { + if (post.file && post.file.isImage) { + return post.file.dimensions; + } + return false; + }, + filesize: function(post) { + if (post.file) { + return post.file.size; + } + return false; + }, + MD5: function(post) { + if (post.file) { + return post.file.MD5; + } + return false; + }, + menu: { + init: function() { + var div, entry, type, _i, _len, _ref; + + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Filter']) { + return; + } + div = $.el('div', { + textContent: 'Filter' + }); + entry = { + type: 'post', + el: div, + order: 50, + open: function(post) { + Filter.menu.post = post; + return true; + }, + subEntries: [] + }; + _ref = [['Name', 'name'], ['Unique ID', 'uniqueID'], ['Tripcode', 'tripcode'], ['Capcode', 'capcode'], ['E-mail', 'email'], ['Subject', 'subject'], ['Comment', 'comment'], ['Flag', 'flag'], ['Filename', 'filename'], ['Image dimensions', 'dimensions'], ['Filesize', 'filesize'], ['Image MD5', 'MD5']]; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + type = _ref[_i]; + entry.subEntries.push(Filter.menu.createSubEntry(type[0], type[1])); + } + return $.event('AddMenuEntry', entry); + }, + createSubEntry: function(text, type) { + var el; + + el = $.el('a', { + href: 'javascript:;', + textContent: text + }); + el.setAttribute('data-type', type); + $.on(el, 'click', Filter.menu.makeFilter); + return { + el: el, + open: function(post) { + var value; + + value = Filter[type](post); + return value !== false; + } + }; + }, + makeFilter: function() { + var re, type, value; + + type = this.dataset.type; + value = Filter[type](Filter.menu.post); + re = ['uniqueID', 'MD5'].contains(type) ? value : value.replace(/\/|\\|\^|\$|\n|\.|\(|\)|\{|\}|\[|\]|\?|\*|\+|\|/g, function(c) { + if (c === '\n') { + return '\\n'; + } else if (c === '\\') { + return '\\\\'; + } else { + return "\\" + c; + } + }); + re = ['uniqueID', 'MD5'].contains(type) ? "/" + re + "/" : "/^" + re + "$/"; + return $.get(type, Conf[type], function(item) { + var save, section, select, ta, tl; + + save = item[type]; + save = save ? "" + save + "\n" + re : re; + $.set(type, save); + Settings.open('Filter'); + section = $('.section-container'); + select = $('select[name=filter]', section); + select.value = type; + Settings.selectFilter.call(select); + ta = $('textarea', section); + tl = ta.textLength; + ta.setSelectionRange(tl, tl); + return ta.focus(); + }); + } + } + }; + + PostHiding = { + init: function() { + if (g.VIEW === 'catalog' || !Conf['Reply Hiding Buttons'] && !Conf['Reply Hiding Link']) { + return; + } + if (Conf['Reply Hiding Buttons']) { + $.addClass(doc, "reply-hide"); + } + this.db = new DataBoard('hiddenPosts'); + return Post.prototype.callbacks.push({ + name: 'Reply Hiding', + cb: this.node + }); + }, + node: function() { + var data; + + if (!this.isReply || this.isClone) { + return; + } + if (data = PostHiding.db.get({ + boardID: this.board.ID, + threadID: this.thread.ID, + postID: this.ID + })) { + if (data.thisPost) { + PostHiding.hide(this, data.makeStub, data.hideRecursively); + } else { + Recursive.apply(PostHiding.hide, this, data.makeStub, true); + Recursive.add(PostHiding.hide, this, data.makeStub, true); + } + } + if (!Conf['Reply Hiding Buttons']) { + return; + } + return $.replace($('.sideArrows', this.nodes.root), PostHiding.makeButton(this, 'hide')); + }, + menu: { + init: function() { + var apply, div, hideStubLink, makeStub, replies, thisPost; + + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Reply Hiding Link']) { + return; + } + div = $.el('div', { + className: 'hide-reply-link', + textContent: 'Hide reply' + }); + apply = $.el('a', { + textContent: 'Apply', + href: 'javascript:;' + }); + $.on(apply, 'click', PostHiding.menu.hide); + thisPost = $.el('label', { + innerHTML: ' This post' + }); + replies = $.el('label', { + innerHTML: " Hide replies" + }); + makeStub = $.el('label', { + innerHTML: " Make stub" + }); + $.event('AddMenuEntry', { + type: 'post', + el: div, + order: 20, + open: function(post) { + if (!post.isReply || post.isClone || post.isHidden) { + return false; + } + PostHiding.menu.post = post; + return true; + }, + subEntries: [ + { + el: apply + }, { + el: thisPost + }, { + el: replies + }, { + el: makeStub + } + ] + }); + div = $.el('div', { + className: 'show-reply-link', + textContent: 'Show reply' + }); + apply = $.el('a', { + textContent: 'Apply', + href: 'javascript:;' + }); + $.on(apply, 'click', PostHiding.menu.show); + thisPost = $.el('label', { + innerHTML: ' This post' + }); + replies = $.el('label', { + innerHTML: " Show replies" + }); + hideStubLink = $.el('a', { + textContent: 'Hide stub', + href: 'javascript:;' + }); + $.on(hideStubLink, 'click', PostHiding.menu.hideStub); + $.event('AddMenuEntry', { + type: 'post', + el: div, + order: 20, + open: function(post) { + var data; + + if (!post.isReply || post.isClone || !post.isHidden) { + return false; + } + if (!(data = PostHiding.db.get({ + boardID: post.board.ID, + threadID: post.thread.ID, + postID: post.ID + }))) { + return false; + } + PostHiding.menu.post = post; + thisPost.firstChild.checked = post.isHidden; + replies.firstChild.checked = (data != null ? data.hideRecursively : void 0) != null ? data.hideRecursively : Conf['Recursive Hiding']; + return true; + }, + subEntries: [ + { + el: apply + }, { + el: thisPost + }, { + el: replies + } + ] + }); + return $.event('AddMenuEntry', { + type: 'post', + el: hideStubLink, + order: 15, + open: function(post) { + var data; + + if (!post.isReply || post.isClone || !post.isHidden) { + return false; + } + if (!(data = PostHiding.db.get({ + boardID: post.board.ID, + threadID: post.thread.ID, + postID: post.ID + }))) { + return false; + } + return PostHiding.menu.post = post; + } + }); + }, + hide: function() { + var makeStub, parent, post, replies, thisPost; + + parent = this.parentNode; + thisPost = $('input[name=thisPost]', parent).checked; + replies = $('input[name=replies]', parent).checked; + makeStub = $('input[name=makeStub]', parent).checked; + post = PostHiding.menu.post; + if (thisPost) { + PostHiding.hide(post, makeStub, replies); + } else if (replies) { + Recursive.apply(PostHiding.hide, post, makeStub, true); + Recursive.add(PostHiding.hide, post, makeStub, true); + } else { + return; + } + PostHiding.saveHiddenState(post, true, thisPost, makeStub, replies); + return $.event('CloseMenu'); + }, + show: function() { + var data, parent, post, replies, thisPost; + + parent = this.parentNode; + thisPost = $('input[name=thisPost]', parent).checked; + replies = $('input[name=replies]', parent).checked; + post = PostHiding.menu.post; + if (thisPost) { + PostHiding.show(post, replies); + } else if (replies) { + Recursive.apply(PostHiding.show, post, true); + Recursive.rm(PostHiding.hide, post, true); + } else { + return; + } + if (data = PostHiding.db.get({ + boardID: post.board.ID, + threadID: post.thread.ID, + postID: post.ID + })) { + PostHiding.saveHiddenState(post, !(thisPost && replies), !thisPost, data.makeStub, !replies); + } + return $.event('CloseMenu'); + }, + hideStub: function() { + var post; + + post = PostHiding.menu.post; + post.nodes.root.hidden = true; + $.event('CloseMenu'); + } + }, + makeButton: function(post, type) { + var a; + + a = $.el('a', { + className: "" + type + "-reply-button", + innerHTML: " " + (type === 'hide' ? '-' : '+') + " ", + href: 'javascript:;' + }); + $.on(a, 'click', PostHiding.toggle); + return a; + }, + saveHiddenState: function(post, isHiding, thisPost, makeStub, hideRecursively) { + var data; + + data = { + boardID: post.board.ID, + threadID: post.thread.ID, + postID: post.ID + }; + if (isHiding) { + data.val = { + thisPost: thisPost !== false, + makeStub: makeStub, + hideRecursively: hideRecursively + }; + return PostHiding.db.set(data); + } else { + return PostHiding.db["delete"](data); + } + }, + toggle: function() { + var post; + + post = Get.postFromNode(this); + if (post.isHidden) { + PostHiding.show(post); + } else { + PostHiding.hide(post); + } + return PostHiding.saveHiddenState(post, post.isHidden); + }, + hide: function(post, makeStub, hideRecursively) { + var a, postInfo, quotelink, _i, _len, _ref; + + if (makeStub == null) { + makeStub = Conf['Stubs']; + } + if (hideRecursively == null) { + hideRecursively = Conf['Recursive Hiding']; + } + if (post.isHidden) { + return; + } + post.isHidden = true; + if (hideRecursively) { + Recursive.apply(PostHiding.hide, post, makeStub, true); + Recursive.add(PostHiding.hide, post, makeStub, true); + } + _ref = Get.allQuotelinksLinkingTo(post); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + quotelink = _ref[_i]; + $.addClass(quotelink, 'filtered'); + } + if (!makeStub) { + post.nodes.root.hidden = true; + return; + } + a = PostHiding.makeButton(post, 'show'); + postInfo = Conf['Anonymize'] ? 'Anonymous' : $('.nameBlock', post.nodes.info).textContent; + $.add(a, $.tn(" " + postInfo)); + post.nodes.stub = $.el('div', { + className: 'stub' + }); + $.add(post.nodes.stub, a); + if (Conf['Menu']) { + $.add(post.nodes.stub, [$.tn(' '), Menu.makeButton(post)]); + } + return $.prepend(post.nodes.root, post.nodes.stub); + }, + show: function(post, showRecursively) { + var quotelink, _i, _len, _ref; + + if (showRecursively == null) { + showRecursively = Conf['Recursive Hiding']; + } + if (post.nodes.stub) { + $.rm(post.nodes.stub); + delete post.nodes.stub; + } else { + post.nodes.root.hidden = false; + } + post.isHidden = false; + if (showRecursively) { + Recursive.apply(PostHiding.show, post, true); + Recursive.rm(PostHiding.hide, post); + } + _ref = Get.allQuotelinksLinkingTo(post); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + quotelink = _ref[_i]; + $.rmClass(quotelink, 'filtered'); + } + } + }; + + Recursive = { + recursives: {}, + init: function() { + if (g.VIEW === 'catalog') { + return; + } + return Post.prototype.callbacks.push({ + name: 'Recursive', + cb: this.node + }); + }, + node: function() { + var i, obj, quote, recursive, _i, _j, _len, _len1, _ref, _ref1; + + if (this.isClone) { + return; + } + _ref = this.quotes; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + quote = _ref[_i]; + if (obj = Recursive.recursives[quote]) { + _ref1 = obj.recursives; + for (i = _j = 0, _len1 = _ref1.length; _j < _len1; i = ++_j) { + recursive = _ref1[i]; + recursive.apply(null, [this].concat(__slice.call(obj.args[i]))); + } + } + } + }, + add: function() { + var args, obj, post, recursive, _base, _name; + + recursive = arguments[0], post = arguments[1], args = 3 <= arguments.length ? __slice.call(arguments, 2) : []; + obj = (_base = Recursive.recursives)[_name = post.fullID] || (_base[_name] = { + recursives: [], + args: [] + }); + obj.recursives.push(recursive); + return obj.args.push(args); + }, + rm: function(recursive, post) { + var i, obj, rec, _i, _len, _ref; + + if (!(obj = Recursive.recursives[post.fullID])) { + return; + } + _ref = obj.recursives; + for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { + rec = _ref[i]; + if (rec === recursive) { + obj.recursives.splice(i, 1); + obj.args.splice(i, 1); + } + } + }, + apply: function() { + var ID, args, fullID, post, recursive, _ref; + + recursive = arguments[0], post = arguments[1], args = 3 <= arguments.length ? __slice.call(arguments, 2) : []; + fullID = post.fullID; + _ref = g.posts; + for (ID in _ref) { + post = _ref[ID]; + if (post.quotes.contains(fullID)) { + recursive.apply(null, [post].concat(__slice.call(args))); + } + } + } + }; + + ThreadHiding = { + init: function() { + if (g.VIEW !== 'index' || !Conf['Thread Hiding Buttons'] && !Conf['Thread Hiding Link']) { + return; + } + this.db = new DataBoard('hiddenThreads'); + this.syncCatalog(); + return Thread.prototype.callbacks.push({ + name: 'Thread Hiding', + cb: this.node + }); + }, + node: function() { + var data; + + if (data = ThreadHiding.db.get({ + boardID: this.board.ID, + threadID: this.ID + })) { + ThreadHiding.hide(this, data.makeStub); + } + if (!Conf['Thread Hiding Buttons']) { + return; + } + return $.prepend(this.OP.nodes.root, ThreadHiding.makeButton(this, 'hide')); + }, + syncCatalog: function() { + var hiddenThreads, hiddenThreadsOnCatalog, threadID; + + hiddenThreads = ThreadHiding.db.get({ + boardID: g.BOARD.ID, + defaultValue: {} + }); + hiddenThreadsOnCatalog = JSON.parse(localStorage.getItem("4chan-hide-t-" + g.BOARD)) || {}; + for (threadID in hiddenThreadsOnCatalog) { + if (!(threadID in hiddenThreads)) { + hiddenThreads[threadID] = {}; + } + } + for (threadID in hiddenThreads) { + if (!(threadID in hiddenThreadsOnCatalog)) { + delete hiddenThreads[threadID]; + } + } + if ((ThreadHiding.db.data.lastChecked || 0) > Date.now() - $.MINUTE) { + ThreadHiding.cleanCatalog(hiddenThreadsOnCatalog); + } + return ThreadHiding.db.set({ + boardID: g.BOARD.ID, + val: hiddenThreads + }); + }, + cleanCatalog: function(hiddenThreadsOnCatalog) { + return $.cache("//api.4chan.org/" + g.BOARD + "/threads.json", function() { + var page, thread, threads, _i, _j, _len, _len1, _ref, _ref1; + + if (this.status !== 200) { + return; + } + threads = {}; + _ref = JSON.parse(this.response); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + page = _ref[_i]; + _ref1 = page.threads; + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + thread = _ref1[_j]; + if (thread.no in hiddenThreadsOnCatalog) { + threads[thread.no] = hiddenThreadsOnCatalog[thread.no]; + } + } + } + if (Object.keys(threads).length) { + return localStorage.setItem("4chan-hide-t-" + g.BOARD, JSON.stringify(threads)); + } else { + return localStorage.removeItem("4chan-hide-t-" + g.BOARD); + } + }); + }, + menu: { + init: function() { + var apply, div, hideStubLink, makeStub; + + if (g.VIEW !== 'index' || !Conf['Menu'] || !Conf['Thread Hiding Link']) { + return; + } + div = $.el('div', { + className: 'hide-thread-link', + textContent: 'Hide thread' + }); + apply = $.el('a', { + textContent: 'Apply', + href: 'javascript:;' + }); + $.on(apply, 'click', ThreadHiding.menu.hide); + makeStub = $.el('label', { + innerHTML: " Make stub" + }); + hideStubLink = $.el('a', { + textContent: 'Hide stub', + href: 'javascript:;' + }); + $.on(hideStubLink, 'click', ThreadHiding.menu.hideStub); + $.event('AddMenuEntry', { + type: 'post', + el: div, + order: 20, + open: function(_arg) { + var isReply, thread; + + thread = _arg.thread, isReply = _arg.isReply; + if (isReply || thread.isHidden) { + return false; + } + ThreadHiding.menu.thread = thread; + return true; + }, + subEntries: [ + { + el: apply + }, { + el: makeStub + } + ] + }); + return $.event('AddMenuEntry', { + type: 'post', + el: hideStubLink, + order: 15, + open: function(_arg) { + var isReply, thread; + + thread = _arg.thread, isReply = _arg.isReply; + if (isReply || !thread.isHidden) { + return false; + } + return ThreadHiding.menu.thread = thread; + } + }); + }, + hide: function() { + var makeStub, thread; + + makeStub = $('input', this.parentNode).checked; + thread = ThreadHiding.menu.thread; + ThreadHiding.hide(thread, makeStub); + ThreadHiding.saveHiddenState(thread, makeStub); + return $.event('CloseMenu'); + }, + hideStub: function() { + var thread; + + thread = ThreadHiding.menu.thread; + ThreadHiding.hide(thread, false); + $.event('CloseMenu'); + } + }, + makeButton: function(thread, type) { + var a; + + a = $.el('a', { + className: "" + type + "-thread-button", + innerHTML: " " + (type === 'hide' ? '-' : '+') + " ", + href: 'javascript:;' + }); + a.setAttribute('data-fullid', thread.fullID); + $.on(a, 'click', ThreadHiding.toggle); + return a; + }, + saveHiddenState: function(thread, makeStub) { + var hiddenThreadsOnCatalog; + + hiddenThreadsOnCatalog = JSON.parse(localStorage.getItem("4chan-hide-t-" + g.BOARD)) || {}; + if (thread.isHidden) { + ThreadHiding.db.set({ + boardID: thread.board.ID, + threadID: thread.ID, + val: { + makeStub: makeStub + } + }); + hiddenThreadsOnCatalog[thread] = true; + } else { + ThreadHiding.db["delete"]({ + boardID: thread.board.ID, + threadID: thread.ID + }); + delete hiddenThreadsOnCatalog[thread]; + } + return localStorage.setItem("4chan-hide-t-" + g.BOARD, JSON.stringify(hiddenThreadsOnCatalog)); + }, + toggle: function(thread) { + if (!(thread instanceof Thread)) { + thread = g.threads[this.dataset.fullid]; + } + if (thread.isHidden) { + ThreadHiding.show(thread); + } else { + ThreadHiding.hide(thread); + } + return ThreadHiding.saveHiddenState(thread); + }, + hide: function(thread, makeStub) { + var OP, a, numReplies, opInfo, span, threadRoot; + + if (makeStub == null) { + makeStub = Conf['Stubs']; + } + OP = thread.OP; + threadRoot = OP.nodes.root.parentNode; + thread.isHidden = true; + if (!makeStub) { + threadRoot.hidden = threadRoot.nextElementSibling.hidden = true; + return; + } + numReplies = 0; + if (span = $('.summary', threadRoot)) { + numReplies = +span.textContent.match(/\d+/); + } + numReplies += $$('.opContainer ~ .replyContainer', threadRoot).length; + numReplies = numReplies === 1 ? '1 reply' : "" + numReplies + " replies"; + opInfo = Conf['Anonymize'] ? 'Anonymous' : $('.nameBlock', OP.nodes.info).textContent; + a = ThreadHiding.makeButton(thread, 'show'); + $.add(a, $.tn(" " + opInfo + " (" + numReplies + ")")); + thread.stub = $.el('div', { + className: 'stub' + }); + $.add(thread.stub, a); + if (Conf['Menu']) { + $.add(thread.stub, [$.tn(' '), Menu.makeButton(OP)]); + } + return $.prepend(threadRoot, thread.stub); + }, + show: function(thread) { + var threadRoot; + + if (thread.stub) { + $.rm(thread.stub); + delete thread.stub; + } + threadRoot = thread.OP.nodes.root.parentNode; + return threadRoot.nextElementSibling.hidden = threadRoot.hidden = thread.isHidden = false; + } + }; + + QuoteBacklink = { + init: function() { + var format; + + if (g.VIEW === 'catalog' || !Conf['Quote Backlinks']) { + return; + } + format = Conf['backlink'].replace(/%id/g, "' + id + '"); + this.funk = Function('id', "return '" + format + "'"); + this.containers = {}; + Post.prototype.callbacks.push({ + name: 'Quote Backlinking Part 1', + cb: this.firstNode + }); + return Post.prototype.callbacks.push({ + name: 'Quote Backlinking Part 2', + cb: this.secondNode + }); + }, + firstNode: function() { + var a, clone, container, containers, frag, link, post, quote, _i, _j, _k, _len, _len1, _len2, _ref, _ref1; + + if (this.isClone || !this.quotes.length) { + return; + } + a = $.el('a', { + href: "/" + this.board + "/res/" + this.thread + "#p" + this, + className: this.isHidden ? 'filtered backlink' : 'backlink', + textContent: (QuoteBacklink.funk(this.ID)) + (Conf['Mark Quotes of You'] && this.info.yours ? '\u00A0(You)' : '') + }); + _ref = this.quotes; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + quote = _ref[_i]; + containers = [QuoteBacklink.getContainer(quote)]; + if ((post = g.posts[quote]) && post.nodes.backlinkContainer) { + _ref1 = post.clones; + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + clone = _ref1[_j]; + containers.push(clone.nodes.backlinkContainer); + } + } + for (_k = 0, _len2 = containers.length; _k < _len2; _k++) { + container = containers[_k]; + frag = [$.tn(' '), link = a.cloneNode(true)]; + if (Conf['Quote Previewing']) { + $.on(link, 'mouseover', QuotePreview.mouseover); + } + if (Conf['Quote Inlining']) { + $.on(link, 'click', QuoteInline.toggle); + if (Conf['Quote Hash Navigation']) { + frag.pushArrays(QuoteInline.qiQuote(link, $.hasClass(link, 'filtered'))); + } + } + $.add(container, frag); + } + } + }, + secondNode: function() { + var container; + + if (this.isClone && (this.origin.isReply || Conf['OP Backlinks'])) { + this.nodes.backlinkContainer = $('.container', this.nodes.info); + return; + } + if (!(this.isReply || Conf['OP Backlinks'])) { + return; + } + container = QuoteBacklink.getContainer(this.fullID); + this.nodes.backlinkContainer = container; + return $.add(this.nodes.info, container); + }, + getContainer: function(id) { + var _base; + + return (_base = this.containers)[id] || (_base[id] = $.el('span', { + className: 'container' + })); + } + }; + + QuoteCT = { + init: function() { + if (g.VIEW === 'catalog' || !Conf['Mark Cross-thread Quotes']) { + return; + } + if (Conf['Comment Expansion']) { + ExpandComment.callbacks.push(this.node); + } + this.text = '\u00A0(Cross-thread)'; + return Post.prototype.callbacks.push({ + name: 'Mark Cross-thread Quotes', + cb: this.node + }); + }, + node: function() { + var board, boardID, quotelink, quotelinks, quotes, thread, threadID, _i, _len, _ref, _ref1; + + if (this.isClone && this.thread === this.context.thread) { + return; + } + if (!(quotes = this.quotes).length) { + return; + } + quotelinks = this.nodes.quotelinks; + _ref = this.isClone ? this.context : this, board = _ref.board, thread = _ref.thread; + for (_i = 0, _len = quotelinks.length; _i < _len; _i++) { + quotelink = quotelinks[_i]; + _ref1 = Get.postDataFromLink(quotelink), boardID = _ref1.boardID, threadID = _ref1.threadID; + if (!threadID) { + continue; + } + if (this.isClone) { + quotelink.textContent = quotelink.textContent.replace(QuoteCT.text, ''); + } + if (boardID === this.board.ID && threadID !== thread.ID) { + $.add(quotelink, $.tn(QuoteCT.text)); + } + } + } + }; + + QuoteInline = { + init: function() { + if (g.VIEW === 'catalog' || !Conf['Quote Inlining']) { + return; + } + if (Conf['Comment Expansion']) { + ExpandComment.callbacks.push(this.node); + } + if (Conf['Quote Hash Navigation']) { + this.node = function() { + var link, _i, _len, _ref; + + _ref = this.nodes.quotelinks.concat(__slice.call(this.nodes.backlinks)); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + link = _ref[_i]; + if (!this.isClone) { + $.after(link, QuoteInline.qiQuote(link, $.hasClass(link, 'filtered'))); + } + $.on(link, 'click', QuoteInline.toggle); + } + }; + } else { + this.node = function() { + var link, _i, _len, _ref; + + _ref = this.nodes.quotelinks.concat(__slice.call(this.nodes.backlinks)); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + link = _ref[_i]; + $.on(link, 'click', QuoteInline.toggle); + } + }; + } + return Post.prototype.callbacks.push({ + name: 'Quote Inlining', + cb: this.node + }); + }, + qiQuote: function(link, hidden) { + return [ + $.tn(' '), $.el('a', { + className: hidden ? 'hashlink filtered' : 'hashlink', + textContent: '#', + href: link.href + }) + ]; + }, + toggle: function(e) { + var boardID, context, postID, threadID, _ref; + + if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) { + return; + } + e.preventDefault(); + _ref = Get.postDataFromLink(this), boardID = _ref.boardID, threadID = _ref.threadID, postID = _ref.postID; + context = Get.contextFromLink(this); + if ($.hasClass(this, 'inlined')) { + QuoteInline.rm(this, boardID, threadID, postID, context); + } else { + if ($.x("ancestor::div[@id='p" + postID + "']", this)) { + return; + } + QuoteInline.add(this, boardID, threadID, postID, context); + } + return this.classList.toggle('inlined'); + }, + findRoot: function(quotelink, isBacklink) { + if (isBacklink) { + return quotelink.parentNode.parentNode; + } else { + return $.x('ancestor-or-self::*[parent::blockquote][1]', quotelink); + } + }, + add: function(quotelink, boardID, threadID, postID, context) { + var inline, isBacklink, post, qroot, root; + + isBacklink = $.hasClass(quotelink, 'backlink'); + inline = $.el('div', { + id: "i" + postID, + className: 'inline' + }); + root = QuoteInline.findRoot(quotelink, isBacklink); + $.after(root, inline); + qroot = $.x('ancestor::*[contains(@class,"postContainer")][1]', root); + $.addClass(qroot, 'hasInline'); + Get.postClone(boardID, threadID, postID, inline, context); + if (!((post = g.posts["" + boardID + "." + postID]) && context.thread === post.thread)) { + return; + } + if (isBacklink && Conf['Forward Hiding']) { + $.addClass(post.nodes.root, 'forwarded'); + post.forwarded++ || (post.forwarded = 1); + } + if (!Unread.posts) { + return; + } + return Unread.readSinglePost(post); + }, + rm: function(quotelink, boardID, threadID, postID, context) { + var el, inlined, isBacklink, post, qroot, root, _ref; + + isBacklink = $.hasClass(quotelink, 'backlink'); + root = QuoteInline.findRoot(quotelink, isBacklink); + root = $.x("following-sibling::div[@id='i" + postID + "'][1]", root); + qroot = $.x('ancestor::*[contains(@class,"postContainer")][1]', root); + $.rm(root); + if (!$('.inline', qroot)) { + $.rmClass(qroot, 'hasInline'); + } + if (!(el = root.firstElementChild)) { + return; + } + post = g.posts["" + boardID + "." + postID]; + post.rmClone(el.dataset.clone); + if (Conf['Forward Hiding'] && isBacklink && context.thread === g.threads["" + boardID + "." + threadID] && !--post.forwarded) { + delete post.forwarded; + $.rmClass(post.nodes.root, 'forwarded'); + } + while (inlined = $('.inlined', el)) { + _ref = Get.postDataFromLink(inlined), boardID = _ref.boardID, threadID = _ref.threadID, postID = _ref.postID; + QuoteInline.rm(inlined, boardID, threadID, postID, context); + $.rmClass(inlined, 'inlined'); + } + } + }; + + QuoteOP = { + init: function() { + if (g.VIEW === 'catalog' || !Conf['Mark OP Quotes']) { + return; + } + if (Conf['Comment Expansion']) { + ExpandComment.callbacks.push(this.node); + } + this.text = '\u00A0(OP)'; + return Post.prototype.callbacks.push({ + name: 'Mark OP Quotes', + cb: this.node + }); + }, + node: function() { + var boardID, op, postID, quotelink, quotelinks, quotes, _i, _j, _len, _len1, _ref; + + if (this.isClone && this.thread === this.context.thread) { + return; + } + if (!(quotes = this.quotes).length) { + return; + } + quotelinks = this.nodes.quotelinks; + if (this.isClone && quotes.contains(this.thread.fullID)) { + for (_i = 0, _len = quotelinks.length; _i < _len; _i++) { + quotelink = quotelinks[_i]; + quotelink.textContent = quotelink.textContent.replace(QuoteOP.text, ''); + } + } + op = (this.isClone ? this.context : this).thread.fullID; + if (!quotes.contains(op)) { + return; + } + for (_j = 0, _len1 = quotelinks.length; _j < _len1; _j++) { + quotelink = quotelinks[_j]; + _ref = Get.postDataFromLink(quotelink), boardID = _ref.boardID, postID = _ref.postID; + if (("" + boardID + "." + postID) === op) { + $.add(quotelink, $.tn(QuoteOP.text)); + } + } + } + }; + + QuotePreview = { + init: function() { + if (g.VIEW === 'catalog' || !Conf['Quote Previewing']) { + return; + } + if (Conf['Comment Expansion']) { + ExpandComment.callbacks.push(this.node); + } + return Post.prototype.callbacks.push({ + name: 'Quote Previewing', + cb: this.node + }); + }, + node: function() { + var link, _i, _len, _ref; + + _ref = this.nodes.quotelinks.concat(__slice.call(this.nodes.backlinks)); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + link = _ref[_i]; + $.on(link, 'mouseover', QuotePreview.mouseover); + } + }, + mouseover: function(e) { + var boardID, clone, origin, post, postID, posts, qp, quote, quoterID, threadID, _i, _j, _len, _len1, _ref, _ref1; + + if ($.hasClass(this, 'inlined')) { + return; + } + _ref = Get.postDataFromLink(this), boardID = _ref.boardID, threadID = _ref.threadID, postID = _ref.postID; + qp = $.el('div', { + id: 'qp', + className: 'dialog' + }); + $.add(Header.hover, qp); + Get.postClone(boardID, threadID, postID, qp, Get.contextFromLink(this)); + UI.hover({ + root: this, + el: qp, + latestEvent: e, + endEvents: 'mouseout click', + cb: QuotePreview.mouseout, + asapTest: function() { + return qp.firstElementChild; + } + }); + if (!(origin = g.posts["" + boardID + "." + postID])) { + return; + } + if (Conf['Quote Highlighting']) { + posts = [origin].concat(origin.clones); + posts.pop(); + for (_i = 0, _len = posts.length; _i < _len; _i++) { + post = posts[_i]; + $.addClass(post.nodes.post, 'qphl'); + } + } + quoterID = $.x('ancestor::*[@id][1]', this).id.match(/\d+$/)[0]; + clone = Get.postFromRoot(qp.firstChild); + _ref1 = clone.nodes.quotelinks.concat(__slice.call(clone.nodes.backlinks)); + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + quote = _ref1[_j]; + if (quote.hash.slice(2) === quoterID) { + $.addClass(quote, 'forwardlink'); + } + } + }, + mouseout: function() { + var clone, post, root, _i, _len, _ref; + + if (!(root = this.el.firstElementChild)) { + return; + } + clone = Get.postFromRoot(root); + post = clone.origin; + post.rmClone(root.dataset.clone); + if (!Conf['Quote Highlighting']) { + return; + } + _ref = [post].concat(post.clones); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + post = _ref[_i]; + $.rmClass(post.nodes.post, 'qphl'); + } + } + }; + + QuoteStrikeThrough = { + init: function() { + if (g.VIEW === 'catalog' || !Conf['Reply Hiding Buttons'] && !Conf['Reply Hiding Link'] && !Conf['Filter']) { + return; + } + return Post.prototype.callbacks.push({ + name: 'Strike-through Quotes', + cb: this.node + }); + }, + node: function() { + var boardID, postID, quotelink, _i, _len, _ref, _ref1, _ref2; + + if (this.isClone) { + return; + } + _ref = this.nodes.quotelinks; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + quotelink = _ref[_i]; + _ref1 = Get.postDataFromLink(quotelink), boardID = _ref1.boardID, postID = _ref1.postID; + if ((_ref2 = g.posts["" + boardID + "." + postID]) != null ? _ref2.isHidden : void 0) { + $.addClass(quotelink, 'filtered'); + } + } + } + }; + + /* + <3 aeosynth + */ + + + QuoteThreading = { + init: function() { + var input; + + if (!(Conf['Quote Threading'] && g.VIEW === 'thread')) { + return; + } + this.enabled = true; + this.controls = $.el('span', { + innerHTML: '' + }); + input = $('input', this.controls); + $.on(input, 'change', QuoteThreading.toggle); + $.event('AddMenuEntry', { + type: 'header', + el: this.controls, + order: 98 + }); + $.on(d, '4chanXInitFinished', this.setup); + return Post.prototype.callbacks.push({ + name: 'Quote Threading', + cb: this.node + }); + }, + setup: function() { + var ID, post, posts; + + $.off(d, '4chanXInitFinished', QuoteThreading.setup); + posts = g.posts; + for (ID in posts) { + post = posts[ID]; + if (post.cb) { + post.cb.call(post); + } + } + return QuoteThreading.hasRun = true; + }, + node: function() { + var ID, fullID, keys, len, post, posts, qid, quote, quotes, uniq, _i, _len; + + if (this.isClone || !QuoteThreading.enabled || this.thread.OP === this) { + return; + } + quotes = this.quotes, ID = this.ID, fullID = this.fullID; + posts = g.posts; + if (!(post = posts[fullID]) || post.isHidden) { + return; + } + uniq = {}; + len = ("" + g.BOARD).length + 1; + for (_i = 0, _len = quotes.length; _i < _len; _i++) { + quote = quotes[_i]; + qid = quote; + if (!(qid.slice(len) < ID)) { + continue; + } + if (qid in posts) { + uniq[qid.slice(len)] = true; + } + } + keys = Object.keys(uniq); + if (keys.length !== 1) { + return; + } + this.threaded = "" + g.BOARD + "." + keys[0]; + return this.cb = QuoteThreading.nodeinsert; + }, + nodeinsert: function() { + var bottom, height, posts, qpost, qroot, threadContainer, top, _ref; + + posts = g.posts; + qpost = posts[this.threaded]; + delete this.threaded; + delete this.cb; + if (this.thread.OP === qpost) { + return false; + } + if (QuoteThreading.hasRun) { + height = doc.clientHeight; + _ref = qpost.nodes.root.getBoundingClientRect(), bottom = _ref.bottom, top = _ref.top; + if (!(Unread.posts.contains(qpost) || ((bottom < height) && (top > 0)))) { + return false; + } + } + qroot = qpost.nodes.root; + if (!$.hasClass(qroot, 'threadOP')) { + $.addClass(qroot, 'threadOP'); + threadContainer = $.el('div', { + className: 'threadContainer' + }); + $.after(qroot, threadContainer); + } else { + threadContainer = qroot.nextSibling; + } + $.add(threadContainer, this.nodes.root); + return true; + }, + toggle: function() { + var container, containers, node, nodes, replies, reply, thread, _i, _j, _len, _len1; + + thread = $('.thread'); + replies = $$('.thread > .replyContainer, .threadContainer > .replyContainer', thread); + QuoteThreading.enabled = this.checked; + if (this.checked) { + nodes = (function() { + var _i, _len, _results; + + _results = []; + for (_i = 0, _len = replies.length; _i < _len; _i++) { + reply = replies[_i]; + _results.push(Get.postFromNode(reply)); + } + return _results; + })(); + for (_i = 0, _len = nodes.length; _i < _len; _i++) { + node = nodes[_i]; + QuoteThreading.node(node); + } + } else { + replies.sort(function(a, b) { + var aID, bID; + + aID = Number(a.id.slice(2)); + bID = Number(b.id.slice(2)); + return aID - bID; + }); + $.add(thread, replies); + containers = $$('.threadContainer', thread); + for (_j = 0, _len1 = containers.length; _j < _len1; _j++) { + container = containers[_j]; + $.rm(container); + } + Unread.update(true); + } + }, + kb: function() { + var control; + + control = $.id('threadingControl'); + return control.click(); + } + }; + + QuoteYou = { + init: function() { + if (g.VIEW === 'catalog' || !Conf['Mark Quotes of You'] || !Conf['Quick Reply']) { + return; + } + if (Conf['Highlight Own Posts']) { + $.addClass(doc, 'highlight-own'); + } + if (Conf['Highlight Posts Quoting You']) { + $.addClass(doc, 'highlight-you'); + } + if (Conf['Comment Expansion']) { + ExpandComment.callbacks.push(this.node); + } + return Post.prototype.callbacks.push({ + name: 'Mark Quotes of You', + cb: this.node + }); + }, + node: function() { + var quotelink, _i, _len, _ref; + + if (this.isClone) { + return; + } + if (this.info.yours) { + $.addClass(this.nodes.root, 'yourPost'); + } + if (!this.quotes.length) { + return; + } + _ref = this.nodes.quotelinks; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + quotelink = _ref[_i]; + if (QR.db.get(Get.postDataFromLink(quotelink))) { + $.add(quotelink, $.tn('\u00A0(You)')); + $.addClass(this.nodes.root, 'quotesYou'); + } + } + } + }; + + Quotify = { + init: function() { + if (g.VIEW === 'catalog' || !Conf['Resurrect Quotes']) { + return; + } + if (Conf['Comment Expansion']) { + ExpandComment.callbacks.push(this.node); + } + return Post.prototype.callbacks.push({ + name: 'Resurrect Quotes', + cb: this.node + }); + }, + node: function() { + var deadlink, _i, _len, _ref; + + _ref = $$('.deadlink', this.nodes.comment); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + deadlink = _ref[_i]; + if (this.isClone) { + if ($.hasClass(deadlink, 'quotelink')) { + this.nodes.quotelinks.push(deadlink); + } + } else { + Quotify.parseDeadlink.call(this, deadlink); + } + } + }, + parseDeadlink: function(deadlink) { + var a, boardID, m, post, postID, quote, quoteID, redirect, _ref; + + if (deadlink.parentNode.className === 'prettyprint') { + $.replace(deadlink, __slice.call(deadlink.childNodes)); + return; + } + quote = deadlink.textContent; + if (!(postID = (_ref = quote.match(/\d+$/)) != null ? _ref[0] : void 0)) { + return; + } + boardID = (m = quote.match(/^>>>\/([a-z\d]+)/)) ? m[1] : this.board.ID; + quoteID = "" + boardID + "." + postID; + if (post = g.posts[quoteID]) { + if (!post.isDead) { + a = $.el('a', { + href: "/" + boardID + "/" + post.thread + "/res/#p" + postID, + className: 'quotelink', + textContent: quote + }); + } else { + a = $.el('a', { + href: "/" + boardID + "/" + post.thread + "/res/#p" + postID, + className: 'quotelink deadlink', + target: '_blank', + textContent: "" + quote + "\u00A0(Dead)" + }); + a.setAttribute('data-boardid', boardID); + a.setAttribute('data-threadid', post.thread.ID); + a.setAttribute('data-postid', postID); + } + } else if (redirect = Redirect.to('thread', { + boardID: boardID, + threadID: 0, + postID: postID + })) { + a = $.el('a', { + href: redirect, + className: 'deadlink', + target: '_blank', + textContent: "" + quote + "\u00A0(Dead)" + }); + if (Redirect.to('post', { + boardID: boardID, + postID: postID + })) { + $.addClass(a, 'quotelink'); + a.setAttribute('data-boardid', boardID); + a.setAttribute('data-postid', postID); + } + } + if (!this.quotes.contains(quoteID)) { + this.quotes.push(quoteID); + } + if (!a) { + deadlink.textContent = "" + quote + "\u00A0(Dead)"; + return; + } + $.replace(deadlink, a); + if ($.hasClass(a, 'quotelink')) { + return this.nodes.quotelinks.push(a); + } + } + }; + + Linkify = { + init: function() { + if (g.VIEW === 'catalog' || !Conf['Linkify']) { + return; + } + this.regString = Conf['Allow False Positives'] ? /(\b([a-z]+:\/\/|[a-z]{3,}\.[-a-z0-9]+\.[a-z]+|[-a-z0-9]+\.[a-z]|[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+|[a-z]{3,}:[a-z0-9?]|[a-z0-9._%+-:]+@[a-z0-9.-]+\.[a-z0-9])[^\s'"]+)/gi : /(((magnet|mailto)\:|(www\.)|(news|(ht|f)tp(s?))\:\/\/){1}\S+)/gi; + if (Conf['Comment Expansion']) { + ExpandComment.callbacks.push(this.node); + } + return Post.prototype.callbacks.push({ + name: 'Linkify', + cb: this.node + }); + }, + cypher: $.el('div'), + node: function() { + var a, child, cypher, cypherText, data, embed, embedder, embeds, i, index, len, link, links, lookahead, name, next, node, nodes, snapshot, spoiler, text, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _m, _ref, _ref1, _ref2; + + if (this.isClone && Conf['Embedding']) { + _ref = $$('.embedder', this.nodes.comment); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + embedder = _ref[_i]; + $.on(embedder, "click", Linkify.toggle); + } + return; + } + snapshot = $.X('.//text()', this.nodes.comment); + cypher = Linkify.cypher; + i = -1; + len = snapshot.snapshotLength; + while (++i < len) { + nodes = $.frag(); + node = snapshot.snapshotItem(i); + data = node.data; + if (!(node.parentNode && Linkify.regString.test(data))) { + continue; + } + Linkify.regString.lastIndex = 0; + cypherText = []; + if (next = node.nextSibling) { + cypher.textContent = node.textContent; + cypherText[0] = cypher.innerHTML; + while ((next.nodeName.toLowerCase() === 'wbr' || next.nodeName.toLowerCase() === 's') && (lookahead = next.nextSibling) && ((name = lookahead.nodeName) === "#text" || name.toLowerCase() === 'br')) { + cypher.textContent = lookahead.textContent; + cypherText.push((spoiler = next.innerHTML) ? "" + (spoiler.replace(/" : ''); + cypherText.push(cypher.innerHTML); + $.rm(next); + next = lookahead.nextSibling; + if (lookahead.nodeName === "#text") { + $.rm(lookahead); + } + if (!next) { + break; + } + } + } + if (cypherText.length) { + data = cypherText.join(''); + } + links = data.match(Linkify.regString); + for (_j = 0, _len1 = links.length; _j < _len1; _j++) { + link = links[_j]; + index = data.indexOf(link); + if (text = data.slice(0, index)) { + cypher.innerHTML = text; + _ref1 = __slice.call(cypher.childNodes); + for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { + child = _ref1[_k]; + $.add(nodes, child); + } + } + cypher.innerHTML = (link.indexOf(':') < 0 ? (link.indexOf('@') > 0 ? 'mailto:' + link : 'http://' + link) : link).replace(/<(wbr|s|\/s)>/g, ''); + a = $.el('a', { + innerHTML: link, + className: 'linkify', + rel: 'nofollow noreferrer', + target: '_blank', + href: cypher.textContent + }); + $.add(nodes, Linkify.embedder(a)); + data = data.slice(index + link.length); + } + if (data) { + cypher.innerHTML = data; + _ref2 = __slice.call(cypher.childNodes); + for (_l = 0, _len3 = _ref2.length; _l < _len3; _l++) { + child = _ref2[_l]; + $.add(nodes, child); + } + } + $.replace(node, nodes); + } + if (Conf['Auto-embed']) { + embeds = $$('.embedder', this.nodes.comment); + for (_m = 0, _len4 = embeds.length; _m < _len4; _m++) { + embed = embeds[_m]; + embed.click(); + } + } + }, + toggle: function() { + var el, embed, style, type, url; + + embed = this.previousElementSibling; + if (this.className.contains("embedded")) { + el = $.el('a', { + rel: 'nofollow noreferrer', + target: 'blank', + className: 'linkify', + href: url = this.getAttribute("data-originalURL"), + textContent: this.getAttribute("data-title") || url + }); + this.textContent = '(embed)'; + $.addClass(el, "" + (this.getAttribute('data-service'))); + } else { + el = (type = Linkify.types[this.getAttribute("data-service")]).el.call(this); + el.style.cssText = (style = type.style) ? style : "border: 0; width: 640px; height: 390px"; + this.textContent = '(unembed)'; + } + $.replace(embed, el); + return $.toggleClass(this, 'embedded'); + }, + types: { + YouTube: { + regExp: /.*(?:youtu.be\/|youtube.*v=|youtube.*\/embed\/|youtube.*\/v\/|youtube.*videos\/)([^#\&\?]*)\??(t\=.*)?/, + el: function() { + return $.el('iframe', { + src: "//www.youtube.com/embed/" + this.name + (this.option ? '#' + this.option : '') + "?wmode=opaque" + }); + }, + title: { + api: function() { + return "https://gdata.youtube.com/feeds/api/videos/" + this.name + "?alt=json&fields=title/text(),yt:noembed,app:control/yt:state/@reasonCode"; + }, + text: function() { + return JSON.parse(this.responseText).entry.title.$t; + } + } + }, + Vocaroo: { + regExp: /.*(?:vocaroo.com\/)([^#\&\?]*).*/, + style: 'border: 0; width: 150px; height: 45px;', + el: function() { + return $.el('object', { + innerHTML: "" + }); + } + }, + Vimeo: { + regExp: /.*(?:vimeo.com\/)([^#\&\?]*).*/, + el: function() { + return $.el('iframe', { + src: "//player.vimeo.com/video/" + this.name + "?wmode=opaque" + }); + }, + title: { + api: function() { + return "https://vimeo.com/api/oembed.json?url=http://vimeo.com/" + this.name; + }, + text: function() { + return JSON.parse(this.responseText).title; + } + } + }, + LiveLeak: { + regExp: /.*(?:liveleak.com\/view.+i=)([0-9a-z_]+)/, + el: function() { + return $.el('object', { + innerHTML: "" + }); + } + }, + audio: { + regExp: /(.*\.(mp3|ogg|wav))$/, + el: function() { + return $.el('audio', { + controls: 'controls', + preload: 'auto', + src: this.name + }); + } + }, + image: { + regExp: /(http|www).*\.(gif|png|jpg|jpeg|bmp)$/, + style: 'border: 0; width: auto; height: auto;', + el: function() { + return $.el('div', { + innerHTML: "" + }); + } + }, + SoundCloud: { + regExp: /.*(?:soundcloud.com\/|snd.sc\/)([^#\&\?]*).*/, + style: 'height: auto; width: 500px; display: inline-block;', + el: function() { + var div; + + div = $.el('div', { + className: "soundcloud", + name: "soundcloud" + }); + $.ajax("//soundcloud.com/oembed?show_artwork=false&&maxwidth=500px&show_comments=false&format=json&url=https://www.soundcloud.com/" + this.name, { + div: div, + onloadend: function() { + return this.div.innerHTML = JSON.parse(this.responseText).html; + } + }, false); + return div; + }, + title: { + api: function() { + return "//soundcloud.com/oembed?show_artwork=false&&maxwidth=500px&show_comments=false&format=json&url=https://www.soundcloud.com/" + this.name; + }, + text: function() { + return JSON.parse(this.responseText).title; + } + } + }, + pastebin: { + regExp: /.*(?:pastebin.com\/(?!u\/))([^#\&\?]*).*/, + el: function() { + var div; + + return div = $.el('iframe', { + src: "http://pastebin.com/embed_iframe.php?i=" + this.name + }); + } + }, + gist: { + regExp: /.*(?:gist.github.com.*\/)([^\/][^\/]*)$/, + el: function() { + var div; + + return div = $.el('iframe', { + src: "http://www.purplegene.com/script?url=https://gist.github.com/" + this.name + ".js" + }); + }, + title: { + api: function() { + return "https://api.github.com/gists/" + this.name; + }, + text: function() { + var file, response; + + response = JSON.parse(this.responseText).files; + for (file in response) { + if (response.hasOwnProperty(file)) { + return file; + } + } + } + } + }, + InstallGentoo: { + regExp: /.*(?:paste.installgentoo.com\/view\/)([0-9a-z_]+)/, + el: function() { + return $.el('iframe', { + src: "http://paste.installgentoo.com/view/embed/" + this.name + }); + } + } + }, + embedder: function(a) { + var callbacks, embed, key, match, service, titles, type, _ref; + + if (!Conf['Link Title']) { + return [a]; + } + titles = {}; + callbacks = function() { + var title; + + return a.textContent = (function() { + switch (this.status) { + case 200: + case 304: + title = "" + (service.text.call(this)); + embed.setAttribute('data-title', title); + titles[embed.name] = [title, Date.now()]; + $.set('CachedTitles', titles); + return title; + case 404: + return "[" + key + "] Not Found"; + case 403: + return "[" + key + "] Forbidden or Private"; + default: + return "[" + key + "] " + this.status + "'d"; + } + }).call(this); + }; + _ref = Linkify.types; + for (key in _ref) { + type = _ref[key]; + if (!(match = a.href.match(type.regExp))) { + continue; + } + embed = $.el('a', { + name: (a.name = match[1]), + option: match[2], + className: 'embedder', + href: 'javascript:;', + textContent: '(embed)' + }); + embed.setAttribute('data-service', key); + embed.setAttribute('data-originalURL', a.href); + $.addClass(a, "" + (embed.getAttribute('data-service'))); + $.on(embed, 'click', Linkify.toggle); + if (!Conf['Embedding']) { + embed.hidden = true; + } + if (Conf['Link Title'] && (service = type.title)) { + $.get('CachedTitles', {}, function(item) { + var err, title; + + titles = item['CachedTitles']; + if (title = titles[match[1]]) { + a.textContent = title[0]; + return embed.setAttribute('data-title', title[0]); + } else { + try { + return $.cache(service.api.call(a), callbacks); + } catch (_error) { + err = _error; + return a.innerHTML = "[" + key + "] Title Link Blocked (are you using NoScript?)"; + } + } + }); + } + return [a, $.tn(' '), embed]; + } + return [a]; + } + }; + + QR = { + init: function() { + var sc; + + if (!Conf['Quick Reply']) { + return; + } + this.db = new DataBoard('yourPosts'); + if (Conf['QR Shortcut']) { + sc = $.el('a', { + className: "qr-shortcut " + (!Conf['Persistent QR'] ? 'disabled' : ''), + textContent: 'QR', + title: 'Quick Reply', + href: 'javascript:;' + }); + $.on(sc, 'click', function() { + if (Conf['Persistent QR'] || !QR.nodes || QR.nodes.el.hidden) { + $.event('CloseMenu'); + QR.open(); + QR.nodes.com.focus(); + return $.rmClass(this, 'disabled'); + } else { + QR.close(); + return $.addClass(this, 'disabled'); + } + }); + Header.addShortcut(sc); + } + if (Conf['Hide Original Post Form']) { + $.asap((function() { + return doc; + }), function() { + return $.addClass(doc, 'hide-original-post-form'); + }); + } + $.ready(this.initReady); + if (Conf['Persistent QR']) { + if (g.BOARD.ID !== 'f') { + $.on(d, '4chanXInitFinished', this.persist); + } else { + $.ready(this.persist); + } + } + return Post.prototype.callbacks.push({ + name: 'Quick Reply', + cb: this.node + }); + }, + initReady: function() { + var link; + + QR.postingIsEnabled = !!$.id('postForm'); + if (!QR.postingIsEnabled) { + return; + } + link = $.el('h1', { + innerHTML: "" + (g.VIEW === 'thread' ? 'Reply to Thread' : 'Start a Thread') + "", + className: "qr-link-container" + }); + $.on(link.firstChild, 'click', function() { + $.event('CloseMenu'); + QR.open(); + QR.nodes.com.focus(); + if (Conf['QR Shortcut']) { + return $.rmClass($('.qr-shortcut'), 'disabled'); + } + }); + $.before($.id('postForm'), link); + $.on(d, 'QRGetSelectedPost', function(_arg) { + var cb; + + cb = _arg.detail; + return cb(QR.selected); + }); + $.on(d, 'QRAddPreSubmitHook', function(_arg) { + var cb; + + cb = _arg.detail; + return QR.preSubmitHooks.push(cb); + }); + $.on(d, 'paste', QR.paste); + $.on(d, 'dragover', QR.dragOver); + $.on(d, 'drop', QR.dropFile); + $.on(d, 'dragstart dragend', QR.drag); + return $.on(d, 'ThreadUpdate', function() { + if (g.DEAD) { + return QR.abort(); + } else { + return QR.status(); + } + }); + }, + node: function() { + return $.on($('a[title="Quote this post"]', this.nodes.info), 'click', QR.quote); + }, + persist: function() { + if (!QR.postingIsEnabled) { + return; + } + QR.open(); + if (Conf['Auto Hide QR']) { + return QR.hide(); + } + }, + open: function() { + var err; + + if (QR.nodes) { + QR.nodes.el.hidden = false; + QR.unhide(); + return; + } + try { + return QR.dialog(); + } catch (_error) { + err = _error; + delete QR.nodes; + return Main.handleErrors({ + message: 'Quick Reply dialog creation crashed.', + error: err + }); + } + }, + close: function() { + var i, _i, _len, _ref; + + if (QR.req) { + QR.abort(); + return; + } + QR.nodes.el.hidden = true; + QR.cleanNotifications(); + d.activeElement.blur(); + $.rmClass(QR.nodes.el, 'dump'); + if (!Conf['Captcha Warning Notifications']) { + $.rmClass(QR.captcha.nodes.input, 'error'); + } + if (Conf['QR Shortcut']) { + $.toggleClass($('.qr-shortcut'), 'disabled'); + } + _ref = QR.posts; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + i = _ref[_i]; + QR.posts[0].rm(); + } + QR.cooldown.auto = false; + return QR.status(); + }, + focusin: function() { + return $.addClass(QR.nodes.el, 'has-focus'); + }, + focusout: function() { + return $.rmClass(QR.nodes.el, 'has-focus'); + }, + hide: function() { + d.activeElement.blur(); + $.addClass(QR.nodes.el, 'autohide'); + return QR.nodes.autohide.checked = true; + }, + unhide: function() { + $.rmClass(QR.nodes.el, 'autohide'); + return QR.nodes.autohide.checked = false; + }, + toggleHide: function() { + if (this.checked) { + return QR.hide(); + } else { + return QR.unhide(); + } + }, + error: function(err) { + var el; + + QR.open(); + if (typeof err === 'string') { + el = $.tn(err); + } else { + el = err; + el.removeAttribute('style'); + } + if (QR.captcha.isEnabled && /captcha|verification/i.test(el.textContent)) { + QR.captcha.nodes.input.focus(); + if (Conf['Captcha Warning Notifications']) { + QR.notifications.push(new Notification('warning', el)); + } else { + $.addClass(QR.captcha.nodes.input, 'error'); + $.on(QR.captcha.nodes.input, 'keydown', function() { + return $.rmClass(QR.captcha.nodes.input, 'error'); + }); + } + } else { + QR.notifications.push(new Notification('warning', el)); + } + if (d.hidden) { + return alert(el.textContent); + } + }, + notifications: [], + cleanNotifications: function() { + var notification, _i, _len, _ref; + + _ref = QR.notifications; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + notification = _ref[_i]; + notification.close(); + } + return QR.notifications = []; + }, + status: function() { + var disabled, status, value; + + if (!QR.nodes) { + return; + } + if (g.DEAD) { + value = 404; + disabled = true; + QR.cooldown.auto = false; + } + value = QR.req ? QR.req.progress : QR.cooldown.seconds || value; + status = QR.nodes.status; + status.value = !value ? 'Submit' : QR.cooldown.auto ? "Auto " + value : value; + return status.disabled = disabled || false; + }, + persona: { + pwd: '', + always: {}, + init: function() { + QR.persona.getPassword(); + return $.get('QR.personas', Conf['QR.personas'], function(_arg) { + var arr, item, personas, type, types, _i, _len, _ref; + + personas = _arg['QR.personas']; + types = { + name: [], + email: [], + sub: [] + }; + _ref = personas.split('\n'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + item = _ref[_i]; + QR.persona.parseItem(item.trim(), types); + } + for (type in types) { + arr = types[type]; + QR.persona.loadPersonas(type, arr); + } + }); + }, + parseItem: function(item, types) { + var boards, match, type, val, _ref, _ref1; + + if (item[0] === '#') { + return; + } + if (!(match = item.match(/(name|email|subject|password):"(.*)"/i))) { + return; + } + _ref = match, match = _ref[0], type = _ref[1], val = _ref[2]; + item = item.replace(match, ''); + boards = ((_ref1 = item.match(/boards:([^;]+)/i)) != null ? _ref1[1].toLowerCase() : void 0) || 'global'; + if (boards !== 'global' && !((boards.split(',')).contains(g.BOARD.ID))) { + return; + } + if (type === 'password') { + QR.persona.pwd = val; + return; + } + if (type === 'subject') { + type = 'sub'; + } + if (/always/i.test(item)) { + QR.persona.always[type] = val; + } + if (!types[type].contains(val)) { + return types[type].push(val); + } + }, + loadPersonas: function(type, arr) { + var list, val, _i, _len; + + list = $("#list-" + type, QR.nodes.el); + for (_i = 0, _len = arr.length; _i < _len; _i++) { + val = arr[_i]; + if (!val) { + continue; + } + $.add(list, $.el('option', { + textContent: val + })); + } + }, + getPassword: function() { + var input, m; + + if (!QR.persona.pwd) { + QR.persona.pwd = (m = d.cookie.match(/4chan_pass=([^;]+)/)) ? decodeURIComponent(m[1]) : (input = $.id('postPassword')) ? input.value : $.id('delPassword').value; + } + return QR.persona.pwd; + }, + get: function(cb) { + return $.get('QR.persona', {}, function(_arg) { + var persona; + + persona = _arg['QR.persona']; + return cb(persona); + }); + }, + set: function(post) { + return $.get('QR.persona', {}, function(_arg) { + var persona; + + persona = _arg['QR.persona']; + persona = { + name: post.name, + email: /^sage$/.test(post.email) ? persona.email : post.email, + sub: Conf['Remember Subject'] ? post.sub : void 0 + }; + return $.set('QR.persona', persona); + }); + } + }, + cooldown: { + init: function() { + var board; + + if (!Conf['Cooldown']) { + return; + } + board = g.BOARD.ID; + QR.cooldown.types = { + thread: (function() { + switch (board) { + case 'q': + return 86400; + case 'b': + case 'soc': + case 'r9k': + return 600; + default: + return 300; + } + })(), + sage: board === 'q' ? 600 : 60, + file: board === 'q' ? 300 : 30, + post: board === 'q' ? 150 : 30 + }; + QR.cooldown.upSpd = 0; + QR.cooldown.upSpdAccuracy = .5; + $.get("cooldown." + board, {}, function(item) { + QR.cooldown.cooldowns = item["cooldown." + board]; + return QR.cooldown.start(); + }); + return $.sync("cooldown." + board, QR.cooldown.sync); + }, + start: function() { + if (!Conf['Cooldown']) { + return; + } + if (QR.cooldown.isCounting) { + return; + } + QR.cooldown.isCounting = true; + return QR.cooldown.count(); + }, + sync: function(cooldowns) { + var id; + + for (id in cooldowns) { + QR.cooldown.cooldowns[id] = cooldowns[id]; + } + return QR.cooldown.start(); + }, + set: function(data) { + var cooldown, delay, hasFile, isReply, isSage, post, req, start, type, upSpd; + + if (!Conf['Cooldown']) { + return; + } + req = data.req, post = data.post, isReply = data.isReply, delay = data.delay; + start = req ? req.uploadEndTime : Date.now(); + if (delay) { + cooldown = { + delay: delay + }; + } else { + if (post.file) { + upSpd = post.file.size / ((req.uploadEndTime - req.uploadStartTime) / $.SECOND); + QR.cooldown.upSpdAccuracy = ((upSpd > QR.cooldown.upSpd * .9) + QR.cooldown.upSpdAccuracy) / 2; + QR.cooldown.upSpd = upSpd; + } + isSage = /sage/i.test(post.email); + hasFile = !!post.file; + type = !isReply ? 'thread' : isSage ? 'sage' : hasFile ? 'file' : 'post'; + cooldown = { + isReply: isReply, + isSage: isSage, + hasFile: hasFile, + timeout: start + QR.cooldown.types[type] * $.SECOND + }; + } + QR.cooldown.cooldowns[start] = cooldown; + $.set("cooldown." + g.BOARD, QR.cooldown.cooldowns); + return QR.cooldown.start(); + }, + unset: function(id) { + delete QR.cooldown.cooldowns[id]; + if (Object.keys(QR.cooldown.cooldowns).length) { + return $.set("cooldown." + g.BOARD, QR.cooldown.cooldowns); + } else { + return $["delete"]("cooldown." + g.BOARD); + } + }, + count: function() { + var cooldown, cooldowns, elapsed, hasFile, isReply, isSage, now, post, seconds, start, type, types, upSpd, upSpdAccuracy, update, _ref; + + if (!Object.keys(QR.cooldown.cooldowns).length) { + $["delete"]("" + g.BOARD + ".cooldown"); + delete QR.cooldown.isCounting; + delete QR.cooldown.seconds; + QR.status(); + return; + } + setTimeout(QR.cooldown.count, $.SECOND); + now = Date.now(); + post = QR.posts[0]; + isReply = post.thread !== 'new'; + isSage = /sage/i.test(post.email); + hasFile = !!post.file; + seconds = null; + _ref = QR.cooldown, types = _ref.types, cooldowns = _ref.cooldowns, upSpd = _ref.upSpd, upSpdAccuracy = _ref.upSpdAccuracy; + for (start in cooldowns) { + cooldown = cooldowns[start]; + if ('delay' in cooldown) { + if (cooldown.delay) { + seconds = Math.max(seconds, cooldown.delay--); + } else { + seconds = Math.max(seconds, 0); + QR.cooldown.unset(start); + } + continue; + } + if (isReply === cooldown.isReply) { + type = !isReply ? 'thread' : isSage && cooldown.isSage ? 'sage' : hasFile && cooldown.hasFile ? 'file' : 'post'; + elapsed = Math.floor((now - start) / $.SECOND); + if (elapsed >= 0) { + seconds = Math.max(seconds, types[type] - elapsed); + if (Conf['Cooldown Prediction'] && hasFile && upSpd) { + seconds -= Math.floor(post.file.size / upSpd * upSpdAccuracy); + seconds = Math.max(seconds, 0); + } + } + } + if (!((start <= now && now <= cooldown.timeout))) { + QR.cooldown.unset(start); + } + } + update = seconds !== null || !!QR.cooldown.seconds; + QR.cooldown.seconds = seconds; + if (update) { + QR.status(); + } + if (seconds === 0 && QR.cooldown.auto && !QR.req) { + return QR.submit(); + } + } + }, + quote: function(e) { + var OP, caretPos, com, index, post, range, s, sel, selectionRoot, text, thread, _ref; + + if (e != null) { + e.preventDefault(); + } + if (!QR.postingIsEnabled) { + 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) { + s = s.replace(/\n/g, '\n>'); + text += ">" + s + "\n"; + } + QR.open(); + if (QR.selected.isLocked) { + index = QR.posts.indexOf(QR.selected); + (QR.posts[index + 1] || new QR.post()).select(); + $.addClass(QR.nodes.el, 'dump'); + QR.cooldown.auto = true; + } + _ref = QR.nodes, com = _ref.com, thread = _ref.thread; + if (!com.value) { + thread.value = OP.ID; + } + caretPos = com.selectionStart; + com.value = com.value.slice(0, caretPos) + text + com.value.slice(com.selectionEnd); + range = caretPos + text.length; + com.setSelectionRange(range, range); + com.focus(); + QR.selected.save(com); + QR.selected.save(thread); + if (Conf['QR Shortcut']) { + return $.rmClass($('.qr-shortcut'), 'disabled'); + } + }, + characterCount: function() { + var count, counter; + + counter = QR.nodes.charCount; + count = QR.nodes.com.textLength; + counter.textContent = count; + counter.hidden = count < 1000; + return (count > 1500 ? $.addClass : $.rmClass)(counter, 'warning'); + }, + drag: function(e) { + var toggle; + + toggle = e.type === 'dragstart' ? $.off : $.on; + toggle(d, 'dragover', QR.dragOver); + return toggle(d, 'drop', QR.dropFile); + }, + dragOver: function(e) { + e.preventDefault(); + return e.dataTransfer.dropEffect = 'copy'; + }, + dropFile: function(e) { + if (!e.dataTransfer.files.length) { + return; + } + e.preventDefault(); + QR.open(); + QR.fileInput(e.dataTransfer.files); + return $.addClass(QR.nodes.el, 'dump'); + }, + paste: function(e) { + var blob, files, item, _i, _len, _ref; + + files = []; + _ref = e.clipboardData.items; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + item = _ref[_i]; + if (item.kind === 'file') { + blob = item.getAsFile(); + blob.name = 'file'; + if (blob.type) { + blob.name += '.' + blob.type.split('/')[1]; + } + files.push(blob); + } + } + if (!files.length) { + return; + } + QR.open(); + return QR.fileInput(files); + }, + openFileInput: function(e) { + if (e.keyCode && e.keyCode !== 32) { + return; + } + return QR.nodes.fileInput.click(); + }, + fileInput: function(files) { + var file, length, max, post, _i, _len; + + if (this instanceof Element) { + files = __slice.call(this.files); + QR.nodes.fileInput.value = null; + } + length = files.length; + if (!length) { + return; + } + max = QR.nodes.fileInput.max; + QR.cleanNotifications(); + if (length === 1) { + file = files[0]; + if (/^text/.test(file.type)) { + QR.selected.pasteText(file); + } else if (file.size > max) { + QR.error("File too large (file: " + ($.bytesToString(file.size)) + ", max: " + ($.bytesToString(max)) + ")."); + } else if (!QR.mimeTypes.contains(file.type)) { + QR.error('Unsupported file type.'); + } else { + QR.selected.setFile(file); + } + return; + } + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + if (/^text/.test(file.type)) { + if ((post = QR.posts[QR.posts.length - 1]).com) { + post = new QR.post(); + } + post.pasteText(file); + } else if (file.size > max) { + QR.error("" + file.name + ": File too large (file: " + ($.bytesToString(file.size)) + ", max: " + ($.bytesToString(max)) + ")."); + } else if (!QR.mimeTypes.contains(file.type)) { + QR.error("" + file.name + ": Unsupported file type."); + } else { + if ((post = QR.posts[QR.posts.length - 1]).file) { + post = new QR.post(); + } + post.setFile(file); + } + } + return $.addClass(QR.nodes.el, 'dump'); + }, + posts: [], + post: (function() { + function _Class(select) { + var el, event, prev, _i, _len, _ref, + _this = this; + + el = $.el('a', { + className: 'qr-preview', + draggable: true, + href: 'javascript:;', + innerHTML: '×' + }); + this.nodes = { + el: el, + rm: el.firstChild, + label: $('label', el), + spoiler: $('input', el), + span: el.lastChild + }; + $.on(el, 'click', this.select.bind(this)); + $.on(this.nodes.rm, 'click', function(e) { + e.stopPropagation(); + return _this.rm(); + }); + $.on(this.nodes.label, 'click', function(e) { + return e.stopPropagation(); + }); + $.on(this.nodes.spoiler, 'change', function(e) { + _this.spoiler = e.target.checked; + if (_this === QR.selected) { + return QR.nodes.spoiler.checked = _this.spoiler; + } + }); + $.add(QR.nodes.dumpList, el); + _ref = ['dragStart', 'dragEnter', 'dragLeave', 'dragOver', 'dragEnd', 'drop']; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + event = _ref[_i]; + $.on(el, event.toLowerCase(), this[event]); + } + this.thread = g.VIEW === 'thread' ? g.THREADID : 'new'; + prev = QR.posts[QR.posts.length - 1]; + QR.posts.push(this); + this.nodes.spoiler.checked = this.spoiler = prev && Conf['Remember Spoiler'] ? prev.spoiler : false; + QR.persona.get(function(persona) { + _this.name = 'name' in QR.persona.always ? QR.persona.always.name : prev ? prev.name : persona.name; + _this.email = 'email' in QR.persona.always ? QR.persona.always.email : prev && !/^sage$/.test(prev.email) ? prev.email : persona.email; + _this.sub = 'sub' in QR.persona.always ? QR.persona.always.sub : Conf['Remember Subject'] ? prev ? prev.sub : persona.sub : ''; + if (QR.selected === _this) { + return _this.load(); + } + }); + if (select) { + this.select(); + } + this.unlock(); + } + + _Class.prototype.rm = function() { + var index; + + $.rm(this.nodes.el); + index = QR.posts.indexOf(this); + if (QR.posts.length === 1) { + new QR.post(true); + $.rmClass(QR.nodes.el, 'dump'); + } else if (this === QR.selected) { + (QR.posts[index - 1] || QR.posts[index + 1]).select(); + } + QR.posts.splice(index, 1); + if (!window.URL) { + return; + } + return URL.revokeObjectURL(this.URL); + }; + + _Class.prototype.lock = function(lock) { + var name, _i, _len, _ref; + + if (lock == null) { + lock = true; + } + this.isLocked = lock; + if (this !== QR.selected) { + return; + } + _ref = ['thread', 'name', 'email', 'sub', 'com', 'spoiler']; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + name = _ref[_i]; + QR.nodes[name].disabled = lock; + } + this.nodes.rm.style.visibility = QR.nodes.fileRM.style.visibility = lock ? 'hidden' : ''; + (lock ? $.off : $.on)(QR.nodes.filename.parentNode, 'click', QR.openFileInput); + this.nodes.spoiler.disabled = lock; + return this.nodes.el.draggable = !lock; + }; + + _Class.prototype.unlock = function() { + return this.lock(false); + }; + + _Class.prototype.select = function() { + var rectEl, rectList; + + if (QR.selected) { + QR.selected.nodes.el.id = null; + QR.selected.forceSave(); + } + QR.selected = this; + this.lock(this.isLocked); + this.nodes.el.id = 'selected'; + rectEl = this.nodes.el.getBoundingClientRect(); + rectList = this.nodes.el.parentNode.getBoundingClientRect(); + this.nodes.el.parentNode.scrollLeft += rectEl.left + rectEl.width / 2 - rectList.left - rectList.width / 2; + this.load(); + return $.event('QRPostSelection', this); + }; + + _Class.prototype.load = function() { + var name, _i, _len, _ref; + + _ref = ['thread', 'name', 'email', 'sub', 'com']; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + name = _ref[_i]; + QR.nodes[name].value = this[name] || null; + } + this.showFileData(); + return QR.characterCount(); + }; + + _Class.prototype.save = function(input) { + var value, _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; + } + }; + + _Class.prototype.forceSave = function() { + var name, _i, _len, _ref; + + if (this !== QR.selected) { + return; + } + _ref = ['thread', 'name', 'email', 'sub', 'com', 'spoiler']; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + name = _ref[_i]; + this.save(QR.nodes[name]); + } + }; + + _Class.prototype.setFile = function(file) { + this.file = file; + this.filename = "" + file.name + " (" + ($.bytesToString(file.size)) + ")"; + this.nodes.el.title = this.filename; + if (QR.spoiler) { + this.nodes.label.hidden = false; + } + if (window.URL) { + URL.revokeObjectURL(this.URL); + } + this.showFileData(); + if (!/^image/.test(file.type)) { + this.nodes.el.style.backgroundImage = null; + return; + } + return this.setThumbnail(); + }; + + _Class.prototype.setThumbnail = function(fileURL) { + var img, reader, + _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; + + s = 90 * 2; + if (_this.file.type === 'image/gif') { + s *= 3; + } + height = img.height, width = img.width; + if (height < s || width < s) { + if (window.URL) { + _this.URL = fileURL; + } + _this.nodes.el.style.backgroundImage = "url(" + _this.URL + ")"; + return; + } + if (height <= width) { + width = s / height * width; + height = s; + } else { + height = s / width * height; + width = s; + } + cv = $.el('canvas'); + 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); + return _this.nodes.el.style.backgroundImage = "url(" + _this.URL + ")"; + }; + if (cv.toBlob) { + cv.toBlob(applyBlob); + return; + } + data = atob(cv.toDataURL().split(',')[1]); + l = data.length; + ui8a = new Uint8Array(l); + for (i = _i = 0; 0 <= l ? _i < l : _i > l; i = 0 <= l ? ++_i : --_i) { + ui8a[i] = data.charCodeAt(i); + } + return applyBlob(new Blob([ui8a], { + type: 'image/png' + })); + }; + return img.src = fileURL; + }; + + _Class.prototype.rmFile = function() { + delete this.file; + delete this.filename; + this.nodes.el.title = null; + this.nodes.el.style.backgroundImage = null; + if (QR.spoiler) { + this.nodes.label.hidden = true; + } + this.showFileData(); + if (!window.URL) { + return; + } + return URL.revokeObjectURL(this.URL); + }; + + _Class.prototype.showFileData = function() { + if (this.file) { + QR.nodes.filename.textContent = this.filename; + QR.nodes.filename.title = this.filename; + QR.nodes.spoiler.checked = this.spoiler; + return $.addClass(QR.nodes.fileSubmit, 'has-file'); + } else { + return $.rmClass(QR.nodes.fileSubmit, 'has-file'); + } + }; + + _Class.prototype.pasteText = function(file) { + var reader, + _this = this; + + reader = new FileReader(); + reader.onload = function(e) { + var text; + + text = e.target.result; + if (_this.com) { + _this.com += "\n" + text; + } else { + _this.com = text; + } + if (QR.selected === _this) { + QR.nodes.com.value = _this.com; + } + return _this.nodes.span.textContent = _this.com; + }; + return reader.readAsText(file); + }; + + _Class.prototype.dragStart = function() { + return $.addClass(this, 'drag'); + }; + + _Class.prototype.dragEnd = function() { + return $.rmClass(this, 'drag'); + }; + + _Class.prototype.dragEnter = function() { + return $.addClass(this, 'over'); + }; + + _Class.prototype.dragLeave = function() { + return $.rmClass(this, 'over'); + }; + + _Class.prototype.dragOver = function(e) { + e.preventDefault(); + return e.dataTransfer.dropEffect = 'move'; + }; + + _Class.prototype.drop = function() { + var el, index, newIndex, oldIndex, post; + + el = $('.drag', this.parentNode); + $.rmClass(el, 'drag'); + $.rmClass(this, 'over'); + if (!this.draggable) { + return; + } + index = function(el) { + return __slice.call(el.parentNode.children).indexOf(el); + }; + oldIndex = index(el); + newIndex = index(this); + (oldIndex < newIndex ? $.after : $.before)(this, el); + post = QR.posts.splice(oldIndex, 1)[0]; + return QR.posts.splice(newIndex, 0, post); + }; + + return _Class; + + })(), + captcha: { + init: function() { + if (d.cookie.indexOf('pass_enabled=1') >= 0) { + return; + } + if (!(this.isEnabled = !!$.id('captchaFormPart'))) { + return; + } + return $.asap((function() { + return $.id('recaptcha_challenge_field_holder'); + }), this.ready.bind(this)); + }, + ready: function() { + var MutationObserver, imgContainer, input, observer, setLifetime, + _this = this; + + setLifetime = function(e) { + return _this.lifetime = e.detail; + }; + $.on(window, 'captcha:timeout', setLifetime); + $.globalEval('window.dispatchEvent(new CustomEvent("captcha:timeout", {detail: RecaptchaState.timeout}))'); + $.off(window, 'captcha:timeout', setLifetime); + imgContainer = $.el('div', { + className: 'captcha-img', + title: 'Reload', + innerHTML: '' + }); + input = $.el('input', { + className: 'captcha-input field', + title: 'Verification', + autocomplete: 'off', + spellcheck: false, + tabIndex: 55 + }); + this.nodes = { + challenge: $.id('recaptcha_challenge_field_holder'), + img: imgContainer.firstChild, + input: input + }; + if (MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.OMutationObserver) { + observer = new MutationObserver(this.load.bind(this)); + observer.observe(this.nodes.challenge, { + childList: true + }); + } else { + $.on(this.nodes.challenge, 'DOMNodeInserted', this.load.bind(this)); + } + $.on(imgContainer, 'click', this.reload.bind(this)); + $.on(input, 'keydown', this.keydown.bind(this)); + $.on(input, 'focus', function() { + return $.addClass(QR.nodes.el, 'focus'); + }); + $.on(input, 'blur', function() { + return $.rmClass(QR.nodes.el, 'focus'); + }); + $.get('captchas', [], function(item) { + return _this.sync(item['captchas']); + }); + $.sync('captchas', this.sync); + this.reload(); + $.addClass(QR.nodes.el, 'has-captcha'); + return $.after(QR.nodes.com.parentNode, [imgContainer, input]); + }, + sync: function(captchas) { + this.captchas = captchas; + return QR.captcha.count(); + }, + getOne: function() { + var captcha, challenge, response; + + this.clear(); + if (captcha = this.captchas.shift()) { + challenge = captcha.challenge, response = captcha.response; + this.count(); + $.set('captchas', this.captchas); + } else { + challenge = this.nodes.img.alt; + if (response = this.nodes.input.value) { + this.reload(); + } + } + if (response) { + response = response.trim(); + if (!/\s/.test(response)) { + response = "" + response + " " + response; + } + } + return { + challenge: challenge, + response: response + }; + }, + save: function() { + var response; + + if (!(response = this.nodes.input.value.trim())) { + return; + } + this.captchas.push({ + challenge: this.nodes.img.alt, + response: response, + timeout: this.timeout + }); + this.count(); + this.reload(); + return $.set('captchas', this.captchas); + }, + clear: function() { + var captcha, i, now, _i, _len, _ref; + + now = Date.now(); + _ref = this.captchas; + for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { + captcha = _ref[i]; + if (captcha.timeout > now) { + break; + } + } + if (!i) { + return; + } + this.captchas = this.captchas.slice(i); + this.count(); + return $.set('captchas', this.captchas); + }, + load: function() { + var challenge; + + if (!this.nodes.challenge.firstChild) { + return; + } + this.timeout = Date.now() + this.lifetime * $.SECOND - $.MINUTE; + challenge = this.nodes.challenge.firstChild.value; + this.nodes.img.alt = challenge; + this.nodes.img.src = "//www.google.com/recaptcha/api/image?c=" + challenge; + this.nodes.input.value = null; + return this.clear(); + }, + count: function() { + var count; + + count = this.captchas.length; + this.nodes.input.placeholder = (function() { + switch (count) { + case 0: + return 'Verification (Shift + Enter to cache)'; + case 1: + return 'Verification (1 cached captcha)'; + default: + return "Verification (" + count + " cached captchas)"; + } + })(); + return this.nodes.input.alt = count; + }, + reload: function(focus) { + $.globalEval('Recaptcha.reload("t")'); + if (focus) { + return this.nodes.input.focus(); + } + }, + keydown: function(e) { + if (e.keyCode === 8 && !this.nodes.input.value) { + this.reload(); + } else if (e.keyCode === 13 && e.shiftKey) { + this.save(); + } else { + return; + } + return e.preventDefault(); + } + }, + dialog: function() { + var dialog, mimeTypes, name, nodes, thread, _i, _len, _ref; + + dialog = UI.dialog('qr', 'top:0;right:0;', "
×
No selected file×+
"); + QR.nodes = nodes = { + el: dialog, + move: $('.move', dialog), + autohide: $('#autohide', dialog), + thread: $('select', dialog), + close: $('.close', dialog), + form: $('form', dialog), + dumpButton: $('#dump-button', dialog), + name: $('[data-name=name]', dialog), + email: $('[data-name=email]', dialog), + sub: $('[data-name=sub]', dialog), + com: $('[data-name=com]', dialog), + dumpList: $('#dump-list', dialog), + addPost: $('#add-post', dialog), + charCount: $('#char-count', dialog), + fileSubmit: $('#file-n-submit', dialog), + filename: $('#qr-filename', dialog), + fileRM: $('#qr-filerm', dialog), + fileExtras: $('#qr-extras-container', dialog), + spoiler: $('#qr-file-spoiler', dialog), + status: $('[type=submit]', dialog), + fileInput: $('[type=file]', dialog) + }; + mimeTypes = $('ul.rules > li').textContent.trim().match(/: (.+)/)[1].toLowerCase().replace(/\w+/g, function(type) { + switch (type) { + case 'jpg': + return 'image/jpeg'; + case 'pdf': + return 'application/pdf'; + case 'swf': + return 'application/x-shockwave-flash'; + default: + return "image/" + type; + } + }); + 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'); + } else { + nodes.spoiler.parentElement.hidden = true; + } + if (g.BOARD.ID === 'f') { + nodes.flashTag = $.el('select', { + name: 'filetag', + innerHTML: "\n\n\n\n\n\n" + }); + $.add(nodes.form, nodes.flashTag); + } + for (thread in g.BOARD.threads) { + $.add(nodes.thread, $.el('option', { + value: thread, + textContent: "Thread No." + thread + })); + } + $.on(nodes.filename.parentNode, 'click keyup', QR.openFileInput); + $.on(dialog, 'focusin', QR.focusin); + $.on(dialog, 'focusout', QR.focusout); + $.on(nodes.autohide, 'change', QR.toggleHide); + $.on(nodes.close, 'click', QR.close); + $.on(nodes.dumpButton, 'click', function() { + return nodes.el.classList.toggle('dump'); + }); + $.on(nodes.addPost, 'click', function() { + return new QR.post(true); + }); + $.on(nodes.form, 'submit', QR.submit); + $.on(nodes.fileRM, 'click', function() { + return QR.selected.rmFile(); + }); + $.on(nodes.fileExtras, 'click', function(e) { + return e.stopPropagation(); + }); + $.on(nodes.spoiler, 'change', function() { + return QR.selected.nodes.spoiler.click(); + }); + $.on(nodes.fileInput, 'change', QR.fileInput); + _ref = ['name', 'email', 'sub', 'com']; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + name = _ref[_i]; + $.on(nodes[name], 'input', function() { + return QR.selected.save(this); + }); + } + $.on(nodes.thread, 'change', function() { + return QR.selected.save(this); + }); + QR.persona.init(); + new QR.post(true); + QR.status(); + QR.cooldown.init(); + QR.captcha.init(); + $.add(d.body, dialog); + return $.event('QRDialogCreation', null, dialog); + }, + preSubmitHooks: [], + submit: function(e) { + var callbacks, challenge, err, filetag, hook, opts, post, postData, response, textOnly, thread, threadID, _i, _len, _ref, _ref1; + + if (e != null) { + e.preventDefault(); + } + if (QR.req) { + QR.abort(); + return; + } + if (QR.cooldown.seconds) { + QR.cooldown.auto = !QR.cooldown.auto; + QR.status(); + return; + } + post = QR.posts[0]; + post.forceSave(); + if (g.BOARD.ID === 'f') { + filetag = QR.nodes.flashTag.value; + } + threadID = post.thread; + thread = g.BOARD.threads[threadID]; + if (threadID === 'new') { + threadID = null; + if (['vg', 'q'].contains(g.BOARD.ID) && !post.sub) { + err = 'New threads require a subject.'; + } else if (!(post.file || (textOnly = !!$('input[name=textonly]', $.id('postForm'))))) { + err = 'No file selected.'; + } + } else if (g.BOARD.threads[threadID].isClosed) { + err = 'You can\'t reply to this thread anymore.'; + } else if (!(post.com || post.file)) { + err = 'No file selected.'; + } else if (post.file && thread.fileLimit) { + err = 'Max limit of image replies has been reached.'; + } else { + _ref = QR.preSubmitHooks; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + hook = _ref[_i]; + if (err = hook(post, thread)) { + break; + } + } + } + if (QR.captcha.isEnabled && !err) { + _ref1 = QR.captcha.getOne(), challenge = _ref1.challenge, response = _ref1.response; + if (!response) { + err = 'No valid captcha.'; + } + } + QR.cleanNotifications(); + if (err) { + QR.cooldown.auto = false; + QR.status(); + QR.error(err); + return; + } + QR.cooldown.auto = QR.posts.length > 1; + if (Conf['Auto Hide QR'] && !QR.cooldown.auto) { + QR.hide(); + } + if (!QR.cooldown.auto && $.x('ancestor::div[@id="qr"]', d.activeElement)) { + d.activeElement.blur(); + } + post.lock(); + postData = { + resto: threadID, + name: post.name, + email: post.email, + sub: post.sub, + com: post.com, + upfile: post.file, + filetag: filetag, + spoiler: post.spoiler, + textonly: textOnly, + mode: 'regist', + pwd: QR.persona.pwd, + recaptcha_challenge_field: challenge, + recaptcha_response_field: response + }; + callbacks = { + onload: QR.response, + onerror: function() { + delete QR.req; + post.unlock(); + QR.cooldown.auto = false; + QR.status(); + return QR.error($.el('span', { + innerHTML: "Connection error. You may have been banned.\n[FAQ]" + })); + } + }; + opts = { + cred: true, + form: $.formData(postData), + upCallbacks: { + onload: function() { + QR.req.isUploadFinished = true; + QR.req.uploadEndTime = Date.now(); + QR.req.progress = '...'; + return QR.status(); + }, + onprogress: function(e) { + QR.req.progress = "" + (Math.round(e.loaded / e.total * 100)) + "%"; + return QR.status(); + } + } + }; + QR.req = $.ajax($.id('postForm').parentNode.action, callbacks, opts); + QR.req.uploadStartTime = Date.now(); + QR.req.progress = '...'; + return QR.status(); + }, + response: function() { + var URL, ban, board, err, h1, isReply, m, post, postID, req, threadID, tmpDoc, _, _ref, _ref1; + + req = QR.req; + delete QR.req; + post = QR.posts[0]; + post.unlock(); + tmpDoc = d.implementation.createHTMLDocument(''); + tmpDoc.documentElement.innerHTML = req.response; + if (ban = $('.banType', tmpDoc)) { + board = $('.board', tmpDoc).innerHTML; + err = $.el('span', { + innerHTML: ban.textContent.toLowerCase() === 'banned' ? ("You are banned on " + board + "! ;_;
") + "Click here to see the reason." : ("You were issued a warning on " + board + " as " + ($('.nameBlock', tmpDoc).innerHTML) + ".
") + ("Reason: " + ($('.reason', tmpDoc).innerHTML)) + }); + } else if (err = tmpDoc.getElementById('errmsg')) { + if ((_ref = $('a', err)) != null) { + _ref.target = '_blank'; + } + } else if (tmpDoc.title !== 'Post successful!') { + err = 'Connection error with sys.4chan.org.'; + } else if (req.status !== 200) { + err = "Error " + req.statusText + " (" + req.status + ")"; + } + if (err) { + if (/captcha|verification/i.test(err.textContent) || err === 'Connection error with sys.4chan.org.') { + if (/mistyped/i.test(err.textContent)) { + err = 'You seem to have mistyped the CAPTCHA.'; + } + QR.cooldown.auto = QR.captcha.isEnabled ? !!QR.captcha.captchas.length : err === 'Connection error with sys.4chan.org.' ? true : false; + QR.cooldown.set({ + delay: 2 + }); + } else if (err.textContent && (m = err.textContent.match(/wait\s(\d+)\ssecond/i))) { + QR.cooldown.auto = QR.captcha.isEnabled ? !!QR.captcha.captchas.length : true; + QR.cooldown.set({ + delay: m[1] + }); + } else { + QR.cooldown.auto = false; + } + QR.status(); + QR.error(err); + return; + } + QR.cleanNotifications(); + h1 = $('h1', tmpDoc); + if (Conf['Posting Success Notifications']) { + QR.notifications.push(new Notification('success', h1.textContent, 5)); + } + QR.persona.set(post); + _ref1 = h1.nextSibling.textContent.match(/thread:(\d+),no:(\d+)/), _ = _ref1[0], threadID = _ref1[1], postID = _ref1[2]; + postID = +postID; + threadID = +threadID || postID; + isReply = threadID !== postID; + QR.db.set({ + boardID: g.BOARD.ID, + threadID: threadID, + postID: postID, + val: true + }); + ThreadUpdater.postID = postID; + $.event('QRPostSuccessful', { + board: g.BOARD, + threadID: threadID, + postID: postID + }); + QR.cooldown.auto = QR.posts.length > 1 && isReply; + if (!(Conf['Persistent QR'] || QR.cooldown.auto)) { + QR.close(); + } else { + post.rm(); + } + QR.cooldown.set({ + req: req, + 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; + } + if (URL) { + if (Conf['Open Post in New Tab']) { + $.open("/" + g.BOARD + "/res/" + threadID); + } else { + window.location = "/" + g.BOARD + "/res/" + threadID; + } + } + return QR.status(); + }, + abort: function() { + if (QR.req && !QR.req.isUploadFinished) { + QR.req.abort(); + delete QR.req; + QR.posts[0].unlock(); + QR.notifications.push(new Notification('info', 'QR upload aborted.', 5)); + } + return QR.status(); + } + }; + + FappeTyme = { + init: function() { + var el, input; + + if (!Conf['Fappe Tyme'] || g.VIEW === 'catalog' || g.BOARD === 'f') { + return; + } + el = $.el('label', { + innerHTML: " Fappe Tyme", + title: 'Fappe Tyme' + }); + FappeTyme.input = input = el.firstElementChild; + $.on(input, 'change', FappeTyme.toggle); + $.event('AddMenuEntry', { + type: 'header', + el: el, + order: 97 + }); + return Post.prototype.callbacks.push({ + name: 'Fappe Tyme', + cb: this.node + }); + }, + node: function() { + if (this.file) { + return; + } + return $.addClass(this.nodes.root, "noFile"); + }, + toggle: function() { + $.event('CloseMenu'); + return (this.checked ? $.addClass : $.rmClass)(doc, 'fappeTyme'); + } + }; + + ImageExpand = { + init: function() { + if (g.VIEW === 'catalog' || !Conf['Image Expansion']) { + return; + } + this.EAI = $.el('a', { + className: 'expand-all-shortcut', + textContent: 'EAI', + title: 'Expand All Images', + href: 'javascript:;' + }); + $.on(this.EAI, 'click', ImageExpand.cb.toggleAll); + Header.addShortcut(this.EAI); + return Post.prototype.callbacks.push({ + name: 'Image Expansion', + cb: this.node + }); + }, + node: function() { + var thumb, _ref; + + if (!((_ref = this.file) != null ? _ref.isImage : void 0)) { + return; + } + thumb = this.file.thumb; + $.on(thumb.parentNode, 'click', ImageExpand.cb.toggle); + if (this.isClone && $.hasClass(thumb, 'expanding')) { + ImageExpand.contract(this); + ImageExpand.expand(this); + return; + } + if (ImageExpand.on && !this.isHidden) { + return ImageExpand.expand(this); + } + }, + cb: { + toggle: function(e) { + if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) { + return; + } + e.preventDefault(); + return ImageExpand.toggle(Get.postFromNode(this)); + }, + toggleAll: function() { + var ID, file, func, post, _i, _len, _ref, _ref1; + + $.event('CloseMenu'); + if (ImageExpand.on = $.hasClass(ImageExpand.EAI, 'expand-all-shortcut')) { + ImageExpand.EAI.className = 'contract-all-shortcut'; + ImageExpand.EAI.title = 'Contract All Images'; + func = ImageExpand.expand; + } else { + ImageExpand.EAI.className = 'expand-all-shortcut'; + ImageExpand.EAI.title = 'Expand All Images'; + func = ImageExpand.contract; + } + _ref = g.posts; + for (ID in _ref) { + post = _ref[ID]; + _ref1 = [post].concat(post.clones); + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + post = _ref1[_i]; + file = post.file; + if (!(file && file.isImage && doc.contains(post.nodes.root))) { + continue; + } + if (ImageExpand.on && (!Conf['Expand spoilers'] && file.isSpoiler || Conf['Expand from here'] && file.thumb.getBoundingClientRect().top < 0)) { + continue; + } + $.queueTask(func, post); + } + } + }, + setFitness: function() { + return (this.checked ? $.addClass : $.rmClass)(doc, this.name.toLowerCase().replace(/\s+/g, '-')); + } + }, + toggle: function(post) { + var headRect, node, rect, root, thumb, top; + + thumb = post.file.thumb; + if (!(post.file.isExpanded || $.hasClass(thumb, 'expanding'))) { + ImageExpand.expand(post); + return; + } + ImageExpand.contract(post); + node = post.nodes.root; + rect = Conf['Advance on contract'] ? (function() { + while (node.nextElementSibling) { + if (!(node = node.nextElementSibling)) { + return post.nodes.root; + } + if (!$.hasClass(node, 'postContainer')) { + continue; + } + if (node.offsetHeight > 0 && !$('.stub', node)) { + break; + } + } + return node.getBoundingClientRect(); + })() : post.nodes.root.getBoundingClientRect(); + if (!(rect.top <= 0 || rect.left <= 0)) { + return; + } + top = rect.top; + if (Conf['Fixed Header'] && !Conf['Bottom Header']) { + headRect = Header.bar.getBoundingClientRect(); + top += -headRect.top - headRect.height; + } + root = d.body; + if (rect.top < 0) { + root.scrollTop += top; + } + if (rect.left < 0) { + return root.scrollLeft = 0; + } + }, + contract: function(post) { + $.rmClass(post.nodes.root, 'expanded-image'); + $.rmClass(post.file.thumb, 'expanding'); + return post.file.isExpanded = false; + }, + expand: function(post, src) { + var img, thumb; + + thumb = post.file.thumb; + if (post.isHidden || post.file.isExpanded || $.hasClass(thumb, 'expanding')) { + return; + } + $.addClass(thumb, 'expanding'); + if (post.file.fullImage) { + $.asap((function() { + return post.file.fullImage.naturalHeight; + }), function() { + return ImageExpand.completeExpand(post); + }); + return; + } + post.file.fullImage = img = $.el('img', { + className: 'full-image', + src: src || post.file.URL + }); + $.on(img, 'error', ImageExpand.error); + $.asap((function() { + return post.file.fullImage.naturalHeight; + }), function() { + return ImageExpand.completeExpand(post); + }); + return $.after(thumb, img); + }, + completeExpand: function(post) { + var prev, thumb; + + thumb = post.file.thumb; + if (!$.hasClass(thumb, 'expanding')) { + return; + } + post.file.isExpanded = true; + if (!post.nodes.root.parentNode) { + $.addClass(post.nodes.root, 'expanded-image'); + $.rmClass(post.file.thumb, 'expanding'); + return; + } + prev = post.nodes.root.getBoundingClientRect(); + return $.queueTask(function() { + var curr, root; + + $.addClass(post.nodes.root, 'expanded-image'); + $.rmClass(post.file.thumb, 'expanding'); + if (!(prev.top + prev.height <= 0)) { + return; + } + root = d.body; + curr = post.nodes.root.getBoundingClientRect(); + return root.scrollTop += curr.height - prev.height + curr.top - prev.top; + }); + }, + error: function() { + var URL, post, src, timeoutID; + + post = Get.postFromNode(this); + $.rm(this); + delete post.file.fullImage; + if (!($.hasClass(post.file.thumb, 'expanding') || $.hasClass(post.nodes.root, 'expanded-image'))) { + return; + } + ImageExpand.contract(post); + src = this.src.split('/'); + if (src[2] === 'images.4chan.org') { + URL = Redirect.to('file', { + boardID: src[3], + filename: src[5] + }); + if (URL) { + setTimeout(ImageExpand.expand, 10000, post, URL); + return; + } + if (g.DEAD || post.isDead || post.file.isDead) { + return; + } + } + timeoutID = setTimeout(ImageExpand.expand, 10000, post); + return $.ajax("//api.4chan.org/" + post.board + "/res/" + post.thread + ".json", { + onload: function() { + var postObj, _i, _len, _ref; + + if (this.status !== 200) { + return; + } + _ref = JSON.parse(this.response).posts; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + postObj = _ref[_i]; + if (postObj.no === post.ID) { + break; + } + } + if (postObj.no !== post.ID) { + clearTimeout(timeoutID); + return post.kill(); + } else if (postObj.filedeleted) { + clearTimeout(timeoutID); + return post.kill(true); + } + } + }); + }, + menu: { + init: function() { + var conf, createSubEntry, el, key, subEntries, _ref; + + if (g.VIEW === 'catalog' || !Conf['Image Expansion']) { + return; + } + el = $.el('span', { + textContent: 'Image Expansion', + className: 'image-expansion-link' + }); + createSubEntry = ImageExpand.menu.createSubEntry; + subEntries = []; + _ref = Config.imageExpansion; + for (key in _ref) { + conf = _ref[key]; + subEntries.push(createSubEntry(key, conf)); + } + return $.event('AddMenuEntry', { + type: 'header', + el: el, + order: 105, + subEntries: subEntries + }); + }, + createSubEntry: function(type, config) { + var input, label; + + label = $.el('label', { + innerHTML: " " + type + }); + input = label.firstElementChild; + if (type === 'Fit width' || type === 'Fit height') { + $.on(input, 'change', ImageExpand.cb.setFitness); + } + if (config) { + label.title = config[1]; + input.checked = Conf[type]; + $.event('change', null, input); + $.on(input, 'change', $.cb.checked); + } + return { + el: label + }; + } + }, + menuToggle: function(e) { + return ImageExpand.opmenu.toggle(e, this, g); + } + }; + + ImageHover = { + init: function() { + if (g.VIEW === 'catalog' || !Conf['Image Hover']) { + return; + } + return Post.prototype.callbacks.push({ + name: 'Image Hover', + cb: this.node + }); + }, + node: function() { + var _ref; + + if (!((_ref = this.file) != null ? _ref.isImage : void 0)) { + return; + } + return $.on(this.file.thumb, 'mouseover', ImageHover.mouseover); + }, + mouseover: function(e) { + var el, post; + + post = Get.postFromNode(this); + el = $.el('img', { + id: 'ihover', + src: post.file.URL + }); + el.setAttribute('data-fullid', post.fullID); + $.add(Header.hover, el); + UI.hover({ + root: this, + el: el, + latestEvent: e, + endEvents: 'mouseout click', + asapTest: function() { + return el.naturalHeight; + } + }); + return $.on(el, 'error', ImageHover.error); + }, + error: function() { + var URL, post, src, timeoutID, + _this = this; + + if (!doc.contains(this)) { + return; + } + post = g.posts[this.dataset.fullid]; + src = this.src.split('/'); + if (src[2] === 'images.4chan.org') { + URL = Redirect.to('file', { + boardID: src[3], + filename: src[5].replace(/\?.+$/, '') + }); + if (URL) { + this.src = URL; + return; + } + if (g.DEAD || post.isDead || post.file.isDead) { + return; + } + } + timeoutID = setTimeout((function() { + return _this.src = post.file.URL + '?' + Date.now(); + }), 3000); + return $.ajax("//api.4chan.org/" + post.board + "/res/" + post.thread + ".json", { + onload: function() { + var postObj, _i, _len, _ref; + + if (this.status !== 200) { + return; + } + _ref = JSON.parse(this.response).posts; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + postObj = _ref[_i]; + if (postObj.no === post.ID) { + break; + } + } + if (postObj.no !== post.ID) { + clearTimeout(timeoutID); + return post.kill(); + } else if (postObj.filedeleted) { + clearTimeout(timeoutID); + return post.kill(true); + } + } + }); + } + }; + + ImageLoader = { + init: function() { + var prefetch; + + if (g.VIEW === 'catalog') { + return; + } + if (!(Conf["Image Prefetching"] || Conf["Replace JPG"] || Conf["Replace PNG"] || Conf["Replace GIF"])) { + return; + } + Post.prototype.callbacks.push({ + name: 'Image Replace', + cb: this.node + }); + if (!(Conf['Image Prefetching'] && g.VIEW === 'thread')) { + return; + } + prefetch = $.el('label', { + innerHTML: ' Prefetch Images' + }); + this.el = prefetch.firstElementChild; + $.on(this.el, 'change', this.toggle); + return $.event('AddMenuEntry', { + type: 'header', + el: prefetch, + order: 104 + }); + }, + node: function() { + var URL, img, string, style, thumb, type, _ref, _ref1; + + if (this.isClone || this.isHidden || this.thread.isHidden || !((_ref = this.file) != null ? _ref.isImage : void 0)) { + return; + } + _ref1 = this.file, thumb = _ref1.thumb, URL = _ref1.URL; + if (!((Conf[string = "Replace " + ((type = (URL.match(/\w{3}$/))[0].toUpperCase()) === 'PEG' ? 'JPG' : type)] && !/spoiler/.test(thumb.src)) || Conf['prefetch'])) { + return; + } + if (this.file.isSpoiler) { + style = thumb.style; + style.maxHeight = style.maxWidth = this.isReply ? '125px' : '250px'; + } + img = $.el('img'); + if (Conf[string]) { + $.on(img, 'load', function() { + return thumb.src = URL; + }); + } + return img.src = URL; + }, + toggle: function() { + var enabled, id, post, _ref; + + enabled = Conf['prefetch'] = this.checked; + if (enabled) { + _ref = g.threads["" + g.BOARD.ID + "." + g.THREADID].posts; + for (id in _ref) { + post = _ref[id]; + ImageLoader.node.call(post); + } + } + } + }; + + RevealSpoilers = { + init: function() { + if (g.VIEW === 'catalog' || !Conf['Reveal Spoilers']) { + return; + } + return Post.prototype.callbacks.push({ + name: 'Reveal Spoilers', + cb: this.node + }); + }, + node: function() { + var thumb, _ref; + + if (this.isClone || !((_ref = this.file) != null ? _ref.isSpoiler : void 0)) { + return; + } + thumb = this.file.thumb; + thumb.removeAttribute('style'); + return thumb.src = this.file.thumbURL; + } + }; + + ArchiveLink = { + init: function() { + var div, entry, type, _i, _len, _ref; + + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Archive Link']) { + return; + } + div = $.el('div', { + textContent: 'Archive' + }); + entry = { + type: 'post', + el: div, + order: 90, + open: function(_arg) { + var ID, board, thread; + + ID = _arg.ID, thread = _arg.thread, board = _arg.board; + return !!Redirect.to('thread', { + postID: ID, + threadID: thread.ID, + boardID: board.ID + }); + }, + subEntries: [] + }; + _ref = [['Post', 'post'], ['Name', 'name'], ['Tripcode', 'tripcode'], ['E-mail', 'email'], ['Subject', 'subject'], ['Filename', 'filename'], ['Image MD5', 'MD5']]; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + type = _ref[_i]; + entry.subEntries.push(this.createSubEntry(type[0], type[1])); + } + return $.event('AddMenuEntry', entry); + }, + createSubEntry: function(text, type) { + var el, open; + + el = $.el('a', { + textContent: text, + target: '_blank' + }); + open = type === 'post' ? function(_arg) { + var ID, board, thread; + + ID = _arg.ID, thread = _arg.thread, board = _arg.board; + el.href = Redirect.to('thread', { + postID: ID, + threadID: thread.ID, + boardID: board.ID + }); + return true; + } : function(post) { + var value; + + value = Filter[type](post); + if (!value) { + return false; + } + el.href = Redirect.to('search', { + boardID: post.board.ID, + type: type, + value: value, + isSearch: true + }); + return true; + }; + return { + el: el, + open: open + }; + } + }; + + DeleteLink = { + init: function() { + var div, fileEl, fileEntry, postEl, postEntry; + + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Delete Link']) { + return; + } + div = $.el('div', { + className: 'delete-link', + textContent: 'Delete' + }); + postEl = $.el('a', { + className: 'delete-post', + href: 'javascript:;' + }); + fileEl = $.el('a', { + className: 'delete-file', + href: 'javascript:;' + }); + postEntry = { + el: postEl, + open: function() { + postEl.textContent = 'Post'; + $.on(postEl, 'click', DeleteLink["delete"]); + return true; + } + }; + fileEntry = { + el: fileEl, + open: function(_arg) { + var file; + + file = _arg.file; + if (!file || file.isDead) { + return false; + } + fileEl.textContent = 'File'; + $.on(fileEl, 'click', DeleteLink["delete"]); + return true; + } + }; + return $.event('AddMenuEntry', { + type: 'post', + el: div, + order: 40, + open: function(post) { + var node; + + if (post.isDead || post.board.ID === 'q') { + return false; + } + DeleteLink.post = post; + node = div.firstChild; + node.textContent = 'Delete'; + DeleteLink.cooldown.start(post, node); + return true; + }, + subEntries: [postEntry, fileEntry] + }); + }, + "delete": function() { + var fileOnly, form, link, post; + + post = DeleteLink.post; + if (DeleteLink.cooldown.counting === post) { + return; + } + $.off(this, 'click', DeleteLink["delete"]); + this.textContent = "Deleting " + this.textContent + "..."; + fileOnly = $.hasClass(this, 'delete-file'); + form = { + mode: 'usrdel', + onlyimgdel: fileOnly, + pwd: QR.persona.getPassword() + }; + form[post.ID] = 'delete'; + link = this; + return $.ajax($.id('delform').action.replace("/" + g.BOARD + "/", "/" + post.board + "/"), { + onload: function() { + return DeleteLink.load(link, post, fileOnly, this.response); + }, + onerror: function() { + return DeleteLink.error(link); + } + }, { + cred: true, + form: $.formData(form) + }); + }, + load: function(link, post, fileOnly, html) { + var msg, s, tmpDoc; + + tmpDoc = d.implementation.createHTMLDocument(''); + tmpDoc.documentElement.innerHTML = html; + if (tmpDoc.title === '4chan - Banned') { + s = 'Banned!'; + } else if (msg = tmpDoc.getElementById('errmsg')) { + s = msg.textContent; + $.on(link, 'click', DeleteLink["delete"]); + } else { + if (tmpDoc.title === 'Updating index...') { + (post.origin || post).kill(fileOnly); + } + s = 'Deleted'; + } + return link.textContent = s; + }, + error: function(link) { + link.textContent = 'Connection error, please retry.'; + return $.on(link, 'click', DeleteLink["delete"]); + }, + cooldown: { + start: function(post, node) { + var length, seconds, _ref; + + if (!((_ref = QR.db) != null ? _ref.get({ + boardID: post.board.ID, + threadID: post.thread.ID, + postID: post.ID + }) : void 0)) { + delete DeleteLink.cooldown.counting; + return; + } + DeleteLink.cooldown.counting = post; + length = 30; + seconds = Math.ceil((length * $.SECOND - (Date.now() - post.info.date)) / $.SECOND); + return DeleteLink.cooldown.count(post, seconds, length, node); + }, + count: function(post, seconds, length, node) { + if (DeleteLink.cooldown.counting !== post) { + return; + } + if (!((0 <= seconds && seconds <= length))) { + if (DeleteLink.cooldown.counting === post) { + node.textContent = 'Delete'; + delete DeleteLink.cooldown.counting; + } + return; + } + setTimeout(DeleteLink.cooldown.count, 1000, post, seconds - 1, length, node); + return node.textContent = "Delete (" + seconds + ")"; + } + } + }; + + DownloadLink = { + init: function() { + var a; + + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Download Link']) { + return; + } + a = $.el('a', { + className: 'download-link', + textContent: 'Download file' + }); + return $.event('AddMenuEntry', { + type: 'post', + el: a, + order: 100, + open: function(_arg) { + var file; + + file = _arg.file; + if (!file) { + return false; + } + a.href = file.URL; + a.download = file.name; + return true; + } + }); + } + }; + + Menu = { + init: function() { + if (g.VIEW === 'catalog' || !Conf['Menu']) { + return; + } + this.menu = new UI.Menu('post'); + return Post.prototype.callbacks.push({ + name: 'Menu', + cb: this.node + }); + }, + node: function() { + var button; + + button = Menu.makeButton(this); + if (this.isClone) { + $.replace($('.menu-button', this.nodes.info), button); + return; + } + return $.add(this.nodes.info, [$.tn('\u00A0'), button]); + }, + makeButton: (function() { + var a; + + a = null; + return function(post) { + var clone; + + 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; + }; + })(), + toggle: function(e) { + var post; + + post = this.dataset.clone ? Get.postFromNode(this) : g.posts[this.dataset.postid]; + return Menu.menu.toggle(e, this, post); + } + }; + + ReportLink = { + init: function() { + var a; + + if (g.VIEW === 'catalog' || !Conf['Menu'] || !Conf['Report Link']) { + return; + } + a = $.el('a', { + className: 'report-link', + href: 'javascript:;', + textContent: 'Report this post' + }); + $.on(a, 'click', ReportLink.report); + return $.event('AddMenuEntry', { + type: 'post', + el: a, + order: 10, + open: function(post) { + ReportLink.post = post; + return !post.isDead; + } + }); + }, + report: function() { + var id, post, set, url; + + post = ReportLink.post; + url = "//sys.4chan.org/" + post.board + "/imgboard.php?mode=report&no=" + post; + id = Date.now(); + set = "toolbar=0,scrollbars=0,location=0,status=1,menubar=0,resizable=1,width=685,height=200"; + return window.open(url, id, set); + } + }; + + Favicon = { + init: function() { + return $.ready(function() { + var href; + + Favicon.el = $('link[rel="shortcut icon"]', d.head); + Favicon.el.type = 'image/x-icon'; + href = Favicon.el.href; + Favicon.SFW = /ws\.ico$/.test(href); + Favicon["default"] = href; + return Favicon["switch"](); + }); + }, + "switch": function() { + switch (Conf['favicon']) { + case 'ferongr': + Favicon.unreadDead = 'data:image/gif;base64,R0lGODlhEAAQAOMHAOgLAnMFAL8AAOgLAukMA/+AgP+rq////////////////////////////////////yH5BAEKAAcALAAAAAAQABAAAARZ8MhJ6xwDWIBv+AM1fEEIBIVRlNKYrtpIECuGzuwpCLg974EYiXUYkUItjGbC6VQ4omXFiKROA6qSy0A8nAo9GS3YCswIWnOvLAi0be23Z1QtdSUaqXcviQAAOw=='; + Favicon.unreadDeadY = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAS1BMVEUAAAAAAAAAAAAJAAASAAAZAQAaAQAiAQAkAQAoFBQyAgAzAgA1AgA4AABBAgBXAwBzBQCEBgGvCAG/AADoCwLpDAP/gID/q6v///9zILr8AAAAA3RSTlMAx9dmesIgAAAAc0lEQVQY02WPgQ6DIBBDmTqnbE70Cvb/v3TAnW5OSKB9ybXg3HUBOAmEEH4FQtrSn4gxi+xjVC9SVOEiSvbZI8zSV+/Xo7icnryZ15GObMxvtWUkB/VJW57kHU7fUcHStm8FkncGE/mwP6CGzq/eauHwvT7sWQt3gZLW+AAAAABJRU5ErkJggg=='; + Favicon.unreadSFW = 'data:image/gif;base64,R0lGODlhEAAQAOMHAADX8QBwfgC2zADX8QDY8nnl8qLp8v///////////////////////////////////yH5BAEKAAcALAAAAAAQABAAAARZ8MhJ6xwDWIBv+AM1fEEIBIVRlNKYrtpIECuGzuwpCLg974EYiXUYkUItjGbC6VQ4omXFiKROA6qSy0A8nAo9GS3YCswIWnOvLAi0be23Z1QtdSUaqXcviQAAOw=='; + Favicon.unreadSFWY = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAASFBMVEUAAAAAAAAAAAAACAkAERMAGBsAGR0AISUALzQALzUAMTcANjwAP0cAVF8AcH4AeokAorYAtswA1/EA2PISIyV55fKi6fL////l+pZqAAAAA3RSTlMAx9dmesIgAAAAcklEQVQY02VPARLCIAxjsjnUWdcg6/9/ukIr00nvIMldEhrC/wHwA0BE3wBUtnICOStQnrNx5oqqzmzKx9vDPH1Nae3F9U4ig3OzjCIX51treYvMxou13EQmBPtHE14xLiawjgoPtfgOaKHP+9VrEXA8O1v7CmSPE3u0AAAAAElFTkSuQmCC'; + Favicon.unreadNSFW = 'data:image/gif;base64,R0lGODlhEAAQAOMHAFT+ACh5AEncAFT+AFX/Acz/su7/5v///////////////////////////////////yH5BAEKAAcALAAAAAAQABAAAARZ8MhJ6xwDWIBv+AM1fEEIBIVRlNKYrtpIECuGzuwpCLg974EYiXUYkUItjGbC6VQ4omXFiKROA6qSy0A8nAo9GS3YCswIWnOvLAi0be23Z1QtdSUaqXcviQAAOw=='; + Favicon.unreadNSFWY = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAS1BMVEUAAAAAAAAAAAADCgAGEgAIGgAJGwALJAANJwASNwASOAATOgAVQQAWRAAeWwAgKBsoeQAwkQA/wABJ3ABU/gBV/wHM/7Lu/+b////r+K2AAAAAA3RSTlMAx9dmesIgAAAAc0lEQVQY02WPgQ6DIBBDmTonbk70Cvb/v3TAnW5OSKB9ybXg3HUBOAmEEH4FQtrSn4gxi+xjVC9SVOEiSvbZI8zSV+/Xo7icnryZ15GObMxvtWUmB/VJW0byDqfvqGBp20mB5J3Bi3zYH1BD38/eauHwvT7sEAt1Fb320QAAAABJRU5ErkJggg=='; + break; + case 'xat-': + Favicon.unreadDead = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA2ElEQVQ4y61TQQrCMBDMQ8WDIEV6LbT2A4og2Hq0veo7fIAH04dY9N4xmyYlpGmI2MCQTWYy3Wy2DAD7B2wWAzWgcTgVeZKlZRxHNYFi2jM18oBh0IcKtC6ixf22WT4IFLs0owxswXu9egm0Ls6bwfCFfNsJYJKfqoEkd3vgUgFVLWObtzNgVKyruC+ljSzr5OEnBzjvjcQecaQhbZgBb4CmGQw+PoMkTUtdbd8VSEPakcGxPOcsoIgUKy0LecY29BmdBrqRfjIwZ93KLs5loHvBnL3cLH/jF+C/+z5dgUysAAAAAElFTkSuQmCC'; + Favicon.unreadDeadY = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAdVBMVEUAAAAAAACKkJGNkpN0d3d0eHdra2dGRkORZ1wAAACmaV6naV4PDw8LCwsLCwvyZWLyZWIeExEyFBTAWlr/eHj/enkAAAAKAAAoAAA4AAA4GhpMAACRAAD/AAD/enn/h4j/m5z/nJ3/0dL/0tL/0tP/09P///9VK8WFAAAAFnRSTlMAPnp6kpKdtcHEzc3p6u7v8PT7/v7++jx7+QAAAIFJREFUGNONj90OgjAMhStKmU5k/h1UmAzUvv8jSrYBIeGC9qLtl/a0JVphAJKUOU36xNfWWiitlU9GUphZbXF/hxg10Li2QdQgPhQ3133c9XLOJvD9uZfI0YOdiiMiJw+2CKIPkZzGtcbgKYIJaI26LAfQOzOqoYNA4Z49Nguv/gEEhw2/C5BUZgAAAABJRU5ErkJggg=='; + Favicon.unreadSFW = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA30lEQVQ4y2P4//8/AyWYgSoGQMF/GJ7Y11VVUVoyKTM9ey4Ig9ggMWQ1YA1IBvzXm34YjkH8mPyJB+Nqlp8FYRAbmxoMF6ArSNrw6T0Qf8Amh9cFMEWVR/7/A+L/uORxhgEIt5/+/3/2lf//5wAxiI0uj+4CBlBgxVUvOwtydgXQZpDmi2/+/7/0GmIQSAwkB1IDUkuUAZeABlx+g2zAZ9wGlAOjChba+LwAUgNSi2HA5Am9VciBhSsQQWyoWgZiovEDsdGI1QBYQiLJAGQalpSxyWEzAJYWkGm8clTJjQCZ1hkoVG0CygAAAABJRU5ErkJggg=='; + Favicon.unreadSFWY = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAdVBMVEUAAAAAAACRjoqTkI13dXR4dXRpZ2tFQ0Zcb5EAAABee6ZefKcPDw8LCwsLCwtisPJisPIRFh4UJDJalMB4xP95xP8AAAABBQcHFx4KISoNLToaKzgaVW4ul8N5xP+Hy/+b1P+c1P/R7P/S6//S7P/T7P////9P0rk0AAAAFnRSTlMAPnp6kpKdtcHEzc3p6u7v8PT7/v7++jx7+QAAAIFJREFUGNONj90OgjAMhStKmU5k/h1UmAzUvv8jSrYBIeGC9qLtl/a0JVphAJKUOU36xNfWWiitlU9GUphZbXF/hxg10Li2QdQgPhQ3133c9XLOJvD9uUrk6MFOxRGRkwdbBNGHSE7jWmPwFMEEtEZdlgPonRmvoYNA4Z49Nguv/gEE3A2/sQ7iRgAAAABJRU5ErkJggg=='; + Favicon.unreadNSFW = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA4ElEQVQ4y2P4//8/AyWYgSoGQMF/GJ7YNbGqrKRiUnp21lwQBrFBYshqwBqQDPifdsYYjkH8mInxB+OWx58FYRAbmxoMF6ArKPmU9B6IP2CTw+sCmKKe/5X/gPg/LnmcYQDCs/63/1/9fzYQzwGz0eXRXcAACqy4ZfFnQc7u+V/xD6T55v+LQHwJbBBIDCQHUgNSS5QBt4Cab/2/jDDgMx4DykrKJ8FCG58XQGpAajEMmNw7uQo5sHAFIogNVctATDR+IDYasRoAS0gkGYBMw5IyNjlsBsDSAjKNV44quREAx58Mr9vt5wQAAAAASUVORK5CYII='; + Favicon.unreadNSFWY = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAdVBMVEUAAAAAAACRipGTjZN2dHd2dHhna2pDRkVckV8AAABepl9ep18PDw8LCwsLCwt08mJ08mIRHhEYMhRpwFqM/3iM/3kAAAAECAIQIAgWLAseOBoePA86dB1mzDOM/3ma/4er/5ur/5zZ/9HZ/9La/9La/9P///85Jx7jAAAAFnRSTlMAPnp6kpKdtcHEzc3p6u7v8PT7/v7++jx7+QAAAIFJREFUGNONj90OgjAMhStKmU5k/h1UmAzUvv8jSrYBIeGC9qLtl/a0JVphAJKUOU36xNfWWiitlU9GUphZbXF/hxg10Li2QdQgPhQ3133c9XLOJvD9uZfI0YOdiiMiJw+2CKIPkZzGtcbgKYIJaI26LAfQOzOqoYNA4Z49Nguv/gEEhw2/C5BUZgAAAABJRU5ErkJggg=='; + break; + case 'Mayhem': + Favicon.unreadDead = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABIUlEQVQ4jZ2ScWuDMBDFgw4pIkU0WsoQkWAYIkXZH4N9/+/V3dmfXSrKYIFHwt17j8vdGWNMIkgFuaDgzgQnwRs4EQs5KdolUQtagRN0givEDBTEOjgtGs0Zq8F7cKqqusVxrMQLaDUWcjBSrXkn8gs51tpJSWLk9b3HUa0aNIL5gPBR1/V4kJvR7lTwl8GmAm1Gf9+c3S+89qBHa8502AsmSrtBaEBPbIbj0ah2madlNAPEccdgJDfAtWifBjqWKShRBT6KoiH8QlEUn/qt0CCjnNdmPUwmFWzj9Oe6LpKuZXcwqq88z78Pch3aZU3dPwwc2sWlfZKCW5tWluV8kGvXClLm6dYN4/aUqfCbnEOzNDGhGZbNargvxCzvMGfRJD8UaDVvgkzo6QAAAABJRU5ErkJggg=='; + Favicon.unreadDeadY = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABj0lEQVQ4y42TQUorQRCGv+oekpj43pOhOyIiKoHBxTMkuAnEtWcwx/AY3sUbBIRcwCw8gCfIMkaTOOUiNdgGRRuKoav+v2qq/i4BakBmXweUwDoxLF5ZhVkC64rYBHYMUAIvwKuBMEwdaFiCNbAAngEC0NHkxBi73vsOsG92HGPsphigY1wOzfNhqhpC6AEd730RQuh9hQEOAY6A/jeAs3a7/f+bWB84ckCpqg+I8Osjgqo+AKUDViJS8LkGMcY+sJrNZssYY387LiIFsBLgL9AC/pgaArzZlF+sZgO4BG7sfgvcA3MxUtOStBIpX7cS3Klqd9OBTIEr4DlLOsuAmqpODXQOiHMuy/O8FkLoJth/6Uh2gQPg87Q3k+7leX6hqnpmPvM/GWfXWeWGqj5+oUS9LMs6wF7iHAwGJ9ZW5uxpup+UGwEtEVoijEYjKl66PJujmvIW3vsFwBiYqzJXZTweY5wSU6Bd7UP1KoECODUrJpOJAtPhcKjAtXGaYptWs57qWyv9Zn/it1a5knj5Dm3v4q8APeACAAAAAElFTkSuQmCC'; + Favicon.unreadSFW = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABCElEQVQ4jZ2S4crCMAxF+0OGDJEPKYrIGKOsiJSx/fJRfSAfTJNyKqXfiuDg0C25N2RJjTGmEVrhTzhw7oStsIEtsVzT4o2Jo9ALThiEM8IdHIgNaHo8mjNWg6/ske8bohPo+63QOLzmooHp8fyAICBSQkVz0QKdsFQEV6WSW/D+7+BbgbIDHcb4Kp61XyjyI16zZ8JemGltQtDBSGxB4/GoN+7TpkkjDCsFArm0IYv3U0BbnYtf8BCy+JytsE0X6VyuKhPPK/GAJ14kvZZDZVV3pZIb8MZr6n4o4PDGKn0S5SdDmyq5PnXQsk+Xbhinp03FFzmHJw6xYRiWm9VxnohZ3vOcxdO8ARmXRvbWdtzQAAAAAElFTkSuQmCC'; + Favicon.unreadSFWY = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAkFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBQcHFx4KISoNLToaVW4oKCgul8M4ODg7OztMTEyRkZHBwcH///9dzWZ0AAAAI3RSTlMEBggKDA4QEhQWFxkbHR8hIyUmKCosLjAxN1hbYc7P0dLc3mzWzBUAAAC+SURBVBjTNY3pcsIwEIM3ePERx/bG5IIe0NIrhVbv/3Y4Ydj9Ic030ogqpY3mDdGGi1EVsYuSvGE2Pkl0TFYAdLGuY1eMWGowzzN6kX41DYVpNbvdKlO4Jx5gSbi2VO+Vcq2jrc/jNLQhtM+n05PfkrKxG/oFHIEXqwqQsVRy7n+AtwLYL3sYR3wA755Jp3Vvv8cn8Js0GXmA7/P5TwzpiLn8MOALuEZNygkm5JTy/+vl4BRVbJvQ1NbWRSxXN64PGOBlhG0qAAAAAElFTkSuQmCC'; + Favicon.unreadNSFW = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABCklEQVQ4jZ2S0WrDMAxF/TBCCKWMYhZKCSGYmFJMSNjD/mhf239qJXNcjBdTWODgRLpXKJKNMaYROuFTOHEehFb4gJZYrunwxsSXMApOmIQzwgOciE1oRjyaM1aDj+yR7xuiHvT9VmgcXnPRwO/9+wWCgEgJFc1FCwzCVhFclUpuw/u3g3cFyg50GPOjePZ+ocjPeM2RCXthpbUFwQAzsQ2Nx6PeuE+bJo0w7BQI5NKGLN5XAW11LX7BQ8jia7bCLl2kc7mqTLzuxAOeeJH0Wk6VVf0oldyEN15T948CDm+sMiZRfjK0pZIbUwcd+3TphnF62lR8kXN44hAbhmG5WQNnT8zynucsnuYJhFpBfkMzqD4AAAAASUVORK5CYII='; + Favicon.unreadNSFWY = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAkFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAIQIAgWLAsePA8oKCg4ODg6dB07OztMTExmzDORkZHBwcH///92I3mvAAAAI3RSTlMEBggKDA4QEhQWFxkbHR8hIyUmKCosLjAxN1hbYc7P0dLc3mzWzBUAAAC+SURBVBjTNY3pcsIwEIM3ePERx/bG5IIe0NIT0ur93w4nDLs/pPlGGlGltNG8IdpwMaoidlGSN8zGJ4mOyQqALtZ17IoRSw3meUYv0q+moTCtZrdbZQr3xAMsCdeW6r1SrnW09XmchjaE9vl0evJbUjZ2Q7+AI/BiVQEylkrO/TfwVgD7ZQ/jiA/g3TPptO7t9/gEfpImIw/wez7/iSEdMZcfBnwB16hJOcGEnFL+f70cnKKKbROa2tq6iOXqBuMXGTe4CAUbAAAAAElFTkSuQmCC'; + break; + case 'Original': + Favicon.unreadDead = 'data:image/gif;base64,R0lGODlhEAAQAKECAAAAAP8AAP///////yH5BAEKAAMALAAAAAAQABAAAAI/nI95wsqygIRxDgGCBhTrwF3Zxowg5H1cSopS6FrGQ82PU1951ckRmYKJVCXizLRC9kAnT0aIiR6lCFT1cigAADs='; + Favicon.unreadDeadY = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAALVBMVEUAAAAAAAAAAAAAAAAKAAAoAAAoKCg4AAA4ODg7OztMAACRAADBwcH/AAD///+WCcPSAAAAA3RSTlMAx9dmesIgAAAAZ0lEQVQI1z2LsQmAUAxEb4Isk0rwp3EPR3ECcRQrh7C3/nAasPwzmCgYuPBy5AH/NALSImqAK+H1oJRqyJVHNAnZqDITVhj7/PrAciJ9il0BHs/jjU+fnB9sQ0IxX6OBO6Xr0xKAxANLZzUanCWzZQAAAABJRU5ErkJggg=='; + Favicon.unreadSFW = 'data:image/gif;base64,R0lGODlhEAAQAKECAAAAAC6Xw////////yH5BAEKAAMALAAAAAAQABAAAAI/nI95wsqygIRxDgGCBhTrwF3Zxowg5H1cSopS6FrGQ82PU1951ckRmYKJVCXizLRC9kAnT0aIiR6lCFT1cigAADs='; + Favicon.unreadSFWY = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAALVBMVEUAAAAAAAAAAAAAAAABBQcHFx4KISoNLToaVW4oKCgul8M4ODg7OzvBwcH///8uS/CdAAAAA3RSTlMAx9dmesIgAAAAZ0lEQVQI1z2LsQ2AUAhEbwKWoftRGvdwBEewchM7d9BFbE6pbP4Mgj+R5MjjwgP+qQSkRtQAV8K3lVI2Q648oknIRpWZsMI4988HjgvpU+wO8HgeHzR9cjZYhoRiPkcDd0rXpyUAiRd5YjKC7MvNRgAAAABJRU5ErkJggg=='; + Favicon.unreadNSFW = 'data:image/gif;base64,R0lGODlhEAAQAKECAAAAAGbMM////////yH5BAEKAAMALAAAAAAQABAAAAI/nI95wsqygIRxDgGCBhTrwF3Zxowg5H1cSopS6FrGQ82PU1951ckRmYKJVCXizLRC9kAnT0aIiR6lCFT1cigAADs='; + Favicon.unreadNSFWY = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAALVBMVEUAAAAAAAAAAAAAAAAECAIQIAgWLAsePA8oKCg4ODg6dB07OztmzDPBwcH///+rsf3XAAAAA3RSTlMAx9dmesIgAAAAZ0lEQVQI1z2LsQ2AUAhEbwKWofRL4x6O4AhuopWb2P4F7E5prP4MgiaSHHlceMA/jYC0iBrgSnjdKaUacuURTUI2qsyEFcaxvD6wnkifYleAx/N449Mn5wfbkFDM52jgTun6tAQg8QAEvjQg42KY2AAAAABJRU5ErkJggg=='; + } + if (Favicon.SFW) { + Favicon.unread = Favicon.unreadSFW; + return Favicon.unreadY = Favicon.unreadSFWY; + } else { + Favicon.unread = Favicon.unreadNSFW; + return Favicon.unreadY = Favicon.unreadNSFWY; + } + }, + dead: 'data:image/gif;base64,R0lGODlhEAAQAKECAAAAAP8AAP///////yH5BAEKAAIALAAAAAAQABAAAAIvlI+pq+D9DAgUoFkPDlbs7lFZKIJOJJ3MyraoB14jFpOcVMpzrnF3OKlZYsMWowAAOw==' + }; + + ThreadExcerpt = { + init: function() { + if (g.VIEW !== 'thread' || !Conf['Thread Excerpt']) { + return; + } + return Thread.prototype.callbacks.push({ + name: 'Thread Excerpt', + cb: this.node + }); + }, + node: function() { + return d.title = Get.threadExcerpt(this); + } + }; + + ThreadStats = { + init: function() { + var sc, + _this = this; + + if (g.VIEW !== 'thread' || !Conf['Thread Stats']) { + return; + } + if (Conf['Updater and Stats in Header']) { + this.dialog = sc = $.el('span', { + innerHTML: "0 / 0" + (Conf["Page Count in Stats"] ? " / 0" : ""), + id: 'thread-stats', + title: 'Post Count / File Count' + (Conf["Page Count in Stats"] ? " / Page Count" : "") + }); + $.ready(function() { + return Header.addShortcut(sc); + }); + } else { + this.dialog = sc = UI.dialog('thread-stats', 'bottom: 0px; right: 0px;', "
0 / 0" + (Conf["Page Count in Stats"] ? " / 0" : "") + "
"); + $.ready(function() { + return $.add(d.body, sc); + }); + } + this.postCountEl = $('#post-count', sc); + this.fileCountEl = $('#file-count', sc); + this.pageCountEl = $('#page-count', sc); + this.lastModified = '0'; + return Thread.prototype.callbacks.push({ + name: 'Thread Stats', + cb: this.node + }); + }, + node: function() { + var ID, fileCount, post, postCount, _ref; + + postCount = 0; + fileCount = 0; + _ref = this.posts; + for (ID in _ref) { + post = _ref[ID]; + postCount++; + if (post.file) { + fileCount++; + } + } + ThreadStats.thread = this; + ThreadStats.fetchPage(); + ThreadStats.update(postCount, fileCount); + return $.on(d, 'ThreadUpdate', ThreadStats.onUpdate); + }, + onUpdate: function(e) { + var fileCount, postCount, _ref; + + if (e.detail[404]) { + return; + } + _ref = e.detail, postCount = _ref.postCount, fileCount = _ref.fileCount; + return ThreadStats.update(postCount, fileCount); + }, + update: function(postCount, fileCount) { + var fileCountEl, postCountEl, thread; + + thread = ThreadStats.thread, postCountEl = ThreadStats.postCountEl, fileCountEl = ThreadStats.fileCountEl; + postCountEl.textContent = postCount; + fileCountEl.textContent = fileCount; + (thread.postLimit && !thread.isSticky ? $.addClass : $.rmClass)(postCountEl, 'warning'); + return (thread.fileLimit && !thread.isSticky ? $.addClass : $.rmClass)(fileCountEl, 'warning'); + }, + fetchPage: function() { + if (ThreadStats.thread.isDead || !Conf["Page Count in Stats"]) { + return; + } + setTimeout(ThreadStats.fetchPage, 2 * $.MINUTE); + return $.ajax("//api.4chan.org/" + ThreadStats.thread.board + "/threads.json", { + onload: ThreadStats.onThreadsLoad + }, { + headers: { + 'If-Modified-Since': ThreadStats.lastModified + } + }); + }, + onThreadsLoad: function() { + var page, pages, thread, _i, _j, _len, _len1, _ref; + + if (!Conf["Page Count in Stats"]) { + return; + } + ThreadStats.lastModified = this.getResponseHeader('Last-Modified'); + if (this.status !== 200) { + return; + } + pages = JSON.parse(this.response); + for (_i = 0, _len = pages.length; _i < _len; _i++) { + page = pages[_i]; + _ref = page.threads; + for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { + thread = _ref[_j]; + if (thread.no === ThreadStats.thread.ID) { + ThreadStats.pageCountEl.textContent = page.page; + (page.page === pages.length - 1 ? $.addClass : $.rmClass)(ThreadStats.pageCountEl, 'warning'); + return; + } + } + } + } + }; + + ThreadUpdater = { + init: function() { + var checked, conf, el, input, name, sc, settings, subEntries, _ref, + _this = this; + + if (g.VIEW !== 'thread' || !Conf['Thread Updater']) { + return; + } + checked = Conf['Auto Update'] ? 'checked' : ''; + if (Conf['Updater and Stats in Header']) { + this.dialog = sc = $.el('span', { + innerHTML: "", + id: 'updater' + }); + $.ready(function() { + return Header.addShortcut(sc); + }); + } else { + this.dialog = sc = UI.dialog('updater', 'bottom: 0px; left: 0px;', "
"); + $.addClass(doc, 'float'); + $.ready(function() { + $.addClass(doc, 'float'); + return $.add(d.body, sc); + }); + } + this.checkPostCount = 0; + this.timer = $('#update-timer', sc); + this.status = $('#update-status', sc); + $.on(this.timer, 'click', ThreadUpdater.update); + $.on(this.status, 'click', ThreadUpdater.update); + subEntries = []; + _ref = Config.updater.checkbox; + for (name in _ref) { + conf = _ref[name]; + checked = Conf[name] ? 'checked' : ''; + el = $.el('label', { + title: "" + conf[1], + innerHTML: " " + name + }); + input = el.firstElementChild; + $.on(input, 'change', $.cb.checked); + if (input.name === 'Scroll BG') { + $.on(input, 'change', ThreadUpdater.cb.scrollBG); + ThreadUpdater.cb.scrollBG(); + } else if (input.name === 'Auto Update') { + $.on(input, 'change', ThreadUpdater.update); + } + subEntries.push({ + el: el + }); + } + settings = $.el('span', { + innerHTML: 'Interval' + }); + $.on(settings, 'click', this.intervalShortcut); + subEntries.push({ + el: settings + }); + $.event('AddMenuEntry', { + type: 'header', + el: $.el('span', { + textContent: 'Updater' + }), + order: 110, + subEntries: subEntries + }); + return Thread.prototype.callbacks.push({ + name: 'Thread Updater', + cb: this.node + }); + }, + node: function() { + ThreadUpdater.thread = this; + ThreadUpdater.root = this.OP.nodes.root.parentNode; + ThreadUpdater.lastPost = +ThreadUpdater.root.lastElementChild.id.match(/\d+/)[0]; + ThreadUpdater.outdateCount = 0; + ThreadUpdater.lastModified = '0'; + ThreadUpdater.cb.interval.call($.el('input', { + value: Conf['Interval'] + })); + $.on(window, 'online offline', ThreadUpdater.cb.online); + $.on(d, 'QRPostSuccessful', ThreadUpdater.cb.checkpost); + $.on(d, 'visibilitychange', ThreadUpdater.cb.visibility); + return ThreadUpdater.cb.online(); + }, + /* + http://freesound.org/people/pierrecartoons1979/sounds/90112/ + cc-by-nc-3.0 + */ + + beep: 'data:audio/wav;base64,UklGRjQDAABXQVZFZm10IBAAAAABAAEAgD4AAIA+AAABAAgAc21wbDwAAABBAAADAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkYXRhzAIAAGMms8em0tleMV4zIpLVo8nhfSlcPR102Ki+5JspVEkdVtKzs+K1NEhUIT7DwKrcy0g6WygsrM2k1NpiLl0zIY/WpMrjgCdbPhxw2Kq+5Z4qUkkdU9K1s+K5NkVTITzBwqnczko3WikrqM+l1NxlLF0zIIvXpsnjgydZPhxs2ay95aIrUEkdUdC3suK8N0NUIjq+xKrcz002WioppdGm091pK1w0IIjYp8jkhydXPxxq2K295aUrTkoeTs65suK+OUFUIzi7xqrb0VA0WSoootKm0t5tKlo1H4TYqMfkiydWQBxm16+85actTEseS8y7seHAPD9TIza5yKra01QyWSson9On0d5wKVk2H4DYqcfkjidUQB1j1rG75KsvSkseScu8seDCPz1TJDW2yara1FYxWSwnm9Sn0N9zKVg2H33ZqsXkkihSQR1g1bK65K0wSEsfR8i+seDEQTxUJTOzy6rY1VowWC0mmNWoz993KVc3H3rYq8TklSlRQh1d1LS647AyR0wgRMbAsN/GRDpTJTKwzKrX1l4vVy4lldWpzt97KVY4IXbUr8LZljVPRCxhw7W3z6ZISkw1VK+4sMWvXEhSPk6buay9sm5JVkZNiLWqtrJ+TldNTnquqbCwilZXU1BwpKirrpNgWFhTaZmnpquZbFlbVmWOpaOonHZcXlljhaGhpZ1+YWBdYn2cn6GdhmdhYGN3lp2enIttY2Jjco+bnJuOdGZlZXCImJqakHpoZ2Zug5WYmZJ/bGlobX6RlpeSg3BqaW16jZSVkoZ0bGtteImSk5KIeG5tbnaFkJKRinxxbm91gY2QkIt/c3BwdH6Kj4+LgnZxcXR8iI2OjIR5c3J0e4WLjYuFe3VzdHmCioyLhn52dHR5gIiKioeAeHV1eH+GiYqHgXp2dnh9hIiJh4J8eHd4fIKHiIeDfXl4eHyBhoeHhH96eHmA', + cb: { + online: function() { + if (ThreadUpdater.online = navigator.onLine) { + ThreadUpdater.outdateCount = 0; + ThreadUpdater.set('timer', ThreadUpdater.getInterval()); + ThreadUpdater.update(); + ThreadUpdater.set('status', null, null); + } else { + ThreadUpdater.set('timer', null); + ThreadUpdater.set('status', 'Offline', 'warning'); + } + return ThreadUpdater.cb.autoUpdate(); + }, + post: function(e) { + if (e.detail.threadID !== ThreadUpdater.thread.ID) { + return; + } + ThreadUpdater.outdateCount = 0; + if (ThreadUpdater.seconds > 2) { + return setTimeout(ThreadUpdater.update, 1000); + } + }, + checkpost: function(e) { + if (!ThreadUpdater.checkPostCount) { + if (e.detail.threadID !== ThreadUpdater.thread.ID) { + return; + } + ThreadUpdater.seconds = 0; + ThreadUpdater.outdateCount = 0; + ThreadUpdater.set('timer', '...'); + } + if (!(g.DEAD || ThreadUpdater.foundPost || ThreadUpdater.checkPostCount >= 5)) { + return setTimeout(ThreadUpdater.update, ++ThreadUpdater.checkPostCount * $.SECOND); + } + ThreadUpdater.set('timer', ThreadUpdater.getInterval()); + ThreadUpdater.checkPostCount = 0; + delete ThreadUpdater.foundPost; + return delete ThreadUpdater.postID; + }, + visibility: function() { + if (d.hidden) { + return; + } + ThreadUpdater.outdateCount = 0; + if (ThreadUpdater.seconds > ThreadUpdater.interval) { + return ThreadUpdater.set('timer', ThreadUpdater.getInterval()); + } + }, + scrollBG: function() { + return ThreadUpdater.scrollBG = Conf['Scroll BG'] ? function() { + return true; + } : function() { + return !d.hidden; + }; + }, + autoUpdate: function() { + if (ThreadUpdater.online) { + return ThreadUpdater.timeoutID = setTimeout(ThreadUpdater.timeout, 1000); + } else { + return clearTimeout(ThreadUpdater.timeoutID); + } + }, + interval: function() { + var val; + + val = +this.value; + if (val < 1) { + val = 1; + } + ThreadUpdater.interval = this.value = val; + return $.cb.value.call(this); + }, + load: function() { + var klass, req, text, _ref; + + req = ThreadUpdater.req; + switch (req.status) { + case 200: + g.DEAD = false; + ThreadUpdater.parse(JSON.parse(req.response).posts); + ThreadUpdater.lastModified = req.getResponseHeader('Last-Modified'); + if (Conf['Auto Update']) { + ThreadUpdater.set('timer', ThreadUpdater.getInterval()); + } + break; + case 404: + g.DEAD = true; + ThreadUpdater.set('timer', null); + ThreadUpdater.set('status', '404', 'warning'); + clearTimeout(ThreadUpdater.timeoutID); + ThreadUpdater.thread.kill(); + $.event('ThreadUpdate', { + 404: true, + thread: ThreadUpdater.thread + }); + break; + default: + if (Conf['Auto Update']) { + ThreadUpdater.outdateCount++; + ThreadUpdater.set('timer', ThreadUpdater.getInterval()); + } + /* + Status Code 304: Not modified + 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. + */ + + _ref = [0, 304].contains(req.status) ? [null, null] : ["" + req.statusText + " (" + req.status + ")", 'warning'], text = _ref[0], klass = _ref[1]; + ThreadUpdater.set('status', text, klass); + } + if (ThreadUpdater.postID) { + ThreadUpdater.cb.checkpost(); + } + return delete ThreadUpdater.req; + } + }, + getInterval: function() { + var i, j; + + i = ThreadUpdater.interval; + j = Math.min(ThreadUpdater.outdateCount, 10); + if (!d.hidden) { + j = Math.min(j, 7); + } + return ThreadUpdater.seconds = Conf['Optional Increase'] ? Math.max(i, [0, 5, 10, 15, 20, 30, 60, 90, 120, 240, 300][j]) : i; + }, + intervalShortcut: function() { + var settings; + + Settings.open('Advanced'); + settings = $.id('fourchanx-settings'); + return $('input[name=Interval]', settings).focus(); + }, + set: function(name, text, klass) { + var el, node; + + el = ThreadUpdater[name]; + if (node = el.firstChild) { + node.data = text; + } else { + el.textContent = text; + } + if (klass !== void 0) { + return el.className = klass; + } + }, + timeout: function() { + var n; + + ThreadUpdater.timeoutID = setTimeout(ThreadUpdater.timeout, 1000); + if (!(n = --ThreadUpdater.seconds)) { + return ThreadUpdater.update(); + } else if (n <= -60) { + ThreadUpdater.set('status', 'Retrying', null); + return ThreadUpdater.update(); + } else if (n > 0) { + return ThreadUpdater.set('timer', n); + } + }, + update: function() { + var url; + + if (!ThreadUpdater.online) { + return; + } + ThreadUpdater.seconds = 0; + if (Conf['Auto Update']) { + ThreadUpdater.set('timer', '...'); + } else { + ThreadUpdater.set('timer', 'Update'); + } + if (ThreadUpdater.req) { + ThreadUpdater.req.onloadend = null; + ThreadUpdater.req.abort(); + } + url = "//api.4chan.org/" + ThreadUpdater.thread.board + "/res/" + ThreadUpdater.thread + ".json"; + return ThreadUpdater.req = $.ajax(url, { + onloadend: ThreadUpdater.cb.load + }, { + headers: { + 'If-Modified-Since': ThreadUpdater.lastModified + } + }); + }, + updateThreadStatus: function(title, OP) { + var icon, message, root, titleLC; + + titleLC = title.toLowerCase(); + if (ThreadUpdater.thread["is" + title] === !!OP[titleLC]) { + return; + } + if (!(ThreadUpdater.thread["is" + title] = !!OP[titleLC])) { + message = title === 'Sticky' ? 'The thread is not a sticky anymore.' : 'The thread is not closed anymore.'; + new Notification('info', message, 30); + $.rm($("." + titleLC + "Icon", ThreadUpdater.thread.OP.nodes.info)); + return; + } + message = title === 'Sticky' ? 'The thread is now a sticky.' : 'The thread is now closed.'; + new Notification('info', message, 30); + icon = $.el('img', { + src: "//static.4chan.org/image/" + titleLC + ".gif", + alt: title, + title: title, + className: "" + titleLC + "Icon" + }); + root = $('[title="Quote this post"]', ThreadUpdater.thread.OP.nodes.info); + if (title === 'Closed') { + root = $('.stickyIcon', ThreadUpdater.thread.OP.nodes.info) || root; + } + return $.after(root, [$.tn(' '), icon]); + }, + parse: function(postObjects) { + var ID, OP, count, deletedFiles, deletedPosts, files, index, key, node, num, post, postObject, posts, root, scroll, _i, _len, _ref; + + OP = postObjects[0]; + Build.spoilerRange[ThreadUpdater.thread.board] = OP.custom_spoiler; + ThreadUpdater.updateThreadStatus('Sticky', OP); + ThreadUpdater.updateThreadStatus('Closed', OP); + ThreadUpdater.thread.postLimit = !!OP.bumplimit; + ThreadUpdater.thread.fileLimit = !!OP.imagelimit; + posts = []; + index = []; + files = []; + count = 0; + for (_i = 0, _len = postObjects.length; _i < _len; _i++) { + postObject = postObjects[_i]; + num = postObject.no; + index.push(num); + if (postObject.fsize) { + files.push(num); + } + if (num <= ThreadUpdater.lastPost) { + continue; + } + count++; + node = Build.postFromObject(postObject, ThreadUpdater.thread.board.ID); + posts.push(new Post(node, ThreadUpdater.thread, ThreadUpdater.thread.board)); + } + deletedPosts = []; + deletedFiles = []; + _ref = ThreadUpdater.thread.posts; + for (ID in _ref) { + post = _ref[ID]; + ID = +ID; + if (post.isDead && index.contains(ID)) { + post.resurrect(); + } else if (!index.contains(ID)) { + post.kill(); + deletedPosts.push(post); + } else if (post.file && !post.file.isDead && !files.contains(ID)) { + post.kill(true); + deletedFiles.push(post); + } + if (ThreadUpdater.postID && ThreadUpdater.postID === ID) { + ThreadUpdater.foundPost = true; + } + } + if (!count) { + ThreadUpdater.set('status', null, null); + ThreadUpdater.outdateCount++; + } else { + ThreadUpdater.set('status', "+" + count, 'new'); + ThreadUpdater.outdateCount = 0; + if (Conf['Beep'] && d.hidden && Unread.posts && !Unread.posts.length) { + if (!ThreadUpdater.audio) { + ThreadUpdater.audio = $.el('audio', { + src: ThreadUpdater.beep + }); + } + ThreadUpdater.audio.play(); + } + ThreadUpdater.lastPost = posts[count - 1].ID; + Main.callbackNodes(Post, posts); + scroll = Conf['Auto Scroll'] && ThreadUpdater.scrollBG() && ThreadUpdater.root.getBoundingClientRect().bottom - doc.clientHeight < 25; + for (key in posts) { + post = posts[key]; + if (!posts.hasOwnProperty(key)) { + continue; + } + root = post.nodes.root; + if (post.cb) { + if (!post.cb.call(post)) { + $.add(ThreadUpdater.root, root); + } + } else { + $.add(ThreadUpdater.root, root); + } + } + if (scroll) { + if (Conf['Bottom Scroll']) { + d.body.scrollTop = d.body.clientHeight; + } else { + if (root) { + Header.scrollToPost(root); + } + } + } + $.queueTask(function() { + var length, threadID; + + threadID = ThreadUpdater.thread.ID; + length = $$('.thread > .postContainer', ThreadUpdater.root).length; + return Fourchan.parseThread(threadID, length - count, length); + }); + } + return $.event('ThreadUpdate', { + 404: false, + thread: ThreadUpdater.thread, + newPosts: posts, + deletedPosts: deletedPosts, + deletedFiles: deletedFiles, + postCount: OP.replies + 1, + fileCount: OP.images + (!!ThreadUpdater.thread.OP.file && !ThreadUpdater.thread.OP.file.isDead) + }); + } + }; + + ThreadWatcher = { + init: function() { + var sc; + + if (!Conf['Thread Watcher']) { + return; + } + this.shortcut = sc = $.el('a', { + textContent: 'Watcher', + id: 'watcher-link', + href: 'javascript:;', + className: 'disabled' + }); + this.dialog = UI.dialog('watcher', 'top: 50px; left: 0px;', '
Thread Watcher×
'); + $.on(d, 'QRPostSuccessful', this.cb.post); + $.sync('WatchedThreads', this.refresh); + $.on(sc, 'click', this.toggleWatcher); + $.on($('.move>.close', ThreadWatcher.dialog), 'click', this.toggleWatcher); + if (Conf['Toggleable Thread Watcher']) { + Header.addShortcut(sc); + $.addClass(doc, 'fixed-watcher'); + } + $.ready(function() { + ThreadWatcher.refresh(); + $.add(d.body, ThreadWatcher.dialog); + if (Conf['Toggleable Thread Watcher']) { + return ThreadWatcher.dialog.hidden = true; + } + }); + return Thread.prototype.callbacks.push({ + name: 'Thread Watcher', + cb: this.node + }); + }, + node: function() { + var favicon, + _this = this; + + favicon = $.el('a', { + className: 'watch-thread-link', + href: 'javascript:;' + }); + $.on(favicon, 'click', ThreadWatcher.cb.toggle); + $.before($('input', this.OP.nodes.post), favicon); + if (g.VIEW !== 'thread') { + return; + } + return $.get('AutoWatch', 0, function(item) { + if (item['AutoWatch'] !== _this.ID) { + return; + } + ThreadWatcher.watch(_this); + return $["delete"]('AutoWatch'); + }); + }, + refresh: function(watched) { + var ID, board, div, favicon, id, link, nodes, props, thread, x, _ref, _ref1; + + if (!watched) { + $.get('WatchedThreads', {}, function(item) { + return ThreadWatcher.refresh(item['WatchedThreads']); + }); + return; + } + nodes = [$('.move', ThreadWatcher.dialog)]; + for (board in watched) { + _ref = watched[board]; + for (id in _ref) { + props = _ref[id]; + x = $.el('a', { + textContent: '×', + className: 'close', + href: 'javascript:;' + }); + $.on(x, 'click', ThreadWatcher.cb.x); + link = $.el('a', props); + link.title = link.textContent; + div = $.el('div'); + $.add(div, [x, $.tn(' '), link]); + nodes.push(div); + } + } + $.rmAll(ThreadWatcher.dialog); + $.add(ThreadWatcher.dialog, nodes); + watched = watched[g.BOARD] || {}; + _ref1 = g.BOARD.threads; + for (ID in _ref1) { + thread = _ref1[ID]; + favicon = $('.watch-thread-link', thread.OP.nodes.post); + if (ID in watched) { + $.addClass(favicon, 'watched'); + } else { + $.rmClass(favicon, 'watched'); + } + } + }, + toggleWatcher: function() { + $.toggleClass(ThreadWatcher.shortcut, 'disabled'); + return ThreadWatcher.dialog.hidden = !ThreadWatcher.dialog.hidden; + }, + cb: { + toggle: function() { + return ThreadWatcher.toggle(Get.postFromNode(this).thread); + }, + x: function() { + var thread; + + thread = this.nextElementSibling.pathname.split('/'); + return ThreadWatcher.unwatch(thread[1], thread[3]); + }, + post: function(e) { + var board, postID, threadID, _ref; + + _ref = e.detail, board = _ref.board, postID = _ref.postID, threadID = _ref.threadID; + if (postID === threadID) { + if (Conf['Auto Watch']) { + return $.set('AutoWatch', threadID); + } + } else if (Conf['Auto Watch Reply']) { + return ThreadWatcher.watch(board.threads[threadID]); + } + } + }, + toggle: function(thread) { + if (!$.hasClass($('.watch-thread-link', thread.OP.nodes.post), 'watched')) { + return ThreadWatcher.watch(thread); + } else { + return ThreadWatcher.unwatch(thread.board, thread.ID); + } + }, + unwatch: function(board, threadID) { + return $.get('WatchedThreads', {}, function(item) { + var watched; + + watched = item['WatchedThreads']; + delete watched[board][threadID]; + if (!Object.keys(watched[board]).length) { + delete watched[board]; + } + ThreadWatcher.refresh(watched); + return $.set('WatchedThreads', watched); + }); + }, + watch: function(thread) { + return $.get('WatchedThreads', {}, function(item) { + var watched, _name; + + watched = item['WatchedThreads']; + watched[_name = thread.board] || (watched[_name] = {}); + watched[thread.board][thread] = { + href: "/" + thread.board + "/res/" + thread, + textContent: Get.threadExcerpt(thread) + }; + ThreadWatcher.refresh(watched); + return $.set('WatchedThreads', watched); + }); + } + }; + + Unread = { + init: function() { + if (g.VIEW !== 'thread' || !Conf['Unread Count'] && !Conf['Unread Favicon']) { + return; + } + this.db = new DataBoard('lastReadPosts', this.sync); + this.hr = $.el('hr', { + id: 'unread-line' + }); + this.posts = []; + this.postsQuotingYou = []; + return Thread.prototype.callbacks.push({ + name: 'Unread', + cb: this.node + }); + }, + node: function() { + Unread.thread = this; + Unread.title = d.title; + Unread.lastReadPost = Unread.db.get({ + boardID: this.board.ID, + threadID: this.ID, + defaultValue: 0 + }); + $.on(d, '4chanXInitFinished', Unread.ready); + $.on(d, 'ThreadUpdate', Unread.onUpdate); + $.on(d, 'scroll visibilitychange', Unread.read); + if (Conf['Unread Line']) { + return $.on(d, 'visibilitychange', Unread.setLine); + } + }, + ready: function() { + var ID, post, posts, _ref; + + $.off(d, '4chanXInitFinished', Unread.ready); + posts = []; + _ref = Unread.thread.posts; + for (ID in _ref) { + post = _ref[ID]; + if (post.isReply) { + posts.push(post); + } + } + Unread.addPosts(posts); + if (Conf['Scroll to Last Read Post']) { + return Unread.scroll(); + } + }, + scroll: function() { + var hash, post, posts, prevID, 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) { + break; + } + } + root.scrollIntoView(false); + return; + } + posts = Object.keys(Unread.thread.posts); + return Header.scrollToPost(Unread.thread.posts[posts[posts.length - 1]].nodes.root); + }, + sync: function() { + var lastReadPost; + + lastReadPost = Unread.db.get({ + boardID: Unread.thread.board.ID, + threadID: Unread.thread.ID, + defaultValue: 0 + }); + if (!(Unread.lastReadPost < lastReadPost)) { + return; + } + Unread.lastReadPost = lastReadPost; + Unread.readArray(Unread.posts); + Unread.readArray(Unread.postsQuotingYou); + Unread.setLine(); + return Unread.update(); + }, + addPosts: function(newPosts) { + var ID, data, post, _i, _len; + + for (_i = 0, _len = newPosts.length; _i < _len; _i++) { + post = newPosts[_i]; + ID = post.ID; + if (ID <= Unread.lastReadPost || post.isHidden) { + continue; + } + if (QR.db) { + data = { + boardID: post.board.ID, + threadID: post.thread.ID, + postID: post.ID + }; + if (QR.db.get(data)) { + continue; + } + } + Unread.posts.push(post); + Unread.addPostQuotingYou(post); + } + if (Conf['Unread Line']) { + Unread.setLine(newPosts.contains(Unread.posts[0])); + } + Unread.read(); + return Unread.update(); + }, + addPostQuotingYou: function(post) { + var quotelink, _i, _len, _ref; + + if (!QR.db) { + return; + } + _ref = post.nodes.quotelinks; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + quotelink = _ref[_i]; + if (QR.db.get(Get.postDataFromLink(quotelink))) { + Unread.postsQuotingYou.push(post); + } + } + }, + onUpdate: function(e) { + if (e.detail[404]) { + return Unread.update(); + } else { + return Unread.addPosts(e.detail.newPosts); + } + }, + readSinglePost: function(post) { + var i; + + if ((i = Unread.posts.indexOf(post)) === -1) { + return; + } + Unread.posts.splice(i, 1); + if (i === 0) { + Unread.lastReadPost = post.ID; + Unread.saveLastReadPost(); + } + if ((i = Unread.postsQuotingYou.indexOf(post)) !== -1) { + Unread.postsQuotingYou.splice(i, 1); + } + return Unread.update(); + }, + readArray: function(arr) { + var i, post, _i, _len; + + for (i = _i = 0, _len = arr.length; _i < _len; i = ++_i) { + post = arr[i]; + if (post.ID > Unread.lastReadPost) { + break; + } + } + return arr.splice(0, i); + }, + read: $.debounce(50, function(e) { + var ID, bottom, height, i, post, posts, read; + + if (d.hidden || !Unread.posts.length) { + return; + } + height = doc.clientHeight; + posts = Unread.posts; + read = []; + i = posts.length; + while (post = posts[--i]) { + bottom = post.nodes.root.getBoundingClientRect().bottom; + if (bottom < height) { + ID = post.ID; + posts.remove(post); + } + } + if (!ID) { + return; + } + Unread.lastReadPost = ID; + Unread.saveLastReadPost(); + Unread.readArray(Unread.postsQuotingYou); + if (e) { + return Unread.update(); + } + }), + saveLastReadPost: $.debounce(2 * $.SECOND, function() { + return Unread.db.set({ + boardID: Unread.thread.board.ID, + threadID: Unread.thread.ID, + val: Unread.lastReadPost + }); + }), + setLine: function(force) { + var post, root; + + if (!(d.hidden || force === true)) { + return; + } + if (post = Unread.posts[0]) { + root = post.nodes.root; + if (root !== $('.thread > .replyContainer', root.parentNode)) { + return $.before(root, Unread.hr); + } + } else { + return $.rm(Unread.hr); + } + }, + update: function(dontrepeat) { + var count; + + count = Unread.posts.length; + if (Conf['Unread Count']) { + d.title = "" + (Conf['Quoted Title'] && Unread.postsQuotingYou.length ? '(!) ' : '') + (count || !Conf['Hide Unread Count at (0)'] ? "(" + count + ") " : '') + (g.DEAD ? "/" + g.BOARD + "/ - 404" : "" + Unread.title); + if (!dontrepeat) { + setTimeout(function() { + d.title = ''; + return Unread.update(true); + }, $.SECOND); + } + } + if (!Conf['Unread Favicon']) { + return; + } + return Favicon.el.href = g.DEAD ? Unread.postsQuotingYou.length ? Favicon.unreadDeadY : count ? Favicon.unreadDead : Favicon.dead : count ? Unread.postsQuotingYou.length ? Favicon.unreadY : Favicon.unread : Favicon["default"]; + } + }; + + Redirect = { + thread: {}, + post: {}, + file: {}, + init: function() { + var archive, arr, boardID, data, id, name, type, _i, _len, _ref, _ref1, _ref2, _ref3; + + _ref = Conf['selectedArchives']; + for (boardID in _ref) { + data = _ref[boardID]; + for (type in data) { + id = data[type]; + _ref1 = Redirect.archives; + for (name in _ref1) { + archive = _ref1[name]; + if (name !== id || type === 'post' && archive.software !== 'foolfuuka') { + continue; + } + arr = type === 'file' ? archive.files : archive.boards; + if (arr.contains(boardID)) { + Redirect[type][boardID] = archive; + } + } + } + } + _ref2 = Redirect.archives; + 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; + } + 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; + } + } + } + }, + archives: { + 'Foolz': { + 'domain': 'archive.foolz.us', + 'http': true, + 'https': true, + 'software': 'foolfuuka', + 'boards': ['a', 'co', 'gd', 'jp', 'm', 'q', 'sp', 'tg', 'tv', 'vp', 'vr', 'wsg'], + 'files': ['a', 'gd', 'jp', 'm', 'q', 'tg', 'vp', 'vr', 'wsg'] + }, + 'NSFW Foolz': { + 'domain': 'nsfw.foolz.us', + 'http': true, + 'https': true, + 'software': 'foolfuuka', + 'boards': ['u'], + 'files': ['u'] + }, + 'The Dark Cave': { + 'domain': 'archive.thedarkcave.org', + 'http': true, + 'https': true, + 'software': 'foolfuuka', + 'boards': ['c', 'int', 'out', 'po'], + 'files': ['c', 'po'] + }, + '4plebs': { + 'domain': 'archive.4plebs.org', + 'http': true, + 'software': 'foolfuuka', + 'boards': ['hr', 'tg', 'tv', 'x'], + 'files': ['hr', 'tg', 'tv', 'x'] + }, + 'Nyafuu': { + 'domain': 'archive.nyafuu.org', + 'http': true, + 'https': true, + 'software': 'foolfuuka', + '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'] + }, + 'nth-chan': { + 'domain': 'nth.pensivenonsen.se', + 'http': true, + 'software': 'foolfuuka', + 'boards': ['vg'], + 'files': ['vg'] + }, + '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'] + }, + 'Install Gentoo': { + 'domain': 'archive.installgentoo.net', + 'http': true, + 'https': true, + 'software': 'fuuka', + 'boards': ['diy', 'g', 'sci'], + 'files': [] + }, + 'Rebecca Black Tech': { + 'domain': 'rbt.asia', + 'http': true, + 'https': true, + 'software': 'fuuka', + 'boards': ['cgl', 'g', 'mu', 'w'], + 'files': ['cgl', 'g', 'mu', 'w'] + }, + 'Heinessen': { + 'domain': 'archive.heinessen.com', + 'http': true, + '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', 's4s', 'tg', 'vr'], + 'files': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 's4s', 'vr'] + } + }, + to: function(dest, data) { + var archive; + + archive = (dest === 'search' ? Redirect.thread : Redirect[dest])[data.boardID]; + if (!archive) { + return ''; + } + return Redirect[dest](archive, data); + }, + protocol: function(archive) { + var protocol; + + protocol = location.protocol; + if (!archive[protocol.slice(0, -1)]) { + protocol = protocol === 'https:' ? 'http:' : 'https:'; + } + return "" + protocol + "//"; + }, + thread: function(archive, _arg) { + var boardID, path, postID, threadID; + + boardID = _arg.boardID, threadID = _arg.threadID, postID = _arg.postID; + path = threadID ? "" + boardID + "/thread/" + threadID : "" + boardID + "/post/" + postID; + if (archive.software === 'foolfuuka') { + path += '/'; + } + if (threadID && postID) { + path += archive.software === 'foolfuuka' ? "#" + postID : "#p" + postID; + } + return "" + (Redirect.protocol(archive)) + archive.domain + "/" + path; + }, + post: function(archive, _arg) { + var boardID, postID, protocol; + + boardID = _arg.boardID, postID = _arg.postID; + protocol = Redirect.protocol(archive); + if (['Foolz', 'NSFW Foolz'].contains(archive.name)) { + protocol = 'https://'; + } + return "" + protocol + archive.domain + "/_/api/chan/post/?board=" + boardID + "&num=" + postID; + }, + file: function(archive, _arg) { + var boardID, filename; + + boardID = _arg.boardID, filename = _arg.filename; + return "" + (Redirect.protocol(archive)) + archive.domain + "/" + boardID + "/full_image/" + filename; + }, + search: function(archive, _arg) { + var boardID, path, type, value; + + boardID = _arg.boardID, type = _arg.type, value = _arg.value; + type = type === 'name' ? 'username' : type === 'MD5' ? 'image' : type; + value = encodeURIComponent(value); + path = archive.software === 'foolfuuka' ? "" + boardID + "/search/" + type + "/" + value : "" + boardID + "/?task=search2&search_" + (type === 'image' ? 'media_hash' : type) + "=" + value; + return "" + (Redirect.protocol(archive)) + archive.domain + "/" + path; + } + }; + + PSAHiding = { + init: function() { + if (!Conf['Announcement Hiding']) { + return; + } + $.addClass(doc, 'hide-announcement'); + return $.on(d, '4chanXInitFinished', this.setup); + }, + setup: function() { + var btn, entry, items, psa; + + $.off(d, '4chanXInitFinished', PSAHiding.setup); + if (!(psa = $.id('globalMessage'))) { + $.rmClass(doc, 'hide-announcement'); + return; + } + entry = { + type: 'header', + el: $.el('a', { + textContent: 'Show announcement', + className: 'show-announcement', + href: 'javascript:;' + }), + order: 50, + open: function() { + return psa.hidden; + } + }; + $.event('AddMenuEntry', entry); + $.on(entry.el, 'click', PSAHiding.toggle); + PSAHiding.btn = btn = $.el('a', { + innerHTML: ' - ', + title: 'Hide announcement.', + className: 'hide-announcement', + href: 'javascript:;' + }); + $.on(btn, 'click', PSAHiding.toggle); + items = { + hiddenPSA: 0, + hiddenPSAs: null + }; + $.get(items, function(_arg) { + var hiddenPSA, hiddenPSAs; + + hiddenPSA = _arg.hiddenPSA, hiddenPSAs = _arg.hiddenPSAs; + if (hiddenPSAs) { + $["delete"]('hiddenPSAs'); + if (hiddenPSAs.contains(psa.textContent.replace(/\W+/g, '').toLowerCase())) { + hiddenPSA = +$.id('globalMessage').dataset.utc; + $.set('hiddenPSA', hiddenPSA); + } + } + PSAHiding.sync(hiddenPSA); + $.before(psa, btn); + return $.rmClass(doc, 'hide-announcement'); + }); + return $.sync('hiddenPSA', PSAHiding.sync); + }, + toggle: function(e) { + var UTC; + + if ($.hasClass(this, 'hide-announcement')) { + UTC = +$.id('globalMessage').dataset.utc; + $.set('hiddenPSA', UTC); + } else { + $.event('CloseMenu'); + $["delete"]('hiddenPSA'); + } + return PSAHiding.sync(UTC); + }, + sync: function(UTC) { + var hr, psa; + + psa = $.id('globalMessage'); + psa.hidden = PSAHiding.btn.hidden = UTC && UTC >= +psa.dataset.utc ? true : false; + if ((hr = psa.nextElementSibling) && hr.nodeName === 'HR') { + return hr.hidden = psa.hidden; + } + } + }; + + CatalogLinks = { + init: function() { + var el, input; + + if (!Conf['Catalog Links']) { + return; + } + el = $.el('label', { + id: 'toggleCatalog', + href: 'javascript:;', + innerHTML: " Catalog Links", + title: "Turn catalog links " + (Conf['Header catalog links'] ? 'off' : 'on') + "." + }); + input = $('input', el); + $.on(input, 'change', this.toggle); + $.sync('Header catalog links', CatalogLinks.set); + $.event('AddMenuEntry', { + type: 'header', + el: el, + order: 95 + }); + return $.on(d, '4chanXInitFinished', function() { + return CatalogLinks.set(Conf['Header catalog links']); + }); + }, + toggle: function() { + var useCatalog; + + $.event('CloseMenu'); + $.set('Header catalog links', useCatalog = this.checked); + return CatalogLinks.set(useCatalog); + }, + set: function(useCatalog) { + var a, board, path, _i, _len, _ref; + + path = useCatalog ? 'catalog' : ''; + _ref = $$("#board-list a[href*=\"boards.4chan.org\"]:not(.catalog),\n#boardNavDesktopFoot a[href*=\"boards.4chan.org\"]"); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + a = _ref[_i]; + board = a.pathname.split('/')[1]; + if (['f', 'status', '4chan'].contains(board) || !board) { + continue; + } + if (Conf['External Catalog']) { + a.href = useCatalog ? CatalogLinks.external(board) : "//boards.4chan.org/" + board + "/"; + } else { + a.pathname = "/" + board + "/" + path; + } + } + return this.title = "Turn catalog links " + (useCatalog ? 'off' : 'on') + "."; + }, + external: function(board) { + return (['a', 'c', 'g', 'co', 'k', 'm', 'o', 'p', 'v', 'vg', 'w', 'cm', '3', 'adv', 'an', 'cgl', 'ck', 'diy', 'fa', 'fit', 'int', 'jp', 'mlp', 'lit', 'mu', 'n', 'po', 'sci', 'toy', 'trv', 'tv', 'vp', 'x', 'q'].contains(board) ? "http://catalog.neet.tv/" + board : ['d', 'e', 'gif', 'h', 'hr', 'hc', 'r9k', 's', 'pol', 'soc', 'u', 'i', 'ic', 'hm', 'r', 'w', 'wg', 'wsg', 't', 'y'].contains(board) ? "http://4index.gropes.us/" + board : "//boards.4chan.org/" + board + "/catalog"); + } + }; + + IDColor = { + init: function() { + if (!Conf['Color User IDs']) { + return; + } + return Post.prototype.callbacks.push({ + name: 'Reveal Spoilers', + cb: this.node + }); + }, + node: function(post) { + var str, uid; + + if (!(uid = $('.hand', this.nodes.uniqueID))) { + return; + } + str = this.info.uniqueID; + if (uid.nodeName === 'SPAN') { + return uid.style.cssText = IDColor.apply.call(str); + } + }, + ids: {}, + compute: function(str) { + var hash, rgb; + + hash = this.hash(str); + rgb = [(hash >> 24) & 0xFF, (hash >> 16) & 0xFF, (hash >> 8) & 0xFF]; + rgb[3] = ((rgb[0] * 0.299) + (rgb[1] * 0.587) + (rgb[2] * 0.114)) > 125; + this.ids[str] = rgb; + return rgb; + }, + apply: function() { + var rgb; + + rgb = IDColor.ids[this] || IDColor.compute(this); + return ("background-color: rgb(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + "); color: ") + (rgb[3] ? "black;" : "white; border-radius: 3px; padding: 0px 2px;"); + }, + hash: function(str) { + var i, j, msg; + + msg = 0; + i = 0; + j = str.length; + while (i < j) { + msg = ((msg << 5) - msg) + str.charCodeAt(i); + ++i; + } + return msg; + } + }; + + CustomCSS = { + init: function() { + if (!Conf['Custom CSS']) { + return; + } + return this.addStyle(); + }, + addStyle: function() { + return this.style = $.addStyle(Conf['usercss']); + }, + rmStyle: function() { + if (this.style) { + $.rm(this.style); + return delete this.style; + } + }, + update: function() { + if (!this.style) { + this.addStyle(); + } + return this.style.textContent = Conf['usercss']; + } + }; + + Emoji = { + init: function() { + var css, icon, name, pos, _ref; + + if (!Conf['Emoji']) { + return; + } + pos = Conf['emojiPos']; + css = ["a.useremail[href]:last-of-type::" + pos + " {\n vertical-align: top;\n margin-" + (pos === "before" ? "right" : "left") + ": 5px;\n}\n"]; + this.icons["PlanNine"] = Emoji.icons["Plan9"]; + this.icons['Sage'] = Emoji.sage[Conf['sageEmoji']]; + _ref = this.icons; + for (name in _ref) { + icon = _ref[name]; + if (!this.icons.hasOwnProperty(name)) { + continue; + } + css.push("a.useremail[href*='" + name + "']:last-of-type::" + pos + ",\na.useremail[href*='" + (name.toLowerCase()) + "']:last-of-type::" + pos + ",\na.useremail[href*='" + (name.toUpperCase()) + "']:last-of-type::" + pos + " {\n content: url('data:image/png;base64," + icon + "');\n}\n"); + } + return $.addStyle(css.join(""), 'emoji'); + }, + sage: { + '4chan SS': 'iVBORw0KGgoAAAANSUhEUgAAAA4AAAANCAYAAACZ3F9/AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAa9JREFUKFOdkt0rg2EUwM95b2zlL0CRRLngksznXrJsNtYW1tjYhM3mY6+IXZAbikhTKJp8XZAp81UmWYhIRHHhUi60e7s6ntdCa2449es8PfU7z+k5B6AbyuE/wQlc4BcO2d06unAUBCgFE0hianOd3NHIcy8NPwrUf9NBPZcOEi7ayXZiea/1V7+ljaXeYAfOgg2So2TOwQWGnwQafOgi962TnMFmatozUeNu4yetASspVvgXiUvii5K5Nm6z56ol3Hdtpy+cwSYy+HRUt1nLsoEato0kXyh6wTac+24brThWv6MNOYNW9prlG/uxmbRrFaT0VrCspZoNPSUNJNyCBcoiLZuhLH0o9U6UrAfGKCz7RlLM81Q8XUwqr4oKPLIQmnA8IupBigacVy7yrya/2JouhryJHJJNykg+UxLGOtz6+SQNpEiMcduls4Wvoli9WklVKz+ol5SU4U6ngql8Qj2eRI+GyajBhSRH4r3cUxhSeRVhsYBmWUWiyM+UMDmDUI2nsfuSC1I27nLgYZJlP8jhjJ3PY8iE+L8tWx4kQC6MQA5b1D9HNiRCFhx8AF/e2qh92VnKAAAAAElFTkSuQmCC', + 'appchan': 'iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAMAAAAolt3jAAABa1BMVEUAAACqrKiCgYIAAAAAAAAAAACHmX5pgl5NUEx/hnx4hXRSUVMiIyKwrbFzn19SbkZ1d3OvtqtpaWhcX1ooMyRsd2aWkZddkEV8vWGcpZl+kHd7jHNdYFuRmI4bHRthaV5WhUFsfGZReUBFZjdJazpGVUBnamYfHB9TeUMzSSpHgS1cY1k1NDUyOC8yWiFywVBoh1lDSEAZHBpucW0ICQgUHhBjfFhCRUA+QTtEQUUBAQFyo1praWspKigWFRZHU0F6j3E9Oz5VWFN0j2hncWONk4sAAABASDxJWkJKTUgAAAAvNC0fJR0DAwMAAAA9QzoWGhQAAAA8YytvrFOJsnlqyT9oqExqtkdrsExpsUsqQx9rpVJDbzBBbi5utk9jiFRuk11iqUR64k5Wf0JIZTpadk5om1BkyjmF1GRNY0FheFdXpjVXhz86XSp2yFJwslR3w1NbxitbtDWW5nNnilhFXTtYqDRwp1dSijiJ7H99AAAAUnRSTlMAJTgNGQml71ypu3cPEN/RDh8HBbOwQN7wVg4CAQZ28vs9EDluXjo58Ge8xwMy0P3+rV8cT73sawEdTv63NAa3rQwo4cUdAl3hWQSWvS8qqYsjEDiCzAAAAIVJREFUeNpFx7GKAQAYAOD/A7GbZVAWZTBZFGQw6LyCF/MIkiTdcOmWSzYbJVE2u1KX0J1v+8QDv/EkyS0yXF/NgeEILiHfyc74mICTQltqYXBeAWU9HGxU09YqqEvAElGjyZYjPyLqitjzHSEiGkrsfMWr0VLe+oy/djGP//YwfbeP8bN3Or0bkqEVblAAAAAASUVORK5CYII=' + }, + icons: { + 'Plan9': 'iVBORw0KGgoAAAANSUhEUgAAAAwAAAAPCAYAAAGn5h7fAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3AoYAzE15J1s7QAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAACAElEQVQoz3WSz4sSARTHvzMjygpqYg3+KIhkE83DKtKlf0C9SrTRuZNEx0VowU6CuSeJNlwwpEO2kJ6SQBiIUAzFjRDF4wrjKosnGx3HmdehFDfpe/2+z/s++D5gU7IsEwRByICIiAEAIiIAYAFAXsjYVr/fLxMRNVvN+prJ5/OA3+/XERFNf02JyeVyDx0OxyvLNQsnimLKfcf9KRQKXQAAnE6nlf5qMpnQycnbP/kAoKoqsSwLAJhOp+AAwOv1otvtpqxWq73dbt/r9XqvEQ6HUalUEvF4XLd5IpvNZqlerzd5nlf6/f6tTCZjBACk0+nb+XxeW4UrikLJZPImAGA0Gq0NIqJyuSyyANDr9Q5Wu1utFvR6/SULAI1G4+vK8Pv90DTtGwsAJpPpaGUYDAZ0Op3PHAAEg8H3tVqtbrtu21sqyxuRSOQJk0ql9IvF4r7b7f7pcrlejkaj57IsH58Pzp8dvjhc/lsBk0gkbLFYrFqtVvd27+4qOk733ePxPDCbzVBVFfP5fCiK4rvhxfDN/qP9wSasGwwGMv1HiqJQsVg8ZlfTHMepkiR1t05gGJBGmM/nMBqNj9nN9kql0lNN064ARISzH2cQBAGz2ewLu2na7XYLwzBbvxYIBBCNRrFj3BmsAZ/PZ+J5/kOhUIAkSVeA8XiMZqt5efrx9OA3GfcgvyVno9cAAAAASUVORK5CYII=', + 'Neko': 'iVBORw0KGgoAAAANSUhEUgAAABMAAAARCAMAAAAIRmf1AAACoFBMVEUAAABnUFZoUVddU1T6+PvFwLzn4eFXVlT/+vZpZGCgm5dKU1Cfnpz//flbWljr5uLp5OCalpNZWFb//f3r6+n28ff9+PRaVVH59Pr//vr38vj57/Dp7eyjn5zq8O5aVVJbYV9nVFhjUFRiWFlZVlFgZGOboJzm5uZhamfz9/bt8fDw6+drb26bl5j/8/lkX1z06uldWFS5r61UT0tfWlbDwr3Ew76moqNRTU7Mx8P75OpeY19pWl1XW1qzr6x5eHaLiojv7+1UT0xIU0uzqadVS0nV0MxkZGT5+PPk497///ra29Xq5eFtY2H28e2hnJignJlUUE1dXV2vrqxkY2FkYF/m3d5vZmfDuruhl5aZlJHx8O75+PZWVVP29vT/9fTj3trv6ubh5eRdXFqTkpBOTUtqZmX88/RMQ0T78vPEvr7HwcHDwsDq6ef///3Gx8H++fXEv7tZWVedmZZXXVudnJp0c3FZU1f79fnb1dlXUVVjXWFrZmy8t7359/qLj455e3q4s69vamZjX1zy4+avpaReWFz/+f1NR0vu6Ozp4+f48/lnYmi8ur3Iw7/69fHz7+xbV1SZmJZVUk1ZV1zq5ez++f/c196uqbDn4uj9+P7z7vRVVVXt6ORiXl/OycXHw8CPi4ihoJ5aWF3/+v/k3+axrLOsp67LzMZYU1m2sq9dWF5WUU1WUk/Au7eYlJGqpqObmphYVV749f7p5Or38fPu6OpiXFz38fH79vLz7urv6+hhYF5cWWKal6D//f/Z09Xg29exraqbl5RqaW6kpKTq5uPv7Of/+PDj29D//vP18Ozs5+OloJymoZ1ZVVJZWVlkYF2hnpmblIyspJmVjYKQi4enop5STUlRTUpcWUhqY1BgWT9ZUjhcV1NiXVkkhke3AAAABHRSTlMA5vjapJ+a9wAAAP9JREFUGBk9wA1EAwEAhuHv3dTQAkLiUlJFJWF0QDLFYDRXIMkomBgxNIYxhOk4wwCqQhQjxgxSGIsALFA5BiYbMZHajz1oJlx51sBJpf6Gd3zONcrqm/r1W8ByK0r+XV1LXyOLLnjW6hMGpu0u1IzPSdO17DgrGC6AadrVodGcDQYbhguP6wAvAaC0BRZQalkUQ8UQDz5tAof0XbejOFcV5xiUoCfjj3O/nf0ZbqAMPYmzU18KSDaRQ08qnfw+B2JNdAEQt2O5vctUGjhoIBU4ygPsj2Vh5zYopDK73hsirdkPTwGCbSHpiYFwYVVC/17pCFSBeUmoqwYQuZtWxx+BVEz0LeVKIQAAAABJRU5ErkJggg==', + 'Madotsuki': 'iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAMAAADTRh9nAAAALVBMVEUAAAC3iopWLTtWPkHnvqUcBxx5GCZyAAARERGbdXJrRUyGRUyYbY23coZFGDRFGEYfAAAAAXRSTlMAQObYZgAAAGhJREFUeF5Vy1kOQyEMQ1Fshzd12P9y61AixLX4yJFo1cvVUfT23GaflF0HPLln6bhnZVKCcrIWGqpCUcKYSP3JSIRySKTtULPNwMaD8/NC8tsyqsd1hR+6qeqIDHc3LD0B3KdtV1f2A+LJBBIHSgcEAAAAAElFTkSuQmCC', + 'Sega': 'iVBORw0KGgoAAAANSUhEUgAAACwAAAALBAMAAAD2A3K8AAAAMFBMVEUAAACMjpOChImytLmdnqMrKzDIyM55dnkODQ94foQ7PkXm5Olsb3VUUVVhZmw8Sl6klHLxAAAAAXRSTlMAQObYZgAAANFJREFUGJVjYIACRiUlJUUGDHBk4syTkxQwhO3/rQ/4ZYsuymi3YEFUqAhC4LCJZJGIi1uimKKjk3KysbOxsaMnAwNLyqoopaXhttf2it1anrJqke1pr1DlBAZhicLnM5YXZ4RWlIYoezx0zrjYqG6czCDsYRzxIko6Q/qFaKy0690Ij0MxN8K2MIhJXF+hsfxJxuwdpYGVaUU3Mm5bqgKFOZOFit3Vp23J3pgsqLxFUXpLtlD5bgcGBs45794dn6mkOVFQUOjNmXPPz8ysOcAAANw6SHLtrqolAAAAAElFTkSuQmCC', + 'Sakamoto': 'iVBORw0KGgoAAAANSUhEUgAAABEAAAAQCAYAAADwMZRfAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAxVJREFUOE+Nk19IU1EYwK+GQQTVQ39egh6ibKlzw91z7rn3bvfOmddNszl1bjKXc5rJJGmBUr7Yg9qTD0IalFgRBEYg6EDQQB+GovQyQgiaUZsoLcgHMcr069w7MgcGXfi453zn+37fv3MYZt/n99e76tzVj4JN/hP79fvXnV3hnNabwUBjoOHcgTYOu/JQspgTzsqKgn9BfD4vkWTzur287PqLVy+zM+yePB7KsRXLywTjnSpnZctBkPCdW8ccDuU55vBO8RXbkC/oP5ph19V5+7LIky0OY1BKbZEbLcFSt7u6pN7jLmltCVrr3DV5jY3+KovFEsccB1KJNVpefe10BqS2tqqO4/AuphBB4L/LkrRqNgtJs1lMypLls1kU38mytMLz/E8VIlutqVqX6/weZG52OttRXjbE0cP/FYLRlpVjDXuQ/r77x2XZPKkCHA4HBAIBkCQpAygIAvh8Pu2MZgO0Lz+QSa/sQfwN9RfpVN66XC6Ynp6GhYUFGBwczAC1t7fD0tISxONx6O7upgHILmsqvLcHodOggfiV/v5+SCaT4HQ6IRaLgdfr1bIRRREmJyfBZrNBNBqF+fl5sNsdgE2GiAbp6bmbdbXC7qWQbxMTE7C2tgY6nQ5SqRSEw2ENopaoZpCXlwdTU1NaoECgCbgiU6y8QH+ECYWaTymK7TWdys7MzIwGaWtrg42NDejo6AB1WjU1NZo+FArB2NgYrK6uQrAlCASxn2z6wkuMp87VIAhkE2MEAwMDkEgkYHx8HBYXF0HtkQpRy1BLiEQisLy8rPVNKSsFjEzrXH4+z1hlS4xDhKadNu7t7YPR0VHweDzAEVWfHru6HxkZgeHhYVAURYNjkylVWKArZjjMzqmdVi+QCsLUkQiEjvDvncEkvU7/qQ0Vgukeo48Go87IiCJnZNmipxiz7wXEbVDnbUxQOgM12h9n6qTq6NvapRdtkwaP0XK8RmPuYSbxYfaQ/sJJhjfknuFRURUi7AMOozcCwl94hLZp5F+EioDQVwqYI6jomZU1NFtM+rOSxZjVazcyvwHr/p/Kws1jegAAAABJRU5ErkJggg==', + 'Baka': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAA0pJREFUOE91k3tI01EUx39JOpA0H4jNx0pbD3XTalISWf8YFlEgldqDsBLLyqjEKBCiLLWiggh6/KEV1WZ7OaelLZvDdDafNW1JFraWe/32+01FrUZ9uy4ylLpw4Z5z7/nc77n3HIqaMRIjZJyEcNX+uFCFeGmI/GZciEIsCFJUTvoAzDz+1y7K76MSwhX5hXl6z+WSbrzU2KB8YEGDwgrTaxZ3b7xHcaHhR3xw7Z5/UviB1ReP5XSg3+TAqYJOxMzWISFIC0GQDomhTVA9skCnsaAwp/vnMq66dBokNuBR9uFd7T9Z1zCunjci0qcRJUVdoJ3DYOhRnC/qBZ+jQbfeCc+37yjY2UEg0iwvJE0k9l8Z+8xqHmTgot0QLdQgTaQFQ2AsOzlHvOu1S5pwOLsHHo8HjHMCq2MazNvTlByKHyrJLDvdR25jMWRxYx5HjeMH2r1BDOOeguRua4OI14jx8a8YH5tA+al3EHKlW6mYOapb2oZBOOwMbEMseAE12L+jjUh3w+VipyAZ65oxn1NP/GMYGR6Ftn4Qsf7qa9S82Y/l/X122G0uL2TbxmZEz1WhXW8mUol8moXu+SCi/OoQ6VsDh3UUwyQ1k9GOaI5MTkX4yWTGHutvgI1F28sviAlRgxeoRm62HvsyW8En9pZ1TYgi6TntoyQtFm86rVgUoJZRvDnKMmXVAGxWmkAYOBwudBqGcHCvHulrGpGT2Uy+z4yT+QYsCXtCUpp8GxbKhx8gDK0ro+KjJGvzdjfDZnN6VdisLD5/JjArQ2zW66PJOj2lEZtStaBphkwah7K6kMJ/GEulp1bMWhAmMbTozOQRaWRtfoZVgjo4iRra4SYgGi26TwjxVeDKhR7Y7U606ixICq9tr7hd7+OthRWL7yUnJ1WPmXotqLhpRICPHCePtuFV6xdUPTAhcWEtRHEqfHpPyto4hPXLXnzflSEJnFaN3OCKDcsFsrEntR9RUmxARLAUgT5iBPuJsXWDBj0dZjRU9yNV+PTbpjTp9OA/pOSk24nRkXf1J462oPxcJ65f6ULlHSMulepRerYDgvj7A0cKpNz/tyTZqbzXO4t0ZZGQJ34RH11lFHIlA8LIqreCCMUZRY3cd2bwL/5/RmjNSXqtAAAAAElFTkSuQmCC', + 'Ponyo': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAuNJREFUOE+Nk3tI01EUx39BTytConQTt1am07m5abi5KT5S8z2dj1yOEMUC7aUgIoimlmUEWX9kBZGWaamEmE6U1BI1XNPNGTrnHs33IwuSXrL4NgcJ0mNdOHDh3PPhnPP9XoKwcroJYvMQiRSicHCQKCgUyZC9/T5rNet5KUFs0zCZbZMsFmZ9fTEjEEBDp4/KSSSb/4JoGIyWaTYbiykpWEhOxhSHAzWD0aqkUGhWAcVkW58xlvuPhfh4zItEmOHxYDR3MhcdDaNAsKJydAz5IySKRNjEUmy88vjOVaU8F0iPCqCNjEBHkC/UYaGYFwqxmJoKLYOhkxPElg0QsbNtTlmox9yjRD9UCbnoOR+J/lwRWtOCcdXfDc2BPpg0d7CQlIQZPh9KKlVkAQjJ2x2zmOSsQu7hpzUJfBhLjsNQmADjxcT10Bcl4rE4EHc5LjBEhEPn7f1WTqXSLQB/s1Tp7vslsoIkyPPiMJAbi86McBguiaHKjoEqR4jJy2K0nAxApzMN5iUGrclrKVaz2fUvuF4tRbxDKA90w5VjTFyLZKHpTBSq4/1QnxGB2qxoVIZx0JopRCPHFSNOThfWZzfrXDcZEowH4iA05ATg68hDtBaL0HAuCm3lJ9Bfcx2fFNUoi/DCjRgfNHHd1wCZA2TyXjNkE6F0cBDpPFiojeNi8EkJdFoN3vXch0nbBJOhDd907dANv8JITxNqziag3ZsJbUDAwLin50Q9QWwl1qSYoNOVvUcOoqOqAAa9Fu9H2/F9+B5WZLcwOyxFX18flLI+VASyMGVeoJHD+Tzq5BS1PoaKRrNT8127P74swsq4FCa9FKvqBqwaOiz3hdEuLKueYSyECT2LNW0eIfo3E/WmEbvnG1MUJnWdpWhDGDvxQXZHo+RR0uW2tnv+auPX+TvtJm7zKpaen/4y2yjBUlcxlvtvmvT16ZWDpQeoVv3/60F/NrHjTf4ugazIXtJ8ivjnz/sJ+yGQRjcqUdIAAAAASUVORK5CYII=', + 'Rabite': 'iVBORw0KGgoAAAANSUhEUgAAABIAAAAQCAYAAAAbBi9cAAAD/0lEQVR4Xl2MXUxbdQDFz/9+9Lb3tkBLCxTKhzgoOOZAsokbJmZxDFHnd+LL4hKVzBgfNCY++ODbjDEaZowvErOM6HRu6hKZY2rIAOkCY4OSDTpFaAsrlJa2t5+39+NvjT7tnJzknIfzI98Nf/C6TuXdguWBd1q9rcb8/CwsZiu2Ywm4nDVo3VWLZCKDaDwJq9mCg31PgjAMKKUwmcyYvTbek9iJRDm6M/XswEDjwNz6plWW6wdZhjUAintFCEEhn0N04zYskljaDLaj8ar49oUrsYR6mrFJNj322w46H8y+mitM/ZJKZmyE4XAvjJSsazpyuSzslVZIkgWKOvvRgQ6Xrdlhqmds7o7bFZoLkctreKxf7GtuCE7IyUQjBQcQ8j/lvxCGQJZz0IoCVpamTtzfIh9nwiaIrCQyjNg8mq11oDLUhNXRJfT1Ozr3tS/PqpnQ80qRgjAmKIqBfK4ItbSLKoOZqR/6neLkENlSUAIhlktvEf+sD2rkm8nWTHtvZCGMVON1ePuaoBER31/MXGly1wSqq9Uug6FluYyWXJiPqFXmjd4Dh9oF9ZKKimYXRtYCx8lmMIDIxlIPGz591av0mtanF7FcCEN6iMXeox2wOJ0QJAmUAoRQaIqCnWAQY1/ewKNGNeQuYXkm0d2NC2e+wvmRr/Hx+6+8PHayrbDyyQBNDb9As3PHKDWG6MTM23RoeJAWsqeoWvyUUv0UHf7pBB0fe4OeeXe3/vmHbx3+8dwIGJ4IsFpMMFe0fbtAn+nwZePr1u4MBK8XIALG/Rt479wYrs2vgeNNAMNgMbiNzybuoKVvn+Gs9kbr6qpBfJfGYHFIkJUCoGwfqcoMX/b27EGhwgOjoCADDlP+CA51ugFFRzoB8FYNaQ1oqKD44+eNL+wNj7zJGQSIhe8+jgQ9thk+27v/KRY6L4FSCkVOwtlQj6P73Qgt/o1ERoKt4iUkE7+jrZMHyzIoK9cOBFfT4LbWAk+0a7ZLnvqHcTNdACgFScfAcjxEdy00VQclHGo7dqGeYxHbvIo6hwhSghCehb3G5p6eW7VxXC5/xGWToMgrKKoaCnIalI9CIARasQAqloMI/x4BWrLLYwE1AEPTwCGHaGjz7pw/leZUNV8wNm9BLy6CxsvxZ1kMbaY4TKIIXlNBsynoVjvAC4CuAoYOVi+CMfLYCUfg95tPHuzZB0YtKzsb58RMucWE/fZmhCbdOP9rNnLnxko6GVoB8lFwyVVw8b/AyeulHoJyN4Rb19dTFyeqBlu6njvfsWcvOJvLs7DMmw/7bvpeE4pU2OIcgcqmp4fGAgt2Txwvqr7lTp5V7LquZxXC6+BqEvGcY5pyjaM1tffJbk89NE3FP5VQ6y7a+paZAAAAAElFTkSuQmCC', + 'Arch': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABCFBMVEUAAAAA//8rqtVAqtUQj88tpdIYks46otwVldUbktEaldMjldM2qNcXk9IWktQZkdIYlc8mnNUXlNEZktEZlNIYktIWlNMXktE7o9klmdMXktFHqdkXk9EWk9EYk9IlmtQXlNEXktAWk9AWlNEYlNFDptkZldMYk9E4otg/p9kXktEXk9AXlNA4otclmdQXk9IYktEXlNEwn9YXk9IXk9FFp9o3otgXk9FPrdwXk9E2otdCptkXk9E/ptkcldIXk9Edl9IXk9EjmdUXk9EXk9EXk9EbldIcldIjmdMmmtQsndUvntYyn9YyoNYzoNc0odc1odc2odc6pNg7pNg9pdlDp9pJqttOrdzlYlFbAAAARXRSTlMAAQYMEBEVFhgcHR0mLS8zNTY3PT4/RU1kdXp6e3+Cg4WIiYqMjZGXl5mbnqSnrbS3zMzV3OPk7Ozv8fT29vf4+fz8/f7SyXIjAAAAmUlEQVR4XlXI1WLCUBQF0YM3SHB3a1B3l7Bx1///E6ANkDtva0jKbCW2XIH1z2hiZEZ4uUgxo7JedTQye/KN/Sb5tbJ+7V9OXd1n+O+38257TL+tah3mADAwSMM7wzQWF4Hff6ubQIZIAIb6vxEF4CZyATXhZa4HwEnEA+2QgoiyQDnIEWkjVSBBZBqXbCRlKYo8+Rwkyx54AOYfFe7HhFa7AAAAAElFTkSuQmCC', + 'CentOS': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAB5lBMVEUAAADy8tng4Ovs9tnk5O3c7bX44LLduNO1tdDh7r/eutj43q2kocX23az07N+qqsvUqcmXl7331ZXJj7r40o/Pn8T42qP63KjNw9n21p3Y387Ml7732JzR55z05MSxtMLGn8TC4Hx8eqt8e62Af6/B4HnG4oPC4HzH44fBf7LCgbOkoMTcsrmtn8PWqcfFtKrj4Jvs2ZOz2FnMqLXT3KfY5p60Z6NUU5XRuqHzwWSywqDn3JaiiLWahrWhkry5zJjRmqm1Z6P1wmb1y319fK632mK5cKi5nH+73Gu73Gy73W283W+9eK17e6y1yZS3aqRZWJdcW5ldXJplXZppaKBwb6VwcKV5eKswL306OYNPTpGkfK+m0kGpUJWq1EnEqIuXK3+Xh7ahP4qhkryMfK6BgK+CdpGMaKKMa6O9ea2+eq6+oYW/eq+NbqWVlL2Wlr7AjanA4HnA4HrBkqbBlafB33rCgbLCmKjCxIzC1mSs1UytV5mtxIWt1lCuz2evWpuvXJywxYzHjrvH4oXIjrrN2HXO5pTO5pXUlYnUlYvVl5Hb0G7e0XTg03rhr5fpzHPpzXTp0Hvtz3/wrDHytknyt0zyuE3yuVHzvVr0wGP1x3T1yHf1yXe0ZaL2zYP30o730pD31ZeRIcF5AAAAQ3RSTlMAFBkbHEhJS0xMTk5UWWBsd4SEiIiPkJCVlZaam6CjpK29wMPDxMTFxcnK193e3+Dg4uTn5+fo6e/v8/P4+fn7/P7+J4XBAAAAAOBJREFUeF5Vj1OvAwEYBb/yGlu717atLW0b17Zt2/6nze42TTpvMw8nOZCAmwUpiIY6c5IiLi9tPX64GairqszHQ4X2VB64v1Cs6PxMPJSdHM777s6/jyaMRGiRLyyrb88OpjZ3CzAXrm1sqzSNNeN7kVBPNgB7cG51abE5l9cXDces7emQ1uadHhutFUg6gpPKkSIqQGavwz7r7O/+/3t/rSdjI9XDM3qz4fr3B/3iA0aJTG9x71+9oR/PLDwUe2wm19bly+fTIxHyEETatbPewGEw6Mk/tKZCEqSQQUlIHB/QNBEjjVN1AAAAAElFTkSuQmCC', + 'Debian': 'iVBORw0KGgoAAAANSUhEUgAAAA0AAAAQCAYAAADNo/U5AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAZ5JREFUOE+Nkk0oBHEYxv8fu5GQj3JwcaDkIAc5IpR87M7MKnIVJVKclaIQ5Sy5OLkgR7n5OigcSNpmd2c2Vyfl4KT8/muWiVU79TTv+7zv837NCBF6PG1X+NpZyEYSD9mIc+tHnBPe23B9xKrCuTmbQA/JKfABrhBswa1hH4A38IwfOxPdX1qcjiCQxO5NyrjKV70TnSbeRPwJvGN3i4yyqnEucPY8ZZX9GSEgGK+RvFfyjk2VKZxzBNG8wJWWgh/xtDOeUXZ7Slr6TrSLYL9N4SMgYTTcwdc2ArvJcElhSVcM6mCNSV8n9hA59yTU5UWMG6HIbLhIWlglgWiC2L4Z79qTdo40D6ISuOWwKCWHyk9Fv8ldpUHOuGTuynwSBUynddPdlbEosVpP9Eu4FnOsRzUYNTsdmZN/d5LDiqM0w+2CMdAFFsFGWgfXxZnheqe/z+0puwEM0HHYV3Z9Sgz8TEz7GkQvpuJ/36ggj2AaHLrSlkULWV5x+h2E8xkZL16YVjGNaAUscfZ/f6c/k9ywLKI2MMcRWl0RLy007idmRbQJ7RIfDAAAAABJRU5ErkJggg==', + 'Fedora': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABPlBMVEUAAAApQXIpQXIpQXIqQ3UpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIqQ3QpQXIpQXIqRHYpQXIpQXIqQ3QqRHYpQXI8brT///8uTYMpQnM5Zqg5ZqnS1+I4ZaY4ZactSn8uRnYrQ3MrRXgsRHUsR3s8bbM8brMtSX4wUosxVI01XZw2X50vUIguToQvR3c6X5o6aKs6aq08Un8qQnM9VIFDWINJXohKcKlXapEqQ3UvUIc2X55bhcBdcJVgcpdhfapmd5tuk8dxgqJ1hKR5jbB6iah/m8Shudq3v9C4wNG/x9bFy9nFzNnFzNrIz9zK0NzK0t/O2+3P1eA2YaDU2eTb3+jb4Oje4urj6fHm6e/s7/Tz9fj3+fz7/P38/f3+/v83YaEa/NNxAAAAHnRSTlMABAoVGyY1SVlpeIuQsLfDzdHW4+3y8/b39/n6+vr4+ns8AAAAyklEQVR4XiWN5XrDMAxF75KOknYdZJS0klNmHjMzMzO9/wvMcH7I37mSJShsJ+5NjMT6umDoHyXDcI/2qJadh++P3cle1de+9yPe3/bTY92wzfzr7wGtP3JrAI72BZGVtcAdQlwHy+JS1pDbBE9qamZF3BYrjQxPEXwKc6dC8bXFm0QIpmt8kn0Rn093q82UCtK8oXZckwFJzuulV8bHkajPyXdbnJnARfDHs0trz+JQ+5AFvzp/L0+cL2qPAINUPrq5OC6p/64F/AMnrST+Dq/r7QAAAABJRU5ErkJggg==', + 'FreeBSD': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAABIAAAASABGyWs+AAAABmJLR0QA/wD/AP+gvaeTAAADXklEQVQYGQXBS2wUZQDA8f83j33M9rF9d7u4loaWklaDpkSo9KDGaIKUaGxshD2YSPRiuDVeTDyhBxosJCoa40ktpAkPDcUqAYVIpUSUPrAulEdD2bbb7e7ObGcfM/P5+4kwKDvq6yJ1FYYcvb+YAkqAHo/HQ7FYrFIoCiurq9ZXJ06YSOkA+kBzfX06bys3zHxS9EL0tXDVyZfefacqV+X/ZSJx5+qLbx98LhaL9RiGEZWlEsWC/Thd9q6Pf3vs2u6Orc83rFsvTwwfLf5obgywT1Vjh2Hh+rbNsnTssJdNLedK5aIrpSuldKVXKsnH4+Pyn6FDXn5tMef9O+3NvdkvP1V4+EYw2AoQ+KSx8dRYS6NXXnwovaItXduSrrkinWxGOmZWJi9OyOK9m1LmsjIz9IH8QUMOd3WfAQwNKCy2tJwbHB5+XasPaxIHmc4g7WWEZ1MquBiRFlJTf1E7+Tl/H/8asavPzTY1nWd2ZkMDRPeBeHPz5ojwsilEQCBvTSKunCF3M8FSNkBGVTHDYYrLj8jVNhDZ2SMa2zo3MTamaIC/u6Ojr3DtrOrvP0BpdATnyBeIhTxpR5ABUlKSUlXS1dWstbVxdz6hPL0l1quGqkLaKwNvVcjEXNRd/4mit4Z19DjefBEPyCKxgQJQcF28dBrHNDGTSZSezsjeff0hraa2Vs2vrvit81O4vj9xLJcC4ADrQA7YAGqBGsAql/EtLdFQE/L7dF1XZmdnSrbPMJfXoLDmolQK8gJyQBowgQhQDRQBD+hsraVhd4e5MH+/oExfvWLJ9q3/3S7qMpNH2hsS40kFS4EUUAMA2IANRIBXv4uzuO67c2PykqkA5YmZ6bN18YPi0Yoknxc4AsJPCMLVAk2BLKDosCWqs/PZaulkuxk9fekcUBAAQGDks5FT0W++3NuYuC0DVUL4DIEdlIQDAj0IRkigaMjArkFx0tf523sffrQHyKsAgHPhwoXLL+yP9/kePNhk5ExUTyKFkJVAUAiCFZrQup4Rv9ftuLV/6ONBYBVABQAArMvJ5MXW7duD6P62sD8UrPAFRU1TpeCpCnGvPZr7WW///v0jpw+VC9ZdAAABAAAAAMLo7drWrmQyPWG/r8tnaGIjaM05ujr16x/ZBFh5AACA/wGZnIuw4Z4A3AAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxMi0wNy0wNFQxMDowOTo0OS0wNDowMOPVpFwAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTItMDctMDRUMTA6MDk6NDktMDQ6MDCSiBzgAAAAAElFTkSuQmCC', + 'Gentoo': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAB9VBMVEUAAAD///+AgICqqv+AgIC/v9+Ojqqii9GAgKptYZKQkOmPj/ddUYBgW4eVjeCTgfiWjO5wbJaZkvPBvepkXomYkNldV4Bzbpl6dJ+Uj7ynoO6Vi+1qZI63se2mnudjXYjOy+GCfaqZjvWlm/Pc2e+Oh7NeWIOWjfeXjeW1sd+gl+diXIfp5/KHgKnn5/F2cZx6c6ZgWoXc2e6dltrAvNu0scrX1eTOyujCvup4c5qpovVpY43///+6uPPJyPXq6fvm5vrz8/z8/P7+/v/d3PixqvmxrPSyrfe0sPO0sfS3tMve2/3r6vy6ufPz8/3d3fi3tM63tPO4tsu5tsu5tvO6tfe6t/Vva5KRjKy7tvW7t/W9vPO/vM+/vvPCwfPEw/TFwvTFxOfGxfTGxvTHxvTIx/TJx/aTiOrNzPXNzfXQzfnRzuHS0fbS0vbT0uHU0e/U0uTU0/bW0+zW1ffX1vfY1/jZ2Pjb2/jc2uSTiemVkLSlnvbe3PTe3vng3fzg3f3g4Pnh4Pnh4fri4enj4/nk5Prl5Prm4/ymn/bn5vro5/rp6O/p6funoPWsqs3t7Pvt7fXv7vzv7v3w7/nx7/3y8f3y8v3z8vytqPWuqPX09P319P319P719f339v739/34+P35+f37+/+uqev9/f6vqvSwrPQAR0dcAAAAPHRSTlMAAQIDBAgJCwwVFyAsNUFHSVBneH+Bh4mVmZmanKCxsrK2tr3ExtDW19rb4ODl5u3t7u/w8/T6+/z9/f4MkNJ1AAAA8ElEQVR4XjXNw5aDURSE0YrRtm3b54+dtm3btm3bz9k3Wek9+2pSYFwT8ibzE93hwAtdJqK3nZo4J9hFXbP+vFHOthV6gnGzstZq94wdCs4UCCDymQ2v7X0LdYoSQ0MIENRYzJbRlPTTHu73ZNAL8vivmVui98PpzuqffX0mIPHJGtOQenukteJ+aS3b9htNpDnT9TeZH1bHAwBRMhGpd6e6uNrLoRgxBKmsX47nBlp678ojpEA40fejcmW4e/No0V8IIPfj6eKgbEJ3ZUnzgE1OqWp9Q3VeWRAsg51f1dZ8c31RmAsc+N5JGbG+zvj3BzDCPrzMDC9SAAAAAElFTkSuQmCC', + 'Mint': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAACVVBMVEUAAADh4eEAAAAAAAAAAAAAAAAAAAAsLCyXl5dgYGCnp6eTk5N3d3fBwcGqqqq8vLzNzc3Ozs7Ozs7Pz8/Pz9DQ0NHR0dLS0tLS0tPT09Pf3t/Pz8/i4eLb29vZ2drZ2tna2dra2trf3t/u7O/u7e/u7O/r6+vt7O/w7/Lw8PDy8fTz8fXz8fbx8fHz8/P19fb49/j49/n6+vuPxlmWyGOx437h9NDr9eD6/fj////+/v75/vTA5Jv6/fb7/fnL5bDL5q+AxjeDxUCEzTyGxUaGzjyHxkiHzz6J0D+Kxk6K0kCLyE2M00WNy06P00mSz1OUyF+W2FGX1FiY0F6Z02CZ21ac0Wiez2yfz2+f2mOh4GCi4GOi4WKi4mOk12+k3Wul32um1Hin0nun4G6n5Gin5Wmo23Op2Huq1n+q43Cr526s4Hit23+v6XSw34Cw34Gw6nWx4IKy4IOy44Cy63ez146z34az4IWz4YW03Y217nu38H2625e645G74pK83pu98Iq984W+4ZjA4px0tzDA5ZrB8ZDC5p7D55/E947F6KHF+JHH4qvH6qTI46/K5LLL5LN1tzLL5bN1uTDL57DM5bPM6qzM66/N5rTP6LbP6bTR6rfS573T67vT7LrV7r3X68XX7MHX773Y77/Y9rvZ8cHa7cjd88bi88/j8tTk8djk9tHm8trn89vo89zo9N3p9N3p9d7p9tvq9d/s+93s/dzy+erz+O73+vT4/PX5/fT5/fX5/vN1uzB3vTD6/ff6/fh5uTj8/fv9/vr9/vx8wjV/xDmrMRH0AAAAOXRSTlMAAAECAwQJDzk/RUlNU3F0kpSVlpeYmpucnaKjpKWqqqqtu8LExMTEzdTU1NXY4evy8vP+/v7+/v6LaR1mAAABD0lEQVR4XiXI03bEABAA0KltW9kaW3eSZW3btm3btm3b/q4mp/fxgqKOtpamhrqaqoqykrQYABh+PVMU9fjE5Xp8o54kgPHN0EBHU2N5YXZykiua0HHd2759VF2Sk5IYE5GGsmCEWLV1kVWwt5O+3x/qpgsy8k4ja+cJl2/v5C22tlgCAHtw9TQSa4s+AzfPSm0BRNl9SydhWJzLC567KrNhgrNwHIJ5qTz/2f9w7Jw/DNqIjVr04exW0AEOXcN3Ab7enr9eDW2VTJgehONyc2Z8XP5YdD0Tcuhcc4/r45OjGX51TEjYPbh8THRPvbz+CHusgSZlT7rP8PkCwfQKaQUi9Igr6JsRBMFiWZgb/AHKElRzKopZJQAAAABJRU5ErkJggg==', + 'Osx': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABrVBMVEUAAAD///////+qqqr///+ZmZn///+qqqqAgID///////+tra339/eAgICoqKjx8fGMjIzm5ubh4eGPj4/g4ODIyMiAgICSkpKLi4vS1tbPz8+Xl5eMjIypqanIyMjW1tZ2dnbR0dGamprFxcV3d3d+fn60tbV3d3dcXFx3d3epqal7fHxxcXF+foCnp6hYWFhyc3Ojo6SMjI5fX196enp+fn6Li4xERERqamqgoKFpaWmFhoeen6A/Pz9QUFCWlpeSk5SUlZWUlZaOjo+Tk5RHR0cuLi5YWFgwMDAeHh40NDQ3Nzc6OjpcXF1rbG0XFxdSU1NVVVVXV1dZWVlbW1tnZ2lwcHABAQEEBAQXFxchISI+P0BISUpaW1xHR0kNDg4qKyszNDU1NTY9Pj8NDQ1cXF4XFxhSU1QSEhIDAwMrKywtLS4uLi4wMDFHSElISEggISE0NDVJSktNTU1FRUVWVlhGRkYEBAVBQUE0NTZQUVJQUVMFBQUqKitWV1lXV1daWlpaWlw+Pj8bGxtcXV9dXV1fX19fYGFgYGBkZGRlZmhpaWlsbGxwcHB2dna844Y9AAAAV3RSTlMAAQIDAwUFBggMDhkeICMkKCgqMDIzPj9ERFBib4CCg4iMjZCcnp+jqamrw83W1tvb3ePl6Ojp6+vs7u7v8PHy9PT09PT3+vr7/f39/f39/v7+/v7+/v50ou7NAAAA30lEQVR4XkXIY3vDYABG4SepMdq2bRSz/capzdm2fvOuDO397Rw0Ly4tz2QAQPbcxuZ2E/STJwfxPhWgG355fRrVAIVb1zeP9UDLfiSwkAcADe8fn7tFxWuEXFRDoer/OgoMTRBCumj8yJwPBo8Zhpk14U856/HI8n0ZUtpZ1udrSzfVneA4roNKjdrwpcMRilb8d8G60+lKnrpWcn9bO+B23w2O8Tzfq4aiNSZJqzn5O4Kw16h06fPZ+VUlUHfo97+VAEb7rSh2UgDd4/U+TBlQY7FMj5gBIGvcarVVfQPVPTG94D0j9QAAAABJRU5ErkJggg==', + 'Rhel': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABj1BMVEUAAAD///////8AAAD///////8AAAD///8AAAD///////8AAAD///8AAAD+/v4AAAAAAAAAAAArKysAAAD///////8AAAAAAAAAAAAAAAD///8AAAAAAAAAAAD///8AAAD///8AAAAAAAAAAAAAAAB5eXn+/v5JSUnKysrS0tJ5eXmqqqqxsrL+/v4ZCgknJyeHh4eIiIjo6OgZCAdOTk7t7e3///8GCwwPAAArKyv19fX29vb9/f0EAAD////+/v4AAAAGBgYHAAAJAAAMAAANAQAPAQAVAQFyCQV9fX2pIRzmEQjn5+cBAAAFAAAAAADnEQjvEgn////uEQjyEgnsEQjzEgnxEgljBwPaEAj9EwnwEglHBQJHBQNNBQIBAAB3CQR5CQSHCgWLCgWRCgWTCwadDAWmDAapDAa/DgfKDwjWEAgGAADh4eHiEQjmEQjmEQkKAADoEQgLAQDtEQgMAQDuEQnvEQjvEQkPAQAfAgEuAwEvAwE8BAL1Egn3Egn4Egn6Egk+BAL+/v5CBQJrB0muAAAAT3RSTlMAAAMEBAkYGhsbMTRLUmpvcHeIjLe6vcHCxM3P0NbW3Ojp6u/w9ff5+fn6+vr6+/v7+/v8/Pz9/f39/f39/f7+/v7+/v7+/v7+/v7+/v7+Q8UoNAAAAO5JREFUeF4tiwVPA0EYRL9SXIsWl+LuxfcOd2Z3764quLu788NZNrxkksmbDP2R7vH6GioLs+iffEzNXd4+TqPErUUpVqMOvwgdzMPn1rv5vPsVeufBTaBK/bH2FPvkEUuIG5jIIc+sHYn/HJ3dC/Hxuo4y8s44dzwBbFkisHN8bVIdXs6jb+H97aCwbHEIqgcml64CD7YllNkAVQC940MLYe5YzvIeQAXNrd19Roc5MdzfdQLUUKaUYyuG9I8y1g4gj6hIak4X5cBIT2MquZJrJdOqpY11ZpAiqVwbY/C7KY1cRCrZxX4pWXVuiuq/hs49kg4OyP4AAAAASUVORK5CYII=', + 'Sabayon': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABvFBMVEUAAAAcUaYdVKwAAAAAAAUABAwWRY4YSZYhZtIhaNYHDx0KCgoFDBcKCgoRMmYSNm0fXL0fXb8AAAAYS5gaTp8fXLwgXsEGBgYFBQUZSpgZTZ4JFSgODg4IEiIOJkwOKVIkW7EnXbQLGzUTExMKGC8LHjwMIkITExMiIiIPEBEPJ00QEhMXOXAaPncOJEgoXbApXbEcHBwwMDAEAgAfHRgQDgo3NC8AAAAHBwcKCgoLCwsJCQkaGhofHx8lJSUwMDA0NDQ4ODiRkZEICQocHBweHh4GBgYHCg8mJiYnJycpKSkrKystLS0uLi4ICAgODg43NzcRERF1dXUUFBSjo6O1tbUbGxsEBAMLGS8MDA0iIiIjIyMkJCQNDQ0NHTYKCQkoKCgPDw8QEBArMDkKCgkRERIREhMxMTEyMjISIz00Njk1NTU2NjYCAgIVFRU5OTo5P0c8PD0+Pj4/QURAQEBHR0dKSkpMTExSUlJiYmJlZWVnZ2cWFhZ2dnZ4eHh8fHx9fX2FhYUXFxeVlZWXl5eYmJiZmZmcnJwZGRmlpaWrq6usrKyvr68KFiq/v7/FxcXY2Nji4uLn5+ft7e0yif9uAAAAN3RSTlMAAAApKSkqKioqg4OEhISEhoa1tra3t7y9vr7S09PT09TU+Pj5+fn5+/v7+/v7+/v7/v7+/v7+70RY/wAAAPpJREFUeF4dyWNjw2AUBeC7dfYyorM6rx1exKltzLZt2/rDa/J8OgBVVlFDX39jcTZoUqCse251a2dvu6ccUtWlanLQ4Vpel+ThlWq1l3wEz58tx4dOt1dMlAJk9A5gMjG75LHwo46hzkwosGOMbejumoRvubC9EOrMviT0E0Us9fvN9dA6zxJCNv6+ECGsb6oNWsgmpZT9/UTUZo3Em6AW34guTL4jiAudiCM1kLcw8/SmHERfT1/eueBiDqR1GK1n9w+K8nglxYxd6QAML4ztXoQuj8YFgWcgqdJp8qzty26vaboCNIxBCshyQDKov0aXr29v1ufq1PwPx5Q7bCoh6eoAAAAASUVORK5CYII=', + 'Slackware': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3AcEDi0qZWWDgAAAAx1JREFUOMt9kktoXHUchb/ffc1M7rySSdJMOknFPMRitLgoNKKI8ZHGKkgrjU8SitidimSh2UkXoQmoO1dGQSxJjdvOtqSaqlR0USEGSjVJGxuSmWR6M3fu4/93YX0g4rc9HA6cc4Q7DI+fpzz7PA8++2mxvZAeBZ4xhHtFcJRmXWsWvb36/OLcyxf5B/KHeYHy7DmGx1+YSDjmWTdlobTGMAStQGkNoLXS4tXDq7u7tUcWz49tA8jR8QUuzB5n5NTCV13F9JEo1JJwTLKuzU61QiOMcd0UDb+BncwQK3Rl15eNja3ui/Njq8aF2eMcO/XlBz0H8oO2ZUkum6A13WB99TtyzXlaCi24SaFa+ZFCzsG2DNnfkdbFjsI1APPhk+d6ujqznycdCxFozadYWvyMpx47wa+bPkGksKwUNnsk3TaCGASRXDZh5LpHXPPg4Rcni+3uYBxrtBbQghlscOVKmYHeEm0ZIZ9xyLffw41ND6VAa43SmjiMByzHYtjzwr9arfshxf5jOKlvKZfn8es77N2uks24PPfSFD/9Uvt7AtPKWmEU9d645eHYJo5tcKi/FX/zG+zmQxQH+rANk862DOW5N/hhaY64cJSa5xNFCgDDILZACMKYWAmh73HmzFsMlBQJ06LeiMinE1S3KzRCm5rXIIoUIoKIYCVM36urZFbEoiBLNMIhAE6/NsSB7h6SKZdL8xsUOnpx9j1KbTdARACIowArYe1ergfNT2i0mIbJys0GI6PT3N1/hJvrPxOFdRJNBQIy/FapI4Bpgohgcjuw+jq8jy8tV55MNBWI4ohS802CpizKv8q+FgALZAfYgSyAZtNro1oLaU1VvxCA029Oraxs7u/tKnXiNjn8HyKwur6lI++6vPK4V7IA7u+1Dyu1tr183ddNbkHuXP8/zEIYeFqiLRl6YO/p0bHJdflT/PD9qZa1W+ry99fcvlAlcZwUpuUAglIRYVgnDEIOlna4q0M/NPnuO1/PzMwg/045O/XeibUt5/Xangx6viSVFpK2jtMpvdyWCz+5ryf10clX3/amp6eZmJjgd441URWWJY8BAAAAAElFTkSuQmCC', + 'Trisquel': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABjFBMVEX///8AAAAAAAAAAAAAADMAAGYAAAAAHFUAGWYAF10AImYAIGAAHloAHGMAKGsAGmYAJmYAJGEAKnUAJ1gAMXYAJnEAJGQAI2EAK28AK3cAGTEAMHgALXEALXgALG0AFUAAI2oAK3EAMngANoYALXMANIAAM4IANIIAL3gANIcANokANoQANYQAOY0ANIYANooAN4kAN40AOY0APZMANIUAOY0AO5AAPZUAPJAAP5MAPpQAQJUAOYsAPpYANoUAPpoAPpUAM4AAQJkAPZIAPJEAQpgAN4cAPpQAPZUAPJEAO4oAOosAOo8AQJoAOYsAO44AQpsAO48AQp0AP5UAQpoARJwAQ58ARaAAQZgAQ54AQ50AQpgARaIARqMARaMARaIAR6QARaIARaEASakARKEAR6MASqsARKEASKcAR6MARqYAR6UATbEATa8ARqUARKAAR6oARqMASKgATK8AR6QATbIATbAASq0AR6cASKgASqwAR6UASKcATa8ASqoASqwAS6wASKoAS60ATbHn4CTpAAAAhHRSTlMAAQIFBQUGCQoLDxAREhMUFBUYGhobHB0eHh8gIiIjJCQkJCYoLC0xMTE0NDo6Oz1BQUNHSUxOVFVVVldaWl5iY2RkZWZoamtsb3FycnR1ent9f4KDhIiJioyNkJGYm5+foqOkpqamqKmqrKytsLKzs7e4uLy8v8TFxcXGx8rO0NXY2eZc4XYcAAAA00lEQVR4XkWN1VoCUQAG/3NWtwh7CTsQJOyk7BaDxuxA6bbrxf32gt25m7kZqDRYxziooDV7+1AalMUavQh2AsEZoWvzigLun+T17/c8QiJZ7qu2QKiNmyZthdcR1/as353jIeU1GxMHo5XHdqPFeX8IaDMdHPYN6dRN7LR4qQewdTa35HWkyh+fbxERAMjwlAWJv3CPSKDQ+H7XvHdkV4Pua3Gtm4sPKIF/WV8dop4VKBw/NU33B3x1JbTt+XwhkJQoqRfWvHOy28uqH8JIdomR/R+s9yR3Cso77AAAAABJRU5ErkJggg==', + 'Ubuntu': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABKVBMVEX////ojFzplGf1zbnqnHLvs5P10b3yuZv1xKrytZXvtJXys5LysI32waT0n3HxiVHwg0jxhk31kFn0h0zxf0P0hUrveTv2iU3yfkD1hEfyejv5eDLybSX0aR7zZxvyayH6ZxnxZBj4YhH7XAb5WALlUQLeTwHgUAHeTgHfTwD65NzdTQDdTQHdTgD31MfcTgLcTADcTQD////xt5/31Mf54dfmfE/dUAbeVQ/jcUDcTgHeWBnnflHohFvpjGbqkGztnX342Mz53dLgXiP65d399PHdUgrtoYLyu6Xzvaf76eLfXB/rkm/fWhvupojwrpTeVhTgYSfgYynzwa30xbL1ybnngFT31snngljhZS3539XhZzDiajbibDn77OX88Ovrl3X99vTjbz1fisGCAAAAMHRSTlMABgYGBwcHJiorMDA1NXGHjY2Nl5mZmZyfn6O5u8XHzc3X193j9fj4+vr6/f39/f08OUojAAAAx0lEQVR4Xi3HZVbDYBhGwQctWqzFPXiQ+36pu+LubvtfBKcN82/UEhld2vWXxyL6F92gbTPabse8hU/uHMx1SZoyyJWPTwq1Rs7GpYE9+Cg+OJcs1MHvU9y4fnrN31yUm18vMCIPjtw3QMndw4rs8ieVzAAcBlewpe1KM3uaBuD3Dda1BhWXAsi6AFY1a2SqifxZ+rnxWYcJDRkUS3fO1R5vwe+XZgw4D4L3RAJiknoXCVX3WeiUpJ5pIxTvVmg45pl5k4Ot/AGV2iqZBWgJJAAAAABJRU5ErkJggg==', + 'Windows': 'iVBORw0KGgoAAAANSUhEUgAAABIAAAAQCAYAAAAbBi9cAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAA+pJREFUOE+F0n84FHYcB3CWSsL9ojo/6ik64c6PnTjmSS0limmrpBm2G002y++xzXRz6zE0R4nbw+RnTj/WD4sbanLkkAe55ccYlyNme4SrO9u9d13PI3/saZ+/vs/3831ez+f9eb5aWsuqy2mjRYeNUa7YmtjfTico7jNJ8z0eG24NB9vvnDrvufzpq89Npnr8VjMddNmuRh9rDfp36mFg91oM7qPIc5JdbDJq3An/JfCu7Hl53W2lpS220pP2OuniN299jAYbYizSENIoAgbCTdrTKtxOJVdvGo8psUwKy7Vxe4ez1YEVudGP8YEZzyveInFJ6mZRHHqYazDspw/pJwTIuERM5JIwmUdGdyo9K7/BszGzzg6fXzZHGJ8KvzQqXKOpoIeZLjofWR++BPWyCEnPY4xFGEKWQcLjMjKmr1MwfcMYwmz/Y4KOgNki0V5k1dkjUWCK93Kp2PMFFawos8cm1gZ2GqjLXktL4mbQPHLQ4B9ZDFE5+S356fQlyuJMqzH++HnTo6ui2OO1ko9Ul+4fxfd3d4F7k4YTReqpuFS88bGZUE2QNNDobuIq8Q5CduHb7lFJaTnvnym9ergjMWD/FG8zf+aKS3G9JO5C01Asah6wUXrvALKEDoitMMHhDKrKJdg8RU2s0EB2EWWur8dd7PDPFv6dUC0Gv3kAN36VPRGP/5k5NS6lljWxG0TDiSr1VKhoPwhevRMSqkwRxDObc/DavGtpP6zoi8XOyZfhnyNEvKANBU0P8VPfI/wyNCGXSn7wlEmyA9KrgmOKGth3eDVvPfyywq2dnUEv2R9qG2rLsH7xJXziKnWcI8tlTvEC7Mu8hROlImTU9aKqcwQ1vWOihWFu+sJknmph5CvxQh87c7bNh/NXo03hrMCosyvLmMNgMF7TQL6J1dsZIUVwjKqEO+cajp5vxPN439U/gKBt8PTcYHzL/BgHCyOf4unAISj6mFC2bYC82kB5Ls460NHRUVsDeYSXpGw7UgC7sAtwShDgzdM38W7BbURXtqpqhfmB8sEQuXwoCM/6faGQuGCxyxyKWhIm+PrSD495WL3cT0hhi8Whc3NbAs9KaOyCTvrJ8qkdX19XBeTUDU00+55USFzVU2yHstcaix0mUAjJkJeuRU868Ucmk0lcguiBnMAVxjbbdHV1yeq8+u4Hgo22huSG+iQXp83ftaxW3lsPZcs6KG5T8OwaAfJiPcxlrVRVRhvF02i0F/t5VbHZ7JWDfErKTLnhE3mFPuRFepg/uxqz6TqLv6euGj3ut87t/4ylvre3t3ZehOWWO1zjSFEqMVP4GfGb/DBykJcjmaZOoLsc+hcVY/LaAgcTQAAAAABJRU5ErkJggg==', + 'OpenBSD': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3AoYAykIPu64pQAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAADTklEQVQ4y32RXUxTdxjGn3N6eujoKT3SUkuk3VoBGfVjgFXAsZ7WkipyYXQbuu3CzUXZmGRbssnFEseFkWzgcGzGXky9MWL8TsC4IeFgtK4oAqOnG5vMVl1pCMVWQD7b/y5M6jLdflfvxfPked/nBQA0NDSChqnGVrLuGkES742NhJAdhAKAuk9yyUs5Gry7RQMZAARCWgivpQiPe71P5DUfH0xaqTL7m/iiLkJmphawa+e4SM2PvUyC4yUIBu8CnAQKAK53rCA5OUtQtStVpJ4Gw/FOBddZVKhCfq4MP4n6+at+DUsJm/e0G9JZzYEvI2tHwlEYjDxomkZ+3nG8WroRtHihZVOhVlorDQzh0okhcByDP4ZGcf+X9XAsvY5/RsBa7Kq5H/CqLctKyl/g08S2i6fq8W/MS3P34T9wNDVYSeDX1eTD9xhiLXbtB/Akwmmv6Kr+ICFkLpGhtNSM3qsSstS3oX8lSsmsxS6ZVn3j6PvVVqhUcvC8AtPxVPxwygVKvngN89WOjgVprggGA4eenjB4nsXsTASpC63I0wVTZYPR11FoKRB8Ax54PCFk6BhMTk5CPR3GSbHouGzknr/bYFq9EAvfc9Tu1sLjHcXNKxLuTOTgzOlOe7IHBc/beAXWpWmXlz8a84nhcLQ+ecVzsAEQrMWuMX+f9HZF2YPZ28FVSNfoPWqOzMUmqYMAJm7+/OOzXQFwHGpyEV+vi+yvtxBC9pDmpgJC4tvI3mo9GTitIxvW24nT7ug67HY/3eDs2bbyrVsrY2day70rV6kRfDAHk5lDLJqAmmeRiD9GJDKHvwb74R8G0mkTPjrQTTG122xkTTbwaV2b1H4u16JQKXGr7yG2b8/H1MQ09IsTSEmRwzf4CCwzD+dmE1re8CI7wwi5XNlFf9vaTXX4dWJg4LLl7h05fpNGwNAMWpp9CIVYNO/tRCzGwpDFQaVMQTS2CKY0BWr3GVGWNSXKACDDaA4Mh976pq9f5Sy09GgKlmeAMIBKzUKpU+BFoxJecRhUfAbMxDi4eADfHVmE79v7q575gvvYeVvjZ58LD5mwsKUyX0hnf0feslnQCWD4zxnc6reKisxsfH2oscqcmTmK/+Ow252cna7K52r+Bky6PqmoT5HBAAAAAElFTkSuQmCC', + 'Gnu': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAFo9M/3AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3AoYAywUV5gQrwAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAADcElEQVQ4y43Tb0jjBRzH8c9v+7nNMebcUW21Cc78g/wcuhByIScoMRwoTBmFlZCmIJ14axqkgoYIkXIqKIVBEuJNUBEUPRlpqDC3Q2Ex0nTezun2YOaPLXNIv7Vvj7zgiOj1+PPk/eADjuNEuHN6ekqMw+H4IzMz8xChUCjV1NT0JbO7uxtfXFy8NZvNr21tbd0AAEQikY6I0m1tbQbx2NjYZiqV+vn29jY+PDw8xhYWFj45PDzcb25uhlQqfSTief6X0dFRpqKigvF4PPPipaWlY7lcXhCLxXJnZmY+ZTY2NnzX19ePGxsbHw0MDLivrq5mc3Jy2pPJZLVWq/2cdbvdDSzLholoNJ1OMy6Xq0Ymk5HNZktOTU29qMgA8HYqlaKDgwNKp9M0PT09BgAM/iGuqqoimUx2yPP8U5/P9wEAMB0dHRUKheJHiUTyeGhoqAUAnE7nR0qlsjcQCLwjlsvlz+bm5mQWi0VSWlr6bXV1tU6hUMj6+/vfN5lMN0xxcfG1zWZ7SETTSqWSGhoamPHxcajV6s+8Xu9Xou7u7t9VKtW00+mkSCTC6PV6aDQa8Dw/Wl9fP8UAQCgUosvLSyovL2eWl5dRUFBw7Ha7v9vc3By5K3g1EAg8FQSBiIguLi4IgBwA2LtEjuPuJxKJ62AwKFpdXf0eQBIvYVmW/cLlchEAWK1WAADT09NzX6PR/OTz+eKVlZUzKpVqTyqVvsnzfLCkpGSrtrb2t97eXnFeXl5ZKpWyZ2RkPPP7/UUnJyefGI3GU+zt7aU4jotOTk7mAUBfX1+b1Wq9kcvlBIAcDgctLCyQxWKhoqIi6uzs/BoAVlZW3qqpqbllZmdnf1hfX//Q4/HEzWbzX+3t7fcMBgMFg0EYjUYmEolAEAREo1Hk5+fT+fk5Mzg4GD86OpJ0dXXJGQBoaWl5Ra/XP6yrq3tQVlam2N7ehslkAsuySCaTUKvVSCQS2NnZSXAcJxYEQTEyMvKeIAhLDADY7fZ7BoPhm6ysLFpbWzuan5//WKvVvsHzPEWjUSYSiSA3N5d0Oh0TjUaf+/1+S2Nj46/4FwYAr7e2tnbF4/E/iYjC4TCFw+F0LBaj/f19mpiYeID/IAagAyABYLXb7cLZ2Rml02nyer3POY6rwv8hEr34u0IkEk1mZ2cTgGMA7768/RtL5JKsGzrLIgAAAABJRU5ErkJggg==', + 'CrunchBang': 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAQCAQAAAC45EetAAAA8ElEQVR4XnWOsUpCYQBGz1TIHYu2Qix6g0DEtSeQu/UIISJtUS8gJq61F1wcdMohcBDxKUR8hsz1xA/y44/cs3znbB+RJ0Skl3pSkeFQbUs79VAPzrwPFRmN1Ja0Ug/16I93+1oi4lKte+zMXv32WuoAm43lXMrqzbFncgWw21lORf4+/PREKpAhYqZuPXZ+T/3yXbZEajV1JavUQ104sRcq0myqc5mnHurWqc/7yhExVwuPncl+C4Bu13L60ueAwcByOtLhgAIRCzU38fRGTmSxUBvSSD3Ui1NvQkXWa7Uq1dRD9R17HiqyRUSy1NP6B7e1Yu2GtlUKAAAAAElFTkSuQmCC', + 'Yuno': 'iVBORw0KGgoAAAANSUhEUgAAABgAAAAPCAYAAAD+pA/bAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAABDtJREFUOE+FlHtMm1UYxrtsi8aEgCb+oTFmZur+WNS5RaPERU10C2qGaBgb6hgwLwMmHTIKlIKlQIHSQrmU24BSSmnpBVooUmihtEC5yKWDjVu5uOkcEca4lG5E93j6EQmELX7Jky/fOed9fu973vMdGu0xT3Cgz57yXMZLDdXcy821PFWLKmuA6HqLMqtLX5POl4iYb2ukWW8IOOFe/qfe3/M4n0eOjwyZD8//bldODOk37N1yDJgl+LVdjEGLFKO9KkzZm8hbje7mIrTXZ7sMtTydrJh15H8hHW11XvN/jGS7VudcD5w34ZZzeQYb67fwYO03LN4exo1+LWzNxbA05O5QuzbHqRYn+++CHDx4YK9WLfaedfQzV5em54g5Zbi8OIml+VFMDLWQ7GXoaSmFWZsDZVGCO2u0EbkhHTrhFqi9PmelSsQ8tAtSVch60dpUeGe4kxgZxegzVkBzlQ2NKBG2+iJIMqMok9r8OLRIMqApToSqmAWTmk9B2+o2YW79oshU7ABcuvAFrVGWXkVKpBYoSaBSxIS2mINpiwbjZiUMZRloVfJQyaXDKObBpimBScpHFe8KmmXpaKhK3arGrBVuVBclHN2CiPNin1OVs1tVJYlQlyZBxA6DviQVo6ZaOKd7sTplw53BVugruBBzfsRslw7rZPxaczWutSpQV/gzJPxo1JexyfaxKBBpuiEx+tw+CpKdEvGWTprGlhcwqbIzL5/DYKMYndpK3L1hxf3ZfkrzwybUZjPhnOqmvlcmutFF1jis9QSShOrcWNSXJ1MA0ou/NZWc8Ddfe4VGO3bk0JON1dyMMlK+gmxNrZCFhZF2Kng7YNO0awt4b7wLNp2EqtAsF6ImP56SG0B6siovTYpIjg15gapCVhAfJRUyIBFEo6k8AyuTtkcC/qvG/XbDexulWJvqgYH0o0nKhVHFJ40XwFQnWM5OCX+XMg86c3KvVMSMapCmPpSTIygTxGKZZOcOXhrr3Mp4uzkFuG6B3ajE3TELDDU8qEmsmvRATxquKkxAnSTFjwKEfv3JU9JC5unG6rQ1bTkbQ4Yq/DVgxOqwBWt2K9Yne3ZCZvrgHO2k5paHzOhSiVCZSkdNTgzy40JRlPgDhDHBCxUZdCs91G8fLeK87zOl6XSOICZYXMGNhDqX9fDP/mbK2DXVi/szm03eLpejl5pzOfqwOt4JBT8OeYwQt/4R/BR0OzXiLCM5LOCji/4nXt46rpywgG+zor5RxgSdupBzJdglSY+5ZZbl3XNY6mbn7W0Lcx06zBg1WBjtcC6OmG+OmRTrFrnIUZESZeVeCpwh8TpiPsQ47/tloM97T+/6m8mg55mT3tStyL54mhlwwtszNvjzD8/6HH8i7PvvPPRioZdRWuDBZUR6pEWG7I8P9Xs1Jsj36MfvvO5J/+rTw58dP7afJPfBgeef3XGz/gskFVpJc4HwGwAAAABJRU5ErkJggg==' + } + }; + + ExpandComment = { + init: function() { + if (g.VIEW !== 'index' || !Conf['Comment Expansion']) { + return; + } + if (g.BOARD.ID === 'g') { + this.callbacks.push(Fourchan.code); + } + if (g.BOARD.ID === 'sci') { + this.callbacks.push(Fourchan.math); + } + return Post.prototype.callbacks.push({ + name: 'Comment Expansion', + cb: this.node + }); + }, + node: function() { + var a; + + if (a = $('.abbr > a:not([onclick])', this.nodes.comment)) { + return $.on(a, 'click', ExpandComment.cb); + } + }, + callbacks: [], + cb: function(e) { + var post; + + e.preventDefault(); + post = Get.postFromNode(this); + return ExpandComment.expand(post); + }, + expand: function(post) { + var a; + + if (post.nodes.longComment && !post.nodes.longComment.parentNode) { + $.replace(post.nodes.shortComment, post.nodes.longComment); + post.nodes.comment = post.nodes.longComment; + return; + } + if (!(a = $('.abbr > a', post.nodes.comment))) { + return; + } + a.textContent = "Post No." + post + " Loading..."; + return $.cache("//api.4chan.org" + a.pathname + ".json", function() { + return ExpandComment.parse(this, a, post); + }); + }, + contract: function(post) { + var a; + + if (!post.nodes.shortComment) { + return; + } + a = $('.abbr > a', post.nodes.shortComment); + a.textContent = 'here'; + $.replace(post.nodes.longComment, post.nodes.shortComment); + return post.nodes.comment = post.nodes.shortComment; + }, + parse: function(req, a, post) { + var callback, clone, comment, href, postObj, posts, quote, spoilerRange, status, _i, _j, _k, _len, _len1, _len2, _ref, _ref1; + + status = req.status; + if (![200, 304].contains(status)) { + a.textContent = "Error " + req.statusText + " (" + status + ")"; + return; + } + posts = JSON.parse(req.response).posts; + if (spoilerRange = posts[0].custom_spoiler) { + Build.spoilerRange[g.BOARD] = spoilerRange; + } + for (_i = 0, _len = posts.length; _i < _len; _i++) { + postObj = posts[_i]; + if (postObj.no === post.ID) { + break; + } + } + if (postObj.no !== post.ID) { + a.textContent = "Post No." + post + " not found."; + return; + } + comment = post.nodes.comment; + clone = comment.cloneNode(false); + clone.innerHTML = postObj.com; + _ref = $$('.quotelink', clone); + for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { + quote = _ref[_j]; + href = quote.getAttribute('href'); + if (href[0] === '/') { + continue; + } + quote.href = "/" + post.board + "/res/" + href; + } + post.nodes.shortComment = comment; + $.replace(comment, clone); + post.nodes.comment = post.nodes.longComment = clone; + post.parseComment(); + post.parseQuotes(); + _ref1 = ExpandComment.callbacks; + for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { + callback = _ref1[_k]; + callback.call(post); + } + } + }; + + ExpandThread = { + init: function() { + if (g.VIEW !== 'index' || !Conf['Thread Expansion']) { + return; + } + return Thread.prototype.callbacks.push({ + name: 'Thread Expansion', + cb: this.node + }); + }, + node: function() { + var a, span; + + if (!(span = $('.summary', this.OP.nodes.root.parentNode))) { + return; + } + a = $.el('a', { + textContent: "+ " + span.textContent, + className: 'summary', + href: 'javascript:;' + }); + $.on(a, 'click', ExpandThread.cbToggle); + return $.replace(span, a); + }, + cbToggle: function() { + var op; + + op = Get.postFromRoot(this.previousElementSibling); + return ExpandThread.toggle(op.thread); + }, + toggle: function(thread) { + var a, inlined, num, post, replies, reply, threadRoot, _i, _j, _k, _len, _len1, _len2, _ref, _ref1; + + threadRoot = thread.OP.nodes.root.parentNode; + a = $('.summary', threadRoot); + switch (thread.isExpanded) { + case false: + case void 0: + thread.isExpanded = 'loading'; + _ref = $$('.thread > .postContainer', threadRoot); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + post = _ref[_i]; + ExpandComment.expand(Get.postFromRoot(post)); + } + if (!a) { + thread.isExpanded = true; + return; + } + thread.isExpanded = 'loading'; + a.textContent = a.textContent.replace('+', '...'); + $.cache("//api.4chan.org/" + thread.board + "/res/" + thread + ".json", function() { + return ExpandThread.parse(this, thread, a); + }); + break; + case 'loading': + thread.isExpanded = false; + if (!a) { + return; + } + a.textContent = a.textContent.replace('...', '+'); + break; + case true: + thread.isExpanded = false; + if (a) { + a.textContent = a.textContent.replace('-', '+').replace('hide', 'view').replace('expanded', 'omitted'); + num = (function() { + if (thread.isSticky) { + return 1; + } else { + switch (g.BOARD.ID) { + case 'b': + case 'vg': + case 'q': + return 3; + case 't': + return 1; + default: + return 5; + } + } + })(); + replies = $$('.thread > .replyContainer', threadRoot).slice(0, -num); + for (_j = 0, _len1 = replies.length; _j < _len1; _j++) { + reply = replies[_j]; + if (Conf['Quote Inlining']) { + while (inlined = $('.inlined', reply)) { + inlined.click(); + } + } + $.rm(reply); + } + } + _ref1 = $$('.thread > .postContainer', threadRoot); + for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { + post = _ref1[_k]; + ExpandComment.contract(Get.postFromRoot(post)); + } + } + }, + parse: function(req, thread, a) { + var link, node, nodes, post, posts, replies, reply, spoilerRange, status, _i, _len; + + if (a.textContent[0] === '+') { + return; + } + status = req.status; + if (![200, 304].contains(status)) { + a.textContent = "Error " + req.statusText + " (" + status + ")"; + $.off(a, 'click', ExpandThread.cb.toggle); + return; + } + thread.isExpanded = true; + a.textContent = a.textContent.replace('...', '-').replace('view', 'hide').replace('omitted', 'expanded'); + posts = JSON.parse(req.response).posts; + if (spoilerRange = posts[0].custom_spoiler) { + Build.spoilerRange[g.BOARD] = spoilerRange; + } + replies = posts.slice(1); + posts = []; + nodes = []; + for (_i = 0, _len = replies.length; _i < _len; _i++) { + reply = replies[_i]; + if (post = thread.posts[reply.no]) { + nodes.push(post.nodes.root); + continue; + } + node = Build.postFromObject(reply, thread.board.ID); + post = new Post(node, thread, thread.board); + link = $('a[title="Highlight this post"]', node); + link.href = "res/" + thread + "#p" + post; + link.nextSibling.href = "res/" + thread + "#q" + post; + posts.push(post); + nodes.push(node); + } + Main.callbackNodes(Post, posts); + $.after(a, nodes); + return Fourchan.parseThread(thread.ID, 1, nodes.length); + } + }; + + FileInfo = { + init: function() { + if (g.VIEW === 'catalog' || !Conf['File Info Formatting']) { + return; + } + this.funk = this.createFunc(Conf['fileInfo']); + return Post.prototype.callbacks.push({ + name: 'File Info Formatting', + cb: this.node + }); + }, + node: function() { + if (!this.file || this.isClone) { + return; + } + return this.file.text.innerHTML = FileInfo.funk(FileInfo, this); + }, + createFunc: function(format) { + var code; + + code = format.replace(/%(.)/g, function(s, c) { + if (c in FileInfo.formatters) { + return "' + FileInfo.formatters." + c + ".call(post) + '"; + } else { + return s; + } + }); + return Function('FileInfo', 'post', "return '" + code + "'"); + }, + convertUnit: function(size, unit) { + var i; + + if (unit === 'B') { + return "" + (size.toFixed()) + " Bytes"; + } + i = 1 + ['KB', 'MB'].indexOf(unit); + while (i--) { + size /= 1024; + } + size = unit === 'MB' ? Math.round(size * 100) / 100 : size.toFixed(); + return "" + size + " " + unit; + }, + escape: function(name) { + return name.replace(/<|>/g, function(c) { + return c === '<' && '<' || '>'; + }); + }, + formatters: { + t: function() { + return this.file.URL.match(/\d+\..+$/)[0]; + }, + T: function() { + return "" + (FileInfo.formatters.t.call(this)) + ""; + }, + l: function() { + return "" + (FileInfo.formatters.n.call(this)) + ""; + }, + L: function() { + return "" + (FileInfo.formatters.N.call(this)) + ""; + }, + n: function() { + var fullname, shortname; + + fullname = this.file.name; + shortname = Build.shortFilename(this.file.name, this.isReply); + if (fullname === shortname) { + return FileInfo.escape(fullname); + } else { + return "" + (FileInfo.escape(shortname)) + "" + (FileInfo.escape(fullname)) + ""; + } + }, + N: function() { + return FileInfo.escape(this.file.name); + }, + p: function() { + if (this.file.isSpoiler) { + return 'Spoiler, '; + } else { + return ''; + } + }, + s: function() { + return this.file.size; + }, + B: function() { + return FileInfo.convertUnit(this.file.sizeInBytes, 'B'); + }, + K: function() { + return FileInfo.convertUnit(this.file.sizeInBytes, 'KB'); + }, + M: function() { + return FileInfo.convertUnit(this.file.sizeInBytes, 'MB'); + }, + r: function() { + if (this.file.isImage) { + return this.file.dimensions; + } else { + return 'PDF'; + } + } + } + }; + + Fourchan = { + init: function() { + var board; + + if (g.VIEW === 'catalog') { + return; + } + board = g.BOARD.ID; + if (board === 'g') { + $.globalEval("window.addEventListener('prettyprint', function(e) {\n var pre = e.detail;\n pre.innerHTML = prettyPrintOne(pre.innerHTML.replace(/\\s/g, ' '));\n}, false);"); + Post.prototype.callbacks.push({ + name: 'Parse /g/ code', + cb: this.code + }); + } + if (board === 'sci') { + $.globalEval("window.addEventListener('jsmath', function(e) {\n if (jsMath.loaded) {\n // process one post\n jsMath.ProcessBeforeShowing(e.detail);\n } else {\n // load jsMath and process whole document\n jsMath.Autoload.Script.Push('ProcessBeforeShowing', [null]);\n jsMath.Autoload.LoadJsMath();\n }\n}, false);"); + return Post.prototype.callbacks.push({ + name: 'Parse /sci/ math', + cb: this.math + }); + } + }, + code: function() { + var pre, _i, _len, _ref; + + if (this.isClone) { + return; + } + _ref = $$('.prettyprint', this.nodes.comment); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + pre = _ref[_i]; + if (!$('.pln', pre)) { + $.event('prettyprint', pre, window); + } + } + }, + math: function() { + if (this.isClone || !$('.math', this.nodes.comment)) { + return; + } + return $.event('jsmath', this.nodes.post, window); + }, + parseThread: function(threadID, offset, limit) { + return $.event('4chanParsingDone', { + threadId: threadID, + offset: offset, + limit: limit + }); + } + }; + + Keybinds = { + init: function() { + var init; + + if (g.VIEW === 'catalog' || !Conf['Keybinds']) { + return; + } + init = function() { + var node, _i, _len, _ref; + + $.off(d, '4chanXInitFinished', init); + $.on(d, 'keydown', Keybinds.keydown); + _ref = $$('[accesskey]'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + node = _ref[_i]; + node.removeAttribute('accesskey'); + } + }; + return $.on(d, '4chanXInitFinished', init); + }, + keydown: function(e) { + var form, key, notification, notifications, op, target, thread, threadRoot, _i, _len; + + if (!(key = Keybinds.keyCode(e))) { + return; + } + target = e.target; + if (['INPUT', 'TEXTAREA'].contains(target.nodeName)) { + if (!/(Esc|Alt|Ctrl|Meta)/.test(key)) { + return; + } + } + threadRoot = Nav.getThread(); + if (op = $('.op', threadRoot)) { + thread = Get.postFromNode(op).thread; + } + switch (key) { + case Conf['Toggle board list']: + if (Conf['Custom Board Navigation']) { + Header.toggleBoardList(); + } + break; + case Conf['Toggle header']: + if (!$('#menu.left')) { + Header.menuButton.click(); + } + Header.headerToggler.click(); + break; + case Conf['Open empty QR']: + Keybinds.qr(threadRoot); + break; + case Conf['Open QR']: + Keybinds.qr(threadRoot, true); + break; + case Conf['Open settings']: + Settings.open(); + break; + case Conf['Close']: + if (Settings.dialog) { + Settings.close(); + } else if ((notifications = $$('.notification')).length) { + for (_i = 0, _len = notifications.length; _i < _len; _i++) { + notification = notifications[_i]; + $('.close', notification).click(); + } + } else if (QR.nodes) { + if (Conf['Persistent QR']) { + QR.hide(); + } else { + QR.close(); + } + } + break; + case Conf['Spoiler tags']: + if (target.nodeName !== 'TEXTAREA') { + return; + } + Keybinds.tags('spoiler', target); + break; + case Conf['Code tags']: + if (target.nodeName !== 'TEXTAREA') { + return; + } + Keybinds.tags('code', target); + break; + case Conf['Eqn tags']: + if (target.nodeName !== 'TEXTAREA') { + return; + } + Keybinds.tags('eqn', target); + break; + case Conf['Math tags']: + if (target.nodeName !== 'TEXTAREA') { + return; + } + Keybinds.tags('math', target); + break; + case Conf['Toggle sage']: + if (QR.nodes) { + Keybinds.sage(); + } + break; + case Conf['Submit QR']: + if (QR.nodes && !QR.status()) { + QR.submit(); + } + break; + case Conf['Watch']: + ThreadWatcher.toggle(thread); + break; + case Conf['Update']: + ThreadUpdater.update(); + break; + case Conf['Expand image']: + Keybinds.img(threadRoot); + break; + case Conf['Expand images']: + Keybinds.img(threadRoot, true); + break; + case Conf['fappeTyme']: + if (!$('#menu.left')) { + Header.menuButton.click(); + } + FappeTyme.input.click(); + break; + case Conf['Front page']: + window.location = "/" + g.BOARD + "/0#delform"; + break; + case Conf['Open front page']: + $.open("/" + g.BOARD + "/#delform"); + break; + case Conf['Next page']: + if (g.VIEW === 'thread') { + return; + } + if (form = $('.next form')) { + window.location = form.action; + } + break; + case Conf['Previous page']: + if (g.VIEW === 'thread') { + return; + } + if (form = $('.prev form')) { + window.location = form.action; + } + break; + case Conf['Open catalog']: + if (Conf['External Catalog']) { + window.location = CatalogLinks.external(g.BOARD.ID); + } else { + window.location = "/" + g.BOARD + "/catalog"; + } + break; + case Conf['Next thread']: + if (g.VIEW === 'thread') { + return; + } + Nav.scroll(+1); + break; + case Conf['Previous thread']: + if (g.VIEW === 'thread') { + return; + } + Nav.scroll(-1); + break; + case Conf['Expand thread']: + ExpandThread.toggle(thread); + break; + case Conf['Open thread']: + Keybinds.open(thread); + break; + case Conf['Open thread tab']: + Keybinds.open(thread, true); + break; + case Conf['Next reply']: + Keybinds.hl(+1, threadRoot); + break; + case Conf['Previous reply']: + Keybinds.hl(-1, threadRoot); + break; + case Conf['Hide']: + if (g.VIEW === 'index') { + ThreadHiding.toggle(thread); + } + break; + default: + return; + } + e.preventDefault(); + return e.stopPropagation(); + }, + keyCode: function(e) { + var kc, key; + + key = (function() { + switch (kc = e.keyCode) { + case 8: + return ''; + case 13: + return 'Enter'; + case 27: + return 'Esc'; + case 37: + return 'Left'; + case 38: + return 'Up'; + case 39: + return 'Right'; + case 40: + return 'Down'; + default: + if ((48 <= kc && kc <= 57) || (65 <= kc && kc <= 90)) { + return String.fromCharCode(kc).toLowerCase(); + } else { + return null; + } + } + })(); + if (key) { + if (e.altKey) { + key = 'Alt+' + key; + } + if (e.ctrlKey) { + key = 'Ctrl+' + key; + } + if (e.metaKey) { + key = 'Meta+' + key; + } + if (e.shiftKey) { + key = 'Shift+' + key; + } + } + return key; + }, + qr: function(thread, quote) { + if (!(Conf['Quick Reply'] && QR.postingIsEnabled)) { + return; + } + QR.open(); + if (quote) { + QR.quote.call($('input', $('.post.highlight', thread) || thread)); + } + QR.nodes.com.focus(); + if (Conf['QR Shortcut']) { + return $.rmClass($('.qr-shortcut'), 'disabled'); + } + }, + tags: function(tag, ta) { + var range, selEnd, selStart, value; + + value = ta.value; + selStart = ta.selectionStart; + selEnd = ta.selectionEnd; + ta.value = value.slice(0, selStart) + ("[" + tag + "]") + value.slice(selStart, selEnd) + ("[/" + tag + "]") + value.slice(selEnd); + range = ("[" + tag + "]").length + selEnd; + ta.setSelectionRange(range, range); + return $.event('input', null, ta); + }, + sage: function() { + var isSage; + + isSage = /sage/i.test(QR.nodes.email.value); + return QR.nodes.email.value = isSage ? "" : "sage"; + }, + img: function(thread, all) { + var post; + + if (all) { + return ImageExpand.cb.toggleAll(); + } else { + post = Get.postFromNode($('.post.highlight', thread) || $('.op', thread)); + return ImageExpand.toggle(post); + } + }, + open: function(thread, tab) { + var url; + + if (g.VIEW !== 'index') { + return; + } + url = "/" + thread.board + "/res/" + thread; + if (tab) { + return $.open(url); + } else { + return location.href = url; + } + }, + hl: function(delta, thread) { + var axe, headRect, next, postEl, rect, replies, reply, root, topMargin, _i, _len; + + if (Conf['Fixed Header'] && Conf['Bottom header']) { + topMargin = 0; + } else { + headRect = Header.bar.getBoundingClientRect(); + topMargin = headRect.top + headRect.height; + } + if (postEl = $('.reply.highlight', thread)) { + $.rmClass(postEl, 'highlight'); + rect = postEl.getBoundingClientRect(); + if (rect.bottom >= topMargin && rect.top <= doc.clientHeight) { + root = postEl.parentNode; + axe = delta === +1 ? 'following' : 'preceding'; + next = $.x("" + axe + "-sibling::div[contains(@class,'replyContainer')][1]/child::div[contains(@class,'reply')]", root); + if (!next) { + this.focus(postEl); + return; + } + if (!(g.VIEW === 'thread' || $.x('ancestor::div[parent::div[@class="board"]]', next) === thread)) { + return; + } + rect = next.getBoundingClientRect(); + if (rect.top < 0 || rect.bottom > doc.clientHeight) { + if (delta === -1) { + window.scrollBy(0, rect.top - topMargin); + } else { + next.scrollIntoView(false); + } + } + this.focus(next); + return; + } + } + replies = $$('.reply', thread); + if (delta === -1) { + replies.reverse(); + } + for (_i = 0, _len = replies.length; _i < _len; _i++) { + reply = replies[_i]; + rect = reply.getBoundingClientRect(); + if (delta === +1 && rect.top >= topMargin || delta === -1 && rect.bottom <= doc.clientHeight) { + this.focus(reply); + return; + } + } + }, + focus: function(post) { + return $.addClass(post, 'highlight'); + } + }; + + Nav = { + init: function() { + var append, next, prev, span; + + switch (g.VIEW) { + case 'index': + if (!Conf['Index Navigation']) { + return; + } + break; + case 'thread': + if (!Conf['Reply Navigation']) { + return; + } + break; + default: + return; + } + span = $.el('span', { + id: 'navlinks' + }); + prev = $.el('a', { + textContent: 'â–²', + href: 'javascript:;' + }); + next = $.el('a', { + textContent: 'â–¼', + href: 'javascript:;' + }); + $.on(prev, 'click', this.prev); + $.on(next, 'click', this.next); + $.add(span, [prev, $.tn(' '), next]); + append = function() { + $.off(d, '4chanXInitFinished', append); + return $.add(d.body, span); + }; + return $.on(d, '4chanXInitFinished', append); + }, + prev: function() { + if (g.VIEW === 'thread') { + return window.scrollTo(0, 0); + } else { + return Nav.scroll(-1); + } + }, + next: function() { + if (g.VIEW === 'thread') { + return window.scrollTo(0, d.body.scrollHeight); + } else { + return Nav.scroll(+1); + } + }, + getThread: function(full) { + var headRect, i, rect, thread, threads, topMargin, _i, _len; + + if (Conf['Bottom header'] || !Conf['Fixed Header']) { + topMargin = 0; + } else { + headRect = Header.bar.getBoundingClientRect(); + topMargin = headRect.top + headRect.height; + } + threads = $$('.thread').filter(function(thread) { + thread = Get.threadFromRoot(thread); + return !(thread.isHidden && !thread.stub); + }); + for (i = _i = 0, _len = threads.length; _i < _len; i = ++_i) { + thread = threads[i]; + rect = thread.getBoundingClientRect(); + if (rect.bottom > topMargin) { + if (full) { + return [threads, thread, i, rect, topMargin]; + } else { + return thread; + } + } + } + return $('.board'); + }, + scroll: function(delta) { + var i, rect, thread, threads, top, topMargin, _ref, _ref1; + + _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; + } + top = ((_ref1 = threads[i]) != null ? _ref1.getBoundingClientRect().top : void 0) - topMargin; + return window.scrollBy(0, top); + } + }; + + RelativeDates = { + INTERVAL: $.MINUTE / 2, + init: function() { + if (g.VIEW === 'catalog' || !Conf['Relative Post Dates']) { + return; + } + $.on(d, 'visibilitychange ThreadUpdate', this.flush); + this.flush(); + return Post.prototype.callbacks.push({ + name: 'Relative Post Dates', + cb: this.node + }); + }, + node: function() { + var dateEl; + + if (this.isClone) { + return; + } + dateEl = this.nodes.date; + dateEl.title = dateEl.textContent; + return RelativeDates.setUpdate(this); + }, + relative: function(diff, now, date) { + var days, months, number, rounded, unit, years; + + unit = (number = diff / $.DAY) >= 1 ? (years = now.getYear() - date.getYear(), months = now.getMonth() - date.getMonth(), days = now.getDate() - date.getDate(), years > 1 ? (number = years - (months < 0 || months === 0 && days < 0), 'year') : years === 1 && (months > 0 || months === 0 && days >= 0) ? (number = years, 'year') : (months = (months + 12) % 12) > 1 ? (number = months - (days < 0), 'month') : months === 1 && days >= 0 ? (number = months, 'month') : 'day') : (number = diff / $.HOUR) >= 1 ? 'hour' : (number = diff / $.MINUTE) >= 1 ? 'minute' : (number = Math.max(0, diff) / $.SECOND, 'second'); + rounded = Math.round(number); + if (rounded !== 1) { + unit += 's'; + } + return "" + rounded + " " + unit + " ago"; + }, + stale: [], + flush: function() { + var now, update, _i, _len, _ref; + + if (d.hidden) { + return; + } + now = new Date(); + _ref = RelativeDates.stale; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + update = _ref[_i]; + update(now); + } + RelativeDates.stale = []; + clearTimeout(RelativeDates.timeout); + return RelativeDates.timeout = setTimeout(RelativeDates.flush, RelativeDates.INTERVAL); + }, + setUpdate: function(post) { + var markStale, setOwnTimeout, update; + + setOwnTimeout = function(diff) { + var delay; + + delay = diff < $.MINUTE ? $.SECOND - (diff + $.SECOND / 2) % $.SECOND : diff < $.HOUR ? $.MINUTE - (diff + $.MINUTE / 2) % $.MINUTE : diff < $.DAY ? $.HOUR - (diff + $.HOUR / 2) % $.HOUR : $.DAY - (diff + $.DAY / 2) % $.DAY; + return setTimeout(markStale, delay); + }; + update = function(now) { + var date, diff, relative, singlePost, _i, _len, _ref; + + date = post.info.date; + diff = now - date; + relative = RelativeDates.relative(diff, now, date); + _ref = [post].concat(post.clones); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + singlePost = _ref[_i]; + singlePost.nodes.date.firstChild.textContent = relative; + } + return setOwnTimeout(diff); + }; + markStale = function() { + return RelativeDates.stale.push(update); + }; + return update(new Date()); + } + }; + + RemoveSpoilers = { + init: function() { + if (!Conf['Remove Spoilers']) { + return; + } + if (Conf['Indicate Spoilers']) { + this.wrapper = function(text) { + return "[spoiler]" + text + "[/spoiler]"; + }; + } + return Post.prototype.callbacks.push({ + name: 'Reveal Spoilers', + cb: this.node + }); + }, + wrapper: function(text) { + return text; + }, + node: function(post) { + var spoiler, spoilers, _i, _len; + + spoilers = $$('s', this.nodes.comment); + for (_i = 0, _len = spoilers.length; _i < _len; _i++) { + spoiler = spoilers[_i]; + $.replace(spoiler, $.tn(RemoveSpoilers.wrapper(spoiler.textContent))); + } + } + }; + + Report = { + init: function() { + if (!/report/.test(location.search)) { + return; + } + return $.ready(this.ready); + }, + ready: function() { + var field, form; + + form = $('form'); + field = $.id('recaptcha_response_field'); + $.on(field, 'keydown', function(e) { + if (e.keyCode === 8 && !field.value) { + return $.globalEval('Recaptcha.reload("t")'); + } + }); + return $.on(form, 'submit', function(e) { + var response; + + e.preventDefault(); + response = field.value.trim(); + if (!/\s/.test(response)) { + field.value = "" + response + " " + response; + } + return form.submit(); + }); + } + }; + + 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']) { + return; + } + this.funk = this.createFunc(Conf['time']); + return Post.prototype.callbacks.push({ + name: 'Time Formatting', + cb: this.node + }); + }, + node: function() { + if (this.isClone) { + return; + } + return this.nodes.date.textContent = Time.funk(Time, this.info.date); + }, + createFunc: function(format) { + var code; + + code = format.replace(/%([A-Za-z])/g, function(s, c) { + if (c in Time.formatters) { + return "' + Time.formatters." + c + ".call(date) + '"; + } else { + return s; + } + }); + return Function('Time', 'date', "return '" + code + "'"); + }, + day: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], + month: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], + zeroPad: function(n) { + if (n < 10) { + return "0" + n; + } else { + return n; + } + }, + formatters: { + a: function() { + return Time.day[this.getDay()].slice(0, 3); + }, + A: function() { + return Time.day[this.getDay()]; + }, + b: function() { + return Time.month[this.getMonth()].slice(0, 3); + }, + B: function() { + return Time.month[this.getMonth()]; + }, + d: function() { + return Time.zeroPad(this.getDate()); + }, + e: function() { + return this.getDate(); + }, + H: function() { + return Time.zeroPad(this.getHours()); + }, + I: function() { + return Time.zeroPad(this.getHours() % 12 || 12); + }, + k: function() { + return this.getHours(); + }, + l: function() { + return this.getHours() % 12 || 12; + }, + m: function() { + return Time.zeroPad(this.getMonth() + 1); + }, + M: function() { + return Time.zeroPad(this.getMinutes()); + }, + p: function() { + if (this.getHours() < 12) { + return 'AM'; + } else { + return 'PM'; + } + }, + P: function() { + if (this.getHours() < 12) { + return 'am'; + } else { + return 'pm'; + } + }, + S: function() { + return Time.zeroPad(this.getSeconds()); + }, + y: function() { + return this.getFullYear() % 100; + }, + Y: function() { + return this.getFullYear(); + } + } + }; + + Settings = { + init: function() { + var link, settings; + + link = $.el('a', { + className: 'settings-link', + textContent: 'Settings', + href: 'javascript:;' + }); + $.on(link, 'click', Settings.open); + Header.addShortcut(link); + $.get('previousversion', null, function(item) { + var changelog, el, previous; + + if (previous = item['previousversion']) { + if (previous === g.VERSION) { + return; + } + changelog = 'https://github.com/seaweedchan/4chan-x/blob/master/CHANGELOG.md'; + el = $.el('span', { + innerHTML: "4chan X has been updated to version " + g.VERSION + "." + }); + new Notification('info', el, 30); + } else { + $.on(d, '4chanXInitFinished', Settings.open); + } + return $.set({ + lastchecked: Date.now(), + previousversion: g.VERSION + }); + }); + Settings.addSection('Main', Settings.main); + Settings.addSection('Filter', Settings.filter); + Settings.addSection('Sauce', Settings.sauce); + Settings.addSection('Advanced', Settings.advanced); + Settings.addSection('Keybinds', Settings.keybinds); + $.on(d, 'AddSettingsSection', Settings.addSection); + $.on(d, 'OpenSettings', function(e) { + return Settings.open(e.detail); + }); + settings = JSON.parse(localStorage.getItem('4chan-settings')) || {}; + if (settings.disableAll) { + return; + } + settings.disableAll = true; + return localStorage.setItem('4chan-settings', JSON.stringify(settings)); + }, + open: function(openSection) { + var dialog, html, link, links, overlay, section, sectionToOpen, _i, _len, _ref; + + $.off(d, '4chanXInitFinished', Settings.open); + if (Settings.dialog) { + return; + } + $.event('CloseMenu'); + html = "
"; + Settings.overlay = overlay = $.el('div', { + id: 'overlay' + }); + Settings.dialog = dialog = $.el('div', { + id: 'fourchanx-settings', + className: 'dialog', + innerHTML: html + }); + $.on($('.export', Settings.dialog), 'click', Settings["export"]); + $.on($('.import', Settings.dialog), 'click', Settings["import"]); + $.on($('input', Settings.dialog), 'change', Settings.onImport); + links = []; + _ref = Settings.sections; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + section = _ref[_i]; + link = $.el('a', { + className: "tab-" + section.hyphenatedTitle, + textContent: section.title, + href: 'javascript:;' + }); + $.on(link, 'click', Settings.openSection.bind(section)); + links.push(link, $.tn(' | ')); + if (section.title === openSection) { + sectionToOpen = link; + } + } + links.pop(); + $.add($('.sections-list', dialog), links); + (sectionToOpen ? sectionToOpen : links[0]).click(); + $.on($('.close', dialog), 'click', Settings.close); + $.on(overlay, 'click', Settings.close); + $.add(d.body, [overlay, dialog]); + return $.event('OpenSettings', null, dialog); + }, + close: function() { + if (!Settings.dialog) { + return; + } + $.rm(Settings.overlay); + $.rm(Settings.dialog); + delete Settings.overlay; + return delete Settings.dialog; + }, + sections: [], + addSection: function(title, open) { + var hyphenatedTitle, _ref; + + if (typeof title !== 'string') { + _ref = title.detail, title = _ref.title, open = _ref.open; + } + hyphenatedTitle = title.toLowerCase().replace(/\s+/g, '-'); + return Settings.sections.push({ + title: title, + hyphenatedTitle: hyphenatedTitle, + open: open + }); + }, + openSection: function() { + var section, selected; + + if (selected = $('.tab-selected', Settings.dialog)) { + $.rmClass(selected, 'tab-selected'); + } + $.addClass($(".tab-" + this.hyphenatedTitle, Settings.dialog), 'tab-selected'); + section = $('section', Settings.dialog); + $.rmAll(section); + section.className = "section-" + this.hyphenatedTitle; + this.open(section, g); + section.scrollTop = 0; + return $.event('OpenSettings', null, section); + }, + main: function(section) { + var arr, button, description, div, fs, hiddenNum, input, inputs, items, key, obj, _ref; + + items = {}; + inputs = {}; + _ref = Config.main; + for (key in _ref) { + obj = _ref[key]; + fs = $.el('fieldset', { + innerHTML: "" + key + "" + }); + for (key in obj) { + arr = obj[key]; + description = arr[1]; + div = $.el('div', { + innerHTML: ": " + description + "" + }); + input = $('input', div); + $.on(input, 'change', $.cb.checked); + items[key] = Conf[key]; + inputs[key] = input; + $.add(fs, div); + } + $.add(section, fs); + } + $.get(items, function(items) { + var val; + + for (key in items) { + val = items[key]; + inputs[key].checked = val; + } + }); + div = $.el('div', { + innerHTML: ": Clear manually-hidden threads and posts on all boards. Refresh the page to apply." + }); + button = $('button', div); + hiddenNum = 0; + $.get('hiddenThreads', { + boards: {} + }, function(item) { + var ID, board, thread, _ref1; + + _ref1 = item.hiddenThreads.boards; + for (ID in _ref1) { + board = _ref1[ID]; + for (ID in board) { + thread = board[ID]; + hiddenNum++; + } + } + return button.textContent = "Hidden: " + hiddenNum; + }); + $.get('hiddenPosts', { + boards: {} + }, function(item) { + var ID, board, post, thread, _ref1; + + _ref1 = item.hiddenPosts.boards; + for (ID in _ref1) { + board = _ref1[ID]; + for (ID in board) { + thread = board[ID]; + for (ID in thread) { + post = thread[ID]; + hiddenNum++; + } + } + } + return button.textContent = "Hidden: " + hiddenNum; + }); + $.on(button, 'click', function() { + this.textContent = 'Hidden: 0'; + return $.get('hiddenThreads', { + boards: {} + }, function(item) { + var boardID; + + for (boardID in item.hiddenThreads.boards) { + localStorage.removeItem("4chan-hide-t-" + boardID); + } + return $["delete"](['hiddenThreads', 'hiddenPosts']); + }); + }); + return $.after($('input[name="Stubs"]', section).parentNode.parentNode, div); + }, + "export": function(now, data) { + var a, db, _i, _len; + + if (typeof now !== 'number') { + now = Date.now(); + data = { + version: g.VERSION, + date: now + }; + Conf['WatchedThreads'] = {}; + for (_i = 0, _len = DataBoards.length; _i < _len; _i++) { + db = DataBoards[_i]; + Conf[db] = { + boards: {} + }; + } + $.get(Conf, function(Conf) { + delete Conf['archives']; + data.Conf = Conf; + return Settings["export"](now, data); + }); + return; + } + a = $.el('a', { + className: 'warning', + textContent: 'Save me!', + download: "4chan X v" + g.VERSION + "-" + now + ".json", + href: "data:application/json;base64," + (btoa(unescape(encodeURIComponent(JSON.stringify(data, null, 2))))), + target: '_blank' + }); + return a.click(); + }, + "import": function() { + return this.nextElementSibling.click(); + }, + onImport: function() { + var file, output, reader; + + if (!(file = this.files[0])) { + return; + } + output = $('.imp-exp-result'); + if (!confirm('Your current settings will be entirely overwritten, are you sure?')) { + output.textContent = 'Import aborted.'; + return; + } + reader = new FileReader(); + reader.onload = function(e) { + var data, err; + + try { + data = JSON.parse(e.target.result); + Settings.loadSettings(data); + if (confirm('Import successful. Refresh now?')) { + return window.location.reload(); + } + } catch (_error) { + err = _error; + output.textContent = 'Import failed due to an error.'; + return c.error(err.stack); + } + }; + return reader.readAsText(file); + }, + loadSettings: function(data) { + var key, val, version, _ref; + + version = data.version.split('.'); + if (version[0] === '2') { + data = Settings.convertSettings(data, { + 'Disable 4chan\'s extension': '', + 'Catalog Links': '', + 'Reply Navigation': '', + 'Show Stubs': 'Stubs', + 'Image Auto-Gif': 'Auto-GIF', + 'Expand From Current': '', + 'Unread Tab Icon': 'Unread Favicon', + 'Post in Title': 'Thread Excerpt', + 'Auto Hide QR': '', + 'Open Reply in New Tab': '', + 'Remember QR size': '', + 'Quote Inline': 'Quote Inlining', + 'Quote Preview': 'Quote Previewing', + 'Indicate OP quote': 'Mark OP Quotes', + 'Indicate Cross-thread Quotes': 'Mark Cross-thread Quotes', + 'Reply Hiding': 'Reply Hiding Buttons', + 'Thread Hiding': 'Thread Hiding Buttons', + 'uniqueid': 'uniqueID', + 'mod': 'capcode', + 'country': 'flag', + 'md5': 'MD5', + 'openEmptyQR': 'Open empty QR', + 'openQR': 'Open QR', + 'openOptions': 'Open settings', + 'close': 'Close', + 'spoiler': 'Spoiler tags', + 'code': 'Code tags', + 'submit': 'Submit QR', + 'watch': 'Watch', + 'update': 'Update', + 'unreadCountTo0': '', + 'expandAllImages': 'Expand images', + 'expandImage': 'Expand image', + 'zero': 'Front page', + 'nextPage': 'Next page', + 'previousPage': 'Previous page', + 'nextThread': 'Next thread', + 'previousThread': 'Previous thread', + 'expandThread': 'Expand thread', + 'openThreadTab': 'Open thread', + 'openThread': 'Open thread tab', + 'nextReply': 'Next reply', + 'previousReply': 'Previous reply', + 'hide': 'Hide', + 'Scrolling': 'Auto Scroll', + 'Verbose': '' + }); + data.Conf.sauces = data.Conf.sauces.replace(/\$\d/g, function(c) { + switch (c) { + case '$1': + return '%TURL'; + case '$2': + return '%URL'; + case '$3': + return '%MD5'; + case '$4': + return '%board'; + default: + return c; + } + }); + _ref = Config.hotkeys; + for (key in _ref) { + val = _ref[key]; + if (!(key in data.Conf)) { + continue; + } + data.Conf[key] = data.Conf[key].replace(/ctrl|alt|meta/g, function(s) { + return "" + (s[0].toUpperCase()) + s.slice(1); + }).replace(/(^|.+\+)[A-Z]$/g, function(s) { + return "Shift+" + s.slice(0, -1) + (s.slice(-1).toLowerCase()); + }); + } + data.Conf.WatchedThreads = data.WatchedThreads; + } else if (version[0] === '3') { + data = Settings.convertSettings(data, { + 'Reply Hiding': 'Reply Hiding Buttons', + 'Thread Hiding': 'Thread Hiding Buttons', + 'Bottom header': 'Bottom Header', + 'Unread Tab Icon': 'Unread Favicon' + }); + } + return $.set(data.Conf); + }, + convertSettings: function(data, map) { + var newKey, prevKey; + + for (prevKey in map) { + newKey = map[prevKey]; + if (newKey) { + data.Conf[newKey] = data.Conf[prevKey]; + } + delete data.Conf[prevKey]; + } + return data; + }, + filter: function(section) { + var select; + + section.innerHTML = "
"; + select = $('select', section); + $.on(select, 'change', Settings.selectFilter); + return Settings.selectFilter.call(select); + }, + selectFilter: function() { + var div, name, ta; + + div = this.nextElementSibling; + if ((name = this.value) !== 'guide') { + $.rmAll(div); + ta = $.el('textarea', { + name: name, + className: 'field', + spellcheck: false + }); + $.get(name, Conf[name], function(item) { + return ta.value = item[name]; + }); + $.on(ta, 'change', $.cb.value); + $.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

    You can use these settings with each regular expression, separate them with semicolons:\n
  • \n Per boards, separate them with commas. It is global if not specified.
    \n For example: boards:a,jp;.\n
  • \n Filter OPs only along with their threads (`only`), replies only (`no`), or both (`yes`, this is default).
    \n For example: op:only;, op:no; or op:yes;.\n
  • \n Overrule the `Show Stubs` setting if specified: create a stub (`yes`) or not (`no`).
    \n For example: stub:yes; or stub:no;.\n
  • \n Highlight instead of hiding. You can specify a class name to use with a userstyle.
    \n For example: highlight; or highlight:wallpaper;.\n
  • \n Highlighted OPs will have their threads put on top of board pages by default.
    \n For example: top:yes; or top:no;.\n
"; + }, + sauce: function(section) { + var ta; + + section.innerHTML = "
Sauce is disabled.
Lines starting with a # will be ignored.
You can specify a display text by appending ;text:[text] to the URL.
    These parameters will be replaced by their corresponding values:\n
  • %TURL: Thumbnail URL.
  • %URL: Full image URL.
  • %MD5: MD5 hash.
  • %board: Current board.
"; + ta = $('textarea', section); + $.get('sauces', Conf['sauces'], function(item) { + return ta.value = item['sauces']; + }); + return $.on(ta, 'change', $.cb.value); + }, + advanced: function(section) { + var archive, boardID, boardOptions, boardSelect, boards, data, event, input, inputs, item, items, name, row, rows, ta, table, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3, _ref4; + + section.innerHTML = "
Archiver
404 Redirect is disabled.
Thread redirectionPost fetchingFile redirection
Disabled selections indicate that only one archive is available for that board and redirection type.
Custom Board Navigation
New lines will be converted into spaces.

In the following examples for /g/, g can be changed to a different board ID (a, b, etc...), the current board (current), or the Status/Twitter link (status, @).
Board link: g
Title link: g-title
Board link (Replace with title when on that board): g-replace
Full text link: g-full
Custom text link: g-text:\"Install Gentoo\"
Index-only link: g-index
Catalog-only link: g-catalog
External link: external-text:\"Google\",\"http://www.google.com\"
Combinations are possible: g-index-text:\"Technology Index\"
Full board list toggle: toggle-all

[ toggle-all ] [current-title] [g-title / a-title / jp-title] [x / wsg / h] [t-text:\"Piracy\"]
\n will give you
[ + ] [Technology] [Technology / Anime & Manga / Otaku Culture] [x / wsg / h] [Piracy]
\n if you are on /g/.\n
Time Formatting is disabled.
:
Day: %a, %A, %d, %e
Month: %m, %b, %B
Year: %y, %Y
Hour: %k, %H, %l, %I, %p, %P
Minute: %M
Second: %S
Quote Backlinks formatting is disabled.
:
File Info Formatting is disabled.
:
Link: %l (truncated), %L (untruncated), %T (Unix timestamp)
Original file name: %n (truncated), %N (untruncated), %t (Unix timestamp)
Spoiler indicator: %p
Size: %B (Bytes), %K (KB), %M (MB), %s (4chan default)
Resolution: %r (Displays 'PDF' for PDF files)
Quick Reply Personas is disabled.

\n One item per line.
\n Items will be added in the relevant input's auto-completion list.
\n Password items will always be used, since there is no password input.
\n Lines starting with a # will be ignored.\n

    You can use these settings with each item, separate them with semicolons:\n
  • Possible items are: name, email, subject and password.
  • Wrap values of items with quotes, like this: email:\"sage\".
  • Force values as defaults with the always keyword, for example: email:\"sage\";always.
  • Select specific boards for an item, separated with commas, for example: email:\"sage\";boards:jp;always.
Unread Favicon is disabled.
Emoji is disabled.
\n Sage Icon:
\n Position:
Thread Updater is disabled.
\n Interval:
"; + items = {}; + inputs = {}; + _ref = ['boardnav', 'time', 'backlink', 'fileInfo', 'favicon', 'sageEmoji', 'emojiPos', 'usercss']; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + name = _ref[_i]; + input = $("[name=" + name + "]", section); + items[name] = Conf[name]; + inputs[name] = input; + event = ['favicon', 'usercss', 'sageEmoji', 'emojiPos'].contains(name) ? 'change' : 'input'; + $.on(input, event, $.cb.value); + } + ta = $('.personafield', section); + $.get('QR.personas', Conf['QR.personas'], function(item) { + return ta.value = item['QR.personas']; + }); + $.on(ta, 'change', $.cb.value); + $.get(items, function(items) { + var key, val; + + for (key in items) { + val = items[key]; + if (['emojiPos'].contains(key)) { + continue; + } + input = inputs[key]; + input.value = val; + if (key === 'usercss') { + continue; + } + $.on(input, event, Settings[key]); + Settings[key].call(input); + } + }); + $.on($('input[name=Interval]', section), 'change', ThreadUpdater.cb.interval); + $.on($('input[name="Custom CSS"]', section), 'change', Settings.togglecss); + $.on($.id('apply-css'), 'click', Settings.usercss); + boards = {}; + _ref1 = Redirect.archives; + for (name in _ref1) { + archive = _ref1[name]; + _ref2 = archive.boards; + for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { + boardID = _ref2[_j]; + data = boards[boardID] || (boards[boardID] = { + thread: [], + post: [], + file: [] + }); + data.thread.push(name); + if (archive.software === 'foolfuuka') { + data.post.push(name); + } + if (archive.files.contains(boardID)) { + data.file.push(name); + } + } + } + rows = []; + boardOptions = []; + _ref3 = Object.keys(boards).sort(); + for (_k = 0, _len2 = _ref3.length; _k < _len2; _k++) { + boardID = _ref3[_k]; + row = $.el('tr', { + className: "board-" + boardID + }); + row.hidden = boardID !== g.BOARD.ID; + boardOptions.push($.el('option', { + textContent: "/" + boardID + "/", + value: "board-" + boardID, + selected: boardID === g.BOARD.ID + })); + data = boards[boardID]; + _ref4 = ['thread', 'post', 'file']; + for (_l = 0, _len3 = _ref4.length; _l < _len3; _l++) { + item = _ref4[_l]; + $.add(row, Settings.addArchiveCell(boardID, data, item)); + } + rows.push(row); + } + $.add($('tbody', section), rows); + boardSelect = $('#archive-board-select', section); + $.add(boardSelect, boardOptions); + table = $.id('archive-table'); + $.on(boardSelect, 'change', function() { + $('tbody > :not([hidden])', table).hidden = true; + return $("tbody > ." + this.value, table).hidden = false; + }); + $.get('selectedArchives', Conf['selectedArchives'], function(_arg) { + var option, selectedArchives, type; + + selectedArchives = _arg.selectedArchives; + for (boardID in selectedArchives) { + data = selectedArchives[boardID]; + for (type in data) { + name = data[type]; + if (option = $("select[data-boardid='" + boardID + "'][data-type='" + type + "'] > option[value='" + name + "']", section)) { + option.selected = true; + } + } + } + }); + }, + addArchiveCell: function(boardID, data, type) { + var archive, i, length, options, select, td; + + length = data[type].length; + td = $.el('td', { + className: 'archive-cell' + }); + if (!length) { + td.textContent = '--'; + return td; + } + options = []; + i = 0; + while (i < length) { + archive = data[type][i++]; + options.push($.el('option', { + textContent: archive, + value: archive + })); + } + td.innerHTML = ''; + select = td.firstElementChild; + if (!(select.disabled = length === 1)) { + select.setAttribute('data-boardid', boardID); + select.setAttribute('data-type', type); + $.on(select, 'change', Settings.saveSelectedArchive); + } + $.add(select, options); + return td; + }, + saveSelectedArchive: function() { + var _this = this; + + return $.get('selectedArchives', Conf['selectedArchives'], function(_arg) { + var selectedArchives, _name; + + selectedArchives = _arg.selectedArchives; + (selectedArchives[_name = _this.dataset.boardid] || (selectedArchives[_name] = {}))[_this.dataset.type] = _this.value; + return $.set('selectedArchives', selectedArchives); + }); + }, + boardnav: function() { + return Header.generateBoardList(this.value); + }, + time: function() { + var funk; + + funk = Time.createFunc(this.value); + return this.nextElementSibling.textContent = funk(Time, new Date()); + }, + backlink: function() { + return this.nextElementSibling.textContent = this.value.replace(/%id/, '123456789'); + }, + fileInfo: function() { + var data, funk; + + data = { + isReply: true, + file: { + URL: '//images.4chan.org/g/src/1334437723720.jpg', + name: 'd9bb2efc98dd0df141a94399ff5880b7.jpg', + size: '276 KB', + sizeInBytes: 276 * 1024, + dimensions: '1280x720', + isImage: true, + isSpoiler: true + } + }; + funk = FileInfo.createFunc(this.value); + return this.nextElementSibling.innerHTML = funk(FileInfo, data); + }, + favicon: function() { + Favicon["switch"](); + if (g.VIEW === 'thread' && Conf['Unread Favicon']) { + Unread.update(); + } + return this.nextElementSibling.innerHTML = "\n\n\n"; + }, + sageEmoji: function() { + return this.nextElementSibling.innerHTML = ""; + }, + togglecss: function() { + if ($('textarea[name=usercss]', $.x('ancestor::fieldset[1]', this)).disabled = !this.checked) { + CustomCSS.rmStyle(); + } else { + CustomCSS.addStyle(); + } + return $.cb.checked.call(this); + }, + usercss: function() { + return CustomCSS.update(); + }, + keybinds: function(section) { + var arr, input, inputs, items, key, tbody, tr, _ref; + + section.innerHTML = "
Keybinds are disabled.
Allowed keys: a-z, 0-9, Ctrl, Shift, Alt, Meta, Enter, Esc, Up, Down, Right, Left.
Press Backspace to disable a keybind.
ActionsKeybinds
"; + tbody = $('tbody', section); + items = {}; + inputs = {}; + _ref = Config.hotkeys; + for (key in _ref) { + arr = _ref[key]; + tr = $.el('tr', { + innerHTML: "" + arr[1] + "" + }); + input = $('input', tr); + input.name = key; + input.spellcheck = false; + items[key] = Conf[key]; + inputs[key] = input; + $.on(input, 'keydown', Settings.keybind); + $.add(tbody, tr); + } + return $.get(items, function(items) { + var val; + + for (key in items) { + val = items[key]; + inputs[key].value = val; + } + }); + }, + keybind: function(e) { + var key; + + if (e.keyCode === 9) { + return; + } + e.preventDefault(); + e.stopPropagation(); + if ((key = Keybinds.keyCode(e)) == null) { + return; + } + this.value = key; + return $.cb.value.call(this); + } + }; + + Main = { + init: function(items) { + var db, flatten, _i, _len; + + flatten = function(parent, obj) { + var key, val; + + if (obj instanceof Array) { + Conf[parent] = obj[0]; + } else if (typeof obj === 'object') { + for (key in obj) { + val = obj[key]; + flatten(key, val); + } + } else { + Conf[parent] = obj; + } + }; + flatten(null, Config); + for (_i = 0, _len = DataBoards.length; _i < _len; _i++) { + db = DataBoards[_i]; + Conf[db] = { + boards: {} + }; + } + Conf['selectedArchives'] = {}; + $.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'); + }), Main.initStyle); + }, + initFeatures: function(items) { + var init, pathname, _ref; + + Conf = items; + pathname = location.pathname.split('/'); + g.BOARD = new Board(pathname[1]); + if ((_ref = g.BOARD.ID) === 'z' || _ref === 'fk') { + return; + } + g.VIEW = (function() { + switch (pathname[2]) { + case 'res': + return 'thread'; + case 'catalog': + return 'catalog'; + default: + return 'index'; + } + })(); + if (g.VIEW === 'thread') { + g.THREADID = +pathname[3]; + } + switch (location.hostname) { + case 'api.4chan.org': + return; + case 'sys.4chan.org': + Report.init(); + return; + case 'images.4chan.org': + $.ready(function() { + var url; + + if (Conf['404 Redirect'] && d.title === '4chan - 404 Not Found') { + Redirect.init(); + url = Redirect.to('file', { + boardID: pathname[1], + filename: pathname[3] + }); + if (url) { + return location.href = url; + } + } + }); + return; + } + init = function(features) { + var err, module, name; + + for (name in features) { + module = features[name]; + try { + module.init(); + } catch (_error) { + err = _error; + Main.handleErrors({ + message: "\"" + name + "\" initialization crashed.", + error: err + }); + } + } + }; + init({ + 'Polyfill': Polyfill, + 'Redirect': Redirect, + 'Header': Header, + 'Catalog Links': CatalogLinks, + 'Settings': Settings, + 'Announcement Hiding': PSAHiding, + 'Fourchan thingies': Fourchan, + 'Emoji': Emoji, + 'Color User IDs': IDColor, + 'Remove Spoilers': RemoveSpoilers, + 'Custom CSS': CustomCSS, + 'Linkify': Linkify, + 'Resurrect Quotes': Quotify, + 'Filter': Filter, + 'Thread Hiding Buttons': ThreadHiding, + 'Reply Hiding Buttons': PostHiding, + 'Recursive': Recursive, + 'Strike-through Quotes': QuoteStrikeThrough, + 'Quick Reply': QR, + 'Menu': Menu, + 'Report Link': ReportLink, + 'Thread Hiding (Menu)': ThreadHiding.menu, + 'Reply Hiding (Menu)': PostHiding.menu, + 'Delete Link': DeleteLink, + 'Filter (Menu)': Filter.menu, + 'Download Link': DownloadLink, + 'Archive Link': ArchiveLink, + 'Quote Inlining': QuoteInline, + 'Quote Previewing': QuotePreview, + 'Quote Backlinks': QuoteBacklink, + 'Mark Quotes of You': QuoteYou, + 'Mark OP Quotes': QuoteOP, + 'Mark Cross-thread Quotes': QuoteCT, + 'Anonymize': Anonymize, + 'Time Formatting': Time, + 'Relative Post Dates': RelativeDates, + 'File Info Formatting': FileInfo, + 'Fappe Tyme': FappeTyme, + 'Sauce': Sauce, + 'Image Expansion': ImageExpand, + 'Image Expansion (Menu)': ImageExpand.menu, + 'Reveal Spoilers': RevealSpoilers, + 'Image Loading': ImageLoader, + 'Image Hover': ImageHover, + 'Comment Expansion': ExpandComment, + 'Thread Expansion': ExpandThread, + 'Thread Excerpt': ThreadExcerpt, + 'Favicon': Favicon, + 'Unread': Unread, + 'Quote Threading': QuoteThreading, + 'Thread Stats': ThreadStats, + 'Thread Updater': ThreadUpdater, + 'Thread Watcher': ThreadWatcher, + 'Index Navigation': Nav, + 'Keybinds': Keybinds + }); + $.on(d, 'AddCallback', Main.addCallback); + return $.ready(Main.initReady); + }, + initStyle: function() { + var MutationObserver, mainStyleSheet, observer, setStyle, style, styleSheets, _ref; + + $.off(d, '4chanMainInit', Main.initStyle); + if (!Main.isThisPageLegit() || $.hasClass(doc, 'fourchan-x')) { + return; + } + if ((_ref = $('link[href*=mobile]', d.head)) != null) { + _ref.disabled = true; + } + $.addClass(doc, 'webkit'); + $.addClass(doc, 'blink'); + $.addClass(doc, 'fourchan-x'); + $.addClass(doc, g.VIEW); + $.addStyle(Main.css); + if (g.VIEW === 'catalog') { + $.addClass(doc, $.id('base-css').href.match(/catalog_(\w+)/)[1].replace('_new', '').replace(/_+/g, '-')); + return; + } + style = 'yotsuba-b'; + mainStyleSheet = $('link[title=switch]', d.head); + styleSheets = $$('link[rel="alternate stylesheet"]', d.head); + setStyle = function() { + var styleSheet, _i, _len; + + $.rmClass(doc, style); + for (_i = 0, _len = styleSheets.length; _i < _len; _i++) { + styleSheet = styleSheets[_i]; + if (styleSheet.href === mainStyleSheet.href) { + style = styleSheet.title.toLowerCase().replace('new', '').trim().replace(/\s+/g, '-'); + break; + } + } + return $.addClass(doc, style); + }; + setStyle(); + if (!mainStyleSheet) { + return; + } + if (MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.OMutationObserver) { + observer = new MutationObserver(setStyle); + return observer.observe(mainStyleSheet, { + attributes: true, + attributeFilter: ['href'] + }); + } else { + return $.on(mainStyleSheet, 'DOMAttrModified', setStyle); + } + }, + initReady: function() { + var board, boardChild, err, errors, href, passLink, posts, styleSelector, thread, threadChild, threads, _i, _j, _len, _len1, _ref, _ref1; + + if (d.title === '4chan - 404 Not Found') { + if (Conf['404 Redirect'] && g.VIEW === 'thread') { + href = Redirect.to('thread', { + boardID: g.BOARD.ID, + threadID: g.THREADID, + postID: +location.hash.match(/\d+/) + }); + location.href = href || ("/" + g.BOARD + "/"); + } + return; + } + if (!$.hasClass(doc, 'fourchan-x')) { + Main.initStyle(); + } + if (board = $('.board')) { + threads = []; + posts = []; + _ref = board.children; + 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); + threads.push(thread); + _ref1 = boardChild.children; + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + threadChild = _ref1[_j]; + if (!$.hasClass(threadChild, 'postContainer')) { + continue; + } + try { + posts.push(new Post(threadChild, 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.", + error: err + }); + } + } + } + if (errors) { + Main.handleErrors(errors); + } + Main.callbackNodes(Thread, threads); + Main.callbackNodesDB(Post, posts, function() { + $.event('4chanXInitFinished'); + return Main.checkUpdate(); + }); + if (styleSelector = $.id('styleSelector')) { + passLink = $.el('a', { + textContent: '4chan Pass', + href: 'javascript:;' + }); + $.on(passLink, 'click', function() { + return window.open('//sys.4chan.org/auth', 'This will steal your data.', 'left=0,top=0,width=500,height=255,toolbar=0,resizable=0'); + }); + $.before(styleSelector.previousSibling, [$.tn('['), passLink, $.tn(']\u00A0\u00A0')]); + } + return; + } + try { + localStorage.getItem('4chan-settings'); + } catch (_error) { + err = _error; + new Notification('warning', 'Cookies need to be enabled on 4chan for 4chan X to properly function.', 30); + } + $.event('4chanXInitFinished'); + return Main.checkUpdate(); + }, + callbackNodes: function(klass, nodes) { + var callback, err, errors, i, len, node, _i, _len, _ref; + + len = nodes.length; + _ref = klass.prototype.callbacks; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + callback = _ref[_i]; + i = 0; + while (i < len) { + node = nodes[i++]; + try { + callback.cb.call(node); + } catch (_error) { + err = _error; + if (!errors) { + errors = []; + } + errors.push({ + message: "\"" + callback.name + "\" crashed on " + klass.name + " No." + node + " (/" + node.board + "/).", + error: err + }); + } + } + } + if (errors) { + return Main.handleErrors(errors); + } + }, + callbackNodesDB: function(klass, nodes, cb) { + var errors, func, i, len, node, queue, softTask; + + queue = []; + softTask = function() { + var args, func, task; + + task = queue.shift(); + func = task[0]; + args = Array.prototype.slice.call(task, 1); + func.apply(func, args); + if (!queue.length) { + return; + } + if ((queue.length % 7) === 0) { + return setTimeout(softTask, 0); + } else { + return softTask(); + } + }; + len = nodes.length; + i = 0; + errors = null; + func = function(node, i) { + var callback, err, _i, _len, _ref; + + _ref = klass.prototype.callbacks; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + callback = _ref[_i]; + try { + callback.cb.call(node); + } catch (_error) { + err = _error; + if (!errors) { + errors = []; + } + errors.push({ + message: "\"" + callback.name + "\" crashed on " + klass.name + " No." + node + " (/" + node.board + "/).", + error: err + }); + } + } + if (i === len) { + if (errors) { + Main.handleErrors(errors); + } + if (cb) { + return cb(); + } + } + }; + while (i < len) { + node = nodes[i]; + queue.push([func, node, ++i]); + } + return softTask(); + }, + addCallback: function(e) { + var Klass, obj; + + obj = e.detail; + if (typeof obj.callback.name !== 'string') { + throw new Error("Invalid callback name: " + obj.callback.name); + } + switch (obj.type) { + case 'Post': + Klass = Post; + break; + case 'Thread': + Klass = Thread; + break; + default: + return; + } + obj.callback.isAddon = true; + return Klass.prototype.callbacks.push(obj.callback); + }, + message: function(e) { + var el, version; + + version = e.data.version; + if (version && version !== g.VERSION) { + el = $.el('span', { + innerHTML: "Update: 4chan X v" + version + " is out, get it here." + }); + return new Notification('info', el, 120); + } + }, + checkUpdate: function() { + var now; + + if (!(Conf['Check for Updates'] && Main.isThisPageLegit())) { + return; + } + now = Date.now(); + return $.get('lastchecked', 0, function(_arg) { + var lastchecked; + + lastchecked = _arg.lastchecked; + if (lastchecked > now - $.DAY) { + return; + } + return $.ready(function() { + $.on(window, 'message', Main.message); + $.set('lastchecked', now); + return $.add(d.head, $.el('script', { + src: 'https://github.com/seaweedchan/4chan-x/raw/master/latest.js' + })); + }); + }); + }, + handleErrors: function(errors) { + var div, error, logs, _i, _len; + + if (!(errors instanceof Array)) { + error = errors; + } else if (errors.length === 1) { + error = errors[0]; + } + if (error) { + new Notification('error', Main.parseError(error), 15); + return; + } + div = $.el('div', { + innerHTML: "" + errors.length + " errors occurred. [show]" + }); + $.on(div.lastElementChild, 'click', function() { + var _ref; + + return _ref = this.textContent === 'show' ? ['hide', false] : ['show', true], this.textContent = _ref[0], logs.hidden = _ref[1], _ref; + }); + logs = $.el('div', { + hidden: true + }); + for (_i = 0, _len = errors.length; _i < _len; _i++) { + error = errors[_i]; + $.add(logs, Main.parseError(error)); + } + return new Notification('error', [div, logs], 30); + }, + parseError: function(data) { + var error, message; + + Main.logError(data); + message = $.el('div', { + textContent: data.message + }); + error = $.el('div', { + textContent: data.error + }); + return [message, error]; + }, + errors: [], + logError: function(data) { + c.error(data.message, data.error.stack); + return Main.errors.push(data); + }, + isThisPageLegit: function() { + 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'); + } + 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.expanded-image {\nclear: both;\n}\n.expanded-image > .op > .file::after {\ncontent: '';\nclear: both;\ndisplay: table;\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/* 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;\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(); + +}).call(this); diff --git a/src/General/meta/operamanifest.json b/src/General/meta/operamanifest.json new file mode 100644 index 000000000..c6c5067d4 --- /dev/null +++ b/src/General/meta/operamanifest.json @@ -0,0 +1,21 @@ +{ + "name": "<%= meta.name %>", + "version": "<%= version %>", + "manifest_version": 2, + "description": "<%= description %>", + "icons": { + "16": "icon16.png", + "48": "icon48.png", + "128": "icon128.png" + }, + "content_scripts": [{ + "js": ["script.js"], + "matches": <%= JSON.stringify(meta.matches) %>, + "all_frames": true, + "run_at": "document_start" + }], + "homepage_url": "<%= meta.page %>", + "permissions": [ + "storage" + ] +}