// Generated by CoffeeScript
// ==UserScript==
// @name 4chan X
// @version 1.10.0.5
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
// @description Cross-browser userscript for maximum lurking on 4chan.
// @license MIT; https://github.com/ccd0/4chan-x/blob/master/LICENSE
// @match *://boards.4chan.org/*
// @match *://sys.4chan.org/*
// @match *://a.4cdn.org/*
// @match *://i.4cdn.org/*
// @match *://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue
// @grant GM_listValues
// @grant GM_openInTab
// @grant GM_xmlhttpRequest
// @run-at document-start
// @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAACVBMVEUAAGcAAABmzDNZt9VtAAAAAXRSTlMAQObYZgAAAF5JREFUeNrtkTESABAQxPD/R6tsE2dUGYUtFJvLDKf93KevHJAjpBorAQWSBIKqFASC4G0pCAkm4GfaEvgYXl0T6HBaE97f0vmnfYHbZOMLZCx9ISdKWwjOWZSC8GYm4SUGwfYgqI4AAAAASUVORK5CYII=
// ==/UserScript==
/*
* 4chan X - Version 1.10.0.5
*
* Licensed under the MIT license.
* https://github.com/ccd0/4chan-x/blob/master/LICENSE
*
* Appchan X Copyright © 2013-2015 Zixaphir <[email protected]>
* http://zixaphir.github.io/appchan-x/
* 4chan x Copyright © 2009-2011 James Campos <[email protected]>
* https://github.com/aeosynth/4chan-x
* 4chan x Copyright © 2012-2014 Nicolas Stepien <[email protected]>
* https://4chan-x.just-believe.in/
* 4chan x Copyright © 2013-2014 Jordan Bates <[email protected]>
* 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
*/
'use strict';
(function() {
var $, $$, Anonymize, AntiAutoplay, ArchiveLink, Banner, Board, Build, Callbacks, Captcha, CatalogLinks, CatalogThread, Clone, Conf, Config, Connection, CrossOrigin, CustomCSS, DataBoard, DeleteLink, DownloadLink, E, Embedding, ExpandComment, ExpandThread, FappeTyme, Favicon, Fetcher, FileInfo, Filter, Fourchan, Gallery, Get, Header, IDColor, IDHighlight, ImageCommon, ImageExpand, ImageHover, ImageLoader, Index, Keybinds, Linkify, Main, MarkNewIPs, Menu, Metadata, Nav, Notice, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, RandomAccessList, Recursive, Redirect, RelativeDates, RemoveSpoilers, ReportLink, RevealSpoilers, Sauce, Settings, ShimSet, SimpleDict, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, Volume, c, d, doc, g,
__slice = [].slice,
__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; },
__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); }; };
Array.prototype.indexOf = function(val, i) {
var len;
i || (i = 0);
len = this.length;
while (i < len) {
if (this[i] === val) {
return i;
}
i++;
}
return -1;
};
__indexOf = [].indexOf;
Config = {
main: {
'Miscellaneous': {
'JSON Navigation': [true, 'Replace the original board index with one supporting searching, sorting, infinite scrolling, and a catalog mode.'],
'Use 4chan X Catalog': [true, 'Link to 4chan X\'s catalog instead of the native 4chan one.', 1],
'External Catalog': [false, 'Link to external catalog instead of the internal one.'],
'Catalog Links': [false, 'Add toggle link in header menu to turn Navigation links into links to each board\'s catalog.'],
'Announcement Hiding': [true, 'Add button to hide 4chan announcements.'],
'Desktop Notifications': [false, 'Enables desktop notifications across various 4chan X features.'],
'404 Redirect': [true, 'Redirect dead threads and images to the archives.'],
'Except Archives from Encryption': [false, 'Permit loading content from, and warningless redirects to, HTTP-only archives from HTTPS pages.'],
'Keybinds': [true, 'Bind actions to keyboard shortcuts.'],
'Time Formatting': [true, 'Localize and format timestamps.'],
'Relative Post Dates': [true, 'Display dates like "3 minutes ago". Tooltip shows the timestamp.'],
'Relative Date Title': [true, 'Show Relative Post Date only when hovering over dates.', 1],
'Comment Expansion': [true, 'Expand comments that are too long to display on the index. Not applicable with JSON Navigation.'],
'File Info Formatting': [true, 'Reformat the file information.'],
'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.'],
'Custom Board Titles': [true, 'Allow editing of the board title and subtitle by ctrl/\u2318+clicking them.'],
'Persistent Custom Board Titles': [false, 'Force custom board titles to be persistent, even if the board titles are updated.', 1],
'Show Updated Notifications': [true, 'Show notifications when 4chan X is successfully updated.'],
'Color User IDs': [false, 'Assign unique colors to user IDs on boards that use them'],
'Remove Spoilers': [false, 'Remove all spoilers in text.'],
'Reveal Spoilers': [false, 'Indicate spoilers if Remove Spoilers is enabled, or make the text appear hovered if Remove Spoiler is disabled.'],
'Show Support Message': [true, 'Warn if your browser or configuration is unsupported and may cause 4chan X to not operate correctly.'],
'Normalize URL': [true, 'Rewrite the URL of the current page, removing stubs and changing /res/ to /thread/.'],
'Disable Autoplaying Sounds': [false, 'Prevent sounds on the page from autoplaying.'],
'Disable Native Extension': [true, '4chan X is NOT designed to work with the native extension.']
},
'Linkification': {
'Linkify': [true, 'Convert text into links where applicable.'],
'Link Title': [true, 'Replace the link of a supported site with its actual title. Currently supported: YouTube, Vimeo, SoundCloud, and Github gists.', 1],
'Embedding': [true, 'Embed supported services. Note: Some services don\'t work on HTTPS.', 1],
'Auto-embed': [false, 'Auto-embed Linkify Embeds.', 2],
'Floating Embeds': [false, 'Embed content in a frame that remains in place when the page is scrolled.', 2]
},
'Filtering': {
'Anonymize': [false, 'Make everyone Anonymous.'],
'Filter': [true, 'Self-moderation placebo.'],
'Filtered Backlinks': [false, 'When enabled, shows backlinks to filtered posts with a line-through decoration. Otherwise, hides the backlinks.', 1],
'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.'],
'Stubs': [true, 'Show stubs of hidden threads / replies.']
},
'Images and Videos': {
'Image Expansion': [true, 'Expand images / videos.'],
'Image Hover': [true, 'Show full image / video on mouseover.'],
'Image Hover in Catalog': [false, 'Show full image / video on mouseover in 4chan X catalog.'],
'Mouse Wheel Volume': [true, 'Adjust volume of hovering videos with mouse wheel.'],
'Gallery': [true, 'Adds a simple and cute image gallery.'],
'Fullscreen Gallery': [false, 'Open gallery in fullscreen mode.', 1],
'PDF in Gallery': [false, 'Show PDF files in gallery.', 1],
'Sauce': [true, 'Add sauce links to images.'],
'WEBM Metadata': [true, 'Add link to fetch title metadata from webm videos.'],
'Reveal Spoiler Thumbnails': [false, 'Replace spoiler thumbnails with the original image.'],
'Replace GIF': [false, 'Replace gif thumbnails with the actual image.'],
'Replace JPG': [false, 'Replace jpg thumbnails with the actual image.'],
'Replace PNG': [false, 'Replace png thumbnails with the actual image.'],
'Replace WEBM': [false, 'Replace webm thumbnails with the actual webm video. Probably will degrade browser performance ;)'],
'Image Prefetching': [false, 'Add link in header menu to turn on image preloading.'],
'Fappe Tyme': [false, 'Hide posts without images when header menu item is checked. *hint* *hint*'],
'Werk Tyme': [false, 'Hide all post images when header menu item is checked.'],
'Autoplay': [true, 'Videos begin playing immediately when opened.'],
'Restart when Opened': [true, 'Restart GIFs and WebMs when you hover over or expand them.'],
'Show Controls': [true, 'Show controls on videos expanded inline.'],
'Click Passthrough': [false, 'Clicks on videos trigger your browser\'s default behavior. Videos can be contracted with button / dragging to the left.', 1],
'Allow Sound': [true, 'Open videos with the sound unmuted.'],
'Loop in New Tab': [true, 'Loop videos opened in their own tabs.'],
'Volume in New Tab': [true, 'Apply 4chan X mute and volume settings to videos opened in their own tabs.']
},
'Menu': {
'Menu': [true, 'Add a drop-down menu to posts.'],
'Report Link': [true, 'Add a report link to the menu.', 1],
'Thread Hiding Link': [true, 'Add a link to hide entire threads.', 1],
'Reply Hiding Link': [true, 'Add a link to hide single replies.', 1],
'Delete Link': [true, 'Add post and image deletion links to the menu.', 1],
'Download Link': [true, 'Add a download with original filename link to the menu.', 1],
'Archive Link': [true, 'Add an archive link to the menu.', 1]
},
'Monitoring': {
'Thread Updater': [true, 'Fetch and insert new replies. Has more options in the header menu and the "Advanced" tab.'],
'Unread Count': [true, 'Show the unread posts count in the tab title.'],
'Quoted Title': [false, 'Change the page title to reflect you\'ve been quoted.', 1],
'Hide Unread Count at (0)': [false, 'Hide the unread posts count in the tab title when it reaches 0.', 1],
'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 for threads in /f/.'],
'Remove Thread Excerpt': [false, 'Replace the excerpt of the thread in the tab title with the board title.'],
'Thread Stats': [true, 'Display reply and image count.'],
'IP Count in Stats': [true, 'Display the unique IP count in the thread stats.', 1],
'Page Count in Stats': [true, 'Display the page count in the thread stats.', 1],
'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': [true, 'Adds a shortcut for the thread watcher, hides the watcher by default, and makes it scroll with the page.', 1],
'Mark New IPs': [false, 'Label each post from a new IP with the thread\'s current IP count.']
},
'Posting': {
'Quick Reply': [true, 'All-in-one form to reply, create threads, automate dumping and more.'],
'QR Shortcut': [true, 'Add a shortcut to the header to toggle the QR.', 1],
'Persistent QR': [true, 'The Quick reply won\'t disappear after posting.', 1],
'Auto Hide QR': [true, 'Automatically hide the quick reply when posting.', 1],
'Open Post in New Tab': [true, 'Open new threads or replies to a thread from the index in a new tab.', 1],
'Remember QR Size': [false, 'Remember the size of the Quick reply.', 1],
'Remember Spoiler': [false, 'Remember the spoiler state, instead of resetting after posting.', 1],
'Show New Thread Option in Threads': [false, 'Show the option to post a new / different thread from inside a thread.', 1],
'Show Name and Subject': [false, 'Show the classic name, email, and subject fields in the QR, even when 4chan doesn\'t use them all.', 1],
'Hide Original Post Form': [true, 'Hide the normal post form.', 1],
'Cooldown': [true, 'Indicate the remaining time before posting again.', 1],
'Posting Success Notifications': [true, 'Show notifications on successful post creation or file uploading.', 1],
'Force Noscript Captcha': [false, 'Use the non-Javascript fallback captcha in the QR even if Javascript is enabled.', 1],
'Captcha Warning Notifications': [true, 'When disabled, shows a red border on the CAPTCHA input until a key is pressed instead of a notification.', 1],
'Auto-load captcha': [false, 'Automatically load the captcha in the QR even if your post is empty.', 1],
'Post on Captcha Completion': [false, 'Submit the post immediately when the captcha is completed.', 1],
'Bottom QR Link': [true, 'Places a link on the bottom of threads to open the QR.', 1]
},
'Quote Links': {
'Quote Backlinks': [true, 'Add quote backlinks.'],
'OP Backlinks': [true, 'Add backlinks to the OP.', 1],
'Quote Inlining': [true, 'Inline quoted post on click.'],
'Quote Hash Navigation': [false, 'Include an extra link after quotes for autoscrolling to quoted posts.', 1],
'Forward Hiding': [true, 'Hide original posts of inlined backlinks.', 1],
'Quote Previewing': [true, 'Show quoted post on hover.'],
'Quote Highlighting': [true, 'Highlight the previewed post.', 1],
'Resurrect Quotes': [true, 'Link dead quotes to the archives.'],
'Mark Quotes of You': [true, 'Add \'(You)\' to quotes linking to your posts.'],
'Highlight Posts Quoting You': [false, 'Highlights any posts that contain a quote to your post.', 1],
'Highlight Own Posts': [false, 'Highlights own posts if Mark Quotes of You is enabled.', 1],
'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, ''],
'Scroll into view': [true, 'Scroll down when expanding images to bring the full image into view.'],
'Expand spoilers': [true, 'Expand all images along with spoilers.'],
'Expand videos': [true, 'Expand all images also expands videos.'],
'Expand from here': [false, 'Expand all images only from current position to thread end.'],
'Advance on contract': [false, 'Advance to next post when contracting an expanded image.']
},
gallery: {
'Hide Thumbnails': [false],
'Fit Width': [true],
'Fit Height': [true],
'Scroll to Post': [true],
'Slide Delay': [6.0]
},
'Default Volume': 1.0,
threadWatcher: {
'Current Board': [false, 'Only show watched threads from the current board.'],
'Auto Update Thread Watcher': [true, 'Periodically check status of watched threads.'],
'Auto Watch': [false, 'Automatically watch threads you start.'],
'Auto Watch Reply': [false, 'Automatically watch threads you reply to.'],
'Auto Prune': [false, 'Automatically remove dead threads.'],
'Show Unread Count': [true, 'Show number of unread posts in watched threads.']
},
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",
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#//saucenao.com/search.php?url=%TURL\n#http://3d.iqdb.org/?url=%TURL\n#http://regex.info/exif.cgi?imgurl=%URL\n# uploaders:\n#//imgur.com/upload?url=%URL;text:Upload to imgur\n# \"View Same\" in archives:\n#https://archive.moe/_/search/image/%MD5/;text:View same on archive.moe\n#https://archive.moe/%board/search/image/%MD5/;text:View same on archive.moe/%board/;boards:a,biz,c,co,diy,gd,h,i,jp,k,m,mlp,po,qa,s4s,sci,tg,u,v,vg,vp,vr,wsg\n#https://rbt.asia/%board/image/%MD5;text:View same on RBT /%board/;boards:cgl,g,mu,qa,w\n# Search with full image only for image file types:\n#https://www.google.com/searchbyimage?image_url=%URL;types:gif,jpg,png\n#https://www.google.com/searchbyimage?image_url=%TURL;types:webm,pdf",
FappeT: {
werk: false
},
'Custom CSS': false,
Index: {
'Index Mode': 'paged',
'Previous Index Mode': 'paged',
'Index Sort': 'bump',
'Index Size': 'small',
'Show Replies': true,
'Pin Watched Threads': false,
'Anchor Hidden Threads': true,
'Refreshed Navigation': false
},
Header: {
'Fixed Header': true,
'Header auto-hide': false,
'Header auto-hide on scroll': false,
'Bottom Header': false,
'Centered links': false,
'Header catalog links': false,
'Bottom Board List': true,
'Shortcut Icons': true,
'Custom Board Navigation': true
},
boardnav: "[ toggle-all ]\na-replace\nc-replace\ng-replace\nk-replace\nv-replace\nvg-replace\nvr-replace\nck-replace\nco-replace\nfit-replace\njp-replace\nmu-replace\nsp-replace\ntv-replace\nvp-replace\n[external-text:\"FAQ\",\"https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions\"]",
QR: {
'QR.personas': "#options:\"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': ['q', 'Open QR without post number inserted.'],
'Open QR': ['Shift+q', 'Open QR with post number inserted.'],
'Open settings': ['Alt+o', 'Open Settings.'],
'Close': ['Esc', 'Close dialogs or notifications.'],
'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 options field.'],
'Submit QR': ['Ctrl+Enter', 'Submit post.'],
'Watch': ['w', 'Watch thread.'],
'Update': ['r', 'Update the thread / refresh the index.'],
'Expand image': ['Shift+e', 'Expand selected image.'],
'Expand images': ['e', 'Expand all images.'],
'Open Gallery': ['g', 'Opens the gallery.'],
'Pause': ['p', 'Pause/play videos in the gallery.'],
'Slideshow': ['s', 'Toggle the gallery slideshow mode.'],
'fappeTyme': ['f', 'Toggle Fappe Tyme.'],
'werkTyme': ['Shift+w', 'Toggle Werk Tyme.'],
'Front page': ['1', 'Jump to front page.'],
'Open front page': ['Shift+1', 'Open front page in a new tab.'],
'Next page': ['Ctrl+Right', 'Jump to the next page.'],
'Previous page': ['Ctrl+Left', 'Jump to the previous page.'],
'Paged mode': ['Alt+1', 'Open the index in paged mode.'],
'Infinite scrolling mode': ['Alt+2', 'Open the index in infinite scrolling mode.'],
'All pages mode': ['Alt+3', 'Open the index in all threads mode.'],
'Open catalog': ['Shift+c', 'Open the catalog of the current board.'],
'Search form': ['Ctrl+Alt+s', 'Focus the search field on the board index.'],
'Cycle sort type': ['Alt+x', 'Cycle through index sort types.'],
'Next thread': ['Ctrl+Down', 'See next thread.'],
'Previous thread': ['Ctrl+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.'],
'Deselect reply': ['Shift+d', 'Deselect reply.'],
'Hide': ['x', 'Hide thread.'],
'Previous Post Quoting You': ['Alt+Up', 'Scroll to the previous post that quotes you.'],
'Next Post Quoting You': ['Alt+Down', 'Scroll to the next post that quotes you.']
},
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.10.0.5',
NAMESPACE: '4chan X.',
NAME: '4chan X',
FAQ: 'https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions',
CHANGELOG: 'https://github.com/ccd0/4chan-x/blob/master/CHANGELOG.md',
boards: {}
};
E = (function() {
var fn, r, regex, str;
str = {
'&': '&',
"'": ''',
'"': '"',
'<': '<',
'>': '>'
};
r = String.prototype.replace;
regex = /[&"'<>]/g;
fn = function(x) {
return str[x];
};
return function(text) {
return r.call(text, regex, fn);
};
})();
$ = function(selector, root) {
if (root == null) {
root = d.body;
}
return root.querySelector(selector);
};
$.DAY = 24 * ($.HOUR = 60 * ($.MINUTE = 60 * ($.SECOND = 1000)));
$.id = function(id) {
return d.getElementById(id);
};
$.ready = function(fc) {
var cb;
if (d.readyState !== 'loading') {
$.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) {
if (typeof val === 'object' && 'newName' in val) {
fd.append(key, val, val.newName);
} else {
fd.append(key, val);
}
}
}
return fd;
};
$.extend = function(object, properties) {
var key, val;
for (key in properties) {
val = properties[key];
object[key] = val;
}
};
$.ajax = (function() {
var blockedError, blockedURLs, lastModified;
lastModified = {};
blockedURLs = {};
blockedError = function(url) {
var message;
if (blockedURLs[url]) {
return;
}
blockedURLs[url] = true;
message = $.el('div', {
innerHTML: E(g.NAME) + " was blocked from loading the following URL:<br><span></span><br>[<a href=\"" + E(g.FAQ) + "#why-was-4chan-x-blocked-from-loading-a-url\" target=\"_blank\">More info</a>]"
});
$('span', message).textContent = (/^\/\//.test(url) ? location.protocol : '') + url;
return new Notice('error', message, 30, function() {
return delete blockedURLs[url];
});
};
return function(url, options, extra) {
var err, form, r, type, upCallbacks, whenModified;
if (extra == null) {
extra = {};
}
type = extra.type, whenModified = extra.whenModified, upCallbacks = extra.upCallbacks, form = extra.form;
r = new XMLHttpRequest();
type || (type = form && 'post' || 'get');
try {
r.open(type, url, true);
} catch (_error) {
err = _error;
blockedError(url);
if (typeof options.onerror === "function") {
options.onerror();
}
return;
}
if (whenModified) {
if (url in lastModified) {
r.setRequestHeader('If-Modified-Since', lastModified[url]);
}
$.on(r, 'load', function() {
return lastModified[url] = r.getResponseHeader('Last-Modified');
});
}
if (/\.json$/.test(url)) {
r.responseType = 'json';
}
$.extend(r, options);
$.extend(r.upload, upCallbacks);
r.send(form);
return r;
};
})();
(function() {
var reqs;
reqs = {};
$.cache = function(url, cb, options) {
var err, req, rm;
if (req = reqs[url]) {
if (req.readyState === 4) {
$.queueTask(function() {
return cb.call(req, req.evt);
});
} else {
req.callbacks.push(cb);
}
return req;
}
rm = function() {
return delete reqs[url];
};
try {
if (!(req = $.ajax(url, options))) {
return;
}
} catch (_error) {
err = _error;
return;
}
$.on(req, 'load', 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;
this.cached = true;
return delete this.callbacks;
});
$.on(req, 'abort error', rm);
req.callbacks = [cb];
return reqs[url] = req;
};
return $.cleanCache = function(testf) {
var url;
for (url in reqs) {
if (testf(url)) {
delete reqs[url];
}
}
};
})();
$.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);
}
};
$.onExists = function(root, selector, subtree, cb) {
var el, observer;
if (el = $(selector, root)) {
return cb(el);
}
observer = new MutationObserver(function() {
if (el = $(selector, root)) {
observer.disconnect();
return cb(el);
}
});
return observer.observe(root, {
childList: true,
subtree: subtree
});
};
$.addStyle = function(css, id, test) {
var style;
style = $.el('style', {
id: id,
textContent: css
});
$.asap((function() {
return d.head && ((test == null) || test());
}), 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, 7, null);
};
$.addClass = function() {
var className, classNames, el, _i, _len;
el = arguments[0], classNames = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
for (_i = 0, _len = classNames.length; _i < _len; _i++) {
className = classNames[_i];
el.classList.add(className);
}
};
$.rmClass = function() {
var className, classNames, el, _i, _len;
el = arguments[0], classNames = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
for (_i = 0, _len = classNames.length; _i < _len; _i++) {
className = classNames[_i];
el.classList.remove(className);
}
};
$.toggleClass = function(el, className) {
return el.classList.toggle(className);
};
$.hasClass = function(el, className) {
return __indexOf.call(el.classList, className) >= 0;
};
$.rm = function(el) {
return el.remove();
};
$.rmAll = function(root) {
return root.textContent = null;
};
$.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);
}
};
$.one = function(el, events, handler) {
var cb;
cb = function(e) {
$.off(el, events, cb);
return handler.call(this, e);
};
return $.on(el, events, cb);
};
$.event = function(event, detail, root) {
if (root == null) {
root = d;
}
if ((detail != null) && typeof cloneInto === 'function') {
detail = cloneInto(detail, d.defaultView);
}
return root.dispatchEvent(new CustomEvent(event, {
bubbles: true,
detail: detail
}));
};
$.open = GM_openInTab;
$.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);
};
$.hasAudio = function(video) {
return video.mozHasAudio || !!video.webkitAudioDecodedByteCount;
};
$.item = function(key, val) {
var item;
item = {};
item[key] = val;
return item;
};
$.syncing = {};
$.oldValue = {};
$.sync = function(key, cb) {
key = g.NAMESPACE + key;
$.syncing[key] = cb;
return $.oldValue[key] = GM_getValue(key);
};
(function() {
var onChange;
onChange = function(key) {
var cb, newValue;
if (!(cb = $.syncing[key])) {
return;
}
newValue = GM_getValue(key);
if (newValue === $.oldValue[key]) {
return;
}
if (newValue != null) {
$.oldValue[key] = newValue;
return cb(JSON.parse(newValue), key);
} else {
delete $.oldValue[key];
return cb(void 0, key);
}
};
$.on(window, 'storage', function(_arg) {
var key;
key = _arg.key;
return onChange(key);
});
return $.forceSync = function(key) {
return onChange(g.NAMESPACE + key);
};
})();
$["delete"] = function(keys) {
var key, _i, _len;
if (!(keys instanceof Array)) {
keys = [keys];
}
for (_i = 0, _len = keys.length; _i < _len; _i++) {
key = keys[_i];
key = g.NAMESPACE + key;
GM_deleteValue(key);
if (key in $.syncing) {
delete $.oldValue[key];
localStorage.removeItem(key);
}
}
};
$.get = function(key, val, cb) {
var items;
if (typeof cb === 'function') {
items = $.item(key, val);
} else {
items = key;
cb = val;
}
return $.queueTask(function() {
for (key in items) {
if (val = GM_getValue(g.NAMESPACE + key)) {
items[key] = JSON.parse(val);
}
}
return cb(items);
});
};
$.set = (function() {
var set;
set = function(key, val) {
key = g.NAMESPACE + key;
val = JSON.stringify(val);
GM_setValue(key, val);
if (key in $.syncing) {
$.oldValue[key] = val;
return localStorage.setItem(key, val);
}
};
return function(keys, val) {
var key;
if (typeof keys === 'string') {
set(keys, val);
return;
}
for (key in keys) {
val = keys[key];
set(key, val);
}
};
})();
$.clear = function(cb) {
var a, board, boards, err, id;
try {
$["delete"](GM_listValues().map(function(key) {
return key.replace(g.NAMESPACE, '');
}));
} catch (_error) {
err = _error;
$["delete"](Object.keys(Conf));
$["delete"](['previousversion', 'AutoWatch', 'cooldown.global', 'QR Size', 'captchas', 'QR.persona', 'hiddenPSA']);
$["delete"]((function() {
var _i, _len, _ref, _results;
_ref = ['embedding', 'updater', 'thread-stats', 'thread-watcher', 'qr'];
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
id = _ref[_i];
_results.push("" + id + ".position");
}
return _results;
})());
boards = (function() {
var _i, _len, _ref, _results;
_ref = $$('#boardNavDesktop > .boardList > a');
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
a = _ref[_i];
_results.push(a.textContent);
}
return _results;
})();
boards.push('qa');
$["delete"]((function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = boards.length; _i < _len; _i++) {
board = boards[_i];
_results.push("cooldown." + board);
}
return _results;
})());
}
return typeof cb === "function" ? cb() : void 0;
};
$$ = function(selector, root) {
if (root == null) {
root = d.body;
}
return __slice.call(root.querySelectorAll(selector));
};
Callbacks = (function() {
function Callbacks(type) {
this.type = type;
this.keys = [];
}
Callbacks.prototype.push = function(_arg) {
var cb, name;
name = _arg.name, cb = _arg.cb;
if (!this[name]) {
this.keys.push(name);
}
return this[name] = cb;
};
Callbacks.prototype.execute = function(node) {
var err, errors, name, _i, _len, _ref;
_ref = this.keys;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
name = _ref[_i];
try {
this[name].call(node);
} catch (_error) {
err = _error;
if (!errors) {
errors = [];
}
errors.push({
message: ['"', name, '" crashed on node ', this.type, ' No.', node.ID, ' (', node.board, ').'].join(''),
error: err
});
}
}
if (errors) {
return Main.handleErrors(errors);
}
};
return Callbacks;
})();
Board = (function() {
Board.prototype.toString = function() {
return this.ID;
};
function Board(ID) {
this.ID = ID;
this.threads = new SimpleDict();
this.posts = new SimpleDict();
g.boards[this] = this;
}
return Board;
})();
Thread = (function() {
Thread.callbacks = new Callbacks('Thread');
Thread.prototype.toString = function() {
return this.ID;
};
function Thread(ID, board) {
this.ID = ID;
this.board = board;
this.fullID = "" + this.board + "." + this.ID;
this.posts = new SimpleDict();
this.isDead = false;
this.isHidden = false;
this.isOnTop = false;
this.isSticky = false;
this.isClosed = false;
this.isArchived = false;
this.postLimit = false;
this.fileLimit = false;
this.ipCount = void 0;
this.OP = null;
this.catalogView = null;
g.threads.push(this.fullID, board.threads.push(this, this));
}
Thread.prototype.setPage = function(pageNum) {
var icon, info, quote, _ref;
_ref = this.OP.nodes, info = _ref.info, quote = _ref.quote;
if (!(icon = $('.page-num', info))) {
icon = $.el('span', {
className: 'page-num'
});
$.after(quote, [$.tn(' '), icon]);
}
icon.title = "This thread is on page " + pageNum + " in the original index.";
icon.textContent = "[" + pageNum + "]";
if (this.catalogView) {
return this.catalogView.nodes.pageCount.textContent = pageNum;
}
};
Thread.prototype.setCount = function(type, count, reachedLimit) {
var el;
if (!this.catalogView) {
return;
}
el = this.catalogView.nodes["" + type + "Count"];
el.textContent = count;
return (reachedLimit ? $.addClass : $.rmClass)(el, 'warning');
};
Thread.prototype.setStatus = function(type, status) {
var name;
name = "is" + type;
if (this[name] === status) {
return;
}
this[name] = status;
if (!this.OP) {
return;
}
this.setIcon('Sticky', this.isSticky);
this.setIcon('Closed', this.isClosed && !this.isArchived);
return this.setIcon('Archived', this.isArchived);
};
Thread.prototype.setIcon = function(type, status) {
var icon, root, typeLC;
typeLC = type.toLowerCase();
icon = $("." + typeLC + "Icon", this.OP.nodes.info);
if (!!icon === status) {
return;
}
if (!status) {
$.rm(icon.previousSibling);
$.rm(icon);
if (this.catalogView) {
$.rm($("." + typeLC + "Icon", this.catalogView.nodes.icons));
}
return;
}
icon = $.el('img', {
src: "" + Build.staticPath + typeLC + Build.gifIcon,
alt: type,
title: type,
className: "" + typeLC + "Icon retina"
});
root = type !== 'Sticky' && this.isSticky ? $('.stickyIcon', this.OP.nodes.info) : $('.page-num', this.OP.nodes.info) || this.OP.nodes.quote;
$.after(root, [$.tn(' '), icon]);
if (!this.catalogView) {
return;
}
return (type === 'Sticky' && this.isClosed ? $.prepend : $.add)(this.catalogView.nodes.icons, icon.cloneNode());
};
Thread.prototype.kill = function() {
return this.isDead = true;
};
Thread.prototype.collect = function() {
this.posts.forEach(function(post) {
return post.collect();
});
g.threads.rm(this.fullID);
return this.board.threads.rm(this);
};
return Thread;
})();
CatalogThread = (function() {
CatalogThread.callbacks = new Callbacks('Catalog Thread');
CatalogThread.prototype.toString = function() {
return this.ID;
};
function CatalogThread(root, thread) {
this.thread = thread;
this.ID = this.thread.ID;
this.board = this.thread.board;
this.nodes = {
root: root,
thumb: $('.catalog-thumb', root),
icons: $('.catalog-icons', root),
postCount: $('.post-count', root),
fileCount: $('.file-count', root),
pageCount: $('.page-count', root),
comment: $('.comment', root)
};
this.thread.catalogView = this;
}
return CatalogThread;
})();
Post = (function() {
Post.callbacks = new Callbacks('Post');
Post.prototype.toString = function() {
return this.ID;
};
function Post(root, thread, board, that) {
var capcode, clone, date, email, flag, info, name, post, subject, tripcode, uniqueID, _i, _len, _ref;
this.thread = thread;
this.board = board;
if (that == null) {
that = {};
}
this.ID = +root.id.slice(2);
this.fullID = "" + this.board + "." + this.ID;
if (that.isOriginalMarkup) {
this.cleanup(root);
}
post = $('.post', root);
info = $('.postInfo', post);
this.nodes = {
root: root,
post: post,
info: info,
nameBlock: $('.nameBlock', info),
quote: $('.postNum > a:nth-of-type(2)', info),
comment: $('.postMessage', post),
links: [],
quotelinks: [],
backlinks: info.getElementsByClassName('backlink')
};
if (!(this.isReply = $.hasClass(post, 'reply'))) {
this.thread.OP = this;
this.thread.isArchived = !!$('.archivedIcon', info);
this.thread.isSticky = !!$('.stickyIcon', info);
this.thread.isClosed = this.thread.isArchived || !!$('.closedIcon', info);
if (this.thread.isArchived) {
this.thread.kill();
}
}
this.info = {};
this.info.nameBlock = Conf['Anonymize'] ? 'Anonymous' : this.nodes.nameBlock.textContent.trim();
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 = $('.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);
}
this.parseComment();
this.parseQuotes();
this.parseFile(that);
this.isDead = false;
this.isHidden = false;
this.clones = [];
if (g.posts[this.fullID]) {
this.isRebuilt = true;
this.clones = g.posts[this.fullID].clones;
_ref = this.clones;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
clone = _ref[_i];
clone.origin = this;
}
}
g.posts.push(this.fullID, thread.posts.push(this, board.posts.push(this, this)));
if (that.isArchived) {
this.kill();
}
}
Post.prototype.parseComment = function() {
var bq, node, spoilers, _i, _len, _ref;
this.nodes.comment.normalize();
bq = this.nodes.comment.cloneNode(true);
_ref = $$('.abbr, .exif, b, marquee', bq);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
node = _ref[_i];
$.rm(node);
}
this.info.comment = this.nodesToText(bq);
spoilers = $$('s', bq);
return this.info.commentSpoilered = (function() {
var _j, _len1;
if (spoilers.length) {
for (_j = 0, _len1 = spoilers.length; _j < _len1; _j++) {
node = spoilers[_j];
$.replace(node, $.tn('[spoiler]'));
}
return this.nodesToText(bq);
} else {
return this.info.comment;
}
}).call(this);
};
Post.prototype.nodesToText = function(bq) {
var i, node, nodes, text;
text = "";
nodes = $.X('.//br|.//text()', bq);
i = 0;
while (node = nodes.snapshotItem(i++)) {
text += node.data || '\n';
}
return text.trim().replace(/\s+$/gm, '');
};
Post.prototype.parseQuotes = function() {
var quotelink, _i, _len, _ref;
this.quotes = [];
_ref = $$(':not(pre) > .quotelink', this.nodes.comment);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
quotelink = _ref[_i];
this.parseQuote(quotelink);
}
};
Post.prototype.parseQuote = function(quotelink) {
var fullID, match;
if (!(match = quotelink.href.match(/boards\.4chan\.org\/([^\/]+)\/(?:res|thread)\/\d+(?:\/[^#]*)?#p(\d+)$/))) {
return;
}
this.nodes.quotelinks.push(quotelink);
if (this.isClone) {
return;
}
fullID = "" + match[1] + "." + match[2];
if (__indexOf.call(this.quotes, fullID) < 0) {
return this.quotes.push(fullID);
}
};
Post.prototype.parseFile = function(that) {
var anchor, fileEl, fileText, nameNode, size, thumb, unit;
if (!((fileEl = $('.file', this.nodes.post)) && (thumb = $('img[data-md5]', fileEl)))) {
return;
}
anchor = thumb.parentNode;
fileText = fileEl.firstElementChild;
this.file = {
text: fileText,
thumb: thumb,
URL: anchor.href,
size: thumb.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 = "" + location.protocol + "//i.4cdn.org/" + this.board + "/" + (this.file.URL.match(/(\d+)\./)[1]) + "s.jpg";
this.file.isImage = /(jpg|png|gif)$/i.test(this.file.URL);
this.file.isVideo = /webm$/i.test(this.file.URL);
nameNode = $('a', fileText);
if (this.file.isImage || this.file.isVideo) {
this.file.dimensions = nameNode.nextSibling.textContent.match(/\d+x\d+/)[0];
}
return this.file.name = fileText.title || nameNode.title || nameNode.textContent;
};
Post.prototype.cleanup = function(root) {
var node, _i, _j, _len, _len1, _ref, _ref1;
_ref = $$('.mobile', root);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
node = _ref[_i];
$.rm(node);
}
_ref1 = $$('.desktop', root);
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
node = _ref1[_j];
$.rmClass(node, 'desktop');
}
};
Post.prototype.kill = function(file) {
var clone, quotelink, strong, _i, _j, _len, _len1, _ref, _ref1;
if (file) {
if (this.file.isDead) {
return;
}
this.file.isDead = true;
$.addClass(this.nodes.root, 'deleted-file');
} else {
if (this.isDead) {
return;
}
this.isDead = true;
$.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);
}
if (file) {
return;
}
_ref1 = Get.allQuotelinksLinkingTo(this);
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
quotelink = _ref1[_j];
if (!(!$.hasClass(quotelink, 'deadlink'))) {
continue;
}
quotelink.textContent = quotelink.textContent + '\u00A0(Dead)';
$.addClass(quotelink, 'deadlink');
}
};
Post.prototype.resurrect = function() {
var clone, quotelink, strong, _i, _j, _len, _len1, _ref, _ref1;
delete this.isDead;
$.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'))) {
continue;
}
quotelink.textContent = quotelink.textContent.replace('\u00A0(Dead)', '');
$.rmClass(quotelink, 'deadlink');
}
};
Post.prototype.collect = function() {
this.kill();
g.posts.rm(this.fullID);
this.thread.posts.rm(this);
return this.board.posts.rm(this);
};
Post.prototype.addClone = function(context, contractThumb) {
return new Clone(this, context, contractThumb);
};
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.dataset.clone = index++;
}
};
return Post;
})();
Clone = (function(_super) {
__extends(Clone, _super);
function Clone(origin, context, contractThumb) {
var file, info, inline, inlined, key, nodes, post, root, val, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3;
this.origin = origin;
this.context = context;
_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 = contractThumb ? this.cloneWithoutVideo(nodes.root) : nodes.root.cloneNode(true);
post = $('.post', root);
info = $('.postInfo', post);
this.nodes = {
root: root,
post: post,
info: info,
nameBlock: $('.nameBlock', info),
quote: $('.postNum > a:nth-of-type(2)', 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.hand', info);
}
if (nodes.flag) {
this.nodes.flag = $('.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.text = file.firstElementChild;
this.file.thumb = $('.fileThumb > [data-md5]', file);
this.file.fullImage = $('.full-image', file);
this.file.videoControls = $('.video-controls', this.file.text);
if (this.file.videoThumb) {
this.file.thumb.muted = true;
}
if (contractThumb) {
ImageExpand.contract(this);
}
}
if (origin.isDead) {
this.isDead = true;
}
this.isClone = true;
root.dataset.clone = origin.clones.push(this) - 1;
}
Clone.prototype.cloneWithoutVideo = function(node) {
var child, clone, _i, _len, _ref;
if (node.tagName === 'VIDEO' && !node.dataset.md5) {
return [];
} else if (node.nodeType === Node.ELEMENT_NODE && $('video', node)) {
clone = node.cloneNode(false);
_ref = node.childNodes;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
child = _ref[_i];
$.add(clone, this.cloneWithoutVideo(child));
}
return clone;
} else {
return node.cloneNode(true);
}
};
return Clone;
})(Post);
DataBoard = (function() {
DataBoard.keys = ['hiddenThreads', 'hiddenPosts', 'lastReadPosts', 'yourPosts', 'watchedThreads', 'customTitles'];
function DataBoard(key, sync, dontClean) {
var init;
this.key = key;
this.onSync = __bind(this.onSync, this);
this.data = Conf[key];
$.sync(key, this.onSync);
if (!dontClean) {
this.clean();
}
if (!sync) {
return;
}
init = (function(_this) {
return function() {
$.off(d, '4chanXInitFinished', init);
return _this.sync = sync;
};
})(this);
$.on(d, '4chanXInitFinished', init);
}
DataBoard.prototype.save = function() {
return $.set(this.key, this.data);
};
DataBoard.prototype["delete"] = function(_arg) {
var boardID, postID, threadID, _ref;
boardID = _arg.boardID, threadID = _arg.threadID, postID = _arg.postID;
$.forceSync(this.key);
if (postID) {
if (!((_ref = this.data.boards[boardID]) != null ? _ref[threadID] : void 0)) {
return;
}
delete this.data.boards[boardID][threadID][postID];
this.deleteIfEmpty({
boardID: boardID,
threadID: threadID
});
} else if (threadID) {
if (!this.data.boards[boardID]) {
return;
}
delete this.data.boards[boardID][threadID];
this.deleteIfEmpty({
boardID: boardID
});
} else {
delete this.data.boards[boardID];
}
return this.save();
};
DataBoard.prototype.deleteIfEmpty = function(_arg) {
var boardID, threadID;
boardID = _arg.boardID, threadID = _arg.threadID;
$.forceSync(this.key);
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;
$.forceSync(this.key);
if (postID !== void 0) {
((_base = ((_base1 = this.data.boards)[boardID] || (_base1[boardID] = {})))[threadID] || (_base[threadID] = {}))[postID] = val;
} else if (threadID !== void 0) {
((_base2 = this.data.boards)[boardID] || (_base2[boardID] = {}))[threadID] = val;
} else {
this.data.boards[boardID] = val;
}
return this.save();
};
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.forceSync = function() {
return $.forceSync(this.key);
};
DataBoard.prototype.clean = function() {
var boardID, now, threadID, val, _ref;
$.forceSync(this.key);
_ref = this.data.boards;
for (boardID in _ref) {
val = _ref[boardID];
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) {
for (threadID in this.data.boards[boardID]) {
this.ajaxClean(boardID, threadID);
}
}
}
return this.save();
};
DataBoard.prototype.ajaxClean = function(boardID, threadID) {
return $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", {
onloadend: (function(_this) {
return function(e) {
if (e.target.status === 404) {
return _this["delete"]({
boardID: boardID,
threadID: threadID
});
}
};
})(this)
}, {
type: 'head'
});
};
DataBoard.prototype.onSync = function(data) {
this.data = data || {
boards: {}
};
return typeof this.sync === "function" ? this.sync() : void 0;
};
return DataBoard;
})();
Notice = (function() {
function Notice(type, content, timeout, onclose) {
this.timeout = timeout;
this.onclose = onclose;
this.close = __bind(this.close, this);
this.add = __bind(this.add, this);
this.el = $.el('div', {
innerHTML: "<a href=\"javascript:;\" class=\"close fa fa-times\" title=\"Close\"></a><div class=\"message\"></div>"
});
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);
}
Notice.prototype.setType = function(type) {
return this.el.className = "notification " + type;
};
Notice.prototype.add = function() {
if (d.hidden) {
$.on(d, 'visibilitychange', this.add);
return;
}
$.off(d, 'visibilitychange', this.add);
$.add(Header.noticesRoot, this.el);
this.el.clientHeight;
this.el.style.opacity = 1;
if (this.timeout) {
return setTimeout(this.close, this.timeout * $.SECOND);
}
};
Notice.prototype.close = function() {
$.off(d, 'visibilitychange', this.add);
$.rm(this.el);
return typeof this.onclose === "function" ? this.onclose() : void 0;
};
return Notice;
})();
RandomAccessList = (function() {
function RandomAccessList(items) {
var item, _i, _len;
this.length = 0;
if (items) {
for (_i = 0, _len = items.length; _i < _len; _i++) {
item = items[_i];
this.push(item);
}
}
}
RandomAccessList.prototype.push = function(data) {
var ID, item, last;
ID = data.ID;
ID || (ID = data.id);
if (this[ID]) {
return;
}
last = this.last;
this[ID] = item = {
prev: last,
next: null,
data: data,
ID: ID
};
item.prev = last;
this.last = last ? last.next = item : this.first = item;
return this.length++;
};
RandomAccessList.prototype.before = function(root, item) {
var prev;
if (item.next === root || item === root) {
return;
}
this.rmi(item);
prev = root.prev;
root.prev = item;
item.next = root;
item.prev = prev;
if (prev) {
return prev.next = item;
} else {
return this.first = item;
}
};
RandomAccessList.prototype.after = function(root, item) {
var next;
if (item.prev === root || item === root) {
return;
}
this.rmi(item);
next = root.next;
root.next = item;
item.prev = root;
item.next = next;
if (next) {
return next.prev = item;
} else {
return this.last = item;
}
};
RandomAccessList.prototype.prepend = function(item) {
var first;
first = this.first;
if (item === first || !this[item.ID]) {
return;
}
this.rmi(item);
item.next = first;
if (first) {
first.prev = item;
} else {
this.last = item;
}
this.first = item;
return delete item.prev;
};
RandomAccessList.prototype.shift = function() {
return this.rm(this.first.ID);
};
RandomAccessList.prototype.order = function() {
var item, order;
order = [item = this.first];
while (item = item.next) {
order.push(item);
}
return order;
};
RandomAccessList.prototype.rm = function(ID) {
var item;
item = this[ID];
if (!item) {
return;
}
delete this[ID];
this.length--;
this.rmi(item);
delete item.next;
return delete item.prev;
};
RandomAccessList.prototype.rmi = function(item) {
var next, prev;
prev = item.prev, next = item.next;
if (prev) {
prev.next = next;
} else {
this.first = next;
}
if (next) {
return next.prev = prev;
} else {
return this.last = prev;
}
};
return RandomAccessList;
})();
SimpleDict = (function() {
function SimpleDict() {
this.keys = [];
}
SimpleDict.prototype.push = function(key, data) {
key = "" + key;
if (!this[key]) {
this.keys.push(key);
}
return this[key] = data;
};
SimpleDict.prototype.rm = function(key) {
var i;
key = "" + key;
if ((i = this.keys.indexOf(key)) !== -1) {
this.keys.splice(i, 1);
return delete this[key];
}
};
SimpleDict.prototype.forEach = function(fn) {
var key, _i, _len, _ref;
_ref = __slice.call(this.keys);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
key = _ref[_i];
fn(this[key]);
}
};
return SimpleDict;
})();
ShimSet = (function() {
function ShimSet() {
this.elements = {};
this.size = 0;
}
ShimSet.prototype.has = function(value) {
return value in this.elements;
};
ShimSet.prototype.add = function(value) {
if (this.elements[value]) {
return;
}
this.elements[value] = true;
return this.size++;
};
ShimSet.prototype["delete"] = function(value) {
if (!this.elements[value]) {
return;
}
delete this.elements[value];
return this.size--;
};
return ShimSet;
})();
if (!('Set' in window)) {
window.Set = ShimSet;
}
Connection = (function() {
function Connection(target, origin, cb) {
this.target = target;
this.origin = origin;
this.cb = cb;
this.onMessage = __bind(this.onMessage, this);
this.send = __bind(this.send, this);
$.on(window, 'message', this.onMessage);
}
Connection.prototype.send = function(data) {
return this.target.postMessage("" + g.NAMESPACE + (JSON.stringify(data)), this.origin);
};
Connection.prototype.onMessage = function(e) {
var data, type, value, _base;
if (!(e.source === this.target && e.origin === this.origin && typeof e.data === 'string' && e.data.slice(0, g.NAMESPACE.length) === g.NAMESPACE)) {
return;
}
data = JSON.parse(e.data.slice(g.NAMESPACE.length));
for (type in data) {
value = data[type];
if (typeof (_base = this.cb)[type] === "function") {
_base[type](value);
}
}
};
return Connection;
})();
Fetcher = (function() {
function Fetcher(boardID, threadID, postID, root, context) {
var post;
this.boardID = boardID;
this.threadID = threadID;
this.postID = postID;
this.root = root;
this.context = context;
if (post = g.posts["" + this.boardID + "." + this.postID]) {
this.insert(post);
return;
}
this.root.textContent = "Loading post No." + this.postID + "...";
if (this.threadID) {
$.cache("//a.4cdn.org/" + this.boardID + "/thread/" + this.threadID + ".json", (function(self) {
return function() {
return self.fetchedPost(this);
};
})(this));
} else {
this.archivedPost();
}
}
Fetcher.prototype.insert = function(post) {
var clone, nodes;
if (!this.root.parentNode) {
return;
}
clone = post.addClone(this.context, $.hasClass(this.root, 'dialog'));
Main.callbackNodes(Clone, [clone]);
nodes = clone.nodes;
$.rmAll(nodes.root);
$.add(nodes.root, nodes.post);
$.rmAll(this.root);
$.add(this.root, nodes.root);
return $.event('PostsInserted');
};
Fetcher.prototype.fetchedPost = function(req) {
var api, board, post, posts, status, thread, _i, _len;
if (post = g.posts["" + this.boardID + "." + this.postID]) {
this.insert(post);
return;
}
status = req.status;
if (status !== 200 && status !== 304) {
if (this.archivedPost()) {
return;
}
$.addClass(this.root, 'warning');
this.root.textContent = status === 404 ? "Thread No." + this.threadID + " 404'd." : "Error " + req.statusText + " (" + req.status + ").";
return;
}
posts = req.response.posts;
Build.spoilerRange[this.boardID] = posts[0].custom_spoiler;
for (_i = 0, _len = posts.length; _i < _len; _i++) {
post = posts[_i];
if (post.no === this.postID) {
break;
}
}
if (post.no !== this.postID) {
if (req.cached) {
api = "//a.4cdn.org/" + this.boardID + "/thread/" + this.threadID + ".json";
$.cleanCache(function(url) {
return url === api;
});
$.cache(api, (function(self) {
return function() {
return self.fetchedPost(this);
};
})(this));
return;
}
if (this.archivedPost()) {
return;
}
$.addClass(this.root, 'warning');
this.root.textContent = "Post No." + this.postID + " was not found.";
return;
}
board = g.boards[this.boardID] || new Board(this.boardID);
thread = g.threads["" + this.boardID + "." + this.threadID] || new Thread(this.threadID, board);
post = new Post(Build.postFromObject(post, this.boardID), thread, board);
post.isFetchedQuote = true;
Main.callbackNodes(Post, [post]);
return this.insert(post);
};
Fetcher.prototype.archivedPost = function() {
var url;
if (!Conf['Resurrect Quotes']) {
return false;
}
if (!(url = Redirect.to('post', {
boardID: this.boardID,
postID: this.postID
}))) {
return false;
}
if (/^https:\/\//.test(url) || location.protocol === 'http:') {
$.cache(url, (function(self) {
return function() {
return self.parseArchivedPost(this.response);
};
})(this), {
responseType: 'json',
withCredentials: url.archive.withCredentials
});
return true;
} else if (Conf['Except Archives from Encryption']) {
CrossOrigin.json(url, (function(_this) {
return function(response) {
var key, media, _ref;
media = response.media;
if (media) {
for (key in media) {
if (/_link$/.test(key)) {
if (!((media[key] != null) && (_ref = media[key].match(/^(http:\/\/[^\/]+\/)?/)[0], __indexOf.call(url.archive.imagehosts, _ref) >= 0))) {
delete media[key];
}
}
}
}
return _this.parseArchivedPost(response);
};
})(this));
return true;
}
return false;
};
Fetcher.prototype.parseArchivedPost = function(data) {
var board, comment, greentext, i, j, o, post, text, text2, thread, _ref;
if (post = g.posts["" + this.boardID + "." + this.postID]) {
this.insert(post);
return;
}
if (data.error) {
$.addClass(this.root, 'warning');
this.root.textContent = data.error;
return;
}
comment = (data.comment || '').split(/(\n|\[\/?(?:b|spoiler|code|moot|banned)\])/);
comment = (function() {
var _i, _len, _results;
_results = [];
for (i = _i = 0, _len = comment.length; _i < _len; i = ++_i) {
text = comment[i];
if (i % 2 === 1) {
_results.push(this.archiveTags[text]);
} else {
greentext = text[0] === '>';
text = text.replace(/(\[\/?[a-z]+):lit(\])/, '$1$2');
text = (function() {
var _j, _len1, _ref, _results1;
_ref = text.split(/(>>(?:>\/[a-z\d]+\/)?\d+)/g);
_results1 = [];
for (j = _j = 0, _len1 = _ref.length; _j < _len1; j = ++_j) {
text2 = _ref[j];
if (j % 2 === 1) {
_results1.push({
innerHTML: "<span class=\"deadlink\">" + E(text2) + "</span>"
});
} else {
_results1.push({
innerHTML: E(text2)
});
}
}
return _results1;
})();
text = {
innerHTML: text.map(function(x) {
return x.innerHTML;
}).join('')
};
if (greentext) {
text = {
innerHTML: "<span class=\"quote\">" + text.innerHTML + "</span>"
};
}
_results.push(text);
}
}
return _results;
}).call(this);
comment = {
innerHTML: comment.map(function(x) {
return x.innerHTML;
}).join('')
};
this.threadID = +data.thread_num;
o = {
postID: this.postID,
threadID: this.threadID,
boardID: this.boardID,
name: data.name,
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 || '',
subject: data.title,
flagCode: data.poster_country,
flagName: data.poster_country_name,
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,
timestamp: data.media.media_orig,
url: data.media.media_link || data.media.remote_media_link || ("//i.4cdn.org/" + this.boardID + "/" + (encodeURIComponent(data.media[this.boardID === 'f' ? 'media_filename' : 'media_orig']))),
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 || ("//i.4cdn.org/" + this.boardID + "/" + data.media.preview_orig),
theight: data.media.preview_h,
twidth: data.media.preview_w,
isSpoiler: data.media.spoiler === '1'
};
if (this.boardID === 'f') {
o.file.tag = JSON.parse(data.media.exif).Tag;
}
}
board = g.boards[this.boardID] || new Board(this.boardID);
thread = g.threads["" + this.boardID + "." + this.threadID] || new Thread(this.threadID, board);
post = new Post(Build.post(o), thread, board, {
isArchived: true
});
if (post.file) {
post.file.thumbURL = o.file.turl;
}
post.isFetchedQuote = true;
Main.callbackNodes(Post, [post]);
return this.insert(post);
};
Fetcher.prototype.archiveTags = {
'\n': {
innerHTML: "<br>"
},
'[b]': {
innerHTML: "<b>"
},
'[/b]': {
innerHTML: "</b>"
},
'[spoiler]': {
innerHTML: "<s>"
},
'[/spoiler]': {
innerHTML: "</s>"
},
'[code]': {
innerHTML: "<pre class=\"prettyprint\">"
},
'[/code]': {
innerHTML: "</pre>"
},
'[moot]': {
innerHTML: "<div style=\"padding:5px;margin-left:.5em;border-color:#faa;border:2px dashed rgba(255,0,0,.1);border-radius:2px\">"
},
'[/moot]': {
innerHTML: "</div>"
},
'[banned]': {
innerHTML: "<strong style=\"color: red;\">"
},
'[/banned]': {
innerHTML: "</strong>"
}
};
return Fetcher;
})();
Polyfill = {
init: function() {
this.notificationPermission();
this.toBlob();
return this.visibility();
},
notificationPermission: function() {
if (!window.Notification || 'permission' in Notification || !window.webkitNotifications) {
return;
}
return Object.defineProperty(Notification, 'permission', {
get: function() {
switch (webkitNotifications.checkPermission()) {
case 0:
return 'granted';
case 1:
return 'default';
case 2:
return 'denied';
}
}
});
},
toBlob: function() {
var _base;
return (_base = HTMLCanvasElement.prototype).toBlob || (_base.toBlob = function(cb) {
var data, i, l, ui8a, _i;
data = atob(this.toDataURL().slice(22));
l = data.length;
ui8a = new Uint8Array(l);
for (i = _i = 0; _i < l; i = _i += 1) {
ui8a[i] = data.charCodeAt(i);
}
return cb(new Blob([ui8a], {
type: 'image/png'
}));
});
},
visibility: function() {
if ('visibilityState' in d) {
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, box, customNavToggler, editCustomNav, footerToggler, headerToggler, linkJustifyToggler, menuButton, scrollHeaderToggler, shortcutToggler;
this.menu = new UI.Menu('header');
menuButton = $.el('span', {
className: 'menu-button'
});
$.extend(menuButton, {
innerHTML: "<i></i>"
});
box = UI.checkbox;
barFixedToggler = box('Fixed Header', 'Fixed Header');
headerToggler = box('Header auto-hide', 'Auto-hide header');
scrollHeaderToggler = box('Header auto-hide on scroll', 'Auto-hide header on scroll');
barPositionToggler = box('Bottom Header', 'Bottom header');
linkJustifyToggler = box('Centered links', 'Centered links');
customNavToggler = box('Custom Board Navigation', 'Custom board navigation');
footerToggler = box('Bottom Board List', 'Hide bottom board list');
shortcutToggler = box('Shortcut Icons', 'Shortcut Icons');
editCustomNav = $.el('a', {
textContent: 'Edit custom board navigation',
href: 'javascript:;'
});
this.barFixedToggler = barFixedToggler.firstElementChild;
this.scrollHeaderToggler = scrollHeaderToggler.firstElementChild;
this.barPositionToggler = barPositionToggler.firstElementChild;
this.linkJustifyToggler = linkJustifyToggler.firstElementChild;
this.headerToggler = headerToggler.firstElementChild;
this.footerToggler = footerToggler.firstElementChild;
this.shortcutToggler = shortcutToggler.firstElementChild;
this.customNavToggler = customNavToggler.firstElementChild;
$.on(menuButton, 'click', this.menuToggle);
$.on(this.headerToggler, 'change', this.toggleBarVisibility);
$.on(this.barFixedToggler, 'change', this.toggleBarFixed);
$.on(this.barPositionToggler, 'change', this.toggleBarPosition);
$.on(this.scrollHeaderToggler, 'change', this.toggleHideBarOnScroll);
$.on(this.linkJustifyToggler, 'change', this.toggleLinkJustify);
$.on(this.footerToggler, 'change', this.toggleFooterVisibility);
$.on(this.shortcutToggler, 'change', this.toggleShortcutIcons);
$.on(this.customNavToggler, 'change', this.toggleCustomNav);
$.on(editCustomNav, 'click', this.editCustomNav);
this.setBarFixed(Conf['Fixed Header']);
this.setHideBarOnScroll(Conf['Header auto-hide on scroll']);
this.setBarVisibility(Conf['Header auto-hide']);
this.setLinkJustify(Conf['Centered links']);
this.setShortcutIcons(Conf['Shortcut Icons']);
this.setFooterVisibility(Conf['Bottom Board List']);
$.sync('Fixed Header', this.setBarFixed);
$.sync('Header auto-hide on scroll', this.setHideBarOnScroll);
$.sync('Bottom Header', this.setBarPosition);
$.sync('Shortcut Icons', this.setShortcutIcons);
$.sync('Header auto-hide', this.setBarVisibility);
$.sync('Centered links', this.setLinkJustify);
$.sync('Bottom Board List', this.setFooterVisibility);
this.addShortcut(menuButton);
this.menu.addEntry({
el: $.el('span', {
textContent: 'Header'
}),
order: 107,
subEntries: [
{
el: barFixedToggler
}, {
el: headerToggler
}, {
el: scrollHeaderToggler
}, {
el: barPositionToggler
}, {
el: linkJustifyToggler
}, {
el: footerToggler
}, {
el: shortcutToggler
}, {
el: customNavToggler
}, {
el: editCustomNav
}
]
});
$.on(window, 'load hashchange', Header.hashScroll);
$.on(d, 'CreateNotification', this.createNotification);
$.asap((function() {
return d.body;
}), (function(_this) {
return function() {
if (!Main.isThisPageLegit()) {
return;
}
$.asap((function() {
return $.id('boardNavMobile') || d.readyState !== 'loading';
}), function() {
var a, footer;
footer = $.id('boardNavDesktop').cloneNode(true);
footer.id = 'boardNavDesktopFoot';
$('#navtopright', footer).id = 'navbotright';
$('#settingsWindowLink', footer).id = 'settingsWindowLinkBot';
Header.bottomBoardList = $('.boardList', footer);
if (a = $("a[href*='/" + g.BOARD + "/']", footer)) {
a.className = 'current';
}
Main.ready(function() {
var oldFooter;
if (oldFooter = $.id('boardNavDesktopFoot')) {
return $.replace($('.boardList', oldFooter), Header.bottomBoardList);
} else {
$.before($.id('absbot'), footer);
return $.globalEval('window.cloneTopNav = function() {};');
}
});
return Header.setBoardList();
});
$.prepend(d.body, _this.bar);
$.add(d.body, Header.hover);
_this.setBarPosition(Conf['Bottom Header']);
return _this;
};
})(this));
Main.ready((function(_this) {
return function() {
var cs;
if (g.VIEW === 'catalog' || !Conf['Disable Native Extension']) {
cs = $.el('a', {
href: 'javascript:;'
});
if (g.VIEW === 'catalog') {
cs.title = cs.textContent = 'Catalog Settings';
cs.className = 'fa fa-book';
} else {
cs.title = cs.textContent = '4chan Settings';
cs.className = 'fa fa-leaf';
}
$.on(cs, 'click', function() {
return $.id('settingsWindowLink').click();
});
return _this.addShortcut(cs);
}
};
})(this));
return this.enableDesktopNotifications();
},
bar: $.el('div', {
id: 'header-bar'
}),
noticesRoot: $.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, chr, node, nodes, spacer, span, _i, _j, _len, _len1, _ref, _ref1;
Header.boardList = boardList = $.el('span', {
id: 'board-list'
});
$.extend(boardList, {
innerHTML: "<span id=\"custom-board-list\"></span><span id=\"full-board-list\" hidden><span class=\"hide-board-list-container brackets-wrap\"><a href=\"javascript:;\" class=\"hide-board-list-button\"> - </a></span> <span class=\"boardList\"></span></span>"
});
btn = $('.hide-board-list-button', boardList);
$.on(btn, 'click', Header.toggleBoardList);
nodes = [];
spacer = function() {
return $.el('span', {
className: 'spacer'
});
};
_ref = $('#boardNavDesktop > .boardList').childNodes;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
node = _ref[_i];
switch (node.nodeName) {
case '#text':
_ref1 = node.nodeValue;
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
chr = _ref1[_j];
span = $.el('span', {
textContent: chr
});
if (chr === ' ') {
span.className = 'space';
}
if (chr === ']') {
nodes.push(spacer());
}
nodes.push(span);
if (chr === '[') {
nodes.push(spacer());
}
}
break;
case 'A':
a = node.cloneNode(true);
if (a.pathname.split('/')[1] === g.BOARD.ID) {
a.className = 'current';
}
nodes.push(a);
}
}
$.add($('.boardList', boardList), nodes);
$.add(Header.bar, [Header.boardList, Header.shortcuts, Header.noticesRoot, Header.toggle]);
Header.setCustomNav(Conf['Custom Board Navigation']);
Header.generateBoardList(Conf['boardnav']);
$.sync('Custom Board Navigation', Header.setCustomNav);
return $.sync('boardnav', Header.generateBoardList);
},
generateBoardList: function(boardnav) {
var as, list, nodes, re, t;
list = $('#custom-board-list', Header.boardList);
$.rmAll(list);
if (!boardnav) {
return;
}
boardnav = boardnav.replace(/(\r\n|\n|\r)/g, ' ');
as = $$('#full-board-list a[title]', Header.boardList);
re = /[\w@]+(-(all|title|replace|full|index|catalog|archive|expired|text:"[^"]+"(,"[^"]+")?))*|[^\w@]+/g;
nodes = (function() {
var _i, _len, _ref, _results;
_ref = boardnav.match(re);
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
t = _ref[_i];
_results.push(Header.mapCustomNavigation(t, as));
}
return _results;
})();
$.add(list, nodes);
return $.ready(CatalogLinks.initBoardList);
},
mapCustomNavigation: function(t, as) {
var a, boardID, href, m, text, url;
if (/^[^\w@]/.test(t)) {
return $.tn(t);
}
text = url = null;
t = t.replace(/-text:"([^"]+)"(?:,"([^"]+)")?/g, function(m0, m1, m2) {
text = m1;
url = m2;
return '';
});
if (/^toggle-all/.test(t)) {
a = $.el('a', {
className: 'show-board-list-button',
textContent: text || '+',
href: 'javascript:;'
});
$.on(a, 'click', Header.toggleBoardList);
return a;
}
if (/^external/.test(t)) {
a = $.el('a', {
href: url || 'javascript:;',
textContent: text || '+',
className: 'external'
});
return a;
}
boardID = t.split('-')[0];
if (boardID === 'current') {
boardID = g.BOARD.ID;
}
a = (function() {
var _i, _len, _ref;
if (boardID === '@') {
return $.el('a', {
href: 'https://twitter.com/4chan',
title: '4chan Twitter',
textContent: '@'
});
}
for (_i = 0, _len = as.length; _i < _len; _i++) {
a = as[_i];
if (a.textContent === boardID) {
return a.cloneNode(true);
}
}
a = $.el('a', {
href: "/" + boardID + "/",
textContent: boardID
});
if ((_ref = g.VIEW) === 'catalog' || _ref === 'archive') {
a.href += g.VIEW;
}
if (boardID === g.BOARD.ID) {
a.className = 'current';
}
return a;
})();
a.textContent = /-title/.test(t) || /-replace/.test(t) && boardID === g.BOARD.ID ? a.title || a.textContent : /-full/.test(t) ? ("/" + boardID + "/") + (a.title ? " - " + a.title : '') : text || boardID;
if (m = t.match(/-(index|catalog)/)) {
a.dataset.only = m[1];
a.href = CatalogLinks[m[1]](boardID);
if (m[1] === 'catalog') {
$.addClass(a, 'catalog');
}
}
if (/-archive/.test(t)) {
if (href = Redirect.to('board', {
boardID: boardID
})) {
a.href = href;
} else {
return a.firstChild;
}
}
if (/-expired/.test(t)) {
if (boardID !== 'b' && boardID !== 'f') {
a.href = "/" + boardID + "/archive";
} else {
return a.firstChild;
}
}
if (boardID === '@') {
$.addClass(a, 'navSmall');
}
return a;
},
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;
},
setLinkJustify: function(centered) {
Header.linkJustifyToggler.checked = centered;
if (centered) {
return $.addClass(doc, 'centered-links');
} else {
return $.rmClass(doc, 'centered-links');
}
},
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);
},
setShortcutIcons: function(show) {
Header.shortcutToggler.checked = show;
if (show) {
return $.addClass(doc, 'shortcut-icons');
} else {
return $.rmClass(doc, 'shortcut-icons');
}
},
toggleShortcutIcons: function() {
$.event('CloseMenu');
Header.setShortcutIcons(this.checked);
Conf['Shortcut Icons'] = this.checked;
return $.set('Shortcut Icons', 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() {
var hide, message;
hide = this.nodeName === 'INPUT' ? this.checked : !$.hasClass(Header.bar, 'autohide');
Conf['Header auto-hide'] = hide;
$.set('Header auto-hide', hide);
Header.setBarVisibility(hide);
message = "The header bar will " + (hide ? 'automatically hide itself.' : 'remain visible.');
return new Notice('info', message, 2);
},
setHideBarOnScroll: function(hide) {
Header.scrollHeaderToggler.checked = hide;
if (hide) {
$.on(window, 'scroll', Header.hideBarOnScroll);
return;
}
$.off(window, 'scroll', Header.hideBarOnScroll);
$.rmClass(Header.bar, 'scroll');
if (!Conf['Header auto-hide']) {
return $.rmClass(Header.bar, 'autohide');
}
},
toggleHideBarOnScroll: function(e) {
var hide;
hide = this.checked;
$.cb.checked.call(this);
return Header.setHideBarOnScroll(hide);
},
hideBarOnScroll: function() {
var offsetY;
offsetY = window.pageYOffset;
if (offsetY > (Header.previousOffset || 0)) {
$.addClass(Header.bar, 'autohide', 'scroll');
} else {
$.rmClass(Header.bar, 'autohide', 'scroll');
}
return Header.previousOffset = offsetY;
},
setBarPosition: function(bottom) {
var args;
Header.barPositionToggler.checked = bottom;
$.event('CloseMenu');
args = bottom ? ['bottom-header', 'top-header', 'after'] : ['top-header', 'bottom-header', 'add'];
$.addClass(doc, args[0]);
$.rmClass(doc, args[1]);
return $[args[2]](Header.bar, Header.noticesRoot);
},
toggleBarPosition: function() {
$.cb.checked.call(this);
return Header.setBarPosition(this.checked);
},
setFooterVisibility: function(hide) {
Header.footerToggler.checked = hide;
return doc.classList.toggle('hide-bottom-board-list', hide);
},
toggleFooterVisibility: function() {
var hide, message;
$.event('CloseMenu');
hide = this.nodeName === 'INPUT' ? this.checked : $.hasClass(doc, 'hide-bottom-board-list');
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 Notice('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-container', full);
return _ref = show ? [false, true, false] : [true, false, true], cust.hidden = _ref[0], full.hidden = _ref[1], btn.hidden = _ref[2], _ref;
},
toggleCustomNav: function() {
$.cb.checked.call(this);
return Header.setCustomNav(this.checked);
},
editCustomNav: function() {
var settings;
Settings.open('Advanced');
settings = $.id('fourchanx-settings');
return $('[name=boardnav]', settings).focus();
},
hashScroll: function() {
var hash, post;
hash = this.location.hash.slice(1);
if (!(/^p\d+$/.test(hash) && (post = $.id(hash)))) {
return;
}
if ((Get.postFromRoot(post)).isHidden) {
return;
}
return Header.scrollTo(post);
},
scrollTo: function(root, down, needed) {
var height, x;
if (down) {
x = Header.getBottomOf(root);
if (Conf['Header auto-hide on scroll'] && Conf['Bottom header']) {
height = Header.bar.getBoundingClientRect().height;
if (x <= 0) {
if (!Header.isHidden()) {
x += height;
}
} else {
if (Header.isHidden()) {
x -= height;
}
}
}
if (!(needed && x >= 0)) {
return window.scrollBy(0, -x);
}
} else {
x = Header.getTopOf(root);
if (Conf['Header auto-hide on scroll'] && !Conf['Bottom header']) {
height = Header.bar.getBoundingClientRect().height;
if (x >= 0) {
if (!Header.isHidden()) {
x += height;
}
} else {
if (Header.isHidden()) {
x -= height;
}
}
}
if (!(needed && x >= 0)) {
return window.scrollBy(0, x);
}
}
},
scrollToIfNeeded: function(root, down) {
return Header.scrollTo(root, down, true);
},
getTopOf: function(root) {
var headRect, top;
top = root.getBoundingClientRect().top;
if (Conf['Fixed Header'] && !Conf['Bottom Header']) {
headRect = Header.toggle.getBoundingClientRect();
top -= headRect.top + headRect.height;
}
return top;
},
getBottomOf: function(root) {
var bottom, clientHeight, headRect;
clientHeight = doc.clientHeight;
bottom = clientHeight - root.getBoundingClientRect().bottom;
if (Conf['Bottom Header']) {
headRect = Header.toggle.getBoundingClientRect();
bottom -= clientHeight - headRect.bottom + headRect.height;
}
return bottom;
},
isNodeVisible: function(node) {
var height;
if (d.hidden || !doc.contains(node)) {
return false;
}
height = node.getBoundingClientRect().height;
return Header.getTopOf(node) + height >= 0 && Header.getBottomOf(node) + height >= 0;
},
isHidden: function() {
var top;
top = Header.bar.getBoundingClientRect().top;
if (Conf['Bottom header']) {
return top === doc.clientHeight;
} else {
return top < 0;
}
},
addShortcut: function(el) {
var shortcut;
shortcut = $.el('span', {
className: 'shortcut brackets-wrap'
});
$.add(shortcut, el);
return $.prepend(Header.shortcuts, shortcut);
},
rmShortcut: function(el) {
return $.rm(el.parentElement);
},
menuToggle: function(e) {
return Header.menu.toggle(e, this, g);
},
createNotification: function(e) {
var content, lifetime, notice, type, _ref;
_ref = e.detail, type = _ref.type, content = _ref.content, lifetime = _ref.lifetime;
return notice = new Notice(type, content, lifetime);
},
areNotificationsEnabled: false,
enableDesktopNotifications: function() {
var authorize, disable, el, notice, _ref;
if (!(window.Notification && Conf['Desktop Notifications'])) {
return;
}
switch (Notification.permission) {
case 'granted':
Header.areNotificationsEnabled = true;
return;
case 'denied':
return;
}
el = $.el('span', {
innerHTML: E(g.NAME) + " needs your permission to show desktop notifications. [<a href=\"" + E(g.FAQ) + "#why-is-4chan-x-asking-for-permission-to-show-desktop-notifications\" target=\"_blank\">FAQ</a>]<br><button>Authorize</button> or <button>Disable</button>"
});
_ref = $$('button', el), authorize = _ref[0], disable = _ref[1];
$.on(authorize, 'click', function() {
return Notification.requestPermission(function(status) {
Header.areNotificationsEnabled = status === 'granted';
if (status === 'default') {
return;
}
return notice.close();
});
});
$.on(disable, 'click', function() {
$.set('Desktop Notifications', false);
return notice.close();
});
return notice = new Notice('info', el);
}
};
Index = {
showHiddenThreads: false,
init: function() {
var anchorEntry, input, label, name, pinEntry, refNavEntry, repliesEntry, select, _i, _j, _len, _len1, _ref, _ref1, _ref2, _ref3, _ref4, _ref5;
if (g.BOARD.ID === 'f' || !Conf['JSON Navigation'] || g.VIEW !== 'index') {
return;
}
this.board = "" + g.BOARD;
CatalogThread.callbacks.push({
name: 'Catalog Features',
cb: this.catalogNode
});
this.search = ((_ref = history.state) != null ? _ref.search : void 0) || '';
if ((_ref1 = history.state) != null ? _ref1.mode : void 0) {
Conf['Index Mode'] = (_ref2 = history.state) != null ? _ref2.mode : void 0;
}
this.currentPage = this.getCurrentPage();
this.pushState({
command: (_ref3 = location.href.match(/#(.*)/)) != null ? _ref3[1] : void 0,
replace: true
});
this.button = $.el('a', {
className: 'index-refresh-shortcut fa fa-refresh',
title: 'Refresh',
href: 'javascript:;',
textContent: 'Refresh Index'
});
$.on(this.button, 'click', function() {
return Index.update();
});
Header.addShortcut(this.button, 1);
repliesEntry = {
el: UI.checkbox('Show Replies', 'Show replies')
};
pinEntry = {
el: UI.checkbox('Pin Watched Threads', 'Pin watched threads')
};
anchorEntry = {
el: UI.checkbox('Anchor Hidden Threads', 'Anchor hidden threads')
};
refNavEntry = {
el: UI.checkbox('Refreshed Navigation', 'Refreshed navigation')
};
pinEntry.el.title = 'Move watched threads to the start of the index.';
anchorEntry.el.title = 'Move hidden threads to the end of the index.';
refNavEntry.el.title = 'Refresh index when navigating through pages.';
_ref4 = [repliesEntry, pinEntry, anchorEntry, refNavEntry];
for (_i = 0, _len = _ref4.length; _i < _len; _i++) {
label = _ref4[_i];
input = label.el.firstChild;
name = input.name;
$.on(input, 'change', $.cb.checked);
switch (name) {
case 'Show Replies':
$.on(input, 'change', this.cb.replies);
break;
case 'Pin Watched Threads':
case 'Anchor Hidden Threads':
$.on(input, 'change', this.cb.sort);
}
}
Header.menu.addEntry({
el: $.el('span', {
textContent: 'Index Navigation'
}),
order: 98,
subEntries: [repliesEntry, pinEntry, anchorEntry, refNavEntry]
});
$.addClass(doc, 'index-loading', "" + (Conf['Index Mode'].replace(/\ /g, '-')) + "-mode");
this.root = $.el('div', {
className: 'board'
});
this.cb.size();
this.pagelist = $.el('div', {
className: 'pagelist'
});
$.extend(this.pagelist, {
innerHTML: "<div class=\"prev\"><a><button disabled>Previous</button></a></div><div class=\"pages\"></div><div class=\"next\"><a><button disabled>Next</button></a></div><div class=\"pages cataloglink\"><a href=\"./catalog\">Catalog</a></div>"
});
$('.cataloglink a', this.pagelist).href = CatalogLinks.catalog();
this.navLinks = $.el('div', {
className: 'navLinks'
});
$.extend(this.navLinks, {
innerHTML: "<span class=\"brackets-wrap refreshlink\"><a href=\"javascript:;\">Refresh</a></span> <span class=\"brackets-wrap indexlink\"><a href=\"#index\">Index</a></span> <span class=\"brackets-wrap cataloglink\"><a href=\"#catalog\">Catalog</a></span> <span class=\"brackets-wrap archlistlink\"><a href=\"./archive\">Archive</a></span> <span class=\"brackets-wrap bottomlink\"><a href=\"#bottom\">Bottom</a></span> <span class=\"brackets-wrap\" id=\"index-last-refresh\"><time title=\"Last index refresh\">...</time></span> <input type=\"search\" id=\"index-search\" class=\"field\" placeholder=\"Search\"><a id=\"index-search-clear\" href=\"javascript:;\" title=\"Clear search\">×</a><span id=\"hidden-label\" hidden> — <span id=\"hidden-count\"></span> <span id=\"hidden-toggle\">[<a href=\"javascript:;\">Show</a>]</span></span><select id=\"index-mode\" name=\"Index Mode\"><option disabled>Index Mode</option><option value=\"paged\">Paged</option><option value=\"infinite\">Infinite scrolling</option><option value=\"all pages\">All threads</option><option value=\"catalog\">Catalog</option></select><select id=\"index-sort\" name=\"Index Sort\"><option disabled>Index Sort</option><option value=\"bump\">Bump order</option><option value=\"lastreply\">Last reply</option><option value=\"birth\">Creation date</option><option value=\"replycount\">Reply count</option><option value=\"filecount\">File count</option></select><select id=\"index-size\" name=\"Index Size\"><option disabled>Image Size</option><option value=\"small\">Small</option><option value=\"large\">Large</option></select>"
});
$('.cataloglink a', this.navLinks).href = CatalogLinks.catalog();
if (g.BOARD.ID === 'b') {
$('.archlistlink', this.navLinks).hidden = true;
}
this.searchInput = $('#index-search', this.navLinks);
this.setupSearch();
this.hideLabel = $('#hidden-label', this.navLinks);
this.selectMode = $('#index-mode', this.navLinks);
this.selectSort = $('#index-sort', this.navLinks);
this.selectSize = $('#index-size', this.navLinks);
$.on(window, 'popstate', this.cb.popstate);
$.on(d, 'scroll', Index.scroll);
$.on(this.pagelist, 'click', this.cb.pageNav);
$.on(this.searchInput, 'input', this.onSearchInput);
$.on($('.refreshlink a', this.navLinks), 'click', this.update);
$.on($('#index-search-clear', this.navLinks), 'click', this.clearSearch);
$.on($('#hidden-toggle a', this.navLinks), 'click', this.cb.toggleHiddenThreads);
$.on(this.selectMode, 'change', this.cb.mode);
_ref5 = [this.selectMode, this.selectSort, this.selectSize];
for (_j = 0, _len1 = _ref5.length; _j < _len1; _j++) {
select = _ref5[_j];
select.value = Conf[select.name];
$.on(select, 'change', $.cb.value);
}
$.on(this.selectSort, 'change', this.cb.sort);
$.on(this.selectSize, 'change', this.cb.size);
this.update();
$.asap((function() {
return $('title + *', doc) || d.readyState !== 'loading';
}), function() {
return d.title = d.title.replace(/\ -\ Page\ \d+/, '');
});
$.asap((function() {
return $('.board > .thread > .postContainer', doc) || d.readyState !== 'loading';
}), function() {
var board, el, threadRoot, topNavPos, _k, _l, _len2, _len3, _ref6, _ref7, _ref8;
if (!Main.isThisPageLegit()) {
return;
}
Index.hat = $('.board > .thread > img:first-child');
if (Index.hat && Index.nodes) {
_ref6 = Index.nodes;
for (_k = 0, _len2 = _ref6.length; _k < _len2; _k++) {
threadRoot = _ref6[_k];
$.prepend(threadRoot, Index.hat.cloneNode(false));
}
}
board = $('.board');
$.replace(board, Index.root);
$.event('PostsInserted');
d.implementation.createDocument(null, null, null).appendChild(board);
_ref7 = $$('.navLinks');
for (_l = 0, _len3 = _ref7.length; _l < _len3; _l++) {
el = _ref7[_l];
$.rm(el);
}
if ((_ref8 = $.id('search-box')) != null) {
_ref8.parentNode.remove();
}
topNavPos = $.id('delform').previousElementSibling;
$.before(topNavPos, $.el('hr'));
return $.before(topNavPos, Index.navLinks);
});
return $.asap((function() {
return $('.pagelist', doc) || d.readyState !== 'loading';
}), function() {
var pagelist;
if (!Main.isThisPageLegit()) {
return;
}
if (pagelist = $('.pagelist')) {
$.replace(pagelist, Index.pagelist);
} else {
$.after($.id('delform'), Index.pagelist);
}
return $.rmClass(doc, 'index-loading');
});
},
scroll: function() {
var nodes, pageNum;
if (Index.req || Conf['Index Mode'] !== 'infinite' || (window.scrollY <= doc.scrollHeight - (300 + window.innerHeight))) {
return;
}
if (Index.pageNum == null) {
Index.pageNum = Index.getCurrentPage();
}
pageNum = ++Index.pageNum;
if (pageNum > Index.pagesNum) {
return Index.endNotice();
}
nodes = Index.buildSinglePage(pageNum);
if (Conf['Show Replies']) {
Index.buildReplies(nodes);
}
return Index.buildStructure(nodes);
},
endNotice: (function() {
var notify, reset;
notify = false;
reset = function() {
return notify = false;
};
return function() {
if (notify) {
return;
}
notify = true;
new Notice('info', "Last page reached.", 2);
return setTimeout(reset, 3 * $.SECOND);
};
})(),
menu: {
init: function() {
if (g.VIEW !== 'index' || !Conf['JSON Navigation'] || !Conf['Menu'] || !Conf['Thread Hiding Link'] || g.BOARD.ID === 'f') {
return;
}
return Menu.menu.addEntry({
el: $.el('a', {
href: 'javascript:;'
}),
order: 20,
open: function(_arg) {
var thread;
thread = _arg.thread;
if (Conf['Index Mode'] !== 'catalog') {
return false;
}
this.el.textContent = thread.isHidden ? 'Unhide thread' : 'Hide thread';
if (this.cb) {
$.off(this.el, 'click', this.cb);
}
this.cb = function() {
$.event('CloseMenu');
return Index.toggleHide(thread);
};
$.on(this.el, 'click', this.cb);
return true;
}
});
}
},
catalogNode: function() {
return $.on(this.nodes.thumb.parentNode, 'click', Index.onClick);
},
onClick: function(e) {
var thread;
if (e.button !== 0) {
return;
}
thread = g.threads[this.parentNode.dataset.fullID];
if (e.shiftKey) {
Index.toggleHide(thread);
} else {
return;
}
return e.preventDefault();
},
toggleHide: function(thread) {
$.rm(thread.catalogView.nodes.root);
if (Index.showHiddenThreads) {
ThreadHiding.show(thread);
if (!ThreadHiding.db.get({
boardID: thread.board.ID,
threadID: thread.ID
})) {
return;
}
} else {
ThreadHiding.hide(thread);
}
return ThreadHiding.saveHiddenState(thread);
},
cycleSortType: function() {
var i, type, types, _i, _len;
types = __slice.call(Index.selectSort.options).filter(function(option) {
return !option.disabled;
});
for (i = _i = 0, _len = types.length; _i < _len; i = ++_i) {
type = types[i];
if (type.selected) {
break;
}
}
types[(i + 1) % types.length].selected = true;
return $.event('change', null, Index.selectSort);
},
cb: {
toggleHiddenThreads: function() {
$('#hidden-toggle a', Index.navLinks).textContent = (Index.showHiddenThreads = !Index.showHiddenThreads) ? 'Hide' : 'Show';
Index.sort();
return Index.buildIndex();
},
mode: function() {
var mode;
mode = this.value;
if (mode !== 'catalog') {
Conf['Previous Index Mode'] = mode;
$.set('Previous Index Mode', mode);
}
return Index.pageLoad(Index.pushState({
mode: mode
}));
},
sort: function() {
Index.sort();
return Index.buildIndex();
},
size: function(e) {
if (Conf['Index Mode'] !== 'catalog') {
$.rmClass(Index.root, 'catalog-small');
$.rmClass(Index.root, 'catalog-large');
} else if (Conf['Index Size'] === 'small') {
$.addClass(Index.root, 'catalog-small');
$.rmClass(Index.root, 'catalog-large');
} else {
$.addClass(Index.root, 'catalog-large');
$.rmClass(Index.root, 'catalog-small');
}
if (e) {
return Index.buildIndex();
}
},
replies: function() {
Index.buildThreads();
Index.sort();
return Index.buildIndex();
},
popstate: function(e) {
var mode, page, search, state, _ref, _ref1;
if (e != null ? e.state : void 0) {
_ref = e.state, search = _ref.search, mode = _ref.mode;
page = Index.getCurrentPage();
state = {};
if (Index.search !== search) {
state.search = Index.search = search;
}
if (Conf['Index Mode'] !== mode) {
state.mode = mode;
Index.saveMode(mode);
}
if (Index.currentPage !== page) {
state.page = Index.currentPage = page;
}
if ((state.search != null) || (state.mode != null) || (state.page != null)) {
return Index.pageLoad(state);
}
} else {
state = Index.pushState({
command: (_ref1 = location.href.match(/#(.*)/)) != null ? _ref1[1] : void 0,
replace: true,
scroll: true
});
if (state.command) {
return Index[Conf['Refreshed Navigation'] ? 'update' : 'pageLoad'](state);
}
}
},
pageNav: function(e) {
var a;
if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) {
return;
}
switch (e.target.nodeName) {
case 'BUTTON':
e.target.blur();
a = e.target.parentNode;
break;
case 'A':
a = e.target;
break;
default:
return;
}
if (a.textContent === 'Catalog') {
return;
}
e.preventDefault();
return Index.userPageNav(+a.pathname.split('/')[2] || 1);
}
},
scrollToIndex: function() {
return Header.scrollToIfNeeded(Index.navLinks);
},
getCurrentPage: function() {
var _ref;
if ((_ref = Conf['Index Mode']) === 'all pages' || _ref === 'catalog') {
return 1;
} else {
return +window.location.pathname.split('/')[2] || 1;
}
},
userPageNav: function(page, noRefresh) {
var state;
state = Index.pushState({
page: page,
scroll: true
});
if (Conf['Refreshed Navigation'] && !noRefresh) {
return Index.update(state);
} else {
if (state.page) {
return Index.pageLoad(state);
}
}
},
pushState: function(state) {
var command, hash, mode, page, pageBeforeSearch, pathname, search, _ref;
pathname = location.pathname, hash = location.hash;
pageBeforeSearch = (_ref = history.state) != null ? _ref.oldpage : void 0;
if (state.command != null) {
command = state.command;
if (command === 'paged' || command === 'infinite' || command === 'all-pages' || command === 'catalog') {
state.mode = command.replace(/-/g, ' ');
} else if (command === 'index') {
state.mode = Conf['Previous Index Mode'];
state.page = 1;
} else if (/^s=/.test(command)) {
state.search = decodeURIComponent(command.slice(2)).replace(/\+/g, ' ').trim();
hash = '';
} else {
delete state.command;
}
}
if (state.search != null) {
search = state.search;
state.page = search ? 1 : pageBeforeSearch || 1;
if (!search) {
pageBeforeSearch = void 0;
} else if (!Index.search) {
pageBeforeSearch = Index.currentPage;
}
Index.search = search;
}
if (state.mode != null) {
mode = state.mode;
if (mode === Conf['Index Mode']) {
delete state.mode;
}
Index.saveMode(mode);
if (mode === 'all pages' || mode === 'catalog') {
state.page = 1;
}
hash = '';
}
if (state.page != null) {
page = state.page;
if (page === Index.currentPage) {
delete state.page;
}
Index.currentPage = page;
pathname = page === 1 ? "/" + g.BOARD + "/" : "/" + g.BOARD + "/" + page;
hash = '';
}
history[state.replace ? 'replaceState' : 'pushState']({
mode: Conf['Index Mode'],
search: Index.search,
oldpage: pageBeforeSearch
}, '', pathname + hash);
return state;
},
saveMode: function(mode) {
Conf['Index Mode'] = mode;
$.set('Index Mode', mode);
if (mode !== 'catalog') {
Conf['Previous Index Mode'] = mode;
return $.set('Previous Index Mode', mode);
}
},
pageLoad: function(_arg) {
var mode, scroll, search, sort;
sort = _arg.sort, search = _arg.search, mode = _arg.mode, scroll = _arg.scroll;
if (sort || (search != null)) {
Index.sort();
Index.buildPagelist();
}
if (search != null) {
Index.setupSearch();
}
if (mode != null) {
Index.applyMode();
}
Index.buildIndex();
Index.setPage();
if (scroll) {
return Index.scrollToIndex();
}
},
applyMode: function() {
var mode, _i, _len, _ref;
_ref = ['paged', 'infinite', 'all pages', 'catalog'];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
mode = _ref[_i];
$[mode === Conf['Index Mode'] ? 'addClass' : 'rmClass'](doc, "" + (mode.replace(/\ /g, '-')) + "-mode");
}
Index.selectMode.value = Conf['Index Mode'];
Index.cb.size();
Index.showHiddenThreads = false;
return $('#hidden-toggle a', Index.navLinks).textContent = 'Show';
},
getPagesNum: function() {
if (Index.search) {
return Math.ceil(Index.sortedNodes.length / Index.threadsNumPerPage);
} else {
return Index.pagesNum;
}
},
getMaxPageNum: function() {
return Math.max(1, Index.getPagesNum());
},
buildPagelist: function() {
var a, i, maxPageNum, nodes, pagesRoot, _i;
pagesRoot = $('.pages', Index.pagelist);
maxPageNum = Index.getMaxPageNum();
if (pagesRoot.childElementCount !== maxPageNum) {
nodes = [];
for (i = _i = 1; _i <= maxPageNum; i = _i += 1) {
a = $.el('a', {
textContent: i,
href: i === 1 ? './' : i
});
nodes.push($.tn('['), a, $.tn('] '));
}
$.rmAll(pagesRoot);
return $.add(pagesRoot, nodes);
}
},
setPage: function() {
var a, href, maxPageNum, next, pageNum, pagesRoot, prev, strong;
pageNum = Index.getCurrentPage();
maxPageNum = Index.getMaxPageNum();
pagesRoot = $('.pages', Index.pagelist);
prev = pagesRoot.previousSibling.firstChild;
next = pagesRoot.nextSibling.firstChild;
href = Math.max(pageNum - 1, 1);
prev.href = href === 1 ? './' : href;
prev.firstChild.disabled = href === pageNum;
href = Math.min(pageNum + 1, maxPageNum);
next.href = href === 1 ? './' : href;
next.firstChild.disabled = href === pageNum;
if (strong = $('strong', pagesRoot)) {
if (+strong.textContent === pageNum) {
return;
}
$.replace(strong, strong.firstChild);
} else {
strong = $.el('strong');
}
a = pagesRoot.children[pageNum - 1];
$.before(a, strong);
return $.add(strong, a);
},
updateHideLabel: function() {
var hiddenCount, thread, threadID, _ref, _ref1;
hiddenCount = 0;
_ref = g.BOARD.threads;
for (threadID in _ref) {
thread = _ref[threadID];
if (thread.isHidden) {
if (_ref1 = thread.ID, __indexOf.call(Index.liveThreadIDs, _ref1) >= 0) {
hiddenCount++;
}
}
}
if (!hiddenCount) {
Index.hideLabel.hidden = true;
if (Index.showHiddenThreads) {
Index.cb.toggleHiddenThreads();
}
return;
}
Index.hideLabel.hidden = false;
return $('#hidden-count', Index.navLinks).textContent = hiddenCount === 1 ? '1 hidden thread' : "" + hiddenCount + " hidden threads";
},
update: function(state) {
var now, _ref, _ref1;
if (!navigator.onLine) {
return;
}
delete Index.pageNum;
if ((_ref = Index.req) != null) {
_ref.abort();
}
if ((_ref1 = Index.notice) != null) {
_ref1.close();
}
now = Date.now();
$.ready(function() {
return Index.nTimeout = setTimeout((function() {
if (Index.req && !Index.notice) {
return Index.notice = new Notice('info', 'Refreshing index...', 2);
}
}), 3 * $.SECOND - (Date.now() - now));
});
Index.req = $.ajax("//a.4cdn.org/" + g.BOARD + "/catalog.json", {
onloadend: function(e) {
return Index.load(e, state);
}
}, {
whenModified: true
});
return $.addClass(Index.button, 'fa-spin');
},
load: function(e, state) {
var err, nTimeout, notice, req, timeEl, _ref;
$.rmClass(Index.button, 'fa-spin');
req = Index.req, notice = Index.notice, nTimeout = Index.nTimeout;
if (nTimeout) {
clearTimeout(nTimeout);
}
delete Index.nTimeout;
delete Index.req;
delete Index.notice;
if (e.type === 'abort') {
req.onloadend = null;
notice.close();
return;
}
if ((_ref = req.status) !== 200 && _ref !== 304) {
err = "Index refresh failed. Error " + req.statusText + " (" + req.status + ")";
if (notice) {
notice.setType('warning');
notice.el.lastElementChild.textContent = err;
setTimeout(notice.close, $.SECOND);
} else {
new Notice('warning', err, 1);
}
return;
}
try {
if (req.status === 200) {
Index.parse(req.response, state);
} else if (req.status === 304 && (state != null)) {
Index.pageLoad(state);
}
} catch (_error) {
err = _error;
c.error("Index failure: " + err.message, err.stack);
if (notice) {
notice.setType('error');
notice.el.lastElementChild.textContent = 'Index refresh failed.';
setTimeout(notice.close, $.SECOND);
} else {
new Notice('error', 'Index refresh failed.', 1);
}
return;
}
timeEl = $('#index-last-refresh time', Index.navLinks);
timeEl.dataset.utc = Date.parse(req.getResponseHeader('Last-Modified'));
RelativeDates.update(timeEl);
return Index.scrollToIndex();
},
parse: function(pages, state) {
$.cleanCache(function(url) {
return /^\/\/a\.4cdn\.org\//.test(url);
});
Index.parseThreadList(pages);
Index.buildThreads();
state || (state = {});
state.sort = true;
return Index.pageLoad(state);
},
parseThreadList: function(pages) {
Index.pagesNum = pages.length;
Index.threadsNumPerPage = pages[0].threads.length;
Index.liveThreadData = pages.reduce((function(arr, next) {
return arr.concat(next.threads);
}), []);
Index.liveThreadIDs = Index.liveThreadData.map(function(data) {
return data.no;
});
g.BOARD.threads.forEach(function(thread) {
var _ref;
if (_ref = thread.ID, __indexOf.call(Index.liveThreadIDs, _ref) < 0) {
return thread.collect();
}
});
},
buildThreads: function() {
var err, errors, i, posts, thread, threadData, threadRoot, threads, _i, _len, _ref;
Index.nodes = [];
threads = [];
posts = [];
_ref = Index.liveThreadData;
for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
threadData = _ref[i];
try {
threadRoot = Build.thread(g.BOARD, threadData);
if (Index.hat) {
$.prepend(threadRoot, Index.hat.cloneNode(false));
}
if (thread = g.BOARD.threads[threadData.no]) {
thread.setCount('post', threadData.replies + 1, threadData.bumplimit);
thread.setCount('file', threadData.images + !!threadData.ext, threadData.imagelimit);
thread.setStatus('Sticky', !!threadData.sticky);
thread.setStatus('Closed', !!threadData.closed);
} else {
thread = new Thread(threadData.no, g.BOARD);
threads.push(thread);
}
Index.nodes.push(threadRoot);
if (!(thread.ID in thread.posts)) {
posts.push(new Post($('.opContainer', threadRoot), thread, g.BOARD));
}
thread.setPage(Math.floor(i / Index.threadsNumPerPage) + 1);
} catch (_error) {
err = _error;
if (!errors) {
errors = [];
}
errors.push({
message: "Parsing of Thread No." + thread + " failed. Thread will be skipped.",
error: err
});
}
}
if (errors) {
Main.handleErrors(errors);
}
$.nodes(Index.nodes);
Main.callbackNodes(Thread, threads);
Main.callbackNodes(Post, posts);
Index.updateHideLabel();
return $.event('IndexRefresh');
},
buildReplies: function(threadRoots) {
var data, err, errors, i, lastReplies, node, nodes, post, posts, thread, threadRoot, _i, _j, _len, _len1;
posts = [];
for (_i = 0, _len = threadRoots.length; _i < _len; _i++) {
threadRoot = threadRoots[_i];
thread = Get.threadFromRoot(threadRoot);
i = Index.liveThreadIDs.indexOf(thread.ID);
if (!(lastReplies = Index.liveThreadData[i].last_replies)) {
continue;
}
nodes = [];
for (_j = 0, _len1 = lastReplies.length; _j < _len1; _j++) {
data = lastReplies[_j];
if (post = thread.posts[data.no]) {
nodes.push(post.nodes.root);
continue;
}
nodes.push(node = Build.postFromObject(data, thread.board.ID));
try {
posts.push(new Post(node, thread, thread.board));
} catch (_error) {
err = _error;
if (!errors) {
errors = [];
}
errors.push({
message: "Parsing of Post No." + data.no + " failed. Post will be skipped.",
error: err
});
}
}
$.add(threadRoot, nodes);
}
if (errors) {
Main.handleErrors(errors);
}
return Main.callbackNodes(Post, posts);
},
buildCatalogViews: function() {
var catalogThreads, thread, threads, _i, _len;
threads = Index.sortedNodes.map(function(threadRoot) {
return Get.threadFromRoot(threadRoot);
}).filter(function(thread) {
return !thread.isHidden !== Index.showHiddenThreads;
});
catalogThreads = [];
for (_i = 0, _len = threads.length; _i < _len; _i++) {
thread = threads[_i];
if (!thread.catalogView) {
catalogThreads.push(new CatalogThread(Build.catalogThread(thread), thread));
}
}
Main.callbackNodes(CatalogThread, catalogThreads);
return threads.map(function(thread) {
return thread.catalogView.nodes.root;
});
},
sizeCatalogViews: function(nodes) {
var height, node, ratio, size, thumb, width, _i, _len, _ref;
size = Conf['Index Size'] === 'small' ? 150 : 250;
for (_i = 0, _len = nodes.length; _i < _len; _i++) {
node = nodes[_i];
thumb = $('.catalog-thumb', node);
_ref = thumb.dataset, width = _ref.width, height = _ref.height;
if (!width) {
continue;
}
ratio = size / Math.max(width, height);
thumb.style.width = width * ratio + 'px';
thumb.style.height = height * ratio + 'px';
}
},
sort: function() {
var liveThreadData, liveThreadIDs, nodes, sortedNodes, sortedThreadIDs, threadID, _i, _len;
liveThreadIDs = Index.liveThreadIDs, liveThreadData = Index.liveThreadData;
sortedThreadIDs = {
lastreply: __slice.call(liveThreadData).sort(function(a, b) {
var num;
if ((num = a.last_replies)) {
a = num[num.length - 1];
}
if ((num = b.last_replies)) {
b = num[num.length - 1];
}
return b.no - a.no;
}).map(function(post) {
return post.no;
}),
bump: liveThreadIDs,
birth: __slice.call(liveThreadIDs).sort(function(a, b) {
return b - a;
}),
replycount: __slice.call(liveThreadData).sort(function(a, b) {
return b.replies - a.replies;
}).map(function(post) {
return post.no;
}),
filecount: __slice.call(liveThreadData).sort(function(a, b) {
return b.images - a.images;
}).map(function(post) {
return post.no;
})
}[Conf['Index Sort']];
Index.sortedNodes = sortedNodes = [];
nodes = Index.nodes;
for (_i = 0, _len = sortedThreadIDs.length; _i < _len; _i++) {
threadID = sortedThreadIDs[_i];
sortedNodes.push(nodes[Index.liveThreadIDs.indexOf(threadID)]);
}
if (Index.search && (nodes = Index.querySearch(Index.search))) {
Index.sortedNodes = nodes;
}
Index.sortOnTop(function(thread) {
return thread.isSticky;
});
Index.sortOnTop(function(thread) {
return thread.isOnTop || Conf['Pin Watched Threads'] && ThreadWatcher.isWatched(thread);
});
if (Conf['Anchor Hidden Threads']) {
return Index.sortOnTop(function(thread) {
return !thread.isHidden;
});
}
},
sortOnTop: function(match) {
var bottomNodes, threadRoot, topNodes, _i, _len, _ref;
topNodes = [];
bottomNodes = [];
_ref = Index.sortedNodes;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
threadRoot = _ref[_i];
(match(Get.threadFromRoot(threadRoot)) ? topNodes : bottomNodes).push(threadRoot);
}
return Index.sortedNodes = topNodes.concat(bottomNodes);
},
buildIndex: function() {
var i, nodes, page, post;
switch (Conf['Index Mode']) {
case 'all pages':
nodes = Index.sortedNodes;
break;
case 'catalog':
nodes = Index.buildCatalogViews();
Index.sizeCatalogViews(nodes);
break;
default:
if (Index.followedThreadID != null) {
i = 0;
while (Index.followedThreadID !== Get.threadFromRoot(Index.sortedNodes[i]).ID) {
i++;
}
page = Math.floor(i / Index.threadsNumPerPage) + 1;
if (page !== Index.getCurrentPage()) {
Index.pushState({
page: page
});
}
}
nodes = Index.buildSinglePage(Index.getCurrentPage());
}
$.rmAll(Index.root);
$.rmAll(Header.hover);
if (Conf['Index Mode'] === 'catalog') {
return $.add(Index.root, nodes);
} else {
if (Conf['Show Replies']) {
Index.buildReplies(nodes);
}
Index.buildStructure(nodes);
if ((Index.followedThreadID != null) && (post = g.posts["" + g.BOARD + "." + Index.followedThreadID])) {
return Header.scrollTo(post.nodes.root);
}
}
},
buildSinglePage: function(pageNum) {
var nodesPerPage, offset;
nodesPerPage = Index.threadsNumPerPage;
offset = nodesPerPage * (pageNum - 1);
return Index.sortedNodes.slice(offset, offset + nodesPerPage);
},
buildStructure: function(nodes) {
var node, _i, _len;
for (_i = 0, _len = nodes.length; _i < _len; _i++) {
node = nodes[_i];
$.add(Index.root, [node, $.el('hr')]);
}
if (doc.contains(Index.root)) {
$.event('PostsInserted');
}
return ThreadHiding.onIndexBuild(nodes);
},
clearSearch: function() {
Index.searchInput.value = '';
Index.onSearchInput();
return Index.searchInput.focus();
},
setupSearch: function(noUpdate) {
if (!noUpdate) {
Index.searchInput.value = Index.search;
}
if (Index.search) {
return Index.searchInput.dataset.searching = 1;
} else {
return Index.searchInput.removeAttribute('data-searching');
}
},
onSearchInput: function() {
var search;
search = Index.searchInput.value.trim();
if (search === Index.search) {
return;
}
return Index.pageLoad(Index.pushState({
search: search,
replace: !!search === !!Index.search
}));
},
querySearch: function(query) {
var keywords;
if (!(keywords = query.toLowerCase().match(/\S+/g))) {
return;
}
return Index.sortedNodes.filter(function(threadRoot) {
return Index.searchMatch(Get.threadFromRoot(threadRoot), keywords);
});
},
searchMatch: function(thread, keywords) {
var file, info, key, keyword, text, _i, _j, _len, _len1, _ref, _ref1;
_ref = thread.OP, info = _ref.info, file = _ref.file;
text = [];
_ref1 = ['comment', 'subject', 'name', 'tripcode', 'email'];
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
key = _ref1[_i];
if (key in info) {
text.push(info[key]);
}
}
if (file) {
text.push(file.name);
}
text = text.join(' ').toLowerCase();
for (_j = 0, _len1 = keywords.length; _j < _len1; _j++) {
keyword = keywords[_j];
if (-1 === text.indexOf(keyword)) {
return false;
}
}
return true;
}
};
Build = {
staticPath: '//s.4cdn.org/image/',
gifIcon: window.devicePixelRatio >= 2 ? '@2x.gif' : '.gif',
spoilerRange: {},
unescape: function(text) {
if (text == null) {
return text;
}
return text.replace(/<[^>]*>/g, '').replace(/&(amp|#039|quot|lt|gt);/g, function(c) {
return {
'&': '&',
''': "'",
'"': '"',
'<': '<',
'>': '>'
}[c];
});
},
shortFilename: function(filename) {
var ext, threshold;
threshold = 30;
ext = filename.match(/\.?[^\.]*$/)[0];
if (filename.length - ext.length > threshold) {
return "" + filename.slice(0, threshold - 5) + "(...)" + ext;
} else {
return filename;
}
},
sameThread: function(boardID, threadID) {
return g.VIEW === 'thread' && g.BOARD.ID === boardID && g.THREADID === +threadID;
},
postURL: function(boardID, threadID, postID) {
if (Build.sameThread(boardID, threadID)) {
return "#p" + postID;
} else {
return "/" + boardID + "/thread/" + threadID + "#p" + postID;
}
},
postFromObject: function(data, boardID) {
var o;
o = {
postID: data.no,
threadID: data.resto || data.no,
boardID: boardID,
name: Build.unescape(data.name),
capcode: data.capcode,
tripcode: data.trip,
uniqueID: data.id,
email: Build.unescape(data.email),
subject: Build.unescape(data.sub),
flagCode: data.country,
flagName: Build.unescape(data.country_name),
date: data.now,
dateUTC: data.time,
comment: {
innerHTML: data.com || ''
},
isSticky: !!data.sticky,
isClosed: !!data.closed,
isArchived: !!data.archived
};
if (data.filedeleted) {
o.file = {
isDeleted: true
};
} else if (data.ext) {
o.file = {
name: (Build.unescape(data.filename)) + data.ext,
timestamp: "" + data.tim + data.ext,
url: boardID === 'f' ? "//i.4cdn.org/" + boardID + "/" + (encodeURIComponent(data.filename)) + data.ext : "//i.4cdn.org/" + boardID + "/" + data.tim + data.ext,
height: data.h,
width: data.w,
MD5: data.md5,
size: data.fsize,
turl: "//i.4cdn.org/" + boardID + "/" + data.tim + "s.jpg",
theight: data.tn_h,
twidth: data.tn_w,
isSpoiler: !!data.spoiler,
isDeleted: false,
tag: data.tag
};
}
return Build.post(o);
},
post: function(o) {
/*
This function contains code from 4chan-JS (https://github.com/4chan/4chan-JS).
@license: https://github.com/4chan/4chan-JS/blob/master/LICENSE
*/
var boardID, capcode, capcodeClass, capcodeIcon, capcodeStart, comment, container, date, dateUTC, desktop2, email, emailField, emailProcessed, file, fileBlock, fileCont, fileDims, fileLink, fileSize, fileText, fileThumb, flag, flagCode, flagName, gifIcon, highlightPost, href, icons, isOP, match, message, name, nameBlock, nameClass, postID, postInfo, postLink, quote, quoteLink, replyLink, shortFilename, spoilerRange, staticPath, subject, subjectField, threadID, tripcode, tripcodeField, type, typeLC, uniqueID, userID, wholePost, _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, comment = o.comment, file = o.file;
name || (name = '');
subject || (subject = '');
isOP = postID === threadID;
staticPath = Build.staticPath, gifIcon = Build.gifIcon;
/* Name Block */
switch (capcode) {
case 'admin':
case 'admin_highlight':
capcodeClass = ' capcodeAdmin';
capcodeStart = {
innerHTML: " <strong class=\"capcode hand id_admin\" title=\"Highlight posts by the Administrator\">## Admin</strong>"
};
capcodeIcon = {
innerHTML: " <img src=\"" + E(staticPath) + "adminicon" + E(gifIcon) + "\" alt=\"Admin Icon\" title=\"This user is the 4chan Administrator.\" class=\"identityIcon retina\">"
};
break;
case 'mod':
capcodeClass = ' capcodeMod';
capcodeStart = {
innerHTML: " <strong class=\"capcode hand id_mod\" title=\"Highlight posts by Moderators\">## Mod</strong>"
};
capcodeIcon = {
innerHTML: " <img src=\"" + E(staticPath) + "modicon" + E(gifIcon) + "\" alt=\"Mod Icon\" title=\"This user is a 4chan Moderator.\" class=\"identityIcon retina\">"
};
break;
case 'developer':
capcodeClass = ' capcodeDeveloper';
capcodeStart = {
innerHTML: " <strong class=\"capcode hand id_developer\" title=\"Highlight posts by Developers\">## Developer</strong>"
};
capcodeIcon = {
innerHTML: " <img src=\"" + E(staticPath) + "developericon" + E(gifIcon) + "\" alt=\"Developer Icon\" title=\"This user is a 4chan Developer.\" class=\"identityIcon retina\">"
};
break;
case 'manager':
capcodeClass = ' capcodeManager';
capcodeStart = {
innerHTML: " <strong class=\"capcode hand id_manager\" title=\"Highlight posts by Managers\">## Manager</strong>"
};
capcodeIcon = {
innerHTML: " <img src=\"" + E(staticPath) + "managericon" + E(gifIcon) + "\" alt=\"Manager Icon\" title=\"This user is a 4chan Manager.\" class=\"identityIcon retina\">"
};
break;
default:
capcodeClass = '';
capcodeStart = {
innerHTML: ""
};
capcodeIcon = isOP && boardID === 'f' ? {
innerHTML: ""
} : {
innerHTML: " "
};
}
nameClass = capcode ? ' capcode' : '';
tripcodeField = tripcode ? {
innerHTML: " <span class=\"postertrip\">" + E(tripcode) + "</span>"
} : {
innerHTML: ""
};
emailField = {
innerHTML: "<span class=\"name" + E(nameClass) + "\">" + E(name) + "</span>" + tripcodeField.innerHTML + capcodeStart.innerHTML
};
if (email) {
emailProcessed = encodeURIComponent(email).replace(/%40/g, '@');
emailField = {
innerHTML: "<a href=\"mailto:" + E(emailProcessed) + "\" class=\"useremail\">" + emailField.innerHTML + "</a>"
};
}
userID = !capcode && uniqueID ? {
innerHTML: " <span class=\"posteruid id_" + E(uniqueID) + "\">(ID: <span class=\"hand\" title=\"Highlight posts by this ID\">" + E(uniqueID) + "</span>)</span>"
} : {
innerHTML: ""
};
flag = !flagCode ? {
innerHTML: ""
} : {
innerHTML: " <span title=\"" + E(flagName) + "\" class=\"flag flag-" + E(flagCode.toLowerCase()) + "\"></span>"
};
nameBlock = {
innerHTML: "<span class=\"nameBlock" + E(capcodeClass) + "\">" + emailField.innerHTML + capcodeIcon.innerHTML + userID.innerHTML + flag.innerHTML + "</span> "
};
/* Post Info */
subjectField = isOP || boardID === 'f' ? {
innerHTML: "<span class=\"subject\">" + E(subject) + "</span> "
} : {
innerHTML: ""
};
desktop2 = isOP && boardID === 'f' ? '' : ' desktop';
postLink = Build.postURL(boardID, threadID, postID);
quoteLink = Build.sameThread(boardID, threadID) ? "javascript:quote('" + (+postID) + "');" : "/" + boardID + "/thread/" + threadID + "#q" + postID;
icons = (function() {
var _i, _len, _ref, _results;
_ref = ['Sticky', 'Closed', 'Archived'];
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
type = _ref[_i];
if (!(o["is" + type] && !(type === 'Closed' && o.isArchived))) {
continue;
}
typeLC = type.toLowerCase();
_results.push({
innerHTML: " <img src=\"" + E(staticPath) + E(typeLC) + E(gifIcon) + "\" alt=\"" + E(type) + "\" title=\"" + E(type) + "\" class=\"" + E(typeLC) + "Icon retina\">"
});
}
return _results;
})();
replyLink = isOP && g.VIEW === 'index' ? {
innerHTML: " <span>[<a href=\"/" + E(boardID) + "/thread/" + E(threadID) + "\" class=\"replylink\">Reply</a>]</span>"
} : {
innerHTML: ""
};
postInfo = {
innerHTML: "<div class=\"postInfo desktop\" id=\"pi" + E(postID) + "\"><input type=\"checkbox\" name=\"" + E(postID) + "\" value=\"delete\"> " + subjectField.innerHTML + nameBlock.innerHTML + "<span class=\"dateTime\" data-utc=\"" + E(dateUTC) + "\">" + E(date) + "</span> <span class=\"postNum" + E(desktop2) + "\"><a href=\"" + E(postLink) + "\" title=\"Link to this post\">No.</a><a href=\"" + E(quoteLink) + "\" title=\"Reply to this post\">" + E(postID) + "</a>" + icons.map(function(x) {
return x.innerHTML;
}).join('') + replyLink.innerHTML + "</span></div>"
};
/* File Info */
fileCont = (file != null ? file.isDeleted : void 0) ? {
innerHTML: "<span class=\"fileThumb\"><img src=\"" + E(staticPath) + "filedeleted-res" + E(gifIcon) + "\" alt=\"File deleted.\" class=\"fileDeletedRes retina\"></span>"
} : file && boardID === 'f' ? {
innerHTML: "<div class=\"fileInfo\"><span class=\"fileText\" id=\"fT" + E(postID) + "\">File: <a data-width=\"" + E(file.width) + "\" data-height=\"" + E(file.height) + "\" href=\"" + E(file.url) + "\" target=\"_blank\">" + E(file.name) + "</a>-(" + E($.bytesToString(file.size)) + ", " + E(file.width) + "x" + E(file.height) + ", " + E(file.tag) + ")</span></div>"
} : file ? (file.isSpoiler ? (shortFilename = 'Spoiler Image', (spoilerRange = Build.spoilerRange[boardID]) ? fileThumb = "" + staticPath + "spoiler-" + boardID + (Math.floor(1 + spoilerRange * Math.random())) + ".png" : fileThumb = "" + staticPath + "spoiler.png", file.twidth = file.theight = 100) : (shortFilename = Build.shortFilename(file.name, !isOP), fileThumb = file.turl), fileSize = $.bytesToString(file.size), fileDims = file.url.slice(-4) === '.pdf' ? 'PDF' : "" + file.width + "x" + file.height, fileLink = file.isSpoiler || file.name === shortFilename ? {
innerHTML: "<a href=\"" + E(file.url) + "\" target=\"_blank\">" + E(shortFilename) + "</a>"
} : {
innerHTML: "<a title=\"" + E(file.name) + "\" href=\"" + E(file.url) + "\" target=\"_blank\">" + E(shortFilename) + "</a>"
}, fileText = file.isSpoiler ? {
innerHTML: "<div class=\"fileText\" id=\"fT" + E(postID) + "\" title=\"" + E(file.name) + "\">File: " + fileLink.innerHTML + " (" + E(fileSize) + ", " + E(fileDims) + ")</div>"
} : {
innerHTML: "<div class=\"fileText\" id=\"fT" + E(postID) + "\">File: " + fileLink.innerHTML + " (" + E(fileSize) + ", " + E(fileDims) + ")</div>"
}, {
innerHTML: fileText.innerHTML + "<a class=\"fileThumb" + E(file.isSpoiler ? " imgspoiler" : "") + "\" href=\"" + E(file.url) + "\" target=\"_blank\"><img src=\"" + E(fileThumb) + "\" alt=\"" + E(fileSize) + "\" data-md5=\"" + E(file.MD5) + "\" style=\"height: " + E(file.theight) + "px; width: " + E(file.twidth) + "px;\"></a>"
}) : void 0;
fileBlock = file ? {
innerHTML: "<div class=\"file\" id=\"f" + E(postID) + "\">" + fileCont.innerHTML + "</div>"
} : {
innerHTML: ""
};
/* Whole Post */
highlightPost = capcode === 'admin_highlight' ? ' highlightPost' : '';
message = {
innerHTML: "<blockquote class=\"postMessage\" id=\"m" + E(postID) + "\">" + comment.innerHTML + "</blockquote>"
};
wholePost = isOP ? {
innerHTML: "<div id=\"p" + E(postID) + "\" class=\"post op" + E(highlightPost) + "\">" + fileBlock.innerHTML + postInfo.innerHTML + message.innerHTML + "</div>"
} : {
innerHTML: "<div class=\"sideArrows\" id=\"sa" + E(postID) + "\">>></div><div id=\"p" + E(postID) + "\" class=\"post reply" + E(highlightPost) + "\">" + postInfo.innerHTML + fileBlock.innerHTML + message.innerHTML + "</div>"
};
container = $.el('div', {
className: "postContainer " + (isOP ? 'op' : 'reply') + "Container",
id: "pc" + postID
});
$.extend(container, wholePost);
_ref = $$('.quotelink', container);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
quote = _ref[_i];
href = quote.getAttribute('href');
if ((href[0] === '#') && !(Build.sameThread(boardID, threadID))) {
quote.href = ("/" + boardID + "/thread/" + threadID) + href;
} else if ((match = href.match(/^\/([^\/]+)\/thread\/(\d+)/)) && (Build.sameThread(match[1], match[2]))) {
quote.href = href.match(/(#[^#]*)?$/)[0] || '#';
}
}
return container;
},
summary: function(boardID, threadID, posts, files) {
var text;
text = [];
text.push("" + posts + " post" + (posts > 1 ? 's' : ''));
if (files) {
text.push("and " + files + " image repl" + (files > 1 ? 'ies' : 'y'));
}
text.push('omitted.');
return $.el('a', {
className: 'summary',
textContent: text.join(' '),
href: "/" + boardID + "/thread/" + threadID
});
},
thread: function(board, data, full) {
var OP, root;
Build.spoilerRange[board] = data.custom_spoiler;
if ((OP = board.posts[data.no]) && (root = OP.nodes.root.parentNode)) {
$.rmAll(root);
} else {
root = $.el('div', {
className: 'thread',
id: "t" + data.no
});
}
$.add(root, Build[full ? 'fullThread' : 'excerptThread'](board, data, OP));
return root;
},
excerptThread: function(board, data, OP) {
var files, nodes, posts, _ref;
nodes = [OP ? OP.nodes.root : Build.postFromObject(data, board.ID)];
if (data.omitted_posts || !Conf['Show Replies'] && data.replies) {
_ref = Conf['Show Replies'] ? [
data.omitted_posts, data.images - data.last_replies.filter(function(data) {
return !!data.ext;
}).length
] : [data.replies, data.images], posts = _ref[0], files = _ref[1];
nodes.push(Build.summary(board.ID, data.no, posts, files));
}
return nodes;
},
fullThread: function(board, data) {
return Build.postFromObject(data, board.ID);
},
catalogThread: function(thread) {
var br, cc, comment, data, exif, fileCount, gifIcon, href, imgClass, pageCount, postCount, pp, quote, root, spoilerRange, src, staticPath, subject, thumb, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3, _ref4;
staticPath = Build.staticPath, gifIcon = Build.gifIcon;
data = Index.liveThreadData[Index.liveThreadIDs.indexOf(thread.ID)];
if (data.spoiler && !Conf['Reveal Spoiler Thumbnails']) {
src = "" + staticPath + "spoiler";
if (spoilerRange = Build.spoilerRange[thread.board]) {
src += ("-" + thread.board) + Math.floor(1 + spoilerRange * Math.random());
}
src += '.png';
imgClass = 'spoiler-file';
} else if (data.filedeleted) {
src = "" + staticPath + "filedeleted-res" + gifIcon;
imgClass = 'deleted-file';
} else if (thread.OP.file) {
src = thread.OP.file.thumbURL;
} else {
src = "" + staticPath + "nofile.png";
imgClass = 'no-file';
}
thumb = imgClass ? {
innerHTML: "<img src=\"" + E(src) + "\" class=\"catalog-thumb " + E(imgClass) + "\">"
} : {
innerHTML: "<img src=\"" + E(src) + "\" class=\"catalog-thumb\" data-width=\"" + E(data.tn_w) + "\" data-height=\"" + E(data.tn_h) + "\">"
};
postCount = data.replies + 1;
fileCount = data.images + !!data.ext;
pageCount = Math.floor(Index.liveThreadIDs.indexOf(thread.ID) / Index.threadsNumPerPage) + 1;
subject = thread.OP.info.subject ? {
innerHTML: "<div class=\"subject\">" + E(thread.OP.info.subject) + "</div>"
} : {
innerHTML: ""
};
comment = {
innerHTML: data.com || ''
};
root = $.el('div', {
className: 'catalog-thread'
});
$.extend(root, {
innerHTML: "<a href=\"/" + E(thread.board) + "/thread/" + E(thread.ID) + "\">" + thumb.innerHTML + "</a><div class=\"catalog-stats\" title=\"Post count / File count / Page count\"><span class=\"post-count\">" + E(postCount) + "</span> / <span class=\"file-count\">" + E(fileCount) + "</span> / <span class=\"page-count\">" + E(pageCount) + "</span><span class=\"catalog-icons\"></span></div>" + subject.innerHTML + "<div class=\"comment\">" + comment.innerHTML + "</div>"
});
root.dataset.fullID = thread.fullID;
if (thread.OP.highlights) {
$.addClass.apply($, [root].concat(__slice.call(thread.OP.highlights)));
}
_ref = $$('.quotelink', root.lastElementChild);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
quote = _ref[_i];
href = quote.getAttribute('href');
if (href[0] === '#') {
quote.href = ("/" + thread.board + "/thread/" + thread.ID) + href;
}
}
_ref1 = $$('.abbr, .exif', root.lastElementChild);
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
exif = _ref1[_j];
$.rm(exif);
}
_ref2 = $$('.prettyprint', root.lastElementChild);
for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
pp = _ref2[_k];
cc = $.el('span', {
className: 'catalog-code'
});
$.add(cc, __slice.call(pp.childNodes));
$.replace(pp, cc);
}
_ref3 = $$('br', root.lastElementChild);
for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {
br = _ref3[_l];
if (((_ref4 = br.previousSibling) != null ? _ref4.nodeName : void 0) === 'BR') {
$.rm(br);
}
}
if (thread.isSticky) {
$.add($('.catalog-icons', root), $.el('img', {
src: "" + staticPath + "sticky" + gifIcon,
className: 'stickyIcon',
title: 'Sticky'
}));
}
if (thread.isClosed) {
$.add($('.catalog-icons', root), $.el('img', {
src: "" + staticPath + "closed" + gifIcon,
className: 'closedIcon',
title: 'Closed'
}));
}
if (data.bumplimit) {
$.addClass($('.post-count', root), 'warning');
}
if (data.imagelimit) {
$.addClass($('.file-count', root), 'warning');
}
return root;
}
};
Get = {
threadExcerpt: function(thread) {
var OP, excerpt, _ref;
OP = thread.OP;
excerpt = ("/" + thread.board + "/ - ") + (((_ref = OP.info.subject) != null ? _ref.trim() : void 0) || OP.info.comment.replace(/\n+/g, ' // ') || OP.info.nameBlock);
if (excerpt.length > 73) {
return "" + excerpt.slice(0, 70) + "...";
}
return excerpt;
},
threadFromRoot: function(root) {
return g.threads["" + g.BOARD + "." + root.id.slice(1)];
},
threadFromNode: function(node) {
return Get.threadFromRoot($.x('ancestor::div[@class="thread"]', node));
},
postFromRoot: function(root) {
var boardID, index, link, post, postID;
link = $('.postNum > a[href*="#"]', 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]|following::div[contains(@class,"postContainer")][1])', root));
},
contextFromNode: function(node) {
return Get.postFromRoot($.x('ancestor::div[parent::div[@class="thread"]][1]', node));
},
postDataFromLink: function(link) {
var boardID, path, postID, threadID, _ref;
if (link.hostname === 'boards.4chan.org') {
path = link.pathname.split('/');
boardID = path[1];
threadID = path[3];
postID = link.hash.slice(2);
} else {
_ref = link.dataset, boardID = _ref.boardID, threadID = _ref.threadID, postID = _ref.postID;
threadID || (threadID = 0);
}
return {
boardID: boardID,
threadID: +threadID,
postID: +postID
};
},
allQuotelinksLinkingTo: function(post) {
var fullID, handleQuotes, posts, qPost, quote, quotelinks, _i, _len, _ref;
quotelinks = [];
posts = g.posts;
fullID = post.fullID;
handleQuotes = function(qPost, type) {
var clone, _i, _len, _ref;
quotelinks.push.apply(quotelinks, qPost.nodes[type]);
_ref = qPost.clones;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
clone = _ref[_i];
quotelinks.push.apply(quotelinks, clone.nodes[type]);
}
};
posts.forEach(function(qPost) {
if (__indexOf.call(qPost.quotes, fullID) >= 0) {
return handleQuotes(qPost, 'quotelinks');
}
});
if (Conf['Quote Backlinks']) {
_ref = post.quotes;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
quote = _ref[_i];
if (qPost = posts[quote]) {
handleQuotes(qPost, 'backlinks');
}
}
}
return quotelinks.filter(function(quotelink) {
var boardID, postID, _ref1;
_ref1 = Get.postDataFromLink(quotelink), boardID = _ref1.boardID, postID = _ref1.postID;
return boardID === post.board.ID && postID === post.ID;
});
},
scriptData: function() {
var script, _i, _len, _ref;
_ref = $$('script:not([src])', d.head);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
script = _ref[_i];
if (/\bcooldowns *=/.test(script.textContent)) {
return script.textContent;
}
}
return '';
}
};
UI = (function() {
var Menu, checkbox, dialog, drag, dragend, dragstart, hover, hoverend, hoverstart, touchend, touchmove;
dialog = function(id, position, properties) {
var child, el, move, _i, _len, _ref;
el = $.el('div', {
className: 'dialog',
id: id
});
$.extend(el, properties);
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 currentMenu, lastToggledButton;
currentMenu = null;
lastToggledButton = null;
function Menu(type) {
this.type = type;
this.addEntry = __bind(this.addEntry, this);
this.onFocus = __bind(this.onFocus, this);
this.keybinds = __bind(this.keybinds, this);
this.close = __bind(this.close, this);
$.on(d, 'AddMenuEntry', (function(_this) {
return function(_arg) {
var detail;
detail = _arg.detail;
if (detail.type !== _this.type) {
return;
}
delete detail.open;
return _this.addEntry(detail);
};
})(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);
return menu;
};
Menu.prototype.toggle = function(e, button, data) {
var previousButton;
e.preventDefault();
e.stopPropagation();
if (currentMenu) {
previousButton = lastToggledButton;
currentMenu.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.menu = this.makeMenu();
currentMenu = this;
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);
}
$.addClass(lastToggledButton, 'active');
$.on(d, 'click scroll CloseMenu', this.close);
$.add(button, menu);
mRect = menu.getBoundingClientRect();
bRect = button.getBoundingClientRect();
bTop = window.scrollY + bRect.top;
bLeft = window.scrollX + 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);
};
Menu.prototype.close = function() {
$.rm(this.menu);
delete this.menu;
$.rmClass(lastToggledButton, 'active');
currentMenu = null;
lastToggledButton = null;
return $.off(d, 'click scroll 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 - second.style.order;
});
return entries[entries.indexOf(entry) + direction];
};
Menu.prototype.keybinds = function(e) {
var entry, next, nextPrev, subEntry, submenu;
entry = $('.focused', this.menu);
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.onFocus = function(e) {
e.stopPropagation();
return this.focus(e.target);
};
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 - 150 ? ['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(entry) {
this.parseEntry(entry);
return this.entries.push(entry);
};
Menu.prototype.parseEntry = function(entry) {
var el, subEntries, subEntry, _i, _len;
el = entry.el, subEntries = entry.subEntries;
$.addClass(el, 'entry');
$.on(el, 'focus mouseover', this.onFocus);
el.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, height, latestEvent, noRemove, o, root, _ref;
root = _arg.root, el = _arg.el, latestEvent = _arg.latestEvent, endEvents = _arg.endEvents, asapTest = _arg.asapTest, height = _arg.height, cb = _arg.cb, noRemove = _arg.noRemove;
o = {
root: root,
el: el,
style: el.style,
isImage: (_ref = el.nodeName) === 'IMG' || _ref === 'VIDEO',
cb: cb,
endEvents: endEvents,
latestEvent: latestEvent,
clientHeight: doc.clientHeight,
clientWidth: doc.clientWidth,
height: height,
noRemove: noRemove
};
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);
}
$.on(root, 'mousemove', o.hover);
o.workaround = function(e) {
if (!root.contains(e.target)) {
return o.hoverend(e);
}
};
return $.on(doc, 'mousemove', o.workaround);
};
hover = function(e) {
var clientX, clientY, height, left, right, style, threshold, top, _ref;
this.latestEvent = e;
height = this.height || this.el.offsetHeight;
clientX = e.clientX, clientY = e.clientY;
top = this.isImage ? Math.max(0, clientY * (this.clientHeight - height) / this.clientHeight) : Math.max(0, Math.min(this.clientHeight - height, clientY - 120));
threshold = this.clientWidth / 2;
if (!this.isImage) {
threshold = Math.max(threshold, this.clientWidth - 400);
}
_ref = clientX <= threshold ? [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;
}
if (!this.noRemove) {
$.rm(this.el);
}
$.off(this.root, this.endEvents, this.hoverend);
$.off(d, 'keydown', this.hoverend);
$.off(this.root, 'mousemove', this.hover);
$.off(doc, 'mousemove', this.workaround);
if (this.cb) {
return this.cb.call(this);
}
};
checkbox = function(name, text, checked) {
var input, label;
if (checked == null) {
checked = Conf[name];
}
label = $.el('label');
input = $.el('input', {
type: 'checkbox',
name: name,
checked: checked
});
$.add(label, [input, $.tn(" " + text)]);
return label;
};
return {
dialog: dialog,
Menu: Menu,
hover: hoverstart,
checkbox: checkbox
};
})();
CrossOrigin = (function() {
return {
binary: function(url, cb, headers) {
if (headers == null) {
headers = {};
}
return GM_xmlhttpRequest({
method: "GET",
url: url,
headers: headers,
overrideMimeType: "text/plain; charset=x-user-defined",
onload: function(xhr) {
var contentDisposition, contentType, data, i, r, _ref, _ref1;
r = xhr.responseText;
data = new Uint8Array(r.length);
i = 0;
while (i < r.length) {
data[i] = r.charCodeAt(i);
i++;
}
contentType = (_ref = xhr.responseHeaders.match(/Content-Type:\s*(.*)/i)) != null ? _ref[1] : void 0;
contentDisposition = (_ref1 = xhr.responseHeaders.match(/Content-Disposition:\s*(.*)/i)) != null ? _ref1[1] : void 0;
return cb(data, contentType, contentDisposition);
},
onerror: function() {
return cb(null);
},
onabort: function() {
return cb(null);
}
});
},
file: function(url, cb) {
return CrossOrigin.binary(url, function(data, contentType, contentDisposition) {
var blob, match, mime, name, _ref, _ref1, _ref2;
if (data == null) {
return cb(null);
}
name = (_ref = url.match(/([^\/]+)\/*$/)) != null ? _ref[1] : void 0;
mime = (contentType != null ? contentType.match(/[^;]*/)[0] : void 0) || 'application/octet-stream';
match = (contentDisposition != null ? (_ref1 = contentDisposition.match(/\bfilename\s*=\s*"((\\"|[^"])+)"/i)) != null ? _ref1[1] : void 0 : void 0) || (contentType != null ? (_ref2 = contentType.match(/\bname\s*=\s*"((\\"|[^"])+)"/i)) != null ? _ref2[1] : void 0 : void 0);
if (match) {
name = match.replace(/\\"/g, '"');
}
blob = new Blob([data], {
type: mime
});
blob.name = name;
return cb(blob);
});
},
json: (function() {
var callbacks, responses;
callbacks = {};
responses = {};
return function(url, cb) {
if (responses[url]) {
cb(responses[url]);
return;
}
if (callbacks[url]) {
callbacks[url].push(cb);
return;
}
callbacks[url] = [cb];
return GM_xmlhttpRequest({
method: "GET",
url: url + '',
onload: function(xhr) {
var response, _i, _len, _ref;
response = JSON.parse(xhr.responseText);
_ref = callbacks[url];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
cb = _ref[_i];
cb(response);
}
delete callbacks[url];
return responses[url] = response;
},
onerror: function() {
return delete callbacks[url];
},
onabort: function() {
return delete callbacks[url];
}
});
};
})()
};
})();
Anonymize = {
init: function() {
var _ref;
if (!(((_ref = g.VIEW) === 'index' || _ref === 'thread' || _ref === 'archive') && Conf['Anonymize'])) {
return;
}
if (g.VIEW === 'archive') {
return this.archive();
}
return Post.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) {
$.replace(email, name);
return delete this.nodes.email;
}
},
archive: function() {
return $.ready(function() {
var name, trip, _i, _j, _len, _len1, _ref, _ref1;
_ref = $$('.name');
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
name = _ref[_i];
name.textContent = 'Anonymous';
}
_ref1 = $$('.postertrip');
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
trip = _ref1[_j];
$.rm(trip);
}
});
}
};
Filter = {
filters: {},
init: function() {
var boards, err, filter, hl, key, line, op, regexp, stub, top, _i, _len, _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6;
if (!(((_ref = g.VIEW) === 'index' || _ref === 'thread') && Conf['Filter'])) {
return;
}
if (!Conf['Filtered Backlinks']) {
$.addClass(doc, 'hide-backlinks');
}
for (key in Config.filter) {
this.filters[key] = [];
_ref1 = Conf[key].split('\n');
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
line = _ref1[_i];
if (line[0] === '#') {
continue;
}
if (!(regexp = line.match(/\/(.+)\/(\w*)/))) {
continue;
}
filter = line.replace(regexp[0], '');
boards = ((_ref2 = filter.match(/boards:([^;]+)/)) != null ? _ref2[1].toLowerCase() : void 0) || 'global';
if (boards !== 'global' && (_ref3 = g.BOARD.ID, __indexOf.call(boards.split(','), _ref3) < 0)) {
continue;
}
if (key === 'uniqueID' || key === 'MD5') {
regexp = regexp[1];
} else {
try {
regexp = RegExp(regexp[1], regexp[2]);
} catch (_error) {
err = _error;
new Notice('warning', [$.tn("Invalid " + key + " filter:"), $.el('br'), $.tn(line), $.el('br'), $.tn(err.message)], 60);
continue;
}
}
op = ((_ref4 = filter.match(/[^t]op:(yes|no|only)/)) != null ? _ref4[1] : void 0) || 'yes';
stub = (function() {
var _ref5;
switch ((_ref5 = filter.match(/stub:(yes|no)/)) != null ? _ref5[1] : void 0) {
case 'yes':
return true;
case 'no':
return false;
default:
return Conf['Stubs'];
}
})();
if (hl = /highlight/.test(filter)) {
hl = ((_ref5 = filter.match(/highlight:([\w-]+)/)) != null ? _ref5[1] : void 0) || 'filter-highlight';
top = ((_ref6 = filter.match(/top:(yes|no)/)) != null ? _ref6[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.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, key, result, value, _i, _len, _ref, _ref1;
if (this.isClone || this.isFetchedQuote) {
return;
}
for (key in Filter.filters) {
if ((value = Filter[key](this)) !== false) {
_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.highlights && (_ref1 = result["class"], __indexOf.call(this.highlights, _ref1) >= 0))) {
(this.highlights || (this.highlights = [])).push(result["class"]);
}
if (!this.isReply && result.top) {
this.thread.isOnTop = true;
}
}
}
}
},
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;
},
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) {
var file;
file = post.file;
if (file && (file.isImage || file.isVideo)) {
return 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, _ref1;
if (!(((_ref = g.VIEW) === 'index' || _ref === 'thread') && Conf['Menu'] && Conf['Filter'])) {
return;
}
div = $.el('div', {
textContent: 'Filter'
});
entry = {
el: div,
order: 50,
open: function(post) {
Filter.menu.post = post;
return true;
},
subEntries: []
};
_ref1 = [['Name', 'name'], ['Unique ID', 'uniqueID'], ['Tripcode', 'tripcode'], ['Capcode', 'capcode'], ['Subject', 'subject'], ['Comment', 'comment'], ['Flag', 'flag'], ['Filename', 'filename'], ['Image dimensions', 'dimensions'], ['Filesize', 'filesize'], ['Image MD5', 'MD5']];
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
type = _ref1[_i];
entry.subEntries.push(Filter.menu.createSubEntry(type[0], type[1]));
}
return Menu.menu.addEntry(entry);
},
createSubEntry: function(text, type) {
var el;
el = $.el('a', {
href: 'javascript:;',
textContent: text
});
el.dataset.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 = type === 'uniqueID' || type === 'MD5' ? value : value.replace(/\/|\\|\^|\$|\n|\.|\(|\)|\{|\}|\[|\]|\?|\*|\+|\|/g, function(c) {
if (c === '\n') {
return '\\n';
} else if (c === '\\') {
return '\\\\';
} else {
return "\\" + c;
}
});
re = type === 'uniqueID' || type === 'MD5' ? "/" + 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() {
var _ref;
if (((_ref = g.VIEW) !== 'index' && _ref !== 'thread') || !Conf['Reply Hiding Buttons'] && !(Conf['Menu'] && Conf['Reply Hiding Link'])) {
return;
}
if (Conf['Reply Hiding Buttons']) {
$.addClass(doc, "reply-hide");
}
this.db = new DataBoard('hiddenPosts');
return Post.callbacks.push({
name: 'Reply Hiding',
cb: this.node
});
},
node: function() {
var data, sideArrows;
if (!this.isReply || this.isClone || this.isFetchedQuote) {
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;
}
sideArrows = $('.sideArrows', this.nodes.root);
$.replace(sideArrows.firstChild, PostHiding.makeButton(this, 'hide'));
return sideArrows.removeAttribute('class');
},
menu: {
init: function() {
var apply, div, hideStubLink, makeStub, replies, thisPost, _ref;
if (((_ref = g.VIEW) !== 'index' && _ref !== 'thread') || !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 = UI.checkbox('thisPost', 'This post', true);
replies = UI.checkbox('replies', 'Hide replies', Conf['Recursive Hiding']);
makeStub = UI.checkbox('makeStub', 'Make stub', Conf['Stubs']);
Menu.menu.addEntry({
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 = UI.checkbox('thisPost', 'This post', false);
replies = UI.checkbox('replies', 'Show replies', false);
hideStubLink = $.el('a', {
textContent: 'Hide stub',
href: 'javascript:;'
});
$.on(hideStubLink, 'click', PostHiding.menu.hideStub);
Menu.menu.addEntry({
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 Menu.menu.addEntry({
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 data, post;
post = PostHiding.menu.post;
if (data = PostHiding.db.get({
boardID: post.board.ID,
threadID: post.thread.ID,
postID: post.ID
})) {
PostHiding.show(post, data.hideRecursively);
PostHiding.hide(post, false, data.hideRecursively);
PostHiding.saveHiddenState(post, true, true, false, data.hideRecursively);
}
$.event('CloseMenu');
}
},
makeButton: function(post, type) {
var a, span;
span = $.el('span', {
className: "fa fa-" + (type === 'hide' ? 'minus' : 'plus') + "-square-o",
textContent: ""
});
a = $.el('a', {
className: "" + type + "-reply-button",
href: 'javascript:;'
});
$.add(a, span);
$.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);
PostHiding[(post.isHidden ? 'show' : 'hide')](post);
return PostHiding.saveHiddenState(post, post.isHidden);
},
hide: function(post, makeStub, hideRecursively) {
var a, 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');
$.add(a, $.tn(" " + post.info.nameBlock));
post.nodes.stub = $.el('div', {
className: 'stub'
});
$.add(post.nodes.stub, a);
if (Conf['Menu']) {
$.add(post.nodes.stub, 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() {
var _ref;
if ((_ref = g.VIEW) !== 'index' && _ref !== 'thread') {
return;
}
return Post.callbacks.push({
name: 'Recursive',
cb: this.node
});
},
node: function() {
var i, obj, quote, recursive, _i, _j, _len, _len1, _ref, _ref1;
if (this.isClone || this.isFetchedQuote) {
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)) {
continue;
}
obj.recursives.splice(i, 1);
obj.args.splice(i, 1);
}
},
apply: function() {
var args, fullID, post, recursive;
recursive = arguments[0], post = arguments[1], args = 3 <= arguments.length ? __slice.call(arguments, 2) : [];
fullID = post.fullID;
return g.posts.forEach(function(post) {
if (__indexOf.call(post.quotes, fullID) >= 0) {
return recursive.apply(null, [post].concat(__slice.call(args)));
}
});
}
};
ThreadHiding = {
init: function() {
var _ref;
if (((_ref = g.VIEW) !== 'index' && _ref !== 'catalog') || !Conf['Thread Hiding Buttons'] && !(Conf['Menu'] && Conf['Thread Hiding Link']) && !Conf['JSON Navigation']) {
return;
}
this.db = new DataBoard('hiddenThreads');
if (g.VIEW === 'catalog') {
return this.catalogWatch();
}
this.catalogSet(g.BOARD);
return Thread.callbacks.push({
name: 'Thread Hiding',
cb: this.node
});
},
catalogSet: function(board) {
var hiddenThreads, threadID;
hiddenThreads = ThreadHiding.db.get({
boardID: board.ID,
defaultValue: {}
});
for (threadID in hiddenThreads) {
hiddenThreads[threadID] = true;
}
return localStorage.setItem("4chan-hide-t-" + board, JSON.stringify(hiddenThreads));
},
catalogWatch: function() {
this.hiddenThreads = JSON.parse(localStorage.getItem("4chan-hide-t-" + g.BOARD)) || {};
return $.ready(function() {
return new MutationObserver(ThreadHiding.catalogSave).observe($.id('threads'), {
attributes: true,
subtree: true,
attributeFilter: ['style']
});
});
},
catalogSave: function() {
var hiddenThreads2, threadID;
hiddenThreads2 = JSON.parse(localStorage.getItem("4chan-hide-t-" + g.BOARD)) || {};
for (threadID in hiddenThreads2) {
if (!(threadID in ThreadHiding.hiddenThreads)) {
ThreadHiding.db.set({
boardID: g.BOARD.ID,
threadID: threadID,
val: {
makeStub: Conf['Stubs']
}
});
}
}
for (threadID in ThreadHiding.hiddenThreads) {
if (!(threadID in hiddenThreads2)) {
ThreadHiding.db["delete"]({
boardID: g.BOARD.ID,
threadID: threadID
});
}
}
return ThreadHiding.hiddenThreads = hiddenThreads2;
},
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'));
},
onIndexBuild: function(nodes) {
var root, thread, _i, _len;
for (_i = 0, _len = nodes.length; _i < _len; _i++) {
root = nodes[_i];
thread = Get.threadFromRoot(root);
if (thread.isHidden && thread.stub && !root.contains(thread.stub)) {
ThreadHiding.makeStub(thread, root);
}
}
},
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 = UI.checkbox('Stubs', 'Make stub');
Menu.menu.addEntry({
el: div,
order: 20,
open: function(_arg) {
var isReply, thread;
thread = _arg.thread, isReply = _arg.isReply;
if (isReply || thread.isHidden || Conf['JSON Navigation'] && Conf['Index Mode'] === 'catalog') {
return false;
}
ThreadHiding.menu.thread = thread;
return true;
},
subEntries: [
{
el: apply
}, {
el: makeStub
}
]
});
div = $.el('a', {
className: 'show-thread-link',
textContent: 'Show thread',
href: 'javascript:;'
});
$.on(div, 'click', ThreadHiding.menu.show);
Menu.menu.addEntry({
el: div,
order: 20,
open: function(_arg) {
var isReply, thread;
thread = _arg.thread, isReply = _arg.isReply;
if (isReply || !thread.isHidden || Conf['JSON Navigation'] && Conf['Index Mode'] === 'catalog') {
return false;
}
ThreadHiding.menu.thread = thread;
return true;
}
});
hideStubLink = $.el('a', {
textContent: 'Hide stub',
href: 'javascript:;'
});
$.on(hideStubLink, 'click', ThreadHiding.menu.hideStub);
return Menu.menu.addEntry({
el: hideStubLink,
order: 15,
open: function(_arg) {
var isReply, thread;
thread = _arg.thread, isReply = _arg.isReply;
if (isReply || !thread.isHidden || Conf['JSON Navigation'] && Conf['Index Mode'] === 'catalog') {
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');
},
show: function() {
var thread;
thread = ThreadHiding.menu.thread;
ThreadHiding.show(thread);
ThreadHiding.saveHiddenState(thread);
return $.event('CloseMenu');
},
hideStub: function() {
var thread;
thread = ThreadHiding.menu.thread;
ThreadHiding.show(thread);
ThreadHiding.hide(thread, false);
ThreadHiding.saveHiddenState(thread, false);
$.event('CloseMenu');
}
},
makeButton: function(thread, type) {
var a;
a = $.el('a', {
className: "" + type + "-thread-button",
href: 'javascript:;'
});
$.extend(a, {
innerHTML: "<span class=\"fa fa-" + E((type === "hide") ? "minus" : "plus") + "-square\"></span>"
});
a.dataset.fullID = thread.fullID;
$.on(a, 'click', ThreadHiding.toggle);
return a;
},
makeStub: function(thread, root) {
var a, numReplies, summary;
numReplies = $$('.thread > .replyContainer', root).length;
if (summary = $('.summary', root)) {
numReplies += +summary.textContent.match(/\d+/);
}
a = ThreadHiding.makeButton(thread, 'show');
$.add(a, $.tn(" " + thread.OP.info.nameBlock + " (" + (numReplies === 1 ? '1 reply' : "" + numReplies + " replies") + ")"));
thread.stub = $.el('div', {
className: 'stub'
});
if (Conf['Menu']) {
$.add(thread.stub, [a, Menu.makeButton(thread.OP)]);
} else {
$.add(thread.stub, a);
}
return $.prepend(root, thread.stub);
},
saveHiddenState: function(thread, makeStub) {
if (thread.isHidden) {
ThreadHiding.db.set({
boardID: thread.board.ID,
threadID: thread.ID,
val: {
makeStub: makeStub
}
});
} else {
ThreadHiding.db["delete"]({
boardID: thread.board.ID,
threadID: thread.ID
});
}
return ThreadHiding.catalogSet(thread.board);
},
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 threadRoot;
if (makeStub == null) {
makeStub = Conf['Stubs'];
}
if (thread.isHidden) {
return;
}
threadRoot = thread.OP.nodes.root.parentNode;
thread.isHidden = true;
if (Conf['JSON Navigation']) {
Index.updateHideLabel();
}
if (!makeStub) {
return threadRoot.hidden = true;
}
return ThreadHiding.makeStub(thread, threadRoot);
},
show: function(thread) {
var threadRoot;
if (thread.stub) {
$.rm(thread.stub);
delete thread.stub;
}
threadRoot = thread.OP.nodes.root.parentNode;
threadRoot.hidden = thread.isHidden = false;
if (Conf['JSON Navigation']) {
return Index.updateHideLabel();
}
}
};
QuoteBacklink = {
containers: {},
init: function() {
var _ref;
if (((_ref = g.VIEW) !== 'index' && _ref !== 'thread') || !Conf['Quote Backlinks']) {
return;
}
Post.callbacks.push({
name: 'Quote Backlinking Part 1',
cb: this.firstNode
});
return Post.callbacks.push({
name: 'Quote Backlinking Part 2',
cb: this.secondNode
});
},
firstNode: function() {
var a, clone, container, containers, hash, link, markYours, nodes, post, quote, _i, _j, _k, _len, _len1, _len2, _ref, _ref1;
if (this.isClone || !this.quotes.length || this.isRebuilt) {
return;
}
markYours = Conf['Quick Reply'] && Conf['Mark Quotes of You'] && QR.db.get({
boardID: this.board.ID,
threadID: this.thread.ID,
postID: this.ID
});
a = $.el('a', {
href: Build.postURL(this.board.ID, this.thread.ID, this.ID),
className: this.isHidden ? 'filtered backlink' : 'backlink',
textContent: Conf['backlink'].replace(/%(?:id|%)/g, (function(_this) {
return function(x) {
return {
'%id': _this.ID,
'%%': '%'
}[x];
};
})(this)) + (markYours ? '\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];
nodes = [$.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']) {
hash = QuoteInline.qiQuote(link, $.hasClass(link, 'filtered'));
nodes.push(hash);
}
}
$.add(container, nodes);
}
}
},
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() {
var _ref;
if (((_ref = g.VIEW) !== 'index' && _ref !== 'thread') || !Conf['Mark Cross-thread Quotes']) {
return;
}
if (Conf['Comment Expansion']) {
ExpandComment.callbacks.push(this.node);
}
this.text = '\u00A0(Cross-thread)';
return Post.callbacks.push({
name: 'Mark Cross-thread Quotes',
cb: this.node
});
},
node: function() {
var board, boardID, quotelink, thread, threadID, _i, _len, _ref, _ref1, _ref2;
if (this.isClone && this.thread === this.context.thread) {
return;
}
_ref = this.isClone ? this.context : this, board = _ref.board, thread = _ref.thread;
_ref1 = this.nodes.quotelinks;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
quotelink = _ref1[_i];
_ref2 = Get.postDataFromLink(quotelink), boardID = _ref2.boardID, threadID = _ref2.threadID;
if (!threadID) {
continue;
}
if (this.isClone) {
quotelink.textContent = quotelink.textContent.replace(QuoteCT.text, '');
}
if (boardID === board.ID && threadID !== thread.ID) {
$.add(quotelink, $.tn(QuoteCT.text));
}
}
}
};
QuoteInline = {
init: function() {
var _ref;
if (((_ref = g.VIEW) !== 'index' && _ref !== 'thread') || !Conf['Quote Inlining']) {
return;
}
this.process = Conf['Quote Hash Navigation'] ? function(link, clone) {
if (!clone) {
$.after(link, QuoteInline.qiQuote(link, $.hasClass(link, 'filtered')));
}
return $.on(link, 'click', QuoteInline.toggle);
} : function(link) {
return $.on(link, 'click', QuoteInline.toggle);
};
if (Conf['Comment Expansion']) {
ExpandComment.callbacks.push(this.node);
}
return Post.callbacks.push({
name: 'Quote Inlining',
cb: this.node
});
},
node: function() {
var isClone, link, process, _i, _j, _len, _len1, _ref, _ref1;
process = QuoteInline.process;
isClone = this.isClone;
_ref = this.nodes.quotelinks;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
link = _ref[_i];
process(link, isClone);
}
_ref1 = this.nodes.backlinks;
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
link = _ref1[_j];
process(link, isClone);
}
},
qiQuote: function(link, hidden) {
var name;
name = "hashlink";
if (hidden) {
name += " filtered";
}
return $.el('a', {
className: name,
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.contextFromNode(this);
if ($.hasClass(this, 'inlined')) {
QuoteInline.rm(this, boardID, threadID, postID, context);
} else {
if ($.x("ancestor::div[@id='pc" + 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');
new Fetcher(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() {
var _ref;
if (((_ref = g.VIEW) !== 'index' && _ref !== 'thread') || !Conf['Mark OP Quotes']) {
return;
}
if (Conf['Comment Expansion']) {
ExpandComment.callbacks.push(this.node);
}
this.text = '\u00A0(OP)';
return Post.callbacks.push({
name: 'Mark OP Quotes',
cb: this.node
});
},
node: function() {
var boardID, fullID, i, postID, quotelink, quotelinks, quotes, _ref, _ref1;
if (this.isClone && this.thread === this.context.thread) {
return;
}
if (!(quotes = this.quotes).length) {
return;
}
quotelinks = this.nodes.quotelinks;
if (this.isClone && (_ref = this.thread.fullID, __indexOf.call(quotes, _ref) >= 0)) {
i = 0;
while (quotelink = quotelinks[i++]) {
quotelink.textContent = quotelink.textContent.replace(QuoteOP.text, '');
}
}
fullID = (this.isClone ? this.context : this).thread.fullID;
if (__indexOf.call(quotes, fullID) < 0) {
return;
}
i = 0;
while (quotelink = quotelinks[i++]) {
_ref1 = Get.postDataFromLink(quotelink), boardID = _ref1.boardID, postID = _ref1.postID;
if (("" + boardID + "." + postID) === fullID) {
$.add(quotelink, $.tn(QuoteOP.text));
}
}
}
};
QuotePreview = {
init: function() {
var _ref;
if (!(((_ref = g.VIEW) === 'index' || _ref === 'thread') && Conf['Quote Previewing'])) {
return;
}
if (Conf['Comment Expansion']) {
ExpandComment.callbacks.push(this.node);
}
return Post.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);
new Fetcher(boardID, threadID, postID, qp, Get.contextFromNode(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() {
var _ref;
if (!(((_ref = g.VIEW) === 'index' || _ref === 'thread') && (Conf['Reply Hiding Buttons'] || (Conf['Menu'] && Conf['Reply Hiding Link']) || Conf['Filter']))) {
return;
}
return Post.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() {
if (!(Conf['Quote Threading'] && g.VIEW === 'thread')) {
return;
}
this.enabled = true;
this.controls = $.el('span', {
innerHTML: "<label><input id=\"threadingControl\" type=\"checkbox\" checked> Threading</label>"
});
this.threadNewLink = $.el('span', {
className: 'brackets-wrap threadnewlink',
hidden: true
});
$.extend(this.threadNewLink, {
innerHTML: "<a href=\"javascript:;\">Thread New Posts</a>"
});
this.input = $('input', this.controls);
$.on(this.input, 'change', this.rethread);
$.on(this.threadNewLink.firstElementChild, 'click', this.rethread);
Header.menu.addEntry(this.entry = {
el: this.controls,
order: 98
});
Thread.callbacks.push({
name: 'Quote Threading',
cb: this.setThread
});
return Post.callbacks.push({
name: 'Quote Threading',
cb: this.node
});
},
parent: {},
children: {},
inserted: {},
setThread: function() {
QuoteThreading.thread = this;
return $.asap((function() {
return !Conf['Thread Updater'] || $('.navLinksBot > .updatelink');
}), function() {
return $.add($('.navLinksBot'), [$.tn(' '), QuoteThreading.threadNewLink]);
});
},
node: function() {
var ancestor, lastParent, parent, parents, quote, _i, _len, _ref;
if (this.isFetchedQuote || this.isClone || !this.isReply) {
return;
}
parents = new Set();
lastParent = null;
_ref = this.quotes;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
quote = _ref[_i];
if (parent = g.posts[quote]) {
if (!parent.isFetchedQuote && parent.isReply && parent.ID < this.ID) {
parents.add(parent.ID);
if (!lastParent || parent.ID > lastParent.ID) {
lastParent = parent;
}
}
}
}
if (!lastParent) {
return;
}
ancestor = lastParent;
while (ancestor = QuoteThreading.parent[ancestor.fullID]) {
parents["delete"](ancestor.ID);
}
if (parents.size === 1) {
return QuoteThreading.parent[this.fullID] = lastParent;
}
},
descendants: function(post) {
var child, children, posts, _i, _len;
posts = [post];
if (children = QuoteThreading.children[post.fullID]) {
for (_i = 0, _len = children.length; _i < _len; _i++) {
child = children[_i];
posts = posts.concat(QuoteThreading.descendants(child));
}
}
return posts;
},
insert: function(post) {
var child, children, descendants, i, next, nodes, order, parent, prev, prev2, threadContainer, x, _base, _i, _j, _k, _len, _name;
if (!(QuoteThreading.enabled && (parent = QuoteThreading.parent[post.fullID]) && !QuoteThreading.inserted[post.fullID])) {
return false;
}
descendants = QuoteThreading.descendants(post);
if (!Unread.posts.has(parent.ID)) {
if ((function() {
var x, _i, _len;
for (_i = 0, _len = descendants.length; _i < _len; _i++) {
x = descendants[_i];
if (Unread.posts.has(x.ID)) {
return true;
}
}
})()) {
QuoteThreading.threadNewLink.hidden = false;
return false;
}
}
order = Unread.order;
children = ((_base = QuoteThreading.children)[_name = parent.fullID] || (_base[_name] = []));
threadContainer = parent.nodes.threadContainer || $.el('div', {
className: 'threadContainer'
});
nodes = [post.nodes.root];
if (post.nodes.threadContainer) {
nodes.push(post.nodes.threadContainer);
}
i = children.length;
for (_i = children.length - 1; _i >= 0; _i += -1) {
child = children[_i];
if (child.ID >= post.ID) {
i--;
}
}
if (i !== children.length) {
next = children[i];
for (_j = 0, _len = descendants.length; _j < _len; _j++) {
x = descendants[_j];
order.before(order[next.ID], order[x.ID]);
}
children.splice(i, 0, post);
$.before(next.nodes.root, nodes);
} else {
prev = parent;
while ((prev2 = QuoteThreading.children[prev.fullID]) && prev2.length) {
prev = prev2[prev2.length - 1];
}
for (_k = descendants.length - 1; _k >= 0; _k += -1) {
x = descendants[_k];
order.after(order[prev.ID], order[x.ID]);
}
children.push(post);
$.add(threadContainer, nodes);
}
QuoteThreading.inserted[post.fullID] = true;
if (!parent.nodes.threadContainer) {
parent.nodes.threadContainer = threadContainer;
$.addClass(parent.nodes.root, 'threadOP');
$.after(parent.nodes.root, threadContainer);
}
return true;
},
rethread: function() {
var nodes, posts, thread;
thread = QuoteThreading.thread;
posts = thread.posts;
QuoteThreading.threadNewLink.hidden = true;
if (QuoteThreading.enabled = QuoteThreading.input.checked) {
posts.forEach(QuoteThreading.insert);
} else {
nodes = [];
Unread.order = new RandomAccessList();
QuoteThreading.inserted = {};
posts.forEach(function(post) {
if (post.isFetchedQuote) {
return;
}
Unread.order.push(post);
if (post.isReply) {
nodes.push(post.nodes.root);
}
if (QuoteThreading.children[post.fullID]) {
delete QuoteThreading.children[post.fullID];
$.rmClass(post.nodes.root, 'threadOP');
$.rm(post.nodes.threadContainer);
return delete post.nodes.threadContainer;
}
});
$.add(thread.OP.nodes.root.parentNode, nodes);
}
Unread.position = Unread.order.first;
Unread.updatePosition();
Unread.setLine(true);
Unread.read();
return Unread.update();
}
};
QuoteYou = {
init: function() {
var _ref;
if (!(((_ref = g.VIEW) === 'index' || _ref === 'thread') && 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);
}
this.text = '\u00A0(You)';
return Post.callbacks.push({
name: 'Mark Quotes of You',
cb: this.node
});
},
node: function() {
var quotelink, _i, _len, _ref;
if (this.isClone) {
return;
}
if (QR.db.get({
boardID: this.board.ID,
threadID: this.thread.ID,
postID: this.ID
})) {
$.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)))) {
continue;
}
$.add(quotelink, $.tn(QuoteYou.text));
$.addClass(quotelink, 'you');
$.addClass(this.nodes.root, 'quotesYou');
}
},
cb: {
seek: function(type) {
var highlight, post, posts, result, str;
if (!(Conf['Mark Quotes of You'] && Conf['Quick Reply'])) {
return;
}
if (highlight = $('.highlight')) {
$.rmClass(highlight, 'highlight');
}
if (!QuoteYou.lastRead) {
if (!(post = QuoteYou.lastRead = $('.quotesYou'))) {
new Notice('warning', 'No posts are currently quoting you, loser.', 20);
return;
}
if (QuoteYou.cb.scroll(post)) {
return;
}
} else {
post = QuoteYou.lastRead;
}
str = "" + type + "::div[contains(@class,'quotesYou')]";
while (post = (result = $.X(str, post)).snapshotItem(type === 'preceding' ? result.snapshotLength - 1 : 0)) {
if (QuoteYou.cb.scroll(post)) {
return;
}
}
posts = $$('.quotesYou');
return QuoteYou.cb.scroll(posts[type === 'following' ? 0 : posts.length - 1]);
},
scroll: function(post) {
if (Get.postFromRoot(post).isHidden) {
return false;
} else {
QuoteYou.lastRead = post;
window.location = "#" + post.id;
Header.scrollTo(post);
$.addClass($('.post', post), 'highlight');
return true;
}
}
}
};
Quotify = {
init: function() {
var _ref;
if (((_ref = g.VIEW) !== 'index' && _ref !== 'thread') || !Conf['Resurrect Quotes']) {
return;
}
if (Conf['Comment Expansion']) {
ExpandComment.callbacks.push(this.node);
}
return Post.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, fetchable, m, post, postID, quote, quoteID, redirect, _ref;
if ($.hasClass(deadlink.parentNode, 'prettyprint')) {
Quotify.fixDeadlink(deadlink);
return;
}
quote = deadlink.textContent;
if (!(postID = (_ref = quote.match(/\d+$/)) != null ? _ref[0] : void 0)) {
return;
}
if (postID[0] === '0') {
Quotify.fixDeadlink(deadlink);
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: Build.postURL(boardID, post.thread.ID, postID),
className: 'quotelink',
textContent: quote
});
} else {
a = $.el('a', {
href: Build.postURL(boardID, post.thread.ID, postID),
className: 'quotelink deadlink',
target: '_blank',
textContent: "" + quote + "\u00A0(Dead)"
});
$.extend(a.dataset, {
boardID: boardID,
threadID: post.thread.ID,
postID: postID
});
}
} else {
redirect = Redirect.to('thread', {
boardID: boardID,
threadID: 0,
postID: postID
});
fetchable = Redirect.to('post', {
boardID: boardID,
postID: postID
});
if (redirect || fetchable) {
a = $.el('a', {
href: redirect || 'javascript:;',
className: 'deadlink',
target: '_blank',
textContent: "" + quote + "\u00A0(Dead)"
});
if (fetchable) {
$.addClass(a, 'quotelink');
$.extend(a.dataset, {
boardID: boardID,
postID: postID
});
}
}
}
if (__indexOf.call(this.quotes, quoteID) < 0) {
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);
}
},
fixDeadlink: function(deadlink) {
var el, green;
if (!(el = deadlink.previousSibling) || el.nodeName === 'BR') {
green = $.el('span', {
className: 'quote'
});
$.before(deadlink, green);
$.add(green, deadlink);
}
return $.replace(deadlink, __slice.call(deadlink.childNodes));
}
};
QR = {
mimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'application/pdf', 'application/vnd.adobe.flash.movie', 'application/x-shockwave-flash', 'video/webm'],
init: function() {
var noscript, sc;
if (!Conf['Quick Reply']) {
return;
}
this.db = new DataBoard('yourPosts');
this.posts = [];
if (g.VIEW === 'archive') {
return;
}
$.globalEval('document.documentElement.dataset.jsEnabled = true;');
noscript = Conf['Force Noscript Captcha'] || !doc.dataset.jsEnabled;
this.captcha = Captcha[noscript ? 'noscript' : 'v2'];
$.on(d, '4chanXInitFinished', this.initReady);
window.addEventListener('focus', this.focus, true);
window.addEventListener('blur', this.focus, true);
$.on(d, 'click', this.focus);
Post.callbacks.push({
name: 'Quick Reply',
cb: this.node
});
if (Conf['QR Shortcut']) {
this.shortcut = sc = $.el('a', {
className: 'qr-shortcut fa fa-comment-o disabled',
textContent: 'QR',
title: 'Quick Reply',
href: 'javascript:;'
});
$.on(sc, 'click', function() {
if (!QR.postingIsEnabled) {
return;
}
if (Conf['Persistent QR'] || !QR.nodes || QR.nodes.el.hidden) {
QR.open();
return QR.nodes.com.focus();
} else {
return QR.close();
}
});
Header.addShortcut(sc);
}
if (Conf['Hide Original Post Form']) {
$.addClass(doc, 'hide-original-post-form');
if (!doc.dataset.jsEnabled) {
return $.onExists(doc, '#postForm noscript', true, $.rm);
}
}
},
initReady: function() {
var link, linkBot;
$.off(d, '4chanXInitFinished', this.initReady);
QR.postingIsEnabled = !!$.id('postForm');
if (!QR.postingIsEnabled) {
return;
}
link = $.el('h1', {
className: "qr-link-container"
});
$.extend(link, {
innerHTML: "<a href=\"javascript:;\" class=\"qr-link\">" + E((g.VIEW === "thread") ? "Reply to Thread" : "Start a Thread") + "</a>"
});
QR.link = link.firstElementChild;
$.on(link.firstChild, 'click', function() {
QR.open();
return QR.nodes.com.focus();
});
if (Conf['Bottom QR Link'] && g.VIEW === 'thread') {
linkBot = $.el('div', {
className: "brackets-wrap qr-link-container-bottom"
});
$.extend(linkBot, {
innerHTML: "<a href=\"javascript:;\" class=\"qr-link-bottom\">Reply to Thread</a>"
});
$.on(linkBot.firstElementChild, 'click', function() {
QR.open();
return QR.nodes.com.focus();
});
$.prepend($('.navLinksBot'), linkBot);
}
$.before($.id('togglePostFormLink'), link);
$.on(d, 'paste', QR.paste);
$.on(d, 'dragover', QR.dragOver);
$.on(d, 'drop', QR.dropFile);
$.on(d, 'dragstart dragend', QR.drag);
$.on(d, 'IndexRefresh', QR.generatePostableThreadsList);
$.on(d, 'ThreadUpdate', QR.statusCheck);
if (!Conf['Persistent QR']) {
return;
}
QR.open();
if (Conf['Auto Hide QR']) {
return QR.hide();
}
},
statusCheck: function() {
var thread;
if (!QR.nodes) {
return;
}
thread = QR.posts[0].thread;
if (thread !== 'new' && g.threads["" + g.BOARD + "." + thread].isDead) {
return QR.abort();
} else {
return QR.status();
}
},
node: function() {
$.on(this.nodes.quote, 'click', QR.quote);
if (this.isFetchedQuote) {
return QR.generatePostableThreadsList();
}
},
open: function() {
var err;
if (QR.nodes) {
if (QR.nodes.el.hidden) {
QR.captcha.setup();
}
QR.nodes.el.hidden = false;
QR.unhide();
} else {
try {
QR.dialog();
} catch (_error) {
err = _error;
delete QR.nodes;
Main.handleErrors({
message: 'Quick Reply dialog creation crashed.',
error: err
});
return;
}
}
if (Conf['QR Shortcut']) {
return $.rmClass(QR.shortcut, 'disabled');
}
},
close: function() {
var post, _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['QR Shortcut']) {
$.addClass(QR.shortcut, 'disabled');
}
new QR.post(true);
_ref = QR.posts.splice(0, QR.posts.length - 1);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
post = _ref[_i];
post["delete"]();
}
QR.cooldown.auto = false;
QR.status();
return QR.captcha.destroy();
},
focus: function() {
return $.queueTask(function() {
var focus;
if (!QR.nodes) {
return;
}
if (!$$('.goog-bubble-content > iframe').some(function(el) {
return el.getBoundingClientRect().top >= 0;
})) {
focus = d.activeElement && QR.nodes.el.contains(d.activeElement);
$[focus ? 'addClass' : 'rmClass'](QR.nodes.el, 'focus');
}
if (typeof chrome !== "undefined" && chrome !== null) {
if (d.activeElement && QR.nodes.el.contains(d.activeElement) && d.activeElement.nodeName === 'IFRAME') {
QR.scrollY = window.scrollY;
return $.on(d, 'scroll', QR.scrollLock);
} else {
return $.off(d, 'scroll', QR.scrollLock);
}
}
});
},
scrollLock: function(e) {
if (d.activeElement && QR.nodes.el.contains(d.activeElement) && d.activeElement.nodeName === 'IFRAME') {
return window.scroll(window.scrollX, QR.scrollY);
} else {
return $.off(d, 'scroll', QR.scrollLock);
}
},
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.setup(true);
QR.captcha.notify(el);
} else {
QR.notify(el);
}
if (d.hidden) {
return alert(el.textContent);
}
},
notify: function(el) {
var notice, notif;
notice = new Notice('warning', el);
if (!(Header.areNotificationsEnabled && d.hidden)) {
return QR.notifications.push(notice);
} else {
notif = new Notification(el.textContent, {
body: el.textContent,
icon: Favicon.logo
});
return notif.onclick = function() {
return window.focus();
};
}
},
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, thread, value;
if (!QR.nodes) {
return;
}
thread = QR.posts[0].thread;
if (thread !== 'new' && g.threads["" + g.BOARD + "." + thread].isDead) {
value = 'Dead';
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;
},
quote: function(e) {
var ancestor, caretPos, com, frag, index, insideCode, node, post, range, sel, text, thread, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _len5, _m, _n, _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7;
if (e != null) {
e.preventDefault();
}
if (!QR.postingIsEnabled) {
return;
}
sel = d.getSelection();
post = Get.postFromNode(this);
text = post.board.ID === g.BOARD.ID ? ">>" + post + "\n" : ">>>/" + post.board + "/" + post + "\n";
if (sel.toString().trim() && post === Get.postFromNode(sel.anchorNode)) {
range = sel.getRangeAt(0);
frag = range.cloneContents();
ancestor = range.commonAncestorContainer;
if ($.x('ancestor-or-self::*[self::s or contains(@class,"removed-spoiler")]', ancestor)) {
$.prepend(frag, $.tn('[spoiler]'));
$.add(frag, $.tn('[/spoiler]'));
}
if (insideCode = $.x('ancestor-or-self::pre[contains(@class,"prettyprint")]', ancestor)) {
$.prepend(frag, $.tn('[code]'));
$.add(frag, $.tn('[/code]'));
}
_ref = $$((insideCode ? 'br' : '.prettyprint br'), frag);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
node = _ref[_i];
$.replace(node, $.tn('\n'));
}
_ref1 = $$('br', frag);
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
node = _ref1[_j];
if (node !== frag.lastChild) {
$.replace(node, $.tn('\n>'));
}
}
_ref2 = $$('s, .removed-spoiler', frag);
for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
node = _ref2[_k];
$.replace(node, [$.tn('[spoiler]')].concat(__slice.call(node.childNodes), [$.tn('[/spoiler]')]));
}
_ref3 = $$('.prettyprint', frag);
for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {
node = _ref3[_l];
$.replace(node, [$.tn('[code]')].concat(__slice.call(node.childNodes), [$.tn('[/code]')]));
}
_ref4 = $$('.linkify[data-original]', frag);
for (_m = 0, _len4 = _ref4.length; _m < _len4; _m++) {
node = _ref4[_m];
$.replace(node, $.tn(node.dataset.original));
}
_ref5 = $$('.embedder', frag);
for (_n = 0, _len5 = _ref5.length; _n < _len5; _n++) {
node = _ref5[_n];
if (((_ref6 = node.previousSibling) != null ? _ref6.nodeValue : void 0) === ' ') {
$.rm(node.previousSibling);
}
$.rm(node);
}
text += ">" + (frag.textContent.trim()) + "\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;
}
_ref7 = QR.nodes, com = _ref7.com, thread = _ref7.thread;
if (!com.value) {
thread.value = Get.threadFromNode(this);
}
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);
return QR.selected.save(thread);
},
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();
return QR.handleFiles(e.dataTransfer.files);
},
paste: function(e) {
var blob, files, item, _i, _len, _ref;
if (!e.clipboardData.items) {
return;
}
files = [];
_ref = e.clipboardData.items;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
item = _ref[_i];
if (!(item.kind === 'file')) {
continue;
}
blob = item.getAsFile();
blob.name = 'file';
if (blob.type) {
blob.name += '.' + blob.type.split('/')[1];
}
files.push(blob);
}
if (!files.length) {
return;
}
QR.open();
QR.handleFiles(files);
return $.addClass(QR.nodes.el, 'dump');
},
handleUrl: function() {
var url;
url = prompt('Enter a URL:');
if (url === null) {
return;
}
return CrossOrigin.file(url, function(blob) {
if (blob) {
return QR.handleFiles([blob]);
} else {
return QR.error("Can't load image.");
}
});
},
handleFiles: function(files) {
var file, i, _i, _len;
if (this !== QR) {
files = __slice.call(this.files);
this.value = null;
}
if (!files.length) {
return;
}
QR.cleanNotifications();
for (i = _i = 0, _len = files.length; _i < _len; i = ++_i) {
file = files[i];
QR.handleFile(file, i, files.length);
}
if (files.length !== 1) {
return $.addClass(QR.nodes.el, 'dump');
}
},
handleFile: function(file, index, nfiles) {
var isNewPost, isSingle, max, post, _ref;
isSingle = nfiles === 1;
if (/^text\//.test(file.type)) {
if (isSingle) {
post = QR.selected;
} else if (index !== 0 || (post = QR.posts[QR.posts.length - 1]).com) {
post = new QR.post();
}
post.pasteText(file);
return;
}
if (_ref = file.type, __indexOf.call(QR.mimeTypes, _ref) < 0) {
QR.error("" + file.name + ": Unsupported file type.");
if (!isSingle) {
return;
}
}
max = QR.nodes.fileInput.max;
if (/^video\//.test(file.type)) {
max = Math.min(max, QR.max_size_video);
}
if (file.size > max) {
QR.error("" + file.name + ": File too large (file: " + ($.bytesToString(file.size)) + ", max: " + ($.bytesToString(max)) + ").");
if (!isSingle) {
return;
}
}
isNewPost = false;
if (isSingle) {
post = QR.selected;
} else if (index !== 0 || (post = QR.posts[QR.posts.length - 1]).file) {
isNewPost = true;
post = new QR.post();
}
return QR.checkDimensions(file, function(pass, el) {
if (pass || isSingle) {
return post.setFile(file, el);
} else if (isNewPost) {
post.rm();
if (el) {
return URL.revokeObjectURL(el.src);
}
}
});
},
checkDimensions: function(file, cb) {
var img, video;
if (/^image\//.test(file.type)) {
img = new Image();
img.onload = function() {
var height, pass, width;
height = img.height, width = img.width;
pass = true;
if (height > QR.max_height || width > QR.max_width) {
QR.error("" + file.name + ": Image too large (image: " + height + "x" + width + "px, max: " + QR.max_height + "x" + QR.max_width + "px)");
pass = false;
}
if (height < QR.min_height || width < QR.min_width) {
QR.error("" + file.name + ": Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)");
pass = false;
}
return cb(pass, img);
};
img.onerror = function() {
return cb(false, null);
};
return img.src = URL.createObjectURL(file);
} else if (/^video\//.test(file.type)) {
video = $.el('video');
$.on(video, 'loadeddata', function() {
var duration, max_height, max_width, pass, videoHeight, videoWidth, _ref;
if (!cb) {
return;
}
videoHeight = video.videoHeight, videoWidth = video.videoWidth, duration = video.duration;
max_height = Math.min(QR.max_height, QR.max_height_video);
max_width = Math.min(QR.max_width, QR.max_width_video);
pass = true;
if (videoHeight > max_height || videoWidth > max_width) {
QR.error("" + file.name + ": Video too large (video: " + videoHeight + "x" + videoWidth + "px, max: " + max_height + "x" + max_width + "px)");
pass = false;
}
if (videoHeight < QR.min_height || videoWidth < QR.min_width) {
QR.error("" + file.name + ": Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)");
pass = false;
}
if (!isFinite(duration)) {
QR.error("" + file.name + ": Video lacks duration metadata (try remuxing)");
pass = false;
} else if (duration > QR.max_duration_video) {
QR.error("" + file.name + ": Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)");
pass = false;
}
if (((_ref = g.BOARD.ID) !== 'gif' && _ref !== 'wsg') && $.hasAudio(video)) {
QR.error("" + file.name + ": Audio not allowed");
pass = false;
}
cb(pass, video);
return cb = null;
});
$.on(video, 'error', function() {
var _ref;
if (!cb) {
return;
}
if (_ref = file.type, __indexOf.call(QR.mimeTypes, _ref) >= 0) {
QR.error("" + file.name + ": Video appears corrupt");
}
URL.revokeObjectURL(file);
cb(false, null);
return cb = null;
});
return video.src = URL.createObjectURL(file);
} else {
return cb(true, null);
}
},
openFileInput: function(e) {
var _ref;
e.stopPropagation();
if (e.shiftKey && e.type === 'click') {
return QR.selected.rmFile();
}
if ((e.ctrlKey || e.metaKey) && e.type === 'click') {
$.addClass(QR.nodes.filename, 'edit');
QR.nodes.filename.focus();
}
if (e.target.nodeName === 'INPUT' || (e.keyCode && ((_ref = e.keyCode) !== 32 && _ref !== 13)) || e.ctrlKey) {
return;
}
e.preventDefault();
return QR.nodes.fileInput.click();
},
generatePostableThreadsList: function() {
var list, options, thread, val, _i, _len, _ref;
if (!QR.nodes) {
return;
}
list = QR.nodes.thread;
options = [list.firstElementChild];
_ref = g.BOARD.threads.keys;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
thread = _ref[_i];
options.push($.el('option', {
value: thread,
textContent: "Thread No." + thread
}));
}
val = list.value;
$.rmAll(list);
$.add(list, options);
list.value = val;
if (list.value === val) {
return;
}
list.value = g.VIEW === 'thread' ? g.THREADID : 'new';
return (g.VIEW === 'thread' ? $.addClass : $.rmClass)(QR.nodes.el, 'reply-to-thread');
},
dialog: function() {
var dialog, event, i, items, m, match_max, match_min, name, node, nodes, rules, save, setNode, _ref;
QR.nodes = nodes = {
el: dialog = UI.dialog('qr', 'top: 50px; right: 0px;', {
innerHTML: "<div class=move><label><input type=checkbox id=autohide title=Auto-hide>Quick Reply</label><a href=javascript:; class=close title=Close>×</a><select data-name=thread title='Create a new thread / Reply'><option value=new>New thread</option></select></div><form><div class=persona><input name=name data-name=name list=\"list-name\" placeholder=Name class=field size=1><input name=email data-name=email list=\"list-email\" placeholder=Options class=field size=1><input name=sub data-name=sub list=\"list-sub\" placeholder=Subject class=field size=1></div><div class=textarea><textarea data-name=com placeholder=Comment class=field></textarea><span id=char-count></span></div><div id=dump-list-container><div id=dump-list></div><a id=add-post href=javascript:; title=\"Add a post\">+</a></div><div id=file-n-submit><span id=qr-filename-container class=field tabindex=0><span id=qr-no-file>No selected file</span><input id=\"qr-filename\" data-name=\"filename\" spellcheck=\"false\"><span id=qr-extras-container><a id=qr-filerm href=javascript:; title='Remove file'><i class=\"fa fa-times-circle\"></i></a><a id=url-button title='Post from url'><i class=\"fa fa-link\"></i></a><a id=dump-button title='Dump list'><i class=\"fa fa-plus-square\"></i></a></span></span><label id=qr-spoiler-label><input type=checkbox id=qr-file-spoiler title='Spoiler image'></label><input type=submit></div><input type=file multiple></form><datalist id=\"list-name\"></datalist><datalist id=\"list-email\"></datalist><datalist id=\"list-sub\"></datalist> "
})
};
setNode = function(name, query) {
return nodes[name] = $(query, dialog);
};
setNode('move', '.move');
setNode('autohide', '#autohide');
setNode('thread', 'select');
setNode('threadPar', '#qr-thread-select');
setNode('close', '.close');
setNode('form', 'form');
setNode('dumpButton', '#dump-button');
setNode('urlButton', '#url-button');
setNode('name', '[data-name=name]');
setNode('email', '[data-name=email]');
setNode('sub', '[data-name=sub]');
setNode('com', '[data-name=com]');
setNode('dumpList', '#dump-list');
setNode('addPost', '#add-post');
setNode('charCount', '#char-count');
setNode('fileSubmit', '#file-n-submit');
setNode('filename', '#qr-filename');
setNode('fileContainer', '#qr-filename-container');
setNode('fileRM', '#qr-filerm');
setNode('fileExtras', '#qr-extras-container');
setNode('spoiler', '#qr-file-spoiler');
setNode('spoilerPar', '#qr-spoiler-label');
setNode('status', '[type=submit]');
setNode('fileInput', '[type=file]');
rules = $('ul.rules').textContent.trim();
match_min = rules.match(/.+smaller than (\d+)x(\d+).+/);
match_max = rules.match(/.+greater than (\d+)x(\d+).+/);
QR.min_width = +(match_min != null ? match_min[1] : void 0) || 1;
QR.min_height = +(match_min != null ? match_min[2] : void 0) || 1;
QR.max_width = +(match_max != null ? match_max[1] : void 0) || 10000;
QR.max_height = +(match_max != null ? match_max[2] : void 0) || 10000;
nodes.fileInput.max = $('input[name=MAX_FILE_SIZE]').value;
QR.max_size_video = (m = Get.scriptData().match(/\bmaxWebmFilesize *= *(\d+)\b/)) ? +m[1] : +nodes.fileInput.max;
QR.max_width_video = QR.max_height_video = 2048;
QR.max_duration_video = (_ref = g.BOARD.ID) === 'gif' || _ref === 'wsg' ? 300 : 120;
if (Conf['Show New Thread Option in Threads']) {
$.addClass(QR.nodes.el, 'show-new-thread-option');
}
if (Conf['Show Name and Subject']) {
$.addClass(QR.nodes.name, 'force-show');
$.addClass(QR.nodes.sub, 'force-show');
QR.nodes.email.placeholder = 'E-mail';
}
QR.forcedAnon = !!$('form[name="post"] input[name="name"][type="hidden"]');
if (QR.forcedAnon) {
$.addClass(QR.nodes.el, 'forced-anon');
}
QR.spoiler = !!$('.postForm input[name=spoiler]');
if (QR.spoiler) {
$.addClass(QR.nodes.el, 'has-spoiler');
} else {
nodes.spoiler.parentElement.hidden = true;
}
if (g.BOARD.ID === 'f' && g.VIEW !== 'thread') {
nodes.flashTag = $.el('select', {
name: 'filetag'
});
$.extend(nodes.flashTag, {
innerHTML: "<option value=\"0\">Hentai</option><option value=\"6\">Porn</option><option value=\"1\">Japanese</option><option value=\"2\">Anime</option><option value=\"3\">Game</option><option value=\"5\">Loop</option><option value=\"4\" selected>Other</option>"
});
nodes.flashTag.dataset["default"] = '4';
$.add(nodes.form, nodes.flashTag);
}
$.on(nodes.filename.parentNode, 'click keydown', QR.openFileInput);
$.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.urlButton, 'click', QR.handleUrl);
$.on(nodes.addPost, 'click', function() {
return new QR.post(true);
});
$.on(nodes.form, 'submit', QR.submit);
$.on(nodes.filename, 'blur', function() {
return $.rmClass(this, 'edit');
});
$.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.handleFiles);
items = ['thread', 'name', 'email', 'sub', 'com', 'filename'];
i = 0;
save = function() {
return QR.selected.save(this);
};
while (name = items[i++]) {
if (!(node = nodes[name])) {
continue;
}
event = node.nodeName === 'SELECT' ? 'change' : 'input';
$.on(nodes[name], event, save);
}
if (Conf['Remember QR Size']) {
$.get('QR Size', '', function(item) {
return nodes.com.style.cssText = item['QR Size'];
});
$.on(nodes.com, 'mouseup', function(e) {
if (e.button !== 0) {
return;
}
return $.set('QR Size', this.style.cssText);
});
}
QR.generatePostableThreadsList();
QR.persona.init();
new QR.post(true);
QR.status();
QR.cooldown.init();
QR.captcha.init();
$.add(d.body, dialog);
QR.captcha.setup();
return $.event('QRDialogCreation', null, dialog);
},
submit: function(e) {
var captcha, cb, err, extra, filetag, formData, options, post, textOnly, thread, threadID;
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' && g.VIEW !== 'thread') {
filetag = QR.nodes.flashTag.value;
}
threadID = post.thread;
thread = g.BOARD.threads[threadID];
if (threadID === 'new') {
threadID = null;
if (g.BOARD.ID === 'vg' && !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.';
}
if (QR.captcha.isEnabled && !err) {
captcha = QR.captcha.getOne();
if (!captcha) {
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();
formData = {
resto: threadID,
name: !QR.forcedAnon ? post.name : void 0,
email: post.email,
sub: !(QR.forcedAnon || threadID) ? post.sub : void 0,
com: post.com,
upfile: post.file,
filetag: filetag,
spoiler: post.spoiler,
textonly: textOnly,
mode: 'regist',
pwd: QR.persona.pwd
};
options = {
responseType: 'document',
withCredentials: true,
onload: QR.response,
onerror: function() {
delete QR.req;
post.unlock();
QR.cooldown.auto = false;
QR.status();
return QR.error($.el('span', {
innerHTML: "4chan X encountered an error while posting. [<a href=\"//4chan.org/banned\" target=\"_blank\">Banned?</a>] [<a href=\"" + E(g.FAQ) + "#what-does-4chan-x-encountered-an-error-while-posting-please-try-again-mean\" target=\"_blank\">More info</a>]"
}));
}
};
extra = {
form: $.formData(formData),
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();
}
}
};
cb = function(response) {
if (response != null) {
extra.form.append('g-recaptcha-response', response);
}
QR.req = $.ajax("https://sys.4chan.org/" + g.BOARD + "/post", options, extra);
return QR.req.progress = '...';
};
if (typeof captcha === 'function') {
QR.req = {
progress: '...',
abort: function() {
return cb = null;
}
};
captcha(function(response) {
if (response) {
return typeof cb === "function" ? cb(response) : void 0;
} else {
delete QR.req;
post.unlock();
QR.cooldown.auto = !!QR.captcha.captchas.length;
return QR.status();
}
});
} else {
cb(captcha);
}
return QR.status();
},
response: function() {
var URL, ban, captchasCount, err, h1, isReply, m, notif, post, postID, postsCount, req, resDoc, threadID, _, _ref, _ref1;
req = QR.req;
delete QR.req;
post = QR.posts[0];
post.unlock();
resDoc = req.response;
if (ban = $('.banType', resDoc)) {
err = $.el('span', ban.textContent.toLowerCase() === 'banned' ? {
innerHTML: "You are banned on " + $(".board", resDoc).innerHTML + "! ;_;<br>Click <a href=\"//www.4chan.org/banned\" target=\"_blank\">here</a> to see the reason."
} : {
innerHTML: "You were issued a warning on " + $(".board", resDoc).innerHTML + " as " + $(".nameBlock", resDoc).innerHTML + ".<br>Reason: " + $(".reason", resDoc).innerHTML
});
} else if (err = resDoc.getElementById('errmsg')) {
if ((_ref = $('a', err)) != null) {
_ref.target = '_blank';
}
} else if (resDoc.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.';
} else if (/expired/i.test(err.textContent)) {
err = 'This CAPTCHA is no longer valid because it has expired.';
}
QR.cooldown.auto = QR.captcha.isEnabled ? !!QR.captcha.captchas.length : err === 'Connection error with sys.4chan.org.' ? true : false;
QR.cooldown.addDelay(post, 2);
} else if (err.textContent && (m = err.textContent.match(/wait\s+(\d+)\s+second/i)) && !/duplicate/i.test(err.textContent)) {
QR.cooldown.auto = QR.captcha.isEnabled ? !!QR.captcha.captchas.length : true;
QR.cooldown.addDelay(post, +m[1]);
QR.captcha.setup(d.activeElement === QR.nodes.status);
} else {
QR.cooldown.auto = false;
}
QR.status();
QR.error(err);
return;
}
h1 = $('h1', resDoc);
QR.cleanNotifications();
if (Conf['Posting Success Notifications']) {
QR.notifications.push(new Notice('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', {
boardID: g.BOARD.ID,
threadID: threadID,
postID: postID
});
$.event('QRPostSuccessful_', {
boardID: g.BOARD.ID,
threadID: threadID,
postID: postID
});
postsCount = QR.posts.length - 1;
QR.cooldown.auto = postsCount && isReply;
if (QR.cooldown.auto && QR.captcha.isEnabled && (captchasCount = QR.captcha.captchas.length) < 3 && captchasCount < postsCount) {
notif = new Notification('Quick reply warning', {
body: "You are running low on cached captchas. Cache count: " + captchasCount + ".",
icon: Favicon.logo
});
notif.onclick = function() {
QR.open();
window.focus();
return QR.captcha.setup(true);
};
notif.onshow = function() {
return setTimeout(function() {
return notif.close();
}, 7 * $.SECOND);
};
}
if (!(Conf['Persistent QR'] || postsCount)) {
QR.close();
} else {
post.rm();
QR.captcha.setup(d.activeElement === QR.nodes.status);
}
QR.cooldown.add(req.uploadEndTime, threadID, postID);
URL = threadID === postID ? "" + window.location.origin + "/" + g.BOARD + "/thread/" + threadID : g.VIEW === 'index' && !QR.cooldown.auto && Conf['Open Post in New Tab'] ? "" + window.location.origin + "/" + g.BOARD + "/thread/" + threadID + "#p" + postID : void 0;
if (URL) {
if (Conf['Open Post in New Tab'] || postsCount) {
$.open(URL);
} else {
window.location = URL;
}
}
return QR.status();
},
abort: function() {
if (QR.req && !QR.req.isUploadFinished) {
QR.req.abort();
delete QR.req;
QR.posts[0].unlock();
QR.cooldown.auto = false;
QR.notifications.push(new Notice('info', 'QR upload aborted.', 5));
}
return QR.status();
}
};
Captcha = {};
Captcha.noscript = {
lifetime: 2 * $.MINUTE,
iframeURL: '//www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc',
init: function() {
var container, input;
if (d.cookie.indexOf('pass_enabled=1') >= 0) {
return;
}
if (!(this.isEnabled = !!$.id('g-recaptcha'))) {
return;
}
container = $.el('div', {
className: 'captcha-img',
title: 'Reload reCAPTCHA'
});
input = $.el('input', {
className: 'captcha-input field',
title: 'Verification',
autocomplete: 'off',
spellcheck: false
});
this.nodes = {
container: container,
input: input
};
$.on(input, 'keydown', this.keydown.bind(this));
$.on(this.nodes.container, 'click', (function(_this) {
return function() {
_this.reload();
return _this.nodes.input.focus();
};
})(this));
this.conn = new Connection(null, "" + location.protocol + "//www.google.com", {
challenge: this.load.bind(this),
token: this.save.bind(this),
error: this.error.bind(this)
});
$.addClass(QR.nodes.el, 'has-captcha');
$.after(QR.nodes.com.parentNode, [container, input]);
this.captchas = [];
$.get('captchas', [], function(_arg) {
var captchas;
captchas = _arg.captchas;
QR.captcha.sync(captchas);
return QR.captcha.clear();
});
$.sync('captchas', this.sync);
this.beforeSetup();
return this.setup();
},
initFrame: function() {
var cb, conn, img, _ref, _ref1;
conn = new Connection(window.top, "" + location.protocol + "//boards.4chan.org", {
response: function(response) {
$.id('response').value = response;
return $('.fbc-challenge > form').submit();
}
});
conn.send({
token: (_ref = $('.fbc-verification-token > textarea')) != null ? _ref.value : void 0,
error: (_ref1 = $('.fbc-error')) != null ? _ref1.textContent : void 0
});
if (!(img = $('.fbc-payload > img'))) {
return;
}
cb = function() {
var canvas;
canvas = $.el('canvas');
canvas.width = img.width;
canvas.height = img.height;
canvas.getContext('2d').drawImage(img, 0, 0);
return conn.send({
challenge: canvas.toDataURL()
});
};
if (img.complete) {
return cb();
} else {
return $.on(img, 'load', cb);
}
},
timers: {},
cb: {
focus: function() {
return QR.captcha.setup(false, true);
}
},
beforeSetup: function() {
var container, input, _ref;
_ref = this.nodes, container = _ref.container, input = _ref.input;
container.hidden = true;
input.value = '';
input.placeholder = 'Focus to load reCAPTCHA';
this.count();
return $.on(input, 'focus click', this.cb.focus);
},
needed: function() {
var captchaCount, postsCount;
captchaCount = this.captchas.length;
if (QR.req) {
captchaCount++;
}
postsCount = QR.posts.length;
if (postsCount === 1 && !Conf['Auto-load captcha'] && !QR.posts[0].com && !QR.posts[0].file) {
postsCount = 0;
}
return captchaCount < postsCount;
},
onNewPost: function() {},
onPostChange: function() {},
setup: function(focus, force) {
if (!(this.isEnabled && (this.needed() || force))) {
return;
}
if (!this.nodes.iframe) {
this.nodes.iframe = $.el('iframe', {
id: 'qr-captcha-iframe',
src: this.iframeURL
});
$.add(d.body, this.nodes.iframe);
this.conn.target = this.nodes.iframe.contentWindow;
} else if (!this.occupied || force) {
this.nodes.iframe.src = this.iframeURL;
}
this.occupied = true;
if (focus) {
return this.nodes.input.focus();
}
},
afterSetup: function() {
var container, input, _ref;
_ref = this.nodes, container = _ref.container, input = _ref.input;
container.hidden = false;
input.placeholder = 'Verification';
this.count();
$.off(input, 'focus click', this.cb.focus);
if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) {
QR.nodes.el.style.top = '';
return QR.nodes.el.style.bottom = '0px';
}
},
destroy: function() {
if (!this.isEnabled) {
return;
}
if (this.nodes.img) {
$.rm(this.nodes.img);
}
delete this.nodes.img;
if (this.nodes.iframe) {
$.rm(this.nodes.iframe);
}
delete this.nodes.iframe;
delete this.occupied;
this.unflag();
return this.beforeSetup();
},
sync: function(captchas) {
if (captchas == null) {
captchas = [];
}
QR.captcha.captchas = captchas;
return QR.captcha.count();
},
getOne: function() {
var captcha;
this.clear();
if (captcha = this.captchas.shift()) {
this.count();
$.set('captchas', this.captchas);
return captcha.response;
} else if (/\S/.test(this.nodes.input.value)) {
return (function(_this) {
return function(cb) {
_this.submitCB = cb;
return _this.sendResponse();
};
})(this);
} else {
return null;
}
},
sendResponse: function() {
var response;
response = this.nodes.input.value;
if (/\S/.test(response)) {
return this.conn.send({
response: response
});
}
},
save: function(token) {
delete this.occupied;
this.nodes.input.value = '';
if (this.submitCB) {
this.submitCB(token);
delete this.submitCB;
if (this.needed()) {
return this.reload();
} else {
return this.destroy();
}
} else {
$.forceSync('captchas');
this.captchas.push({
response: token,
timeout: this.timeout
});
this.count();
$.set('captchas', this.captchas);
return this.reload();
}
},
error: function(message) {
this.occupied = true;
this.nodes.input.value = '';
if (this.submitCB) {
this.submitCB();
delete this.submitCB;
}
return QR.error("Captcha Error: " + message);
},
notify: function(el) {
if (Conf['Captcha Warning Notifications'] && !d.hidden) {
return QR.notify(el);
} else {
$.addClass(this.nodes.input, 'error');
return $.one(this.nodes.input, 'keydown', this.unflag.bind(this));
}
},
unflag: function() {
return $.rmClass(this.nodes.input, 'error');
},
clear: function() {
var captcha, i, now, _i, _len, _ref;
if (!this.captchas.length) {
return;
}
$.forceSync('captchas');
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(src) {
var container, img, input, _ref;
_ref = this.nodes, container = _ref.container, input = _ref.input, img = _ref.img;
this.occupied = true;
this.timeout = Date.now() + this.lifetime;
if (!img) {
img = this.nodes.img = new Image;
$.one(img, 'load', this.afterSetup.bind(this));
$.on(img, 'load', function() {
return this.hidden = false;
});
$.add(container, img);
}
img.src = src;
input.value = '';
this.clear();
clearTimeout(this.timers.expire);
return this.timers.expire = setTimeout(this.expire.bind(this), this.lifetime);
},
count: function() {
var count, placeholder;
count = this.captchas ? this.captchas.length : 0;
placeholder = this.nodes.input.placeholder.replace(/\ \(.*\)$/, '');
placeholder += (function() {
switch (count) {
case 0:
if (placeholder === 'Verification') {
return ' (Shift + Enter to cache)';
} else {
return '';
}
break;
case 1:
return ' (1 cached captcha)';
default:
return " (" + count + " cached captchas)";
}
})();
this.nodes.input.placeholder = placeholder;
this.nodes.input.alt = count;
clearTimeout(this.timers.clear);
if (this.captchas.length) {
return this.timers.clear = setTimeout(this.clear.bind(this), this.captchas[0].timeout - Date.now());
}
},
expire: function() {
if (!this.nodes.iframe) {
return;
}
if (this.needed() || d.activeElement === this.nodes.input) {
return this.reload();
} else {
return this.destroy();
}
},
reload: function() {
var _ref;
this.nodes.iframe.src = this.iframeURL;
this.occupied = true;
return (_ref = this.nodes.img) != null ? _ref.hidden = true : void 0;
},
keydown: function(e) {
if (e.keyCode === 8 && !this.nodes.input.value) {
if (this.nodes.iframe) {
this.reload();
} else {
this.setup();
}
} else if (e.keyCode === 13 && e.shiftKey) {
this.sendResponse();
} else {
return;
}
return e.preventDefault();
}
};
Captcha.v2 = {
lifetime: 2 * $.MINUTE,
init: function() {
var counter, root;
if (d.cookie.indexOf('pass_enabled=1') >= 0) {
return;
}
if (!(this.isEnabled = !!$.id('g-recaptcha'))) {
return;
}
this.captchas = [];
$.get('captchas', [], function(_arg) {
var captchas;
captchas = _arg.captchas;
return QR.captcha.sync(captchas);
});
$.sync('captchas', this.sync.bind(this));
root = $.el('div', {
className: 'captcha-root'
});
$.extend(root, {
innerHTML: "<div class=\"captcha-counter\"><a href=\"javascript:;\"></a></div>"
});
counter = $('.captcha-counter > a', root);
this.nodes = {
root: root,
counter: counter
};
this.count();
$.addClass(QR.nodes.el, 'has-captcha');
$.after(QR.nodes.com.parentNode, root);
$.on(counter, 'click', this.toggle.bind(this));
return $.on(window, 'captcha:success', (function(_this) {
return function() {
return $.queueTask(function() {
return _this.save(false);
});
};
})(this));
},
shouldFocus: false,
timeouts: {},
postsCount: 0,
needed: function() {
var captchaCount;
captchaCount = this.captchas.length;
if (QR.req) {
captchaCount++;
}
this.postsCount = QR.posts.length;
if (this.postsCount === 1 && !Conf['Auto-load captcha'] && !QR.posts[0].com && !QR.posts[0].file) {
this.postsCount = 0;
}
return captchaCount < this.postsCount;
},
onNewPost: function() {
return this.setup();
},
onPostChange: function() {
if (this.postsCount === 0) {
this.setup();
}
if (QR.posts.length === 1 && !Conf['Auto-load captcha'] && !QR.posts[0].com && !QR.posts[0].file) {
return this.postsCount = 0;
}
},
toggle: function() {
if (this.nodes.container && !this.timeouts.destroy) {
return this.destroy();
} else {
return this.setup(true, true);
}
},
setup: function(focus, force) {
var iframe;
if (!(this.isEnabled && (this.needed() || force))) {
return;
}
$.addClass(QR.nodes.el, 'captcha-open');
if (focus) {
this.shouldFocus = true;
}
if (this.timeouts.destroy) {
clearTimeout(this.timeouts.destroy);
delete this.timeouts.destroy;
return this.reload();
}
if (this.nodes.container) {
if (this.shouldFocus && (iframe = $('iframe', this.nodes.container))) {
iframe.focus();
delete this.shouldFocus;
}
return;
}
this.nodes.container = $.el('div', {
className: 'captcha-container'
});
$.prepend(this.nodes.root, this.nodes.container);
new MutationObserver(this.afterSetup.bind(this)).observe(this.nodes.container, {
childList: true,
subtree: true
});
return $.globalEval('(function() {\n function render() {\n var container = document.querySelector("#qr .captcha-container");\n container.dataset.widgetID = window.grecaptcha.render(container, {\n sitekey: \'6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc\',\n theme: document.documentElement.classList.contains(\'tomorrow\') ? \'dark\' : \'light\',\n callback: function(response) {\n window.dispatchEvent(new CustomEvent("captcha:success", {detail: response}));\n }\n });\n }\n if (window.grecaptcha) {\n render();\n } else {\n var cbNative = window.onRecaptchaLoaded;\n window.onRecaptchaLoaded = function() {\n render();\n cbNative();\n }\n }\n})();');
},
afterSetup: function(mutations) {
var iframe, mutation, node, textarea, _i, _j, _len, _len1, _ref;
for (_i = 0, _len = mutations.length; _i < _len; _i++) {
mutation = mutations[_i];
_ref = mutation.addedNodes;
for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
node = _ref[_j];
if (iframe = $.x('./descendant-or-self::iframe', node)) {
this.setupIFrame(iframe);
}
if (textarea = $.x('./descendant-or-self::textarea', node)) {
this.setupTextArea(textarea);
}
}
}
},
setupIFrame: function(iframe) {
this.setupTime = Date.now();
if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) {
QR.nodes.el.style.top = null;
QR.nodes.el.style.bottom = '0px';
}
if (this.shouldFocus) {
iframe.focus();
}
return this.shouldFocus = false;
},
setupTextArea: function(textarea) {
return $.one(textarea, 'input', (function(_this) {
return function() {
return _this.save(true);
};
})(this));
},
destroy: function() {
if (!this.isEnabled) {
return;
}
delete this.timeouts.destroy;
$.rmClass(QR.nodes.el, 'captcha-open');
if (this.nodes.container) {
$.rm(this.nodes.container);
}
return delete this.nodes.container;
},
sync: function(captchas) {
if (captchas == null) {
captchas = [];
}
this.captchas = captchas;
this.clear();
return this.count();
},
getOne: function() {
var captcha;
this.clear();
if (captcha = this.captchas.shift()) {
$.set('captchas', this.captchas);
this.count();
return captcha.response;
} else {
return null;
}
},
save: function(pasted) {
var _base;
$.forceSync('captchas');
this.captchas.push({
response: $('textarea', this.nodes.container).value,
timeout: (pasted ? this.setupTime : Date.now()) + this.lifetime
});
$.set('captchas', this.captchas);
this.count();
if (this.needed()) {
if (QR.cooldown.auto || Conf['Post on Captcha Completion']) {
this.shouldFocus = true;
} else {
QR.nodes.status.focus();
}
this.reload();
} else {
if (pasted) {
this.destroy();
} else {
if ((_base = this.timeouts).destroy == null) {
_base.destroy = setTimeout(this.destroy.bind(this), 3 * $.SECOND);
}
}
QR.nodes.status.focus();
}
if (Conf['Post on Captcha Completion'] && !QR.cooldown.auto) {
return QR.submit();
}
},
notify: function(el) {
return QR.notify(el);
},
clear: function() {
var captcha, i, now, _i, _len, _ref;
if (!this.captchas.length) {
return;
}
$.forceSync('captchas');
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();
$.set('captchas', this.captchas);
return this.setup(true);
},
count: function() {
this.nodes.counter.textContent = "Captchas: " + this.captchas.length;
clearTimeout(this.timeouts.clear);
if (this.captchas.length) {
return this.timeouts.clear = setTimeout(this.clear.bind(this), this.captchas[0].timeout - Date.now());
}
},
reload: function() {
return $.globalEval('(function() {\n var container = document.querySelector("#qr .captcha-container");\n window.grecaptcha.reset(container.dataset.widgetID);\n})();');
}
};
QR.cooldown = {
seconds: 0,
init: function() {
var delay, items, key, keys, m, scope, type, _ref, _results;
if (!Conf['Cooldown']) {
return;
}
QR.cooldown.delays = (m = Get.scriptData().match(/\bcooldowns *= *({[^}]+})/)) ? JSON.parse(m[1]) : {
thread: 0,
reply: 0,
image: 0,
reply_intra: 0,
image_intra: 0
};
QR.cooldown.maxDelay = 0;
_ref = QR.cooldown.delays;
for (type in _ref) {
delay = _ref[type];
if (type !== 'thread') {
QR.cooldown.maxDelay = Math.max(QR.cooldown.maxDelay, delay);
}
}
QR.cooldown.delays['thread_global'] = 300;
keys = QR.cooldown.keys = {
local: "cooldown." + g.BOARD,
global: 'cooldown.global'
};
items = {};
for (scope in keys) {
key = keys[scope];
items[key] = {};
}
$.get(items, function(items) {
for (scope in keys) {
key = keys[scope];
QR.cooldown[scope] = items[key];
}
return QR.cooldown.start();
});
_results = [];
for (scope in keys) {
key = keys[scope];
_results.push($.sync(key, QR.cooldown.sync(scope)));
}
return _results;
},
start: function() {
if (QR.cooldown.isCounting || Object.keys(QR.cooldown.local).length + Object.keys(QR.cooldown.global).length === 0) {
return;
}
QR.cooldown.isCounting = true;
return QR.cooldown.count();
},
sync: function(scope) {
return function(cooldowns) {
QR.cooldown[scope] = cooldowns || {};
return QR.cooldown.start();
};
},
add: function(start, threadID, postID) {
var boardID;
if (!Conf['Cooldown']) {
return;
}
boardID = g.BOARD.ID;
QR.cooldown.set('local', start, {
threadID: threadID,
postID: postID
});
if (threadID === postID) {
QR.cooldown.set('global', start, {
boardID: boardID,
threadID: threadID,
postID: postID
});
}
return QR.cooldown.start();
},
addDelay: function(post, delay) {
var cooldown;
if (!Conf['Cooldown']) {
return;
}
cooldown = QR.cooldown.categorize(post);
cooldown.delay = delay;
QR.cooldown.set('local', Date.now(), cooldown);
return QR.cooldown.start();
},
"delete": function(post) {
var cooldown, id, _ref;
if (!(Conf['Cooldown'] && g.BOARD.ID === post.board.ID)) {
return;
}
$.forceSync(QR.cooldown.keys.local);
_ref = QR.cooldown.local;
for (id in _ref) {
cooldown = _ref[id];
if ((cooldown.delay == null) && cooldown.threadID === post.thread.ID && cooldown.postID === post.ID) {
delete QR.cooldown.local[id];
}
}
return QR.cooldown.save('local');
},
categorize: function(post) {
if (post.thread === 'new') {
return {
type: 'thread'
};
} else {
return {
type: !!post.file ? 'image' : 'reply',
threadID: +post.thread
};
}
},
set: function(scope, id, value) {
$.forceSync(QR.cooldown.keys[scope]);
QR.cooldown[scope][id] = value;
return $.set(QR.cooldown.keys[scope], QR.cooldown[scope]);
},
save: function(scope) {
if (Object.keys(QR.cooldown[scope]).length) {
return $.set(QR.cooldown.keys[scope], QR.cooldown[scope]);
} else {
return $["delete"](QR.cooldown.keys[scope]);
}
},
count: function() {
var cooldown, elapsed, key, maxDelay, now, save, scope, seconds, start, suffix, threadID, type, update, _ref, _ref1, _ref2;
now = Date.now();
_ref = QR.cooldown.categorize(QR.posts[0]), type = _ref.type, threadID = _ref.threadID;
seconds = 0;
_ref1 = QR.cooldown.keys;
for (scope in _ref1) {
key = _ref1[scope];
$.forceSync(key);
save = false;
_ref2 = QR.cooldown[scope];
for (start in _ref2) {
cooldown = _ref2[start];
start = +start;
elapsed = Math.floor((now - start) / $.SECOND);
if (elapsed < 0) {
delete QR.cooldown[scope][start];
save = true;
continue;
}
if (cooldown.delay != null) {
if (cooldown.delay <= elapsed) {
delete QR.cooldown[scope][start];
save = true;
} else if (cooldown.type === type && cooldown.threadID === threadID) {
seconds = Math.max(seconds, cooldown.delay - elapsed);
}
continue;
}
maxDelay = cooldown.threadID !== cooldown.postID ? QR.cooldown.maxDelay : QR.cooldown.delays[scope === 'global' ? 'thread_global' : 'thread'];
if (maxDelay <= elapsed) {
delete QR.cooldown[scope][start];
save = true;
continue;
}
if ((type === 'thread') === (cooldown.threadID === cooldown.postID) && cooldown.boardID !== g.BOARD.ID) {
suffix = scope === 'global' ? '_global' : type !== 'thread' && threadID === cooldown.threadID ? '_intra' : '';
seconds = Math.max(seconds, QR.cooldown.delays[type + suffix] - elapsed);
}
}
if (save) {
QR.cooldown.save(scope);
}
}
if (Object.keys(QR.cooldown.local).length + Object.keys(QR.cooldown.global).length) {
clearTimeout(QR.cooldown.timeout);
QR.cooldown.timeout = setTimeout(QR.cooldown.count, $.SECOND);
} else {
delete QR.cooldown.isCounting;
}
update = seconds !== QR.cooldown.seconds;
QR.cooldown.seconds = seconds;
if (update) {
QR.status();
}
if (seconds === 0 && QR.cooldown.auto && !QR.req) {
return QR.submit();
}
}
};
QR.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, _ref2;
if (item[0] === '#') {
return;
}
if (!(match = item.match(/(name|options|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' && (_ref2 = g.BOARD.ID, __indexOf.call(boards.split(','), _ref2) < 0)) {
return;
}
if (type === 'password') {
QR.persona.pwd = val;
return;
}
if (type === 'options') {
type = 'email';
}
if (type === 'subject') {
type = 'sub';
}
if (/always/i.test(item)) {
QR.persona.always[type] = val;
}
if (__indexOf.call(types[type], val) < 0) {
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) {
$.add(list, $.el('option', {
textContent: val
}));
}
}
},
getPassword: function() {
var input, m, _ref;
if (!QR.persona.pwd) {
QR.persona.pwd = (m = d.cookie.match(/4chan_pass=([^;]+)/)) ? decodeURIComponent(m[1]) : (input = $.id('postPassword')) ? input.value : ((_ref = $.id('delPassword')) != null ? _ref.value : void 0) || '';
}
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
};
return $.set('QR.persona', persona);
});
}
};
QR.post = (function() {
function _Class(select) {
this.select = __bind(this.select, this);
var el, event, prev, _i, _len, _ref;
el = $.el('a', {
className: 'qr-preview',
draggable: true,
href: 'javascript:;'
});
$.extend(el, {
innerHTML: "<a class=\"remove fa fa-times-circle\" title=\"Remove\"></a><label hidden><input type=\"checkbox\"> Spoiler</label><span></span>"
});
this.nodes = {
el: el,
rm: el.firstChild,
label: $('label', el),
spoiler: $('input', el),
span: el.lastChild
};
$.on(el, 'click', this.select);
$.on(this.nodes.rm, 'click', (function(_this) {
return function(e) {
e.stopPropagation();
return _this.rm();
};
})(this));
$.on(this.nodes.label, 'click', (function(_this) {
return function(e) {
return e.stopPropagation();
};
})(this));
$.on(this.nodes.spoiler, 'change', (function(_this) {
return function(e) {
_this.spoiler = e.target.checked;
if (_this === QR.selected) {
return QR.nodes.spoiler.checked = _this.spoiler;
}
};
})(this));
$.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(_this) {
return 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 : '';
if (QR.selected === _this) {
return _this.load();
}
};
})(this));
if (select) {
this.select();
}
this.unlock();
$.queueTask(function() {
return QR.captcha.onNewPost();
});
}
_Class.prototype.rm = function() {
var index;
this["delete"]();
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);
return QR.status();
};
_Class.prototype["delete"] = function() {
$.rm(this.nodes.el);
return URL.revokeObjectURL(this.URL);
};
_Class.prototype.lock = function(lock) {
var name, node, _i, _len, _ref;
if (lock == null) {
lock = true;
}
this.isLocked = lock;
if (this !== QR.selected) {
return;
}
_ref = ['thread', 'name', 'email', 'sub', 'com', 'fileButton', 'filename', 'spoiler'];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
name = _ref[_i];
if (node = QR.nodes[name]) {
node.disabled = lock;
}
}
this.nodes.rm.style.visibility = lock ? 'hidden' : '';
(lock ? $.off : $.on)(QR.nodes.filename.previousElementSibling, '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;
return this.load();
};
_Class.prototype.load = function() {
var name, node, _i, _len, _ref;
_ref = ['thread', 'name', 'email', 'sub', 'com', 'filename'];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
name = _ref[_i];
if (!(node = QR.nodes[name])) {
continue;
}
node.value = this[name] || node.dataset["default"] || null;
}
(this.thread !== 'new' ? $.addClass : $.rmClass)(QR.nodes.el, 'reply-to-thread');
this.showFileData();
return QR.characterCount();
};
_Class.prototype.save = function(input) {
var name, _ref;
if (input.type === 'checkbox') {
this.spoiler = input.checked;
return;
}
name = input.dataset.name;
this[name] = input.value || input.dataset["default"] || null;
switch (name) {
case 'thread':
(this.thread !== 'new' ? $.addClass : $.rmClass)(QR.nodes.el, 'reply-to-thread');
return QR.status();
case 'com':
this.nodes.span.textContent = this.com;
QR.captcha.onPostChange();
QR.characterCount();
if (QR.cooldown.auto && this === QR.posts[0] && (0 < (_ref = QR.cooldown.seconds) && _ref <= 5)) {
return QR.cooldown.auto = false;
}
break;
case 'filename':
if (!this.file) {
return;
}
this.file.newName = this.filename.replace(/[/\\]/g, '-');
if (!/\.(jpe?g|png|gif|pdf|swf|webm)$/i.test(this.filename)) {
this.file.newName += '.jpg';
}
return this.updateFilename();
}
};
_Class.prototype.forceSave = function() {
var name, node, _i, _len, _ref;
if (this !== QR.selected) {
return;
}
_ref = ['thread', 'name', 'email', 'sub', 'com', 'filename', 'spoiler'];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
name = _ref[_i];
if (!(node = QR.nodes[name])) {
continue;
}
this.save(node);
}
};
_Class.prototype.setFile = function(file, el) {
this.file = file;
this.filename = file.name;
this.filesize = $.bytesToString(file.size);
if (QR.spoiler) {
this.nodes.label.hidden = false;
}
QR.captcha.onPostChange();
URL.revokeObjectURL(this.URL);
if (this === QR.selected) {
this.showFileData();
} else {
this.updateFilename();
}
if (el) {
return this.setThumbnail(el);
} else {
return this.nodes.el.style.backgroundImage = null;
}
};
_Class.prototype.setThumbnail = function(el) {
var cv, height, isVideo, s, width;
isVideo = el.tagName === 'VIDEO';
s = 90 * 2 * window.devicePixelRatio;
if (this.file.type === 'image/gif') {
s *= 3;
}
if (isVideo) {
height = el.videoHeight;
width = el.videoWidth;
} else {
height = el.height, width = el.width;
if (height < s || width < s) {
this.URL = el.src;
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 = height;
cv.width = width;
cv.getContext('2d').drawImage(el, 0, 0, width, height);
URL.revokeObjectURL(el.src);
return cv.toBlob((function(_this) {
return function(blob) {
_this.URL = URL.createObjectURL(blob);
return _this.nodes.el.style.backgroundImage = "url(" + _this.URL + ")";
};
})(this));
};
_Class.prototype.rmFile = function() {
if (this.isLocked) {
return;
}
delete this.file;
delete this.filename;
delete this.filesize;
this.nodes.el.title = null;
QR.nodes.fileContainer.title = '';
this.nodes.el.style.backgroundImage = null;
if (QR.spoiler) {
this.nodes.label.hidden = true;
}
this.showFileData();
return URL.revokeObjectURL(this.URL);
};
_Class.prototype.updateFilename = function() {
var long;
long = "" + this.filename + " (" + this.filesize + ")\nCtrl/\u2318+click to edit filename. Shift+click to clear.";
this.nodes.el.title = long;
if (this !== QR.selected) {
return;
}
return QR.nodes.fileContainer.title = long;
};
_Class.prototype.showFileData = function() {
if (this.file) {
this.updateFilename();
QR.nodes.filename.value = 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;
reader = new FileReader();
reader.onload = (function(_this) {
return 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;
};
})(this);
return reader.readAsText(file);
};
_Class.prototype.dragStart = function(e) {
e.dataTransfer.setDragImage(this, e.layerX, e.layerY);
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;
$.rmClass(this, 'over');
if (!this.draggable) {
return;
}
el = $('.drag', this.parentNode);
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];
QR.posts.splice(newIndex, 0, post);
return QR.status();
};
return _Class;
})();
FappeTyme = {
init: function() {
var el, lc, type, _i, _len, _ref, _ref1;
if (!((Conf['Fappe Tyme'] || Conf['Werk Tyme']) && ((_ref = g.VIEW) === 'index' || _ref === 'thread') && g.BOARD.ID !== 'f')) {
return;
}
this.nodes = {};
this.enabled = {
fappe: false,
werk: Conf['werk']
};
_ref1 = ["Fappe", "Werk"];
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
type = _ref1[_i];
if (!Conf["" + type + " Tyme"]) {
continue;
}
lc = type.toLowerCase();
el = UI.checkbox(lc, "" + type + " Tyme", false);
el.title = "" + type + " Tyme";
this.nodes[lc] = el.firstElementChild;
if (Conf[lc]) {
this.set(lc, true);
}
$.on(this.nodes[lc], 'change', this.toggle.bind(this, lc));
Header.menu.addEntry({
el: el,
order: 97
});
}
if (Conf['Werk Tyme']) {
$.sync('werk', this.set.bind(this, 'werk'));
}
Post.callbacks.push({
name: 'Fappe Tyme',
cb: this.node
});
return CatalogThread.callbacks.push({
name: 'Werk Tyme',
cb: this.catalogNode
});
},
node: function() {
if (this.file) {
return;
}
return $.addClass(this.nodes.root, "noFile");
},
catalogNode: function() {
var file, filename;
file = this.thread.OP.file;
if (!file) {
return;
}
filename = $.el('div', {
textContent: file.name,
className: 'werkTyme-filename'
});
return $.add(this.nodes.thumb.parentNode, filename);
},
set: function(type, enabled) {
this.enabled[type] = this.nodes[type].checked = enabled;
return $["" + (enabled ? 'add' : 'rm') + "Class"](doc, "" + type + "Tyme");
},
toggle: function(type) {
this.set(type, !this.enabled[type]);
if (type === 'werk') {
return $.cb.checked.call(this.nodes[type]);
}
}
};
Gallery = {
init: function() {
var el, _ref;
if (!(this.enabled = Conf['Gallery'] && ((_ref = g.VIEW) === 'index' || _ref === 'thread') && g.BOARD.ID !== 'f')) {
return;
}
this.delay = Conf['Slide Delay'];
el = $.el('a', {
href: 'javascript:;',
id: 'appchan-gal',
title: 'Gallery',
className: 'fa fa-picture-o',
textContent: 'Gallery'
});
$.on(el, 'click', this.cb.toggle);
Header.addShortcut(el);
return Post.callbacks.push({
name: 'Gallery',
cb: this.node
});
},
node: function() {
if (!this.file) {
return;
}
if (Gallery.nodes) {
Gallery.generateThumb(this);
Gallery.nodes.total.textContent = Gallery.images.length;
}
if (!Conf['Image Expansion']) {
return $.on(this.file.thumb.parentNode, 'click', Gallery.cb.image);
}
},
build: function(image) {
var candidate, cb, dialog, entry, file, key, menuButton, nodes, post, thumb, value, _i, _j, _len, _len1, _ref, _ref1, _ref2;
if (Conf['Fullscreen Gallery']) {
$.one(d, 'fullscreenchange mozfullscreenchange webkitfullscreenchange', function() {
return $.on(d, 'fullscreenchange mozfullscreenchange webkitfullscreenchange', cb.close);
});
if (typeof doc.mozRequestFullScreen === "function") {
doc.mozRequestFullScreen();
}
if (typeof doc.webkitRequestFullScreen === "function") {
doc.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
}
}
Gallery.images = [];
nodes = Gallery.nodes = {};
Gallery.fullIDs = {};
Gallery.slideshow = false;
nodes.el = dialog = $.el('div', {
id: 'a-gallery'
});
$.extend(dialog, {
innerHTML: "<div class=\"gal-viewport\"><span class=\"gal-buttons\"><a href=\"javascript:;\" class=\"gal-start\" title=\"Start slideshow\"><i></i></a><a href=\"javascript:;\" class=\"gal-stop\" title=\"Stop slideshow\"><i></i></a><a href=\"javascript:;\" class=\"menu-button\"><i></i></a><a href=\"javascript:;\" class=\"gal-close\">×</a></span><a class=\"gal-name\" target=\"_blank\"></a><span class=\"gal-count\"><span class=\"count\"></span> / <span class=\"total\"></span></span><div class=\"gal-prev\"></div><div class=\"gal-image\"><a href=\"javascript:;\"><img></a></div><div class=\"gal-next\"></div></div><div class=\"gal-thumbnails\"></div>"
});
_ref = {
buttons: '.gal-buttons',
frame: '.gal-image',
name: '.gal-name',
count: '.count',
total: '.total',
thumbs: '.gal-thumbnails',
next: '.gal-image a',
current: '.gal-image img'
};
for (key in _ref) {
value = _ref[key];
nodes[key] = $(value, dialog);
}
menuButton = $('.menu-button', dialog);
nodes.menu = new UI.Menu('gallery');
cb = Gallery.cb;
$.on(nodes.frame, 'click', cb.blank);
$.on(nodes.next, 'click', cb.click);
$.on(nodes.name, 'click', ImageCommon.download);
$.on($('.gal-prev', dialog), 'click', cb.prev);
$.on($('.gal-next', dialog), 'click', cb.next);
$.on($('.gal-start', dialog), 'click', cb.start);
$.on($('.gal-stop', dialog), 'click', cb.stop);
$.on($('.gal-close', dialog), 'click', cb.close);
$.on(menuButton, 'click', function(e) {
return nodes.menu.toggle(e, this, g);
});
_ref1 = Gallery.menu.createSubEntries();
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
entry = _ref1[_i];
entry.order = 0;
nodes.menu.addEntry(entry);
}
$.on(d, 'keydown', cb.keybinds);
if (Conf['Keybinds']) {
$.off(d, 'keydown', Keybinds.keydown);
}
_ref2 = $$('.post .file');
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
file = _ref2[_j];
post = Get.postFromNode(file);
if (!post.file) {
continue;
}
Gallery.generateThumb(post);
if (!image && Gallery.fullIDs[post.fullID]) {
candidate = post.file.thumb.parentNode;
if (Header.getTopOf(candidate) + candidate.getBoundingClientRect().height >= 0) {
image = candidate;
}
}
}
$.addClass(doc, 'gallery-open');
$.add(d.body, dialog);
nodes.thumbs.scrollTop = 0;
nodes.current.parentElement.scrollTop = 0;
if (image) {
thumb = $("[href='" + image.href + "']", nodes.thumbs);
}
thumb || (thumb = Gallery.images[Gallery.images.length - 1]);
if (thumb) {
Gallery.open(thumb);
}
doc.style.overflow = 'hidden';
return nodes.total.textContent = Gallery.images.length;
},
generateThumb: function(post) {
var thumb, thumbImg;
if (post.isClone || post.isHidden) {
return;
}
if (!(post.file && (post.file.isImage || post.file.isVideo || Conf['PDF in Gallery']))) {
return;
}
if (Gallery.fullIDs[post.fullID]) {
return;
}
Gallery.fullIDs[post.fullID] = true;
thumb = $.el('a', {
className: 'gal-thumb',
href: post.file.URL,
target: '_blank',
title: post.file.name
});
thumb.dataset.id = Gallery.images.length;
thumb.dataset.post = post.fullID;
thumbImg = post.file.thumb.cloneNode(false);
thumbImg.style.cssText = '';
$.add(thumb, thumbImg);
$.on(thumb, 'click', Gallery.cb.open);
Gallery.images.push(thumb);
return $.add(Gallery.nodes.thumbs, thumb);
},
open: function(thumb) {
var el, elType, file, name, newID, nodes, oldID, post, slideshow, _ref;
nodes = Gallery.nodes;
name = nodes.name;
oldID = +nodes.current.dataset.id;
newID = +thumb.dataset.id;
slideshow = Gallery.slideshow && (newID > oldID || (oldID === Gallery.images.length - 1 && newID === 0));
if (el = $('.gal-highlight', nodes.thumbs)) {
$.rmClass(el, 'gal-highlight');
}
$.addClass(thumb, 'gal-highlight');
elType = /\.webm$/.test(thumb.href) ? 'video' : /\.pdf$/.test(thumb.href) ? 'iframe' : 'img';
$[elType === 'iframe' ? 'addClass' : 'rmClass'](doc, 'gal-pdf');
file = $.el(elType, {
title: name.download = name.textContent = thumb.title
});
$.extend(file.dataset, thumb.dataset);
$.on(file, 'error', Gallery.error);
file.src = name.href = thumb.href;
$.off(nodes.current, 'error', Gallery.error);
ImageCommon.pause(nodes.current);
$.replace(nodes.current, file);
if (elType === 'video') {
file.loop = true;
Volume.setup(file);
if (Conf['Autoplay']) {
file.play();
}
if (Conf['Show Controls']) {
ImageCommon.addControls(file);
}
}
nodes.count.textContent = +thumb.dataset.id + 1;
nodes.current = file;
nodes.frame.scrollTop = 0;
nodes.next.focus();
if (slideshow) {
Gallery.setupTimer();
} else {
Gallery.cb.stop();
}
if (Conf['Scroll to Post'] && (post = (_ref = (post = g.posts[file.dataset.post])) != null ? _ref.nodes.root : void 0)) {
Header.scrollTo(post);
}
return nodes.thumbs.scrollTop = thumb.offsetTop + thumb.offsetHeight / 2 - nodes.thumbs.clientHeight / 2;
},
error: function() {
var _ref;
if (((_ref = this.error) != null ? _ref.code : void 0) === MediaError.MEDIA_ERR_DECODE) {
return new Notice('error', 'Corrupt or unplayable video', 30);
}
if (this.src.split('/')[2] !== 'i.4cdn.org') {
return;
}
return ImageCommon.error(this, g.posts[this.dataset.post], null, (function(_this) {
return function(url) {
if (!url) {
return;
}
Gallery.images[_this.dataset.id].href = url;
if (Gallery.nodes.current === _this) {
return _this.src = url;
}
};
})(this));
},
cleanupTimer: function() {
var current;
clearTimeout(Gallery.timeoutID);
current = Gallery.nodes.current;
$.off(current, 'canplaythrough load', Gallery.startTimer);
return $.off(current, 'ended', Gallery.cb.next);
},
startTimer: function() {
return Gallery.timeoutID = setTimeout(Gallery.checkTimer, Gallery.delay * $.SECOND);
},
setupTimer: function() {
var current, isVideo;
Gallery.cleanupTimer();
current = Gallery.nodes.current;
isVideo = current.nodeName === 'VIDEO';
if (isVideo) {
current.play();
}
if ((isVideo ? current.readyState >= 4 : current.complete) || current.nodeName === 'IFRAME') {
return Gallery.startTimer();
} else {
return $.on(current, (isVideo ? 'canplaythrough' : 'load'), Gallery.startTimer);
}
},
checkTimer: function() {
var current;
current = Gallery.nodes.current;
if (current.nodeName === 'VIDEO' && !current.paused) {
$.on(current, 'ended', Gallery.cb.next);
return current.loop = false;
} else {
return Gallery.cb.next();
}
},
cb: {
keybinds: function(e) {
var cb, key;
if (!(key = Keybinds.keyCode(e))) {
return;
}
cb = (function() {
switch (key) {
case Conf['Close']:
case Conf['Open Gallery']:
return Gallery.cb.close;
case 'Right':
return Gallery.cb.next;
case 'Enter':
return Gallery.cb.advance;
case 'Left':
case '':
return Gallery.cb.prev;
case Conf['Pause']:
return Gallery.cb.pause;
case Conf['Slideshow']:
return Gallery.cb.toggleSlideshow;
}
})();
if (!cb) {
return;
}
e.stopPropagation();
e.preventDefault();
return cb();
},
open: function(e) {
if (e) {
e.preventDefault();
}
if (this) {
return Gallery.open(this);
}
},
image: function(e) {
e.preventDefault();
e.stopPropagation();
return Gallery.build(this);
},
prev: function() {
return Gallery.cb.open.call(Gallery.images[+Gallery.nodes.current.dataset.id - 1] || Gallery.images[Gallery.images.length - 1]);
},
next: function() {
return Gallery.cb.open.call(Gallery.images[+Gallery.nodes.current.dataset.id + 1] || Gallery.images[0]);
},
click: function(e) {
if (ImageCommon.onControls(e)) {
return;
}
e.preventDefault();
return Gallery.cb.advance();
},
advance: function() {
if (Gallery.nodes.current.paused) {
return Gallery.nodes.current.play();
} else {
return Gallery.cb.next();
}
},
toggle: function() {
return (Gallery.nodes ? Gallery.cb.close : Gallery.build)();
},
blank: function(e) {
if (e.target === this) {
return Gallery.cb.close();
}
},
toggleSlideshow: function() {
return Gallery.cb[Gallery.slideshow ? 'stop' : 'start']();
},
pause: function() {
var current;
Gallery.cb.stop();
current = Gallery.nodes.current;
if (current.nodeName === 'VIDEO') {
return current[current.paused ? 'play' : 'pause']();
}
},
start: function() {
$.addClass(Gallery.nodes.buttons, 'gal-playing');
Gallery.slideshow = true;
return Gallery.setupTimer();
},
stop: function() {
var current;
if (!Gallery.slideshow) {
return;
}
Gallery.cleanupTimer();
current = Gallery.nodes.current;
if (current.nodeName === 'VIDEO') {
current.loop = true;
}
$.rmClass(Gallery.nodes.buttons, 'gal-playing');
return Gallery.slideshow = false;
},
close: function() {
$.off(Gallery.nodes.current, 'error', Gallery.error);
ImageCommon.pause(Gallery.nodes.current);
$.rm(Gallery.nodes.el);
$.rmClass(doc, 'gallery-open');
if (Conf['Fullscreen Gallery']) {
$.off(d, 'fullscreenchange mozfullscreenchange webkitfullscreenchange', Gallery.cb.close);
if (typeof d.mozCancelFullScreen === "function") {
d.mozCancelFullScreen();
}
if (typeof d.webkitExitFullscreen === "function") {
d.webkitExitFullscreen();
}
}
delete Gallery.nodes;
delete Gallery.fullIDs;
doc.style.overflow = '';
$.off(d, 'keydown', Gallery.cb.keybinds);
if (Conf['Keybinds']) {
$.on(d, 'keydown', Keybinds.keydown);
}
return clearTimeout(Gallery.timeoutID);
},
setFitness: function() {
return (this.checked ? $.addClass : $.rmClass)(doc, "gal-" + (this.name.toLowerCase().replace(/\s+/g, '-')));
},
setDelay: function() {
return Gallery.delay = +this.value;
}
},
menu: {
init: function() {
var el;
if (!Gallery.enabled) {
return;
}
el = $.el('span', {
textContent: 'Gallery',
className: 'gallery-link'
});
return Header.menu.addEntry({
el: el,
order: 105,
subEntries: Gallery.menu.createSubEntries()
});
},
createSubEntry: function(name) {
var input, label;
label = UI.checkbox(name, name);
input = label.firstElementChild;
if (name === 'Fit Width' || name === 'Fit Height' || name === 'Hide Thumbnails') {
$.on(input, 'change', Gallery.cb.setFitness);
}
$.event('change', null, input);
$.on(input, 'change', $.cb.checked);
return {
el: label
};
},
createSubEntries: function() {
var delayInput, delayLabel, item, subEntries;
subEntries = (function() {
var _i, _len, _ref, _results;
_ref = ['Hide Thumbnails', 'Fit Width', 'Fit Height', 'Scroll to Post'];
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
item = _ref[_i];
_results.push(Gallery.menu.createSubEntry(item));
}
return _results;
})();
delayLabel = $.el('label', {
innerHTML: "Slide Delay: <input type=\"number\" name=\"Slide Delay\" min=\"0\" step=\"any\" class=\"field\">"
});
delayInput = delayLabel.firstElementChild;
delayInput.value = Gallery.delay;
$.on(delayInput, 'change', Gallery.cb.setDelay);
$.on(delayInput, 'change', $.cb.value);
subEntries.push({
el: delayLabel
});
return subEntries;
}
}
};
ImageCommon = {
pause: function(video) {
if (video.nodeName !== 'VIDEO') {
return;
}
video.pause();
$.off(video, 'volumechange', Volume.change);
return video.muted = true;
},
rewind: function(el) {
if (el.nodeName === 'VIDEO') {
if (el.readyState >= el.HAVE_METADATA) {
return el.currentTime = 0;
}
} else if (/\.gif$/.test(el.src)) {
return $.queueTask(function() {
return el.src = el.src;
});
}
},
pushCache: function(el) {
ImageCommon.cache = el;
return $.on(el, 'error', ImageCommon.cacheError);
},
popCache: function() {
var el;
el = ImageCommon.cache;
$.off(el, 'error', ImageCommon.cacheError);
delete ImageCommon.cache;
return el;
},
cacheError: function() {
if (ImageCommon.cache === this) {
return delete ImageCommon.cache;
}
},
decodeError: function(file, post) {
var message, _ref;
if (((_ref = file.error) != null ? _ref.code : void 0) !== MediaError.MEDIA_ERR_DECODE) {
return false;
}
if (!(message = $('.warning', post.file.thumb.parentNode))) {
message = $.el('div', {
className: 'warning'
});
$.after(post.file.thumb, message);
}
message.textContent = 'Error: Corrupt or unplayable video';
return true;
},
error: function(file, post, delay, cb) {
var URL, redirect, src, timeoutID;
src = post.file.URL.split('/');
URL = Redirect.to('file', {
boardID: post.board.ID,
filename: src[src.length - 1]
});
if (!(Conf['404 Redirect'] && URL && Redirect.securityCheck(URL))) {
URL = null;
}
if ((post.isDead || post.file.isDead) && file.src.split('/')[2] === 'i.4cdn.org') {
return cb(URL);
}
if (delay != null) {
timeoutID = setTimeout((function() {
return cb(URL);
}), delay);
}
if (post.isDead || post.file.isDead) {
return;
}
redirect = function() {
if (file.src.split('/')[2] === 'i.4cdn.org') {
if (delay != null) {
clearTimeout(timeoutID);
}
return cb(URL);
}
};
return $.ajax("//a.4cdn.org/" + post.board + "/thread/" + post.thread + ".json", {
onload: function() {
var postObj, _i, _len, _ref;
if (this.status === 404) {
post.kill();
}
if (this.status !== 200) {
return redirect();
}
_ref = 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) {
post.kill();
return redirect();
} else if (postObj.filedeleted) {
post.kill(true);
return redirect();
} else {
return URL = post.file.URL;
}
}
});
},
addControls: function(video) {
var handler;
handler = function() {
var t;
$.off(video, 'mouseover', handler);
t = new Date().getTime();
return $.asap((function() {
return (typeof chrome !== "undefined" && chrome !== null) || (video.readyState >= 3 && video.currentTime <= Math.max(0.1, video.duration - 0.5)) || new Date().getTime() >= t + 1000;
}), function() {
return video.controls = true;
});
};
return $.on(video, 'mouseover', handler);
},
onControls: function(e) {
return (Conf['Show Controls'] && Conf['Click Passthrough'] && e.target.nodeName === 'VIDEO') || (e.target.controls && e.target.getBoundingClientRect().bottom - e.clientY < 35);
},
download: function(e) {
if (this.protocol === 'blob:') {
return true;
}
e.preventDefault();
return CrossOrigin.file(this.href, (function(_this) {
return function(blob) {
if (blob) {
_this.href = URL.createObjectURL(blob);
return _this.click();
} else {
return new Notice('error', "Could not download " + _this.href, 30);
}
};
})(this));
}
};
ImageExpand = {
init: function() {
var _ref;
if (!(this.enabled = Conf['Image Expansion'] && ((_ref = g.VIEW) === 'index' || _ref === 'thread') && g.BOARD.ID !== 'f')) {
return;
}
this.EAI = $.el('a', {
className: 'expand-all-shortcut fa fa-expand',
textContent: 'EAI',
title: 'Expand All Images',
href: 'javascript:;'
});
$.on(this.EAI, 'click', this.cb.toggleAll);
Header.addShortcut(this.EAI, 3);
$.on(d, 'scroll visibilitychange', this.cb.playVideos);
this.videoControls = $.el('span', {
className: 'video-controls'
});
$.extend(this.videoControls, {
innerHTML: " <a href=\"javascript:;\" title=\"You can also contract the video by dragging it to the left.\">contract</a>"
});
return Post.callbacks.push({
name: 'Image Expansion',
cb: this.node
});
},
node: function() {
var _ref;
if (!(this.file && (this.file.isImage || this.file.isVideo))) {
return;
}
$.on(this.file.thumb.parentNode, 'click', ImageExpand.cb.toggle);
if (this.isClone) {
if (this.file.isExpanding) {
ImageExpand.contract(this);
return ImageExpand.expand(this);
} else if (this.file.isExpanded && this.file.isVideo) {
Volume.setup(this.file.fullImage);
ImageExpand.setupVideoCB(this);
return ImageExpand.setupVideo(this, !((_ref = this.origin.file.fullImage) != null ? _ref.paused : void 0) || this.origin.file.wasPlaying, this.file.fullImage.controls);
}
} else if (ImageExpand.on && !this.isHidden && !this.isFetchedQuote && (Conf['Expand spoilers'] || !this.file.isSpoiler) && (Conf['Expand videos'] || !this.file.isVideo)) {
return ImageExpand.expand(this);
}
},
cb: {
toggle: function(e) {
var file, post, _ref;
if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) {
return;
}
post = Get.postFromNode(this);
file = post.file;
if (file.isExpanded && ImageCommon.onControls(e)) {
return;
}
e.preventDefault();
if ((_ref = file.fullImage) != null ? _ref.paused : void 0) {
return file.fullImage.play();
} else {
return ImageExpand.toggle(post);
}
},
toggleAll: function() {
var func, toggle;
$.event('CloseMenu');
toggle = function(post) {
var file;
file = post.file;
if (!(file && (file.isImage || file.isVideo) && doc.contains(post.nodes.root))) {
return;
}
if (ImageExpand.on && (!Conf['Expand spoilers'] && file.isSpoiler || !Conf['Expand videos'] && file.isVideo || Conf['Expand from here'] && Header.getTopOf(file.thumb) < 0)) {
return;
}
return $.queueTask(func, post);
};
if (ImageExpand.on = $.hasClass(ImageExpand.EAI, 'expand-all-shortcut')) {
ImageExpand.EAI.className = 'contract-all-shortcut fa fa-compress';
ImageExpand.EAI.title = 'Contract All Images';
func = ImageExpand.expand;
} else {
ImageExpand.EAI.className = 'expand-all-shortcut fa fa-expand';
ImageExpand.EAI.title = 'Expand All Images';
func = ImageExpand.contract;
}
return g.posts.forEach(function(post) {
var _i, _len, _ref;
_ref = [post].concat(__slice.call(post.clones));
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
post = _ref[_i];
toggle(post);
}
});
},
playVideos: function(e) {
return g.posts.forEach(function(post) {
var file, video, visible, _i, _len, _ref;
_ref = [post].concat(__slice.call(post.clones));
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
post = _ref[_i];
file = post.file;
if (!(file && file.isVideo && file.isExpanded)) {
continue;
}
video = file.fullImage;
visible = ($.hasAudio(video) && !video.muted) || Header.isNodeVisible(video);
if (visible && file.wasPlaying) {
delete file.wasPlaying;
video.play();
} else if (!visible && !video.paused) {
file.wasPlaying = true;
video.pause();
}
}
});
},
setFitness: function() {
return $[this.checked ? 'addClass' : 'rmClass'](doc, this.name.toLowerCase().replace(/\s+/g, '-'));
}
},
toggle: function(post) {
var next;
if (!(post.file.isExpanding || post.file.isExpanded)) {
post.file.scrollIntoView = Conf['Scroll into view'];
ImageExpand.expand(post);
return;
}
ImageExpand.contract(post);
if (Conf['Advance on contract']) {
next = post.nodes.root;
while (next = $.x("following::div[contains(@class,'postContainer')][1]", next)) {
if (!($('.stub', next) || next.offsetHeight === 0)) {
break;
}
}
if (next) {
return Header.scrollTo(next);
}
}
},
contract: function(post) {
var bottom, cb, el, eventName, file, oldHeight, scrollY, top, x, _i, _len, _ref, _ref1;
file = post.file;
if (el = file.fullImage) {
top = Header.getTopOf(el);
bottom = top + el.getBoundingClientRect().height;
oldHeight = d.body.clientHeight;
scrollY = window.scrollY;
}
$.rmClass(post.nodes.root, 'expanded-image');
$.rmClass(file.thumb, 'expanding');
if (file.videoControls) {
$.rm(file.videoControls);
}
file.thumb.parentNode.href = file.URL;
file.thumb.parentNode.target = '_blank';
_ref = ['isExpanding', 'isExpanded', 'videoControls', 'wasPlaying', 'scrollIntoView'];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
x = _ref[_i];
delete file[x];
}
if (!el) {
return;
}
if (doc.contains(el)) {
if (bottom <= 0) {
window.scroll(0, scrollY + d.body.clientHeight - oldHeight);
} else {
Header.scrollToIfNeeded(post.nodes.root);
}
if (window.scrollX > 0) {
window.scroll(0, window.scrollY);
}
}
$.off(el, 'error', ImageExpand.error);
ImageCommon.pushCache(el);
if (file.isVideo) {
ImageCommon.pause(el);
_ref1 = ImageExpand.videoCB;
for (eventName in _ref1) {
cb = _ref1[eventName];
$.off(el, eventName, cb);
}
}
if (Conf['Restart when Opened']) {
ImageCommon.rewind(file.thumb);
}
delete file.fullImage;
return $.queueTask(function() {
if (file.isExpanding || file.isExpanded) {
return;
}
$.rmClass(el, 'full-image');
if (el.id) {
return;
}
return $.rm(el);
});
},
expand: function(post, src) {
var el, file, isVideo, thumb, _ref;
file = post.file;
thumb = file.thumb, isVideo = file.isVideo;
if (post.isHidden || file.isExpanding || file.isExpanded) {
return;
}
$.addClass(thumb, 'expanding');
file.isExpanding = true;
if (file.fullImage) {
el = file.fullImage;
} else if (((_ref = ImageCommon.cache) != null ? _ref.dataset.fullID : void 0) === post.fullID) {
el = file.fullImage = ImageCommon.popCache();
$.on(el, 'error', ImageExpand.error);
if (Conf['Restart when Opened'] && el.id !== 'ihover') {
ImageCommon.rewind(el);
}
el.removeAttribute('id');
} else {
el = file.fullImage = $.el((isVideo ? 'video' : 'img'));
el.dataset.fullID = post.fullID;
$.on(el, 'error', ImageExpand.error);
el.src = src || file.URL;
}
el.className = 'full-image';
$.after(thumb, el);
if (isVideo) {
if (Conf['Show Controls'] && Conf['Click Passthrough'] && !file.videoControls) {
file.videoControls = ImageExpand.videoControls.cloneNode(true);
$.add(file.text, file.videoControls);
}
thumb.parentNode.removeAttribute('href');
thumb.parentNode.removeAttribute('target');
el.loop = true;
Volume.setup(el);
ImageExpand.setupVideoCB(post);
}
if (!isVideo) {
return $.asap((function() {
return el.naturalHeight;
}), function() {
return ImageExpand.completeExpand(post);
});
} else if (el.readyState >= el.HAVE_METADATA) {
return ImageExpand.completeExpand(post);
} else {
return $.on(el, 'loadedmetadata', function() {
return ImageExpand.completeExpand(post);
});
}
},
completeExpand: function(post) {
var bottom, file, imageBottom, oldHeight, scrollY;
file = post.file;
if (!file.isExpanding) {
return;
}
bottom = Header.getTopOf(file.thumb) + file.thumb.getBoundingClientRect().height;
oldHeight = d.body.clientHeight;
scrollY = window.scrollY;
$.addClass(post.nodes.root, 'expanded-image');
$.rmClass(file.thumb, 'expanding');
file.isExpanded = true;
delete file.isExpanding;
if (doc.contains(post.nodes.root) && bottom <= 0) {
window.scroll(window.scrollX, scrollY + d.body.clientHeight - oldHeight);
}
if (file.scrollIntoView) {
delete file.scrollIntoView;
imageBottom = Header.getBottomOf(file.fullImage) - 25;
if (imageBottom < 0) {
window.scrollBy(0, Math.min(-imageBottom, Header.getTopOf(file.fullImage)));
}
}
if (file.isVideo) {
return ImageExpand.setupVideo(post, Conf['Autoplay'], Conf['Show Controls']);
}
},
setupVideo: function(post, playing, controls) {
var fullImage;
fullImage = post.file.fullImage;
if (!playing) {
fullImage.controls = controls;
return;
}
fullImage.controls = false;
$.asap((function() {
return doc.contains(fullImage);
}), function() {
if (!d.hidden && Header.isNodeVisible(fullImage)) {
return fullImage.play();
} else {
return post.file.wasPlaying = true;
}
});
if (controls) {
return ImageCommon.addControls(fullImage);
}
},
videoCB: (function() {
var mousedown;
mousedown = false;
return {
mouseover: function() {
return mousedown = false;
},
mousedown: function(e) {
if (e.button === 0) {
return mousedown = true;
}
},
mouseup: function(e) {
if (e.button === 0) {
return mousedown = false;
}
},
mouseout: function(e) {
if (mousedown && e.clientX <= this.getBoundingClientRect().left) {
return ImageExpand.toggle(Get.postFromNode(this));
}
}
};
})(),
setupVideoCB: function(post) {
var cb, eventName, _ref;
_ref = ImageExpand.videoCB;
for (eventName in _ref) {
cb = _ref[eventName];
$.on(post.file.fullImage, eventName, cb);
}
if (post.file.videoControls) {
return $.on(post.file.videoControls.firstElementChild, 'click', function() {
return ImageExpand.toggle(post);
});
}
},
error: function() {
var post;
post = Get.postFromNode(this);
$.rm(this);
delete post.file.fullImage;
if (!(post.file.isExpanding || post.file.isExpanded)) {
return;
}
if (ImageCommon.decodeError(this, post)) {
return ImageExpand.contract(post);
}
if (this.src.split('/')[2] !== 'i.4cdn.org') {
return ImageExpand.contract(post);
}
return ImageCommon.error(this, post, 10 * $.SECOND, function(URL) {
if (post.file.isExpanding || post.file.isExpanded) {
ImageExpand.contract(post);
if (URL) {
return ImageExpand.expand(post, URL);
}
}
});
},
menu: {
init: function() {
var conf, createSubEntry, el, name, subEntries, _ref;
if (!ImageExpand.enabled) {
return;
}
el = $.el('span', {
textContent: 'Image Expansion',
className: 'image-expansion-link'
});
createSubEntry = ImageExpand.menu.createSubEntry;
subEntries = [];
_ref = Config.imageExpansion;
for (name in _ref) {
conf = _ref[name];
subEntries.push(createSubEntry(name, conf[1]));
}
return Header.menu.addEntry({
el: el,
order: 105,
subEntries: subEntries
});
},
createSubEntry: function(name, desc) {
var input, label;
label = UI.checkbox(name, name);
label.title = desc;
input = label.firstElementChild;
if (name === 'Fit width' || name === 'Fit height') {
$.on(input, 'change', ImageExpand.cb.setFitness);
}
$.event('change', null, input);
$.on(input, 'change', $.cb.checked);
return {
el: label
};
}
}
};
ImageHover = {
init: function() {
var _ref;
if ((_ref = g.VIEW) !== 'index' && _ref !== 'thread') {
return;
}
if (Conf['Image Hover']) {
Post.callbacks.push({
name: 'Image Hover',
cb: this.node
});
}
if (Conf['Image Hover in Catalog']) {
return CatalogThread.callbacks.push({
name: 'Image Hover',
cb: this.catalogNode
});
}
},
node: function() {
if (!(this.file && (this.file.isImage || this.file.isVideo))) {
return;
}
$.on(this.file.thumb, 'mouseover', ImageHover.mouseover(this));
if (Conf['Mouse Wheel Volume'] && this.file.isVideo) {
return $.on(this.file.thumb, 'wheel', ImageHover.wheel);
}
},
catalogNode: function() {
var file;
file = this.thread.OP.file;
if (!(file && (file.isImage || file.isVideo))) {
return;
}
$.on(this.nodes.thumb, 'mouseover', ImageHover.mouseover(this.thread.OP));
if (Conf['Mouse Wheel Volume'] && this.thread.OP.file.isVideo) {
return $.on(this.nodes.thumb, 'wheel', ImageHover.wheel);
}
},
mouseover: function(post) {
return function(e) {
var el, error, file, height, isVideo, left, maxHeight, maxWidth, padding, right, scale, width, x, _ref, _ref1, _ref2;
if (!doc.contains(this)) {
return;
}
file = post.file;
isVideo = file.isVideo;
if (file.isExpanding || file.isExpanded) {
return;
}
error = ImageHover.error(post);
if (((_ref = ImageCommon.cache) != null ? _ref.dataset.fullID : void 0) === post.fullID) {
el = ImageCommon.popCache();
$.on(el, 'error', error);
} else {
el = $.el((isVideo ? 'video' : 'img'));
el.dataset.fullID = post.fullID;
$.on(el, 'error', error);
el.src = file.URL;
}
if (Conf['Restart when Opened']) {
ImageCommon.rewind(el);
ImageCommon.rewind(this);
}
el.id = 'ihover';
$.add(Header.hover, el);
if (isVideo) {
el.loop = true;
el.controls = false;
Volume.setup(el);
if (Conf['Autoplay']) {
el.play();
}
}
_ref1 = (function() {
var _i, _len, _ref1, _results;
_ref1 = file.dimensions.split('x');
_results = [];
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
x = _ref1[_i];
_results.push(+x);
}
return _results;
})(), width = _ref1[0], height = _ref1[1];
_ref2 = this.getBoundingClientRect(), left = _ref2.left, right = _ref2.right;
padding = 16;
maxWidth = Math.max(left, doc.clientWidth - right);
maxHeight = doc.clientHeight - padding;
scale = Math.min(1, maxWidth / width, maxHeight / height);
el.style.maxWidth = "" + (scale * width) + "px";
el.style.maxHeight = "" + (scale * height) + "px";
return UI.hover({
root: this,
el: el,
latestEvent: e,
endEvents: 'mouseout click',
asapTest: function() {
return true;
},
height: scale * height + padding,
noRemove: true,
cb: function() {
$.off(el, 'error', error);
ImageCommon.pushCache(el);
ImageCommon.pause(el);
$.rm(el);
return el.removeAttribute('style');
}
});
};
},
error: function(post) {
return function() {
if (ImageCommon.decodeError(this, post)) {
return;
}
return ImageCommon.error(this, post, 3 * $.SECOND, (function(_this) {
return function(URL) {
if (URL) {
return _this.src = URL + (_this.src === URL ? '?' + Date.now() : '');
} else {
return $.rm(_this);
}
};
})(this));
};
},
wheel: function(e) {
var el, volume;
if (!(el = $.id('ihover'))) {
return;
}
if (el.muted || !$.hasAudio(el)) {
return;
}
volume = el.volume + 0.1;
if (e.deltaY < 0) {
volume *= 1.1;
}
if (e.deltaY > 0) {
volume /= 1.1;
}
el.volume = $.minmax(volume - 0.1, 0, 1);
return e.preventDefault();
}
};
ImageLoader = {
init: function() {
var prefetch, _ref;
if (!(((_ref = g.VIEW) === 'index' || _ref === 'thread') && g.BOARD.ID !== 'f')) {
return;
}
if (!(Conf['Image Prefetching'] || Conf['Replace JPG'] || Conf['Replace PNG'] || Conf['Replace GIF'] || Conf['Replace WEBM'])) {
return;
}
Post.callbacks.push({
name: 'Image Replace',
cb: this.node
});
$.on(d, 'PostsInserted', function() {
return g.posts.forEach(ImageLoader.prefetch);
});
if (Conf['Replace WEBM']) {
$.on(d, 'scroll visibilitychange 4chanXInitFinished PostsInserted', this.playVideos);
}
if (!Conf['Image Prefetching']) {
return;
}
prefetch = $.el('label', {
innerHTML: "<input type=\"checkbox\" name=\"prefetch\"> Prefetch Images"
});
this.el = prefetch.firstElementChild;
$.on(this.el, 'change', this.toggle);
return Header.menu.addEntry({
el: prefetch,
order: 104
});
},
node: function() {
if (this.isClone || !this.file) {
return;
}
if (Conf['Replace WEBM'] && this.file.isVideo) {
ImageLoader.replaceVideo(this);
}
return ImageLoader.prefetch(this);
},
replaceVideo: function(post) {
var attr, file, thumb, video, _i, _len, _ref;
file = post.file;
thumb = file.thumb;
video = $.el('video', {
preload: 'none',
loop: true,
muted: true,
poster: thumb.src,
textContent: thumb.alt,
className: thumb.className
});
video.setAttribute('muted', 'muted');
video.dataset.md5 = thumb.dataset.md5;
_ref = ['height', 'width', 'maxHeight', 'maxWidth'];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
attr = _ref[_i];
video.style[attr] = thumb.style[attr];
}
video.src = file.URL;
$.replace(thumb, video);
file.thumb = video;
return file.videoThumb = true;
},
prefetch: function(post) {
var URL, clone, el, file, isImage, isVideo, match, replace, thumb, type, _i, _len, _ref;
file = post.file;
if (!file) {
return;
}
isImage = file.isImage, isVideo = file.isVideo, thumb = file.thumb, URL = file.URL;
if (file.isPrefetched || !(isImage || isVideo) || post.isHidden || post.thread.isHidden) {
return;
}
type = (match = URL.match(/\.([^.]+)$/)[1].toUpperCase()) === 'JPEG' ? 'JPG' : match;
replace = Conf["Replace " + type] && !/spoiler/.test(thumb.src);
if (!(replace || Conf['prefetch'])) {
return;
}
if (![post].concat(__slice.call(post.clones)).some(function(clone) {
return doc.contains(clone.nodes.root);
})) {
return;
}
file.isPrefetched = true;
if (file.videoThumb) {
_ref = post.clones;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
clone = _ref[_i];
clone.file.thumb.preload = 'auto';
}
thumb.preload = 'auto';
if (typeof chrome === "undefined" || chrome === null) {
$.on(thumb, 'loadeddata', function() {
return this.removeAttribute('poster');
});
}
return;
}
el = $.el(isImage ? 'img' : 'video');
if (replace && isImage) {
$.on(el, 'load', function() {
var _j, _len1, _ref1;
_ref1 = post.clones;
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
clone = _ref1[_j];
clone.file.thumb.src = URL;
}
return thumb.src = URL;
});
}
return el.src = URL;
},
toggle: function() {
if (Conf['prefetch'] = this.checked) {
g.posts.forEach(ImageLoader.prefetch);
}
},
playVideos: function() {
var qpClone, _ref;
qpClone = (_ref = $.id('qp')) != null ? _ref.firstElementChild : void 0;
return g.posts.forEach(function(post) {
var thumb, _i, _len, _ref1, _ref2;
_ref1 = [post].concat(__slice.call(post.clones));
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
post = _ref1[_i];
if (!((_ref2 = post.file) != null ? _ref2.videoThumb : void 0)) {
continue;
}
thumb = post.file.thumb;
if (Header.isNodeVisible(thumb) || post.nodes.root === qpClone) {
thumb.play();
} else {
thumb.pause();
}
}
});
}
};
Metadata = {
init: function() {
var _ref;
if (!(Conf['WEBM Metadata'] && ((_ref = g.VIEW) === 'index' || _ref === 'thread') && g.BOARD.ID !== 'f')) {
return;
}
return Post.callbacks.push({
name: 'WEBM Metadata',
cb: this.node
});
},
node: function() {
var el;
if (!(this.file && /webm$/i.test(this.file.URL))) {
return;
}
if (this.isClone) {
el = $('.webm-title', this.file.text);
} else {
el = $.el('span', {
className: 'webm-title'
});
$.extend(el, {
innerHTML: "<a href=\"javascript:;\"></a>"
});
$.add(this.file.text, [$.tn('\u00A0'), el]);
}
if (el.children.length === 1) {
return $.one(el.lastElementChild, 'mouseover focus', Metadata.load);
}
},
load: function() {
$.rmClass(this.parentNode, 'error');
$.addClass(this.parentNode, 'loading');
return CrossOrigin.binary(Get.postFromNode(this).file.URL, (function(_this) {
return function(data) {
var output, title;
$.rmClass(_this.parentNode, 'loading');
if (data != null) {
title = Metadata.parse(data);
output = $.el('span', {
textContent: title || ''
});
if (title == null) {
$.addClass(_this.parentNode, 'not-found');
}
$.before(_this, output);
_this.parentNode.tabIndex = 0;
if (d.activeElement === _this) {
_this.parentNode.focus();
}
return _this.tabIndex = -1;
} else {
$.addClass(_this.parentNode, 'error');
return $.one(_this, 'click', Metadata.load);
}
};
})(this), {
Range: 'bytes=0-9999'
});
},
parse: function(data) {
var element, i, readInt, size, title;
readInt = function() {
var len, n;
n = data[i++];
len = 0;
while (n < (0x80 >> len)) {
len++;
}
n ^= 0x80 >> len;
while (len-- && i < data.length) {
n = (n << 8) ^ data[i++];
}
return n;
};
i = 0;
while (i < data.length) {
element = readInt();
size = readInt();
if (element === 0x3BA9) {
title = '';
while (size-- && i < data.length) {
title += String.fromCharCode(data[i++]);
}
return decodeURIComponent(escape(title));
} else if (element !== 0x8538067 && element !== 0x549A966) {
i += size;
}
}
return null;
}
};
RevealSpoilers = {
init: function() {
var _ref;
if (!(((_ref = g.VIEW) === 'index' || _ref === 'thread') && Conf['Reveal Spoiler Thumbnails'])) {
return;
}
return Post.callbacks.push({
name: 'Reveal Spoiler Thumbnails',
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');
thumb.style.maxHeight = thumb.style.maxWidth = this.isReply ? '125px' : '250px';
return thumb.src = this.file.thumbURL;
}
};
Sauce = {
init: function() {
var err, link, links, _i, _len, _ref, _ref1;
if (!(((_ref = g.VIEW) === 'index' || _ref === 'thread') && Conf['Sauce'])) {
return;
}
links = [];
_ref1 = Conf['sauces'].split('\n');
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
link = _ref1[_i];
try {
if (link[0] !== '#') {
links.push(link.trim());
}
} catch (_error) {
err = _error;
}
}
if (!links.length) {
return;
}
this.links = links;
this.link = $.el('a', {
target: '_blank'
});
return Post.callbacks.push({
name: 'Sauce',
cb: this.node
});
},
createSauceLink: function(link, post) {
var a, ext, i, key, m, part, parts, _i, _len, _ref, _ref1, _ref2, _ref3;
parts = {};
_ref = link.split(/;(?=(?:text|boards|types):)/);
for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
part = _ref[i];
if (i === 0) {
parts['url'] = part;
} else {
m = part.match(/^(\w*):(.*)$/);
parts[m[1]] = m[2];
}
}
parts['text'] || (parts['text'] = ((_ref1 = parts['url'].match(/(\w+)\.\w+\//)) != null ? _ref1[1] : void 0) || '?');
for (key in parts) {
parts[key] = parts[key].replace(/%(T?URL|MD5|board|name|%|semi)/g, function(parameter) {
var type;
type = {
'%TURL': post.file.thumbURL,
'%URL': post.file.URL,
'%MD5': post.file.MD5,
'%board': post.board.ID,
'%name': post.file.name,
'%%': '%',
'%semi': ';'
}[parameter];
if (key === 'url' && parameter !== '%%' && parameter !== '%semi') {
if (/^javascript:/i.test(parts['url'])) {
type = JSON.stringify(type);
}
type = encodeURIComponent(type);
}
return type;
});
}
ext = ((_ref2 = post.file.URL.match(/\.([^\.]*)$/)) != null ? _ref2[1] : void 0) || '';
if (!(!parts['boards'] || (_ref3 = post.board.ID, __indexOf.call(parts['boards'].split(','), _ref3) >= 0))) {
return null;
}
if (!(!parts['types'] || __indexOf.call(parts['types'].split(','), ext) >= 0)) {
return null;
}
a = Sauce.link.cloneNode(true);
a.href = parts['url'];
a.textContent = parts['text'];
if (/^javascript:/i.test(parts['url'])) {
a.removeAttribute('target');
}
return a;
},
node: function() {
var link, node, 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];
if (node = Sauce.createSauceLink(link, this)) {
nodes.push($.tn('\u00A0'), node);
}
}
return $.add(this.file.text, nodes);
}
};
Volume = {
init: function() {
var unmuteEntry, volumeEntry, _ref, _ref1;
if (!(((_ref = g.VIEW) === 'index' || _ref === 'thread') && (Conf['Image Expansion'] || Conf['Image Hover'] || Conf['Image Hover in Catalog'] || Conf['Gallery']))) {
return;
}
$.sync('Allow Sound', function(x) {
var _ref1;
Conf['Allow Sound'] = x;
return (_ref1 = Volume.inputs) != null ? _ref1.unmute.checked = x : void 0;
});
$.sync('Default Volume', function(x) {
var _ref1;
Conf['Default Volume'] = x;
return (_ref1 = Volume.inputs) != null ? _ref1.volume.value = x : void 0;
});
if ((_ref1 = g.BOARD.ID) !== 'gif' && _ref1 !== 'wsg') {
return;
}
unmuteEntry = UI.checkbox('Allow Sound', 'Allow Sound');
unmuteEntry.title = Config.main['Images and Videos']['Allow Sound'][1];
volumeEntry = $.el('label', {
title: 'Default volume for videos.'
});
$.extend(volumeEntry, {
innerHTML: "<input name=\"Default Volume\" type=\"range\" min=\"0\" max=\"1\" step=\"0.01\" value=\"" + E(Conf["Default Volume"]) + "\"> Volume"
});
this.inputs = {
unmute: unmuteEntry.firstElementChild,
volume: volumeEntry.firstElementChild
};
$.on(this.inputs.unmute, 'change', $.cb.checked);
$.on(this.inputs.volume, 'change', $.cb.value);
Header.menu.addEntry({
el: unmuteEntry,
order: 200
});
return Header.menu.addEntry({
el: volumeEntry,
order: 201
});
},
setup: function(video) {
video.muted = !Conf['Allow Sound'];
video.volume = Conf['Default Volume'];
return $.on(video, 'volumechange', Volume.change);
},
change: function() {
var items, muted, volume;
muted = this.muted, volume = this.volume;
items = {
'Allow Sound': !muted,
'Default Volume': volume
};
$.set(items);
$.extend(Conf, items);
if (Volume.inputs) {
Volume.inputs.unmute.checked = !muted;
return Volume.inputs.volume.value = volume;
}
}
};
Embedding = {
init: function() {
var type, _i, _len, _ref;
if (!(Conf['Embedding'] || Conf['Link Title'])) {
return;
}
this.types = {};
_ref = this.ordered_types;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
type = _ref[_i];
this.types[type.key] = type;
}
if (Conf['Floating Embeds']) {
this.dialog = UI.dialog('embedding', 'top: 50px; right: 0px;', {
innerHTML: "<div><div class=\"move\"></div><a href=\"javascript:;\" class=\"jump\" title=\"Jump to post\">→</a><a href=\"javascript:;\" class=\"close\" title=\"Close\">×</a></div><div id=\"media-embed\"><div></div></div>"
});
this.media = $('#media-embed', this.dialog);
$.one(d, '4chanXInitFinished', this.ready);
}
if (Conf['Link Title']) {
return $.on(d, '4chanXInitFinished PostsInserted', function() {
var key, service, _ref1, _ref2;
_ref1 = Embedding.types;
for (key in _ref1) {
service = _ref1[key];
if ((_ref2 = service.title) != null ? _ref2.batchSize : void 0) {
Embedding.flushTitles(service.title);
}
}
});
}
},
events: function(post) {
var el, i, items;
if (!Conf['Embedding']) {
return;
}
i = 0;
items = $$('.embedder', post.nodes.comment);
while (el = items[i++]) {
$.on(el, 'click', Embedding.cb.toggle);
if ($.hasClass(el, 'embedded')) {
Embedding.cb.toggle.call(el);
}
}
},
process: function(link, post) {
var data;
if (!(Conf['Embedding'] || Conf['Link Title'])) {
return;
}
if ($.x('ancestor::pre', link)) {
return;
}
if (data = Embedding.services(link)) {
data.post = post;
if (Conf['Embedding']) {
Embedding.embed(data);
}
if (Conf['Link Title']) {
return Embedding.title(data);
}
}
},
services: function(link) {
var href, match, type, _i, _len, _ref;
href = link.href;
_ref = Embedding.ordered_types;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
type = _ref[_i];
if (!(match = type.regExp.exec(href))) {
continue;
}
if (type.dummy || type.httpOnly && location.protocol !== 'http:') {
return;
}
return {
key: type.key,
uid: match[1],
options: match[2],
link: link
};
}
},
embed: function(data) {
var embed, key, link, name, options, post, uid, value, _ref;
key = data.key, uid = data.uid, options = data.options, link = data.link, post = data.post;
embed = $.el('a', {
className: 'embedder',
rel: 'nofollow noreferrer',
href: link.href,
textContent: '(embed)'
});
_ref = {
key: key,
uid: uid,
options: options
};
for (name in _ref) {
value = _ref[name];
embed.dataset[name] = value;
}
$.addClass(link, "" + embed.dataset.key);
$.on(embed, 'click', Embedding.cb.toggle);
$.after(link, [$.tn(' '), embed]);
if (Conf['Auto-embed'] && !Conf['Floating Embeds'] && !post.isFetchedQuote) {
return $.asap((function() {
return doc.contains(embed);
}), function() {
return Embedding.cb.toggle.call(embed);
});
}
},
ready: function() {
$.addClass(Embedding.dialog, 'empty');
$.on($('.close', Embedding.dialog), 'click', Embedding.closeFloat);
$.on($('.move', Embedding.dialog), 'mousedown', Embedding.dragEmbed);
$.on($('.jump', Embedding.dialog), 'click', function() {
if (doc.contains(Embedding.lastEmbed)) {
return Header.scrollTo(Embedding.lastEmbed);
}
});
return $.add(d.body, Embedding.dialog);
},
closeFloat: function() {
delete Embedding.lastEmbed;
$.addClass(Embedding.dialog, 'empty');
return $.replace(Embedding.media.firstChild, $.el('div'));
},
dragEmbed: function() {
var style;
style = Embedding.media.style;
if (Embedding.dragEmbed.mouseup) {
$.off(d, 'mouseup', Embedding.dragEmbed);
Embedding.dragEmbed.mouseup = false;
style.visibility = '';
return;
}
$.on(d, 'mouseup', Embedding.dragEmbed);
Embedding.dragEmbed.mouseup = true;
return style.visibility = 'hidden';
},
title: function(data) {
var key, link, options, post, service, uid;
key = data.key, uid = data.uid, options = data.options, link = data.link, post = data.post;
if (!(service = Embedding.types[key].title)) {
return;
}
if (service.batchSize) {
(service.queue || (service.queue = [])).push(data);
if (service.queue.length >= service.batchSize) {
return Embedding.flushTitles(service);
}
} else {
if (!$.cache(service.api(uid), (function() {
return Embedding.cb.title(this, data);
}), {
responseType: 'json'
})) {
return $.extend(link, {
innerHTML: "[" + E(key) + "] <span class=\"warning\">Title Link Blocked</span> (are you using NoScript?)</a>"
});
}
}
},
flushTitles: function(service) {
var cb, data, queue, _i, _len;
queue = service.queue;
if (!(queue != null ? queue.length : void 0)) {
return;
}
service.queue = [];
cb = function() {
var data, _i, _len;
for (_i = 0, _len = queue.length; _i < _len; _i++) {
data = queue[_i];
Embedding.cb.title(this, data);
}
};
if (!$.cache(service.api((function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = queue.length; _i < _len; _i++) {
data = queue[_i];
_results.push(data.uid);
}
return _results;
})()), cb, {
responseType: 'json'
})) {
for (_i = 0, _len = queue.length; _i < _len; _i++) {
data = queue[_i];
$.extend(data.link, {
innerHTML: "[" + E(data.key) + "] <span class=\"warning\">Title Link Blocked</span> (are you using NoScript?)</a>"
});
}
}
},
cb: {
toggle: function(e) {
var div;
if (e != null) {
e.preventDefault();
}
if (Conf['Floating Embeds']) {
if (!(div = Embedding.media.firstChild)) {
return;
}
$.replace(div, Embedding.cb.embed(this));
Embedding.lastEmbed = Get.postFromNode(this).nodes.root;
$.rmClass(Embedding.dialog, 'empty');
return;
}
if ($.hasClass(this, "embedded")) {
$.rm(this.nextElementSibling);
this.textContent = '(embed)';
} else {
$.after(this, Embedding.cb.embed(this));
this.textContent = '(unembed)';
}
return $.toggleClass(this, 'embedded');
},
embed: function(a) {
var container, el, type;
container = $.el('div');
$.add(container, el = (type = Embedding.types[a.dataset.key]).el(a));
el.style.cssText = type.style != null ? type.style : "border:0;width:640px;height:390px";
return container;
},
title: function(req, data) {
var key, link, link2, options, post, post2, service, status, text, uid, _base, _i, _j, _len, _len1, _ref, _ref1;
key = data.key, uid = data.uid, options = data.options, link = data.link, post = data.post;
status = req.status;
service = Embedding.types[key].title;
text = "[" + key + "] " + ((function() {
switch (status) {
case 200:
case 304:
return service.text(req.response, uid);
case 404:
return "Not Found";
case 403:
return "Forbidden or Private";
default:
return "" + status + "'d";
}
})());
link.dataset.original = link.textContent;
link.textContent = text;
_ref = post.clones;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
post2 = _ref[_i];
_ref1 = $$('a.linkify', post2.nodes.comment);
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
link2 = _ref1[_j];
if (!(link2.href === link.href)) {
continue;
}
if ((_base = link2.dataset).original == null) {
_base.original = link2.textContent;
}
link2.textContent = text;
}
}
}
},
ordered_types: [
{
key: 'audio',
regExp: /\.(?:mp3|ogg|wav)(?:\?|$)/i,
style: '',
el: function(a) {
return $.el('audio', {
controls: true,
preload: 'auto',
src: a.href
});
}
}, {
key: 'gist',
regExp: /^\w+:\/\/gist\.github\.com\/(?:[\w\-]+\/)?(\w+)/,
el: function(a) {
var content, el;
el = $.el('iframe');
el.setAttribute('sandbox', 'allow-scripts');
content = {
innerHTML: "<html><head><title>" + E(a.dataset.uid) + "</title></head><body><script src=\"https://gist.github.com/" + E(a.dataset.uid) + ".js\"></script></body></html>"
};
el.src = "data:text/html;charset=utf-8,<!doctype html>" + (encodeURIComponent(content.innerHTML));
return el;
},
title: {
api: function(uid) {
return "https://api.github.com/gists/" + uid;
},
text: function(_arg) {
var file, files;
files = _arg.files;
for (file in files) {
if (files.hasOwnProperty(file)) {
return file;
}
}
}
}
}, {
key: 'image',
regExp: /\.(?:gif|png|jpg|jpeg|bmp)(?:\?|$)/i,
style: '',
el: function(a) {
return $.el('div', {
innerHTML: "<a target=\"_blank\" href=\"" + E(a.href) + "\"><img src=\"" + E(a.href) + "\" style=\"max-width: 80vw; max-height: 80vh;\"></a>"
});
}
}, {
key: 'InstallGentoo',
regExp: /^\w+:\/\/paste\.installgentoo\.com\/view\/(?:raw\/|download\/|embed\/)?(\w+)/,
el: function(a) {
return $.el('iframe', {
src: "https://paste.installgentoo.com/view/embed/" + a.dataset.uid
});
}
}, {
key: 'Twitter',
regExp: /^\w+:\/\/(?:www\.)?twitter\.com\/(\w+\/status\/\d+)/,
el: function(a) {
return $.el('iframe', {
src: "https://twitframe.com/show?url=https://twitter.com/" + a.dataset.uid
});
}
}, {
key: 'LiveLeak',
regExp: /^\w+:\/\/(?:\w+\.)?liveleak\.com\/.*\?.*i=(\w+)/,
httpOnly: true,
el: function(a) {
var el;
el = $.el('iframe', {
width: "640",
height: "360",
src: "http://www.liveleak.com/ll_embed?i=" + a.dataset.uid,
frameborder: "0"
});
el.setAttribute("allowfullscreen", "true");
return el;
}
}, {
key: 'MediaCrush',
regExp: /^\w+:\/\/(?:www\.)?mediacru\.sh\/([\w\-]+)/,
style: '',
el: function(a) {
var el;
el = $.el('div');
$.queueTask(function() {
return $.cache("https://mediacru.sh/" + a.dataset.uid + ".json", function() {
var embed, ext, file, files, i, status, type, _i, _j, _k, _len, _len1, _len2, _ref, _ref1;
if (!doc.contains(el)) {
return;
}
status = this.status;
if (status !== 200 && status !== 304) {
return el.textContent = "ERROR " + status;
}
files = this.response.files;
_ref = ['video/mp4', 'video/webm', 'video/ogv', 'image/svg+xml', 'image/png', 'image/gif', 'image/jpeg', 'audio/mpeg', 'audio/ogg'];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
type = _ref[_i];
for (_j = 0, _len1 = files.length; _j < _len1; _j++) {
file = files[_j];
if (file.type === type) {
embed = file;
break;
}
}
if (embed) {
break;
}
}
if (!embed) {
return el.textContent = "ERROR: Not a valid filetype";
}
switch (embed.type) {
case 'video/mp4':
case 'video/webm':
case 'video/ogv':
$.extend(el, {
innerHTML: "<video controls loop style=\"max-width: 80vw; max-height: 80vh;\"><source type=\"video/mp4\"><source type=\"video/webm\"></video>"
});
_ref1 = ['mp4', 'webm'];
for (i = _k = 0, _len2 = _ref1.length; _k < _len2; i = ++_k) {
ext = _ref1[i];
el.firstChild.children[i].src = "https://mediacru.sh/" + a.dataset.uid + "." + ext;
}
break;
case 'image/svg+xml':
case 'image/png':
case 'image/gif':
case 'image/jpeg':
$.extend(el, {
innerHTML: "<a target=\"_blank\" href=\"" + E(a.href) + "\"><img src=\"https://mediacru.sh/" + E(file.file) + "\" style=\"max-width: 80vw; max-height: 80vh;\"></a>"
});
break;
case 'audio/mpeg':
case 'audio/ogg':
$.extend(el, {
innerHTML: "<audio controls><source type=\"audio/ogg\" src=\"https://mediacru.sh/" + E(a.dataset.uid) + ".ogg\"></audio>"
});
break;
default:
el.textContent = "ERROR: No valid filetype.";
}
});
});
return el;
}
}, {
key: 'pastebin',
regExp: /^\w+:\/\/(?:\w+\.)?pastebin\.com\/(?!u\/)(?:[\w\.]+\?i\=)?(\w+)/,
httpOnly: true,
el: function(a) {
var div;
return div = $.el('iframe', {
src: "http://pastebin.com/embed_iframe.php?i=" + a.dataset.uid
});
}
}, {
key: 'gfycat',
regExp: /^\w+:\/\/(?:www\.)?gfycat\.com\/(?:iframe\/)?(\w+)/,
el: function(a) {
var div;
return div = $.el('iframe', {
src: "//gfycat.com/iframe/" + a.dataset.uid
});
}
}, {
key: 'SoundCloud',
regExp: /^\w+:\/\/(?:www\.)?(?:soundcloud\.com\/|snd\.sc\/)([\w\-\/]+)/,
style: 'border: 0; width: 500px; height: 400px;',
el: function(a) {
return $.el('iframe', {
src: "https://w.soundcloud.com/player/?visual=true&show_comments=false&url=https%3A%2F%2Fsoundcloud.com%2F" + (encodeURIComponent(a.dataset.uid))
});
},
title: {
api: function(uid) {
return "//soundcloud.com/oembed?format=json&url=https%3A%2F%2Fsoundcloud.com%2F" + (encodeURIComponent(uid));
},
text: function(_) {
return _.title;
}
}
}, {
key: 'StrawPoll',
regExp: /^\w+:\/\/(?:www\.)?strawpoll\.me\/(?:embed_\d+\/)?(\d+(?:\/r)?)/,
httpOnly: true,
style: 'border: 0; width: 600px; height: 406px;',
el: function(a) {
return $.el('iframe', {
src: "http://strawpoll.me/embed_1/" + a.dataset.uid
});
}
}, {
key: 'TwitchTV',
regExp: /^\w+:\/\/(?:www\.)?twitch\.tv\/([^#\&\?]*)/,
httpOnly: true,
style: "border: none; width: 640px; height: 360px;",
el: function(a) {
var channel, id, idparam, obj, result, type, _;
if (result = /(\w+)\/([bc])\/(\d+)/i.exec(a.dataset.uid)) {
_ = result[0], channel = result[1], type = result[2], id = result[3];
idparam = {
'b': 'archive_id',
'c': 'chapter_id'
};
obj = $.el('object', {
data: 'http://www.twitch.tv/widgets/archive_embed_player.swf'
});
$.extend(obj, {
innerHTML: "<param name=\"allowFullScreen\" value=\"true\"><param name=\"flashvars\">"
});
obj.children[1].value = "channel=" + channel + "&start_volume=25&auto_play=false&" + idparam[type] + "=" + id;
return obj;
} else {
channel = (/(\w+)/.exec(a.dataset.uid))[0];
obj = $.el('object', {
data: "http://www.twitch.tv/widgets/live_embed_player.swf?channel=" + channel
});
$.extend(obj, {
innerHTML: "<param name=\"allowFullScreen\" value=\"true\"><param name=\"flashvars\">"
});
obj.children[1].value = "hostname=www.twitch.tv&channel=" + channel + "&auto_play=true&start_volume=25";
return obj;
}
}
}, {
key: 'Vocaroo',
regExp: /^\w+:\/\/(?:www\.)?vocaroo\.com\/i\/(\w+)/,
style: '',
el: function(a) {
return $.el('audio', {
controls: true,
preload: 'auto',
src: "http://vocaroo.com/media_command.php?media=" + a.dataset.uid + "&command=download_ogg"
});
}
}, {
key: 'Vimeo',
regExp: /^\w+:\/\/(?:www\.)?vimeo\.com\/(\d+)/,
el: function(a) {
return $.el('iframe', {
src: "//player.vimeo.com/video/" + a.dataset.uid + "?wmode=opaque"
});
},
title: {
api: function(uid) {
return "https://vimeo.com/api/oembed.json?url=http://vimeo.com/" + uid;
},
text: function(_) {
return _.title;
}
}
}, {
key: 'Vine',
regExp: /^\w+:\/\/(?:www\.)?vine\.co\/v\/(\w+)/,
style: 'border: none; width: 500px; height: 500px;',
el: function(a) {
return $.el('iframe', {
src: "https://vine.co/v/" + a.dataset.uid + "/card"
});
}
}, {
key: 'YouTube',
regExp: /^\w+:\/\/(?:youtu.be\/|[\w\.]*youtube[\w\.]*\/.*(?:v=|\/embed\/|\/v\/|\/videos\/))([\w\-]{11})[^#\&\?]?(.*)/,
el: function(a) {
var el, start;
start = a.dataset.options.match(/\b(?:star)?t\=(\w+)/);
if (start) {
start = start[1];
}
if (start && !/^\d+$/.test(start)) {
start += ' 0h0m0s';
start = 3600 * start.match(/(\d+)h/)[1] + 60 * start.match(/(\d+)m/)[1] + 1 * start.match(/(\d+)s/)[1];
}
el = $.el('iframe', {
src: "//www.youtube.com/embed/" + a.dataset.uid + "?wmode=opaque" + (start ? '&start=' + start : '')
});
el.setAttribute("allowfullscreen", "true");
return el;
},
title: {
batchSize: 50,
api: function(uids) {
var ids, key;
ids = encodeURIComponent(uids.join(','));
key = 'AIzaSyB5_zaen_-46Uhz1xGR-lz1YoUMHqCD6CE';
return "https://www.googleapis.com/youtube/v3/videos?part=snippet&id=" + ids + "&fields=items%28id%2Csnippet%28title%29%29&key=" + key;
},
text: function(data, uid) {
var item, _i, _len, _ref;
_ref = data.items;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
item = _ref[_i];
if (item.id === uid) {
return item.snippet.title;
}
}
return 'Not Found';
}
}
}, {
key: 'Loopvid',
regExp: /^\w+:\/\/(?:www\.)?loopvid.appspot.com\/((?:pf|kd|lv|mc|gd|gh|db|nn)\/[\w\-]+(,[\w\-]+)*|fc\/\w+\/\d+)/,
style: 'max-width: 80vw; max-height: 80vh;',
el: function(a) {
var base, el, host, name, names, type, types, url, _, _i, _j, _len, _len1, _ref, _ref1;
el = $.el('video', {
controls: true,
preload: 'auto',
loop: true
});
_ref = a.dataset.uid.match(/(\w+)\/(.*)/), _ = _ref[0], host = _ref[1], names = _ref[2];
types = host === 'gd' || host === 'fc' ? [''] : ['.webm', '.mp4'];
_ref1 = names.split(',');
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
name = _ref1[_i];
for (_j = 0, _len1 = types.length; _j < _len1; _j++) {
type = types[_j];
base = "" + name + type;
url = (function() {
switch (host) {
case 'pf':
return "http://a.pomf.se/" + base;
case 'kd':
return "http://kastden.org/loopvid/" + base;
case 'lv':
return "http://loopvid.mooo.com/videos/" + base;
case 'mc':
return "https://cdn.mediacru.sh/" + base;
case 'gd':
return "https://docs.google.com/uc?export=download&id=" + base;
case 'gh':
return "https://googledrive.com/host/" + base;
case 'db':
return "https://googledrive.com/host/" + base;
case 'fc':
return "//i.4cdn.org/" + base + ".webm";
case 'nn':
return "http://naenara.eu/loopvids/" + base;
}
})();
$.add(el, $.el('source', {
src: url
}));
}
}
return el;
}
}, {
key: 'Clyp',
regExp: /^\w+:\/\/(?:www\.)?clyp\.it\/(\w+)/,
style: '',
el: function(a) {
return $.el('audio', {
controls: true,
preload: 'auto',
src: "http://clyp.it/" + a.dataset.uid + ".ogg"
});
}
}, {
key: 'Loopvid-dummy',
regExp: /^\w+:\/\/(?:www\.)?loopvid.appspot.com\//,
dummy: true
}, {
key: 'MediaFire-dummy',
regExp: /^\w+:\/\/(?:www\.)?mediafire.com\//,
dummy: true
}, {
key: 'video',
regExp: /\.(?:ogv|webm|mp4)(?:\?|$)/i,
style: 'max-width: 80vw; max-height: 80vh;',
el: function(a) {
return $.el('video', {
controls: true,
preload: 'auto',
src: a.href
});
}
}
]
};
Linkify = {
init: function() {
var _ref;
if (((_ref = g.VIEW) !== 'index' && _ref !== 'thread') || !Conf['Linkify']) {
return;
}
if (Conf['Comment Expansion']) {
ExpandComment.callbacks.push(this.node);
}
Post.callbacks.push({
name: 'Linkify',
cb: this.node
});
CatalogThread.callbacks.push({
name: 'Linkify',
cb: this.catalogNode
});
return Embedding.init();
},
node: function() {
var link, links, _i, _len;
if (this.isClone) {
return Embedding.events(this);
}
if (!Linkify.regString.test(this.info.comment)) {
return;
}
links = Linkify.process(this.nodes.comment);
for (_i = 0, _len = links.length; _i < _len; _i++) {
link = links[_i];
Embedding.process(link, this);
}
},
catalogNode: function() {
if (!Linkify.regString.test(this.thread.OP.info.comment)) {
return;
}
return Linkify.process(this.nodes.comment);
},
process: function(node) {
var data, end, endNode, i, index, length, links, result, saved, snapshot, space, test, word;
test = /[^\s'"]+/g;
space = /[\s'"]/;
snapshot = $.X('.//br|.//text()', node);
i = 0;
links = [];
while (node = snapshot.snapshotItem(i++)) {
data = node.data;
if (!data || node.parentElement.nodeName === "A") {
continue;
}
while (result = test.exec(data)) {
index = result.index;
endNode = node;
word = result[0];
if ((length = index + word.length) === data.length) {
test.lastIndex = 0;
while ((saved = snapshot.snapshotItem(i++))) {
if (saved.nodeName === 'BR') {
break;
}
endNode = saved;
data = saved.data;
if (end = space.exec(data)) {
word += data.slice(0, end.index);
test.lastIndex = length = end.index;
i--;
break;
} else {
length = data.length;
word += data;
}
}
}
if (Linkify.regString.test(word)) {
links.push(Linkify.makeRange(node, endNode, index, length));
}
if (!(test.lastIndex && node === endNode)) {
break;
}
}
}
i = links.length;
while (i--) {
links[i] = Linkify.makeLink(links[i]);
}
return links;
},
regString: /((https?|mailto|git|magnet|ftp|irc):([a-z\d%\/?])|([-a-z\d]+[.])+(aero|asia|biz|cat|com|coop|dance|info|int|jobs|mobi|moe|museum|name|net|org|post|pro|tel|travel|xxx|edu|gov|mil|[a-z]{2})([:\/]|(?![^\s'"]))|[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}|[-\w\d.@]+@[a-z\d.-]+\.[a-z\d])/i,
makeRange: function(startNode, endNode, startOffset, endOffset) {
var range;
range = document.createRange();
range.setStart(startNode, startOffset);
range.setEnd(endNode, endOffset);
return range;
},
makeLink: function(range) {
var a, i, t, text;
text = range.toString();
i = text.search(Linkify.regString);
if (i > 0) {
text = text.slice(i);
while (range.startOffset + i >= range.startContainer.data.length) {
i--;
}
if (i) {
range.setStart(range.startContainer, range.startOffset + i);
}
}
i = 0;
while (/[)\]}>.,]/.test(t = text.charAt(text.length - (1 + i)))) {
if (!(/[.,]/.test(t) || (text.match(/[()\[\]{}<>]/g)).length % 2)) {
break;
}
i++;
}
if (i) {
text = text.slice(0, -i);
while (range.endOffset - i < 0) {
i--;
}
if (i) {
range.setEnd(range.endContainer, range.endOffset - i);
}
}
if (!/((mailto|magnet):|.+:\/\/)/.test(text)) {
text = (/@/.test(text) ? 'mailto:' : 'http://') + text;
}
a = $.el('a', {
className: 'linkify',
rel: 'nofollow noreferrer',
target: '_blank',
href: text
});
$.add(a, range.extractContents());
range.insertNode(a);
range.detach();
return a;
}
};
ArchiveLink = {
init: function() {
var div, entry, type, _i, _len, _ref, _ref1;
if (!(((_ref = g.VIEW) === 'index' || _ref === 'thread') && Conf['Menu'] && Conf['Archive Link'])) {
return;
}
div = $.el('div', {
textContent: 'Archive'
});
entry = {
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: []
};
_ref1 = [['Post', 'post'], ['Name', 'name'], ['Tripcode', 'tripcode'], ['Unique ID', 'uniqueID'], ['Subject', 'subject'], ['Filename', 'filename'], ['Image MD5', 'MD5']];
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
type = _ref1[_i];
entry.subEntries.push(this.createSubEntry(type[0], type[1]));
}
return Menu.menu.addEntry(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, _ref;
if (!(((_ref = g.VIEW) === 'index' || _ref === 'thread') && 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 Menu.menu.addEntry({
el: div,
order: 40,
open: function(post) {
var node;
if (post.isDead) {
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"]);
fileOnly = $.hasClass(this, 'delete-file');
this.textContent = "Deleting " + (fileOnly ? 'file' : 'post') + "...";
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 + "/"), {
responseType: 'document',
withCredentials: true,
onload: function() {
return DeleteLink.load(link, post, fileOnly, this.response);
},
onerror: function() {
return DeleteLink.error(link);
}
}, {
form: $.formData(form)
});
},
load: function(link, post, fileOnly, resDoc) {
var msg, s;
if (resDoc.title === '4chan - Banned') {
s = 'Banned!';
} else if (msg = resDoc.getElementById('errmsg')) {
s = msg.textContent;
$.on(link, 'click', DeleteLink["delete"]);
} else {
if (resDoc.title === 'Updating index...') {
QR.cooldown["delete"](post);
(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 = 60;
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, _ref;
if (!(((_ref = g.VIEW) === 'index' || _ref === 'thread') && Conf['Menu'] && Conf['Download Link'])) {
return;
}
a = $.el('a', {
className: 'download-link',
textContent: 'Download file'
});
$.on(a, 'click', ImageCommon.download);
return Menu.menu.addEntry({
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() {
var _ref;
if (!(((_ref = g.VIEW) === 'index' || _ref === 'thread') && Conf['Menu'])) {
return;
}
this.button = $.el('a', {
className: 'menu-button',
href: 'javascript:;'
});
$.extend(this.button, {
innerHTML: "<i class=\"fa fa-angle-down\"></i>"
});
this.menu = new UI.Menu('post');
Post.callbacks.push({
name: 'Menu',
cb: this.node
});
return CatalogThread.callbacks.push({
name: 'Menu',
cb: this.catalogNode
});
},
node: function() {
if (this.isClone) {
Menu.makeButton(this, $('.menu-button', this.nodes.info));
return;
}
return $.add(this.nodes.info, Menu.makeButton(this));
},
catalogNode: function() {
return $.after(this.nodes.icons, Menu.makeButton(this.thread.OP));
},
makeButton: function(post, button) {
button || (button = Menu.button.cloneNode(true));
$.on(button, 'click', function(e) {
return Menu.menu.toggle(e, this, post);
});
return button;
}
};
ReportLink = {
init: function() {
var a, _ref;
if (!(((_ref = g.VIEW) === 'index' || _ref === 'thread') && Conf['Menu'] && Conf['Report Link'])) {
return;
}
a = $.el('a', {
className: 'report-link',
href: 'javascript:;',
textContent: 'Report this post'
});
$.on(a, 'click', ReportLink.report);
return Menu.menu.addEntry({
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=285";
return window.open(url, id, set);
}
};
Favicon = {
init: function() {
return $.asap((function() {
return d.head && (Favicon.el = $('link[rel="shortcut icon"]', d.head));
}), Favicon.initAsap);
},
initAsap: function() {
var href;
Favicon.el.type = 'image/x-icon';
href = Favicon.el.href;
Favicon.SFW = /ws\.ico$/.test(href);
Favicon["default"] = href;
return Favicon["switch"]();
},
"switch": function() {
var f, i, items, t;
items = {
ferongr: ['iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAFVBMVEX///9zBQC/AADpDAP/gID/q6voCwJJTwpOAAAAAXRSTlMAQObYZgAAAGJJREFUeF5Fi7ENg0AQBCfa/AFdDh2gdwPIogMK2E2+/xLslwOvdqRJhv+GQQPUCtJM7svankLrq/I+TY5e6Ueh1jyBMX7AFJi9vwfyVO4CbbO6jNYpp9GyVPbdkFhVgAQ2H0NOE5jk9DT8AAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAxUlEQVR42q1TOwrCQBB9s0FRtJI0WoqFtSLYegoP4gVSeJsUHsHSI3iFeIqRXXgwrhlXwYHHhLwPTB7B36abBCV+0pA4DUBQUNZYQptGtW3jtoKyxgoe0yrBCoyZfL/5ioQ3URZOXW9I341l3oo+NXEZiW4CEuIzvPECopED4OaZ3RNmeAm4u+a8Jr5f17VyVoL8fr8qcltzwlyyj2iqcgPOQ9ExkHAITgD75bYBe0A5S4H/P9htuWMF3QXoQpwaKeT+lnsC6JE5I6aq6fEAAAAASUVORK5CYII=', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAFVBMVEX///8AcH4AtswA2PJ55fKi6fIA1/FtpPADAAAAAXRSTlMAQObYZgAAAGJJREFUeF5Fi7ENg0AQBCfa/AFdDh2gdwPIogMK2E2+/xLslwOvdqRJhv+GQQPUCtJM7svankLrq/I+TY5e6Ueh1jyBMX7AFJi9vwfyVO4CbbO6jNYpp9GyVPbdkFhVgAQ2H0NOE5jk9DT8AAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAxElEQVQ4y2NgoBq4/vE/HJOsBiRQUIfA2AzBqQYqUfn00/9FLz+BaQxDCKqBmX7jExijKEDSDJPHrnnbGQhGV4RmOFwdVkNwhQMheYwQxhaIi7b9Z9A3gWAQm2BUoQOgRhgA8o7j1ozLC4LCyAZcx6kZI5qg4kLKqggDFFWxJySsUQVzlb4pwgAJaTRvokcVNgOqOv8zcHBCsL07DgNg8YsczzA5MxtUL+DMD8g0slxI/H8GQ/P/DJKyeKIRpglXZsIiBwBhP5O+VbI/JgAAAABJRU5ErkJggg==', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAFVBMVEX///8oeQBJ3ABV/wHM/7Lu/+ZU/gAqUP3dAAAAAXRSTlMAQObYZgAAAGJJREFUeF5Fi7ENg0AQBCfa/AFdDh2gdwPIogMK2E2+/xLslwOvdqRJhv+GQQPUCtJM7svankLrq/I+TY5e6Ueh1jyBMX7AFJi9vwfyVO4CbbO6jNYpp9GyVPbdkFhVgAQ2H0NOE5jk9DT8AAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAx0lEQVQ4y2NgoBYI+cfwH4ZJVgMS0KhEYGyG4FQDkzjzf9P/d/+fgWl0QwiqgSkI/c8IxsgKkDXD5LFq9rwDweiK0A2HqcNqCK5wICSPEcLYAtH+AMN/IXMIBrEJRie6OEgjDAC5x3FqxuUFNiEUA67j1IweTTBxBQ1puAG86jgSEraogskJWSBcwCGF5k30qMJmgMFEhv/MXBAs5oLDAFj8IsczTE7UEeECbhU8+QGZRpaTi2b4L2zF8J9TGk80wjThykzY5AAW/2O1C2mIbgAAAABJRU5ErkJggg=='],
'xat-': ['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'],
Mayhem: ['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'],
'4chanJS': ['iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAD1BMVEUBAAAAAAD/AABnZ2f///8nFk05AAAAAXRSTlMAQObYZgAAAEFJREFUeNqNjgEKACAMAjvX/98cAkkxgmSgO8Bt/Ai4ApJ6KKhzF3OiEMDASrGB/QWgPEHsUpN+Ng9xAETMYhDrWmeHAMcmvycWAAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAD1BMVEUBAAAAAAD/AAD///9nZ2f77Y6hAAAAAXRSTlMAQObYZgAAAEBJREFUeF6NjQEKACAMAnfW/98cAxFiBIngOsTqR8B1IGkeG9p5i7XabgAGZNigXgA8aoCUxvzWAIcBItGiSEwdccYA3BuRAWkAAAAASUVORK5CYII=', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAD1BMVEUBAAAAAAAul8NnZ2f////82iC9AAAAAXRSTlMAQObYZgAAAEFJREFUeNqNjgEKACAMAjvX/98cAkkxgmSgO8Bt/Ai4ApJ6KKhzF3OiEMDASrGB/QWgPEHsUpN+Ng9xAETMYhDrWmeHAMcmvycWAAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAD1BMVEUBAAAAAAAul8P///9nZ2cgIeMlAAAAAXRSTlMAQObYZgAAAEBJREFUeF6NjQEKACAMAnfW/98cAxFiBIngOsTqR8B1IGkeG9p5i7XabgAGZNigXgA8aoCUxvzWAIcBItGiSEwdccYA3BuRAWkAAAAASUVORK5CYII=', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAElBMVEUBAAAAAABmzDNlyjJnZ2f///+6o7dfAAAAAXRSTlMAQObYZgAAAERJREFUeF6NjkEKADEIA51o///lJZfQxUsHITogWi8AvwZJuxmYa25xDooBLEwOWFTYAsYVhdorLZt9Ng9xCUTCUCQ2H3F4ANrZ2WNiAAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAElBMVEUBAAAAAABmzDP///9lyjJnZ2cIHys9AAAAAXRSTlMAQObYZgAAAENJREFUeF6NjUEKwEAMAjNm9/9fLkEslFwqgjoEUn8EfAqSdrkwzj6ieyyTkQEVGWRvANfO1iEX620AjgBEwqR4Y+sBeGAA6d+vQ4IAAAAASUVORK5CYII='],
Original: ['iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAADFBMVEX/////AAD///8AAABBZmS3AAAAAXRSTlMAQObYZgAAAExJREFUeF4tyrENgDAMAMFXKuQswQLBG3mOlBnFS1gwDfIYLpEivvjq2MlqjmYvYg5jWEzCwtDSQlwcXKCVLrpFbvLvvSf9uZJ2HusDtJAY7Tkn1oYAAAAASUVORK5CYII=', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAhElEQVR42q1RwQnAMAjMu5M4guAKXa4j5dUROo5tipSDcrFChUONd0di2m/hEGVOHDyIPufgwAFASDkpoSzmBrkJ2UMyR9LsJ3rvrqo3Rt1YMIMhhNnOxLMnoMFBxHyJAr2IOBFzA8U+6pLBdmEJTA0aMVjpDd6Loks0s5HZNwYx8tfZCZ0kll7ORffZAAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAADFBMVEX///8ul8P///8AAACaqgkzAAAAAXRSTlMAQObYZgAAAExJREFUeF4tyrENgDAMAMFXKuQswQLBG3mOlBnFS1gwDfIYLpEivvjq2MlqjmYvYg5jWEzCwtDSQlwcXKCVLrpFbvLvvSf9uZJ2HusDtJAY7Tkn1oYAAAAASUVORK5CYII=', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAALVBMVEUAAAAAAAAAAAAAAAABBQcHFx4KISoNLToaVW4oKCgul8M4ODg7OzvBwcH///8uS/CdAAAAA3RSTlMAx9dmesIgAAAAV0lEQVR42m2NWw6AIBAD1eILZO5/XI0UAgm7H9tOsu0yGWAQSOoFijHOxOANGqm/LczpOaXs4gISrPZ+gc2+hO5w2xdwgOjBFUIF+sEJrhUl9JFr+badFwR+BfqlmGUJAAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAADFBMVEX///9mzDP///8AAACT0n1lAAAAAXRSTlMAQObYZgAAAExJREFUeF4tyrENgDAMAMFXKuQswQLBG3mOlBnFS1gwDfIYLpEivvjq2MlqjmYvYg5jWEzCwtDSQlwcXKCVLrpFbvLvvSf9uZJ2HusDtJAY7Tkn1oYAAAAASUVORK5CYII=', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAALVBMVEUAAAAAAAAAAAAAAAAECAIQIAgWLAsePA8oKCg4ODg6dB07OztmzDPBwcH///+rsf3XAAAAA3RSTlMAx9dmesIgAAAAV0lEQVR42m2NWw6AIBAD1eIDhbn/cTVSCCTsfmw7ybbLZIBBIKkXKKU0E4M3aKT+tjCn5xiziwuIsNr7BTb7ErrDZV/AAaIHdwgV6AcnuFaU0Eeu5dt2XiUyBjCQ2bIrAAAAAElFTkSuQmCC'],
'Metro': ['iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAC/AABrZQDiAAAAAXRSTlMAQObYZgAAABJJREFUCB1jZGBgrMNAQEEc4gCSfAX5bRw/NQAAAABJRU5ErkJggg==', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAAAAAAAAAAHAAAdAAApAAAsAAA4AABsAACQAAC/AAD///9SVhtjAAAAA3RSTlMAPse+s4iwAAAAM0lEQVQIW2NggAGuVasWgDBpDDAQUoSaob0Jao73lgVojOitUEazBZRRvR3KmJa5AO4KAGBtLuMAuhIIAAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAAA1/GhpCidAAAAAXRSTlMAQObYZgAAABJJREFUCB1jZGBgrMNAQEEc4gCSfAX5bRw/NQAAAABJRU5ErkJggg==', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAAAAAAAAAAACAkAISUALzQAMTcAQEcAeokAorYA1/H///8BrzTFAAAAA3RSTlMAPse+s4iwAAAAM0lEQVQIW2NggAGuVasWgDBpDDAQUoSaob0Jao73lgVojOitUEazBZRRvR3KmJa5AO4KAGBtLuMAuhIIAAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAABV/wErM5hwAAAAAXRSTlMAQObYZgAAABJJREFUCB1jZGBgrMNAQEEc4gCSfAX5bRw/NQAAAABJRU5ErkJggg==', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAAAAAAAAAADCgANKAASOAATOwAZTAAwkQBAwQBV/wH////+Fmy4AAAAA3RSTlMAPse+s4iwAAAAM0lEQVQIW2NggAGuVasWgDBpDDAQUoSaob0Jao73lgVojOitUEazBZRRvR3KmJa5AO4KAGBtLuMAuhIIAAAAAElFTkSuQmCC']
}[Conf['favicon']];
f = Favicon;
t = 'data:image/png;base64,';
i = 0;
while (items[i]) {
items[i] = t + items[i++];
}
f.unreadDead = items[0], f.unreadDeadY = items[1], f.unreadSFW = items[2], f.unreadSFWY = items[3], f.unreadNSFW = items[4], f.unreadNSFWY = items[5];
return f.update();
},
update: function() {
if (this.SFW) {
this.unread = this.unreadSFW;
return this.unreadY = this.unreadSFWY;
} else {
this.unread = this.unreadNSFW;
return this.unreadY = this.unreadNSFWY;
}
},
dead: 'data:image/gif;base64,R0lGODlhEAAQAKECAAAAAP8AAP///////yH5BAEKAAIALAAAAAAQABAAAAIvlI+pq+D9DAgUoFkPDlbs7lFZKIJOJJ3MyraoB14jFpOcVMpzrnF3OKlZYsMWowAAOw==',
logo: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACAAgMAAAC+UIlYAAAACVBMVEUAAGcAAABmzDNZt9VtAAAAAXRSTlMAQObYZgAAAGlJREFUWMPtlkEKADEIA/tJP9lXLttQto2yHxgDHozTi0ToGK2WKZZ+HAQQMZc+xBwI4EZ+wAC2IfPuSIDOZJrSZQEAX9eVJhhwIuUYAnQe8rhAEMAZlTI2MID9f5Clyh0JeE1V1ZEAvB4qDfwuJTSGRAAAAABJRU5ErkJggg=='
};
MarkNewIPs = {
init: function() {
if (g.VIEW !== 'thread' || !Conf['Mark New IPs']) {
return;
}
return Thread.callbacks.push({
name: 'Mark New IPs',
cb: this.node
});
},
node: function() {
var x;
MarkNewIPs.ipCount = this.ipCount;
MarkNewIPs.postIDs = (function() {
var _i, _len, _ref, _results;
_ref = this.posts.keys;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
x = _ref[_i];
_results.push(+x);
}
return _results;
}).call(this);
return $.on(d, 'ThreadUpdate', MarkNewIPs.onUpdate);
},
onUpdate: function(e) {
var added, fullID, i, ipCount, newPosts, obj, postIDs, removed, x, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1;
_ref = e.detail, ipCount = _ref.ipCount, newPosts = _ref.newPosts;
postIDs = ThreadUpdater.postIDs;
if (ipCount == null) {
return;
}
if (newPosts.length) {
obj = {};
_ref1 = MarkNewIPs.postIDs;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
x = _ref1[_i];
obj[x] = true;
}
added = 0;
for (_j = 0, _len1 = postIDs.length; _j < _len1; _j++) {
x = postIDs[_j];
if (!(x in obj)) {
added++;
}
}
removed = MarkNewIPs.postIDs.length + added - postIDs.length;
switch (ipCount - MarkNewIPs.ipCount) {
case added:
i = MarkNewIPs.ipCount;
for (_k = 0, _len2 = newPosts.length; _k < _len2; _k++) {
fullID = newPosts[_k];
MarkNewIPs.markNew(g.posts[fullID], ++i);
}
break;
case -removed:
for (_l = 0, _len3 = newPosts.length; _l < _len3; _l++) {
fullID = newPosts[_l];
MarkNewIPs.markOld(g.posts[fullID]);
}
}
}
MarkNewIPs.ipCount = ipCount;
return MarkNewIPs.postIDs = postIDs;
},
markNew: function(post, ipCount) {
var counter, suffix;
suffix = (Math.floor(ipCount / 10)) % 10 === 1 ? 'th' : ['st', 'nd', 'rd'][ipCount % 10 - 1] || 'th';
counter = $.el('span', {
className: 'ip-counter',
textContent: "(" + ipCount + ")"
});
post.nodes.nameBlock.title = "This is the " + ipCount + suffix + " IP in the thread.";
$.add(post.nodes.nameBlock, [$.tn(' '), counter]);
return $.addClass(post.nodes.root, 'new-ip');
},
markOld: function(post) {
post.nodes.nameBlock.title = 'Not the first post from this IP.';
return $.addClass(post.nodes.root, 'old-ip');
}
};
ThreadExcerpt = {
init: function() {
if (g.BOARD.ID !== 'f' || g.VIEW !== 'thread' || !Conf['Thread Excerpt']) {
return;
}
return Thread.callbacks.push({
name: 'Thread Excerpt',
cb: this.node
});
},
node: function() {
return d.title = Get.threadExcerpt(this);
}
};
ThreadStats = {
init: function() {
var sc, statsHTML, statsTitle;
if (g.VIEW !== 'thread' || !Conf['Thread Stats']) {
return;
}
statsHTML = {
innerHTML: "<span id=\"post-count\">?</span> / <span id=\"file-count\">?</span>"
};
statsTitle = 'Posts / Files';
if (Conf['IP Count in Stats']) {
statsHTML = {
innerHTML: statsHTML.innerHTML + " / <span id=\"ip-count\">?</span>"
};
statsTitle += ' / IPs';
}
if (Conf['Page Count in Stats']) {
statsHTML = {
innerHTML: statsHTML.innerHTML + " / <span id=\"page-count\">?</span>"
};
statsTitle += ' / Page';
}
if (Conf['Updater and Stats in Header']) {
this.dialog = sc = $.el('span', {
id: 'thread-stats',
title: statsTitle
});
$.extend(sc, statsHTML);
$.ready(function() {
return Header.addShortcut(sc);
});
} else {
this.dialog = sc = UI.dialog('thread-stats', 'bottom: 0px; right: 0px;', {
innerHTML: "<div class=\"move\" title=\"" + E(statsTitle) + "\">" + statsHTML.innerHTML + "</div>"
});
$.addClass(doc, 'float');
$.ready((function(_this) {
return function() {
return $.add(d.body, sc);
};
})(this));
}
this.postCountEl = $('#post-count', sc);
this.fileCountEl = $('#file-count', sc);
this.ipCountEl = $('#ip-count', sc);
this.pageCountEl = $('#page-count', sc);
return Thread.callbacks.push({
name: 'Thread Stats',
cb: this.node
});
},
node: function() {
var fileCount, postCount;
postCount = 0;
fileCount = 0;
this.posts.forEach(function(post) {
postCount++;
if (post.file) {
fileCount++;
}
if (Conf["Page Count in Stats"]) {
return ThreadStats.lastPost = post.info.date;
}
});
ThreadStats.thread = this;
ThreadStats.fetchPage();
ThreadStats.update(postCount, fileCount, this.ipCount);
return $.on(d, 'ThreadUpdate', ThreadStats.onUpdate);
},
onUpdate: function(e) {
var fileCount, ipCount, newPosts, postCount, _ref, _ref1;
if (e.detail[404]) {
return;
}
_ref = e.detail, postCount = _ref.postCount, fileCount = _ref.fileCount, ipCount = _ref.ipCount, newPosts = _ref.newPosts;
ThreadStats.update(postCount, fileCount, ipCount);
if (!Conf["Page Count in Stats"]) {
return;
}
if (newPosts.length) {
ThreadStats.lastPost = g.posts[newPosts[newPosts.length - 1]].info.date;
}
if (ThreadStats.lastPost > ThreadStats.lastPageUpdate && ((_ref1 = ThreadStats.pageCountEl) != null ? _ref1.textContent : void 0) !== '1') {
return ThreadStats.fetchPage();
}
},
update: function(postCount, fileCount, ipCount) {
var fileCountEl, ipCountEl, postCountEl, thread;
thread = ThreadStats.thread, postCountEl = ThreadStats.postCountEl, fileCountEl = ThreadStats.fileCountEl, ipCountEl = ThreadStats.ipCountEl;
postCountEl.textContent = postCount;
fileCountEl.textContent = fileCount;
if ((ipCount != null) && Conf["IP Count in Stats"]) {
ipCountEl.textContent = ipCount;
}
(thread.postLimit && !thread.isSticky ? $.addClass : $.rmClass)(postCountEl, 'warning');
return (thread.fileLimit && !thread.isSticky ? $.addClass : $.rmClass)(fileCountEl, 'warning');
},
fetchPage: function() {
if (!Conf["Page Count in Stats"]) {
return;
}
clearTimeout(ThreadStats.timeout);
if (ThreadStats.thread.isDead) {
ThreadStats.pageCountEl.textContent = 'Dead';
$.addClass(ThreadStats.pageCountEl, 'warning');
return;
}
ThreadStats.timeout = setTimeout(ThreadStats.fetchPage, 2 * $.MINUTE);
return $.ajax("//a.4cdn.org/" + ThreadStats.thread.board + "/threads.json", {
onload: ThreadStats.onThreadsLoad
}, {
whenModified: true
});
},
onThreadsLoad: function() {
var page, thread, _i, _j, _len, _len1, _ref, _ref1;
if (!(Conf["Page Count in Stats"] && this.status === 200)) {
return;
}
_ref = 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 === ThreadStats.thread.ID)) {
continue;
}
ThreadStats.pageCountEl.textContent = page.page;
(page.page === this.response.length ? $.addClass : $.rmClass)(ThreadStats.pageCountEl, 'warning');
ThreadStats.lastPageUpdate = new Date(thread.last_modified * $.SECOND);
return;
}
}
}
};
ThreadUpdater = {
init: function() {
var conf, el, input, name, sc, subEntries, updateLink, _ref;
if (g.VIEW !== 'thread' || !Conf['Thread Updater']) {
return;
}
if (Conf['Updater and Stats in Header']) {
this.dialog = sc = $.el('span', {
id: 'updater'
});
$.extend(sc, {
innerHTML: "<span id=\"update-status\"></span><span id=\"update-timer\" title=\"Update now\"></span>"
});
$.ready(function() {
return Header.addShortcut(sc);
});
} else {
this.dialog = sc = UI.dialog('updater', 'bottom: 0px; left: 0px;', {
innerHTML: "<div class=\"move\"></div><span id=\"update-status\"></span><span id=\"update-timer\" title=\"Update now\"></span>"
});
$.addClass(doc, 'float');
$.ready(function() {
return $.add(d.body, sc);
});
}
this.checkPostCount = 0;
this.timer = $('#update-timer', sc);
this.status = $('#update-status', sc);
this.isUpdating = Conf['Auto Update'];
$.on(this.timer, 'click', this.update);
$.on(this.status, 'click', this.update);
updateLink = $.el('span', {
className: 'brackets-wrap updatelink'
});
$.extend(updateLink, {
innerHTML: "<a href=\"javascript:;\">Update</a>"
});
Main.ready(function() {
return $.add($('.navLinksBot'), [$.tn(' '), updateLink]);
});
$.on(updateLink.firstElementChild, 'click', this.update);
subEntries = [];
_ref = Config.updater.checkbox;
for (name in _ref) {
conf = _ref[name];
el = UI.checkbox(name, name);
el.title = conf[1];
input = el.firstElementChild;
$.on(input, 'change', $.cb.checked);
if (input.name === 'Scroll BG') {
$.on(input, 'change', this.cb.scrollBG);
this.cb.scrollBG();
} else if (input.name === 'Auto Update') {
$.on(input, 'change', this.cb.autoUpdate);
}
subEntries.push({
el: el
});
}
this.settings = $.el('span', {
innerHTML: "<a href=\"javascript:;\">Interval</a>"
});
$.on(this.settings, 'click', this.intervalShortcut);
subEntries.push({
el: this.settings
});
Header.menu.addEntry(this.entry = {
el: $.el('span', {
textContent: 'Updater'
}),
order: 110,
subEntries: subEntries
});
return Thread.callbacks.push({
name: 'Thread Updater',
cb: this.node
});
},
node: function() {
ThreadUpdater.thread = this;
ThreadUpdater.root = this.OP.nodes.root.parentNode;
ThreadUpdater.lastPost = +this.posts.keys[this.posts.keys.length - 1];
ThreadUpdater.outdateCount = 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);
if (ThreadUpdater.thread.isArchived) {
return ThreadUpdater.set('status', 'Archived', 'warning');
} else {
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.thread.isDead) {
return;
}
if (ThreadUpdater.online = navigator.onLine) {
ThreadUpdater.outdateCount = 0;
ThreadUpdater.setInterval();
return ThreadUpdater.set('status', '', '');
} else {
ThreadUpdater.set('timer', '');
ThreadUpdater.set('status', 'Offline', 'warning');
return clearTimeout(ThreadUpdater.timeoutID);
}
},
checkpost: function(e) {
if (!ThreadUpdater.checkPostCount) {
if (e && e.detail.threadID !== ThreadUpdater.thread.ID) {
return;
}
ThreadUpdater.seconds = 0;
ThreadUpdater.outdateCount = 0;
ThreadUpdater.set('timer', '...');
}
if (!(ThreadUpdater.thread.isDead || ThreadUpdater.foundPost || ThreadUpdater.checkPostCount >= 5)) {
return setTimeout(ThreadUpdater.update, ++ThreadUpdater.checkPostCount * $.SECOND);
}
ThreadUpdater.setInterval();
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.setInterval();
}
},
scrollBG: function() {
return ThreadUpdater.scrollBG = Conf['Scroll BG'] ? function() {
return true;
} : function() {
return !d.hidden;
};
},
autoUpdate: function(e) {
return ThreadUpdater.count(ThreadUpdater.isUpdating = this.checked);
},
interval: function(e) {
var val;
val = parseInt(this.value, 10);
if (val < 1) {
val = 1;
}
ThreadUpdater.interval = this.value = val;
if (e) {
return $.cb.value.call(this);
}
},
load: function(e) {
var req;
req = ThreadUpdater.req;
switch (req.status) {
case 200:
ThreadUpdater.parse(req.response.posts);
if (ThreadUpdater.thread.isArchived) {
ThreadUpdater.set('status', 'Archived', 'warning');
ThreadUpdater.kill();
} else {
ThreadUpdater.setInterval();
}
break;
case 404:
$.ajax("//a.4cdn.org/" + ThreadUpdater.thread.board + "/catalog.json", {
onloadend: function() {
var confirmed, page, thread, _i, _j, _len, _len1, _ref, _ref1;
if (this.status === 200) {
confirmed = true;
_ref = 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 === ThreadUpdater.thread.ID) {
confirmed = false;
break;
}
}
}
} else {
confirmed = false;
}
if (confirmed) {
ThreadUpdater.set('status', '404', 'warning');
return ThreadUpdater.kill();
} else {
return ThreadUpdater.error(req);
}
}
});
break;
default:
ThreadUpdater.error(req);
}
if (ThreadUpdater.postID) {
return ThreadUpdater.cb.checkpost();
}
}
},
kill: function() {
ThreadUpdater.set('timer', '');
clearTimeout(ThreadUpdater.timeoutID);
ThreadUpdater.thread.kill();
return $.event('ThreadUpdate', {
404: true,
threadID: ThreadUpdater.thread.fullID
});
},
error: function(req) {
var klass, text, _ref;
ThreadUpdater.setInterval();
_ref = req.status === 304 ? ['', ''] : ["" + req.statusText + " (" + req.status + ")", 'warning'], text = _ref[0], klass = _ref[1];
return ThreadUpdater.set('status', text, klass);
},
setInterval: function() {
var cur, i, j, limit;
i = ThreadUpdater.interval + 1;
if (Conf['Optional Increase']) {
cur = ThreadUpdater.outdateCount || 1;
limit = d.hidden ? 7 : 10;
j = cur <= limit ? cur : limit;
cur = (Math.floor(i * 0.1) || 1) * j * j;
ThreadUpdater.seconds = cur > i ? cur <= 300 ? cur : 300 : i;
} else {
ThreadUpdater.seconds = i;
}
ThreadUpdater.set('timer', ThreadUpdater.seconds);
return ThreadUpdater.count(true);
},
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;
}
},
count: function(start) {
clearTimeout(ThreadUpdater.timeoutID);
if (start && ThreadUpdater.isUpdating && navigator.onLine) {
return ThreadUpdater.timeout();
}
},
timeout: function() {
var n;
ThreadUpdater.timeoutID = setTimeout(ThreadUpdater.timeout, 1000);
if (!(n = --ThreadUpdater.seconds)) {
ThreadUpdater.outdateCount++;
return ThreadUpdater.update();
} else if (n <= -60) {
ThreadUpdater.set('status', 'Retrying', '');
return ThreadUpdater.update();
} else if (n > 0) {
return ThreadUpdater.set('timer', n);
}
},
update: function() {
var _ref;
if (!navigator.onLine) {
return;
}
ThreadUpdater.count();
if (Conf['Auto Update']) {
ThreadUpdater.set('timer', '...');
} else {
ThreadUpdater.set('timer', 'Update');
}
if ((_ref = ThreadUpdater.req) != null) {
_ref.abort();
}
return ThreadUpdater.req = $.ajax("//a.4cdn.org/" + ThreadUpdater.thread.board + "/thread/" + ThreadUpdater.thread + ".json", {
onloadend: ThreadUpdater.cb.load,
timeout: $.MINUTE
}, {
whenModified: true
});
},
updateThreadStatus: function(type, status) {
var change, hasChanged;
if (!(hasChanged = ThreadUpdater.thread["is" + type] !== status)) {
return;
}
ThreadUpdater.thread.setStatus(type, status);
if (type === 'Closed' && ThreadUpdater.thread.isArchived) {
return;
}
change = type === 'Sticky' ? status ? 'now a sticky' : 'not a sticky anymore' : status ? 'now closed' : 'not closed anymore';
return new Notice('info', "The thread is " + change + ".", 30);
},
parse: function(postObjects) {
var OP, count, files, index, ipCountEl, node, num, post, postObject, posts, root, scroll, _i, _j, _len, _len1;
OP = postObjects[0];
Build.spoilerRange[ThreadUpdater.thread.board] = OP.custom_spoiler;
ThreadUpdater.thread.setStatus('Archived', !!+OP.archived);
ThreadUpdater.updateThreadStatus('Sticky', !!OP.sticky);
ThreadUpdater.updateThreadStatus('Closed', !!OP.closed);
ThreadUpdater.thread.postLimit = !!OP.bumplimit;
ThreadUpdater.thread.fileLimit = !!OP.imagelimit;
if (OP.unique_ips != null) {
ThreadUpdater.thread.ipCount = OP.unique_ips;
}
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));
}
ThreadUpdater.thread.posts.forEach(function(post) {
var ID;
ID = +post.ID;
if (!(post.info.date > Date.now() - 60 * $.SECOND)) {
if (__indexOf.call(index, ID) < 0) {
post.kill();
} else if (post.isDead) {
post.resurrect();
} else if (post.file && !(post.file.isDead || __indexOf.call(files, ID) >= 0)) {
post.kill(true);
}
}
if (ThreadUpdater.postID && ThreadUpdater.postID === ID) {
return ThreadUpdater.foundPost = true;
}
});
if (!count) {
ThreadUpdater.set('status', '', '');
} 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 (_j = 0, _len1 = posts.length; _j < _len1; _j++) {
post = posts[_j];
root = post.nodes.root;
if (!QuoteThreading.insert(post)) {
$.add(ThreadUpdater.root, post.nodes.root);
}
}
$.event('PostsInserted');
if (scroll) {
if (Conf['Bottom Scroll']) {
window.scrollTo(0, d.body.clientHeight);
} else {
if (root) {
Header.scrollTo(root);
}
}
}
}
if ((OP.unique_ips != null) && (ipCountEl = $.id('unique-ips'))) {
ipCountEl.textContent = OP.unique_ips;
ipCountEl.previousSibling.textContent = ipCountEl.previousSibling.textContent.replace(/\b(?:is|are)\b/, OP.unique_ips === 1 ? 'is' : 'are');
ipCountEl.nextSibling.textContent = ipCountEl.nextSibling.textContent.replace(/\bposters?\b/, OP.unique_ips === 1 ? 'poster' : 'posters');
}
ThreadUpdater.postIDs = index;
return $.event('ThreadUpdate', {
404: false,
threadID: ThreadUpdater.thread.fullID,
newPosts: (function() {
var _k, _len2, _results;
_results = [];
for (_k = 0, _len2 = posts.length; _k < _len2; _k++) {
post = posts[_k];
_results.push(post.fullID);
}
return _results;
})(),
postCount: OP.replies + 1,
fileCount: OP.images + (!!ThreadUpdater.thread.OP.file && !ThreadUpdater.thread.OP.file.isDead),
ipCount: OP.unique_ips
});
}
};
ThreadWatcher = {
init: function() {
var sc;
if (!Conf['Thread Watcher']) {
return;
}
this.shortcut = sc = $.el('a', {
id: 'watcher-link',
textContent: 'Watcher',
title: 'Thread Watcher',
href: 'javascript:;',
className: 'disabled fa fa-eye'
});
this.db = new DataBoard('watchedThreads', this.refresh, true);
this.dialog = UI.dialog('thread-watcher', 'top: 50px; left: 0px;', {
innerHTML: "<div class=\"move\">Thread Watcher <a class=\"refresh fa fa-refresh\" title=\"Check threads\" href=\"javascript:;\"></a><span id=\"watcher-status\"></span><a class=\"menu-button\" href=\"javascript:;\"><i class=\"fa fa-angle-down\"></i></a><a class=\"close\" href=\"javascript:;\">×</a></div><div id=\"watched-threads\"></div>"
});
this.status = $('#watcher-status', this.dialog);
this.list = this.dialog.lastElementChild;
this.refreshButton = $('.refresh', this.dialog);
this.unreaddb = Unread.db || new DataBoard('lastReadPosts');
$.on(d, 'QRPostSuccessful', this.cb.post);
$.on(sc, 'click', this.toggleWatcher);
$.on(this.refreshButton, 'click', this.fetchAllStatus);
$.on($('.move > .close', this.dialog), 'click', this.toggleWatcher);
$.on(d, '4chanXInitFinished', this.ready);
switch (g.VIEW) {
case 'index':
$.on(d, 'IndexRefresh', this.cb.onIndexRefresh);
break;
case 'thread':
$.on(d, 'ThreadUpdate', this.cb.onThreadRefresh);
}
if (Conf['Toggleable Thread Watcher']) {
Header.addShortcut(sc);
$.addClass(doc, 'fixed-watcher');
}
ThreadWatcher.fetchAuto();
if (g.VIEW === 'index' && Conf['JSON Navigation'] && Conf['Menu'] && g.BOARD.ID !== 'f') {
Menu.menu.addEntry({
el: $.el('a', {
href: 'javascript:;'
}),
order: 6,
open: function(_arg) {
var thread;
thread = _arg.thread;
if (Conf['Index Mode'] !== 'catalog') {
return false;
}
this.el.textContent = ThreadWatcher.isWatched(thread) ? 'Unwatch thread' : 'Watch thread';
if (this.cb) {
$.off(this.el, 'click', this.cb);
}
this.cb = function() {
$.event('CloseMenu');
return ThreadWatcher.toggle(thread);
};
$.on(this.el, 'click', this.cb);
return true;
}
});
}
Post.callbacks.push({
name: 'Thread Watcher',
cb: this.node
});
return CatalogThread.callbacks.push({
name: 'Thread Watcher',
cb: this.catalogNode
});
},
isWatched: function(thread) {
var _ref;
return (_ref = ThreadWatcher.db) != null ? _ref.get({
boardID: thread.board.ID,
threadID: thread.ID
}) : void 0;
},
node: function() {
var toggler;
if (this.isReply) {
return;
}
if (this.isClone) {
toggler = $('.watch-thread-link', this.nodes.post);
} else {
toggler = $.el('img', {
className: 'watch-thread-link'
});
$.before($('input', this.nodes.post), toggler);
}
return $.on(toggler, 'click', ThreadWatcher.cb.toggle);
},
catalogNode: function() {
if (ThreadWatcher.isWatched(this.thread)) {
$.addClass(this.nodes.root, 'watched');
}
return $.on(this.nodes.thumb.parentNode, 'click', (function(_this) {
return function(e) {
if (!(e.button === 0 && e.altKey)) {
return;
}
ThreadWatcher.toggle(_this.thread);
return e.preventDefault();
};
})(this));
},
ready: function() {
$.off(d, '4chanXInitFinished', ThreadWatcher.ready);
if (!Main.isThisPageLegit()) {
return;
}
ThreadWatcher.refresh();
$.add(d.body, ThreadWatcher.dialog);
if (Conf['Toggleable Thread Watcher']) {
ThreadWatcher.dialog.hidden = true;
}
if (!Conf['Auto Watch']) {
return;
}
return $.get('AutoWatch', 0, function(_arg) {
var AutoWatch, thread;
AutoWatch = _arg.AutoWatch;
if (!(thread = g.BOARD.threads[AutoWatch])) {
return;
}
ThreadWatcher.add(thread);
return $["delete"]('AutoWatch');
});
},
toggleWatcher: function() {
$.toggleClass(ThreadWatcher.shortcut, 'disabled');
return ThreadWatcher.dialog.hidden = !ThreadWatcher.dialog.hidden;
},
cb: {
openAll: function() {
var a, _i, _len, _ref;
if ($.hasClass(this, 'disabled')) {
return;
}
_ref = $$('a[title]', ThreadWatcher.list);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
a = _ref[_i];
$.open(a.href);
}
return $.event('CloseMenu');
},
pruneDeads: function() {
var boardID, data, threadID, _i, _len, _ref, _ref1;
if ($.hasClass(this, 'disabled')) {
return;
}
_ref = ThreadWatcher.getAll();
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
_ref1 = _ref[_i], boardID = _ref1.boardID, threadID = _ref1.threadID, data = _ref1.data;
if (!data.isDead) {
continue;
}
delete ThreadWatcher.db.data.boards[boardID][threadID];
ThreadWatcher.db.deleteIfEmpty({
boardID: boardID
});
}
ThreadWatcher.db.save();
ThreadWatcher.refresh();
return $.event('CloseMenu');
},
toggle: function() {
var thread;
thread = Get.postFromNode(this).thread;
Index.followedThreadID = thread.ID;
ThreadWatcher.toggle(thread);
return delete Index.followedThreadID;
},
rm: function() {
var boardID, threadID, _ref;
_ref = this.parentNode.dataset.fullID.split('.'), boardID = _ref[0], threadID = _ref[1];
return ThreadWatcher.rm(boardID, +threadID);
},
post: function(e) {
var boardID, postID, threadID, _ref;
_ref = e.detail, boardID = _ref.boardID, threadID = _ref.threadID, postID = _ref.postID;
if (postID === threadID) {
if (Conf['Auto Watch']) {
return $.set('AutoWatch', threadID);
}
} else if (Conf['Auto Watch Reply']) {
return ThreadWatcher.add(g.threads[boardID + '.' + threadID]);
}
},
onIndexRefresh: function() {
var boardID, data, db, threadID, _ref;
db = ThreadWatcher.db;
boardID = g.BOARD.ID;
db.forceSync();
_ref = db.data.boards[boardID];
for (threadID in _ref) {
data = _ref[threadID];
if (!data.isDead && !(threadID in g.BOARD.threads)) {
if (Conf['Auto Prune']) {
ThreadWatcher.db["delete"]({
boardID: boardID,
threadID: threadID
});
} else {
data.isDead = true;
ThreadWatcher.db.set({
boardID: boardID,
threadID: threadID,
val: data
});
}
}
}
return ThreadWatcher.refresh();
},
onThreadRefresh: function(e) {
var thread;
thread = g.threads[e.detail.threadID];
if (!(e.detail[404] && ThreadWatcher.db.get({
boardID: thread.board.ID,
threadID: thread.ID
}))) {
return;
}
return ThreadWatcher.add(thread);
}
},
fetchCount: {
fetched: 0,
fetching: 0
},
fetchAuto: function() {
var db, interval, now;
clearTimeout(ThreadWatcher.timeout);
if (!Conf['Auto Update Thread Watcher']) {
return;
}
db = ThreadWatcher.db;
interval = Conf['Show Unread Count'] ? 5 * $.MINUTE : 2 * $.HOUR;
now = Date.now();
if (now >= (db.data.lastChecked || 0) + interval) {
db.data.lastChecked = now;
ThreadWatcher.fetchAllStatus();
db.save();
}
return ThreadWatcher.timeout = setTimeout(ThreadWatcher.fetchAuto, interval);
},
fetchAllStatus: function() {
var thread, threads, _i, _len, _ref;
ThreadWatcher.db.forceSync();
ThreadWatcher.unreaddb.forceSync();
if ((_ref = QR.db) != null) {
_ref.forceSync();
}
if (!(threads = ThreadWatcher.getAll()).length) {
return;
}
for (_i = 0, _len = threads.length; _i < _len; _i++) {
thread = threads[_i];
ThreadWatcher.fetchStatus(thread);
}
},
fetchStatus: function(thread, force) {
var boardID, data, fetchCount, threadID;
boardID = thread.boardID, threadID = thread.threadID, data = thread.data;
if (data.isDead && !force) {
return;
}
fetchCount = ThreadWatcher.fetchCount;
if (fetchCount.fetching === 0) {
ThreadWatcher.status.textContent = '...';
$.addClass(ThreadWatcher.refreshButton, 'fa-spin');
}
fetchCount.fetching++;
return $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", {
onloadend: function() {
return ThreadWatcher.parseStatus.call(this, thread);
}
});
},
parseStatus: function(_arg) {
var boardID, data, fetchCount, isDead, lastReadPost, match, postObj, quotingYou, regexp, status, threadID, unread, _i, _len, _ref, _ref1;
boardID = _arg.boardID, threadID = _arg.threadID, data = _arg.data;
fetchCount = ThreadWatcher.fetchCount;
fetchCount.fetched++;
if (fetchCount.fetched === fetchCount.fetching) {
fetchCount.fetched = 0;
fetchCount.fetching = 0;
status = '';
$.rmClass(ThreadWatcher.refreshButton, 'fa-spin');
} else {
status = "" + (Math.round(fetchCount.fetched / fetchCount.fetching * 100)) + "%";
}
ThreadWatcher.status.textContent = status;
if (this.status === 200 && this.response) {
isDead = !!this.response.posts[0].archived;
if (isDead && Conf['Auto Prune']) {
ThreadWatcher.db["delete"]({
boardID: boardID,
threadID: threadID
});
ThreadWatcher.refresh();
return;
}
lastReadPost = ThreadWatcher.unreaddb.get({
boardID: boardID,
threadID: threadID,
defaultValue: 0
});
unread = quotingYou = 0;
_ref = this.response.posts;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
postObj = _ref[_i];
if (!(postObj.no > lastReadPost)) {
continue;
}
if ((_ref1 = QR.db) != null ? _ref1.get({
boardID: boardID,
threadID: threadID,
postID: postObj.no
}) : void 0) {
continue;
}
unread++;
if (!(QR.db && postObj.com)) {
continue;
}
regexp = /<a [^>]*\bhref="(?:\/([^\/]+)\/thread\/(\d+))?(?:#p(\d+))?"/g;
while (match = regexp.exec(postObj.com)) {
if (QR.db.get({
boardID: match[1] || boardID,
threadID: match[2] || threadID,
postID: match[3] || match[2] || threadID
})) {
quotingYou++;
continue;
}
}
}
if (isDead !== data.isDead || unread !== data.unread || quotingYou !== data.quotingYou) {
data.isDead = isDead;
data.unread = unread;
data.quotingYou = quotingYou;
ThreadWatcher.db.set({
boardID: boardID,
threadID: threadID,
val: data
});
return ThreadWatcher.refresh();
}
} else if (this.status === 404) {
if (Conf['Auto Prune']) {
ThreadWatcher.db["delete"]({
boardID: boardID,
threadID: threadID
});
} else {
data.isDead = true;
delete data.unread;
delete data.quotingYou;
ThreadWatcher.db.set({
boardID: boardID,
threadID: threadID,
val: data
});
}
return ThreadWatcher.refresh();
}
},
getAll: function() {
var all, boardID, data, threadID, threads, _ref;
all = [];
_ref = ThreadWatcher.db.data.boards;
for (boardID in _ref) {
threads = _ref[boardID];
if (Conf['Current Board'] && boardID !== g.BOARD.ID) {
continue;
}
for (threadID in threads) {
data = threads[threadID];
all.push({
boardID: boardID,
threadID: threadID,
data: data
});
}
}
return all;
},
makeLine: function(boardID, threadID, data) {
var count, div, fullID, link, title, x;
x = $.el('a', {
className: 'fa fa-times',
href: 'javascript:;'
});
$.on(x, 'click', ThreadWatcher.cb.rm);
link = $.el('a', {
href: "/" + boardID + "/thread/" + threadID,
title: data.excerpt,
className: 'watcher-link'
});
if (Conf['Show Unread Count'] && (data.unread != null)) {
count = $.el('span', {
textContent: "(" + data.unread + ")",
className: 'watcher-unread'
});
$.add(link, count);
}
title = $.el('span', {
textContent: data.excerpt,
className: 'watcher-title'
});
$.add(link, title);
div = $.el('div');
fullID = "" + boardID + "." + threadID;
div.dataset.fullID = fullID;
if (g.VIEW === 'thread' && fullID === ("" + g.BOARD + "." + g.THREADID)) {
$.addClass(div, 'current');
}
if (data.isDead) {
$.addClass(div, 'dead-thread');
}
if (Conf['Show Unread Count']) {
if (data.unread) {
$.addClass(div, 'replies-unread');
}
if (data.quotingYou) {
$.addClass(div, 'replies-quoting-you');
}
}
$.add(div, [x, $.tn(' '), link]);
return div;
},
refresh: function() {
var boardID, data, list, nodes, refresher, threadID, _i, _j, _len, _len1, _ref, _ref1, _ref2;
nodes = [];
_ref = ThreadWatcher.getAll();
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
_ref1 = _ref[_i], boardID = _ref1.boardID, threadID = _ref1.threadID, data = _ref1.data;
nodes.push(ThreadWatcher.makeLine(boardID, threadID, data));
}
list = ThreadWatcher.list;
$.rmAll(list);
$.add(list, nodes);
g.threads.forEach(function(thread) {
var helper, post, toggler, _j, _len1, _ref2;
helper = ThreadWatcher.isWatched(thread) ? ['addClass', 'Unwatch'] : ['rmClass', 'Watch'];
if (thread.OP) {
_ref2 = [thread.OP].concat(__slice.call(thread.OP.clones));
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
post = _ref2[_j];
toggler = $('.watch-thread-link', post.nodes.post);
$[helper[0]](toggler, 'watched');
toggler.title = "" + helper[1] + " Thread";
}
}
if (thread.catalogView) {
return $[helper[0]](thread.catalogView.nodes.root, 'watched');
}
});
ThreadWatcher.refreshIcon();
_ref2 = ThreadWatcher.menu.refreshers;
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
refresher = _ref2[_j];
refresher();
}
if (Index.nodes && Conf['Pin Watched Threads']) {
Index.sort();
return Index.buildIndex();
}
},
refreshIcon: function() {
var className, _i, _len, _ref;
_ref = ['replies-unread', 'replies-quoting-you'];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
className = _ref[_i];
ThreadWatcher.shortcut.classList.toggle(className, !!$("." + className, ThreadWatcher.dialog));
}
},
update: function(boardID, threadID, newData) {
var data, key, line, n, newLine, val, _ref;
if (!(data = (_ref = ThreadWatcher.db) != null ? _ref.get({
boardID: boardID,
threadID: threadID
}) : void 0)) {
return;
}
if (newData.isDead && Conf['Auto Prune']) {
ThreadWatcher.db["delete"]({
boardID: boardID,
threadID: threadID
});
ThreadWatcher.refresh();
return;
}
n = 0;
for (key in newData) {
val = newData[key];
if (data[key] !== val) {
n++;
}
}
if (!n) {
return;
}
ThreadWatcher.db.forceSync();
if (!(data = ThreadWatcher.db.get({
boardID: boardID,
threadID: threadID
}))) {
return;
}
$.extend(data, newData);
ThreadWatcher.db.set({
boardID: boardID,
threadID: threadID,
val: data
});
if (line = $("#watched-threads > [data-full-i-d='" + boardID + "." + threadID + "']", ThreadWatcher.dialog)) {
newLine = ThreadWatcher.makeLine(boardID, threadID, data);
$.replace(line, newLine);
return ThreadWatcher.refreshIcon();
} else {
return ThreadWatcher.refresh();
}
},
toggle: function(thread) {
var boardID, threadID;
boardID = thread.board.ID;
threadID = thread.ID;
if (ThreadWatcher.db.get({
boardID: boardID,
threadID: threadID
})) {
return ThreadWatcher.rm(boardID, threadID);
} else {
return ThreadWatcher.add(thread);
}
},
add: function(thread) {
var boardID, data, threadID;
data = {};
boardID = thread.board.ID;
threadID = thread.ID;
if (thread.isDead) {
if (Conf['Auto Prune'] && ThreadWatcher.db.get({
boardID: boardID,
threadID: threadID
})) {
ThreadWatcher.rm(boardID, threadID);
return;
}
data.isDead = true;
}
data.excerpt = Get.threadExcerpt(thread);
ThreadWatcher.db.set({
boardID: boardID,
threadID: threadID,
val: data
});
ThreadWatcher.refresh();
if (Conf['Show Unread Count']) {
return ThreadWatcher.fetchStatus({
boardID: boardID,
threadID: threadID,
data: data
}, true);
}
},
rm: function(boardID, threadID) {
ThreadWatcher.db["delete"]({
boardID: boardID,
threadID: threadID
});
return ThreadWatcher.refresh();
},
convert: function(oldFormat) {
var boardID, data, newFormat, threadID, threads;
newFormat = {};
for (boardID in oldFormat) {
threads = oldFormat[boardID];
for (threadID in threads) {
data = threads[threadID];
(newFormat[boardID] || (newFormat[boardID] = {}))[threadID] = {
excerpt: data.textContent
};
}
}
return newFormat;
},
menu: {
refreshers: [],
init: function() {
var menu;
if (!Conf['Thread Watcher']) {
return;
}
menu = this.menu = new UI.Menu('thread watcher');
$.on($('.menu-button', ThreadWatcher.dialog), 'click', function(e) {
return menu.toggle(e, this, ThreadWatcher);
});
this.addHeaderMenuEntry();
return this.addMenuEntries();
},
addHeaderMenuEntry: function() {
var entryEl;
if (g.VIEW !== 'thread') {
return;
}
entryEl = $.el('a', {
href: 'javascript:;'
});
Header.menu.addEntry({
el: entryEl,
order: 60
});
$.on(entryEl, 'click', function() {
return ThreadWatcher.toggle(g.threads["" + g.BOARD + "." + g.THREADID]);
});
return this.refreshers.push(function() {
var addClass, rmClass, text, _ref;
_ref = $('.current', ThreadWatcher.list) ? ['unwatch-thread', 'watch-thread', 'Unwatch thread'] : ['watch-thread', 'unwatch-thread', 'Watch thread'], addClass = _ref[0], rmClass = _ref[1], text = _ref[2];
$.addClass(entryEl, addClass);
$.rmClass(entryEl, rmClass);
return entryEl.textContent = text;
});
},
addMenuEntries: function() {
var cb, conf, entries, entry, name, refresh, subEntries, _i, _len, _ref, _ref1;
entries = [];
entries.push({
cb: ThreadWatcher.cb.openAll,
entry: {
el: $.el('a', {
textContent: 'Open all threads'
})
},
refresh: function() {
return (ThreadWatcher.list.firstElementChild ? $.rmClass : $.addClass)(this.el, 'disabled');
}
});
entries.push({
cb: ThreadWatcher.cb.pruneDeads,
entry: {
el: $.el('a', {
textContent: 'Prune dead threads'
})
},
refresh: function() {
return ($('.dead-thread', ThreadWatcher.list) ? $.rmClass : $.addClass)(this.el, 'disabled');
}
});
subEntries = [];
_ref = Config.threadWatcher;
for (name in _ref) {
conf = _ref[name];
subEntries.push(this.createSubEntry(name, conf[1]));
}
entries.push({
entry: {
el: $.el('span', {
textContent: 'Settings'
}),
subEntries: subEntries
}
});
for (_i = 0, _len = entries.length; _i < _len; _i++) {
_ref1 = entries[_i], entry = _ref1.entry, cb = _ref1.cb, refresh = _ref1.refresh;
if (entry.el.nodeName === 'A') {
entry.el.href = 'javascript:;';
}
if (cb) {
$.on(entry.el, 'click', cb);
}
if (refresh) {
this.refreshers.push(refresh.bind(entry));
}
this.menu.addEntry(entry);
}
},
createSubEntry: function(name, desc) {
var entry, input;
entry = {
type: 'thread watcher',
el: UI.checkbox(name, name.replace(' Thread Watcher', ''))
};
entry.el.title = desc;
input = entry.el.firstElementChild;
$.on(input, 'change', $.cb.checked);
if (name === 'Current Board' || name === 'Show Unread Count') {
$.on(input, 'change', ThreadWatcher.refresh);
}
if (name === 'Show Unread Count' || name === 'Auto Update Thread Watcher') {
$.on(input, 'change', ThreadWatcher.fetchAuto);
}
return entry;
}
}
};
Unread = {
init: function() {
if (!(g.VIEW === 'thread' && (Conf['Unread Count'] || Conf['Unread Favicon'] || Conf['Unread Line'] || Conf['Scroll to Last Read Post'] || Conf['Thread Watcher'] || Conf['Desktop Notifications'] || Conf['Quote Threading']))) {
return;
}
this.db = new DataBoard('lastReadPosts', this.sync);
this.hr = $.el('hr', {
id: 'unread-line'
});
this.posts = new Set();
this.postsQuotingYou = new Set();
this.order = new RandomAccessList();
this.position = null;
Thread.callbacks.push({
name: 'Unread',
cb: this.node
});
return Post.callbacks.push({
name: 'Unread',
cb: this.addPost
});
},
node: function() {
var ID, _i, _len, _ref;
Unread.thread = this;
Unread.title = d.title;
Unread.lastReadPost = Unread.db.get({
boardID: this.board.ID,
threadID: this.ID,
defaultValue: 0
});
Unread.readCount = 0;
_ref = this.posts.keys;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
ID = _ref[_i];
if (+ID <= Unread.lastReadPost) {
Unread.readCount++;
}
}
$.one(d, '4chanXInitFinished', Unread.ready);
return $.on(d, 'ThreadUpdate', Unread.onUpdate);
},
ready: function() {
Unread.setLine(true);
Unread.read();
Unread.update();
if (Conf['Scroll to Last Read Post']) {
Unread.scroll();
}
$.on(d, 'scroll visibilitychange', Unread.read);
if (Conf['Unread Line']) {
return $.on(d, 'visibilitychange', Unread.setLine);
}
},
positionPrev: function() {
if (Unread.position) {
return Unread.position.prev;
} else {
return Unread.order.last;
}
},
scroll: function() {
var hash, position, root;
if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) {
return;
}
position = Unread.positionPrev();
while (position) {
root = position.data.nodes.root;
if (!root.getBoundingClientRect().height) {
position = position.prev;
} else {
Header.scrollToIfNeeded(root, true);
break;
}
}
},
sync: function() {
var ID, i, lastReadPost, postIDs, _i, _ref, _ref1;
if (Unread.lastReadPost == null) {
return;
}
lastReadPost = Unread.db.get({
boardID: Unread.thread.board.ID,
threadID: Unread.thread.ID,
defaultValue: 0
});
if (!(Unread.lastReadPost < lastReadPost)) {
return;
}
Unread.lastReadPost = lastReadPost;
postIDs = Unread.thread.posts.keys;
for (i = _i = _ref = Unread.readCount, _ref1 = postIDs.length; _i < _ref1; i = _i += 1) {
ID = +postIDs[i];
if (!Unread.thread.posts[ID].isFetchedQuote) {
if (ID > Unread.lastReadPost) {
break;
}
Unread.posts["delete"](ID);
Unread.postsQuotingYou["delete"](ID);
}
Unread.readCount++;
}
Unread.updatePosition();
Unread.setLine();
return Unread.update();
},
addPost: function() {
var _ref;
if (this.isFetchedQuote || this.isClone) {
return;
}
Unread.order.push(this);
if (this.ID <= Unread.lastReadPost || this.isHidden || ((_ref = QR.db) != null ? _ref.get({
boardID: this.board.ID,
threadID: this.thread.ID,
postID: this.ID
}) : void 0)) {
return;
}
Unread.posts.add(this.ID);
Unread.addPostQuotingYou(this);
return Unread.position != null ? Unread.position : Unread.position = Unread.order[this.ID];
},
addPostQuotingYou: function(post) {
var quotelink, _i, _len, _ref, _ref1;
_ref = post.nodes.quotelinks;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
quotelink = _ref[_i];
if (!((_ref1 = QR.db) != null ? _ref1.get(Get.postDataFromLink(quotelink)) : void 0)) {
continue;
}
Unread.postsQuotingYou.add(post.ID);
Unread.openNotification(post);
return;
}
},
openNotification: function(post) {
var notif;
if (!Header.areNotificationsEnabled) {
return;
}
notif = new Notification("" + post.info.nameBlock + " replied to you", {
body: post.info[Conf['Remove Spoilers'] || Conf['Reveal Spoilers'] ? 'comment' : 'commentSpoilered'],
icon: Favicon.logo
});
notif.onclick = function() {
Header.scrollToIfNeeded(post.nodes.root, true);
return window.focus();
};
return notif.onshow = function() {
return setTimeout(function() {
return notif.close();
}, 7 * $.SECOND);
};
},
onUpdate: function(e) {
if (!e.detail[404]) {
Unread.setLine();
Unread.read();
}
return Unread.update();
},
readSinglePost: function(post) {
var ID;
ID = post.ID;
if (!Unread.posts.has(ID)) {
return;
}
Unread.posts["delete"](ID);
Unread.postsQuotingYou["delete"](ID);
Unread.updatePosition();
Unread.saveLastReadPost();
return Unread.update();
},
read: $.debounce(100, function(e) {
var ID, count, data, height, root, _ref, _ref1;
if (d.hidden || !Unread.posts.size) {
return;
}
height = doc.clientHeight;
count = 0;
while (Unread.position) {
_ref = Unread.position, ID = _ref.ID, data = _ref.data;
root = data.nodes.root;
if (!(!root.getBoundingClientRect().height || Header.getBottomOf(root) > -1)) {
break;
}
count++;
Unread.posts["delete"](ID);
Unread.postsQuotingYou["delete"](ID);
if (Conf['Mark Quotes of You'] && ((_ref1 = QR.db) != null ? _ref1.get({
boardID: data.board.ID,
threadID: data.thread.ID,
postID: ID
}) : void 0)) {
QuoteYou.lastRead = root;
}
Unread.position = Unread.position.next;
}
if (!count) {
return;
}
Unread.updatePosition();
Unread.saveLastReadPost();
if (e) {
return Unread.update();
}
}),
updatePosition: function() {
while (Unread.position && !Unread.posts.has(Unread.position.ID)) {
Unread.position = Unread.position.next;
}
},
saveLastReadPost: $.debounce(2 * $.SECOND, function() {
var ID, i, postIDs, _i, _ref, _ref1;
postIDs = Unread.thread.posts.keys;
for (i = _i = _ref = Unread.readCount, _ref1 = postIDs.length; _i < _ref1; i = _i += 1) {
ID = +postIDs[i];
if (!Unread.thread.posts[ID].isFetchedQuote) {
if (Unread.posts.has(ID)) {
break;
}
Unread.lastReadPost = ID;
}
Unread.readCount++;
}
if (Unread.thread.isDead && !Unread.thread.isArchived) {
return;
}
Unread.db.forceSync();
return Unread.db.set({
boardID: Unread.thread.board.ID,
threadID: Unread.thread.ID,
val: Unread.lastReadPost
});
}),
setLine: function(force) {
if (!Conf['Unread Line']) {
return;
}
if (d.hidden || (force === true)) {
if (Unread.linePosition = Unread.positionPrev()) {
$.after(Unread.linePosition.data.nodes.root, Unread.hr);
} else {
$.rm(Unread.hr);
}
}
return Unread.hr.hidden = Unread.linePosition === Unread.order.last;
},
update: function() {
var count, countQuotingYou, titleCount, titleDead, titleQuotingYou;
count = Unread.posts.size;
countQuotingYou = Unread.postsQuotingYou.size;
if (Conf['Unread Count']) {
titleQuotingYou = Conf['Quoted Title'] && countQuotingYou ? '(!) ' : '';
titleCount = count || !Conf['Hide Unread Count at (0)'] ? "(" + count + ") " : '';
titleDead = Unread.thread.isDead ? Unread.title.replace('-', (Unread.thread.isArchived ? '- Archived -' : '- 404 -')) : Unread.title;
d.title = "" + titleQuotingYou + titleCount + titleDead;
}
if (!(Unread.thread.isDead && !Unread.thread.isArchived)) {
ThreadWatcher.update(Unread.thread.board.ID, Unread.thread.ID, {
isDead: Unread.thread.isDead,
unread: count,
quotingYou: countQuotingYou
});
}
if (!Conf['Unread Favicon']) {
return;
}
Favicon.el.href = Unread.thread.isDead ? countQuotingYou ? Favicon.unreadDeadY : count ? Favicon.unreadDead : Favicon.dead : count ? countQuotingYou ? Favicon.unreadY : Favicon.unread : Favicon["default"];
return $.add(d.head, Favicon.el);
}
};
Redirect = {
init: function() {
var archive, archives, boardID, boards, data, files, id, name, o, record, software, type, withCredentials, _i, _j, _len, _len1, _ref, _ref1;
o = {
thread: {},
post: {},
file: {}
};
archives = {};
_ref = Redirect.archives;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
data = _ref[_i];
name = data.name, boards = data.boards, files = data.files, software = data.software, withCredentials = data.withCredentials;
archives[name] = data;
for (_j = 0, _len1 = boards.length; _j < _len1; _j++) {
boardID = boards[_j];
if (!(!withCredentials)) {
continue;
}
if (!(boardID in o.thread)) {
o.thread[boardID] = data;
}
if (!(boardID in o.post || software !== 'foolfuuka')) {
o.post[boardID] = data;
}
if (!(boardID in o.file || __indexOf.call(files, boardID) < 0)) {
o.file[boardID] = data;
}
}
}
_ref1 = Conf['selectedArchives'];
for (boardID in _ref1) {
record = _ref1[boardID];
for (type in record) {
id = record[type];
if (id === 'disabled') {
delete o[type][boardID];
} else if (archive = archives[id]) {
boards = type === 'file' ? archive.files : archive.boards;
if (__indexOf.call(boards, boardID) >= 0) {
o[type][boardID] = archive;
}
}
}
}
return Redirect.data = o;
},
archives: [{"uid":0,"name":"Moe","domain":"archive.moe","http":false,"https":true,"software":"foolfuuka","boards":["a","biz","c","co","diy","gd","h","i","int","jp","k","m","mlp","out","po","qa","r9k","s4s","sci","tg","tv","u","v","vg","vp","vr","wsg"],"files":["a","biz","c","co","diy","gd","h","i","jp","k","m","mlp","po","qa","s4s","sci","tg","u","v","vg","vp","vr","wsg"]},{"uid":3,"name":"4plebs Archive","domain":"archive.4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["adv","f","hr","o","pol","s4s","tg","trv","tv","x"],"files":["adv","f","hr","o","pol","s4s","tg","trv","tv","x"]},{"uid":5,"name":"Love is Over","domain":"archive.loveisover.me","http":true,"https":true,"software":"foolfuuka","boards":["c","d","e","i","lgbt","t","u","w","wg"],"files":["c","d","e","i","lgbt","t","u","w","wg"]},{"uid":8,"name":"Rebecca Black Tech","domain":"rbt.asia","http":false,"https":true,"software":"fuuka","boards":["cgl","g","mu","qa","w"],"files":["cgl","g","mu","qa","w"]},{"uid":10,"name":"warosu","domain":"warosu.org","http":false,"https":true,"software":"fuuka","boards":["3","biz","cgl","ck","diy","fa","g","ic","jp","lit","sci","tg","vr"],"files":["3","biz","cgl","ck","diy","fa","g","ic","jp","lit","sci","tg","vr"]},{"uid":15,"name":"fgts","domain":"fgts.jp","http":true,"https":true,"software":"foolfuuka","boards":["asp","cm","h","hc","hm","n","p","qa","r","s","soc","y"],"files":["asp","cm","h","hc","hm","n","p","qa","r","s","soc","y"]},{"uid":21,"name":"imcute","domain":"imcute.yt","http":true,"https":false,"software":"foolfuuka","boards":["an","fit","gif","int","mlp","out","r9k","qa","toy"],"files":["an","fit","gif","int","mlp","out","r9k","qa","toy"],"imagehosts":["http://imcute.yt/"]}],
to: function(dest, data) {
var archive;
archive = (dest === 'search' || dest === 'board' ? Redirect.data.thread : Redirect.data[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 URL, boardID, postID, protocol;
boardID = _arg.boardID, postID = _arg.postID;
protocol = Redirect.protocol(archive);
URL = new String("" + protocol + archive.domain + "/_/api/chan/post/?board=" + boardID + "&num=" + postID);
if (!Redirect.securityCheck(URL)) {
return '';
}
URL.archive = archive;
return URL;
},
file: function(archive, _arg) {
var boardID, filename;
boardID = _arg.boardID, filename = _arg.filename;
return "" + (Redirect.protocol(archive)) + archive.domain + "/" + boardID + "/full_image/" + filename;
},
board: function(archive, _arg) {
var boardID;
boardID = _arg.boardID;
return "" + (Redirect.protocol(archive)) + archive.domain + "/" + boardID + "/";
},
search: function(archive, _arg) {
var boardID, path, type, value;
boardID = _arg.boardID, type = _arg.type, value = _arg.value;
type = type === 'name' ? 'username' : type === 'uniqueID' ? 'uid' : 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;
},
securityCheck: function(URL) {
return /^https:\/\//.test(URL) || location.protocol === 'http:' || Conf['Except Archives from Encryption'];
},
navigate: function(URL, alternative) {
if (URL && (Redirect.securityCheck(URL) || confirm("Redirect to " + URL + "?\n\nYour connection will not be encrypted."))) {
return location.replace(URL);
} else if (alternative) {
return location.replace(alternative);
}
}
};
PSAHiding = {
init: function() {
if (!Conf['Announcement Hiding']) {
return;
}
$.addClass(doc, 'hide-announcement');
return $.one(d, '4chanXInitFinished', this.setup);
},
setup: function() {
var btn, entry, hr, psa, _ref;
if (!(psa = PSAHiding.psa = $.id('globalMessage'))) {
$.rmClass(doc, 'hide-announcement');
return;
}
if ((hr = (_ref = $.id('globalToggle')) != null ? _ref.previousElementSibling : void 0) && hr.nodeName === 'HR') {
PSAHiding.hr = hr;
}
entry = {
el: $.el('a', {
textContent: 'Show announcement',
className: 'show-announcement',
href: 'javascript:;'
}),
order: 50,
open: function() {
return PSAHiding.hidden;
}
};
Header.menu.addEntry(entry);
$.on(entry.el, 'click', PSAHiding.toggle);
PSAHiding.btn = btn = $.el('span', {
title: 'Mark announcement as read and hide.',
className: 'hide-announcement'
});
$.extend(btn, {
innerHTML: "[<a href=\"javascript:;\">Dismiss</a>]"
});
$.on(btn, 'click', PSAHiding.toggle);
$.get('hiddenPSA', 0, function(_arg) {
var hiddenPSA;
hiddenPSA = _arg.hiddenPSA;
PSAHiding.sync(hiddenPSA);
$.add(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 psa, _ref;
psa = PSAHiding.psa;
PSAHiding.hidden = PSAHiding.btn.hidden = (UTC != null) && UTC >= +psa.dataset.utc;
if (PSAHiding.hidden) {
$.rm(psa);
} else {
$.after($.id('globalToggle'), psa);
}
if ((_ref = PSAHiding.hr) != null) {
_ref.hidden = PSAHiding.hidden;
}
}
};
AntiAutoplay = {
init: function() {
var audio, _i, _len, _ref;
if (!Conf['Disable Autoplaying Sounds']) {
return;
}
$.addClass(doc, 'anti-autoplay');
_ref = $$('audio[autoplay]', doc);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
audio = _ref[_i];
this.stop(audio);
}
window.addEventListener('loadstart', ((function(_this) {
return function(e) {
return _this.stop(e.target);
};
})(this)), true);
Post.callbacks.push({
name: 'Disable Autoplaying Sounds',
cb: this.node
});
CatalogThread.callbacks.push({
name: 'Disable Autoplaying Sounds',
cb: this.node
});
return $.ready((function(_this) {
return function() {
return _this.process(d.body);
};
})(this));
},
stop: function(audio) {
if (!audio.autoplay) {
return;
}
audio.pause();
audio.autoplay = false;
if (audio.controls) {
return;
}
audio.controls = true;
return $.addClass(audio, 'controls-added');
},
node: function() {
return AntiAutoplay.process(this.nodes.root);
},
process: function(root) {
var iframe, object, _i, _j, _len, _len1, _ref, _ref1;
_ref = $$('iframe[src*="youtube"][src*="autoplay=1"]', root);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
iframe = _ref[_i];
iframe.src = iframe.src.replace(/\?autoplay=1&?/, '?').replace('&autoplay=1', '');
}
_ref1 = $$('object[data*="youtube"][data*="autoplay=1"]', root);
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
object = _ref1[_j];
object.data = object.data.replace(/\?autoplay=1&?/, '?').replace('&autoplay=1', '');
}
}
};
Banner = {
banners: ["0.jpg","1.jpg","2.jpg","4.jpg","6.jpg","7.jpg","8.jpg","9.jpg","10.jpg","11.jpg","12.jpg","13.jpg","14.jpg","16.jpg","17.jpg","18.jpg","19.jpg","20.jpg","21.jpg","22.jpg","24.jpg","25.jpg","26.jpg","28.jpg","29.jpg","33.jpg","38.jpg","39.jpg","43.jpg","44.jpg","45.jpg","46.jpg","47.jpg","52.jpg","54.jpg","57.jpg","59.jpg","60.jpg","61.jpg","64.jpg","66.jpg","67.jpg","69.jpg","71.jpg","72.jpg","76.jpg","77.jpg","81.jpg","82.jpg","83.jpg","84.jpg","88.jpg","90.jpg","91.jpg","96.jpg","98.jpg","99.jpg","100.jpg","104.jpg","106.jpg","116.jpg","119.jpg","137.jpg","140.jpg","148.jpg","149.jpg","150.jpg","154.jpg","156.jpg","157.jpg","158.jpg","159.jpg","161.jpg","162.jpg","164.jpg","165.jpg","166.jpg","167.jpg","168.jpg","169.jpg","170.jpg","171.jpg","172.jpg","173.jpg","174.jpg","175.jpg","176.jpg","178.jpg","179.jpg","180.jpg","181.jpg","182.jpg","183.jpg","186.jpg","189.jpg","190.jpg","192.jpg","193.jpg","194.jpg","197.jpg","198.jpg","200.jpg","201.jpg","202.jpg","203.jpg","205.jpg","206.jpg","207.jpg","208.jpg","210.jpg","213.jpg","214.jpg","215.jpg","216.jpg","218.jpg","219.jpg","220.jpg","221.jpg","222.jpg","223.jpg","224.jpg","227.jpg","0.png","1.png","2.png","3.png","5.png","6.png","9.png","10.png","11.png","12.png","14.png","16.png","19.png","20.png","21.png","22.png","23.png","24.png","26.png","27.png","28.png","29.png","30.png","31.png","32.png","33.png","34.png","37.png","39.png","40.png","41.png","42.png","43.png","44.png","45.png","48.png","49.png","50.png","51.png","52.png","53.png","57.png","58.png","59.png","64.png","66.png","67.png","68.png","69.png","70.png","71.png","72.png","76.png","78.png","81.png","82.png","85.png","86.png","87.png","89.png","95.png","98.png","100.png","101.png","102.png","105.png","106.png","107.png","109.png","110.png","111.png","112.png","113.png","114.png","115.png","116.png","118.png","119.png","120.png","121.png","122.png","123.png","126.png","128.png","130.png","134.png","136.png","138.png","139.png","140.png","142.png","145.png","146.png","149.png","150.png","151.png","152.png","153.png","154.png","155.png","156.png","157.png","158.png","159.png","160.png","163.png","164.png","165.png","166.png","167.png","168.png","169.png","170.png","171.png","172.png","173.png","174.png","178.png","179.png","180.png","181.png","182.png","184.png","186.png","188.png","190.png","192.png","193.png","194.png","195.png","196.png","197.png","198.png","200.png","202.png","203.png","205.png","206.png","207.png","209.png","212.png","213.png","214.png","216.png","217.png","218.png","219.png","220.png","221.png","222.png","223.png","224.png","225.png","226.png","229.png","231.png","232.png","233.png","234.png","235.png","237.png","238.png","239.png","240.png","241.png","242.png","244.png","245.png","246.png","247.png","248.png","249.png","250.png","253.png","254.png","255.png","257.png","258.png","259.png","260.png","262.png","268.png","0.gif","1.gif","2.gif","3.gif","4.gif","5.gif","6.gif","7.gif","8.gif","9.gif","10.gif","12.gif","13.gif","14.gif","15.gif","16.gif","18.gif","19.gif","20.gif","21.gif","22.gif","23.gif","24.gif","28.gif","29.gif","30.gif","33.gif","34.gif","35.gif","36.gif","37.gif","39.gif","40.gif","42.gif","44.gif","45.gif","46.gif","48.gif","50.gif","52.gif","54.gif","55.gif","57.gif","58.gif","59.gif","60.gif","61.gif","62.gif","63.gif","64.gif","66.gif","67.gif","68.gif","69.gif","70.gif","72.gif","73.gif","75.gif","76.gif","77.gif","78.gif","80.gif","81.gif","82.gif","83.gif","86.gif","87.gif","88.gif","92.gif","93.gif","94.gif","95.gif","96.gif","97.gif","98.gif","99.gif","100.gif","101.gif","102.gif","103.gif","104.gif","105.gif","106.gif","108.gif","109.gif","110.gif","111.gif","112.gif","113.gif","115.gif","116.gif","117.gif","118.gif","119.gif","120.gif","122.gif","123.gif","124.gif","127.gif","129.gif","130.gif","131.gif","134.gif","135.gif","136.gif","138.gif","139.gif","141.gif","144.gif","146.gif","148.gif","149.gif","153.gif","154.gif","155.gif","157.gif","158.gif","159.gif","160.gif","161.gif","162.gif","164.gif","166.gif","167.gif","168.gif","169.gif","170.gif","171.gif","172.gif","173.gif","174.gif","175.gif","176.gif","177.gif","178.gif","181.gif","182.gif","183.gif","185.gif","186.gif","187.gif","188.gif","189.gif","190.gif","191.gif","192.gif","193.gif","195.gif","196.gif","197.gif","200.gif","201.gif","202.gif","203.gif","204.gif","205.gif","206.gif","207.gif","208.gif","209.gif","210.gif","211.gif","212.gif","213.gif","214.gif","215.gif","216.gif","217.gif","219.gif","220.gif","221.gif","222.gif","224.gif","225.gif","226.gif","227.gif","228.gif","230.gif","232.gif","233.gif","234.gif","235.gif","238.gif","240.gif","241.gif","243.gif","244.gif","245.gif","246.gif","247.gif","249.gif","250.gif","251.gif","253.gif"],
init: function() {
if (Conf['Custom Board Titles']) {
this.db = new DataBoard('customTitles', null, true);
}
$.asap((function() {
return d.body;
}), function() {
return $.asap((function() {
return $('hr');
}), Banner.ready);
});
if (g.BOARD.ID !== 'f') {
return Main.ready(function() {
return $.queueTask(Banner.load);
});
}
},
ready: function() {
var banner, children;
banner = $(".boardBanner");
children = banner.children;
if (g.BOARD.ID !== 'f' && g.VIEW === 'thread' && Conf['Remove Thread Excerpt']) {
Banner.setTitle(children[1].textContent);
}
children[0].title = "Click to change";
$.on(children[0], 'click', Banner.cb.toggle);
if (Conf['Custom Board Titles']) {
Banner.custom(children[1]);
if (children[2]) {
return Banner.custom(children[2]);
}
}
},
load: function() {
var bannerCnt, img;
bannerCnt = $.id('bannerCnt');
if (!bannerCnt.firstChild) {
img = $.el('img', {
alt: '4chan',
src: '//s.4cdn.org/image/title/' + bannerCnt.dataset.src
});
return $.add(bannerCnt, img);
}
},
setTitle: function(title) {
if (Unread.title != null) {
Unread.title = title;
return Unread.update();
} else {
return d.title = title;
}
},
cb: {
toggle: function() {
var banner, i, _ref;
if (!((_ref = Banner.choices) != null ? _ref.length : void 0)) {
Banner.choices = Banner.banners.slice();
}
i = Math.floor(Banner.choices.length * Math.random());
banner = Banner.choices.splice(i, 1);
return $('img', this.parentNode).src = "//s.4cdn.org/image/title/" + banner;
},
click: function(e) {
var br, _base, _i, _len, _name, _ref;
if (!(e.ctrlKey || e.metaKey)) {
return;
}
if ((_base = Banner.original)[_name = this.className] == null) {
_base[_name] = this.cloneNode(true);
}
this.contentEditable = true;
_ref = $$('br', this);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
br = _ref[_i];
$.replace(br, $.tn('\n'));
}
return this.focus();
},
keydown: function(e) {
e.stopPropagation();
if (!e.shiftKey && e.keyCode === 13) {
return this.blur();
}
},
blur: function() {
var br, _i, _len, _ref;
_ref = $$('br', this);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
br = _ref[_i];
$.replace(br, $.tn('\n'));
}
if (this.textContent = this.textContent.replace(/\n*$/, '')) {
this.contentEditable = false;
return Banner.db.set({
boardID: g.BOARD.ID,
threadID: this.className,
val: {
title: this.textContent,
orig: Banner.original[this.className].textContent
}
});
} else {
$.rmAll(this);
$.add(this, __slice.call(Banner.original[this.className].cloneNode(true).childNodes));
return Banner.db["delete"]({
boardID: g.BOARD.ID,
threadID: this.className
});
}
}
},
original: {},
custom: function(child) {
var className, data, event, items, string, string2, _i, _len, _ref;
className = child.className;
child.title = "Ctrl/\u2318+click to edit board " + (className.slice(5).toLowerCase());
child.spellcheck = false;
_ref = ['click', 'keydown', 'blur'];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
event = _ref[_i];
$.on(child, event, Banner.cb[event]);
}
string = "" + g.BOARD + "." + className;
string2 = "" + string + ".orig";
items = {};
items[string] = '';
items[string2] = child.textContent;
$.get(items, function(items) {
if (items[string]) {
Banner.db.set({
boardID: g.BOARD.ID,
threadID: className,
val: {
title: items[string],
orig: items[string2]
}
});
}
return $["delete"]([string, string2]);
});
if (data = Banner.db.get({
boardID: g.BOARD.ID,
threadID: className
})) {
if (Conf['Persistent Custom Board Titles'] || data.orig === child.textContent) {
Banner.original[className] = child.cloneNode(true);
return child.textContent = data.title;
} else {
return Banner.db["delete"]({
boardID: g.BOARD.ID,
threadID: className
});
}
}
}
};
CatalogLinks = {
init: function() {
var el, input, selector;
if ((Conf['External Catalog'] || Conf['JSON Navigation']) && !(Conf['JSON Navigation'] && g.VIEW === 'index')) {
selector = (function() {
switch (g.VIEW) {
case 'thread':
case 'archive':
return '.navLinks.desktop > a';
case 'catalog':
return '.navLinks > :first-child > a';
case 'index':
return '#ctrl-top > a, .cataloglink > a';
}
})();
$.ready(function() {
var catalogLink, link, _i, _len, _ref;
_ref = $$(selector);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
link = _ref[_i];
switch (link.pathname) {
case "/" + g.BOARD + "/":
if (Conf['JSON Navigation']) {
link.textContent = 'Index';
}
link.href = CatalogLinks.index();
break;
case "/" + g.BOARD + "/catalog":
link.href = CatalogLinks.catalog();
}
if (g.VIEW === 'catalog' && Conf['JSON Navigation'] && Conf['Use 4chan X Catalog']) {
catalogLink = link.parentNode.cloneNode(true);
catalogLink.firstElementChild.textContent = '4chan X Catalog';
catalogLink.firstElementChild.href = CatalogLinks.catalog();
$.after(link.parentNode, [$.tn(' '), catalogLink]);
}
}
});
}
if (Conf['JSON Navigation'] && Conf['Use 4chan X Catalog']) {
Post.callbacks.push({
name: 'Catalog Link Rewrite',
cb: this.node
});
CatalogThread.callbacks.push({
name: 'Catalog Link Rewrite',
cb: this.node
});
}
if (Conf['Catalog Links']) {
CatalogLinks.el = el = UI.checkbox('Header catalog links', 'Catalog Links');
el.id = 'toggleCatalog';
input = $('input', el);
$.on(input, 'change', this.toggle);
$.sync('Header catalog links', CatalogLinks.set);
return Header.menu.addEntry({
el: el,
order: 95
});
}
},
node: function() {
var a, m, _i, _len, _ref;
_ref = $$('a', this.nodes.comment);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
a = _ref[_i];
if (m = a.href.match(/^https?:\/\/boards\.4chan\.org\/([^\/]+)\/catalog(#s=.*)?/)) {
a.href = "//boards.4chan.org/" + m[1] + "/" + (m[2] || '#catalog');
}
}
},
initBoardList: function() {
if (!Conf['Catalog Links']) {
return;
}
return CatalogLinks.set(Conf['Header catalog links']);
},
toggle: function() {
$.event('CloseMenu');
$.set('Header catalog links', this.checked);
return CatalogLinks.set(this.checked);
},
set: function(useCatalog) {
var a, board, _i, _len, _ref, _ref1;
_ref = $$('a:not([data-only])', Header.boardList).concat($$('a', Header.bottomBoardList));
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
a = _ref[_i];
if (((_ref1 = a.hostname) !== 'boards.4chan.org' && _ref1 !== 'catalog.neet.tv' && _ref1 !== '4index.gropes.us') || !(board = a.pathname.split('/')[1]) || (board === 'f' || board === 'status' || board === '4chan') || a.pathname.split('/')[2] === 'archive' || $.hasClass(a, 'external')) {
continue;
}
a.href = useCatalog ? CatalogLinks.catalog(board) : "/" + board + "/";
}
CatalogLinks.el.title = "Turn catalog links " + (useCatalog ? 'off' : 'on') + ".";
return $('input', CatalogLinks.el).checked = useCatalog;
},
catalog: function(board) {
if (board == null) {
board = g.BOARD.ID;
}
if (Conf['External Catalog'] && (board === 'a' || board === 'c' || board === 'g' || board === 'biz' || board === 'k' || board === 'm' || board === 'o' || board === 'p' || board === 'v' || board === 'vg' || board === 'vr' || board === 'w' || board === 'wg' || board === 'cm' || board === '3' || board === 'adv' || board === 'an' || board === 'asp' || board === 'cgl' || board === 'ck' || board === 'co' || board === 'diy' || board === 'fa' || board === 'fit' || board === 'gd' || board === 'int' || board === 'jp' || board === 'lit' || board === 'mlp' || board === 'mu' || board === 'n' || board === 'out' || board === 'po' || board === 'sci' || board === 'sp' || board === 'tg' || board === 'toy' || board === 'trv' || board === 'tv' || board === 'vp' || board === 'wsg' || board === 'x' || board === 'f' || board === 'pol' || board === 's4s' || board === 'lgbt')) {
return "http://catalog.neet.tv/" + board;
} else if (Conf['JSON Navigation'] && Conf['Use 4chan X Catalog']) {
if (g.BOARD.ID === board && g.VIEW === 'index') {
return '#catalog';
} else {
return "/" + board + "/#catalog";
}
} else {
return "/" + board + "/catalog";
}
},
index: function(board) {
if (board == null) {
board = g.BOARD.ID;
}
if (Conf['JSON Navigation']) {
if (g.BOARD.ID === board && g.VIEW === 'index') {
return '#index';
} else {
return "/" + board + "/#index";
}
} else {
return "/" + board + "/";
}
}
};
CustomCSS = {
init: function() {
if (!Conf['Custom CSS']) {
return;
}
return this.addStyle();
},
addStyle: function() {
return this.style = $.addStyle(Conf['usercss'], 'custom-css', function() {
return $.id('fourchanx-css');
});
},
rmStyle: function() {
if (this.style) {
$.rm(this.style);
return delete this.style;
}
},
update: function() {
if (!this.style) {
return this.addStyle();
}
return this.style.textContent = Conf['usercss'];
}
};
ExpandComment = {
init: function() {
if (g.VIEW !== 'index' || !Conf['Comment Expansion'] || Conf['JSON Navigation']) {
return;
}
if (g.BOARD.ID === 'g') {
this.callbacks.push(Fourchan.code);
}
if (g.BOARD.ID === 'sci') {
this.callbacks.push(Fourchan.math);
}
return Post.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) {
e.preventDefault();
return ExpandComment.expand(Get.postFromNode(this));
},
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("//a.4cdn.org" + (a.pathname.split('/').splice(0, 4).join('/')) + ".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 (status !== 200 && status !== 304) {
a.textContent = "Error " + req.statusText + " (" + status + ")";
return;
}
posts = 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;
}
if (href[0] === '#') {
quote.href = "" + (a.pathname.split('/').splice(0, 4).join('/')) + href;
} else {
quote.href = "" + (a.pathname.split('/').splice(0, 3).join('/')) + "/" + 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 = {
statuses: {},
init: function() {
if (g.VIEW === 'thread' || !Conf['Thread Expansion']) {
return;
}
if (Conf['JSON Navigation']) {
return $.on(d, 'IndexRefresh', this.onIndexRefresh);
} else {
return Thread.callbacks.push({
name: 'Expand Thread',
cb: function() {
return ExpandThread.setButton(this);
}
});
}
},
setButton: function(thread) {
var a;
if (!(a = $.x('following-sibling::*[contains(@class,"summary")][1]', thread.OP.nodes.root))) {
return;
}
a.textContent = ExpandThread.text.apply(ExpandThread, ['+'].concat(__slice.call(a.textContent.match(/\d+/g))));
a.style.cursor = 'pointer';
return $.on(a, 'click', ExpandThread.cbToggle);
},
disconnect: function(refresh) {
var status, threadID, _ref, _ref1;
if (g.VIEW === 'thread' || !Conf['Thread Expansion']) {
return;
}
_ref = ExpandThread.statuses;
for (threadID in _ref) {
status = _ref[threadID];
if ((_ref1 = status.req) != null) {
_ref1.abort();
}
delete ExpandThread.statuses[threadID];
}
if (!refresh) {
return $.off(d, 'IndexRefresh', this.onIndexRefresh);
}
},
onIndexRefresh: function() {
ExpandThread.disconnect(true);
return g.BOARD.threads.forEach(function(thread) {
return ExpandThread.setButton(thread);
});
},
text: function(status, posts, files) {
return ("" + status + " " + posts + " post" + (posts > 1 ? 's' : '')) + (+files ? " and " + files + " image repl" + (files > 1 ? 'ies' : 'y') : "") + (" " + (status === '-' ? 'shown' : 'omitted') + ".");
},
cbToggle: function(e) {
if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) {
return;
}
e.preventDefault();
return ExpandThread.toggle(Get.threadFromNode(this));
},
toggle: function(thread) {
var a, threadRoot;
threadRoot = thread.OP.nodes.root.parentNode;
if (!(a = $('.summary', threadRoot))) {
return;
}
if (thread.ID in ExpandThread.statuses) {
return ExpandThread.contract(thread, a, threadRoot);
} else {
return ExpandThread.expand(thread, a, threadRoot);
}
},
expand: function(thread, a, threadRoot) {
var status;
ExpandThread.statuses[thread] = status = {};
a.textContent = ExpandThread.text.apply(ExpandThread, ['...'].concat(__slice.call(a.textContent.match(/\d+/g))));
return status.req = $.cache("//a.4cdn.org/" + thread.board + "/thread/" + thread + ".json", function() {
delete status.req;
return ExpandThread.parse(this, thread, a);
});
},
contract: function(thread, a, threadRoot) {
var filesCount, inlined, num, postsCount, replies, reply, status, _i, _len;
status = ExpandThread.statuses[thread];
delete ExpandThread.statuses[thread];
if (status.req) {
status.req.abort();
if (a) {
a.textContent = ExpandThread.text.apply(ExpandThread, ['+'].concat(__slice.call(a.textContent.match(/\d+/g))));
}
return;
}
replies = $$('.thread > .replyContainer', threadRoot);
if (!Conf['JSON Navigation'] || Conf['Show Replies']) {
num = (function() {
if (thread.isSticky) {
return 1;
} else {
switch (g.BOARD.ID) {
case 'b':
case 'vg':
return 3;
case 't':
return 1;
default:
return 5;
}
}
})();
replies = replies.slice(0, -num);
}
postsCount = 0;
filesCount = 0;
for (_i = 0, _len = replies.length; _i < _len; _i++) {
reply = replies[_i];
if (Conf['Quote Inlining']) {
while (inlined = $('.inlined', reply)) {
inlined.click();
}
}
postsCount++;
if ('file' in Get.postFromRoot(reply)) {
filesCount++;
}
$.rm(reply);
}
return a.textContent = ExpandThread.text('+', postsCount, filesCount);
},
parse: function(req, thread, a) {
var filesCount, post, postData, posts, postsCount, postsRoot, root, _i, _len, _ref, _ref1;
if ((_ref = req.status) !== 200 && _ref !== 304) {
a.textContent = "Error " + req.statusText + " (" + req.status + ")";
return;
}
Build.spoilerRange[thread.board] = req.response.posts[0].custom_spoiler;
posts = [];
postsRoot = [];
filesCount = 0;
_ref1 = req.response.posts;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
postData = _ref1[_i];
if (postData.no === thread.ID) {
continue;
}
if ((post = thread.posts[postData.no]) && !post.isFetchedQuote) {
if ('file' in post) {
filesCount++;
}
postsRoot.push(post.nodes.root);
continue;
}
root = Build.postFromObject(postData, thread.board.ID);
post = new Post(root, thread, thread.board);
if ('file' in post) {
filesCount++;
}
posts.push(post);
postsRoot.push(root);
}
Main.callbackNodes(Post, posts);
$.after(a, postsRoot);
$.event('PostsInserted');
postsCount = postsRoot.length;
return a.textContent = ExpandThread.text('-', postsCount, filesCount);
}
};
FileInfo = {
init: function() {
var _ref;
if (((_ref = g.VIEW) !== 'index' && _ref !== 'thread') || !Conf['File Info Formatting']) {
return;
}
return Post.callbacks.push({
name: 'File Info Formatting',
cb: this.node
});
},
node: function() {
if (!this.file || this.isClone) {
return;
}
$.extend(this.file.text, {
innerHTML: "<span class=\"file-info\"></span>"
});
return FileInfo.format(Conf['fileInfo'], this, this.file.text.firstElementChild);
},
format: function(formatString, post, outputNode) {
var output;
output = [];
formatString.replace(/%(.)|[^%]+/g, function(s, c) {
output.push(c in FileInfo.formatters ? FileInfo.formatters[c].call(post) : {
innerHTML: E(s)
});
return '';
});
return $.extend(outputNode, {
innerHTML: output.map(function(x) {
return x.innerHTML;
}).join('')
});
},
formatters: {
t: function() {
return {
innerHTML: E(this.file.URL.match(/\d+\..+$/)[0])
};
},
T: function() {
return {
innerHTML: "<a href=\"" + E(this.file.URL) + "\" target=\"_blank\">" + FileInfo.formatters.t.call(this).innerHTML + "</a>"
};
},
l: function() {
return {
innerHTML: "<a href=\"" + E(this.file.URL) + "\" target=\"_blank\">" + FileInfo.formatters.n.call(this).innerHTML + "</a>"
};
},
L: function() {
return {
innerHTML: "<a href=\"" + E(this.file.URL) + "\" target=\"_blank\">" + FileInfo.formatters.N.call(this).innerHTML + "</a>"
};
},
n: function() {
var fullname, shortname;
fullname = this.file.name;
shortname = Build.shortFilename(this.file.name, this.isReply);
if (fullname === shortname) {
return {
innerHTML: E(fullname)
};
} else {
return {
innerHTML: "<span class=\"fnswitch\"><span class=\"fntrunc\">" + E(shortname) + "</span><span class=\"fnfull\">" + E(fullname) + "</span></span>"
};
}
},
N: function() {
return {
innerHTML: E(this.file.name)
};
},
p: function() {
if (this.file.isSpoiler) {
return {
innerHTML: "Spoiler, "
};
} else {
return {
innerHTML: ""
};
}
},
s: function() {
return {
innerHTML: E(this.file.size)
};
},
B: function() {
return {
innerHTML: E(Math.round(this.file.sizeInBytes)) + " Bytes"
};
},
K: function() {
return {
innerHTML: E(Math.round(this.file.sizeInBytes/1024)) + " KB"
};
},
M: function() {
return {
innerHTML: E(Math.round(this.file.sizeInBytes/1048576*100)/100) + " MB"
};
},
r: function() {
return {
innerHTML: E(this.file.dimensions || "PDF")
};
},
'%': function() {
return {
innerHTML: "%"
};
}
}
};
Fourchan = {
init: function() {
var _ref;
if ((_ref = g.VIEW) !== 'index' && _ref !== 'thread') {
return;
}
if (g.BOARD.ID === 'g') {
$.globalEval('window.addEventListener(\'prettyprint\', function(e) {\n window.dispatchEvent(new CustomEvent(\'prettyprint:cb\', {\n detail: prettyPrintOne(e.detail)\n }));\n}, false);');
Post.callbacks.push({
name: 'Parse /g/ code',
cb: this.code
});
}
if (g.BOARD.ID === 'sci') {
$.globalEval('window.addEventListener(\'jsmath\', function(e) {\n if (!jsMath) return;\n if (jsMath.loaded) {\n // process one post\n jsMath.ProcessBeforeShowing(e.target);\n } else if (jsMath.Autoload && jsMath.Autoload.checked) {\n // load jsMath and process whole document\n jsMath.Autoload.Script.Push(\'ProcessBeforeShowing\', [null]);\n jsMath.Autoload.LoadJsMath();\n }\n}, false);');
Post.callbacks.push({
name: 'Parse /sci/ math',
cb: this.math
});
CatalogThread.callbacks.push({
name: 'Parse /sci/ math',
cb: this.math
});
}
return Main.ready(function() {
return $.globalEval('(function() {\n window.clickable_ids = false;\n var nodes = document.querySelectorAll(\'.posteruid, .capcode\');\n for (var i = 0; i < nodes.length; i++) {\n nodes[i].removeEventListener("click", window.idClick, false);\n }\n window.removeEventListener("message", Report.onMessage, false);\n})();');
});
},
code: function() {
var apply, pre, _i, _len, _ref;
if (this.isClone) {
return;
}
apply = function(e) {
pre.innerHTML = e.detail;
return $.addClass(pre, 'prettyprinted');
};
$.on(window, 'prettyprint:cb', apply);
_ref = $$('.prettyprint:not(.prettyprinted)', this.nodes.comment);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
pre = _ref[_i];
$.event('prettyprint', pre.innerHTML, window);
}
$.off(window, 'prettyprint:cb', apply);
},
math: function() {
if ((this.isClone && doc.contains(this.origin.nodes.root)) || !$('.math', this.nodes.comment)) {
return;
}
return $.asap(((function(_this) {
return function() {
return doc.contains(_this.nodes.comment);
};
})(this)), (function(_this) {
return function() {
return $.event('jsmath', null, _this.nodes.comment);
};
})(this));
}
};
IDColor = {
init: function() {
var _ref;
if (!(((_ref = g.VIEW) === 'index' || _ref === 'thread') && Conf['Color User IDs'])) {
return;
}
this.ids = {
Heaven: [0, 0, 0, '#fff']
};
return Post.callbacks.push({
name: 'Color User IDs',
cb: this.node
});
},
node: function() {
var rgb, span, style, uid;
if (this.isClone || !((uid = this.info.uniqueID) && (span = $('span.hand', this.nodes.uniqueID)))) {
return;
}
rgb = IDColor.ids[uid] || IDColor.compute(uid);
style = span.style;
style.color = rgb[3];
style.backgroundColor = "rgb(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + ")";
return $.addClass(span, 'painted');
},
compute: function(uid) {
var hash, rgb;
hash = IDColor.hash(uid);
rgb = [(hash >> 24) & 0xFF, (hash >> 16) & 0xFF, (hash >> 8) & 0xFF];
rgb.push((rgb[0] * 0.299 + rgb[1] * 0.587 + rgb[2] * 0.114) > 125 ? '#000' : '#fff');
return this.ids[uid] = rgb;
},
hash: function(uid) {
var i, msg;
msg = 0;
i = 0;
while (i < 8) {
msg = (msg << 5) - msg + uid.charCodeAt(i++);
}
return msg;
}
};
IDHighlight = {
init: function() {
var _ref;
if ((_ref = g.VIEW) !== 'index' && _ref !== 'thread') {
return;
}
return Post.callbacks.push({
name: 'Highlight by User ID',
cb: this.node
});
},
uniqueID: null,
node: function() {
if (this.nodes.uniqueID) {
$.on(this.nodes.uniqueID, 'click', IDHighlight.click(this));
}
if (this.nodes.capcode) {
$.on(this.nodes.capcode, 'click', IDHighlight.click(this));
}
if (!this.isClone) {
return IDHighlight.set(this);
}
},
set: function(post) {
var match;
match = (post.info.uniqueID || post.info.capcode) === IDHighlight.uniqueID;
return $[match ? 'addClass' : 'rmClass'](post.nodes.post, 'highlight');
},
click: function(post) {
return function() {
var uniqueID;
uniqueID = post.info.uniqueID || post.info.capcode;
IDHighlight.uniqueID = IDHighlight.uniqueID === uniqueID ? null : uniqueID;
return g.posts.forEach(IDHighlight.set);
};
}
};
Keybinds = {
init: function() {
var hotkey, init;
if (!Conf['Keybinds']) {
return;
}
for (hotkey in Conf.hotkeys) {
$.sync(hotkey, Keybinds.sync);
}
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);
},
sync: function(key, hotkey) {
return Conf[hotkey] = key;
},
keydown: function(e) {
var form, key, notification, notifications, op, searchInput, target, thread, threadRoot, _i, _len, _ref, _ref1, _ref2, _ref3, _ref4, _ref5;
if (!(key = Keybinds.keyCode(e))) {
return;
}
target = e.target;
if ((_ref = target.nodeName) === 'INPUT' || _ref === 'TEXTAREA') {
if (!/(Esc|Alt|Ctrl|Meta|Shift\+\w{2,})/.test(key)) {
return;
}
}
if (!(((_ref1 = g.VIEW) !== 'index' && _ref1 !== 'thread') || g.VIEW === 'index' && Conf['JSON Navigation'] && Conf['Index Mode'] === 'catalog')) {
threadRoot = Nav.getThread();
if (op = $('.op', threadRoot)) {
thread = Get.postFromNode(op).thread;
}
}
switch (key) {
case Conf['Toggle board list']:
if (!Conf['Custom Board Navigation']) {
return;
}
Header.toggleBoardList();
break;
case Conf['Toggle header']:
Header.toggleBarVisibility();
break;
case Conf['Open empty QR']:
if (!QR.postingIsEnabled) {
return;
}
Keybinds.qr();
break;
case Conf['Open QR']:
if (!(QR.postingIsEnabled && threadRoot)) {
return;
}
Keybinds.qr(threadRoot);
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 && !(QR.nodes.el.hidden || window.getComputedStyle(QR.nodes.form).display === 'none')) {
if (Conf['Persistent QR']) {
QR.hide();
} else {
QR.close();
}
} else if (Embedding.lastEmbed) {
Embedding.closeFloat();
} else {
return;
}
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 && !QR.nodes.el.hidden)) {
return;
}
Keybinds.sage();
break;
case Conf['Submit QR']:
if (!(QR.nodes && !QR.nodes.el.hidden)) {
return;
}
if (!QR.status()) {
QR.submit();
}
break;
case Conf['Update']:
switch (g.VIEW) {
case 'thread':
if (!Conf['Thread Updater']) {
return;
}
ThreadUpdater.update();
break;
case 'index':
if (!Conf['JSON Navigation']) {
return;
}
Index.update();
break;
default:
return;
}
break;
case Conf['Watch']:
if (!thread) {
return;
}
ThreadWatcher.toggle(thread);
break;
case Conf['Expand image']:
if (!(ImageExpand.enabled && threadRoot)) {
return;
}
Keybinds.img(threadRoot);
break;
case Conf['Expand images']:
if (!(ImageExpand.enabled && threadRoot)) {
return;
}
Keybinds.img(threadRoot, true);
break;
case Conf['Open Gallery']:
if (!Gallery.enabled) {
return;
}
Gallery.cb.toggle();
break;
case Conf['fappeTyme']:
if (!(Conf['Fappe Tyme'] && ((_ref2 = g.VIEW) === 'index' || _ref2 === 'thread') && g.BOARD.ID !== 'f')) {
return;
}
FappeTyme.toggle('fappe');
break;
case Conf['werkTyme']:
if (!(Conf['Werk Tyme'] && ((_ref3 = g.VIEW) === 'index' || _ref3 === 'thread') && g.BOARD.ID !== 'f')) {
return;
}
FappeTyme.toggle('werk');
break;
case Conf['Front page']:
if (Conf['JSON Navigation'] && g.VIEW === 'index') {
Index.userPageNav(1);
} else {
window.location = "/" + g.BOARD + "/";
}
break;
case Conf['Open front page']:
$.open("/" + g.BOARD + "/");
break;
case Conf['Next page']:
if (g.VIEW !== 'index') {
return;
}
if (Conf['JSON Navigation']) {
if ((_ref4 = Conf['Index Mode']) !== 'paged' && _ref4 !== 'infinite') {
return;
}
$('.next button', Index.pagelist).click();
} else {
if (form = $('.next form')) {
window.location = form.action;
}
}
break;
case Conf['Previous page']:
if (g.VIEW !== 'index') {
return;
}
if (Conf['JSON Navigation']) {
if ((_ref5 = Conf['Index Mode']) !== 'paged' && _ref5 !== 'infinite') {
return;
}
$('.prev button', Index.pagelist).click();
} else {
if (form = $('.prev form')) {
window.location = form.action;
}
}
break;
case Conf['Search form']:
if (g.VIEW !== 'index') {
return;
}
searchInput = Conf['JSON Navigation'] ? Index.searchInput : $.id('search-box');
Header.scrollToIfNeeded(searchInput);
searchInput.focus();
break;
case Conf['Paged mode']:
if (!Conf['JSON Navigation']) {
return;
}
window.location = g.VIEW === 'index' ? '#paged' : "/" + g.BOARD + "/#paged";
break;
case Conf['Infinite scrolling mode']:
if (!Conf['JSON Navigation']) {
return;
}
window.location = g.VIEW === 'index' ? '#infinite' : "/" + g.BOARD + "/#infinite";
break;
case Conf['All pages mode']:
if (!Conf['JSON Navigation']) {
return;
}
window.location = g.VIEW === 'index' ? '#all-pages' : "/" + g.BOARD + "/#all-pages";
break;
case Conf['Open catalog']:
window.location = CatalogLinks.catalog();
break;
case Conf['Cycle sort type']:
if (!(Conf['JSON Navigation'] && g.VIEW === 'index' && g.BOARD !== 'f')) {
return;
}
Index.cycleSortType();
break;
case Conf['Next thread']:
if (!(g.VIEW === 'index' && threadRoot)) {
return;
}
Nav.scroll(+1);
break;
case Conf['Previous thread']:
if (!(g.VIEW === 'index' && threadRoot)) {
return;
}
Nav.scroll(-1);
break;
case Conf['Expand thread']:
if (!(g.VIEW === 'index' && threadRoot)) {
return;
}
ExpandThread.toggle(thread);
break;
case Conf['Open thread']:
if (!(g.VIEW === 'index' && threadRoot)) {
return;
}
Keybinds.open(thread);
break;
case Conf['Open thread tab']:
if (!(g.VIEW === 'index' && threadRoot)) {
return;
}
Keybinds.open(thread, true);
break;
case Conf['Next reply']:
if (!threadRoot) {
return;
}
Keybinds.hl(+1, threadRoot);
break;
case Conf['Previous reply']:
if (!threadRoot) {
return;
}
Keybinds.hl(-1, threadRoot);
break;
case Conf['Deselect reply']:
if (!threadRoot) {
return;
}
Keybinds.hl(0, threadRoot);
break;
case Conf['Hide']:
if (!thread) {
return;
}
if (ThreadHiding.db) {
ThreadHiding.toggle(thread);
}
break;
case Conf['Previous Post Quoting You']:
if (!threadRoot) {
return;
}
QuoteYou.cb.seek('preceding');
break;
case Conf['Next Post Quoting You']:
if (!threadRoot) {
return;
}
QuoteYou.cb.seek('following');
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) {
QR.open();
if (thread != null) {
QR.quote.call($('input', $('.post.highlight', thread) || thread));
}
return QR.nodes.com.focus();
},
tags: function(tag, ta) {
var range, selEnd, selStart, supported, value;
supported = (function() {
switch (tag) {
case 'spoiler':
return !!$('.postForm input[name=spoiler]');
case 'code':
return g.BOARD.ID === 'g';
case 'math':
case 'eqn':
return g.BOARD.ID === 'sci';
}
})();
if (!supported) {
new Notice('warning', "[" + tag + "] tags are not supported on /" + g.BOARD + "/.", 20);
}
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 + "/thread/" + thread;
if (tab) {
return $.open(url);
} else {
return location.href = url;
}
},
hl: function(delta, thread) {
var axis, height, next, postEl, replies, reply, root, _i, _len;
postEl = $('.reply.highlight', thread);
if (!delta) {
if (postEl) {
$.rmClass(postEl, 'highlight');
}
return;
}
if (postEl) {
height = postEl.getBoundingClientRect().height;
if (Header.getTopOf(postEl) >= -height && Header.getBottomOf(postEl) >= -height) {
root = postEl.parentNode;
axis = delta === +1 ? 'following' : 'preceding';
if (!(next = $.x("" + axis + "-sibling::div[contains(@class,'replyContainer') and not(@hidden) and not(child::div[@class='stub'])][1]/child::div[contains(@class,'reply')]", root))) {
return;
}
Header.scrollToIfNeeded(next, delta === +1);
this.focus(next);
$.rmClass(postEl, 'highlight');
return;
}
$.rmClass(postEl, 'highlight');
}
replies = $$('.reply', thread);
if (delta === -1) {
replies.reverse();
}
for (_i = 0, _len = replies.length; _i < _len; _i++) {
reply = replies[_i];
if (delta === +1 && Header.getTopOf(reply) > 0 || delta === -1 && Header.getBottomOf(reply) > 0) {
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() {
var thread, threadRoot, _i, _len, _ref;
_ref = $$('.thread');
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
threadRoot = _ref[_i];
thread = Get.threadFromRoot(threadRoot);
if (thread.isHidden && !thread.stub) {
continue;
}
if (Header.getTopOf(threadRoot) >= -threadRoot.getBoundingClientRect().height) {
return threadRoot;
}
}
return $('.board');
},
scroll: function(delta) {
var axis, extra, next, thread, top, _ref;
if ((_ref = d.activeElement) != null) {
_ref.blur();
}
thread = Nav.getThread();
axis = delta === +1 ? 'following' : 'preceding';
if (next = $.x("" + axis + "-sibling::div[contains(@class,'thread') and not(@hidden)][1]", thread)) {
top = Header.getTopOf(thread);
if (delta === +1 && top < 5 || delta === -1 && top > -5) {
thread = next;
}
}
extra = Header.getTopOf(thread) + doc.clientHeight - d.body.getBoundingClientRect().bottom;
if (extra > 0) {
d.body.style.marginBottom = "" + extra + "px";
}
Header.scrollTo(thread);
if (extra > 0 && !Nav.haveExtra) {
Nav.haveExtra = true;
return $.on(d, 'scroll', Nav.removeExtra);
}
},
removeExtra: function() {
var extra;
extra = doc.clientHeight - d.body.getBoundingClientRect().bottom;
if (extra > 0) {
return d.body.style.marginBottom = "" + extra + "px";
} else {
d.body.style.marginBottom = null;
delete Nav.haveExtra;
return $.off(d, 'scroll', Nav.removeExtra);
}
}
};
RelativeDates = {
INTERVAL: $.MINUTE / 2,
init: function() {
var _ref;
if (((_ref = g.VIEW) === 'index' || _ref === 'thread') && Conf['Relative Post Dates'] && !Conf['Relative Date Title'] || g.VIEW === 'index' && Conf['JSON Navigation'] && g.BOARD.ID !== 'f') {
this.flush();
$.on(d, 'visibilitychange ThreadUpdate', this.flush);
}
if (Conf['Relative Post Dates']) {
return Post.callbacks.push({
name: 'Relative Post Dates',
cb: this.node
});
}
},
node: function() {
var dateEl;
dateEl = this.nodes.date;
if (Conf['Relative Date Title']) {
$.on(dateEl, 'mouseover', (function(_this) {
return function() {
return RelativeDates.hover(_this);
};
})(this));
return;
}
if (this.isClone) {
return;
}
dateEl.title = dateEl.textContent;
return RelativeDates.update(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 * years) > 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 data, now, _i, _len, _ref;
if (d.hidden) {
return;
}
now = new Date();
_ref = RelativeDates.stale;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
data = _ref[_i];
RelativeDates.update(data, now);
}
RelativeDates.stale = [];
clearTimeout(RelativeDates.timeout);
return RelativeDates.timeout = setTimeout(RelativeDates.flush, RelativeDates.INTERVAL);
},
hover: function(post) {
var date, diff, now;
date = post.info.date;
now = new Date();
diff = now - date;
return post.nodes.date.title = RelativeDates.relative(diff, now, date);
},
update: function(data, now) {
var date, diff, isPost, relative, singlePost, _i, _len, _ref;
isPost = data instanceof Post;
date = isPost ? data.info.date : new Date(+data.dataset.utc);
now || (now = new Date());
diff = now - date;
relative = RelativeDates.relative(diff, now, date);
if (isPost) {
_ref = [data].concat(data.clones);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
singlePost = _ref[_i];
singlePost.nodes.date.firstChild.textContent = relative;
}
} else {
data.firstChild.textContent = relative;
}
return RelativeDates.setOwnTimeout(diff, data);
},
setOwnTimeout: function(diff, data) {
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(RelativeDates.markStale, delay, data);
},
markStale: function(data) {
if (__indexOf.call(RelativeDates.stale, data) >= 0) {
return;
}
if (data instanceof Post && !g.posts[data.fullID]) {
return;
}
return RelativeDates.stale.push(data);
}
};
RemoveSpoilers = {
init: function() {
if (Conf['Reveal Spoilers']) {
$.addClass(doc, 'reveal-spoilers');
}
if (!Conf['Remove Spoilers']) {
return;
}
Post.callbacks.push({
name: 'Reveal Spoilers',
cb: this.node
});
CatalogThread.callbacks.push({
name: 'Reveal Spoilers',
cb: this.node
});
if (g.VIEW === 'archive') {
return $.ready(function() {
return RemoveSpoilers.unspoiler($.id('arc-list'));
});
}
},
node: function(post) {
return RemoveSpoilers.unspoiler(this.nodes.comment);
},
unspoiler: function(el) {
var span, spoiler, spoilers, _i, _len;
spoilers = $$('s', el);
for (_i = 0, _len = spoilers.length; _i < _len; _i++) {
spoiler = spoilers[_i];
span = $.el('span', {
className: 'removed-spoiler'
});
$.replace(spoiler, span);
$.add(span, __slice.call(spoiler.childNodes));
}
}
};
Time = {
init: function() {
var _ref;
if (!(((_ref = g.VIEW) === 'index' || _ref === 'thread') && Conf['Time Formatting'])) {
return;
}
return Post.callbacks.push({
name: 'Time Formatting',
cb: this.node
});
},
node: function() {
if (this.isClone) {
return;
}
return this.nodes.date.textContent = Time.format(Conf['time'], this.info.date);
},
format: function(formatString, date) {
return formatString.replace(/%(.)/g, function(s, c) {
if (c in Time.formatters) {
return Time.formatters[c].call(date);
} else {
return s;
}
});
},
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().toString().slice(2);
},
Y: function() {
return this.getFullYear();
},
'%': function() {
return '%';
}
}
};
Settings = {
init: function() {
var add, link, settings;
link = $.el('a', {
className: 'settings-link fa fa-wrench',
textContent: 'Settings',
title: '4chan X Settings',
href: 'javascript:;'
});
$.on(link, 'click', Settings.open);
Header.addShortcut(link);
add = this.addSection;
add('Main', this.main);
add('Filter', this.filter);
add('Sauce', this.sauce);
add('Advanced', this.advanced);
add('Keybinds', this.keybinds);
$.on(d, 'AddSettingsSection', Settings.addSection);
$.on(d, 'OpenSettings', function(e) {
return Settings.open(e.detail);
});
if (Conf['Disable Native Extension']) {
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, link, links, overlay, section, sectionToOpen, _i, _len, _ref;
if (Settings.overlay) {
return;
}
$.event('CloseMenu');
Settings.dialog = dialog = $.el('div', {
id: 'fourchanx-settings',
className: 'dialog'
});
$.extend(dialog, {
innerHTML: "<nav><div class=sections-list></div><p class='imp-exp-result warning'></p><div class=credits><a class=export>Export</a> | <a class=import>Import</a> | <a class=reset>Reset Settings</a> | <input type=file hidden><a href='https://github.com/ccd0/4chan-x' target=_blank>4chan X</a> | <a href='https://github.com/ccd0/4chan-x/blob/master/CHANGELOG.md' target=_blank></a> | <a href='https://github.com/ccd0/4chan-x/issues' target=_blank>Issues</a> | <a href=javascript:; class='close fa fa-times' title=Close></a></div></nav><div class=section-container><section></section></div>"
});
$('a[href$="/CHANGELOG.md"]', dialog).textContent = g.VERSION;
Settings.overlay = overlay = $.el('div', {
id: 'overlay'
});
$.on($('.export', dialog), 'click', Settings["export"]);
$.on($('.import', dialog), 'click', Settings["import"]);
$.on($('.reset', dialog), 'click', Settings.reset);
$.on($('input', 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);
if (openSection !== 'none') {
(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() {
var _ref;
if (!Settings.dialog) {
return;
}
if ((_ref = d.activeElement) != null) {
_ref.blur();
}
$.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, container, containers, description, div, fs, input, inputs, items, key, level, obj, _ref;
items = {};
inputs = {};
_ref = Config.main;
for (key in _ref) {
obj = _ref[key];
fs = $.el('fieldset', {
innerHTML: "<legend>" + E(key) + "</legend>"
});
containers = [fs];
for (key in obj) {
arr = obj[key];
description = arr[1];
div = $.el('div', {
innerHTML: "<label><input type=\"checkbox\" name=\"" + E(key) + "\">" + E(key) + "</label><span class=\"description\">: " + E(description) + "</span>"
});
input = $('input', div);
$.on(input, 'change', function() {
this.parentNode.parentNode.dataset.checked = this.checked;
return $.cb.checked.call(this);
});
items[key] = Conf[key];
inputs[key] = input;
level = arr[2] || 0;
if (containers.length <= level) {
container = $.el('div', {
className: 'suboption-list'
});
$.add(containers[containers.length - 1].lastElementChild, container);
containers[level] = container;
} else if (containers.length > level + 1) {
containers.splice(level + 1, containers.length - (level + 1));
}
$.add(containers[level], div);
}
$.add(section, fs);
}
$.get(items, function(items) {
var val;
for (key in items) {
val = items[key];
inputs[key].checked = val;
inputs[key].parentNode.parentNode.dataset.checked = val;
}
});
div = $.el('div', {
innerHTML: "<button></button><span class=\"description\">: Clear manually-hidden threads and posts on all boards. Reload the page to apply."
});
button = $('button', div);
$.get({
hiddenThreads: {},
hiddenPosts: {}
}, function(_arg) {
var ID, board, hiddenNum, hiddenPosts, hiddenThreads, thread, _ref1, _ref2;
hiddenThreads = _arg.hiddenThreads, hiddenPosts = _arg.hiddenPosts;
hiddenNum = 0;
_ref1 = hiddenThreads.boards;
for (ID in _ref1) {
board = _ref1[ID];
hiddenNum += Object.keys(board).length;
}
_ref2 = hiddenPosts.boards;
for (ID in _ref2) {
board = _ref2[ID];
for (ID in board) {
thread = board[ID];
hiddenNum += Object.keys(thread).length;
}
}
return button.textContent = "Hidden: " + hiddenNum;
});
$.on(button, 'click', function() {
this.textContent = 'Hidden: 0';
return $.get('hiddenThreads', {}, function(_arg) {
var boardID, hiddenThreads;
hiddenThreads = _arg.hiddenThreads;
for (boardID in hiddenThreads.boards) {
localStorage.removeItem("4chan-hide-t-" + boardID);
}
return $["delete"](['hiddenThreads', 'hiddenPosts']);
});
});
return $.after($('input[name="Stubs"]', section).parentNode.parentNode, div);
},
"export": function() {
return $.get(Conf, function(Conf) {
delete Conf['archives'];
return Settings.downloadExport({
version: g.VERSION,
date: Date.now(),
Conf: Conf
});
});
},
downloadExport: function(data) {
var a, p;
a = $.el('a', {
download: "4chan X v" + g.VERSION + "-" + data.date + ".json",
href: "data:application/json;base64," + (btoa(unescape(encodeURIComponent(JSON.stringify(data, null, 2)))))
});
p = $('.imp-exp-result', Settings.dialog);
$.rmAll(p);
$.add(p, a);
return a.click();
},
"import": function() {
return $('input[type=file]', this.parentNode).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 err;
try {
Settings.loadSettings(JSON.parse(e.target.result));
if (confirm('Import successful. Reload 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 convertSettings, key, val, version, _ref;
version = data.version.split('.');
if (version[0] === '2') {
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;
};
data = convertSettings(data, {
'Disable 4chan\'s extension': '',
'Remove Slug': '',
'Check for Updates': '',
'Recursive Filtering': 'Recursive Hiding',
'Reply Hiding': 'Reply Hiding Buttons',
'Thread Hiding': 'Thread Hiding Buttons',
'Show Stubs': 'Stubs',
'Image Auto-Gif': 'Replace GIF',
'Reveal Spoilers': 'Reveal Spoiler Thumbnails',
'Expand From Current': 'Expand from here',
'Post in Title': 'Thread Excerpt',
'Open Reply in New Tab': 'Open Post in New Tab',
'Remember QR size': 'Remember QR Size',
'Remember Subject': '',
'Quote Inline': 'Quote Inlining',
'Quote Preview': 'Quote Previewing',
'Indicate OP quote': 'Mark OP Quotes',
'Indicate You quote': 'Mark Quotes of You',
'Indicate Cross-thread Quotes': 'Mark Cross-thread Quotes',
'uniqueid': 'uniqueID',
'mod': 'capcode',
'email': '',
'country': 'flag',
'md5': 'MD5',
'openEmptyQR': 'Open empty QR',
'openQR': 'Open QR',
'openOptions': 'Open settings',
'close': 'Close',
'spoiler': 'Spoiler tags',
'sageru': 'Toggle sage',
'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) {
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;
}
if (data.Conf['WatchedThreads']) {
data.Conf['watchedThreads'] = {
boards: ThreadWatcher.convert(data.Conf['WatchedThreads'])
};
delete data.Conf['WatchedThreads'];
}
return $.clear(function() {
return $.set(data.Conf);
});
},
reset: function() {
if (confirm('Your current settings will be entirely wiped, are you sure?')) {
return $.clear(function() {
if (confirm('Reset successful. Reload now?')) {
return window.location.reload();
}
});
}
},
filter: function(section) {
var select;
$.extend(section, {
innerHTML: "<select name=filter><option value=guide>Guide</option><option value=name>Name</option><option value=uniqueID>Unique ID</option><option value=tripcode>Tripcode</option><option value=capcode>Capcode</option><option value=subject>Subject</option><option value=comment>Comment</option><option value=flag>Flag</option><option value=filename>Filename</option><option value=dimensions>Image dimensions</option><option value=filesize>Filesize</option><option value=MD5>Image MD5</option></select><div></div>"
});
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;
}
$.extend(div, {
innerHTML: "<div class=warning><code>Filter</code> is disabled.</div><p>Use <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions\">regular expressions</a>, one per line.<br>Lines starting with a <code>#</code> will be ignored.<br>For example, <code>/weeaboo/i</code> will filter posts containing the string `<code>weeaboo</code>`, case-insensitive.<br>MD5 filtering uses exact string matching, not regular expressions.</p><ul>You can use these settings with each regular expression, separate them with semicolons:<li>Per boards, separate them with commas. It is global if not specified.<br>For example: <code>boards:a,jp;</code>.</li><li>Filter OPs only along with their threads (`only`), replies only (`no`), or both (`yes`, this is default).<br>For example: <code>op:only;</code>, <code>op:no;</code> or <code>op:yes;</code>.</li><li>Overrule the `Show Stubs` setting if specified: create a stub (`yes`) or not (`no`).<br>For example: <code>stub:yes;</code> or <code>stub:no;</code>.</li><li>Highlight instead of hiding. You can specify a class name to use with a userstyle.<br>For example: <code>highlight;</code> or <code>highlight:wallpaper;</code>.</li><li>Highlighted OPs will have their threads put on top of the board index by default.<br>For example: <code>top:yes;</code> or <code>top:no;</code>.</li></ul><p>Note: If you're using the native catalog rather than 4chan X's catalog, 4chan X's filters do not apply there.<br>The native catalog has its own separate filter list.</p>"
});
return $('.warning', div).hidden = Conf['Filter'];
},
sauce: function(section) {
var ta;
$.extend(section, {
innerHTML: "<div class=\"warning\"><code>Sauce</code> is disabled.</div><div>Lines starting with a <code>#</code> will be ignored.</div><div>You can specify a display text by appending <code>;text:[text]</code> to the URL.</div><div>You can specify the applicable boards by appending <code>;boards:[board1],[board2]</code>.</div><div>You can specify the applicable file types by appending <code>;types:[extension1],[extension2]</code>.</div><ul>These parameters will be replaced by their corresponding values:<li><code>%TURL</code>: Thumbnail URL.</li><li><code>%URL</code>: Full image URL.</li><li><code>%MD5</code>: MD5 hash.</li><li><code>%name</code>: Original file name.</li><li><code>%board</code>: Current board.</li><li><code>%%</code>, <code>%semi</code>: Literal <code>%</code> and <code>;</code>.</li></ul><textarea name=\"sauces\" class=\"field\" spellcheck=\"false\"></textarea>"
});
$('.warning', section).hidden = Conf['Sauce'];
ta = $('textarea', section);
$.get('sauces', Conf['sauces'], function(item) {
return ta.value = item['sauces'];
});
return $.on(ta, 'change', $.cb.value);
},
advanced: function(section) {
var applyCSS, archBoards, boardID, boardOptions, boardSelect, boards, customCSS, files, i, input, inputs, interval, item, items, name, o, row, rows, software, ta, table, warning, withCredentials, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _len5, _len6, _m, _n, _o, _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6;
$.extend(section, {
innerHTML: "<fieldset><legend>Archiver</legend><div class=\"warning\" data-feature='404 Redirect'><code>404 Redirect</code> is disabled.</div><select id='archive-board-select'></select><table id='archive-table'><thead><th>Thread redirection</th><th>Post fetching</th><th>File redirection</th></thead><tbody></tbody></table></fieldset><fieldset><legend>Custom Board Navigation</legend><div><textarea name=boardnav class=field spellcheck=false></textarea></div><span class=note>New lines will be converted into spaces.</span><br><br><div class=note>In the following examples for /g/, <code>g</code> can be changed to a different board ID (<code>a</code>, <code>b</code>, etc...), the current board (<code>current</code>), or the Twitter link (<code>@</code>).</div><div>Board link: <code>g</code></div><div>Archive link: <code>g-archive</code></div><div>Internal archive link: <code>g-expired</code></div><div>Title link: <code>g-title</code></div><div>Board link (Replace with title when on that board): <code>g-replace</code></div><div>Full text link: <code>g-full</code></div><div>Custom text link: <code>g-text:\"Install Gentoo\"</code></div><div>Index-only link: <code>g-index</code></div><div>Catalog-only link: <code>g-catalog</code></div><div>External link: <code>external-text:\"Google\",\"http://www.google.com\"</code></div><div>Combinations are possible: <code>g-index-text:\"Technology Index\"</code></div><div>Full board list toggle: <code>toggle-all</code></div><br><div class=note><code>[ toggle-all ] [current-title] [g-title / a-title / jp-title] [x / wsg / h] [t-text:\"Piracy\"]</code><br>will give you<br><code>[ + ] [Technology] [Technology / Anime & Manga / Otaku Culture] [x / wsg / h] [Piracy]</code><br>if you are on /g/.</div></fieldset><fieldset><legend>Time Formatting <span class=warning data-feature='Time Formatting'>is disabled.</span></legend><div><input name=time class=field spellcheck=false>: <span class=time-preview></span></div><div>Supported <a href=//en.wikipedia.org/wiki/Date_%28Unix%29#Formatting>format specifiers</a>:</div><div>Day: <code>%a</code>, <code>%A</code>, <code>%d</code>, <code>%e</code></div><div>Month: <code>%m</code>, <code>%b</code>, <code>%B</code></div><div>Year: <code>%y</code>, <code>%Y</code></div><div>Hour: <code>%k</code>, <code>%H</code>, <code>%l</code>, <code>%I</code>, <code>%p</code>, <code>%P</code></div><div>Minute: <code>%M</code></div><div>Second: <code>%S</code></div><div>Literal <code>%</code>: <code>%%</code></div></fieldset><fieldset><legend>Quote Backlinks formatting <span class=warning data-feature='Quote Backlinks'>is disabled.</span></legend><div><input name=backlink class=field spellcheck=false>: <span class=backlink-preview></span></div></fieldset><fieldset><legend>File Info Formatting <span class=warning data-feature='File Info Formatting'>is disabled.</span></legend><div><input name=fileInfo class=field spellcheck=false>: <span class='file-info file-info-preview'></span></div><div>Link: <code>%l</code> (truncated), <code>%L</code> (untruncated), <code>%T</code> (Unix timestamp)</div><div>Original file name: <code>%n</code> (truncated), <code>%N</code> (untruncated), <code>%t</code> (Unix timestamp)</div><div>Spoiler indicator: <code>%p</code></div><div>Size: <code>%B</code> (Bytes), <code>%K</code> (KB), <code>%M</code> (MB), <code>%s</code> (4chan default)</div><div>Resolution: <code>%r</code> (Displays 'PDF' for PDF files)</div><div>Literal <code>%</code>: <code>%%</code></div></fieldset><fieldset><legend>Quick Reply Personas</legend><textarea class=\"personafield field\" name=\"QR.personas\" spellcheck=\"false\"></textarea><p>One item per line.<br>Items will be added in the relevant input's auto-completion list.<br>Password items will always be used, since there is no password input.<br>Lines starting with a <code>#</code> will be ignored.</p><ul>You can use these settings with each item, separate them with semicolons:<li>Possible items are: <code>name</code>, <code>options</code> (or equivalently <code>email</code>), <code>subject</code> and <code>password</code>.</li><li>Wrap values of items with quotes, like this: <code>options:\"sage\"</code>.</li><li>Force values as defaults with the <code>always</code> keyword, for example: <code>options:\"sage\";always</code>.</li><li>Select specific boards for an item, separated with commas, for example: <code>options:\"sage\";boards:jp;always</code>.</li></ul></fieldset><fieldset><legend>Unread Favicon <span class=warning data-feature='Unread Favicon'>is disabled.</span></legend><select name=favicon><option value=ferongr>ferongr</option><option value=xat->xat-</option><option value=4chanJS>4chanJS</option><option value=Mayhem>Mayhem</option><option value=Original>Original</option><option value=Metro>Metro</option></select><span class=favicon-preview><img src=\"data:image/gif;base64,R0lGODlhEAAQAPAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAIOhI%2Bpy%2B0Po5y02ouzPgUAOw%3D%3D\"><img src=\"data:image/gif;base64,R0lGODlhEAAQAPAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAIOhI%2Bpy%2B0Po5y02ouzPgUAOw%3D%3D\"><img src=\"data:image/gif;base64,R0lGODlhEAAQAPAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAIOhI%2Bpy%2B0Po5y02ouzPgUAOw%3D%3D\"><img src=\"data:image/gif;base64,R0lGODlhEAAQAPAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAIOhI%2Bpy%2B0Po5y02ouzPgUAOw%3D%3D\"></span></fieldset><fieldset><legend>Thread Updater <span class=warning data-feature='Thread Updater'>is disabled.</span></legend><div>Interval: <input type=\"number\" name=\"Interval\" class=\"field\" min=\"1\"> seconds</div></fieldset><fieldset><legend><label><input type=checkbox name='Custom CSS'> Custom CSS</label></legend><button id=apply-css>Apply CSS</button><textarea name=usercss class=field spellcheck=false></textarea></fieldset>"
});
_ref = $$('.warning', section);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
warning = _ref[_i];
warning.hidden = Conf[warning.dataset.feature];
}
items = {};
inputs = {};
_ref1 = ['boardnav', 'time', 'backlink', 'fileInfo', 'favicon', 'usercss'];
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
name = _ref1[_j];
input = $("[name='" + name + "']", section);
items[name] = Conf[name];
inputs[name] = input;
if (name === 'usercss') {
$.on(input, 'change', $.cb.value);
} else if (name === 'favicon') {
$.on(input, 'change', $.cb.value);
$.on(input, 'change', Settings[name]);
} else {
$.on(input, 'input', $.cb.value);
$.on(input, 'input', Settings[name]);
}
}
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];
input = inputs[key];
input.value = val;
if (key === 'usercss') {
continue;
}
Settings[key].call(input);
}
});
interval = $('input[name="Interval"]', section);
customCSS = $('input[name="Custom CSS"]', section);
applyCSS = $('#apply-css', section);
interval.value = Conf['Interval'];
customCSS.checked = Conf['Custom CSS'];
inputs['usercss'].disabled = !Conf['Custom CSS'];
applyCSS.disabled = !Conf['Custom CSS'];
$.on(interval, 'change', ThreadUpdater.cb.interval);
$.on(customCSS, 'change', Settings.togglecss);
$.on(applyCSS, 'click', Settings.usercss);
archBoards = {};
_ref2 = Redirect.archives;
for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
_ref3 = _ref2[_k], name = _ref3.name, boards = _ref3.boards, files = _ref3.files, software = _ref3.software, withCredentials = _ref3.withCredentials;
for (_l = 0, _len3 = boards.length; _l < _len3; _l++) {
boardID = boards[_l];
o = archBoards[boardID] || (archBoards[boardID] = {
thread: [[], []],
post: [[], []],
file: [[], []]
});
i = +(!!withCredentials);
o.thread[i].push(name);
if (software === 'foolfuuka') {
o.post[i].push(name);
}
if (__indexOf.call(files, boardID) >= 0) {
o.file[i].push(name);
}
}
}
for (boardID in archBoards) {
o = archBoards[boardID];
_ref4 = ['thread', 'post', 'file'];
for (_m = 0, _len4 = _ref4.length; _m < _len4; _m++) {
item = _ref4[_m];
i = o[item][0].length ? 1 : 0;
o[item][i].push('disabled');
o[item] = o[item][0].concat(o[item][1]);
}
}
rows = [];
boardOptions = [];
_ref5 = Object.keys(archBoards).sort();
for (_n = 0, _len5 = _ref5.length; _n < _len5; _n++) {
boardID = _ref5[_n];
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
}));
o = archBoards[boardID];
_ref6 = ['thread', 'post', 'file'];
for (_o = 0, _len6 = _ref6.length; _o < _len6; _o++) {
item = _ref6[_o];
$.add(row, Settings.addArchiveCell(boardID, o, item));
}
rows.push(row);
}
if (!(g.BOARD.ID in archBoards)) {
rows[0].hidden = false;
}
$.add($('tbody', section), rows);
boardSelect = $('#archive-board-select', section);
$.add(boardSelect, boardOptions);
table = $('#archive-table', section);
$.on(boardSelect, 'change', function() {
$('tbody > :not([hidden])', table).hidden = true;
return $("tbody > ." + this.value, table).hidden = false;
});
$.get('selectedArchives', Conf['selectedArchives'], function(_arg) {
var data, 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
}));
}
$.extend(td, {
innerHTML: "<select></select>"
});
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() {
return $.get('selectedArchives', Conf['selectedArchives'], (function(_this) {
return function(_arg) {
var selectedArchives, _name;
selectedArchives = _arg.selectedArchives;
(selectedArchives[_name = _this.dataset.boardid] || (selectedArchives[_name] = {}))[_this.dataset.type] = _this.value;
return $.set('selectedArchives', selectedArchives);
};
})(this));
},
boardnav: function() {
return Header.generateBoardList(this.value);
},
time: function() {
return this.nextElementSibling.textContent = Time.format(this.value, new Date());
},
backlink: function() {
return this.nextElementSibling.textContent = this.value.replace(/%(?:id|%)/g, function(x) {
return {
'%id': '123456789',
'%%': '%'
}[x];
});
},
fileInfo: function() {
var data;
data = {
isReply: true,
file: {
URL: '//i.4cdn.org/g/1334437723720.jpg',
name: 'd9bb2efc98dd0df141a94399ff5880b7.jpg',
size: '276 KB',
sizeInBytes: 276 * 1024,
dimensions: '1280x720',
isImage: true,
isSpoiler: true
}
};
return FileInfo.format(this.value, data, this.nextElementSibling);
},
favicon: function() {
var img;
Favicon["switch"]();
if (g.VIEW === 'thread' && Conf['Unread Favicon']) {
Unread.update();
}
img = this.nextElementSibling.children;
img[0].src = Favicon["default"];
img[1].src = Favicon.unreadSFW;
img[2].src = Favicon.unreadNSFW;
return img[3].src = Favicon.unreadDead;
},
togglecss: function() {
if ($('textarea[name=usercss]', $.x('ancestor::fieldset[1]', this)).disabled = $.id('apply-css').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;
$.extend(section, {
innerHTML: "<div class=warning><code>Keybinds</code> are disabled.</div><div>Allowed keys: <kbd>a-z</kbd>, <kbd>0-9</kbd>, <kbd>Ctrl</kbd>, <kbd>Shift</kbd>, <kbd>Alt</kbd>, <kbd>Meta</kbd>, <kbd>Enter</kbd>, <kbd>Esc</kbd>, <kbd>Up</kbd>, <kbd>Down</kbd>, <kbd>Right</kbd>, <kbd>Left</kbd>.</div><div>Press <kbd>Backspace</kbd> to disable a keybind.</div><table><tbody><tr><th>Actions</th><th>Keybinds</th></tr></tbody></table>"
});
$('.warning', section).hidden = Conf['Keybinds'];
tbody = $('tbody', section);
items = {};
inputs = {};
_ref = Config.hotkeys;
for (key in _ref) {
arr = _ref[key];
tr = $.el('tr', {
innerHTML: "<td>" + E(arr[1]) + "</td><td><input class=\"field\"></td>"
});
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() {
var db, flatten, pathname, _i, _len, _ref, _ref1;
if (location.hostname === 'www.google.com') {
return $.ready(function() {
return Captcha.noscript.initFrame();
});
}
g.threads = new SimpleDict();
g.posts = new SimpleDict();
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':
case 'thread':
return 'thread';
case 'catalog':
return 'catalog';
case 'archive':
return 'archive';
default:
return 'index';
}
})();
if (g.VIEW === 'thread') {
g.THREADID = +pathname[3];
}
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);
_ref1 = DataBoard.keys;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
db = _ref1[_i];
Conf[db] = {
boards: {}
};
}
Conf['selectedArchives'] = {};
$.get(Conf, function(items) {
$.extend(Conf, items);
return $.asap((function() {
return doc = d.documentElement;
}), Main.initFeatures);
});
return $.asap((function() {
return doc = d.documentElement;
}), function() {
return $.onExists(doc, 'body', false, Main.initStyle);
});
},
initFeatures: function() {
var err, feature, name, pathname, _i, _len, _ref, _ref1;
switch (location.hostname) {
case 'a.4cdn.org':
return;
case 'sys.4chan.org':
return;
case 'i.4cdn.org':
$.asap((function() {
return d.readyState !== 'loading';
}), function() {
var URL, pathname, video, _ref;
if (Conf['404 Redirect'] && ((_ref = d.title) === '4chan - Temporarily Offline' || _ref === '4chan - 404 Not Found')) {
Redirect.init();
pathname = location.pathname.split('/');
URL = Redirect.to('file', {
boardID: g.BOARD.ID,
filename: pathname[pathname.length - 1]
});
return Redirect.navigate(URL);
} else if (video = $('video')) {
if (Conf['Volume in New Tab']) {
Volume.setup(video);
}
if (Conf['Loop in New Tab']) {
video.loop = true;
video.controls = false;
video.play();
return ImageCommon.addControls(video);
}
}
});
return;
}
if (Conf['Normalize URL'] && g.VIEW === 'thread') {
pathname = location.pathname.split('/');
if (pathname[2] !== 'thread' || pathname.length > 4) {
pathname[2] = 'thread';
history.replaceState(null, '', pathname.slice(0, 4).join('/') + location.hash);
}
}
_ref = Main.features;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
_ref1 = _ref[_i], name = _ref1[0], feature = _ref1[1];
try {
feature.init();
} catch (_error) {
err = _error;
Main.handleErrors({
message: "\"" + name + "\" initialization crashed.",
error: err
});
}
}
return $.ready(Main.initReady);
},
initStyle: function() {
var _ref;
if (!Main.isThisPageLegit() || $.hasClass(doc, 'fourchan-x')) {
return;
}
if ((_ref = $('link[href*=mobile]', d.head)) != null) {
_ref.disabled = true;
}
$.addClass(doc, 'fourchan-x', 'seaweedchan');
$.addClass(doc, g.VIEW === 'thread' ? 'thread-view' : g.VIEW);
$.addClass(doc, typeof chrome !== "undefined" && chrome !== null ? 'blink' : 'gecko');
$.addStyle(Main.css, 'fourchanx-css');
return Main.setClass();
},
setClass: function() {
var mainStyleSheet, setStyle, style, styleSheets;
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;
}
return new MutationObserver(setStyle).observe(mainStyleSheet, {
attributes: true,
attributeFilter: ['href']
});
},
initReady: function() {
var GMver, err, href, i, passLink, styleSelector, v, _i, _len, _ref, _ref1;
if ((_ref = d.title) === '4chan - Temporarily Offline' || _ref === '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+/)
});
Redirect.navigate(href, "/" + g.BOARD + "/");
}
return;
}
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')]);
}
if (!(Conf['JSON Navigation'] && g.VIEW === 'index')) {
Main.initThread();
} else {
$.event('4chanXInitFinished');
}
$.get('previousversion', null, function(_arg) {
var el, previousversion;
previousversion = _arg.previousversion;
if (previousversion === g.VERSION) {
return;
}
if (previousversion) {
el = $.el('span', {
innerHTML: E(g.NAME) + " has been updated to <a href=\"" + E(g.CHANGELOG) + "\" target=\"_blank\">version " + E(g.VERSION) + "</a>."
});
new Notice('info', el, 15);
} else {
Settings.open();
}
return $.set('previousversion', g.VERSION);
});
if (Conf['Show Support Message']) {
GMver = GM_info.version.split('.');
_ref1 = "1.14".split('.');
for (i = _i = 0, _len = _ref1.length; _i < _len; i = ++_i) {
v = _ref1[i];
if (v === GMver[i]) {
continue;
}
(v < GMver[i]) || new Notice('warning', "Your version of Greasemonkey is outdated (v" + GM_info.version + " instead of v1.14 minimum) and 4chan X may not operate correctly.", 30);
break;
}
try {
return localStorage.getItem('4chan-settings');
} catch (_error) {
err = _error;
return new Notice('warning', 'Cookies need to be enabled on 4chan for 4chan X to operate properly.', 30);
}
}
},
initThread: function() {
var board, err, errors, m, postRoot, posts, scriptData, thread, threadRoot, threads, _i, _j, _len, _len1, _ref, _ref1;
if (board = $('.board')) {
threads = [];
posts = [];
_ref = $$('.board > .thread', board);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
threadRoot = _ref[_i];
thread = new Thread(+threadRoot.id.slice(1), g.BOARD);
threads.push(thread);
_ref1 = $$('.thread > .postContainer', threadRoot);
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
postRoot = _ref1[_j];
try {
posts.push(new Post(postRoot, thread, g.BOARD));
} catch (_error) {
err = _error;
if (!errors) {
errors = [];
}
errors.push({
message: "Parsing of Post No." + (postRoot.id.match(/\d+/)) + " failed. Post will be skipped.",
error: err
});
}
}
}
if (errors) {
Main.handleErrors(errors);
}
if (g.VIEW === 'thread') {
scriptData = Get.scriptData();
threads[0].postLimit = /\bbumplimit *= *1\b/.test(scriptData);
threads[0].fileLimit = /\bimagelimit *= *1\b/.test(scriptData);
threads[0].ipCount = (m = scriptData.match(/\bunique_ips *= *(\d+)\b/)) ? +m[1] : void 0;
}
Main.callbackNodes(Thread, threads);
return Main.callbackNodesDB(Post, posts, function() {
var post, _k, _len2;
for (_k = 0, _len2 = posts.length; _k < _len2; _k++) {
post = posts[_k];
QuoteThreading.insert(post);
}
return $.event('4chanXInitFinished');
});
} else {
return $.event('4chanXInitFinished');
}
},
callbackNodes: function(klass, nodes) {
var cb, i, node;
i = 0;
cb = klass.callbacks;
while (node = nodes[i++]) {
cb.execute(node);
}
},
callbackNodesDB: function(klass, nodes, cb) {
var cbs, fn, i, softTask;
i = 0;
cbs = klass.callbacks;
fn = function() {
var node;
if (!(node = nodes[i])) {
return false;
}
cbs.execute(node);
return ++i % 25;
};
softTask = function() {
while (fn()) {
continue;
}
if (!nodes[i]) {
if (cb) {
cb();
}
return;
}
return setTimeout(softTask, 0);
};
return softTask();
},
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 Notice('error', Main.parseError(error), 15);
return;
}
div = $.el('div', {
innerHTML: E(errors.length) + " errors occurred. [<a href=\"javascript:;\">show</a>]"
});
$.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 Notice('error', [div, logs], 30);
},
parseError: function(data) {
var error, message;
c.error(data.message, data.error.stack);
message = $.el('div', {
textContent: data.message
});
error = $.el('div', {
textContent: "" + (data.error.name || 'Error') + ": " + (data.error.message || 'see console for details')
});
return [message, error];
},
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' && _ref !== '504 Gateway Time-out');
}
return Main.thisPageIsLegit;
},
ready: function(cb) {
return $.ready(function() {
if (Main.isThisPageLegit()) {
return cb();
}
});
},
css: "/*! * Font Awesome 4.0.3 * the iconic font designed for Bootstrap * ------------------------------------------------------------------------------ * The full suite of pictographic icons, examples, and documentation can be * found at http://fontawesome.io. Stay up to date on Twitter at * http://twitter.com/fontawesome. * * License * ------------------------------------------------------------------------------ * - The Font Awesome font is licensed under SIL OFL 1.1 - * http://scripts.sil.org/OFL * - Font Awesome CSS, LESS, and SASS files are licensed under MIT License - * http://opensource.org/licenses/mit-license.html * - Font Awesome documentation licensed under CC BY 3.0 - * http://creativecommons.org/licenses/by/3.0/ * - Attribution is no longer required in Font Awesome 3.0, but much appreciated: * \"Font Awesome by Dave Gandy - http://fontawesome.io\" * * Author - Dave Gandy * ------------------------------------------------------------------------------ * Email: [email protected] * Twitter: http://twitter.com/davegandy * Work: Lead Product Designer @ Kyruus - http://kyruus.com */ @font-face{font-family:FontAwesome;src:url('data:application/font-woff;base64,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') format('woff');font-weight:400;font-style:normal}.fa::before{font-family:FontAwesome;font-weight:400;font-style:normal;-webkit-font-smoothing:antialiased;*margin-right:.3em;text-decoration:inherit;display:none;speak:none} .fa::before {display:inline-block;font-size:13px;visibility:visible} :root:not(.shortcut-icons) #shortcuts .fa::before {display:none} :root.shortcut-icons #shortcuts .fa::before{font-size:15px!important;margin-top:-3px!important;position:relative;top:1px} :root.shortcut-icons #shortcuts .fa, .menu-button .fa{font-size:0;visibility:hidden} :root.shortcut-icons .shortcut.brackets-wrap::after,:root.shortcut-icons .shortcut.brackets-wrap::before{display:none} :root.shortcut-icons #shortcuts a .fa, .menu-button .fa, .hide-reply-button .fa, .hide-thread-button .fa {display:inline} /* Update this line only */ .fa-glass:before{content:\"\\f000\"}.fa-music:before{content:\"\\f001\"}.fa-search:before{content:\"\\f002\"}.fa-envelope-o:before{content:\"\\f003\"}.fa-heart:before{content:\"\\f004\"}.fa-star:before{content:\"\\f005\"}.fa-star-o:before{content:\"\\f006\"}.fa-user:before{content:\"\\f007\"}.fa-film:before{content:\"\\f008\"}.fa-th-large:before{content:\"\\f009\"}.fa-th:before{content:\"\\f00a\"}.fa-th-list:before{content:\"\\f00b\"}.fa-check:before{content:\"\\f00c\"}.fa-times:before{content:\"\\f00d\"}.fa-search-plus:before{content:\"\\f00e\"}.fa-search-minus:before{content:\"\\f010\"}.fa-power-off:before{content:\"\\f011\"}.fa-signal:before{content:\"\\f012\"}.fa-gear:before,.fa-cog:before{content:\"\\f013\"}.fa-trash-o:before{content:\"\\f014\"}.fa-home:before{content:\"\\f015\"}.fa-file-o:before{content:\"\\f016\"}.fa-clock-o:before{content:\"\\f017\"}.fa-road:before{content:\"\\f018\"}.fa-download:before{content:\"\\f019\"}.fa-arrow-circle-o-down:before{content:\"\\f01a\"}.fa-arrow-circle-o-up:before{content:\"\\f01b\"}.fa-inbox:before{content:\"\\f01c\"}.fa-play-circle-o:before{content:\"\\f01d\"}.fa-rotate-right:before,.fa-repeat:before{content:\"\\f01e\"}.fa-refresh:before{content:\"\\f021\"}.fa-list-alt:before{content:\"\\f022\"}.fa-lock:before{content:\"\\f023\"}.fa-flag:before{content:\"\\f024\"}.fa-headphones:before{content:\"\\f025\"}.fa-volume-off:before{content:\"\\f026\"}.fa-volume-down:before{content:\"\\f027\"}.fa-volume-up:before{content:\"\\f028\"}.fa-qrcode:before{content:\"\\f029\"}.fa-barcode:before{content:\"\\f02a\"}.fa-tag:before{content:\"\\f02b\"}.fa-tags:before{content:\"\\f02c\"}.fa-book:before{content:\"\\f02d\"}.fa-bookmark:before{content:\"\\f02e\"}.fa-print:before{content:\"\\f02f\"}.fa-camera:before{content:\"\\f030\"}.fa-font:before{content:\"\\f031\"}.fa-bold:before{content:\"\\f032\"}.fa-italic:before{content:\"\\f033\"}.fa-text-height:before{content:\"\\f034\"}.fa-text-width:before{content:\"\\f035\"}.fa-align-left:before{content:\"\\f036\"}.fa-align-center:before{content:\"\\f037\"}.fa-align-right:before{content:\"\\f038\"}.fa-align-justify:before{content:\"\\f039\"}.fa-list:before{content:\"\\f03a\"}.fa-dedent:before,.fa-outdent:before{content:\"\\f03b\"}.fa-indent:before{content:\"\\f03c\"}.fa-video-camera:before{content:\"\\f03d\"}.fa-picture-o:before{content:\"\\f03e\"}.fa-pencil:before{content:\"\\f040\"}.fa-map-marker:before{content:\"\\f041\"}.fa-adjust:before{content:\"\\f042\"}.fa-tint:before{content:\"\\f043\"}.fa-edit:before,.fa-pencil-square-o:before{content:\"\\f044\"}.fa-share-square-o:before{content:\"\\f045\"}.fa-check-square-o:before{content:\"\\f046\"}.fa-arrows:before{content:\"\\f047\"}.fa-step-backward:before{content:\"\\f048\"}.fa-fast-backward:before{content:\"\\f049\"}.fa-backward:before{content:\"\\f04a\"}.fa-play:before{content:\"\\f04b\"}.fa-pause:before{content:\"\\f04c\"}.fa-stop:before{content:\"\\f04d\"}.fa-forward:before{content:\"\\f04e\"}.fa-fast-forward:before{content:\"\\f050\"}.fa-step-forward:before{content:\"\\f051\"}.fa-eject:before{content:\"\\f052\"}.fa-chevron-left:before{content:\"\\f053\"}.fa-chevron-right:before{content:\"\\f054\"}.fa-plus-circle:before{content:\"\\f055\"}.fa-minus-circle:before{content:\"\\f056\"}.fa-times-circle:before{content:\"\\f057\"}.fa-check-circle:before{content:\"\\f058\"}.fa-question-circle:before{content:\"\\f059\"}.fa-info-circle:before{content:\"\\f05a\"}.fa-crosshairs:before{content:\"\\f05b\"}.fa-times-circle-o:before{content:\"\\f05c\"}.fa-check-circle-o:before{content:\"\\f05d\"}.fa-ban:before{content:\"\\f05e\"}.fa-arrow-left:before{content:\"\\f060\"}.fa-arrow-right:before{content:\"\\f061\"}.fa-arrow-up:before{content:\"\\f062\"}.fa-arrow-down:before{content:\"\\f063\"}.fa-mail-forward:before,.fa-share:before{content:\"\\f064\"}.fa-expand:before{content:\"\\f065\"}.fa-compress:before{content:\"\\f066\"}.fa-plus:before{content:\"\\f067\"}.fa-minus:before{content:\"\\f068\"}.fa-asterisk:before{content:\"\\f069\"}.fa-exclamation-circle:before{content:\"\\f06a\"}.fa-gift:before{content:\"\\f06b\"}.fa-leaf:before{content:\"\\f06c\"}.fa-fire:before{content:\"\\f06d\"}.fa-eye:before{content:\"\\f06e\"}.fa-eye-slash:before{content:\"\\f070\"}.fa-warning:before,.fa-exclamation-triangle:before{content:\"\\f071\"}.fa-plane:before{content:\"\\f072\"}.fa-calendar:before{content:\"\\f073\"}.fa-random:before{content:\"\\f074\"}.fa-comment:before{content:\"\\f075\"}.fa-magnet:before{content:\"\\f076\"}.fa-chevron-up:before{content:\"\\f077\"}.fa-chevron-down:before{content:\"\\f078\"}.fa-retweet:before{content:\"\\f079\"}.fa-shopping-cart:before{content:\"\\f07a\"}.fa-folder:before{content:\"\\f07b\"}.fa-folder-open:before{content:\"\\f07c\"}.fa-arrows-v:before{content:\"\\f07d\"}.fa-arrows-h:before{content:\"\\f07e\"}.fa-bar-chart-o:before{content:\"\\f080\"}.fa-twitter-square:before{content:\"\\f081\"}.fa-facebook-square:before{content:\"\\f082\"}.fa-camera-retro:before{content:\"\\f083\"}.fa-key:before{content:\"\\f084\"}.fa-gears:before,.fa-cogs:before{content:\"\\f085\"}.fa-comments:before{content:\"\\f086\"}.fa-thumbs-o-up:before{content:\"\\f087\"}.fa-thumbs-o-down:before{content:\"\\f088\"}.fa-star-half:before{content:\"\\f089\"}.fa-heart-o:before{content:\"\\f08a\"}.fa-sign-out:before{content:\"\\f08b\"}.fa-linkedin-square:before{content:\"\\f08c\"}.fa-thumb-tack:before{content:\"\\f08d\"}.fa-external-link:before{content:\"\\f08e\"}.fa-sign-in:before{content:\"\\f090\"}.fa-trophy:before{content:\"\\f091\"}.fa-github-square:before{content:\"\\f092\"}.fa-upload:before{content:\"\\f093\"}.fa-lemon-o:before{content:\"\\f094\"}.fa-phone:before{content:\"\\f095\"}.fa-square-o:before{content:\"\\f096\"}.fa-bookmark-o:before{content:\"\\f097\"}.fa-phone-square:before{content:\"\\f098\"}.fa-twitter:before{content:\"\\f099\"}.fa-facebook:before{content:\"\\f09a\"}.fa-github:before{content:\"\\f09b\"}.fa-unlock:before{content:\"\\f09c\"}.fa-credit-card:before{content:\"\\f09d\"}.fa-rss:before{content:\"\\f09e\"}.fa-hdd-o:before{content:\"\\f0a0\"}.fa-bullhorn:before{content:\"\\f0a1\"}.fa-bell:before{content:\"\\f0f3\"}.fa-certificate:before{content:\"\\f0a3\"}.fa-hand-o-right:before{content:\"\\f0a4\"}.fa-hand-o-left:before{content:\"\\f0a5\"}.fa-hand-o-up:before{content:\"\\f0a6\"}.fa-hand-o-down:before{content:\"\\f0a7\"}.fa-arrow-circle-left:before{content:\"\\f0a8\"}.fa-arrow-circle-right:before{content:\"\\f0a9\"}.fa-arrow-circle-up:before{content:\"\\f0aa\"}.fa-arrow-circle-down:before{content:\"\\f0ab\"}.fa-globe:before{content:\"\\f0ac\"}.fa-wrench:before{content:\"\\f0ad\"}.fa-tasks:before{content:\"\\f0ae\"}.fa-filter:before{content:\"\\f0b0\"}.fa-briefcase:before{content:\"\\f0b1\"}.fa-arrows-alt:before{content:\"\\f0b2\"}.fa-group:before,.fa-users:before{content:\"\\f0c0\"}.fa-chain:before,.fa-link:before{content:\"\\f0c1\"}.fa-cloud:before{content:\"\\f0c2\"}.fa-flask:before{content:\"\\f0c3\"}.fa-cut:before,.fa-scissors:before{content:\"\\f0c4\"}.fa-copy:before,.fa-files-o:before{content:\"\\f0c5\"}.fa-paperclip:before{content:\"\\f0c6\"}.fa-save:before,.fa-floppy-o:before{content:\"\\f0c7\"}.fa-square:before{content:\"\\f0c8\"}.fa-bars:before{content:\"\\f0c9\"}.fa-list-ul:before{content:\"\\f0ca\"}.fa-list-ol:before{content:\"\\f0cb\"}.fa-strikethrough:before{content:\"\\f0cc\"}.fa-underline:before{content:\"\\f0cd\"}.fa-table:before{content:\"\\f0ce\"}.fa-magic:before{content:\"\\f0d0\"}.fa-truck:before{content:\"\\f0d1\"}.fa-pinterest:before{content:\"\\f0d2\"}.fa-pinterest-square:before{content:\"\\f0d3\"}.fa-google-plus-square:before{content:\"\\f0d4\"}.fa-google-plus:before{content:\"\\f0d5\"}.fa-money:before{content:\"\\f0d6\"}.fa-caret-down:before{content:\"\\f0d7\"}.fa-caret-up:before{content:\"\\f0d8\"}.fa-caret-left:before{content:\"\\f0d9\"}.fa-caret-right:before{content:\"\\f0da\"}.fa-columns:before{content:\"\\f0db\"}.fa-unsorted:before,.fa-sort:before{content:\"\\f0dc\"}.fa-sort-down:before,.fa-sort-asc:before{content:\"\\f0dd\"}.fa-sort-up:before,.fa-sort-desc:before{content:\"\\f0de\"}.fa-envelope:before{content:\"\\f0e0\"}.fa-linkedin:before{content:\"\\f0e1\"}.fa-rotate-left:before,.fa-undo:before{content:\"\\f0e2\"}.fa-legal:before,.fa-gavel:before{content:\"\\f0e3\"}.fa-dashboard:before,.fa-tachometer:before{content:\"\\f0e4\"}.fa-comment-o:before{content:\"\\f0e5\"}.fa-comments-o:before{content:\"\\f0e6\"}.fa-flash:before,.fa-bolt:before{content:\"\\f0e7\"}.fa-sitemap:before{content:\"\\f0e8\"}.fa-umbrella:before{content:\"\\f0e9\"}.fa-paste:before,.fa-clipboard:before{content:\"\\f0ea\"}.fa-lightbulb-o:before{content:\"\\f0eb\"}.fa-exchange:before{content:\"\\f0ec\"}.fa-cloud-download:before{content:\"\\f0ed\"}.fa-cloud-upload:before{content:\"\\f0ee\"}.fa-user-md:before{content:\"\\f0f0\"}.fa-stethoscope:before{content:\"\\f0f1\"}.fa-suitcase:before{content:\"\\f0f2\"}.fa-bell-o:before{content:\"\\f0a2\"}.fa-coffee:before{content:\"\\f0f4\"}.fa-cutlery:before{content:\"\\f0f5\"}.fa-file-text-o:before{content:\"\\f0f6\"}.fa-building-o:before{content:\"\\f0f7\"}.fa-hospital-o:before{content:\"\\f0f8\"}.fa-ambulance:before{content:\"\\f0f9\"}.fa-medkit:before{content:\"\\f0fa\"}.fa-fighter-jet:before{content:\"\\f0fb\"}.fa-beer:before{content:\"\\f0fc\"}.fa-h-square:before{content:\"\\f0fd\"}.fa-plus-square:before{content:\"\\f0fe\"}.fa-angle-double-left:before{content:\"\\f100\"}.fa-angle-double-right:before{content:\"\\f101\"}.fa-angle-double-up:before{content:\"\\f102\"}.fa-angle-double-down:before{content:\"\\f103\"}.fa-angle-left:before{content:\"\\f104\"}.fa-angle-right:before{content:\"\\f105\"}.fa-angle-up:before{content:\"\\f106\"}.fa-angle-down:before{content:\"\\f107\"}.fa-desktop:before{content:\"\\f108\"}.fa-laptop:before{content:\"\\f109\"}.fa-tablet:before{content:\"\\f10a\"}.fa-mobile-phone:before,.fa-mobile:before{content:\"\\f10b\"}.fa-circle-o:before{content:\"\\f10c\"}.fa-quote-left:before{content:\"\\f10d\"}.fa-quote-right:before{content:\"\\f10e\"}.fa-spinner:before{content:\"\\f110\"}.fa-circle:before{content:\"\\f111\"}.fa-mail-reply:before,.fa-reply:before{content:\"\\f112\"}.fa-github-alt:before{content:\"\\f113\"}.fa-folder-o:before{content:\"\\f114\"}.fa-folder-open-o:before{content:\"\\f115\"}.fa-smile-o:before{content:\"\\f118\"}.fa-frown-o:before{content:\"\\f119\"}.fa-meh-o:before{content:\"\\f11a\"}.fa-gamepad:before{content:\"\\f11b\"}.fa-keyboard-o:before{content:\"\\f11c\"}.fa-flag-o:before{content:\"\\f11d\"}.fa-flag-checkered:before{content:\"\\f11e\"}.fa-terminal:before{content:\"\\f120\"}.fa-code:before{content:\"\\f121\"}.fa-reply-all:before{content:\"\\f122\"}.fa-mail-reply-all:before{content:\"\\f122\"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:\"\\f123\"}.fa-location-arrow:before{content:\"\\f124\"}.fa-crop:before{content:\"\\f125\"}.fa-code-fork:before{content:\"\\f126\"}.fa-unlink:before,.fa-chain-broken:before{content:\"\\f127\"}.fa-question:before{content:\"\\f128\"}.fa-info:before{content:\"\\f129\"}.fa-exclamation:before{content:\"\\f12a\"}.fa-superscript:before{content:\"\\f12b\"}.fa-subscript:before{content:\"\\f12c\"}.fa-eraser:before{content:\"\\f12d\"}.fa-puzzle-piece:before{content:\"\\f12e\"}.fa-microphone:before{content:\"\\f130\"}.fa-microphone-slash:before{content:\"\\f131\"}.fa-shield:before{content:\"\\f132\"}.fa-calendar-o:before{content:\"\\f133\"}.fa-fire-extinguisher:before{content:\"\\f134\"}.fa-rocket:before{content:\"\\f135\"}.fa-maxcdn:before{content:\"\\f136\"}.fa-chevron-circle-left:before{content:\"\\f137\"}.fa-chevron-circle-right:before{content:\"\\f138\"}.fa-chevron-circle-up:before{content:\"\\f139\"}.fa-chevron-circle-down:before{content:\"\\f13a\"}.fa-html5:before{content:\"\\f13b\"}.fa-css3:before{content:\"\\f13c\"}.fa-anchor:before{content:\"\\f13d\"}.fa-unlock-alt:before{content:\"\\f13e\"}.fa-bullseye:before{content:\"\\f140\"}.fa-ellipsis-h:before{content:\"\\f141\"}.fa-ellipsis-v:before{content:\"\\f142\"}.fa-rss-square:before{content:\"\\f143\"}.fa-play-circle:before{content:\"\\f144\"}.fa-ticket:before{content:\"\\f145\"}.fa-minus-square:before{content:\"\\f146\"}.fa-minus-square-o:before{content:\"\\f147\"}.fa-level-up:before{content:\"\\f148\"}.fa-level-down:before{content:\"\\f149\"}.fa-check-square:before{content:\"\\f14a\"}.fa-pencil-square:before{content:\"\\f14b\"}.fa-external-link-square:before{content:\"\\f14c\"}.fa-share-square:before{content:\"\\f14d\"}.fa-compass:before{content:\"\\f14e\"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:\"\\f150\"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:\"\\f151\"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:\"\\f152\"}.fa-euro:before,.fa-eur:before{content:\"\\f153\"}.fa-gbp:before{content:\"\\f154\"}.fa-dollar:before,.fa-usd:before{content:\"\\f155\"}.fa-rupee:before,.fa-inr:before{content:\"\\f156\"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:\"\\f157\"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:\"\\f158\"}.fa-won:before,.fa-krw:before{content:\"\\f159\"}.fa-bitcoin:before,.fa-btc:before{content:\"\\f15a\"}.fa-file:before{content:\"\\f15b\"}.fa-file-text:before{content:\"\\f15c\"}.fa-sort-alpha-asc:before{content:\"\\f15d\"}.fa-sort-alpha-desc:before{content:\"\\f15e\"}.fa-sort-amount-asc:before{content:\"\\f160\"}.fa-sort-amount-desc:before{content:\"\\f161\"}.fa-sort-numeric-asc:before{content:\"\\f162\"}.fa-sort-numeric-desc:before{content:\"\\f163\"}.fa-thumbs-up:before{content:\"\\f164\"}.fa-thumbs-down:before{content:\"\\f165\"}.fa-youtube-square:before{content:\"\\f166\"}.fa-youtube:before{content:\"\\f167\"}.fa-xing:before{content:\"\\f168\"}.fa-xing-square:before{content:\"\\f169\"}.fa-youtube-play:before{content:\"\\f16a\"}.fa-dropbox:before{content:\"\\f16b\"}.fa-stack-overflow:before{content:\"\\f16c\"}.fa-instagram:before{content:\"\\f16d\"}.fa-flickr:before{content:\"\\f16e\"}.fa-adn:before{content:\"\\f170\"}.fa-bitbucket:before{content:\"\\f171\"}.fa-bitbucket-square:before{content:\"\\f172\"}.fa-tumblr:before{content:\"\\f173\"}.fa-tumblr-square:before{content:\"\\f174\"}.fa-long-arrow-down:before{content:\"\\f175\"}.fa-long-arrow-up:before{content:\"\\f176\"}.fa-long-arrow-left:before{content:\"\\f177\"}.fa-long-arrow-right:before{content:\"\\f178\"}.fa-apple:before{content:\"\\f179\"}.fa-windows:before{content:\"\\f17a\"}.fa-android:before{content:\"\\f17b\"}.fa-linux:before{content:\"\\f17c\"}.fa-dribbble:before{content:\"\\f17d\"}.fa-skype:before{content:\"\\f17e\"}.fa-foursquare:before{content:\"\\f180\"}.fa-trello:before{content:\"\\f181\"}.fa-female:before{content:\"\\f182\"}.fa-male:before{content:\"\\f183\"}.fa-gittip:before{content:\"\\f184\"}.fa-sun-o:before{content:\"\\f185\"}.fa-moon-o:before{content:\"\\f186\"}.fa-archive:before{content:\"\\f187\"}.fa-bug:before{content:\"\\f188\"}.fa-vk:before{content:\"\\f189\"}.fa-weibo:before{content:\"\\f18a\"}.fa-renren:before{content:\"\\f18b\"}.fa-pagelines:before{content:\"\\f18c\"}.fa-stack-exchange:before{content:\"\\f18d\"}.fa-arrow-circle-o-right:before{content:\"\\f18e\"}.fa-arrow-circle-o-left:before{content:\"\\f190\"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:\"\\f191\"}.fa-dot-circle-o:before{content:\"\\f192\"}.fa-wheelchair:before{content:\"\\f193\"}.fa-vimeo-square:before{content:\"\\f194\"}.fa-turkish-lira:before,.fa-try:before{content:\"\\f195\"}.fa-plus-square-o:before{content:\"\\f196\"} /* */ .fa-spin::before{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}\n/* General */ .dialog { border: 1px solid; display: block; } .dialog:not(#qr):not(#thread-watcher):not(#header-bar) { box-shadow: 0 1px 2px rgba(0, 0, 0, .15); } #qr, #thread-watcher { box-shadow: -1px 2px 2px rgba(0, 0, 0, 0.25); } .captcha-img, .field { background-color: #FFF; border: 1px solid #CCC; -moz-box-sizing: border-box; box-sizing: border-box; color: #333; font: 13px sans-serif; outline: none; transition: color .25s, border-color .25s; transition: color .25s, border-color .25s; } .field::-moz-placeholder, .field:hover::-moz-placeholder { color: #AAA !important; font-size: 13px !important; opacity: 1.0 !important; } .captch-img:hover, .field:hover { border-color: #999; } .field:hover, .field:focus { color: #000; } .field[disabled] { background-color: #F2F2F2; color: #888; } .field::-webkit-search-decoration { display: none; } .move { cursor: move; overflow: hidden; } label, .watch-thread-link { cursor: pointer; } a[href=\"javascript:;\"] { text-decoration: none; } .warning { color: red; } #boardNavDesktop, #boardNavMobile { display: none !important; } :root.hide-bottom-board-list #boardNavDesktopFoot { display: none; } body.hasDropDownNav{ margin-top: 5px; } a { outline: none !important; } .painted { border-radius: 3px; padding: 0px 2px; } .ad-plea { display: none; } /* 4chan style fixes */ .opContainer, .op { display: block !important; overflow: visible !important; } .reply > .file > .fileText { margin: 0 20px; } .hashlink::before { content: ' '; visibility: hidden; } .inline + .hashlink, [hidden] { display: none !important; } hr + div.center:not(.ad-cnt):not(.topad):not(.middlead):not(.bottomad) { display: none !important; } .page-num { margin-right: -8px; } .fileText a { unicode-bidi: -moz-isolate; unicode-bidi: -webkit-isolate; } .thread > img:first-child { /* party hats */ pointer-events: none; } marquee, .postMessage marquee + br, .postMessage marquee + br + br { display: none; } /* Anti-autoplay */ audio.controls-added { display: block; margin: auto; } :root.anti-autoplay div.embed { position: static; width: auto; height: auto; text-align: center; } /* fixed, z-index */ #overlay, #fourchanx-settings, #qp, #ihover, #navlinks, .fixed #header-bar, :root.float #updater, :root.float #thread-stats, #qr { position: fixed; } #fourchanx-settings { z-index: 999; } #overlay { z-index: 900; } #qp, #ihover { z-index: 60; } #menu, .gal-buttons { z-index: 50; } #updater, #thread-stats { z-index: 40; } :root.fixed #header-bar, #notifications { z-index: 35; } #a-gallery { z-index: 30; } #navlinks { z-index: 25; } #qr { z-index: 20; } #embedding { z-index: 11; } #thread-watcher { z-index: 10; } /* Header */ .fixed.top-header body { padding-top: 2em; } .fixed.bottom-header body { padding-bottom: 2em; } .fixed #header-bar { right: 0; left: 0; padding: 3px 4px 4px; } .fixed.top-header #header-bar { top: 0; } .fixed.bottom-header #header-bar { bottom: 0; } #header-bar { border-width: 0; transition: all .1s .05s ease-in-out; } :root.fixed #header-bar { box-shadow: -5px 1px 10px rgba(0, 0, 0, 0.20); } #header-bar #custom-board-list .current { padding: 1px 1px 4px 1px; } :root.centered-links #shortcuts { width: 300px; text-align: right; } :root.centered-links #header-bar { text-align: center; } #custom-board-list { font-size: 13px; vertical-align: middle; } #full-board-list { vertical-align: middle; } :root.centered-links #custom-board-list { position: relative; left: 150px; } .fixed.top-header #header-bar { border-bottom-width: 1px; } .fixed.bottom-header #header-bar { box-shadow: 0 -1px 2px rgba(0, 0, 0, .15); border-top-width: 1px; } .fixed.bottom-header #header-bar .menu-button i { border-top: none; border-bottom: 6px solid; } .fixed #header-bar.autohide:not(:hover) { box-shadow: none; transition: all .8s .6s cubic-bezier(.55, .055, .675, .19); } .fixed.top-header #header-bar.autohide:not(:hover) { margin-bottom: -1em; -webkit-transform: translateY(-100%); transform: translateY(-100%); } .fixed.bottom-header #header-bar.autohide:not(:hover) { -webkit-transform: translateY(100%); transform: translateY(100%); } #scroll-marker { left: 0; right: 0; height: 10px; position: absolute; } :root:not(.autohide) #scroll-marker { pointer-events: none; } #header-bar #scroll-marker { display: none; } .fixed #header-bar #scroll-marker { display: block; } .fixed.top-header #header-bar #scroll-marker { top: 100%; } .fixed.bottom-header #header-bar #scroll-marker { bottom: 100%; } #header-bar a:not(.entry):not(.close) { text-decoration: none; padding: 1px; } #shortcuts:empty { display: none; } .brackets-wrap::before { content: \"\\00a0[\"; } .brackets-wrap::after { content: \"]\\00a0\"; } .dead-thread, .disabled:not(.replies-quoting-you) { opacity: .45; } #shortcuts { float: right; } .shortcut { margin-left: 3px; vertical-align: middle; } #navbotright, #navtopright { display: none; } #toggleMsgBtn { display: none !important; } .current { font-weight: bold; } :root.fixed.bottom-header #jsMath_button { bottom: auto; top: 1px; } /* 4chan X link brackets */ .brackets-wrap::before { content: \"[\"; } .brackets-wrap::after { content: \"]\"; } /* Notifications */ #notifications { position: fixed; top: 0; height: 0; text-align: center; right: 0; left: 0; visibility: visible; } :root.fixed.top-header:not(.gallery-open) #header-bar #notifications, :root.fixed.top-header #header-bar.autohide #notifications { position: absolute; top: 100%; } .notification { color: #FFF; font-weight: 700; text-shadow: 0 1px 2px rgba(0, 0, 0, .5); box-shadow: 0 1px 2px rgba(0, 0, 0, .15); border-radius: 2px; margin: 1px auto; width: 500px; max-width: 100%; position: relative; transition: all .25s ease-in-out; } .notification.error { background-color: hsla(0, 100%, 38%, .9); } .notification.warning { background-color: hsla(36, 100%, 38%, .9); } .notification.info { background-color: hsla(200, 100%, 38%, .9); } .notification.success { background-color: hsla(104, 100%, 38%, .9); } .notification a { color: white; } .notification > .close { padding: 7px; top: 0px; right: 5px; position: absolute; } .notification > .fa-times::before { font-size: 11px !important; } .message { -moz-box-sizing: border-box; box-sizing: border-box; padding: 6px 20px; max-height: 200px; width: 100%; overflow: auto; } /* Settings */ :root.fourchan-x body { -moz-box-sizing: border-box; box-sizing: border-box; } #overlay { background-color: rgba(0, 0, 0, .5); top: 0; left: 0; height: 100%; width: 100%; } #fourchanx-settings { -moz-box-sizing: border-box; box-sizing: border-box; box-shadow: 0 0 15px rgba(0, 0, 0, .15); height: 600px; max-height: 100%; width: 900px; max-width: 100%; margin: auto; padding: 3px; top: 50%; left: 50%; -moz-transform: translate(-50%, -50%); -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%); } #fourchanx-settings > nav { padding: 2px 2px 0; height: 15px; } #fourchanx-settings > nav a { text-decoration: underline; } #fourchanx-settings > nav a.close { text-decoration: none; padding: 0 2px; margin: 0; } .section-container { overflow: auto; position: absolute; top: 2.1em; right: 5px; bottom: 5px; left: 5px; padding-right: 5px; } .sections-list { padding: 0 3px; float: left; } .credits { float: right; } .tab-selected { font-weight: 700; } .section-sauce ul, .section-advanced ul { list-style: none; margin: 0; } .section-sauce ul { padding: 8px; } .section-advanced ul { padding: 0px; } .section-sauce li, .section-advanced li { padding-left: 4px; } .section-main label { text-decoration: underline; } div[data-checked=\"false\"] > .suboption-list { display: none; } .suboption-list { position: relative; } .suboption-list::before { content: \"\"; display: inline-block; position: absolute; left: .7em; width: 0; height: 100%; border-left: 1px solid; } .suboption-list > div { position: relative; padding-left: 1.4em; } .suboption-list > div::before { content: \"\"; display: inline-block; position: absolute; left: .7em; width: .7em; height: .6em; border-left: 1px solid; border-bottom: 1px solid; } .section-filter ul { padding: 0; } .section-filter li { margin: 10px 40px; list-style: disc; } .section-filter textarea { height: 500px; } .section-sauce textarea { height: 350px; } .section-advanced .field[name=\"boardnav\"] { width: 100%; } .section-advanced textarea { height: 150px; } .section-advanced .archive-cell { min-width: 160px; text-align: center; } .section-advanced #archive-board-select { position: absolute; } .section-advanced .note { font-size: 0.8em; font-style: italic; margin-left: 10px; } .section-advanced .note code { font-style: normal; font-size: 11px; } .section-keybinds .field { font-family: monospace; } #fourchanx-settings fieldset { border: 1px solid; border-radius: 3px; padding: 0.35em 0.625em 0.75em; margin: 0px 2px; } #fourchanx-settings legend { font-weight: 700; color: inherit; } #fourchanx-settings textarea { font-family: monospace; min-width: 100%; max-width: 100%; } #fourchanx-settings code { color: #000; background-color: #FFF; padding: 0 2px; } #fourchanx-settings th { text-align: center; font-weight: bold; } #fourchanx-settings p { margin: 1em 0px; } .unscroll { overflow: hidden; } /* Index */ :root.index-loading .navLinks, :root.index-loading .board, :root.index-loading .pagelist, :root.infinite-mode .pagelist, :root.all-pages-mode .pagelist, :root.catalog-mode .pagelist, :root:not(.catalog-mode) .indexlink, :root.catalog-mode .cataloglink, :root:not(.catalog-mode) #hidden-label, :root:not(.catalog-mode) #index-size { display: none; } #index-search { padding-right: 1.5em; width: 100px; transition: color .25s, border-color .25s, width .25s; } #index-search:focus, #index-search[data-searching] { width: 200px; } #index-search-clear { color: gray; display: inline-block; position: relative; left: -1em; width: 0; } #index-search:not([data-searching]) + #index-search-clear { display: none; } #index-mode, #index-sort, #index-size { float: right; } .summary { text-decoration: none; } /* Catalog */ :root.catalog-mode .board { text-align: center; } .catalog-thread { display: -webkit-inline-flex; display: inline-flex; text-align: left; -webkit-flex-direction: column; flex-direction: column; -webkit-align-items: center; align-items: center; margin: 0 2px 5px; word-wrap: break-word; vertical-align: top; } .catalog-thread > a { flex-shrink: 0; -webkit-flex-shrink: 0; position: relative; } .catalog-small .catalog-thread { width: 165px; max-height: 320px; } .catalog-large .catalog-thread { width: 270px; max-height: 410px; } .catalog-thumb { border-radius: 2px; box-shadow: 0 0 5px rgba(0, 0, 0, .25); } .catalog-thumb.spoiler-file { width: 100px; height: 100px; } .catalog-thumb.deleted-file { width: 127px; height: 13px; padding: 20px 11px; } .catalog-thumb.no-file { width: 77px; height: 13px; padding: 20px 36px; } .catalog-icons > img, .catalog-stats > .menu-button { width: 1em; height: 1em; margin: 0; vertical-align: text-top; padding-left: 2px; } .catalog-stats > .menu-button { text-align: center; font-weight: normal; } .catalog-stats > .menu-button > i::before { line-height: 11px; } .catalog-stats { -webkit-flex-shrink: 0; flex-shrink: 0; cursor: help; font-size: 10px; font-weight: 700; margin-top: 2px; } .catalog-thread > .subject { -webkit-flex-shrink: 0; flex-shrink: 0; -webkit-align-self: stretch; align-self: stretch; font-weight: 700; line-height: 1; text-align: center; } .catalog-thread > .comment { -webkit-flex-shrink: 1; flex-shrink: 1; -webkit-align-self: stretch; align-self: stretch; overflow: hidden; text-align: center; } /* /tg/ dice rolls */ .catalog-thread > .comment > b { font-weight: normal; } .catalog-code { background-color: #FFF; display: inline-block; max-width: 100%; } /* Announcement Hiding */ :root.hide-announcement #globalMessage { display: none; } span.hide-announcement { font-size: 11px; position: relative; bottom: 5px; } .globalMessage, h2, h3 { color: inherit !important; font-size: 13px; font-weight: 100; } /* Unread */ #unread-line { margin: 0; border-color: rgb(255,0,0); } /* Thread Updater */ #updater { background: none; border: none; box-shadow: none; } #updater > .move { position: absolute; left: 0; top: -5px; width: 100%; height: 5px; } #updater > div:last-child { text-align: center; } #updater input[type=\"number\"] { width: 4em; } :root.float #updater { padding: 0px 3px; } .new { color: limegreen; } #update-status.new { margin-right: 5px; } #update-timer { cursor: pointer; } /* Thread Watcher */ #thread-watcher { position: absolute; } #thread-watcher { padding-bottom: 3px; padding-left: 3px; overflow: hidden; white-space: nowrap; min-width: 146px; max-height: 92%; overflow-y: auto; } #thread-watcher .refresh { padding: 0px 3px; } :root.fixed-watcher #thread-watcher { position: fixed; } :root:not(.fixed-watcher) #thread-watcher:not(:hover) { max-height: 210px; overflow-y: hidden; } #thread-watcher > .move { padding-top: 3px; } #watched-threads > div { padding-left: 3px; padding-right: 3px; } #watched-threads .watcher-link { max-width: 250px; display: -webkit-inline-flex; display: inline-flex; -webkit-flex-direction: row; flex-direction: row; } #watched-threads .watcher-unread { -webkit-flex: 0 0 auto; flex: 0 0 auto; } #watched-threads .watcher-unread::after { content: \"\\00a0\"; } #watched-threads .watcher-title { overflow: hidden; text-overflow: ellipsis; -webkit-flex: 0 1 auto; flex: 0 1 auto; } #thread-watcher a { text-decoration: none; } #thread-watcher .move > .close { position: absolute; right: 0px; top: 0px; padding: 0px 4px; } .watch-thread-link { padding-top: 18px; width: 18px; height: 0px; display: inline-block; background-repeat: no-repeat; opacity: 0.2; position: relative; top: 1px; } .watch-thread-link.watched { opacity: 1; } /* Thread Stats */ #thread-stats { background: none; border: none; box-shadow: none; } :root.float #thread-stats > .move > span { pointer-events: none; } :root.float #thread-stats { padding: 0px 3px; } /* Quote */ .catalog-thread > .comment > span.quote, #arc-list span.quote { color: #789922; } :root:not(.catalog-mode) .deadlink { text-decoration: none !important; } .backlink.deadlink:not(.forwardlink), .quotelink.deadlink:not(.forwardlink) { text-decoration: underline !important; } .inlined { opacity: .5; } #qp input, .forwarded { display: none; } .quotelink.forwardlink, .backlink.forwardlink { text-decoration: none; border-bottom: 1px dashed; } @supports (text-decoration-style: dashed) or (-moz-text-decoration-style: dashed) { .quotelink.forwardlink, .backlink.forwardlink { text-decoration: underline; -moz-text-decoration-style: dashed; text-decoration-style: dashed; border-bottom: none; } } .filtered { text-decoration: underline line-through; } :root.hide-backlinks .backlink.filtered, :root.hide-backlinks .backlink.filtered + .hashlink.filtered { display: none; } .inline { border: 1px solid; display: table; margin: 2px 0; } .inline .post { border: 0 !important; background-color: transparent !important; display: table !important; margin: 0 !important; padding: 1px 2px !important; } #qp > .opContainer::after { content: ''; clear: both; display: table; } #qp .post { border: none; margin: 0; padding: 2px 2px 5px; } #qp img { max-height: 80vh; max-width: 50vw; } .qphl { outline: 2px solid rgba(216, 94, 49, .7); } :root.highlight-own .yourPost > .reply, :root.highlight-you .quotesYou > .reply { border-left: 2px solid rgba(221,0,0,.5); } /* Quote Threading */ .threadContainer { margin-left: 20px; border-left: 1px solid rgba(128,128,128,.3); } .threadOP { clear: both; } /* File */ .fnswitch:hover > .fntrunc, .fnswitch:not(:hover) > .fnfull, .expanded-image > .post > .file > .fileThumb > video[data-md5], .expanded-image > .post > .file > .fileThumb > img[data-md5] { display: none; } .full-image { display: none; cursor: pointer; } .expanded-image > .post > .file > .fileThumb > .full-image { display: inline; } .expanded-image { clear: left; } .expanding { opacity: .5; } :root.fit-height .full-image { max-height: 100vh; } :root.fit-width .full-image { max-width: 100%; } :root.gecko.fit-width .full-image { width: 100%; } .fileThumb > .warning { clear: both; } /* WEBM Metadata */ .webm-title > a::before { content: \"title\"; text-decoration: underline; } .webm-title.loading > a::after { content: \"...\"; } .webm-title.error > a:hover::before, .webm-title.error > a:focus::before { content: \"error\"; text-decoration: none; } .webm-title > span { cursor: text; } .webm-title.not-found > span::before { content: \"not found\"; } .webm-title:not(:hover):not(:focus) > span, .webm-title:hover > span + a, .webm-title:focus > span + a { display: none; } /* Volume control */ input[name=\"Default Volume\"] { width: 4em; height: 1ex; vertical-align: middle; margin: 0px; } /* Fappe Tyme */ :root.fappeTyme .thread > .noFile, :root.fappeTyme .threadContainer > .noFile { display: none; } /* Werk Tyme */ :root.werkTyme .postContainer:not(.noFile) .fileThumb, :root.werkTyme .catalog-thumb:not(.deleted-file):not(.no-file), :root:not(.werkTyme) .werkTyme-filename { display: none; } .werkTyme-filename { font-weight: bold; } :root.werkTyme .catalog-thread > a { text-align: center; -webkit-align-self: stretch; align-self: stretch; } .catalog-thread.watched .werkTyme-filename, .filter-highlight .werkTyme-filename { border: 2px solid rgba(255, 0, 0, .5); } /* Index/Reply Navigation */ #navlinks { font-size: 16px; top: 25px; right: 10px; } :root.catalog-mode #navlinks { display: none; } /* Filter */ .opContainer.filter-highlight { box-shadow: inset 5px 0 rgba(255, 0, 0, .5); } .filter-highlight > .reply { box-shadow: -5px 0 rgba(255, 0, 0, .5); } .catalog-thread.watched .catalog-thumb, .filter-highlight .catalog-thumb { border: 2px solid rgba(255, 0, 0, .5); } /* Spoiler text */ :root.reveal-spoilers s, :root.reveal-spoilers s > a { color: white !important; } :root.reveal-spoilers .removed-spoiler::before { content: \"[spoiler]\"; } :root.reveal-spoilers .removed-spoiler::after { content: \"[/spoiler]\"; } /* Thread & Reply Hiding */ .hide-thread-button, .hide-reply-button { float: left; margin-right: 4px; padding: 2px; } .hide-thread-button:not(:hover), .hide-reply-button:not(:hover) { opacity: 0.4; } .threadContainer .hide-reply-button { margin-left: 2px !important; position: relative; left: 1px; } .hide-thread-button { margin-top: -1px; } .stub ~ * { display: none !important; } .stub input { display: inline-block; } .thread[hidden] + hr { display: none; } :root.reply-hide div.sideArrows { display: none; } /* QR */ :root.hide-original-post-form #togglePostFormLink, #qr.autohide:not(.focus):not(:hover):not(:active) > form, :root.thread-view #qr:not(.show-new-thread-option) select[data-name=\"thread\"], #file-n-submit:not(.has-file) #qr-filerm { display: none; } :root.hide-original-post-form #postForm { display: none !important; } #qr select, #dump-button, #url-button, .remove, .captcha-img { cursor: pointer; } #qr { position: fixed; padding: 1px; border: 1px solid transparent; min-width: 300px; border-radius: 3px 3px 0 0; } #qrtab { border-radius: 3px 3px 0 0; } #qrtab { margin-bottom: 1px; } #qr .close { float: right; padding: 0 3px; } #qr .warning { min-height: 1.6em; vertical-align: middle; padding: 0 1px; border-width: 1px; border-style: solid; } .qr-link-container { text-align: center; } .qr-link-container-bottom { width: 200px; position: absolute; left: -100px; margin-left: 50%; text-align: center; } .qr-link { border-radius: 3px; padding: 6px 10px 5px; font-weight: bold; vertical-align: middle; border-style: solid; border-width: 1px; font-size: 10pt; } .persona { width: 100%; display: -webkit-flex; display: flex; -webkit-flex-direction: row; flex-direction: row; } #dump-button { width: 10%; margin: 0; margin-right: 4px; font: 13px sans-serif; padding: 1px 0px 2px; opacity: 0.6; } #url-button { width: 10%; margin: 0; margin-right: 4px; font: 13px sans-serif; padding: 1px 0px 2px; opacity: 0.6; } .persona .field { -webkit-flex: 1; flex: 1; width: 0; } #qr.forced-anon input[data-name=\"name\"]:not(.force-show), #qr.forced-anon input[data-name=\"sub\"]:not(.force-show), #qr.reply-to-thread input[data-name=\"sub\"]:not(.force-show) { display: none; } #qr textarea.field { height: 14.8em; min-height: 9em; } #qr.has-captcha textarea.field { height: 9em; } input.field.tripped:not(:hover):not(:focus) { color: transparent !important; text-shadow: none !important; } #qr textarea { resize: both; } /* Noscript Recaptcha */ .captcha-img { margin: 0px; text-align: center; background-image: #fff; font-size: 0px; min-height: 59px; min-width: 302px; } .captcha-input{ width: 100%; margin: 1px 0 0; } .captcha-input.error:focus { border-color: rgb(255,0,0) !important; } #qr-captcha-iframe { display: none; } /* Recaptcha v2 */ #qr .captcha-root { position: relative; } #qr .captcha-container > div > div { margin: auto; } #qr .captcha-counter { display: block; width: 100%; text-align: center; pointer-events: none; } #qr.captcha-open .captcha-counter { position: absolute; bottom: 3px; } #qr .captcha-counter > a { pointer-events: auto; } #qr:not(.captcha-open) .captcha-counter > a { display: block; width: 100%; } .field { -moz-box-sizing: border-box; margin: 0px; padding: 2px 4px 3px; } #qr textarea { min-width: 100%; } #qr [type=\"submit\"] { width: 25%; vertical-align: top; } :root.webkit #qr [type=\"submit\"] { height: 24px; } #qr label input[type=\"checkbox\"] { position: relative; top: 2px; } /* Fake File Input */ input#qr-filename { border: none !important; width: 80%; padding: 0px 4px; position: relative; bottom: 1px; background: none !important; } input#qr-filename:not(.edit) { pointer-events: none; } #qr-filename, #qr-filesize, .has-file #qr-no-file { display: none; } #qr-no-file, .has-file #qr-filename, .has-file #qr-filesize { display: inline-block; margin: 0 0 2px; overflow: hidden; text-overflow: ellipsis; vertical-align: top; } #qr-no-file { color: #AAA; padding: 1px 4px; } #qr-filename-container { -moz-box-sizing: border-box; display: inline-block; position: relative; width: 100px; min-width: 74.6%; max-width: 74.6%; margin-right: 0.4%; margin-top: 1px; overflow: hidden; padding: 2px 1px 0; height: 22px; } #qr-filename-container:hover { cursor: text; } #qr-extras-container { position: absolute; right: 0px; } #qr-filerm { margin-right: 3px; z-index: 2; } #file-n-submit { height: 23px; } #qr input[type=\"file\"] { visibility: hidden; position: absolute; } /* Thread Select / Spoiler Label */ #qr select[data-name=\"thread\"] { float: right; } #qr.has-spoiler .has-file #qr-spoiler-label { width: 6.7%; min-width: 6.7%; max-width: 6.7%; display: inline-block; text-align: center; vertical-align: top; } #qr.has-spoiler #file-n-submit:not(.has-file) #qr-spoiler-label { display: none; } #qr.has-spoiler .has-file #qr-filename-container { max-width: 67.9%; min-width: 67.9%; } #qr-spoiler-label input { position: relative; top: 3px; } /* Dumping UI */ .dump #dump-list-container { display: block; } #dump-list-container { display: none; position: relative; overflow-y: hidden; margin-top: 1px; } #dump-list { overflow-x: auto; overflow-y: hidden; white-space: nowrap; width: 248px; max-width: 100%; min-width: 100%; } #dump-list:hover { overflow-x: auto; } .qr-preview { -moz-box-sizing: border-box; counter-increment: thumbnails; cursor: move; display: inline-block; height: 90px; width: 90px; padding: 2px; opacity: .5; overflow: hidden; position: relative; text-shadow: 0 0 2px #000; -moz-transition: opacity .25s ease-in-out; vertical-align: top; background-size: cover; } .qr-preview:hover, .qr-preview:focus { opacity: .9; } .qr-preview::before { content: counter(thumbnails); color: #fff; position: absolute; top: 3px; right: 3px; text-shadow: 0 0 3px #000, 0 0 8px #000; } .qr-preview#selected { opacity: 1; } .qr-preview.drag { box-shadow: 0 0 10px rgba(0,0,0,.5); } .qr-preview.over { border-color: #fff; } .qr-preview > span { color: #fff; } .remove { background: none; color: #e00; padding: 1px; } a:only-of-type > .remove { display: none; } .remove:hover::after { content: \" Remove\"; } .qr-preview > label { background: rgba(0,0,0,.5); color: #fff; right: 0; bottom: 0; left: 0; position: absolute; text-align: center; } .qr-preview > label > input { margin: 0; } #add-post { cursor: pointer; font-size: 2em; position: absolute; top: 50%; right: 10px; -moz-transform: translateY(-50%); } .textarea { position: relative; } :root.webkit .textarea { margin-bottom: -2px; } #char-count { color: #000; background: hsla(0, 0%, 100%, .5); font-size: 8pt; position: absolute; bottom: 1px; right: 1px; pointer-events: none; } /* Menu */ .menu-button:not(.fa-bars) { display: inline-block; position: relative; cursor: pointer; } #header-bar .menu-button i { border-top: 6px solid; border-right: 4px solid transparent; border-left: 4px solid transparent; display: inline-block; margin: 2px; vertical-align: middle; } .reply .menu-button, .op .menu-button, #thread-watcher .menu-button { margin-left: -1px !important; width: 20px; height: 15px; text-align: center; } .menu-button + .container:not(:empty) { margin-left: -5px; } #menu { position: fixed; outline: none; } #menu, .submenu { border-radius: 3px; padding-top: 1px; padding-bottom: 3px; } .entry { cursor: pointer; display: block; outline: none; padding: 2px 10px; position: relative; text-decoration: none; white-space: nowrap; min-width: 70px; text-align: left; text-shadow: none; } .left>.entry.has-submenu { padding-right: 17px !important; } .entry input[type=\"checkbox\"], .entry input[type=\"radio\"] { margin: 0px; position: relative; top: 2px; } .has-submenu::after { content: \"\"; border-left: .5em solid; border-top: .3em solid transparent; border-bottom: .3em solid transparent; display: inline-block; margin: .3em; position: absolute; right: 3px; } .left .has-submenu::after { border-left: 0; border-right: .5em solid; } .submenu { display: none; position: absolute; left: 100%; top: -1px; margin-left: 0px; margin-top: -2px; } .focused > .submenu { display: block; } .imp-exp-result { position: absolute; text-align: center; margin: auto; right: 0px; left: 0px; width: 200px; } .export, .import, .reset { cursor: pointer; text-decoration: none !important; } /* Custom Board Titles */ .boardTitle, .boardSubtitle { white-space: pre-line; } .boardTitle[contenteditable=\"true\"], .boardSubtitle[contenteditable=\"true\"] { cursor: text !important; } div.boardTitle { font-weight: 400 !important; } /* Link Title Favicons */ .linkify.YouTube { background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAYAAABr5z2BAAABIklEQVQoz53LvUrDUBjG8bOoOammSf1IoBSvoCB4JeIqOHgBLt6AIMRBBQelWurQ2kERnMRBsBUcIp5FJSBI5oQsJVkkUHh8W0o5nhaFHvjBgef/Mq+Q46RJBMkI/vE+aOus956tnEswIZe1LV0QyJ5sE2GzgZfVMtRNIdiDpccEssdlB1mW4bvTwdvWJtRdErM7U+8S/FJykCRJX5qm+KpVce8UMNLRLbulz4iSjTAMh6Iowsd5BeNadp3nUF0VlxAEwZBotXC0Usa4ll3meZdA1iguwvf9vpvDA2wvmKgYGtSud8suDB4TyGr2PF49D/vra9jRZ1BVdknMzgwuCGSnZEObwu6sBnVTCHZiaC7BhFx2PKdxUidiAH/4lLo9Mv0DELVs9qsOHXwAAAAASUVORK5CYII=') center left no-repeat!important; padding-left: 18px; } .linkify.Vimeo { background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAYFBMVEUAAAAIdZUKh6sLlLkLmr4LmsAMp88NrdYVW3MZj7Acstkrt9s1e5E7vN5EfI9JvdtKwuBijp5kpbl30eiDt8aG1uqRr7qTyNehxM+k4PCy3enB3OTg6Ovv9PXw+fz////L9U5WAAAAAXRSTlMAQObYZgAAAIFJREFUeNplz90OwiAMBWAQpAoyxclkP3je/y0H2AQXz0WT8100rRD6kNI9/cRroemQL3hXhoujZYj4OHoAmBvYGcBISwbWBvfXCrytnIDUQMkbsBpagMA7zhtQdyTFQAmIG7IkYniiZuh3XGsPqoOZkMOJOpAcLqUzNFGGu/57fwc1hgtp0mVSyQAAAABJRU5ErkJggg==') center left no-repeat!important; padding-left: 18px; } .linkify.SoundCloud { background: 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; padding-left: 18px; } .linkify.audio { background: 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; padding-left: 18px; } .linkify.LiveLeak { background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAlNJREFUGBkFwU2LVmUYAODrPu8Z5x1xSpRBXQyFoLsBE+wfiO5atJOgnf9DUPwFgtGinUgEaQsRhHYuMtpEiEWuG5iNjuOcj+c8z911xXcXL/68c3Dw1fzhg0QgEQAAEYGUKXFie9vxlSs/xk/rdavjGEkmkWSih65z4osv9GfOiK6LzEyZ2uGh4dUrmzs72ddlUUhkoiMr4PT167589Mh6c1N0nSRlqrX67dat+PDyZXRT19m5edPnt28rGFHxMcJ6d9fprS1/37tneP3aemPD1uamUydPOru3p5DdGOH0tWsu3LhhxIQJM2qEpRT/Pn3q/du3AhARSmvGTH0lplKMrVkiYpVpQaJlighzhDkzhmEA0fcWoqAfyaFW4zTlgCABxlrNmY4ylUzLsiREprFWc0T2M+ZSjKWY0AEaltZUjJixZJIpuk5pTWlNP2BYFvOyKJkCAKU1tTXHrZlqVWolUxdhxsfVSj9FmJfFMM9GdICGGa01HyMstYpMIFPJVNDPmYZSTOPoOEKHzNRlKpmWWh1j6TpLa2SKTKVWU6Z+Qolwdm/P9QcPZKa2LH69e9eIMs+WCL/cv2/98CGZPrt61am+V9APq1X89eyZ/968obVYaiXT4dGREgG+vnPHeHgYMsH2+fP+efEihtVKv7SWw/6+9/v7KYLMhIywTJPamvOXLomukyRsrNf+ePzYkpl9dJ3SWgSCSCQCfz5/7pMLF2yfO6eLiAQcHRz4/cmT+HR7O+Ob3d0fNt69+7a2BiICQCJbA0EgE5lpvbXl1OXL3/8Pfax4+6SjSukAAAAASUVORK5CYII=') center left no-repeat!important; padding-left: 18px; } .linkify.Vocaroo { background: 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; padding-left: 18px; } .linkify.pastebin { background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAB1FBMVEUAAAAAAAAAAABWYWwAAABbY3BbYm5dZnFdZXJeZnMEBAQHCAhYYGpdZnFdZnBgaHIlJyomKCooKi09QkdESU5eZGtdYmhdYmleY2lrcXdqb3Rqb3Rqb3SSmJ+SlJeWmJutr7GtrrCWm6ChpKhbW1tmZmZvb290dHR3d3d4eHh5eXl6enp8fHx+gIJ/f3+CgoKDg4OEhISFhYWHh4eKioqKjI2Li4uMjIyOjo6Pj4+QkJCRkZGSkpKUlJSVl5mWlpaYmZqZm52ampqbm5ucnJydnZ2enp6fn5+hoaGioqKkpKSkpaalpaWmp6mmp6qnqauoqKioqquoqq2qqqqrrK2srKysra6srrCsrrGurq6vr6+wsLCxsbGysrKztLa0tLS1t7m2tra3t7e4uLi5ubm6urq7u7u8vLy9vb2+vr7AwMDAwsTBwcHExcfFxcXFxsnGxsbHx8fIyMjJycnMzMzNzc3Ozs7O0NLPz8/Q0NDR0dHR09XT09PV1dXV1dbV1tfV19rW1tbX19fX19jY2tzZ2dnZ2tva2tra3N3a3N7c3Nze3t7f39/f4OHg4ODi4uLl5+jm5ubs7Ozs7e3u7u7v7+/v8PDw8PDx8fHy8vLz8/P29vYSoLMZAAAAJHRSTlMABAUGCwsNHCAiLzMzMzZEYGJwgIuOnJycnqmqq9bc3+/w8fkZ0N/uAAAA/klEQVQoU2NgYGDl5YMDdgYGBmZZ3964CYFtIR3e9Q7K/AwMHI55KfaFmcHWMy3K3MwlGRg4wz0zdYpcorRbNbL0LaWAAp3ts2umV8wo6MupTauQBgqUG03VL7W3sfZSb1erAgm02M+yzYrVCXUy6zapAQlUx/dEdyX3J3ZHVUYVywAF8o2rDNN1Go2jzGLMokAC2QbuSc42mXmaOXop9iAtCXrJ5qXWjT59Abl2ESJAAX/tSIMMiyrrqQ3T6uS5gQK6kSqpqkUermGTexQFmYACflqR+hlWZSamzQpCLEDPsSmVVDT1TJw0JUhOAMRnYOARFRMTE5cQF+ZiBPIAII5B3EVG0b4AAAAASUVORK5CYII=') center left no-repeat!important; padding-left: 18px; } .linkify.gist { background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABblBMVEXc3NykpKTW1tbb29ugoKCdnZ0AAAACAgIEDRcKCgoMDAwODg4QIzYRDAoTExMUDwwVAg0WICsaEw8aGhoiCBklGxUmERwwKCQ7LSU7Ozs8LSZFLyNINi1JNyxJNy1KSklMOi5VR1FXV1daQTRkZGRseYZwU0F4eHh7dnR8bWV/YE6IdGiKcGCKkJaNgYeNjY2RdGOScWCUcWCZmZmhoaGkpKSoqKirfmaurq6xsbG1tbW6urq+vr7AbmzBb23CwsLGxsbHx8fHyMjJycnJysrMzMzOiYbPi4fQ0NDRoYbT09PU1NTW1tbY2NjZqIzZ2dnb29vd3d3f39/i4uLktZrk5OTl5eXm5ubn5+fo6Ojq6urs7OzttKLu7u7wuqbw8PDx8fHz8/P4+Pj5+fn7uZj8vpz9ya79ybD/tZf/upr/wZ//w6H/xKH/xaL/xrH/yqj/y7T/zqv/z7D/07D/17n/2Lv/2Lz/3L//38n/4Mk3Q/ZuAAAABnRSTlMSFcbGzc5MNKFvAAAA1klEQVQoz2NgYPZHAswMDEwRSclwkBTBxOARn4gE4j0YXBOiJNUDg7y8Ar1UlOITXBkcY73Z2Li42dg42dn4wmIdGeyjQ7nZoEA4PNqewSZKlw0O9KJsGKwjBdl4ZeWkJGQUhNjEIq0ZrMI5+D0ri7Jz8itCRAXCrRgsQ3mUy+xicrPSbfO0REItGSyCVaVL3ONSU9LcCtQUgy0YzIJ85M1LizMzCsv9xF2CzBhMAwN99TV1DI0MtDWcAgNNGUycA5CAswkDi5kDwrMOZiwMjKzGSICVEQDhZj0UQV7PewAAAABJRU5ErkJggg==') center left no-repeat!important; padding-left: 18px; } .linkify.image { background: 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; padding-left: 18px; } .linkify.InstallGentoo { background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABcVBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3dIYAAAAAAAAAAAAbGh4BBAcCBgoBBgoCBwsCCQ/QzucCCA7MyuXZ1eUBBQmTh8fo5/i9svIAAADh3vQAAAACCA0CCQ8CCQ4DDBQbGCUDChDr6vgAAAAAAAAREBIDCxK6tdfe2fTv7/cDCxIDDBQEDRUHDhgMJjXk4PZdXWdLUFoUNEYOKDgSMUMRLUBneI4eTGj08/QmW3onW3rTzvfOx/giU3IiVHMkWHdEaYJobHv3+PokWHpua6TNy9xZgZ+1quz8/foQKj0XPFInWn0nW38tZ4o6fqg8gq48grA9hrU/i7pAhrNAiLdBjLtEjr1FksNIjr5Il8pImMtKWnNqhL97odKFqti5q/q5rPq60+nCt/vLw/vPx/jV0vHY0/rc1/rg2/vh3fzn4fzu6/vx8vf19Pv19Pz49/v5+Pv8/Pv8/fr9/vv+/frziVtUAAAAT3RSTlMABQYHCAoNDhARGRobL0ZOV1xdXV5fYGBmZnB0eX2MjZSaoaGio6mqqqustLq7zubo6Ojo6evt7u/x8fLy9/f4+Pj5+vr6+vr6+/39/v7+XKgUSwAAAMhJREFUKM9jYGDg4OZmZgABKINT1dBAhBHIYFMxMBIDisjbhoZbCTExsCu5hoeY8DEwcOkEx8fY6MqpucTGB0izglVEplcU5/gmRYWBVQDNMK+s0hN3SvMyBpsBNJxXw0NfwTEjVQZqHQMHj5RfWW5mliSEC7TPzK6yJD/bXZQRzGdXcisqLy309okA2Q4Eis4peQWmstqBCdGW/CABraC45ERBBs3A6Fh/AbAKTwsHa34QZW8NVsGuLqwswQSjQICTmYMFQaEDAAF8JHLfKGswAAAAAElFTkSuQmCC') center left no-repeat!important; padding-left: 18px; } .linkify.video { background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QAxgDGAP8nNqN7AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gMZBjQQLEEqGwAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAA5SURBVDjLY2AYaMDIwMDwn1JD/lPCZhpwL+B1wf///ykzgBhDiAoDfIYQZQAjIyP5BuDTPJqQqAQAvW0ZAMk8+EEAAAAASUVORK5CYII=') center left no-repeat!important; padding-left: 18px; } /* Embedding */ #embedding { padding: 1px 4px 1px 4px; position: fixed; } #embedding.empty { display: none; } #embedding > div:first-child { display: flex; } #embedding .move { flex: 1; } #embedding .jump { margin: -1px 4px; text-decoration: none; } /* Gallery */ #a-gallery { position: fixed; top: 0; bottom: 0; left: 0; right: 0; display: -webkit-flex; display: flex; -webkit-flex-direction: row; flex-direction: row; background: rgba(0,0,0,0.7); } .gal-viewport { display: -webkit-flex; display: flex; -webkit-align-items: stretch; align-items: stretch; -webkit-flex-direction: row; flex-direction: row; -webkit-flex: 1 1 auto; flex: 1 1 auto; overflow: hidden; } .gal-thumbnails { -webkit-flex: 0 0 150px; flex: 0 0 150px; overflow-y: auto; display: -webkit-flex; display: flex; -webkit-flex-direction: column; flex-direction: column; -webkit-align-items: stretch; align-items: stretch; text-align: center; background: rgba(0,0,0,.5); border-left: 1px solid #222; } .gal-hide-thumbnails .gal-thumbnails { display: none; } .gal-thumb img, .gal-thumb video { max-width: 125px; max-height: 125px; height: auto; width: auto; } .gal-thumb { -webkit-flex: 0 0 auto; flex: 0 0 auto; padding: 3px; line-height: 0; transition: background .2s linear; } .gal-highlight { background: rgba(0, 190, 255,.8); } .gal-prev { order: 0; border-right: 1px solid #222; } .gal-next { order: 2; border-left: 1px solid #222; } .gal-prev, .gal-next { -webkit-flex: 0 0 20px; flex: 0 0 20px; position: relative; cursor: pointer; opacity: 0.7; background-color: rgba(0, 0, 0, 0.3); } .gal-prev:hover, .gal-next:hover { opacity: 1; } .gal-prev::after, .gal-next::after { position: absolute; top: 48.6%; -webkit-transform: translateY(-50%); transform: translateY(-50%); display: inline-block; border-top: 11px solid transparent; border-bottom: 11px solid transparent; content: \"\"; } .gal-prev::after { border-right: 12px solid #fff; right: 5px; } .gal-next::after { border-left: 12px solid #fff; right: 3px; } .gal-image { order: 1; -webkit-flex: 1 0 auto; flex: 1 0 auto; display: -webkit-flex; display: flex; -webkit-align-items: flex-start; align-items: flex-start; -webkit-justify-content: space-around; justify-content: space-around; overflow: hidden; /* Flex > Non-Flex child max-width and overflow fix (Firefox only?) */ width: 1%; } :root:not(.gal-fit-height):not(.gal-pdf) .gal-image { overflow-y: scroll !important; } :root:not(.gal-fit-width):not(.gal-pdf) .gal-image { overflow-x: scroll !important; } .gal-image a { margin: auto; line-height: 0; max-width: 100%; } :root.gal-pdf .gal-image a { width: 100%; height: 100%; } .gal-fit-width .gal-image img, .gal-fit-width .gal-image video { max-width: 100%; } .gal-fit-height .gal-image img, .gal-fit-height .gal-image video { /* Chrome doesn't support viewpoint units in calc() http://bugs.chromium.org/168840 \"It looks like the original author of viewport units in WebKit is not coming back to fix this stuff.\" Well, fuck. */ max-height: 95vh; max-height: calc(100vh - 25px); } .gal-image iframe { width: 100%; height: 100%; } .gal-buttons { font-size: 2em; margin-right: 3px; padding-left: 7px; padding-right: 7px; top: 5px; } :root.gal-pdf .gal-buttons { top: 40px; background: rgba(0,0,0,0.6) !important; border-radius: 3px; } .gal-buttons a { color: #ffffff; text-shadow: 0px 0px 1px #000000; } .gal-buttons i { display: inline-block; margin: 2px; position: relative; } .gal-start i { border-left: 10px solid; border-top: 6px solid transparent; border-bottom: 6px solid transparent; bottom: 1px; } .gal-stop i { border: 5px solid; bottom: 2px; } .gal-buttons.gal-playing > .gal-start, .gal-buttons:not(.gal-playing) > .gal-stop { display: none; } .gal-buttons .menu-button i { border-top: 10px solid; border-right: 6px solid transparent; border-left: 6px solid transparent; bottom: 2px; vertical-align: baseline; } .gal-buttons, .gal-name, .gal-count { position: fixed; right: 195px; } .gal-hide-thumbnails .gal-buttons, .gal-hide-thumbnails .gal-count, .gal-hide-thumbnails .gal-name { right: 44px; } .gal-name { bottom: 6px; background: rgba(0,0,0,0.6) !important; border-radius: 3px; padding: 1px 5px 2px 5px; text-decoration: none !important; color: white !important; } .gal-name:hover, .gal-buttons a:hover { color: rgb(95, 95, 101) !important; } :root.gal-pdf .gal-buttons a:hover { color: rgb(204, 204, 204) !important; } .gal-count { bottom: 27px; background: rgba(0,0,0,0.6) !important; border-radius: 3px; padding: 1px 5px 2px 5px; color: #ffffff !important; } :root:not(.gal-fit-width):not(.gal-pdf) .gal-name { bottom: 23px !important; } :root:not(.gal-fit-width):not(.gal-pdf) .gal-count { bottom: 44px !important; } :root.gal-fit-height:not(.gal-pdf):not(.gal-hide-thumbnails) .gal-buttons, :root.gal-fit-height:not(.gal-pdf):not(.gal-hide-thumbnails) .gal-name, :root.gal-fit-height:not(.gal-pdf):not(.gal-hide-thumbnails) .gal-count { right: 178px !important; } :root.gal-hide-thumbnails:.gal-fit-height:not(.gal-pdf) .gal-buttons, :root.gal-hide-thumbnails:.gal-fit-height:not(.gal-pdf) .gal-name, :root.gal-hide-thumbnails:.gal-fit-height:not(.gal-pdf) .gal-count { right: 28px !important; } .field[name=\"Slide Delay\"] { width: 4em; } :root.gallery-open.fixed #header-bar:not(.autohide), :root.gallery-open.fixed #header-bar:not(.autohide) .fa::before { visibility: hidden; }\n/* General */ :root.yotsuba .dialog { background-color: #F0E0D6; border-color: #D9BFB7; } :root.yotsuba .field:focus { border-color: #EA8; } /* Header */ :root.yotsuba #header-bar.dialog { background-color: rgba(240,224,214,0.98); } :root.yotsuba #header-bar, :root.yotsuba #notifications { font-size: 9pt; color: #B86; } :root.yotsuba #board-list a, :root.yotsuba #shortcuts a { color: #800000; } :root.yotsuba.fixed #custom-board-list a.current { border-bottom: 1px solid rgba(178,0,0,0.2); } :root.yotsuba.fixed #custom-board-list .current:hover { border-bottom-color: rgba(255,0,0,0.2); } /* Settings */ :root.yotsuba #fourchanx-settings fieldset, :root.yotsuba .section-main div::before { border-color: #D9BFB7; } :root.yotsuba .suboption-list > div:last-of-type { background-color: #F0E0D6; } /* Quote */ :root.yotsuba .backlink.deadlink { color: #00E !important; } :root.yotsuba .inline { border-color: #D9BFB7; background-color: rgba(255, 255, 255, .14); } /* QR */ .yotsuba #dump-list::-webkit-scrollbar-thumb { background-color: #F0E0D6; border-color: #D9BFB7; } :root.yotsuba .qr-preview { background-color: rgba(0, 0, 0, .15); } :root.yotsuba .qr-link { border-color: rgb(225, 209, 199) rgb(225, 209, 199) rgb(210, 194, 184); background: linear-gradient(#FFEFE5, #F0E0D6) repeat scroll 0% 0% transparent; } :root.yotsuba .qr-link:hover { background: #F0E0D6; } /* Menu */ :root.yotsuba #menu { color: #800000; } :root.yotsuba .entry { font-size: 10pt; } :root.yotsuba .focused.entry { background: rgba(255, 255, 255, .33); } /* Thread Watcher */ :root.yotsuba .replies-quoting-you > a, :root.yotsuba #watcher-link.disabled.replies-quoting-you { color: #F00; } /* Watcher Favicon */ :root.yotsuba .watch-thread-link { background-image: url(\"data:image/svg+xml,<svg viewBox='0 0 26 26' preserveAspectRatio='true' xmlns='http://www.w3.org/2000/svg'><path fill='rgb(128,0,0)' d='M24.132,7.971c-2.203-2.205-5.916-2.098-8.25,0.235L15.5,8.588l-0.382-0.382c-2.334-2.333-6.047-2.44-8.25-0.235c-2.204,2.203-2.098,5.916,0.235,8.249l8.396,8.396l8.396-8.396C26.229,13.887,26.336,10.174,24.132,7.971z'/></svg>\"); } /* Board Title */ :root.yotsuba div.boardTitle { font-family: sans-serif !important; text-shadow: 1px 1px 1px rgba(100,0,0,0.6); }\n/* General */ :root.yotsuba-b .dialog { background-color: #D6DAF0; border-color: #B7C5D9; } :root.yotsuba-b .field:focus { border-color: #98E; } /* Header */ :root.yotsuba-b #header-bar.dialog { background-color: rgba(214,218,240,0.98); } :root.yotsuba-b #header-bar, :root.yotsuba-b #notifications { font-size: 9pt; color: #89A; } :root.yotsuba-b #board-list a, :root.yotsuba-b #shortcuts a { color: #34345C; } :root.yotsuba-b.fixed #custom-board-list .current { border-bottom: 1px solid rgba(30, 30, 255, 0.2); } :root.yotsuba-b.fixed #custom-board-list .current:hover { border-bottom-color: rgba(255,0,0,0.2); } /* Settings */ :root.yotsuba-b #fourchanx-settings fieldset, :root.yotsuba-b .section-main div::before { border-color: #B7C5D9; } :root.yotsuba-b .suboption-list > div:last-of-type { background-color: #D6DAF0; } /* Quote */ :root.yotsuba-b .backlink.deadlink { color: #34345C !important; } :root.yotsuba-b .inline { border-color: #B7C5D9; background-color: rgba(255, 255, 255, .14); } /* QR */ .yotsuba-b #dump-list::-webkit-scrollbar-thumb { background-color: #D6DAF0; border-color: #B7C5D9; } :root.yotsuba-b .qr-preview { background-color: rgba(0, 0, 0, .15); } :root.yotsuba-b .qr-link { border-color: rgb(199, 203, 225) rgb(199, 203, 225) rgb(184, 188, 210); background: linear-gradient(#E5E9FF, #D6DAF0) repeat scroll 0% 0% transparent; } :root.yotsuba-b .qr-link:hover { background: #D9DDF3; } /* Menu */ :root.yotsuba-b #menu { color: #000; } :root.yotsuba-b .entry { font-size: 10pt; } :root.yotsuba-b .focused.entry { background: rgba(255, 255, 255, .33); } /* Thread Watcher */ :root.yotsuba-b .replies-quoting-you > a, :root.yotsuba-b #watcher-link.disabled.replies-quoting-you { color: #F00; } /* Watcher Favicon */ :root.yotsuba-b .watch-thread-link { background-image: url(\"data:image/svg+xml,<svg viewBox='0 0 26 26' preserveAspectRatio='true' xmlns='http://www.w3.org/2000/svg'><path fill='rgb(0,0,0)' d='M24.132,7.971c-2.203-2.205-5.916-2.098-8.25,0.235L15.5,8.588l-0.382-0.382c-2.334-2.333-6.047-2.44-8.25-0.235c-2.204,2.203-2.098,5.916,0.235,8.249l8.396,8.396l8.396-8.396C26.229,13.887,26.336,10.174,24.132,7.971z'/></svg>\"); } /* Board Title */ :root.yotsuba-b div.boardTitle { font-family: sans-serif !important; text-shadow: 1px 1px 1px rgba(105,10,15,0.6); }\n/* General */ :root.futaba .dialog { background-color: #F0E0D6; border-color: #D9BFB7; } :root.futaba .field:focus { border-color: #EA8; } /* Header */ :root.futaba #header-bar.dialog { background-color: rgba(240,224,214,0.98); } :root.futaba #header-bar, :root.futaba #notifications { font-size: 11pt; color: #B86; } :root.futaba #header-bar a, :root.futaba #notifications a { color: #800000; } :root.futaba.fixed #custom-board-list a.current { border-bottom: 1px solid rgba(178,0,0,0.2); } :root.futaba.fixed #custom-board-list .current:hover { border-bottom-color: rgba(255,0,0,0.2); } /* Settings */ :root.futaba #fourchanx-settings fieldset, :root.futaba .section-main div::before { border-color: #D9BFB7; } :root.futaba .suboption-list > div:last-of-type { background-color: #F0E0D6; } /* Quote */ :root.futaba .backlink.deadlink { color: #00E !important; } :root.futaba .inline { border-color: #D9BFB7; background-color: rgba(255, 255, 255, .14); } /* QR */ .futaba #dump-list::-webkit-scrollbar-thumb { background-color: #F0E0D6; border-color: #D9BFB7; } :root.futaba .qr-preview { background-color: rgba(0, 0, 0, .15); } :root.futaba .qr-link { border-color: rgb(225, 209, 199) rgb(225, 209, 199) rgb(210, 194, 184); background: linear-gradient(#FFEFE5, #F0E0D6) repeat scroll 0% 0% transparent; } :root.futaba .qr-link:hover { background: #F0E0D6; } /* Menu */ :root.futaba #menu { color: #800000; } :root.futaba .entry { font-size: 12pt; } :root.futaba .focused.entry { background: rgba(255, 255, 255, .33); } /* Thread Watcher */ :root.futaba .replies-quoting-you > a, :root.futaba #watcher-link.disabled.replies-quoting-you { color: #F00; } /* Watcher Favicon */ :root.futaba .watch-thread-link { background-image: url(\"data:image/svg+xml,<svg viewBox='0 0 26 26' preserveAspectRatio='true' xmlns='http://www.w3.org/2000/svg'><path fill='rgb(128,0,0)' d='M24.132,7.971c-2.203-2.205-5.916-2.098-8.25,0.235L15.5,8.588l-0.382-0.382c-2.334-2.333-6.047-2.44-8.25-0.235c-2.204,2.203-2.098,5.916,0.235,8.249l8.396,8.396l8.396-8.396C26.229,13.887,26.336,10.174,24.132,7.971z'/></svg>\"); }\n/* General */ :root.burichan .dialog { background-color: #D6DAF0; border-color: #B7C5D9; } :root.burichan .field:focus { border-color: #98E; } /* Header */ :root.burichan #header-bar.dialog { background-color: rgba(214,218,240,0.98); } :root.burichan #header-bar, :root.burichan #header-bar #notifications { font-size: 11pt; color: #89A; } :root.burichan #header-bar a, :root.burichan #header-bar #notifications a { color: #34345C; } :root.burichan.fixed #custom-board-list .current { border-bottom: 1px solid rgba(30, 30, 255, 0.2); } :root.burichan.fixed #custom-board-list .current:hover { border-bottom-color: rgba(255,0,0,0.2); } /* Settings */ :root.burichan #fourchanx-settings fieldset, :root.burichan .section-main div::before { border-color: #B7C5D9; } :root.burichan .suboption-list > div:last-of-type { background-color: #D6DAF0; } /* Quote */ :root.burichan .backlink.deadlink { color: #34345C !important; } :root.burichan .inline { border-color: #B7C5D9; background-color: rgba(255, 255, 255, .14); } /* QR */ .burichan #dump-list::-webkit-scrollbar-thumb { background-color: #D6DAF0; border-color: #B7C5D9; } :root.burichan .qr-preview { background-color: rgba(0, 0, 0, .15); } :root.burichan .qr-link { border-color: rgb(199, 203, 225) rgb(199, 203, 225) rgb(184, 188, 210); background: linear-gradient(#E5E9FF, #D6DAF0) repeat scroll 0% 0% transparent; } :root.burichan .qr-link:hover { background: #D9DDF3; } /* Menu */ :root.burichan #menu { color: #000000; } :root.burichan .entry { font-size: 12pt; } :root.burichan .focused.entry { background: rgba(255, 255, 255, .33); } /* Thread Watcher */ :root.burichan .replies-quoting-you > a, :root.burichan #watcher-link.disabled.replies-quoting-you { color: #F00; } /* Watcher Favicon */ :root.burichan .watch-thread-link { background-image: url(\"data:image/svg+xml,<svg viewBox='0 0 26 26' preserveAspectRatio='true' xmlns='http://www.w3.org/2000/svg'><path fill='rgb(0,0,0)' d='M24.132,7.971c-2.203-2.205-5.916-2.098-8.25,0.235L15.5,8.588l-0.382-0.382c-2.334-2.333-6.047-2.44-8.25-0.235c-2.204,2.203-2.098,5.916,0.235,8.249l8.396,8.396l8.396-8.396C26.229,13.887,26.336,10.174,24.132,7.971z'/></svg>\"); }\n/* General */ :root.tomorrow .dialog { background-color: #282A2E; border-color: #111; } :root.tomorrow img[src*=\"//boards.4chan.org/js/jsMath/fonts/\"] { filter: invert(100%); } /* Header */ :root.tomorrow #header-bar.dialog { background-color: rgba(40,42,46,0.9); } :root.tomorrow #header-bar, :root.tomorrow #notifications { font-size: 9pt; color: #C5C8C6; } :root.tomorrow #header-bar a, :root.tomorrow #notifications a { color: #81A2BE; } :root.tomorrow.fixed #custom-board-list a.current { border-bottom: 1px solid rgba(83,124,160,0.4); } :root.tomorrow.fixed #custom-board-list .current:hover { border-bottom-color: rgba(95,137,172,0.4); } /* Settings */ :root.tomorrow #fourchanx-settings fieldset, :root.tomorrow .section-main div::before { border-color: #111; } :root.tomorrow .suboption-list > div:last-of-type { background-color: #282A2E; } /* Catalog */ :root.tomorrow .catalog-code { background-color: rgba(255, 255, 255, 0.1); } /* Quote */ :root.tomorrow .catalog-thread > .comment > span.quote, :root.tomorrow #arc-list span.quote { color: #B5BD68; } :root.tomorrow .backlink.deadlink { color: #81A2BE !important; } :root.tomorrow .inline { border-color: #111; background-color: rgba(0, 0, 0, .14); } /* QR */ .tomorrow #dump-list::-webkit-scrollbar-thumb { background-color: #282A2E; border-color: #111; } :root.tomorrow .qr-preview { background-color: rgba(255, 255, 255, .15); } :root.tomorrow #qr .field { background-color: rgb(26, 27, 29); color: rgb(197,200,198); border-color: rgb(40, 41, 42); } :root.tomorrow #qr .field:focus { border-color: rgb(129, 162, 190) !important; background-color: rgb(30,32,36); } :root.tomorrow #qr-filename { color: rgb(197,200,198); } :root.tomorrow .qr-link { border-color: rgb(25, 27, 31) rgb(25, 27, 31) rgb(10, 12, 16); background: linear-gradient(#37393D, #282A2E) repeat scroll 0% 0% transparent; } :root.tomorrow .qr-link:hover { background: #282A2E; } /* Menu */ :root.tomorrow #menu { color: #C5C8C6; } :root.tomorrow .entry { font-size: 10pt; } :root.tomorrow .focused.entry { background: rgba(0, 0, 0, .33); } /* Thread Watcher */ :root.tomorrow .replies-quoting-you > a, :root.tomorrow #watcher-link.disabled.replies-quoting-you { color: #F00 !important; } /* Watcher Favicon */ :root.tomorrow .watch-thread-link { background-image: url(\"data:image/svg+xml,<svg viewBox='0 0 26 26' preserveAspectRatio='true' xmlns='http://www.w3.org/2000/svg'><path fill='rgb(197,200,198)' d='M24.132,7.971c-2.203-2.205-5.916-2.098-8.25,0.235L15.5,8.588l-0.382-0.382c-2.334-2.333-6.047-2.44-8.25-0.235c-2.204,2.203-2.098,5.916,0.235,8.249l8.396,8.396l8.396-8.396C26.229,13.887,26.336,10.174,24.132,7.971z'/></svg>\"); } /* Board Title */ :root.tomorrow div.boardTitle { font-family: sans-serif !important; text-shadow: 1px 1px 1px rgba(167,170,168,0.6); }\n/* General */ :root.photon .dialog { background-color: #DDD; border-color: #CCC; } :root.photon .field:focus { border-color: #EA8; } /* Header */ :root.photon #header-bar.dialog { background-color: rgba(221,221,221,0.98); } :root.photon #header-bar, :root.photon #notifications { font-size: 9pt; color: #333; } :root.photon #header-bar a, :root.photon #notifications a { color: #FF6600; } :root.photon.fixed #custom-board-list a.current { border-bottom: 1px solid rgba(0,74,153,0.2); } :root.photon.fixed #custom-board-list .current:hover { border-bottom-color: rgba(255,51,0,0.2); } /* Settings */ :root.photon #fourchanx-settings fieldset, :root.photon .section-main div::before { border-color: #CCC; } :root.photon .suboption-list > div:last-of-type { background-color: #DDD; } /* Catalog */ :root.photon .catalog-code { background-color: rgba(150, 150, 150, 0.2); } /* Quote */ :root.photon #arc-list tr:nth-of-type(odd) span.quote { color: #C0E17A; } :root.photon .backlink.deadlink { color: #F60 !important; } :root.photon .inline { border-color: #CCC; background-color: rgba(255, 255, 255, .14); } /* QR */ .photon #dump-list::-webkit-scrollbar-thumb { background-color: #DDD; border-color: #CCC; } :root.photon .qr-preview { background-color: rgba(0, 0, 0, .15); } :root.photon .qr-link { border-color: rgb(206, 206, 206) rgb(206, 206, 206) rgb(191, 191, 191); background: linear-gradient(#ECECEC, #DDD) repeat scroll 0% 0% transparent; } :root.photon .qr-link:hover { background: #DDDDDD; } /* Menu */ :root.photon #menu { color: #333; } :root.photon .entry { font-size: 10pt; } :root.photon .focused.entry { background: rgba(255, 255, 255, .33); } /* Thread Watcher */ :root.photon .replies-quoting-you > a, :root.photon #watcher-link.disabled.replies-quoting-you { color: #00F !important; } /* Watcher Favicon */ :root.photon .watch-thread-link { background-image: url(\"data:image/svg+xml,<svg viewBox='0 0 26 26' preserveAspectRatio='true' xmlns='http://www.w3.org/2000/svg'><path fill='rgb(51,51,51)' d='M24.132,7.971c-2.203-2.205-5.916-2.098-8.25,0.235L15.5,8.588l-0.382-0.382c-2.334-2.333-6.047-2.44-8.25-0.235c-2.204,2.203-2.098,5.916,0.235,8.249l8.396,8.396l8.396-8.396C26.229,13.887,26.336,10.174,24.132,7.971z'/></svg>\"); } /* Board Title */ :root.photon div.boardTitle { font-family: sans-serif !important; text-shadow: 1px 1px 1px rgba(0,74,153,0.6); }",
features: [['Polyfill', Polyfill], ['Redirect', Redirect], ['Header', Header], ['Catalog Links', CatalogLinks], ['Settings', Settings], ['Index Generator', Index], ['Disable Autoplay', AntiAutoplay], ['Announcement Hiding', PSAHiding], ['Fourchan thingies', Fourchan], ['Color User IDs', IDColor], ['Highlight by User ID', IDHighlight], ['Custom CSS', CustomCSS], ['Linkify', Linkify], ['Reveal Spoilers', RemoveSpoilers], ['Resurrect Quotes', Quotify], ['Filter', Filter], ['Thread Hiding Buttons', ThreadHiding], ['Reply Hiding Buttons', PostHiding], ['Recursive', Recursive], ['Strike-through Quotes', QuoteStrikeThrough], ['Quick Reply', QR], ['Menu', Menu], ['Index Generator (Menu)', Index.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], ['Gallery', Gallery], ['Gallery (menu)', Gallery.menu], ['Sauce', Sauce], ['Image Expansion', ImageExpand], ['Image Expansion (Menu)', ImageExpand.menu], ['Reveal Spoiler Thumbnails', RevealSpoilers], ['Image Loading', ImageLoader], ['Image Hover', ImageHover], ['Volume Control', Volume], ['WEBM Metadata', Metadata], ['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], ['Thread Watcher (Menu)', ThreadWatcher.menu], ['Mark New IPs', MarkNewIPs], ['Index Navigation', Nav], ['Keybinds', Keybinds], ['Banner', Banner]]
};
Main.init();
}).call(this);