diff --git a/CHANGELOG.md b/CHANGELOG.md index bf2597c30..a78b546ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ Sometimes the changelog has notes (not comprehensive) acknowledging people's work. This does not mean the changes are their fault, only that their code was used. All changes to the script are chosen by and the fault of the maintainer (ccd0). +### v1.11.31 + +**v1.11.31.0** *(2016-04-21)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.11.31.0/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.11.31.0/builds/4chan-X-noupdate.crx "Chromium version")] +- Based on v1.11.30.3. +- Fix scrolling issue that happened when `Reply Pruning` removes posts from above you in a thread. +- Fix race condition causing persona data to occasionally not be filled into posts. +- Improve connection error message, remove link to banned page. + ### v1.11.30 **v1.11.30.3** *(2016-04-09)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.11.30.3/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.11.30.3/builds/4chan-X-noupdate.crx "Chromium version")] diff --git a/builds/4chan-X-beta.crx b/builds/4chan-X-beta.crx index 7eb21004d..de54a68a6 100644 Binary files a/builds/4chan-X-beta.crx and b/builds/4chan-X-beta.crx differ diff --git a/builds/4chan-X-beta.meta.js b/builds/4chan-X-beta.meta.js index c07def64c..852af908b 100644 --- a/builds/4chan-X-beta.meta.js +++ b/builds/4chan-X-beta.meta.js @@ -1,6 +1,6 @@ // ==UserScript== // @name 4chan X beta -// @version 1.11.30.3 +// @version 1.11.31.0 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X diff --git a/builds/4chan-X-beta.user.js b/builds/4chan-X-beta.user.js index b91ca6af8..ddc829c9d 100644 --- a/builds/4chan-X-beta.user.js +++ b/builds/4chan-X-beta.user.js @@ -1,7 +1,6 @@ -// Generated by CoffeeScript // ==UserScript== // @name 4chan X beta -// @version 1.11.30.3 +// @version 1.11.31.0 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X @@ -107,7 +106,7 @@ /* * Contains data from external sources: * -* audio/beep.wav from http://freesound.org/people/pierrecartoons1979/sounds/90112/ +* src/Monitoring/ThreadUpdater/beep.wav from http://freesound.org/people/pierrecartoons1979/sounds/90112/ * cc-by-nc-3.0 * * Font Awesome by Dave Gandy (http://fontawesome.io) @@ -119,12 +118,56 @@ '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, Flash, Fourchan, Gallery, Get, Header, IDColor, IDHighlight, ImageCommon, ImageExpand, ImageHover, ImageLoader, Index, Keybinds, Linkify, Main, MarkNewIPs, Menu, Metadata, Nav, NormalizeURL, Notice, PSAHiding, PassLink, Polyfill, Post, PostHiding, PostSuccessful, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, RandomAccessList, Recursive, Redirect, RelativeDates, RemoveSpoilers, ReplyPruning, Report, ReportLink, RevealSpoilers, Sauce, Settings, ShimSet, SimpleDict, Thread, ThreadExcerpt, ThreadHiding, ThreadLinks, 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; }, - extend = 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; }, - hasProp = {}.hasOwnProperty, - bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + +var $, $$, Anonymize, AntiAutoplay, ArchiveLink, Banner, Board, Build, CSS, Callbacks, Captcha, CatalogLinks, CatalogThread, Config, Connection, CrossOrigin, CustomCSS, DataBoard, DeleteLink, DownloadLink, Embedding, ExpandComment, ExpandThread, FappeTyme, Favicon, Fetcher, FileInfo, Filter, Flash, Fourchan, Gallery, Get, Header, IDColor, IDHighlight, ImageCommon, ImageExpand, ImageHover, ImageLoader, Index, Keybinds, Linkify, Main, MarkNewIPs, Menu, Metadata, Nav, NormalizeURL, Notice, PSAHiding, PassLink, Polyfill, Post, PostHiding, PostSuccessful, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, RandomAccessList, Recursive, Redirect, RelativeDates, RemoveSpoilers, ReplyPruning, Report, ReportLink, RevealSpoilers, Sauce, Settings, ShimSet, SimpleDict, Thread, ThreadExcerpt, ThreadHiding, ThreadLinks, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, Volume; + +var Conf, E, c, d, doc, g; + +Conf = {}; +c = console; +d = document; +doc = d.documentElement; + +g = { + VERSION: '1.11.31.0', + NAMESPACE: '4chan X.', + 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); + }; +})(); + +E.cat = function(templates) { + var html, i, len; + html = ''; + for (i = 0, len = templates.length; i < len; i++) { + html += templates[i].innerHTML; + } + return html; +}; + +E.url = function(content) { + return "data:text/html;charset=utf-8," + encodeURIComponent(content.innerHTML); +}; + +Config = (function() { + var Config; Config = { main: { @@ -368,7 +411,7 @@ ":root.tomorrow div.boardTitle {\n" + " font-family: sans-serif !important;\n" + " text-shadow: 1px 1px 1px rgba(167,170,168,0.6);\n" + -"}", +"}\n", hotkeys: { 'Toggle board list': ['Ctrl+b', 'Toggle the full board list.'], 'Toggle header': ['Shift+h', 'Toggle the auto-hide option of the header.'], @@ -434,18204 +477,23 @@ 'Autohiding Scrollbar': false }; - Conf = {}; + return Config; - c = console; +}).call(this); - d = document; +CSS = { - doc = d.documentElement; - - g = { - VERSION: '1.11.30.3', - NAMESPACE: '4chan X.', - 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); - }; - })(); - - E.cat = function(templates) { - var html, k, len1, x; - html = ''; - for (k = 0, len1 = templates.length; k < len1; k++) { - x = templates[k]; - html += x.innerHTML; - } - return html; - }; - - E.url = function(content) { - return "data:text/html;charset=utf-8," + (encodeURIComponent(content.innerHTML)); - }; - - $ = 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: "4chan X was blocked from loading the following URL:

[More info]" - }); - $('span', message).textContent = (/^\/\//.test(url) ? location.protocol : '') + url; - return new Notice('warning', message, 30, function() { - return delete blockedURLs[url]; - }); - }; - return function(url, options, extra) { - var err, event, form, k, len1, r, ref, ref1, type, upCallbacks, whenModified; - if (options == null) { - options = {}; - } - if (extra == null) { - extra = {}; - } - type = extra.type, whenModified = extra.whenModified, upCallbacks = extra.upCallbacks, form = extra.form; - url = url.replace(/^((?:https?:)?\/\/(?:\w+\.)?4c(?:ha|d)n\.org)\/adv\//, '$1//adv/'); - r = new XMLHttpRequest(); - type || (type = form && 'post' || 'get'); - try { - r.open(type, url, true); - } catch (_error) { - err = _error; - blockedError(url); - ref = ['error', 'loadend']; - for (k = 0, len1 = ref.length; k < len1; k++) { - event = ref[k]; - r["on" + event] = options["on" + event]; - $.queueTask($.event, event, null, r); - } - return; - } - if (whenModified) { - if (((ref1 = lastModified[whenModified]) != null ? ref1[url] : void 0) != null) { - r.setRequestHeader('If-Modified-Since', lastModified[whenModified][url]); - } - $.on(r, 'load', function() { - return (lastModified[whenModified] || (lastModified[whenModified] = {}))[url] = r.getResponseHeader('Last-Modified'); - }); - } - if (/\.json$/.test(url)) { - if (options.responseType == null) { - options.responseType = 'json'; - } - } - $.extend(r, options); - if (options.responseType === 'json' && r.responseType !== 'json' && delete r.response) { - Object.defineProperty(r, 'response', { - configurable: true, - enumerable: true, - get: function() { - return JSON.parse(r.responseText); - } - }); - } - $.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, true); - }); - } 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 fn1, k, len1, ref; - this.evt = e; - ref = this.callbacks; - fn1 = (function(_this) { - return function(cb) { - return $.queueTask(function() { - return cb.call(_this, e, false); - }); - }; - })(this); - for (k = 0, len1 = ref.length; k < len1; k++) { - cb = ref[k]; - fn1(cb); - } - 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, cb) { - var el, observer; - if (el = $(selector, root)) { - return cb(el); - } - if ($.engine === 'edge' && d.readyState === 'loading') { - $.asap((function() { - return d.readyState !== 'loading' || $(selector, root); - }), function() { - return $.onExists(root, selector, cb); - }); - return; - } - observer = new MutationObserver(function() { - if (el = $(selector, root)) { - observer.disconnect(); - return cb(el); - } - }); - return observer.observe(root, { - childList: true, - subtree: true - }); - }; - - $.addStyle = function(css, id, test) { - var style; - if (test == null) { - test = 'head'; - } - style = $.el('style', { - textContent: css - }); - if (id != null) { - style.id = id; - } - $.onExists(doc, 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, k, len1; - el = arguments[0], classNames = 2 <= arguments.length ? slice.call(arguments, 1) : []; - for (k = 0, len1 = classNames.length; k < len1; k++) { - className = classNames[k]; - el.classList.add(className); - } - }; - - $.rmClass = function() { - var className, classNames, el, k, len1; - el = arguments[0], classNames = 2 <= arguments.length ? slice.call(arguments, 1) : []; - for (k = 0, len1 = classNames.length; k < len1; k++) { - className = classNames[k]; - 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 != null ? el.remove() : void 0; - }; - - $.rmAll = function(root) { - return root.textContent = null; - }; - - $.tn = function(s) { - return d.createTextNode(s); - }; - - $.frag = function() { - return d.createDocumentFragment(); - }; - - $.nodes = function(nodes) { - var frag, k, len1, node; - if (!(nodes instanceof Array)) { - return nodes; - } - frag = $.frag(); - for (k = 0, len1 = nodes.length; k < len1; k++) { - node = nodes[k]; - 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, properties2) { - var el; - el = d.createElement(tag); - if (properties) { - $.extend(el, properties); - } - if (properties2) { - $.extend(el, properties2); - } - return el; - }; - - $.on = function(el, events, handler) { - var event, k, len1, ref; - ref = events.split(' '); - for (k = 0, len1 = ref.length; k < len1; k++) { - event = ref[k]; - el.addEventListener(event, handler, false); - } - }; - - $.off = function(el, events, handler) { - var event, k, len1, ref; - ref = events.split(' '); - for (k = 0, len1 = ref.length; k < len1; k++) { - event = ref[k]; - 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 - })); - }; - - (function() { - var clone, err, ref, unsafeConstructors; - if (!(/PaleMoon\//.test(navigator.userAgent) && +(typeof GM_info !== "undefined" && GM_info !== null ? (ref = GM_info.version) != null ? ref.split('.')[0] : void 0 : void 0) >= 2 && typeof cloneInto === 'undefined')) { - return; - } - try { - return new CustomEvent('x', { - detail: {} - }); - } catch (_error) { - err = _error; - unsafeConstructors = { - Object: unsafeWindow.Object, - Array: unsafeWindow.Array - }; - clone = function(obj) { - var constructor, key, obj2, val; - if ((obj != null) && typeof obj === 'object' && (constructor = unsafeConstructors[obj.constructor.name])) { - obj2 = new constructor(); - for (key in obj) { - val = obj[key]; - obj2[key] = clone(val); - } - return obj2; - } else { - return obj; - } - }; - return $.event = function(event, detail, root) { - if (root == null) { - root = d; - } - return root.dispatchEvent(new CustomEvent(event, { - bubbles: true, - detail: clone(detail) - })); - }; - } - })(); - - $.open = typeof GM_openInTab !== "undefined" && GM_openInTab !== null ? GM_openInTab : function(url) { - return window.open(url, '_blank'); - }; - - $.debounce = function(wait, fn) { - var args, exec, lastCall, that, timeout; - lastCall = 0; - timeout = null; - that = null; - args = null; - exec = function() { - lastCall = Date.now(); - return fn.apply(that, args); - }; - return function() { - args = arguments; - that = this; - if (lastCall < Date.now() - wait) { - return exec(); - } - clearTimeout(timeout); - return timeout = setTimeout(exec, wait); - }; - }; - - $.queueTask = (function() { - var execTask, taskChannel, taskQueue; - taskQueue = []; - execTask = function() { - var args, func, task; - task = taskQueue.shift(); - func = task[0]; - args = Array.prototype.slice.call(task, 1); - return func.apply(func, args); - }; - if (window.MessageChannel) { - taskChannel = new MessageChannel(); - taskChannel.port1.onmessage = execTask; - return function() { - taskQueue.push(arguments); - return taskChannel.port2.postMessage(null); - }; - } else { - return function() { - taskQueue.push(arguments); - return setTimeout(execTask, 0); - }; - } - })(); - - $.globalEval = function(code) { - var script; - script = $.el('script', { - textContent: code - }); - $.add(d.head || doc, script); - return $.rm(script); - }; - - $.global = function(fn) { - if (doc) { - return $.globalEval("(" + fn + ")();"); - } else { - return fn(); - } - }; - - $.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; - }; - - $.engine = (function() { - if (/Edge\//.test(navigator.userAgent)) { - return 'edge'; - } - if (/Chrome\//.test(navigator.userAgent)) { - return 'blink'; - } - if (/WebKit\//.test(navigator.userAgent)) { - return 'webkit'; - } - if (/Gecko\/|Goanna/.test(navigator.userAgent)) { - return 'gecko'; - } - })(); - - try { - localStorage.getItem('x'); - $.hasStorage = true; - } catch (_error) { - $.hasStorage = false; - } - - $.item = function(key, val) { - var item; - item = {}; - item[key] = val; - return item; - }; - - $.syncing = {}; - - if (typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null) { - $.getValue = GM_getValue; - $.listValues = function() { - return GM_listValues(); - }; - } else if ($.hasStorage) { - $.getValue = function(key) { - return localStorage[key]; - }; - $.listValues = function() { - var key, results; - results = []; - for (key in localStorage) { - if (key.slice(0, g.NAMESPACE.length) === g.NAMESPACE) { - results.push(key); - } - } - return results; - }; - } else { - $.getValue = function() {}; - $.listValues = function() { - return []; - }; - } - - if (typeof GM_addValueChangeListener !== "undefined" && GM_addValueChangeListener !== null) { - $.setValue = GM_setValue; - $.deleteValue = GM_deleteValue; - } else if (typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null) { - $.oldValue = {}; - $.setValue = function(key, val) { - GM_setValue(key, val); - if (key in $.syncing) { - $.oldValue[key] = val; - if ($.hasStorage) { - return localStorage[key] = val; - } - } - }; - $.deleteValue = function(key) { - GM_deleteValue(key); - if (key in $.syncing) { - delete $.oldValue[key]; - if ($.hasStorage) { - return localStorage.removeItem(key); - } - } - }; - if (!$.hasStorage) { - $.cantSync = true; - } - } else if ($.hasStorage) { - $.oldValue = {}; - $.setValue = function(key, val) { - if (key in $.syncing) { - $.oldValue[key] = val; - } - return localStorage[key] = val; - }; - $.deleteValue = function(key) { - if (key in $.syncing) { - delete $.oldValue[key]; - } - return localStorage.removeItem(key); - }; - } else { - $.setValue = function() {}; - $.deleteValue = function() {}; - $.cantSync = $.cantSet = true; - } - - if (typeof GM_addValueChangeListener !== "undefined" && GM_addValueChangeListener !== null) { - $.sync = function(key, cb) { - return $.syncing[key] = GM_addValueChangeListener(g.NAMESPACE + key, function(key2, oldValue, newValue, remote) { - if (remote) { - if (newValue !== void 0) { - newValue = JSON.parse(newValue); - } - return cb(newValue, key); - } - }); - }; - $.forceSync = function() {}; - } else if ((typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null) || $.hasStorage) { - $.sync = function(key, cb) { - key = g.NAMESPACE + key; - $.syncing[key] = cb; - return $.oldValue[key] = $.getValue(key); - }; - (function() { - var onChange; - onChange = function(arg) { - var cb, key, newValue; - key = arg.key, newValue = arg.newValue; - if (!(cb = $.syncing[key])) { - return; - } - if (newValue != null) { - if (newValue === $.oldValue[key]) { - return; - } - $.oldValue[key] = newValue; - return cb(JSON.parse(newValue), key.slice(g.NAMESPACE.length)); - } else { - if ($.oldValue[key] == null) { - return; - } - delete $.oldValue[key]; - return cb(void 0, key.slice(g.NAMESPACE.length)); - } - }; - $.on(window, 'storage', onChange); - return $.forceSync = function(key) { - key = g.NAMESPACE + key; - return onChange({ - key: key, - newValue: $.getValue(key) - }); - }; - })(); - } else { - $.sync = function() {}; - $.forceSync = function() {}; - } - - $["delete"] = function(keys) { - var k, key, len1; - if (!(keys instanceof Array)) { - keys = [keys]; - } - for (k = 0, len1 = keys.length; k < len1; k++) { - key = keys[k]; - $.deleteValue(g.NAMESPACE + 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 = $.getValue(g.NAMESPACE + key)) { - items[key] = JSON.parse(val); - } - } - return cb(items); - }); - }; - - $.set = function(keys, val, cb) { - var key, value; - if (typeof keys === 'string') { - $.setValue(g.NAMESPACE + keys, JSON.stringify(val)); - } else { - for (key in keys) { - value = keys[key]; - $.setValue(g.NAMESPACE + key, JSON.stringify(value)); - } - cb = val; - } - return typeof cb === "function" ? cb() : void 0; - }; - - $.clear = function(cb) { - var id; - $["delete"](Object.keys(Conf)); - $["delete"](['previousversion', 'AutoWatch', 'QR Size', 'captchas', 'QR.persona', 'hiddenPSA']); - $["delete"]((function() { - var k, len1, ref, results; - ref = ['embedding', 'updater', 'thread-stats', 'thread-watcher', 'qr']; - results = []; - for (k = 0, len1 = ref.length; k < len1; k++) { - id = ref[k]; - results.push(id + ".position"); - } - return results; - })()); - try { - $["delete"]($.listValues().map(function(key) { - return key.replace(g.NAMESPACE, ''); - })); - } catch (_error) {} - 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(type1) { - this.type = type1; - 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, keys) { - var err, errors, k, len1, name, ref; - if (keys == null) { - keys = this.keys; - } - for (k = 0, len1 = keys.length; k < len1; k++) { - name = keys[k]; - try { - if ((ref = this[name]) != null) { - ref.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(ID1) { - this.ID = ID1; - 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(ID1, board1) { - this.ID = ID1; - this.board = board1; - 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; - this.board.threads.push(this.ID, this); - g.threads.push(this.fullID, 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, thread1) { - this.thread = thread1; - 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, thread1, board1) { - var capcode, clone, date, email, flag, info, k, len1, name, post, ref, subject, tripcode, uniqueID; - this.thread = thread1; - this.board = board1; - this.ID = +root.id.slice(2); - this.fullID = this.board + "." + this.ID; - this.context = this; - root.dataset.fullID = this.fullID; - 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: [] - }; - if ($.engine === 'edge') { - Object.defineProperty(this.nodes, 'backlinks', { - configurable: true, - enumerable: true, - get: function() { - return info.getElementsByClassName('backlink'); - } - }); - } else { - this.nodes.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 || void 0; - } - 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(); - 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 (k = 0, len1 = ref.length; k < len1; k++) { - clone = ref[k]; - clone.origin = this; - } - } - this.board.posts.push(this.ID, this); - this.thread.posts.push(this.ID, this); - g.posts.push(this.fullID, this); - } - - Post.prototype.parseComment = function() { - var abbr, bq, commentDisplay, k, len1, len2, node, q, ref, spoilers; - this.nodes.comment.normalize(); - bq = this.nodes.comment.cloneNode(true); - ref = $$('.abbr + br, .exif, b, .fortune', bq); - for (k = 0, len1 = ref.length; k < len1; k++) { - node = ref[k]; - $.rm(node); - } - if (abbr = $('.abbr', bq)) { - $.rm(abbr); - } - this.info.comment = this.nodesToText(bq); - if (abbr) { - this.info.comment = this.info.comment.replace(/\n\n$/, ''); - } - commentDisplay = this.info.comment; - if (!(Conf['Remove Spoilers'] || Conf['Reveal Spoilers'])) { - spoilers = $$('s', bq); - if (spoilers.length) { - for (q = 0, len2 = spoilers.length; q < len2; q++) { - node = spoilers[q]; - $.replace(node, $.tn('[spoiler]')); - } - commentDisplay = this.nodesToText(bq); - } - } - return this.info.commentDisplay = commentDisplay.trim().replace(/\s+$/gm, ''); - }; - - 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; - }; - - Post.prototype.parseQuotes = function() { - var k, len1, quotelink, ref; - this.quotes = []; - ref = $$(':not(pre) > .quotelink', this.nodes.comment); - for (k = 0, len1 = ref.length; k < len1; k++) { - quotelink = ref[k]; - this.parseQuote(quotelink); - } - }; - - Post.prototype.parseQuote = function(quotelink) { - var fullID, match; - match = quotelink.href.match(/^https?:\/\/boards\.4chan\.org\/+([^\/]+)\/+(?:res|thread)\/+\d+(?:\/[^#]*)?#p(\d+)$/); - if (!(match || (this.isClone && quotelink.dataset.postID))) { - 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() { - var fileEl, fileText, info, link, m, ref, ref1, ref2, size, thumb, unit; - if (!(fileEl = $('.file', this.nodes.post))) { - return; - } - if (!(link = $('.fileText > a, .fileText-original > a', fileEl))) { - return; - } - if (!(info = (ref = link.nextSibling) != null ? ref.textContent.match(/\(([\d.]+ [KMG]?B).*\)/) : void 0)) { - return; - } - fileText = fileEl.firstElementChild; - this.file = { - text: fileText, - link: link, - url: link.href, - name: fileText.title || link.title || link.textContent, - size: info[1], - isImage: /(jpg|png|gif)$/i.test(link.href), - isVideo: /webm$/i.test(link.href), - dimensions: (ref1 = info[0].match(/\d+x\d+/)) != null ? ref1[0] : void 0, - tag: (ref2 = info[0].match(/,[^,]*, ([a-z]+)\)/i)) != null ? ref2[1] : void 0 - }; - 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; - if ((thumb = $('.fileThumb > [data-md5]', fileEl))) { - return $.extend(this.file, { - thumb: thumb, - thumbURL: (m = link.href.match(/\d+(?=\.\w+$)/)) ? location.protocol + "//i.4cdn.org/" + this.board + "/" + m[0] + "s.jpg" : void 0, - MD5: thumb.dataset.md5, - isSpoiler: $.hasClass(thumb.parentNode, 'imgspoiler') - }); - } - }; - - Post.prototype.kill = function(file) { - var clone, k, len1, len2, q, quotelink, ref, ref1, strong; - 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 (k = 0, len1 = ref.length; k < len1; k++) { - clone = ref[k]; - clone.kill(file); - } - if (file) { - return; - } - ref1 = Get.allQuotelinksLinkingTo(this); - for (q = 0, len2 = ref1.length; q < len2; q++) { - quotelink = ref1[q]; - if (!(!$.hasClass(quotelink, 'deadlink'))) { - continue; - } - quotelink.textContent = quotelink.textContent + '\u00A0(Dead)'; - $.addClass(quotelink, 'deadlink'); - } - }; - - Post.prototype.resurrect = function() { - var clone, k, len1, len2, q, quotelink, ref, ref1, strong; - this.isDead = false; - $.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 (k = 0, len1 = ref.length; k < len1; k++) { - clone = ref[k]; - clone.resurrect(); - } - ref1 = Get.allQuotelinksLinkingTo(this); - for (q = 0, len2 = ref1.length; q < len2; q++) { - quotelink = ref1[q]; - if (!($.hasClass(quotelink, 'deadlink'))) { - continue; - } - quotelink.textContent = quotelink.textContent.replace('\u00A0(Dead)', ''); - $.rmClass(quotelink, 'deadlink'); - } - }; - - Post.prototype.collect = function() { - 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, k, len1, ref; - this.clones.splice(index, 1); - ref = this.clones.slice(index); - for (k = 0, len1 = ref.length; k < len1; k++) { - clone = ref[k]; - clone.nodes.root.dataset.clone = index++; - } - }; - - return Post; - - })(); - - Clone = (function(superClass) { - extend(Clone, superClass); - - Clone.prototype.isClone = true; - - function Clone(origin1, context1, contractThumb) { - var file, info, inline, inlined, k, key, len1, len2, len3, len4, node, nodes, post, q, ref, ref1, ref2, ref3, ref4, ref5, root, u, v, val; - this.origin = origin1; - this.context = context1; - ref = ['ID', 'fullID', 'board', 'thread', 'info', 'quotes', 'isReply']; - for (k = 0, len1 = ref.length; k < len1; k++) { - key = ref[k]; - this[key] = this.origin[key]; - } - nodes = this.origin.nodes; - root = contractThumb ? this.cloneWithoutVideo(nodes.root) : nodes.root.cloneNode(true); - Clone.prefix || (Clone.prefix = 0); - ref1 = [root].concat(slice.call($$('[id]', root))); - for (q = 0, len2 = ref1.length; q < len2; q++) { - node = ref1[q]; - node.id = Clone.prefix + node.id; - } - Clone.prefix++; - 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: [] - }; - if ($.engine === 'edge') { - Object.defineProperty(this.nodes, 'backlinks', { - configurable: true, - enumerable: true, - get: function() { - return info.getElementsByClassName('backlink'); - } - }); - } else { - this.nodes.backlinks = info.getElementsByClassName('backlink'); - } - ref2 = $$('.inline', post); - for (u = 0, len3 = ref2.length; u < len3; u++) { - inline = ref2[u]; - $.rm(inline); - } - ref3 = $$('.inlined', post); - for (v = 0, len4 = ref3.length; v < len4; v++) { - inlined = ref3[v]; - $.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(); - this.quotes = slice.call(this.origin.quotes); - if (this.origin.file) { - this.file = {}; - ref4 = this.origin.file; - for (key in ref4) { - val = ref4[key]; - this.file[key] = val; - } - file = $('.file', post); - this.file.text = file.firstElementChild; - this.file.link = $('.fileText > a, .fileText-original', file); - 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 ((ref5 = this.file.thumb) != null ? ref5.dataset.src : void 0) { - this.file.thumb.src = this.file.thumb.dataset.src; - this.file.thumb.removeAttribute('data-src'); - } - if (this.file.thumb && contractThumb) { - ImageExpand.contract(this); - } - } - if (this.origin.isDead) { - this.isDead = true; - } - root.dataset.clone = this.origin.clones.push(this) - 1; - } - - Clone.prototype.cloneWithoutVideo = function(node) { - var child, clone, k, len1, 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 (k = 0, len1 = ref.length; k < len1; k++) { - child = ref[k]; - $.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(key1, sync, dontClean) { - var init; - this.key = key1; - this.onSync = bind(this.onSync, this); - this.data = Conf[this.key]; - $.sync(this.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(cb) { - return $.set(this.key, this.data, cb); - }; - - DataBoard.prototype["delete"] = function(arg) { - var boardID, postID, ref, threadID; - 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, cb) { - var base1, base2, base3, boardID, postID, threadID, val; - boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, val = arg.val; - $.forceSync(this.key); - if (postID !== void 0) { - ((base1 = ((base2 = this.data.boards)[boardID] || (base2[boardID] = {})))[threadID] || (base1[threadID] = {}))[postID] = val; - } else if (threadID !== void 0) { - ((base3 = this.data.boards)[boardID] || (base3[boardID] = {}))[threadID] = val; - } else { - this.data.boards[boardID] = val; - } - return this.save(cb); - }; - - DataBoard.prototype.get = function(arg) { - var ID, board, boardID, defaultValue, k, len1, postID, thread, threadID, val; - boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, defaultValue = arg.defaultValue; - if (board = this.data.boards[boardID]) { - if (threadID == null) { - if (postID != null) { - for (thread = k = 0, len1 = board.length; k < len1; thread = ++k) { - ID = board[thread]; - if (postID in thread) { - val = thread[postID]; - break; - } - } - } else { - val = board; - } - } else if (thread = board[threadID]) { - val = postID != null ? thread[postID] : thread; - } - } - return val || defaultValue; - }; - - DataBoard.prototype.forceSync = function() { - return $.forceSync(this.key); - }; - - DataBoard.prototype.clean = function() { - var boardID, now, ref, val; - $.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) { - this.ajaxClean(boardID); - } - } - }; - - DataBoard.prototype.ajaxClean = function(boardID) { - return $.cache("//a.4cdn.org/" + boardID + "/threads.json", (function(_this) { - return function(e1) { - var ref; - if ((ref = e1.target.status) !== 200 && ref !== 404) { - return; - } - return $.cache("//a.4cdn.org/" + boardID + "/archive.json", function(e2) { - var ref1; - if ((ref1 = e2.target.status) !== 200 && ref1 !== 404) { - return; - } - return _this.ajaxCleanParse(boardID, e1.target.response, e2.target.response); - }); - }; - })(this)); - }; - - DataBoard.prototype.ajaxCleanParse = function(boardID, response1, response2) { - var ID, board, k, len1, len2, len3, page, q, ref, thread, threads, u; - if (!(board = this.data.boards[boardID])) { - return; - } - threads = {}; - if (response1) { - for (k = 0, len1 = response1.length; k < len1; k++) { - page = response1[k]; - ref = page.threads; - for (q = 0, len2 = ref.length; q < len2; q++) { - thread = ref[q]; - ID = thread.no; - if (ID in board) { - threads[ID] = board[ID]; - } - } - } - } - if (response2) { - for (u = 0, len3 = response2.length; u < len3; u++) { - ID = response2[u]; - if (ID in board) { - threads[ID] = board[ID]; - } - } - } - this.data.boards[boardID] = threads; - this.deleteIfEmpty({ - boardID: boardID - }); - return this.save(); - }; - - 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, timeout1, onclose) { - this.timeout = timeout1; - this.onclose = onclose; - this.close = bind(this.close, this); - this.add = bind(this.add, this); - this.el = $.el('div', { - innerHTML: "
" - }); - this.el.style.opacity = 0; - this.setType(type); - $.on(this.el.firstElementChild, 'click', this.close); - if (typeof content === 'string') { - content = $.tn(content); - } - $.add(this.el.lastElementChild, content); - $.ready(this.add); - } - - 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, k, len1; - this.length = 0; - if (items) { - for (k = 0, len1 = items.length; k < len1; k++) { - item = items[k]; - 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 k, key, len1, ref; - ref = slice.call(this.keys); - for (k = 0, len1 = ref.length; k < len1; k++) { - key = ref[k]; - 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(target1, origin1, cb1) { - this.target = target1; - this.origin = origin1; - this.cb = cb1 != null ? cb1 : {}; - this.onMessage = bind(this.onMessage, this); - this.send = bind(this.send, this); - $.on(window, 'message', this.onMessage); - } - - Connection.prototype.targetWindow = function() { - if (this.target instanceof window.HTMLIFrameElement) { - return this.target.contentWindow; - } else { - return this.target; - } - }; - - Connection.prototype.send = function(data) { - return this.targetWindow().postMessage("" + g.NAMESPACE + (JSON.stringify(data)), this.origin); - }; - - Connection.prototype.onMessage = function(e) { - var base1, data, type, value; - if (!(e.source === this.targetWindow() && 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 (base1 = this.cb)[type] === "function") { - base1[type](value); - } - } - }; - - return Connection; - - })(); - - Fetcher = (function() { - function Fetcher(boardID1, threadID1, postID1, root1, quoter1) { - var post; - this.boardID = boardID1; - this.threadID = threadID1; - this.postID = postID1; - this.root = root1; - this.quoter = quoter1; - 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(_this) { - return function(e, isCached) { - return _this.fetchedPost(e.target, isCached); - }; - })(this)); - } else { - this.archivedPost(); - } - } - - Fetcher.prototype.insert = function(post) { - var boardID, clone, k, len1, nodes, postID, quote, ref, ref1; - if (!this.root.parentNode) { - return; - } - clone = post.addClone(this.quoter.context, $.hasClass(this.root, 'dialog')); - Main.callbackNodes(Clone, [clone]); - nodes = clone.nodes; - $.rmAll(nodes.root); - $.add(nodes.root, nodes.post); - ref = clone.nodes.quotelinks.concat(slice.call(clone.nodes.backlinks)); - for (k = 0, len1 = ref.length; k < len1; k++) { - quote = ref[k]; - ref1 = Get.postDataFromLink(quote), boardID = ref1.boardID, postID = ref1.postID; - if (postID === this.quoter.ID && boardID === this.quoter.board.ID) { - $.addClass(quote, 'forwardlink'); - } - } - $.rmAll(this.root); - $.add(this.root, nodes.root); - return $.event('PostsInserted'); - }; - - Fetcher.prototype.fetchedPost = function(req, isCached) { - var api, board, k, len1, post, posts, status, thread; - 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 (k = 0, len1 = posts.length; k < len1; k++) { - post = posts[k]; - if (post.no === this.postID) { - break; - } - } - if (post.no !== this.postID) { - if (isCached) { - api = "//a.4cdn.org/" + this.boardID + "/thread/" + this.threadID + ".json"; - $.cleanCache(function(url) { - return url === api; - }); - $.cache(api, (function(_this) { - return function(e) { - return _this.fetchedPost(e.target, false); - }; - })(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 archive, url; - if (!Conf['Resurrect Quotes']) { - return false; - } - if (!(url = Redirect.to('post', { - boardID: this.boardID, - postID: this.postID - }))) { - return false; - } - archive = Redirect.data.post[this.boardID]; - if (/^https:\/\//.test(url) || location.protocol === 'http:') { - $.cache(url, (function(_this) { - return function(e) { - return _this.parseArchivedPost(e.target.response, url, archive); - }; - })(this), { - responseType: 'json', - withCredentials: archive.withCredentials - }); - return true; - } else if (Conf['Exempt 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 (!((ref = media[key]) != null ? ref.match(/^http:\/\//) : void 0)) { - delete media[key]; - } - } - } - } - return _this.parseArchivedPost(response, url, archive); - }; - })(this)); - return true; - } - return false; - }; - - Fetcher.prototype.parseArchivedPost = function(data, url, archive) { - var board, comment, greentext, i, j, key, o, post, ref, ref1, text, text2, thread, val; - if (post = g.posts[this.boardID + "." + this.postID]) { - this.insert(post); - return; - } - if (data == null) { - $.addClass(this.root, 'warning'); - this.root.textContent = "Error fetching Post No." + this.postID + " from " + archive.name + "."; - 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 k, len1, results; - results = []; - for (i = k = 0, len1 = comment.length; k < len1; i = ++k) { - text = comment[i]; - if (i % 2 === 1) { - results.push(this.archiveTags[text]); - } else { - greentext = text[0] === '>'; - text = text.replace(/(\[\/?[a-z]+):lit(\])/g, '$1$2'); - text = (function() { - var len2, q, ref, results1; - ref = text.split(/(>>(?:>\/[a-z\d]+\/)?\d+)/g); - results1 = []; - for (j = q = 0, len2 = ref.length; q < len2; j = ++q) { - text2 = ref[j]; - results1.push({ - innerHTML: (j % 2 ? "" + E(text2) + "" : E(text2)) - }); - } - return results1; - })(); - text = { - innerHTML: (greentext ? "" + E.cat(text) + "" : E.cat(text)) - }; - results.push(text); - } - } - return results; - }).call(this); - comment = { - innerHTML: E.cat(comment) - }; - this.threadID = +data.thread_num; - o = { - postID: this.postID, - threadID: this.threadID, - boardID: this.boardID, - isReply: this.postID !== this.threadID - }; - o.info = { - subject: data.title, - email: data.email, - name: data.name || '', - tripcode: data.trip, - capcode: (function() { - switch (data.capcode) { - case 'M': - return 'Mod'; - case 'A': - return 'Admin'; - case 'D': - return 'Developer'; - } - })(), - uniqueID: data.poster_hash, - flagCode: data.poster_country, - flag: data.poster_country_name, - dateUTC: data.timestamp, - dateText: data.fourchan_date, - commentHTML: comment - }; - if (o.info.capcode) { - delete o.info.uniqueID; - } - if ((ref = data.media) != null ? ref.media_filename : void 0) { - ref1 = data.media; - for (key in ref1) { - val = ref1[key]; - if (/_link$/.test(key) && (val != null ? val[0] : void 0) === '/') { - data.media[key] = url.split('/', 3).join('/') + val; - } - } - o.file = { - name: data.media.media_filename, - url: data.media.media_link || data.media.remote_media_link || (location.protocol + "//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: $.bytesToString(data.media.media_size), - thumbURL: data.media.thumb_link || (location.protocol + "//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 (!/\.pdf$/.test(o.file.url)) { - o.file.dimensions = o.file.width + "x" + o.file.height; - } - if (this.boardID === 'f' && data.media.exif) { - 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); - post.kill(); - if (post.file) { - post.file.thumbURL = o.file.thumbURL; - } - post.isFetchedQuote = true; - Main.callbackNodes(Post, [post]); - return this.insert(post); - }; - - Fetcher.prototype.archiveTags = { - '\n': { - innerHTML: "
" - }, - '[b]': { - innerHTML: "" - }, - '[/b]': { - innerHTML: "" - }, - '[spoiler]': { - innerHTML: "" - }, - '[/spoiler]': { - innerHTML: "" - }, - '[code]': { - innerHTML: "
"
-      },
-      '[/code]': {
-        innerHTML: "
" - }, - '[moot]': { - innerHTML: "
" - }, - '[/moot]': { - innerHTML: "
" - }, - '[banned]': { - innerHTML: "" - }, - '[/banned]': { - innerHTML: "" - } - }; - - return Fetcher; - - })(); - - Polyfill = { - init: function() { - return this.toBlob(); - }, - toBlob: function() { - if (HTMLCanvasElement.prototype.toBlob) { - return; - } - HTMLCanvasElement.prototype.toBlob = function(cb, type, encoderOptions) { - var data, i, k, l, ref, ui8a, url; - if (type == null) { - type = 'image/png'; - } - url = this.toDataURL(type, encoderOptions); - data = atob(url.slice(url.indexOf(',') + 1)); - l = data.length; - ui8a = new Uint8Array(l); - for (i = k = 0, ref = l; k < ref; i = k += 1) { - ui8a[i] = data.charCodeAt(i); - } - return cb(new Blob([ui8a], { - type: type - })); - }; - return $.globalEval("HTMLCanvasElement.prototype.toBlob = (" + HTMLCanvasElement.prototype.toBlob + ");"); - } - }; - - 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: "" - }); - 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 popstate', 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 absbot, oldFooter; - if ((oldFooter = $.id('boardNavDesktopFoot'))) { - return $.replace($('.boardList', oldFooter), Header.bottomBoardList); - } else if ((absbot = $.id('absbot'))) { - $.before(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, k, len1, len2, node, nodes, q, ref, ref1, spacer, span; - Header.boardList = boardList = $.el('span', { - id: 'board-list' - }); - $.extend(boardList, { - innerHTML: "" - }); - btn = $('.hide-board-list-button', boardList); - $.on(btn, 'click', Header.toggleBoardList); - nodes = []; - spacer = function() { - return $.el('span', { - className: 'spacer' - }); - }; - ref = $('#boardNavDesktop > .boardList').childNodes; - for (k = 0, len1 = ref.length; k < len1; k++) { - node = ref[k]; - switch (node.nodeName) { - case '#text': - ref1 = node.nodeValue; - for (q = 0, len2 = ref1.length; q < len2; q++) { - chr = ref1[q]; - 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|(mode|sort|text):"[^"]+"(,"[^"]+")?))*|[^\w@]+/g; - nodes = (function() { - var k, len1, ref, results; - ref = boardnav.match(re); - results = []; - for (k = 0, len1 = ref.length; k < len1; k++) { - t = ref[k]; - results.push(Header.mapCustomNavigation(t, as)); - } - return results; - })(); - $.add(list, nodes); - return $.ready(CatalogLinks.initBoardList); - }, - mapCustomNavigation: function(t, as) { - var a, boardID, href, indexOptions, 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 ''; - }); - indexOptions = []; - t = t.replace(/-(?:mode|sort):"([^"]+)"/g, function(m0, m1) { - indexOptions.push(m1.toLowerCase().replace(/\ /g, '-')); - return ''; - }); - indexOptions = indexOptions.join('/'); - 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 k, len1, ref; - if (boardID === '@') { - return $.el('a', { - href: 'https://twitter.com/4chan', - title: '4chan Twitter', - textContent: '@' - }); - } - for (k = 0, len1 = as.length; k < len1; k++) { - a = as[k]; - 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)/)) { - if (!(boardID === 'f' && m[1] === 'catalog')) { - a.dataset.only = m[1]; - a.href = CatalogLinks[m[1]](boardID); - if (m[1] === 'catalog') { - $.addClass(a, 'catalog'); - } - } else { - return a.firstChild; - } - } - if (Conf['JSON Index'] && indexOptions) { - a.dataset.indexOptions = indexOptions; - if (a.hostname === 'boards.4chan.org' && a.pathname.split('/')[2] === '') { - a.href += (a.hash ? '/' : '#') + indexOptions; - } - } - 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' && boardID !== 'trash') { - 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() { - 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(e) { - var el, hash; - if (e) { - if (e.state) { - return; - } - if (!history.state) { - history.replaceState({}, ''); - } - } - if ((hash = location.hash.slice(1))) { - ReplyPruning.showIfHidden(hash); - if ((el = $.id(hash))) { - return $.queueTask(function() { - return Header.scrollTo(el); - }); - } - } - }, - scrollTo: function(root, down, needed) { - var height, x; - if (!root.offsetParent) { - return; - } - if (down) { - x = Header.getBottomOf(root); - if (Conf['Fixed Header'] && 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['Fixed Header'] && 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['Fixed Header'] && 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, ref, type; - 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: "4chan X needs your permission to show desktop notifications. [FAQ]
or " - }); - 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, - changed: {}, - init: function() { - var anchorEntry, input, k, label, len1, len2, name, pinEntry, q, ref, ref1, ref2, ref3, ref4, ref5, ref6, refNavEntry, repliesEntry, select, sortEntry; - if (g.BOARD.ID === 'f' || !Conf['JSON Index'] || g.VIEW !== 'index') { - return; - } - CatalogThread.callbacks.push({ - name: 'Catalog Features', - cb: this.catalogNode - }); - this.search = ((ref = history.state) != null ? ref.searched : void 0) || ''; - if ((ref1 = history.state) != null ? ref1.mode : void 0) { - Conf['Index Mode'] = (ref2 = history.state) != null ? ref2.mode : void 0; - } - this.currentSort = (ref3 = history.state) != null ? ref3.sort : void 0; - this.currentSort || (this.currentSort = typeof Conf['Index Sort'] === 'object' ? Conf['Index Sort'][g.BOARD.ID] || 'bump' : Conf['Index Sort']); - this.currentPage = this.getCurrentPage(); - this.processHash(); - $.addClass(doc, 'index-loading', (Conf['Index Mode'].replace(/\ /g, '-')) + "-mode"); - $.on(window, 'popstate', this.cb.popstate); - $.on(d, 'scroll', Index.scroll); - 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') - }; - sortEntry = { - el: UI.checkbox('Per-Board Sort Type', 'Per-board sort type', typeof Conf['Index Sort'] === 'object') - }; - 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') - }; - sortEntry.el.title = 'Set the sorting order of each board independently.'; - 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 (k = 0, len1 = ref4.length; k < len1; k++) { - label = ref4[k]; - 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.resort); - } - } - $.on(sortEntry.el.firstChild, 'change', this.cb.perBoardSort); - Header.menu.addEntry({ - el: $.el('span', { - textContent: 'Index Navigation' - }), - order: 100, - subEntries: [repliesEntry, sortEntry, pinEntry, anchorEntry, refNavEntry] - }); - this.navLinks = $.el('div', { - className: 'navLinks json-index' - }); - $.extend(this.navLinks, { - innerHTML: "Index Catalog Archive Bottom ×" - }); - $('.cataloglink a', this.navLinks).href = CatalogLinks.catalog(); - if ((ref5 = g.BOARD.ID) === 'b' || ref5 === 'trash') { - $('.archlistlink', this.navLinks).hidden = true; - } - $.on($('#index-last-refresh a', this.navLinks), 'click', this.cb.refreshFront); - this.searchInput = $('#index-search', this.navLinks); - this.setupSearch(); - $.on(this.searchInput, 'input', this.onSearchInput); - $.on($('#index-search-clear', this.navLinks), 'click', this.clearSearch); - this.hideLabel = $('#hidden-label', this.navLinks); - $.on($('#hidden-toggle a', this.navLinks), 'click', this.cb.toggleHiddenThreads); - this.selectMode = $('#index-mode', this.navLinks); - this.selectSort = $('#index-sort', this.navLinks); - this.selectSize = $('#index-size', this.navLinks); - $.on(this.selectMode, 'change', this.cb.mode); - $.on(this.selectSort, 'change', this.cb.sort); - $.on(this.selectSize, 'change', $.cb.value); - $.on(this.selectSize, 'change', this.cb.size); - ref6 = [this.selectMode, this.selectSize]; - for (q = 0, len2 = ref6.length; q < len2; q++) { - select = ref6[q]; - select.value = Conf[select.name]; - } - this.selectSort.value = Index.currentSort; - this.root = $.el('div', { - className: 'board json-index' - }); - this.cb.size(); - this.pagelist = $.el('div', { - className: 'pagelist json-index' - }); - $.extend(this.pagelist, { - innerHTML: "
Catalog
" - }); - $('.cataloglink a', this.pagelist).href = CatalogLinks.catalog(); - $.on(this.pagelist, 'click', this.cb.pageNav); - this.update(true); - $.onExists(doc, 'title + *', function() { - return d.title = d.title.replace(/\ -\ Page\ \d+/, ''); - }); - $.onExists(doc, '.board > .thread > .postContainer, .board + *', function() { - var board, el, len3, len4, ref7, ref8, threadRoot, topNavPos, u, v; - Index.hat = $('.board > .thread > img:first-child'); - if (Index.hat) { - if (Index.nodes) { - ref7 = Index.nodes; - for (u = 0, len3 = ref7.length; u < len3; u++) { - threadRoot = ref7[u]; - $.prepend(threadRoot, Index.hat.cloneNode(false)); - } - } - $.addClass(doc, 'hats-enabled'); - $.addStyle(".catalog-thread::after {background-image: url(" + Index.hat.src + ");}"); - } - board = $('.board'); - $.replace(board, Index.root); - $.event('PostsInserted'); - try { - d.implementation.createDocument(null, null, null).appendChild(board); - } catch (_error) {} - ref8 = $$('.navLinks'); - for (v = 0, len4 = ref8.length; v < len4; v++) { - el = ref8[v]; - $.rm(el); - } - $.rm($.id('ctrl-top')); - topNavPos = $.id('delform').previousElementSibling; - $.before(topNavPos, $.el('hr')); - return $.before(topNavPos, Index.navLinks); - }); - return Main.ready(function() { - var pagelist; - if ((pagelist = $('.pagelist'))) { - $.replace(pagelist, Index.pagelist); - } - return $.rmClass(doc, 'index-loading'); - }); - }, - scroll: function() { - var nodes, pageNum; - if (Index.req || !Index.liveThreadData || Conf['Index Mode'] !== 'infinite' || (window.scrollY <= doc.scrollHeight - (300 + window.innerHeight))) { - return; - } - if (Index.pageNum == null) { - Index.pageNum = Index.currentPage; - } - 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 Index'] || !Conf['Menu'] || !Conf['Thread Hiding Link'] || g.BOARD.ID === 'f') { - return; - } - return Menu.menu.addEntry({ - el: $.el('a', { - href: 'javascript:;', - className: 'has-shortcut-text' - }, { - innerHTML: "Shift+click" - }), - order: 20, - open: function(arg) { - var thread; - thread = arg.thread; - if (Conf['Index Mode'] !== 'catalog') { - return false; - } - this.el.firstElementChild.textContent = thread.isHidden ? 'Unhide' : 'Hide'; - 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, k, len1, type, types; - types = slice.call(Index.selectSort.options).filter(function(option) { - return !option.disabled; - }); - for (i = k = 0, len1 = types.length; k < len1; i = ++k) { - 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() { - Index.pushState({ - mode: this.value - }); - return Index.pageLoad(false); - }, - sort: function() { - Index.pushState({ - sort: this.value - }); - return Index.pageLoad(false); - }, - resort: function() { - Index.sort(); - return Index.buildIndex(); - }, - perBoardSort: function() { - Conf['Index Sort'] = this.checked ? {} : ''; - return Index.saveSort(); - }, - 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, nCommands, page, ref, searched, sort; - if (e != null ? e.state : void 0) { - ref = e.state, searched = ref.searched, mode = ref.mode, sort = ref.sort; - page = Index.getCurrentPage(); - Index.setState({ - search: searched, - mode: mode, - sort: sort, - page: page - }); - return Index.pageLoad(false); - } else { - nCommands = Index.processHash(); - if (Conf['Refreshed Navigation'] && nCommands) { - return Index.update(); - } else { - return Index.pageLoad(); - } - } - }, - 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); - }, - refreshFront: function() { - Index.pushState({ - page: 1 - }); - return Index.update(); - } - }, - scrollToIndex: function() { - return Header.scrollToIfNeeded((Index.navLinks.getBoundingClientRect().height ? Index.navLinks : Index.root)); - }, - getCurrentPage: function() { - return +window.location.pathname.split(/\/+/)[2] || 1; - }, - userPageNav: function(page) { - Index.pushState({ - page: page - }); - if (Conf['Refreshed Navigation']) { - return Index.update(); - } else { - return Index.pageLoad(); - } - }, - hashCommands: { - mode: { - 'paged': 'paged', - 'infinite-scrolling': 'infinite', - 'infinite': 'infinite', - 'all-threads': 'all pages', - 'all-pages': 'all pages', - 'catalog': 'catalog' - }, - sort: { - 'bump-order': 'bump', - 'last-reply': 'lastreply', - 'last-long-reply': 'lastlong', - 'creation-date': 'birth', - 'reply-count': 'replycount', - 'file-count': 'filecount' - } - }, - processHash: function() { - var command, commands, hash, k, leftover, len1, mode, ref, sort, state; - hash = ((ref = location.href.match(/#.*/)) != null ? ref[0] : void 0) || ''; - state = { - replace: true - }; - commands = hash.slice(1).split('/'); - leftover = []; - for (k = 0, len1 = commands.length; k < len1; k++) { - command = commands[k]; - if ((mode = Index.hashCommands.mode[command])) { - state.mode = mode; - } else if (command === 'index') { - state.mode = Conf['Previous Index Mode']; - state.page = 1; - } else if ((sort = Index.hashCommands.sort[command])) { - state.sort = sort; - } else if (/^s=/.test(command)) { - state.search = decodeURIComponent(command.slice(2)).replace(/\+/g, ' ').trim(); - } else { - leftover.push(command); - } - } - hash = leftover.join('/'); - if (hash) { - state.hash = "#" + hash; - } - Index.pushState(state); - return commands.length - leftover.length; - }, - pushState: function(state) { - var hash, pageBeforeSearch, pathname, ref, replace, search; - search = state.search, hash = state.hash, replace = state.replace; - pageBeforeSearch = (ref = history.state) != null ? ref.oldpage : void 0; - if ((search != null) && search !== Index.search) { - state.page = search ? 1 : pageBeforeSearch || 1; - if (!search) { - pageBeforeSearch = void 0; - } else if (!Index.search) { - pageBeforeSearch = Index.currentPage; - } - } - Index.setState(state); - pathname = Index.currentPage === 1 ? "/" + g.BOARD + "/" : "/" + g.BOARD + "/" + Index.currentPage; - hash || (hash = ''); - return history[replace ? 'replaceState' : 'pushState']({ - mode: Conf['Index Mode'], - sort: Index.currentSort, - searched: Index.search, - oldpage: pageBeforeSearch - }, '', location.protocol + "//" + location.host + pathname + hash); - }, - setState: function(arg) { - var hash, mode, page, ref, search, sort; - search = arg.search, mode = arg.mode, sort = arg.sort, page = arg.page, hash = arg.hash; - if ((search != null) && search !== Index.search) { - Index.changed.search = true; - Index.search = search; - } - if ((mode != null) && mode !== Conf['Index Mode']) { - Index.changed.mode = true; - Conf['Index Mode'] = mode; - $.set('Index Mode', mode); - if (!(mode === 'catalog' || Conf['Previous Index Mode'] === mode)) { - Conf['Previous Index Mode'] = mode; - $.set('Previous Index Mode', mode); - } - } - if ((sort != null) && sort !== Index.currentSort) { - Index.changed.sort = true; - Index.currentSort = sort; - Index.saveSort(); - } - if ((ref = Conf['Index Mode']) === 'all pages' || ref === 'catalog') { - page = 1; - } - if ((page != null) && page !== Index.currentPage) { - Index.changed.page = true; - Index.currentPage = page; - } - if (hash != null) { - return Index.changed.hash = true; - } - }, - saveSort: function() { - if (typeof Conf['Index Sort'] === 'object') { - Conf['Index Sort'][g.BOARD.ID] = Index.currentSort; - } else { - Conf['Index Sort'] = Index.currentSort; - } - return $.set('Index Sort', Conf['Index Sort']); - }, - pageLoad: function(scroll) { - var hash, mode, page, ref, search, sort, threads; - if (scroll == null) { - scroll = true; - } - if (!Index.liveThreadData) { - return; - } - ref = Index.changed, threads = ref.threads, search = ref.search, mode = ref.mode, sort = ref.sort, page = ref.page, hash = ref.hash; - if (threads || search || sort) { - Index.sort(); - } - if (threads || search) { - Index.buildPagelist(); - } - if (search) { - Index.setupSearch(); - } - if (mode) { - Index.setupMode(); - } - if (sort) { - Index.setupSort(); - } - if (threads || search || mode || page || sort) { - Index.buildIndex(); - } - if (threads || search || mode || page) { - Index.setPage(); - } - if (scroll && !hash) { - Index.scrollToIndex(); - } - if (hash) { - Header.hashScroll(); - } - return Index.changed = {}; - }, - setupMode: function() { - var k, len1, mode, ref; - ref = ['paged', 'infinite', 'all pages', 'catalog']; - for (k = 0, len1 = ref.length; k < len1; k++) { - mode = ref[k]; - $[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'; - }, - setupSort: function() { - return Index.selectSort.value = Index.currentSort; - }, - 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, k, maxPageNum, nodes, pagesRoot, ref; - pagesRoot = $('.pages', Index.pagelist); - maxPageNum = Index.getMaxPageNum(); - if (pagesRoot.childElementCount !== maxPageNum) { - nodes = []; - for (i = k = 1, ref = maxPageNum; k <= ref; i = k += 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.currentPage; - 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, ref, ref1, thread, threadID; - 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(firstTime) { - var now, ref, ref1; - if ((ref = Index.req) != null) { - ref.abort(); - } - if ((ref1 = Index.notice) != null) { - ref1.close(); - } - if (Conf['Index Refresh Notifications'] && d.readyState !== 'loading') { - Index.notice = new Notice('info', 'Refreshing index...'); - } else { - now = Date.now(); - $.ready(function() { - return Index.nTimeout = setTimeout((function() { - if (Index.req && !Index.notice) { - return Index.notice = new Notice('info', 'Refreshing index...'); - } - }), 3 * $.SECOND - (Date.now() - now)); - }); - } - if (!firstTime && d.readyState !== 'loading' && !$('.board + *')) { - location.reload(); - return; - } - Index.req = $.ajax("//a.4cdn.org/" + g.BOARD + "/catalog.json", { - onabort: Index.load, - onloadend: Index.load - }, { - whenModified: 'Index' - }); - return $.addClass(Index.button, 'fa-spin'); - }, - load: function(e) { - var err, nTimeout, notice, ref, req, timeEl; - $.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; - if (notice != 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); - } else if (req.status === 304) { - Index.pageLoad(); - } - } 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; - } - if (notice) { - if (Conf['Index Refresh Notifications']) { - notice.setType('success'); - notice.el.lastElementChild.textContent = 'Index refreshed!'; - setTimeout(notice.close, $.SECOND); - } else { - notice.close(); - } - } - timeEl = $('#index-last-refresh time', Index.navLinks); - timeEl.dataset.utc = Date.parse(req.getResponseHeader('Last-Modified')); - return RelativeDates.update(timeEl); - }, - parse: function(pages) { - $.cleanCache(function(url) { - return /^\/\/a\.4cdn\.org\//.test(url); - }); - Index.parseThreadList(pages); - Index.buildThreads(); - Index.changed.threads = true; - return Index.pageLoad(); - }, - parseThreadList: function(pages) { - var ref; - Index.pagesNum = pages.length; - Index.threadsNumPerPage = ((ref = pages[0]) != null ? ref.threads.length : void 0) || 1; - 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 ref1; - if (ref1 = thread.ID, indexOf.call(Index.liveThreadIDs, ref1) < 0) { - return thread.collect(); - } - }); - }, - buildThreads: function() { - var err, errors, i, k, len1, posts, ref, thread, threadData, threadRoot, threads; - if (!Index.liveThreadData) { - return; - } - Index.nodes = []; - threads = []; - posts = []; - ref = Index.liveThreadData; - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - 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.OP && !thread.OP.isFetchedQuote)) { - 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, k, lastReplies, len1, len2, node, nodes, post, posts, q, thread, threadRoot; - posts = []; - for (k = 0, len1 = threadRoots.length; k < len1; k++) { - threadRoot = threadRoots[k]; - thread = Get.threadFromRoot(threadRoot); - i = Index.liveThreadIDs.indexOf(thread.ID); - if (!(lastReplies = Index.liveThreadData[i].last_replies)) { - continue; - } - nodes = []; - for (q = 0, len2 = lastReplies.length; q < len2; q++) { - data = lastReplies[q]; - if ((post = thread.posts[data.no]) && !post.isFetchedQuote) { - 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, k, len1, thread, threads; - threads = Index.sortedNodes.map(function(threadRoot) { - return Get.threadFromRoot(threadRoot); - }).filter(function(thread) { - return !thread.isHidden !== Index.showHiddenThreads; - }); - catalogThreads = []; - for (k = 0, len1 = threads.length; k < len1; k++) { - thread = threads[k]; - 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, k, len1, node, ratio, ref, size, thumb, width; - size = Conf['Index Size'] === 'small' ? 150 : 250; - for (k = 0, len1 = nodes.length; k < len1; k++) { - node = nodes[k]; - 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 k, lastlong, len1, liveThreadData, liveThreadIDs, nodes, sortedNodes, sortedThreadIDs, threadID; - liveThreadIDs = Index.liveThreadIDs, liveThreadData = Index.liveThreadData; - if (!liveThreadData) { - return; - } - sortedThreadIDs = (function() { - switch (Index.currentSort) { - case 'lastreply': - return 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; - }); - case 'lastlong': - lastlong = function(thread) { - var i, k, r, ref; - ref = thread.last_replies || []; - for (i = k = ref.length - 1; k >= 0; i = k += -1) { - r = ref[i]; - if (r.com && Build.parseComment(r.com).replace(/[^a-z]/ig, '').length >= 100) { - return r; - } - } - return thread; - }; - return slice.call(liveThreadData).sort(function(a, b) { - return lastlong(b).no - lastlong(a).no; - }).map(function(post) { - return post.no; - }); - case 'bump': - return liveThreadIDs; - case 'birth': - return slice.call(liveThreadIDs).sort(function(a, b) { - return b - a; - }); - case 'replycount': - return slice.call(liveThreadData).sort(function(a, b) { - return b.replies - a.replies; - }).map(function(post) { - return post.no; - }); - case 'filecount': - return slice.call(liveThreadData).sort(function(a, b) { - return b.images - a.images; - }).map(function(post) { - return post.no; - }); - } - })(); - Index.sortedNodes = sortedNodes = []; - nodes = Index.nodes; - for (k = 0, len1 = sortedThreadIDs.length; k < len1; k++) { - threadID = sortedThreadIDs[k]; - 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, k, len1, ref, threadRoot, topNodes; - topNodes = []; - bottomNodes = []; - ref = Index.sortedNodes; - for (k = 0, len1 = ref.length; k < len1; k++) { - threadRoot = ref[k]; - (match(Get.threadFromRoot(threadRoot)) ? topNodes : bottomNodes).push(threadRoot); - } - return Index.sortedNodes = topNodes.concat(bottomNodes); - }, - buildIndex: function() { - var i, nodes, page, post; - if (!Index.liveThreadData) { - return; - } - 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.currentPage) { - Index.currentPage = page; - Index.pushState({ - page: page - }); - Index.setPage(); - } - } - nodes = Index.buildSinglePage(Index.currentPage); - } - delete Index.pageNum; - $.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 k, len1, node, thumb; - for (k = 0, len1 = nodes.length; k < len1; k++) { - node = nodes[k]; - if (thumb = $('img[data-src]', node)) { - thumb.src = thumb.dataset.src; - thumb.removeAttribute('data-src'); - } - $.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() { - 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; - } - Index.pushState({ - search: search, - replace: !!search === !!Index.search - }); - return Index.pageLoad(false); - }, - 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, k, key, keyword, len1, len2, q, ref, ref1, text; - ref = thread.OP, info = ref.info, file = ref.file; - text = []; - ref1 = ['comment', 'subject', 'name', 'tripcode', 'email']; - for (k = 0, len1 = ref1.length; k < len1; k++) { - key = ref1[k]; - if (key in info) { - text.push(info[key]); - } - } - if (file) { - text.push(file.name); - } - text = text.join(' ').toLowerCase(); - for (q = 0, len2 = keywords.length; q < len2; q++) { - keyword = keywords[q]; - 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|#44);/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; - } - }, - spoilerThumb: function(boardID) { - var spoilerRange; - if (spoilerRange = Build.spoilerRange[boardID]) { - return Build.staticPath + "spoiler-" + boardID + (Math.floor(1 + spoilerRange * Math.random())) + ".png"; - } else { - return Build.staticPath + "spoiler.png"; - } - }, - 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; - } - }, - parseJSON: function(data, boardID) { - var o; - o = { - postID: data.no, - threadID: data.resto || data.no, - boardID: boardID, - isReply: !!data.resto, - isSticky: !!data.sticky, - isClosed: !!data.closed, - isArchived: !!data.archived, - fileDeleted: !!data.filedeleted - }; - o.info = { - subject: Build.unescape(data.sub), - email: Build.unescape(data.email), - name: Build.unescape(data.name) || '', - tripcode: data.trip, - uniqueID: data.id, - flagCode: data.country, - flag: Build.unescape(data.country_name), - dateUTC: data.time, - dateText: data.now, - commentHTML: { - innerHTML: data.com || '' - } - }; - if (data.capcode) { - o.info.capcode = data.capcode.replace(/_highlight$/, '').replace(/_/g, ' ').replace(/\b\w/g, function(c) { - return c.toUpperCase(); - }); - o.capcodeHighlight = /_highlight$/.test(data.capcode); - delete o.info.uniqueID; - } - if (data.ext) { - o.file = { - name: (Build.unescape(data.filename)) + data.ext, - url: boardID === 'f' ? location.protocol + "//i.4cdn.org/" + boardID + "/" + (encodeURIComponent(data.filename)) + data.ext : location.protocol + "//i.4cdn.org/" + boardID + "/" + data.tim + data.ext, - height: data.h, - width: data.w, - MD5: data.md5, - size: $.bytesToString(data.fsize), - thumbURL: location.protocol + "//i.4cdn.org/" + boardID + "/" + data.tim + "s.jpg", - theight: data.tn_h, - twidth: data.tn_w, - isSpoiler: !!data.spoiler, - tag: data.tag - }; - if (!/\.pdf$/.test(o.file.url)) { - o.file.dimensions = o.file.width + "x" + o.file.height; - } - } - return o; - }, - parseComment: function(html) { - html = html.replace(//gi, '\n').replace(/\n\nRolled [^<]*<\/b>/i, '').replace(/]*>/g, ''); - return Build.unescape(html); - }, - postFromObject: function(data, boardID, suppressThumb) { - var o; - o = Build.parseJSON(data, boardID); - return Build.post(o, suppressThumb); - }, - post: function(o, suppressThumb) { - var boardID, capcode, capcodeDescription, capcodeLC, capcodeLong, capcodePlural, commentHTML, container, dateText, dateUTC, email, file, fileBlock, fileThumb, fileURL, flag, flagCode, gifIcon, href, k, len1, match, name, postClass, postID, postInfo, postLink, protocol, quote, quoteLink, ref, ref1, shortFilename, staticPath, subject, threadID, tripcode, uniqueID, wholePost; - postID = o.postID, threadID = o.threadID, boardID = o.boardID, file = o.file; - ref = o.info, subject = ref.subject, email = ref.email, name = ref.name, tripcode = ref.tripcode, capcode = ref.capcode, uniqueID = ref.uniqueID, flagCode = ref.flagCode, flag = ref.flag, dateUTC = ref.dateUTC, dateText = ref.dateText, commentHTML = ref.commentHTML; - staticPath = Build.staticPath, gifIcon = Build.gifIcon; - - /* Post Info */ - if (capcode) { - capcodeLC = capcode.toLowerCase(); - if (capcode === 'Founder') { - capcodePlural = 'the Founder'; - capcodeDescription = "4chan's Founder"; - } else { - capcodeLong = { - 'Admin': 'Administrator', - 'Mod': 'Moderator' - }[capcode] || capcode; - capcodePlural = capcodeLong + "s"; - capcodeDescription = "a 4chan " + capcodeLong; - } - } - postLink = Build.postURL(boardID, threadID, postID); - quoteLink = Build.sameThread(boardID, threadID) ? "javascript:quote('" + (+postID) + "');" : "/" + boardID + "/thread/" + threadID + "#q" + postID; - postInfo = { - innerHTML: "
" + (!o.isReply || boardID === "f" || subject ? "" + E(subject || "") + " " : "") + "" + (email ? "" : "") + "" + E(name) + "" + (tripcode ? " " + E(tripcode) + "" : "") + (capcode ? " ## " + E(capcode) + "" : "") + (email ? "" : "") + (boardID === "f" && !o.isReply || capcode ? "" : " ") + (capcode ? " \""" : "") + (uniqueID && !capcode ? " (ID: " + E(uniqueID) + ")" : "") + (flagCode ? " " : "") + " " + E(dateText) + " No." + E(postID) + "" + (o.isSticky ? " \"Sticky\"" : "") + (o.isClosed && !o.isArchived ? " \"Closed\"" : "") + (o.isArchived ? " \"Archived\"" : "") + (!o.isReply && g.VIEW === "index" ? "   [Reply]" : "") + "
" - }; - - /* File Info */ - if (file) { - protocol = /^https?:(?=\/\/i\.4cdn\.org\/)/; - fileURL = file.url.replace(protocol, ''); - shortFilename = Build.shortFilename(file.name); - fileThumb = file.isSpoiler ? Build.spoilerThumb(boardID) : file.thumbURL.replace(protocol, ''); - } - fileBlock = { - innerHTML: (file ? "
" + (boardID === "f" ? "
File: " + E(file.name) + "-(" + E(file.size) + ", " + E(file.dimensions) + (file.tag ? ", " + E(file.tag) : "") + ")
" : "
File: " + (file.isSpoiler ? "Spoiler Image" : E(shortFilename)) + " (" + E(file.size) + ", " + E(file.dimensions || "PDF") + ")
") + "
" : (o.fileDeleted ? "
\"File
" : "")) - }; - - /* Whole Post */ - postClass = o.isReply ? 'reply' : 'op'; - wholePost = { - innerHTML: (o.isReply ? "
>>
" : "") + "
" + (o.isReply ? postInfo.innerHTML + fileBlock.innerHTML : fileBlock.innerHTML + postInfo.innerHTML) + "
" + commentHTML.innerHTML + "
" - }; - container = $.el('div', { - className: "postContainer " + postClass + "Container", - id: "pc" + postID - }); - $.extend(container, wholePost); - ref1 = $$('.quotelink', container); - for (k = 0, len1 = ref1.length; k < len1; k++) { - quote = ref1[k]; - 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] || '#'; - } else if (/^\d+(#|$)/.test(href) && !(g.VIEW === 'thread' && g.BOARD.ID === boardID)) { - quote.href = "/" + boardID + "/thread/" + href; - } - } - return container; - }, - summaryText: function(status, posts, files) { - var text; - text = ''; - if (status) { - text += status + " "; - } - text += posts + " post" + (posts > 1 ? 's' : ''); - if (+files) { - text += " and " + files + " image repl" + (files > 1 ? 'ies' : 'y'); - } - return text += " " + (status === '-' ? 'shown' : 'omitted') + "."; - }, - summary: function(boardID, threadID, posts, files) { - return $.el('a', { - className: 'summary', - textContent: Build.summaryText('', posts, files), - href: "/" + boardID + "/thread/" + threadID - }); - }, - thread: function(board, data, full) { - var OP, root; - Build.spoilerRange[board] = data.custom_spoiler; - if (OP = board.posts[data.no]) { - if (OP.isFetchedQuote) { - OP = null; - } - } - if (OP && (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, true)]; - 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, k, len1, len2, len3, len4, pageCount, postCount, pp, q, quote, ref, ref1, ref2, ref3, ref4, root, spoilerRange, src, staticPath, u, v; - 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'; - } - postCount = data.replies + 1; - fileCount = data.images + !!data.ext; - pageCount = Math.floor(Index.liveThreadIDs.indexOf(thread.ID) / Index.threadsNumPerPage) + 1; - comment = { - innerHTML: data.com || '' - }; - root = $.el('div', { - className: 'catalog-thread' - }); - $.extend(root, { - innerHTML: "
" + E(postCount) + " / " + E(fileCount) + " / " + E(pageCount) + "
" + (thread.OP.info.subject ? "
" + E(thread.OP.info.subject) + "
" : "") + "
" + comment.innerHTML + "
" - }); - root.dataset.fullID = thread.fullID; - if (thread.OP.highlights) { - $.addClass.apply($, [root].concat(slice.call(thread.OP.highlights))); - } - ref = $$('.quotelink', root.lastElementChild); - for (k = 0, len1 = ref.length; k < len1; k++) { - quote = ref[k]; - href = quote.getAttribute('href'); - if (href[0] === '#') { - quote.href = ("/" + thread.board + "/thread/" + thread.ID) + href; - } - } - ref1 = $$('.abbr, .exif', root.lastElementChild); - for (q = 0, len2 = ref1.length; q < len2; q++) { - exif = ref1[q]; - $.rm(exif); - } - ref2 = $$('.prettyprint', root.lastElementChild); - for (u = 0, len3 = ref2.length; u < len3; u++) { - pp = ref2[u]; - cc = $.el('span', { - className: 'catalog-code' - }); - $.add(cc, slice.call(pp.childNodes)); - $.replace(pp, cc); - } - ref3 = $$('br', root.lastElementChild); - for (v = 0, len4 = ref3.length; v < len4; v++) { - br = ref3[v]; - 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.commentDisplay.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 index, post; - if (root == null) { - return null; - } - post = g.posts[root.dataset.fullID]; - index = root.dataset.clone; - 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)); - }, - postDataFromLink: function(link) { - var boardID, path, postID, ref, threadID; - 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, k, len1, posts, qPost, quote, quotelinks, ref; - quotelinks = []; - posts = g.posts; - fullID = post.fullID; - handleQuotes = function(qPost, type) { - var clone, k, len1, ref; - quotelinks.push.apply(quotelinks, qPost.nodes[type]); - ref = qPost.clones; - for (k = 0, len1 = ref.length; k < len1; k++) { - clone = ref[k]; - 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 (k = 0, len1 = ref.length; k < len1; k++) { - quote = ref[k]; - 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 k, len1, ref, script; - ref = $$('script:not([src])', d.head); - for (k = 0, len1 = ref.length; k < len1; k++) { - script = ref[k]; - 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, k, len1, move, 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 (k = 0, len1 = ref.length; k < len1; k++) { - child = ref[k]; - 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(type1) { - this.type = type1; - 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, k, left, len1, mRect, menu, ref, ref1, ref2, right, style, top; - menu = this.menu = this.makeMenu(); - currentMenu = this; - lastToggledButton = button; - this.entries.sort(function(first, second) { - return first.order - second.order; - }); - ref = this.entries; - for (k = 0, len1 = ref.length; k < len1; k++) { - entry = ref[k]; - this.insertEntry(entry, menu, data); - } - $.addClass(lastToggledButton, 'active'); - $.on(d, 'click CloseMenu', this.close); - if (this.type !== 'gallery') { - $.on(d, 'scroll', 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 err, k, len1, ref, subEntry, submenu; - if (typeof entry.open === 'function') { - try { - if (!entry.open(data)) { - return; - } - } catch (_error) { - err = _error; - Main.handleErrors({ - message: "Error in building the " + this.type + " menu.", - error: err - }); - 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 (k = 0, len1 = ref.length; k < len1; k++) { - subEntry = ref[k]; - 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, k, left, len1, ref, ref1, ref2, right, sRect, style, submenu, top; - while (focused = $.x('parent::*/child::*[contains(@class,"focused")]', entry)) { - $.rmClass(focused, 'focused'); - } - ref = $$('.focused', entry); - for (k = 0, len1 = ref.length; k < len1; k++) { - focused = ref[k]; - $.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, k, len1, subEntries, subEntry; - 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 (k = 0, len1 = subEntries.length; k < len1; k++) { - subEntry = subEntries[k]; - this.parseEntry(subEntry); - } - }; - - return Menu; - - })(); - dragstart = function(e) { - var el, isTouching, o, rect, ref, screenHeight, screenWidth; - 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 k, len1, ref, touch; - ref = e.changedTouches; - for (k = 0, len1 = ref.length; k < len1; k++) { - touch = ref[k]; - 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 k, len1, ref, touch; - ref = e.changedTouches; - for (k = 0, len1 = ref.length; k < len1; k++) { - touch = ref[k]; - 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 cb, el, endEvents, height, latestEvent, noRemove, o, ref, root; - root = arg.root, el = arg.el, latestEvent = arg.latestEvent, endEvents = arg.endEvents, 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); - o.hover(o.latestEvent); - new MutationObserver(function() { - if (el.parentNode) { - return o.hover(o.latestEvent); - } - }).observe(el, { - childList: true - }); - $.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); - }; - hoverstart.padding = 25; - hover = function(e) { - var clientX, clientY, height, left, ref, right, style, threshold, top; - this.latestEvent = e; - height = (this.height || this.el.offsetHeight) + hoverstart.padding; - 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) { - var options, ref, workaround; - if (headers == null) { - headers = {}; - } - url = url.replace(/^((?:https?:)?\/\/(?:\w+\.)?4c(?:ha|d)n\.org)\/adv\//, '$1//adv/'); - workaround = $.engine === 'gecko' && (typeof GM_info !== "undefined" && GM_info !== null) && /^[0-2]\.|^3\.[01](?!\d)/.test(GM_info.version); - workaround || (workaround = /PaleMoon\//.test(navigator.userAgent)); - workaround || (workaround = (typeof GM_info !== "undefined" && GM_info !== null ? (ref = GM_info.script) != null ? ref.includeJSB : void 0 : void 0) != null); - options = { - method: "GET", - url: url, - headers: headers, - onload: function(xhr) { - var contentDisposition, contentType, data, i, r, ref1, ref2; - if (workaround) { - r = xhr.responseText; - data = new Uint8Array(r.length); - i = 0; - while (i < r.length) { - data[i] = r.charCodeAt(i); - i++; - } - } else { - data = new Uint8Array(xhr.response); - } - if (typeof xhr.responseHeaders === 'object') { - contentType = xhr.responseHeaders['Content-Type']; - contentDisposition = xhr.responseHeaders['Content-Disposition']; - } else { - contentType = (ref1 = xhr.responseHeaders.match(/Content-Type:\s*(.*)/i)) != null ? ref1[1] : void 0; - contentDisposition = (ref2 = xhr.responseHeaders.match(/Content-Disposition:\s*(.*)/i)) != null ? ref2[1] : void 0; - } - return cb(data, contentType, contentDisposition); - }, - onerror: function() { - return cb(null); - }, - onabort: function() { - return cb(null); - } - }; - if (workaround) { - options.overrideMimeType = options.mimeType = 'text/plain; charset=x-user-defined'; - } else { - options.responseType = 'arraybuffer'; - } - return GM_xmlhttpRequest(options); - }, - file: function(url, cb) { - return CrossOrigin.binary(url, function(data, contentType, contentDisposition) { - var blob, match, mime, name, ref, ref1, ref2, ref3; - 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, '"'); - } - if ((typeof GM_info !== "undefined" && GM_info !== null ? (ref3 = GM_info.script) != null ? ref3.includeJSB : void 0 : void 0) != null) { - mime = QR.typeFromExtension[name.match(/[^.]*$/)[0].toLowerCase()] || 'application/octet-stream'; - } - 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 k, len1, ref, response; - response = JSON.parse(xhr.responseText); - ref = callbacks[url]; - for (k = 0, len1 = ref.length; k < len1; k++) { - cb = ref[k]; - 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, ref, tripcode; - 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 k, len1, len2, name, q, ref, ref1, trip; - ref = $$('.name'); - for (k = 0, len1 = ref.length; k < len1; k++) { - name = ref[k]; - name.textContent = 'Anonymous'; - } - ref1 = $$('.postertrip'); - for (q = 0, len2 = ref1.length; q < len2; q++) { - trip = ref1[q]; - $.rm(trip); - } - }); - } - }; - - Filter = { - filters: {}, - init: function() { - var boards, err, excludes, filter, hl, k, key, len1, line, op, ref, ref1, ref2, ref3, ref4, ref5, ref6, regexp, stub, top; - 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 (k = 0, len1 = ref1.length; k < len1; k++) { - line = ref1[k]; - 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'; - boards = boards === 'global' ? null : boards.split(','); - if (boards === null) { - excludes = ((ref3 = filter.match(/exclude:([^;]+)/)) != null ? ref3[1].toLowerCase().split(',') : void 0) || null; - } - 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, boards, excludes, 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, boards, excludes, 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, boardID, isReply) { - if (boards && indexOf.call(boards, boardID) < 0) { - return false; - } - if (excludes && indexOf.call(excludes, boardID) >= 0) { - return false; - } - if (isReply && op === 'only' || !isReply && op === 'no') { - return false; - } - if (!test(value)) { - return false; - } - return settings; - }; - }, - node: function() { - var filter, k, key, len1, ref, ref1, result, value; - if (this.isClone) { - return; - } - for (key in Filter.filters) { - if ((value = Filter[key](this)) != null) { - ref = Filter.filters[key]; - for (k = 0, len1 = ref.length; k < len1; k++) { - filter = ref[k]; - if (!(result = filter(value, this.board.ID, this.isReply))) { - continue; - } - if (result.hide && !this.isFetchedQuote) { - 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; - } - } - } - } - }, - isHidden: function(post) { - var filter, k, key, len1, ref, result, value; - for (key in Filter.filters) { - if ((value = Filter[key](post)) != null) { - ref = Filter.filters[key]; - for (k = 0, len1 = ref.length; k < len1; k++) { - filter = ref[k]; - if (result = filter(value, post.boardID, post.isReply)) { - if (result.hide) { - return true; - } - } - } - } - } - return false; - }, - postID: function(post) { - var ref; - return "" + ((ref = post.ID) != null ? ref : post.postID); - }, - name: function(post) { - return post.info.name; - }, - uniqueID: function(post) { - return post.info.uniqueID; - }, - tripcode: function(post) { - return post.info.tripcode; - }, - capcode: function(post) { - return post.info.capcode; - }, - subject: function(post) { - return post.info.subject; - }, - comment: function(post) { - var base1; - return (base1 = post.info).comment != null ? base1.comment : base1.comment = Build.parseComment(post.info.commentHTML.innerHTML); - }, - flag: function(post) { - return post.info.flag; - }, - filename: function(post) { - var ref; - return (ref = post.file) != null ? ref.name : void 0; - }, - dimensions: function(post) { - var ref; - return (ref = post.file) != null ? ref.dimensions : void 0; - }, - filesize: function(post) { - var ref; - return (ref = post.file) != null ? ref.size : void 0; - }, - MD5: function(post) { - var ref; - return (ref = post.file) != null ? ref.MD5 : void 0; - }, - menu: { - init: function() { - var div, entry, k, len1, ref, ref1, type; - 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 (k = 0, len1 = ref1.length; k < len1; k++) { - type = ref1[k]; - 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 != null; - } - }; - }, - 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, ref, replies, thisPost; - if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Menu'] || !Conf['Reply Hiding Link']) { - return; - } - div = $.el('div', { - className: 'hide-reply-link', - textContent: 'Hide' - }); - 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' - }); - 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, k, len1, quotelink, 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 (k = 0, len1 = ref.length; k < len1; k++) { - quotelink = ref[k]; - $.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 k, len1, quotelink, 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 (k = 0, len1 = ref.length; k < len1; k++) { - quotelink = ref[k]; - $.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, k, len1, len2, obj, q, quote, recursive, ref, ref1; - if (this.isClone || this.isFetchedQuote) { - return; - } - ref = this.quotes; - for (k = 0, len1 = ref.length; k < len1; k++) { - quote = ref[k]; - if (obj = Recursive.recursives[quote]) { - ref1 = obj.recursives; - for (i = q = 0, len2 = ref1.length; q < len2; i = ++q) { - recursive = ref1[i]; - recursive.apply(null, [this].concat(slice.call(obj.args[i]))); - } - } - } - }, - add: function() { - var args, base1, name1, obj, post, recursive; - recursive = arguments[0], post = arguments[1], args = 3 <= arguments.length ? slice.call(arguments, 2) : []; - obj = (base1 = Recursive.recursives)[name1 = post.fullID] || (base1[name1] = { - recursives: [], - args: [] - }); - obj.recursives.push(recursive); - return obj.args.push(args); - }, - rm: function(recursive, post) { - var i, k, len1, obj, rec, ref; - if (!(obj = Recursive.recursives[post.fullID])) { - return; - } - ref = obj.recursives; - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - 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 Index']) { - return; - } - this.db = new DataBoard('hiddenThreads'); - if (g.VIEW === 'catalog') { - return this.catalogWatch(); - } - this.catalogSet(g.BOARD); - return Post.callbacks.push({ - name: 'Thread Hiding', - cb: this.node - }); - }, - catalogSet: function(board) { - var hiddenThreads, threadID; - if (!$.hasStorage) { - return; - } - 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() { - if (!$.hasStorage) { - return; - } - this.hiddenThreads = JSON.parse(localStorage.getItem("4chan-hide-t-" + g.BOARD)) || {}; - return Main.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 (this.isReply || this.isClone || this.isFetchedQuote) { - return; - } - if (data = ThreadHiding.db.get({ - boardID: this.board.ID, - threadID: this.ID - })) { - ThreadHiding.hide(this.thread, data.makeStub); - } - if (!Conf['Thread Hiding Buttons']) { - return; - } - return $.prepend(this.nodes.root, ThreadHiding.makeButton(this.thread, 'hide')); - }, - onIndexBuild: function(nodes) { - var k, len1, root, thread; - for (k = 0, len1 = nodes.length; k < len1; k++) { - root = nodes[k]; - 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' - }); - 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 Index'] && 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', - 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 Index'] && 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 Index'] && 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: "" - }); - 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 Index']) { - 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 Index']) { - 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, k, len1, len2, len3, link, markYours, nodes, post, q, quote, ref, ref1, ref2, u; - if (this.isClone || !this.quotes.length || this.isRebuilt) { - return; - } - markYours = Conf['Mark Quotes of You'] && ((ref = QuoteYou.db) != null ? ref.get({ - boardID: this.board.ID, - threadID: this.thread.ID, - postID: this.ID - }) : void 0); - 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)' : '') - }); - ref1 = this.quotes; - for (k = 0, len1 = ref1.length; k < len1; k++) { - quote = ref1[k]; - containers = [QuoteBacklink.getContainer(quote)]; - if ((post = g.posts[quote]) && post.nodes.backlinkContainer) { - ref2 = post.clones; - for (q = 0, len2 = ref2.length; q < len2; q++) { - clone = ref2[q]; - containers.push(clone.nodes.backlinkContainer); - } - } - for (u = 0, len3 = containers.length; u < len3; u++) { - container = containers[u]; - link = a.cloneNode(true); - nodes = container.firstChild ? [$.tn(' '), link] : [link]; - 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 base1; - return (base1 = this.containers)[id] || (base1[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, k, len1, quotelink, ref, ref1, ref2, thread, threadID; - if (this.isClone && this.thread === this.context.thread) { - return; - } - ref = this.context, board = ref.board, thread = ref.thread; - ref1 = this.nodes.quotelinks; - for (k = 0, len1 = ref1.length; k < len1; k++) { - quotelink = ref1[k]; - 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; - } - if (Conf['Comment Expansion']) { - ExpandComment.callbacks.push(this.node); - } - return Post.callbacks.push({ - name: 'Quote Inlining', - cb: this.node - }); - }, - node: function() { - var isClone, k, len1, len2, link, process, q, ref, ref1; - process = QuoteInline.process; - isClone = this.isClone; - ref = this.nodes.quotelinks; - for (k = 0, len1 = ref.length; k < len1; k++) { - link = ref[k]; - process(link, isClone); - } - ref1 = this.nodes.backlinks; - for (q = 0, len2 = ref1.length; q < len2; q++) { - link = ref1[q]; - process(link, isClone); - } - }, - process: function(link, clone) { - if (Conf['Quote Hash Navigation']) { - if (!clone) { - $.after(link, QuoteInline.qiQuote(link, $.hasClass(link, 'filtered'))); - } - } - return $.on(link, 'click', QuoteInline.toggle); - }, - 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, quoter, ref, ref1, threadID; - if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) { - return; - } - ref = Get.postDataFromLink(this), boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; - if (Conf['Inline Cross-thread Quotes Only'] && g.VIEW === 'thread' && ((ref1 = g.posts[boardID + "." + postID]) != null ? ref1.nodes.root.offsetParent : void 0)) { - return; - } - e.preventDefault(); - quoter = Get.postFromNode(this); - context = quoter.context; - if ($.hasClass(this, 'inlined')) { - QuoteInline.rm(this, boardID, threadID, postID, context); - } else { - if ($.x("ancestor::div[@data-full-i-d='" + boardID + "." + postID + "']", this)) { - return; - } - QuoteInline.add(this, boardID, threadID, postID, context, quoter); - } - 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, quoter) { - var inline, isBacklink, post, qroot, root; - isBacklink = $.hasClass(quotelink, 'backlink'); - inline = $.el('div', { - className: 'inline' - }); - inline.dataset.fullID = boardID + "." + postID; - 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, quoter); - 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, ref, root; - isBacklink = $.hasClass(quotelink, 'backlink'); - root = QuoteInline.findRoot(quotelink, isBacklink); - root = $.x("following-sibling::div[@data-full-i-d='" + boardID + "." + 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.context.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 k, len1, link, ref; - ref = this.nodes.quotelinks.concat(slice.call(this.nodes.backlinks)); - for (k = 0, len1 = ref.length; k < len1; k++) { - link = ref[k]; - $.on(link, 'mouseover', QuotePreview.mouseover); - } - }, - mouseover: function(e) { - var boardID, k, len1, origin, post, postID, posts, qp, ref, threadID; - if ($.hasClass(this, 'inlined') || !d.contains(this)) { - 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.postFromNode(this)); - UI.hover({ - root: this, - el: qp, - latestEvent: e, - endEvents: 'mouseout click', - cb: QuotePreview.mouseout - }); - if (Conf['Quote Highlighting'] && (origin = g.posts[boardID + "." + postID])) { - posts = [origin].concat(origin.clones); - posts.pop(); - for (k = 0, len1 = posts.length; k < len1; k++) { - post = posts[k]; - $.addClass(post.nodes.post, 'qphl'); - } - } - }, - mouseout: function() { - var clone, k, len1, post, ref, root; - 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 (k = 0, len1 = ref.length; k < len1; k++) { - post = ref[k]; - $.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, k, len1, postID, quotelink, ref, ref1, ref2; - if (this.isClone) { - return; - } - ref = this.nodes.quotelinks; - for (k = 0, len1 = ref.length; k < len1; k++) { - quotelink = ref[k]; - 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.controls = $.el('label', { - innerHTML: " Threading" - }); - this.threadNewLink = $.el('span', { - className: 'brackets-wrap threadnewlink', - hidden: true - }); - $.extend(this.threadNewLink, { - innerHTML: "Thread New Posts" - }); - this.input = $('input', this.controls); - this.input.checked = Conf['Thread Quotes']; - $.on(this.input, 'change', this.setEnabled); - $.on(this.input, 'change', this.rethread); - $.on(this.threadNewLink.firstElementChild, 'click', this.rethread); - $.on(d, '4chanXInitFinished', (function(_this) { - return function() { - return _this.ready = true; - }; - })(this)); - Header.menu.addEntry(this.entry = { - el: this.controls, - order: 99 - }); - Thread.callbacks.push({ - name: 'Quote Threading', - cb: this.setThread - }); - return Post.callbacks.push({ - name: 'Quote Threading', - cb: this.node - }); - }, - parent: {}, - children: {}, - inserted: {}, - setEnabled: function() { - var other, ref; - other = (ref = ReplyPruning.inputs) != null ? ref.enabled : void 0; - if (this.checked && (other != null ? other.checked : void 0)) { - other.checked = false; - $.event('change', null, other); - } - return $.cb.checked.call(this); - }, - setThread: function() { - QuoteThreading.thread = this; - return $.asap((function() { - return !Conf['Thread Updater'] || $('.navLinksBot > .updatelink'); - }), function() { - var navLinksBot; - if ((navLinksBot = $('.navLinksBot'))) { - return $.add(navLinksBot, [$.tn(' '), QuoteThreading.threadNewLink]); - } - }); - }, - node: function() { - var ancestor, k, lastParent, len1, parent, parents, quote, ref; - if (this.isFetchedQuote || this.isClone || !this.isReply) { - return; - } - parents = new Set(); - lastParent = null; - ref = this.quotes; - for (k = 0, len1 = ref.length; k < len1; k++) { - quote = ref[k]; - 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, k, len1, posts; - posts = [post]; - if (children = QuoteThreading.children[post.fullID]) { - for (k = 0, len1 = children.length; k < len1; k++) { - child = children[k]; - posts = posts.concat(QuoteThreading.descendants(child)); - } - } - return posts; - }, - insert: function(post) { - var base1, child, children, descendants, i, k, len1, name1, next, nodes, order, parent, prev, prev2, q, threadContainer, u, x; - if (!(Conf['Thread Quotes'] && (parent = QuoteThreading.parent[post.fullID]) && !QuoteThreading.inserted[post.fullID])) { - return false; - } - descendants = QuoteThreading.descendants(post); - if (!Unread.posts.has(parent.ID)) { - if ((function() { - var k, len1, x; - for (k = 0, len1 = descendants.length; k < len1; k++) { - x = descendants[k]; - if (Unread.posts.has(x.ID)) { - return true; - } - } - })()) { - QuoteThreading.threadNewLink.hidden = false; - return false; - } - } - order = Unread.order; - children = ((base1 = QuoteThreading.children)[name1 = parent.fullID] || (base1[name1] = [])); - 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 (k = children.length - 1; k >= 0; k += -1) { - child = children[k]; - if (child.ID >= post.ID) { - i--; - } - } - if (i !== children.length) { - next = children[i]; - for (q = 0, len1 = descendants.length; q < len1; q++) { - x = descendants[q]; - 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 (u = descendants.length - 1; u >= 0; u += -1) { - x = descendants[u]; - 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; - if (!QuoteThreading.ready) { - return; - } - thread = QuoteThreading.thread; - posts = thread.posts; - QuoteThreading.threadNewLink.hidden = true; - if (Conf['Thread Quotes']) { - 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 (!Conf['Remember Your Posts']) { - return; - } - this.db = new DataBoard('yourPosts'); - $.sync('Remember Your Posts', function(enabled) { - return Conf['Remember Your Posts'] = enabled; - }); - $.on(d, 'QRPostSuccessful', function(e) { - var boardID, postID, ref, threadID; - $.forceSync('Remember Your Posts'); - if (Conf['Remember Your Posts']) { - ref = e.detail, boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; - return QuoteYou.db.set({ - boardID: boardID, - threadID: threadID, - postID: postID, - val: true - }); - } - }); - if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { - 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 k, len1, quotelink, ref; - if (this.isClone) { - return; - } - if (QuoteYou.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 (k = 0, len1 = ref.length; k < len1; k++) { - quotelink = ref[k]; - if (!(QuoteYou.db.get(Get.postDataFromLink(quotelink)))) { - continue; - } - if (Conf['Mark Quotes of You']) { - $.add(quotelink, $.tn(QuoteYou.text)); - } - $.addClass(quotelink, 'you'); - $.addClass(this.nodes.root, 'quotesYou'); - } - }, - cb: { - seek: function(type) { - var highlight, post, posts, result, str; - if (highlight = $('.highlight')) { - $.rmClass(highlight, 'highlight'); - } - if (!(QuoteYou.lastRead && doc.contains(QuoteYou.lastRead) && $.hasClass(QuoteYou.lastRead, 'quotesYou'))) { - 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(root) { - var post; - post = $('.post', root); - if (!post.getBoundingClientRect().height) { - return false; - } else { - QuoteYou.lastRead = root; - window.location = "#" + post.id; - Header.scrollTo(post); - $.addClass(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, k, len1, ref; - if (this.isClone) { - return; - } - ref = $$('.deadlink', this.nodes.comment); - for (k = 0, len1 = ref.length; k < len1; k++) { - deadlink = ref[k]; - 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', - 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', - 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'], - validExtension: /\.(jpe?g|png|gif|pdf|swf|webm)$/i, - typeFromExtension: { - 'jpg': 'image/jpeg', - 'jpeg': 'image/jpeg', - 'png': 'image/png', - 'gif': 'image/gif', - 'pdf': 'application/pdf', - 'swf': 'application/vnd.adobe.flash.movie', - 'webm': 'video/webm' - }, - extensionFromType: { - 'image/jpeg': 'jpg', - 'image/png': 'png', - 'image/gif': 'gif', - 'application/pdf': 'pdf', - 'application/vnd.adobe.flash.movie': 'swf', - 'application/x-shockwave-flash': 'swf', - 'video/webm': 'webm' - }, - init: function() { - var sc, version; - if (!Conf['Quick Reply']) { - return; - } - this.posts = []; - if (g.VIEW === 'archive') { - return; - } - version = Conf['Use Recaptcha v1'] && Main.jsEnabled ? 'v1' : 'v2'; - this.captcha = Captcha[version]; - $.on(d, '4chanXInitFinished', this.initReady); - 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(); - } - }); - return Header.addShortcut(sc); - } - }, - initReady: function() { - var link, linkBot, navLinksBot, origToggle; - $.off(d, '4chanXInitFinished', this.initReady); - QR.postingIsEnabled = !!$.id('postForm'); - if (!QR.postingIsEnabled) { - return; - } - link = $.el('h1', { - className: "qr-link-container" - }); - $.extend(link, { - innerHTML: "" + (g.VIEW === "thread" ? "Reply to Thread" : "Start a Thread") + "" - }); - 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: "Reply to Thread" - }); - $.on(linkBot.firstElementChild, 'click', function() { - QR.open(); - return QR.nodes.com.focus(); - }); - if ((navLinksBot = $('.navLinksBot'))) { - $.prepend(navLinksBot, linkBot); - } - } - origToggle = $.id('togglePostFormLink'); - $.before(origToggle, link); - origToggle.firstElementChild.textContent = 'Original Form'; - $.on(d, 'QRGetFile', QR.getFile); - $.on(d, 'QRSetFile', QR.setFile); - $.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 k, len1, post, 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 (k = 0, len1 = ref.length; k < len1; k++) { - post = ref[k]; - post["delete"](); - } - QR.cooldown.auto = false; - QR.status(); - return QR.captcha.destroy(); - }, - focus: function() { - return $.queueTask(function() { - if (!QR.inBubble()) { - QR.hasFocus = d.activeElement && QR.nodes.el.contains(d.activeElement); - return QR.nodes.el.classList.toggle('focus', QR.hasFocus); - } - }); - }, - inBubble: function() { - var bubbles, ref; - bubbles = $$('iframe[src^="https://www.google.com/recaptcha/api2/frame"]'); - return (ref = d.activeElement, indexOf.call(bubbles, ref) >= 0) || bubbles.some(function(el) { - return getComputedStyle(el).visibility !== 'hidden' && el.getBoundingClientRect().bottom > 0; - }); - }, - 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(); - } - }, - toggleSJIS: function(e) { - e.preventDefault(); - Conf['sjisPreview'] = !Conf['sjisPreview']; - $.set('sjisPreview', Conf['sjisPreview']); - return QR.nodes.el.classList.toggle('sjis-preview', Conf['sjisPreview']); - }, - texPreviewShow: function() { - if ($.hasClass(QR.nodes.el, 'tex-preview')) { - return QR.texPreviewHide(); - } - $.addClass(QR.nodes.el, 'tex-preview'); - QR.nodes.texPreview.textContent = QR.nodes.com.value; - return $.event('mathjax', null, QR.nodes.texPreview); - }, - texPreviewHide: function() { - return $.rmClass(QR.nodes.el, 'tex-preview'); - }, - setCustomCooldown: function(enabled) { - Conf['customCooldownEnabled'] = enabled; - QR.cooldown.customCooldown = enabled; - return QR.nodes.customCooldown.classList.toggle('disabled', !enabled); - }, - toggleCustomCooldown: function() { - var enabled; - enabled = $.hasClass(this, 'disabled'); - QR.setCustomCooldown(enabled); - return $.set('customCooldownEnabled', enabled); - }, - error: function(err, focusOverride) { - var el, notice, notif; - QR.open(); - if (typeof err === 'string') { - el = $.tn(err); - } else { - el = err; - el.removeAttribute('style'); - } - notice = new Notice('warning', el); - QR.notifications.push(notice); - if (!Header.areNotificationsEnabled) { - if (d.hidden && !QR.cooldown.auto) { - return alert(el.textContent); - } - } else if (d.hidden || !(focusOverride || d.hasFocus())) { - try { - notif = new Notification(el.textContent, { - body: el.textContent, - icon: Favicon.logo - }); - notif.onclick = function() { - return $.global(function() { - return window.focus(); - }); - }; - if ($.engine !== 'gecko') { - notif.onclose = function() { - return notice.close(); - }; - return notif.onshow = function() { - return setTimeout(function() { - notif.onclose = null; - return notif.close(); - }, 7 * $.SECOND); - }; - } - } catch (_error) {} - } - }, - notifications: [], - cleanNotifications: function() { - var k, len1, notification, ref; - ref = QR.notifications; - for (k = 0, len1 = ref.length; k < len1; k++) { - notification = ref[k]; - 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; - }, - openPost: function() { - var index; - 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'); - return QR.cooldown.auto = true; - } - }, - quote: function(e) { - var aa, ancestor, caretPos, com, frag, insideCode, k, len1, len2, len3, len4, len5, len6, node, post, q, range, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, sel, text, thread, u, v, z; - 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 (k = 0, len1 = ref.length; k < len1; k++) { - node = ref[k]; - $.replace(node, $.tn('\n')); - } - ref1 = $$('br', frag); - for (q = 0, len2 = ref1.length; q < len2; q++) { - node = ref1[q]; - if (node !== frag.lastChild) { - $.replace(node, $.tn('\n>')); - } - } - ref2 = $$('s, .removed-spoiler', frag); - for (u = 0, len3 = ref2.length; u < len3; u++) { - node = ref2[u]; - $.replace(node, [$.tn('[spoiler]')].concat(slice.call(node.childNodes), [$.tn('[/spoiler]')])); - } - ref3 = $$('.prettyprint', frag); - for (v = 0, len4 = ref3.length; v < len4; v++) { - node = ref3[v]; - $.replace(node, [$.tn('[code]')].concat(slice.call(node.childNodes), [$.tn('[/code]')])); - } - ref4 = $$('.linkify[data-original]', frag); - for (z = 0, len5 = ref4.length; z < len5; z++) { - node = ref4[z]; - $.replace(node, $.tn(node.dataset.original)); - } - ref5 = $$('.embedder', frag); - for (aa = 0, len6 = ref5.length; aa < len6; aa++) { - node = ref5[aa]; - if (((ref6 = node.previousSibling) != null ? ref6.nodeValue : void 0) === ' ') { - $.rm(node.previousSibling); - } - $.rm(node); - } - text += ">" + (frag.textContent.trim()) + "\n"; - } - QR.openPost(); - 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.value.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '_').length; - counter.textContent = count; - counter.hidden = count < QR.max_comment / 2; - return (count > QR.max_comment ? $.addClass : $.rmClass)(counter, 'warning'); - }, - getFile: function() { - var ref; - return $.event('QRFile', (ref = QR.selected) != null ? ref.file : void 0); - }, - setFile: function(e) { - var file, name, ref, source; - ref = e.detail, file = ref.file, name = ref.name, source = ref.source; - if (name != null) { - file.name = name; - } - if (source != null) { - file.source = source; - } - QR.open(); - return QR.handleFiles([file]); - }, - 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, k, len1, ref; - if (!e.clipboardData.items) { - return; - } - files = []; - ref = e.clipboardData.items; - for (k = 0, len1 = ref.length; k < len1; k++) { - item = ref[k]; - 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'); - }, - pasteFF: function() { - var arr, blob, bstr, i, images, img, k, len1, m, pasteArea, q, ref, src; - pasteArea = QR.nodes.pasteArea; - if (!pasteArea.childNodes.length) { - return; - } - images = $$('img', pasteArea); - $.rmAll(pasteArea); - for (k = 0, len1 = images.length; k < len1; k++) { - img = images[k]; - src = img.src; - if (m = src.match(/data:(image\/(\w+));base64,(.+)/)) { - bstr = atob(m[3]); - arr = new Uint8Array(bstr.length); - for (i = q = 0, ref = bstr.length; 0 <= ref ? q < ref : q > ref; i = 0 <= ref ? ++q : --q) { - arr[i] = bstr.charCodeAt(i); - } - blob = new Blob([arr], { - type: m[1] - }); - blob.name = "file." + m[2]; - QR.handleFiles([blob]); - } else if (/^https?:\/\//.test(src)) { - QR.handleUrl(src); - } - } - }, - handleUrl: function(urlDefault) { - var url; - url = prompt('Enter a URL:', urlDefault); - if (url === null) { - return; - } - QR.nodes.fileButton.focus(); - return CrossOrigin.file(url, function(blob) { - if (blob && !/^text\//.test(blob.type)) { - return QR.handleFiles([blob]); - } else { - return QR.error("Can't load file."); - } - }); - }, - handleFiles: function(files) { - var file, k, len1; - if (this !== QR) { - files = slice.call(this.files); - this.value = null; - } - if (!files.length) { - return; - } - QR.cleanNotifications(); - for (k = 0, len1 = files.length; k < len1; k++) { - file = files[k]; - QR.handleFile(file, files.length); - } - if (files.length !== 1) { - $.addClass(QR.nodes.el, 'dump'); - } - if (d.activeElement === QR.nodes.fileButton && $.hasClass(QR.nodes.fileSubmit, 'has-file')) { - return QR.nodes.filename.focus(); - } - }, - handleFile: function(file, nfiles) { - var isText, post; - isText = /^text\//.test(file.type); - if (nfiles === 1) { - post = QR.selected; - } else { - post = QR.posts[QR.posts.length - 1]; - if ((isText ? post.com || post.pasting : post.file)) { - post = new QR.post(); - } - } - return post[isText ? 'pasteText' : 'setFile'](file); - }, - openFileInput: function() { - if (QR.nodes.fileButton.disabled) { - return; - } - QR.nodes.fileInput.click(); - return QR.nodes.fileButton.focus(); - }, - generatePostableThreadsList: function() { - var k, len1, list, options, ref, thread, val; - if (!QR.nodes) { - return; - } - list = QR.nodes.thread; - options = [list.firstElementChild]; - ref = g.BOARD.threads.keys; - for (k = 0, len1 = ref.length; k < len1; k++) { - thread = ref[k]; - options.push($.el('option', { - value: thread, - textContent: "Thread " + 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, ref, rules, save, scriptData, setNode; - QR.nodes = nodes = { - el: dialog = UI.dialog('qr', 'top: 50px; right: 0px;', { - innerHTML: "
×
No selected file
" - }) - }; - setNode = function(name, query) { - return nodes[name] = $(query, dialog); - }; - setNode('move', '.move'); - setNode('autohide', '#autohide'); - setNode('close', '.close'); - setNode('thread', 'select'); - setNode('form', 'form'); - setNode('sjisToggle', '#sjis-toggle'); - setNode('texButton', '#tex-preview-button'); - setNode('name', '[data-name=name]'); - setNode('email', '[data-name=email]'); - setNode('sub', '[data-name=sub]'); - setNode('com', '[data-name=com]'); - setNode('charCount', '#char-count'); - setNode('texPreview', '#tex-preview'); - setNode('dumpList', '#dump-list'); - setNode('addPost', '#add-post'); - setNode('oekaki', '.oekaki'); - setNode('drawButton', '#qr-draw-button'); - setNode('fileSubmit', '#file-n-submit'); - setNode('fileButton', '#qr-file-button'); - setNode('noFile', '#qr-no-file'); - setNode('filename', '#qr-filename'); - setNode('spoiler', '#qr-file-spoiler'); - setNode('oekakiButton', '#qr-oekaki-button'); - setNode('fileRM', '#qr-filerm'); - setNode('urlButton', '#url-button'); - setNode('pasteArea', '#paste-area'); - setNode('customCooldown', '#custom-cooldown-button'); - setNode('dumpButton', '#dump-button'); - setNode('status', '[type=submit]'); - setNode('flashTag', '[name=filetag]'); - 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; - scriptData = Get.scriptData(); - QR.max_size = (m = scriptData.match(/\bmaxFilesize *= *(\d+)\b/)) ? +m[1] : 4194304; - QR.max_size_video = (m = scriptData.match(/\bmaxWebmFilesize *= *(\d+)\b/)) ? +m[1] : QR.max_size; - QR.max_comment = (m = scriptData.match(/\bcomlen *= *(\d+)\b/)) ? +m[1] : 2000; - 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'); - } - if (g.BOARD.ID === 'jp' && Conf['sjisPreview']) { - $.addClass(QR.nodes.el, 'sjis-preview'); - } - if (parseInt(Conf['customCooldown'], 10) > 0) { - $.addClass(QR.nodes.fileSubmit, 'custom-cooldown'); - $.get('customCooldownEnabled', Conf['customCooldownEnabled'], function(arg) { - var customCooldownEnabled; - customCooldownEnabled = arg.customCooldownEnabled; - QR.setCustomCooldown(customCooldownEnabled); - return $.sync('customCooldownEnabled', QR.setCustomCooldown); - }); - } - $.on(nodes.autohide, 'change', QR.toggleHide); - $.on(nodes.close, 'click', QR.close); - $.on(nodes.form, 'submit', QR.submit); - $.on(nodes.sjisToggle, 'click', QR.toggleSJIS); - $.on(nodes.texButton, 'mousedown', QR.texPreviewShow); - $.on(nodes.texButton, 'mouseup', QR.texPreviewHide); - $.on(nodes.addPost, 'click', function() { - return new QR.post(true); - }); - $.on(nodes.drawButton, 'click', QR.oekaki.draw); - $.on(nodes.fileButton, 'click', QR.openFileInput); - $.on(nodes.noFile, 'click', QR.openFileInput); - $.on(nodes.filename, 'focus', function() { - return $.addClass(this.parentNode, 'focus'); - }); - $.on(nodes.filename, 'blur', function() { - return $.rmClass(this.parentNode, 'focus'); - }); - $.on(nodes.spoiler, 'change', function() { - return QR.selected.nodes.spoiler.click(); - }); - $.on(nodes.oekakiButton, 'click', QR.oekaki.button); - $.on(nodes.fileRM, 'click', function() { - return QR.selected.rmFile(); - }); - $.on(nodes.urlButton, 'click', function() { - return QR.handleUrl(''); - }); - $.on(nodes.customCooldown, 'click', QR.toggleCustomCooldown); - $.on(nodes.dumpButton, 'click', function() { - return nodes.el.classList.toggle('dump'); - }); - $.on(nodes.fileInput, 'change', QR.handleFiles); - window.addEventListener('focus', QR.focus, true); - window.addEventListener('blur', QR.focus, true); - $.on(d, 'click', QR.focus); - if ($.engine === 'gecko') { - nodes.pasteArea.hidden = false; - new MutationObserver(QR.pasteFF).observe(nodes.pasteArea, { - childList: true - }); - } - 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 ($.engine === 'gecko' && 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.setup(); - QR.captcha.init(); - $.add(d.body, dialog); - QR.captcha.setup(); - QR.oekaki.setup(); - return $.event('QRDialogCreation', null, dialog); - }, - submit: function(e) { - var captcha, cb, err, extra, filetag, formData, options, post, ref, 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(); - threadID = post.thread; - thread = g.BOARD.threads[threadID]; - if (g.BOARD.ID === 'f' && threadID === 'new') { - filetag = QR.nodes.flashTag.value; - } - if (threadID === 'new') { - threadID = null; - if (g.BOARD.ID === 'vg' && !post.sub) { - err = 'New threads require a subject.'; - } else if (!($.hasClass(d.body, 'text_only') || 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 comment or file.'; - } else if (post.file && thread.fileLimit) { - err = 'Max limit of image replies has been reached.'; - } - if (g.BOARD.ID === 'r9k' && !((ref = post.com) != null ? ref.match(/[a-z-]/i) : void 0)) { - err || (err = 'Original comment required.'); - } - if (QR.captcha.isEnabled && !err) { - captcha = QR.captcha.getOne(); - if (!captcha) { - err = 'No valid captcha.'; - QR.captcha.setup(!QR.cooldown.auto || d.activeElement === QR.nodes.status); - } - } - 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. [Banned?] [More info]" - })); - } - }; - extra = { - form: $.formData(formData), - upCallbacks: { - onload: function() { - QR.req.isUploadFinished = true; - 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) { - if (response.challenge != null) { - extra.form.append('recaptcha_challenge_field', response.challenge); - extra.form.append('recaptcha_response_field', response.response); - } else { - extra.form.append('g-recaptcha-response', 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, err, h1, isReply, lastPostToThread, m, open, post, postID, postsCount, ref, ref1, ref2, req, resDoc, seconds, threadID; - 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 + "! ;_;
Click here to see the reason." - } : { - innerHTML: "You were issued a warning on " + $(".board", resDoc).innerHTML + " as " + $(".nameBlock", resDoc).innerHTML + ".
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 = $.el('span', { - innerHTML: "You mistyped the CAPTCHA, or the CAPTCHA malfunctioned [complain here]." - }); - } else if (/expired/i.test(err.textContent)) { - err = 'This CAPTCHA is no longer valid because it has expired.'; - } - QR.cooldown.auto = QR.captcha.isEnabled || err === 'Connection error with sys.4chan.org.'; - QR.cooldown.addDelay(post, 2); - } else if (err.textContent && (m = err.textContent.match(/(?:(\d+)\s+minutes?\s+)?(\d+)\s+second/i)) && !/duplicate|hour/i.test(err.textContent)) { - QR.cooldown.auto = !/have\s+been\s+muted/i.test(err.textContent); - seconds = 60 * (+(m[1] || 0)) + (+m[2]); - if (/muted/i.test(err.textContent)) { - QR.cooldown.addMute(seconds); - } else { - QR.cooldown.addDelay(post, seconds); - } - } else { - QR.cooldown.auto = false; - } - QR.captcha.setup(QR.cooldown.auto && ((ref1 = d.activeElement) === QR.nodes.status || ref1 === d.body)); - if (QR.captcha.isEnabled && !QR.captcha.captchas.length) { - 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)); - } - ref2 = h1.nextSibling.textContent.match(/thread:(\d+),no:(\d+)/), _ = ref2[0], threadID = ref2[1], postID = ref2[2]; - postID = +postID; - threadID = +threadID || postID; - isReply = threadID !== 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; - lastPostToThread = !((function() { - var k, len1, p, ref3; - ref3 = QR.posts.slice(1); - for (k = 0, len1 = ref3.length; k < len1; k++) { - p = ref3[k]; - if (p.thread === post.thread) { - return true; - } - } - })()); - if (!(Conf['Persistent QR'] || postsCount)) { - QR.close(); - } else { - post.rm(); - QR.captcha.setup(d.activeElement === QR.nodes.status); - } - QR.cooldown.add(threadID, postID); - URL = threadID === postID ? window.location.origin + "/" + g.BOARD + "/thread/" + threadID : g.VIEW === 'index' && lastPostToThread && Conf['Open Post in New Tab'] ? window.location.origin + "/" + g.BOARD + "/thread/" + threadID + "#p" + postID : void 0; - if (URL) { - open = Conf['Open Post in New Tab'] || postsCount ? function() { - return $.open(URL); - } : function() { - return window.location = URL; - }; - if (threadID === postID) { - QR.waitForThread(URL, open); - } else { - open(); - } - } - return QR.status(); - }, - waitForThread: function(url, cb) { - var attempts, check; - attempts = 0; - check = function() { - return $.ajax(url, { - onloadend: function() { - attempts++; - if (attempts >= 6 || this.status === 200) { - return cb(); - } else { - return setTimeout(check, attempts * $.SECOND); - } - } - }, { - type: 'HEAD' - }); - }; - return check(); - }, - 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.fixes = { - imageKeys: '789456123uiojklm'.split('').concat(['Comma', 'Period']), - imageKeys16: '7890uiopjkl'.split('').concat(['Semicolon', 'm', 'Comma', 'Period', 'Slash']), - css: '.rc-imageselect-target > div:focus, .rc-image-tile-target:focus {\n outline: 2px solid #4a90e2;\n}\n.rc-imageselect-target td:focus {\n box-shadow: inset 0 0 0 2px #4a90e2;\n outline: none;\n}\n.rc-button-default:focus {\n box-shadow: inset 0 0 0 2px #0063d6;\n}', - cssNoscript: '.fbc-payload-imageselect {\n position: relative;\n}\n.fbc-payload-imageselect > label {\n position: absolute;\n display: block;\n height: 93.3px;\n width: 93.3px;\n}\nlabel[data-row="0"] {top: 0px;}\nlabel[data-row="1"] {top: 93.3px;}\nlabel[data-row="2"] {top: 186.6px;}\nlabel[data-col="0"] {left: 0px;}\nlabel[data-col="1"] {left: 93.3px;}\nlabel[data-col="2"] {left: 186.6px;}\n.fbc-payload-imageselect > input:focus + label {\n outline: 2px solid #4a90e2;\n}\n.fbc-button-verify input:focus {\n box-shadow: inset 0 0 0 2px #0063d6;\n}\nbody.focus .fbc {\n box-shadow: inset 0 0 0 2px #4a90e2;\n}', - init: function() { - switch (location.pathname.split('/')[3]) { - case 'anchor': - return this.initMain(); - case 'frame': - return this.initPopup(); - case 'fallback': - return this.initNoscript(); - } - }, - initMain: function() { - var a, k, len1, ref; - $.onExists(d.body, '#recaptcha-anchor', function(checkbox) { - var focus; - focus = function() { - var ref; - if (d.hasFocus() && ((ref = d.activeElement) === d.documentElement || ref === d.body)) { - return checkbox.focus(); - } - }; - focus(); - return $.on(window, 'focus', function() { - return $.queueTask(focus); - }); - }); - ref = $$('.rc-anchor-pt a'); - for (k = 0, len1 = ref.length; k < len1; k++) { - a = ref[k]; - a.tabIndex = -1; - } - }, - initPopup: function() { - $.addStyle(this.css); - this.fixImages(); - new MutationObserver((function(_this) { - return function() { - return _this.fixImages(); - }; - })(this)).observe(d.body, { - childList: true, - subtree: true - }); - return $.on(d, 'keydown', this.keybinds.bind(this)); - }, - initNoscript: function() { - var data, ref, token; - this.noscript = true; - data = (token = (ref = $('.fbc-verification-token > textarea')) != null ? ref.value : void 0) ? { - token: token - } : { - working: true - }; - new Connection(window.parent, '*').send(data); - d.body.classList.toggle('focus', d.hasFocus()); - $.on(window, 'focus blur', function() { - return d.body.classList.toggle('focus', d.hasFocus()); - }); - this.images = $$('.fbc-payload-imageselect > input'); - this.width = 3; - if (this.images.length !== 9) { - return; - } - $.addStyle(this.cssNoscript); - this.addLabels(); - $.on(d, 'keydown', this.keybinds.bind(this)); - return $.on($('.fbc-imageselect-challenge > form'), 'submit', this.checkForm.bind(this)); - }, - fixImages: function() { - var img, k, len1, ref; - this.images = $$('.rc-image-tile-target'); - if (!this.images.length) { - this.images = $$('.rc-imageselect-target > div, .rc-imageselect-target td'); - } - this.width = $$('.rc-imageselect-target tr:first-of-type td').length || Math.round(Math.sqrt(this.images.length)); - ref = this.images; - for (k = 0, len1 = ref.length; k < len1; k++) { - img = ref[k]; - img.tabIndex = 0; - } - if (this.images.length === 9) { - this.addTooltips(this.images); - } else { - this.addTooltips16(this.images); - } - return this.complaintLinks(); - }, - complaintLinks: function() { - var errmsg, k, len1, link, ref; - ref = $$('.rc-imageselect-incorrect-response, .rc-imageselect-error-select-one, .rc-imageselect-error-select-more, .rc-imageselect-error-dynamic-more'); - for (k = 0, len1 = ref.length; k < len1; k++) { - errmsg = ref[k]; - if (!$('a', errmsg)) { - link = $.el('a', { - href: 'https://www.4chan-x.net/captchas.html', - target: '_blank', - textContent: '[complain]' - }); - $.add(errmsg, [$.tn(' '), link]); - } - } - }, - addLabels: function() { - var checkbox, i, imageSelect, label, labels; - imageSelect = $('.fbc-payload-imageselect'); - labels = (function() { - var k, len1, ref, results; - ref = this.images; - results = []; - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - checkbox = ref[i]; - checkbox.id = "checkbox-" + i; - label = $.el('label', { - htmlFor: checkbox.id - }); - label.dataset.row = Math.floor(i / 3); - label.dataset.col = i % 3; - $.after(checkbox, label); - results.push(label); - } - return results; - }).call(this); - return this.addTooltips(labels); - }, - addTooltips: function(nodes) { - var i, k, len1, node; - for (i = k = 0, len1 = nodes.length; k < len1; i = ++k) { - node = nodes[i]; - node.title = this.imageKeys[i] + " or " + (this.imageKeys[i + 9][0].toUpperCase()) + this.imageKeys[i + 9].slice(1); - } - }, - addTooltips16: function(nodes) { - var i, k, key, len1, node, ref; - ref = this.imageKeys16; - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - key = ref[i]; - if (i % 4 < this.width && (node = nodes[nodes.length - (4 - Math.floor(i / 4)) * this.width + (i % 4)])) { - node.title = "" + (key[0].toUpperCase()) + key.slice(1); - } - } - }, - checkForm: function(e) { - var checkbox, k, len1, n, ref; - n = 0; - ref = this.images; - for (k = 0, len1 = ref.length; k < len1; k++) { - checkbox = ref[k]; - if (checkbox.checked) { - n++; - } - } - if (n === 0) { - return e.preventDefault(); - } - }, - keybinds: function(e) { - var dx, i, img, key, last, n, reload, verify, w, x; - if (!(this.images && doc.contains(this.images[0]))) { - return; - } - n = this.images.length; - w = this.width; - last = n + w - 1; - reload = $('#recaptcha-reload-button, .fbc-button-reload'); - verify = $('#recaptcha-verify-button, .fbc-button-verify > input'); - x = this.images.indexOf(d.activeElement); - if (x < 0) { - x = d.activeElement === verify ? last : n; - } - key = Keybinds.keyCode(e); - if (!this.noscript && key === 'Space' && x < n) { - this.images[x].click(); - } else if (n === 9 && (i = this.imageKeys.indexOf(key)) >= 0) { - this.images[i % 9].click(); - verify.focus(); - } else if (n !== 9 && (i = this.imageKeys16.indexOf(key)) >= 0 && i % 4 < w && (img = this.images[n - (4 - Math.floor(i / 4)) * w + (i % 4)])) { - img.click(); - verify.focus(); - } else if (dx = { - 'Up': n, - 'Down': w, - 'Left': last, - 'Right': 1 - }[key]) { - x = (x + dx) % (n + w); - if ((n < x && x < last)) { - x = dx === last ? n : last; - } - (this.images[x] || (x === n ? reload : void 0) || (x === last ? verify : void 0)).focus(); - } else { - return; - } - e.preventDefault(); - return e.stopPropagation(); - } - }; - - Captcha.replace = { - init: function() { - if (!(d.cookie.indexOf('pass_enabled=1') < 0)) { - return; - } - if (location.hostname === 'sys.4chan.org' && /[?&]altc\b/.test(location.search) && Main.jsEnabled) { - $.onExists(doc, 'script[src="//www.google.com/recaptcha/api/js/recaptcha_ajax.js"]', function() { - $.global(function() { - return window.el.onload = null; - }); - return Captcha.v1.create(); - }); - return; - } - if (((Conf['Use Recaptcha v1'] && location.hostname === 'boards.4chan.org') || (Conf['Use Recaptcha v1 in Reports'] && location.hostname === 'sys.4chan.org')) && Main.jsEnabled) { - $.ready(Captcha.replace.v1); - return; - } - if (Conf['Force Noscript Captcha'] && Main.jsEnabled) { - $.ready(Captcha.replace.noscript); - return; - } - if (Conf['captchaLanguage'].trim() || Conf['Captcha Fixes']) { - if (location.hostname === 'boards.4chan.org') { - return $.onExists(doc, '#captchaFormPart', function(node) { - return $.onExists(node, 'iframe', Captcha.replace.iframe); - }); - } else { - return $.onExists(doc, 'iframe', Captcha.replace.iframe); - } - } - }, - noscript: function() { - var insert, noscript, original, span, toggle; - if (!((original = $('#g-recaptcha, #captchaContainerAlt')) && (noscript = $('noscript')))) { - return; - } - span = $.el('span', { - id: 'captcha-forced-noscript' - }); - $.replace(noscript, span); - $.rm(original); - insert = function() { - span.innerHTML = noscript.textContent; - return Captcha.replace.iframe($('iframe', span)); - }; - if ((toggle = $('#togglePostFormLink a, #form-link'))) { - return $.on(toggle, 'click', insert); - } else { - return insert(); - } - }, - v1: function() { - var form, link; - if (!$.id('g-recaptcha')) { - return; - } - Captcha.v1.replace(); - if ((link = $.id('form-link'))) { - return $.on(link, 'click', function() { - return Captcha.v1.create(); - }); - } else if (location.hostname === 'boards.4chan.org') { - form = $.id('postForm'); - return form.addEventListener('focus', (function() { - return Captcha.v1.create(); - }), true); - } else { - return Captcha.v1.create(); - } - }, - iframe: function(iframe) { - var lang, src; - if ((lang = Conf['captchaLanguage'].trim())) { - src = /[?&]hl=/.test(iframe.src) ? iframe.src.replace(/([?&]hl=)[^&]*/, '$1' + encodeURIComponent(lang)) : iframe.src + ("&hl=" + (encodeURIComponent(lang))); - if (iframe.src !== src) { - iframe.src = src; - } - } - return Captcha.replace.autocopy(iframe); - }, - autocopy: function(iframe) { - if (!(Conf['Captcha Fixes'] && /^https:\/\/www\.google\.com\/recaptcha\/api\/fallback\?/.test(iframe.src))) { - return; - } - return new Connection(iframe, 'https://www.google.com', { - working: function() { - var ref, ref1; - if ((ref = $.id('qr')) != null ? ref.contains(iframe) : void 0) { - return (ref1 = $('#qr .captcha-container textarea')) != null ? ref1.parentNode.hidden = true : void 0; - } - }, - token: function(token) { - var node, textarea; - node = iframe; - while ((node = node.parentNode)) { - if ((textarea = $('textarea', node))) { - break; - } - } - textarea.value = token; - return $.event('input', null, textarea); - } - }); - } - }; - - Captcha.v1 = { - blank: "data:image/svg+xml,", - init: function() { - var imgContainer, input; - if (d.cookie.indexOf('pass_enabled=1') >= 0) { - return; - } - if (!(this.isEnabled = !!$('#g-recaptcha, #captchaContainerAlt'))) { - return; - } - imgContainer = $.el('div', { - className: 'captcha-img', - title: 'Reload reCAPTCHA' - }); - $.extend(imgContainer, { - innerHTML: "" - }); - input = $.el('input', { - className: 'captcha-input field', - title: 'Verification', - autocomplete: 'off', - spellcheck: false - }); - this.nodes = { - img: imgContainer.firstChild, - input: input - }; - $.on(input, 'blur', QR.focusout); - $.on(input, 'focus', QR.focusin); - $.on(input, 'keydown', QR.captcha.keydown.bind(QR.captcha)); - $.on(this.nodes.img.parentNode, 'click', QR.captcha.reload.bind(QR.captcha)); - $.addClass(QR.nodes.el, 'has-captcha', 'captcha-v1'); - $.after(QR.nodes.com.parentNode, [imgContainer, 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.replace(); - this.beforeSetup(); - if (Conf['Auto-load captcha']) { - this.setup(); - } - new MutationObserver(this.afterSetup).observe($.id('captchaContainerAlt'), { - childList: true - }); - return this.afterSetup(); - }, - replace: function() { - var container, old; - if (this.script) { - return; - } - if (!(this.script = $('script[src="//www.google.com/recaptcha/api/js/recaptcha_ajax.js"]', d.head))) { - this.script = $.el('script', { - src: '//www.google.com/recaptcha/api/js/recaptcha_ajax.js' - }); - $.add(d.head, this.script); - } - if (old = $.id('g-recaptcha')) { - container = $.el('div', { - id: 'captchaContainerAlt' - }); - return $.replace(old, container); - } - }, - create: function() { - var cont, lang; - cont = $.id('captchaContainerAlt'); - if (this.occupied) { - return; - } - this.occupied = true; - if ((lang = Conf['captchaLanguage'].trim())) { - cont.dataset.lang = lang; - } - $.onExists(cont, '#recaptcha_image', function(image) { - return $.on(image, 'click', function() { - if ($.id('recaptcha_challenge_image')) { - return $.global(function() { - return window.Recaptcha.reload(); - }); - } - }); - }); - $.onExists(cont, '#recaptcha_response_field', function(field) { - $.on(field, 'keydown', function(e) { - if (e.keyCode === 8 && !field.value) { - return $.global(function() { - return window.Recaptcha.reload(); - }); - } - }); - if (location.hostname === 'sys.4chan.org') { - return field.focus(); - } - }); - return $.global(function() { - var container, options, script; - container = document.getElementById('captchaContainerAlt'); - options = { - theme: 'clean', - tabindex: { - "boards.4chan.org": 5 - }[location.hostname], - lang: container.dataset.lang - }; - if (window.Recaptcha) { - return window.Recaptcha.create('6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc', container, options); - } else { - script = document.head.querySelector('script[src="//www.google.com/recaptcha/api/js/recaptcha_ajax.js"]'); - return script.addEventListener('load', function() { - return window.Recaptcha.create('6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc', container, options); - }, false); - } - }); - }, - cb: { - focus: function() { - return QR.captcha.setup(false, true); - } - }, - beforeSetup: function() { - var img, input, ref; - ref = this.nodes, img = ref.img, input = ref.input; - img.parentNode.hidden = true; - img.src = this.blank; - 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 && (force || this.needed()))) { - return; - } - this.create(); - if (focus) { - $.addClass(QR.nodes.el, 'focus'); - return this.nodes.input.focus(); - } - }, - afterSetup: function() { - var challenge, img, input, ref, setLifetime; - if (!(challenge = $.id('recaptcha_challenge_field_holder'))) { - return; - } - if (challenge === QR.captcha.nodes.challenge) { - return; - } - setLifetime = function(e) { - return QR.captcha.lifetime = e.detail; - }; - $.on(window, 'captcha:timeout', setLifetime); - $.global(function() { - return window.dispatchEvent(new CustomEvent('captcha:timeout', { - detail: window.RecaptchaState.timeout - })); - }); - $.off(window, 'captcha:timeout', setLifetime); - ref = QR.captcha.nodes, img = ref.img, input = ref.input; - img.parentNode.hidden = false; - input.placeholder = 'Verification'; - QR.captcha.count(); - $.off(input, 'focus click', QR.captcha.cb.focus); - QR.captcha.nodes.challenge = challenge; - new MutationObserver(QR.captcha.load.bind(QR.captcha)).observe(challenge, { - childList: true, - subtree: true, - attributes: true - }); - QR.captcha.load(); - if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) { - QR.nodes.el.style.top = null; - return QR.nodes.el.style.bottom = '0px'; - } - }, - destroy: function() { - if (!this.script) { - return; - } - $.global(function() { - return window.Recaptcha.destroy(); - }); - delete this.occupied; - if (this.nodes) { - return this.beforeSetup(); - } - }, - sync: function(captchas) { - if (captchas == null) { - captchas = []; - } - QR.captcha.captchas = captchas; - return QR.captcha.count(); - }, - getOne: function() { - var captcha, challenge, response, timeout; - this.clear(); - if (captcha = this.captchas.shift()) { - this.count(); - $.set('captchas', this.captchas); - return captcha; - } else { - challenge = this.nodes.img.alt; - timeout = this.timeout; - if (/\S/.test(response = this.nodes.input.value)) { - this.destroy(); - return { - challenge: challenge, - response: response, - timeout: timeout - }; - } else { - return null; - } - } - }, - save: function() { - var response; - if (!/\S/.test(response = this.nodes.input.value)) { - return; - } - this.nodes.input.value = ''; - this.captchas.push({ - challenge: this.nodes.img.alt, - response: response, - timeout: this.timeout - }); - this.captchas.sort(function(a, b) { - return a.timeout - b.timeout; - }); - this.count(); - this.destroy(); - this.setup(false, true); - return $.set('captchas', this.captchas); - }, - clear: function() { - var captcha, i, k, len1, now, ref; - if (!this.captchas.length) { - return; - } - $.forceSync('captchas'); - now = Date.now(); - ref = this.captchas; - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - captcha = ref[i]; - if (captcha.timeout > now) { - break; - } - } - if (!i) { - return; - } - this.captchas = this.captchas.slice(i); - this.count(); - return $.set('captchas', this.captchas); - }, - load: function() { - var challenge, challenge_image; - if ($('#captchaContainerAlt[class~="recaptcha_is_showing_audio"]')) { - this.nodes.img.src = this.blank; - return; - } - if (!this.nodes.challenge.firstChild) { - return; - } - if (!(challenge_image = $.id('recaptcha_challenge_image'))) { - return; - } - this.timeout = Date.now() + this.lifetime * $.SECOND - $.MINUTE; - challenge = this.nodes.challenge.firstChild.value; - this.nodes.img.alt = challenge; - this.nodes.img.src = challenge_image.src; - this.nodes.input.value = ''; - return this.clear(); - }, - 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.timer); - if (count) { - return this.timer = setTimeout(this.clear.bind(this), this.captchas[0].timeout - Date.now()); - } - }, - reload: function(focus) { - $.global(function() { - if (window.Recaptcha.type === 'image') { - window.Recaptcha.reload(); - } else { - window.Recaptcha.switch_type('image'); - } - return window.Recaptcha.should_focus = false; - }); - if (focus) { - return this.nodes.input.focus(); - } - }, - keydown: function(e) { - if (e.keyCode === 8 && !this.nodes.input.value) { - this.reload(); - } else if (e.keyCode === 13 && e.shiftKey) { - this.save(); - } else { - return; - } - return e.preventDefault(); - } - }; - - Captcha.v2 = { - lifetime: 2 * $.MINUTE, - init: function() { - var counter, root; - if (d.cookie.indexOf('pass_enabled=1') >= 0) { - return; - } - if (!(this.isEnabled = !!$('#g-recaptcha, #captchaContainerAlt, #captcha-forced-noscript'))) { - return; - } - if ((this.noscript = Conf['Force Noscript Captcha'] || !Main.jsEnabled)) { - $.addClass(QR.nodes.el, 'noscript-captcha'); - } - 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: "
" - }); - counter = $('.captcha-counter > a', root); - this.nodes = { - root: root, - counter: counter - }; - this.count(); - $.addClass(QR.nodes.el, 'has-captcha', 'captcha-v2'); - $.after(QR.nodes.com.parentNode, root); - $.on(counter, 'click', this.toggle.bind(this)); - $.on(counter, 'keydown', (function(_this) { - return function(e) { - if (Keybinds.keyCode(e) !== 'Space') { - return; - } - _this.toggle(); - e.preventDefault(); - return e.stopPropagation(); - }; - })(this)); - return $.on(window, 'captcha:success', (function(_this) { - return function() { - return $.queueTask(function() { - return _this.save(false); - }); - }; - })(this)); - }, - timeouts: {}, - postsCount: 0, - noscriptURL: function() { - var lang, url; - url = 'https://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc'; - if ((lang = Conf['captchaLanguage'].trim())) { - url += "&hl=" + (encodeURIComponent(lang)); - } - return url; - }, - 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) { - if (!(this.isEnabled && (this.needed() || force))) { - return; - } - if (focus) { - $.addClass(QR.nodes.el, 'focus'); - this.nodes.counter.focus(); - } - if (this.timeouts.destroy) { - clearTimeout(this.timeouts.destroy); - delete this.timeouts.destroy; - return this.reload(); - } - if (this.nodes.container) { - $.queueTask((function(_this) { - return function() { - var iframe; - if (_this.nodes.container && d.activeElement === _this.nodes.counter && (iframe = $('iframe', _this.nodes.container))) { - iframe.focus(); - return QR.focus(); - } - }; - })(this)); - 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 - }); - if (this.noscript) { - return this.setupNoscript(); - } else { - return this.setupJS(); - } - }, - setupNoscript: function() { - var div, iframe, textarea; - iframe = $.el('iframe', { - id: 'qr-captcha-iframe', - src: this.noscriptURL() - }); - div = $.el('div'); - textarea = $.el('textarea'); - $.add(div, textarea); - return $.add(this.nodes.container, [iframe, div]); - }, - setupJS: function() { - return $.global(function() { - var cbNative, render; - render = function() { - var classList, container; - classList = document.documentElement.classList; - container = document.querySelector('#qr .captcha-container'); - return container.dataset.widgetID = window.grecaptcha.render(container, { - sitekey: '6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc', - theme: classList.contains('tomorrow') || classList.contains('dark-captcha') ? 'dark' : 'light', - callback: function(response) { - return window.dispatchEvent(new CustomEvent('captcha:success', { - detail: response - })); - } - }); - }; - if (window.grecaptcha) { - return render(); - } else { - cbNative = window.onRecaptchaLoaded; - return window.onRecaptchaLoaded = function() { - render(); - return cbNative(); - }; - } - }); - }, - afterSetup: function(mutations) { - var iframe, k, len1, len2, mutation, node, q, ref, textarea; - for (k = 0, len1 = mutations.length; k < len1; k++) { - mutation = mutations[k]; - ref = mutation.addedNodes; - for (q = 0, len2 = ref.length; q < len2; q++) { - node = ref[q]; - 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) { - if (!doc.contains(iframe)) { - return; - } - Captcha.replace.iframe(iframe); - $.addClass(QR.nodes.el, 'captcha-open'); - this.fixQRPosition(); - $.on(iframe, 'load', this.fixQRPosition); - if (d.activeElement === this.nodes.counter) { - iframe.focus(); - } - return $.global(function() { - var f; - f = document.querySelector('#qr iframe'); - return f.focus = f.blur = function() {}; - }); - }, - fixQRPosition: function() { - if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) { - QR.nodes.el.style.top = null; - return QR.nodes.el.style.bottom = '0px'; - } - }, - setupTextArea: function(textarea) { - return $.one(textarea, 'input', (function(_this) { - return function() { - return _this.save(true); - }; - })(this)); - }, - destroy: function() { - var garbage, i, ins, node, ref; - if (!this.isEnabled) { - return; - } - delete this.timeouts.destroy; - $.rmClass(QR.nodes.el, 'captcha-open'); - if (this.nodes.container) { - $.rm(this.nodes.container); - } - delete this.nodes.container; - garbage = $.X('//iframe[starts-with(@src, "https://www.google.com/recaptcha/api2/frame")]/ancestor-or-self::*[parent::body]'); - i = 0; - while (node = garbage.snapshotItem(i++)) { - if (((ref = (ins = node.nextSibling)) != null ? ref.nodeName : void 0) === 'INS') { - $.rm(ins); - } - $.rm(node); - } - }, - 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; - } else { - return null; - } - }, - save: function(pasted, token) { - var base1, focus, ref; - $.forceSync('captchas'); - this.captchas.push({ - response: token || $('textarea', this.nodes.container).value, - timeout: Date.now() + this.lifetime - }); - this.captchas.sort(function(a, b) { - return a.timeout - b.timeout; - }); - $.set('captchas', this.captchas); - this.count(); - focus = ((ref = d.activeElement) != null ? ref.nodeName : void 0) === 'IFRAME' && /https?:\/\/www\.google\.com\/recaptcha\//.test(d.activeElement.src); - if (this.needed()) { - if (focus) { - if (QR.cooldown.auto || Conf['Post on Captcha Completion']) { - this.nodes.counter.focus(); - } else { - QR.nodes.status.focus(); - } - } - this.reload(); - } else { - if (pasted) { - this.destroy(); - } else { - if ((base1 = this.timeouts).destroy == null) { - base1.destroy = setTimeout(this.destroy.bind(this), 3 * $.SECOND); - } - } - if (focus) { - QR.nodes.status.focus(); - } - } - if (Conf['Post on Captcha Completion'] && !QR.cooldown.auto) { - return QR.submit(); - } - }, - clear: function() { - var captcha, i, k, len1, now, ref; - if (!this.captchas.length) { - return; - } - $.forceSync('captchas'); - now = Date.now(); - ref = this.captchas; - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - 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(d.activeElement === QR.nodes.status); - }, - 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() { - if ($('iframe[src^="https://www.google.com/recaptcha/api/fallback?"]', this.nodes.container)) { - this.destroy(); - return this.setup(false, true); - } else { - return $.global(function() { - var container; - container = document.querySelector('#qr .captcha-container'); - return window.grecaptcha.reset(container.dataset.widgetID); - }); - } - } - }; - - PassLink = { - init: function() { - if (!Conf['Pass Link']) { - return; - } - return Main.ready(this.ready); - }, - ready: function() { - var passLink, styleSelector; - if (!(styleSelector = $.id('styleSelector'))) { - return; - } - passLink = $.el('span', { - className: 'brackets-wrap pass-link-container' - }); - $.extend(passLink, { - innerHTML: "4chan Pass" - }); - $.on(passLink.firstElementChild, 'click', function() { - return window.open('//sys.4chan.org/auth', Date.now(), 'width=500,height=280,toolbar=0'); - }); - return $.before(styleSelector.previousSibling, [passLink, $.tn('\u00A0\u00A0')]); - } - }; - - PostSuccessful = { - init: function() { - if (!Conf['Remember Your Posts']) { - return; - } - return $.ready(this.ready); - }, - ready: function() { - var _, db, postID, ref, threadID; - if (d.title !== 'Post successful!') { - return; - } - ref = $('h1').nextSibling.textContent.match(/thread:(\d+),no:(\d+)/), _ = ref[0], threadID = ref[1], postID = ref[2]; - postID = +postID; - threadID = +threadID || postID; - db = new DataBoard('yourPosts'); - return db.set({ - boardID: g.BOARD.ID, - threadID: threadID, - postID: postID, - val: true - }); - } - }; - - QR.cooldown = { - seconds: 0, - delays: { - thread: 0, - reply: 0, - image: 0, - reply_intra: 0, - image_intra: 0, - deletion: 60, - thread_global: 300 - }, - init: function() { - if (!Conf['Quick Reply']) { - return; - } - this.data = Conf['cooldowns']; - return $.sync('cooldowns', this.sync); - }, - setup: function() { - var delay, m, ref, type; - if (m = Get.scriptData().match(/\bcooldowns *= *({[^}]+})/)) { - $.extend(QR.cooldown.delays, JSON.parse(m[1])); - } - QR.cooldown.maxDelay = 0; - ref = QR.cooldown.delays; - for (type in ref) { - delay = ref[type]; - if (type !== 'thread' && type !== 'thread_global') { - QR.cooldown.maxDelay = Math.max(QR.cooldown.maxDelay, delay); - } - } - QR.cooldown.isSetup = true; - return QR.cooldown.start(); - }, - start: function() { - var data; - data = QR.cooldown.data; - if (!(Conf['Cooldown'] && QR.cooldown.isSetup && !QR.cooldown.isCounting && Object.keys(data[g.BOARD.ID] || {}).length + Object.keys(data.global || {}).length > 0)) { - return; - } - QR.cooldown.isCounting = true; - return QR.cooldown.count(); - }, - sync: function(data) { - QR.cooldown.data = data || {}; - return QR.cooldown.start(); - }, - add: function(threadID, postID) { - var boardID, start; - if (!Conf['Cooldown']) { - return; - } - start = Date.now(); - boardID = g.BOARD.ID; - QR.cooldown.set(boardID, 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(g.BOARD.ID, Date.now(), cooldown); - return QR.cooldown.start(); - }, - addMute: function(delay) { - if (!Conf['Cooldown']) { - return; - } - QR.cooldown.set(g.BOARD.ID, Date.now(), { - type: 'mute', - delay: delay - }); - return QR.cooldown.start(); - }, - "delete": function(post) { - var base1, cooldown, cooldowns, id, name1; - if (!QR.cooldown.data) { - return; - } - $.forceSync('cooldowns'); - cooldowns = ((base1 = QR.cooldown.data)[name1 = post.board.ID] || (base1[name1] = {})); - for (id in cooldowns) { - cooldown = cooldowns[id]; - if ((cooldown.delay == null) && cooldown.threadID === post.thread.ID && cooldown.postID === post.ID) { - delete cooldowns[id]; - } - } - return QR.cooldown.save([post.board.ID]); - }, - secondsDeletion: function(post) { - var cooldown, cooldowns, seconds, start; - if (!(QR.cooldown.data && Conf['Cooldown'])) { - return 0; - } - cooldowns = QR.cooldown.data[post.board.ID] || {}; - for (start in cooldowns) { - cooldown = cooldowns[start]; - if ((cooldown.delay == null) && cooldown.threadID === post.thread.ID && cooldown.postID === post.ID) { - seconds = QR.cooldown.delays.deletion - Math.floor((Date.now() - start) / $.SECOND); - return Math.max(seconds, 0); - } - } - return 0; - }, - 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) { - var base1, cooldowns; - $.forceSync('cooldowns'); - cooldowns = ((base1 = QR.cooldown.data)[scope] || (base1[scope] = {})); - cooldowns[id] = value; - return $.set('cooldowns', QR.cooldown.data); - }, - save: function(scopes) { - var data, k, len1, scope; - data = QR.cooldown.data; - for (k = 0, len1 = scopes.length; k < len1; k++) { - scope = scopes[k]; - if (scope in data && !Object.keys(data[scope]).length) { - delete data[scope]; - } - } - return $.set('cooldowns', data); - }, - count: function() { - var base1, cooldown, cooldowns, elapsed, k, len1, maxDelay, nCooldowns, now, ref, ref1, save, scope, seconds, start, suffix, threadID, type, update; - $.forceSync('cooldowns'); - save = []; - nCooldowns = 0; - now = Date.now(); - ref = QR.cooldown.categorize(QR.posts[0]), type = ref.type, threadID = ref.threadID; - seconds = 0; - if (Conf['Cooldown']) { - ref1 = [g.BOARD.ID, 'global']; - for (k = 0, len1 = ref1.length; k < len1; k++) { - scope = ref1[k]; - cooldowns = ((base1 = QR.cooldown.data)[scope] || (base1[scope] = {})); - for (start in cooldowns) { - cooldown = cooldowns[start]; - start = +start; - elapsed = Math.floor((now - start) / $.SECOND); - if (elapsed < 0) { - delete cooldowns[start]; - save.push(scope); - continue; - } - if (cooldown.delay != null) { - if (cooldown.delay <= elapsed) { - delete cooldowns[start]; - save.push(scope); - } else if ((cooldown.type === type && cooldown.threadID === threadID) || cooldown.type === 'mute') { - 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 (QR.cooldown.customCooldown) { - maxDelay = Math.max(maxDelay, parseInt(Conf['customCooldown'], 10)); - } - if (maxDelay <= elapsed) { - delete cooldowns[start]; - save.push(scope); - 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 (QR.cooldown.customCooldown) { - seconds = Math.max(seconds, parseInt(Conf['customCooldown'], 10) - elapsed); - } - } - nCooldowns += Object.keys(cooldowns).length; - } - } - if (save.length) { - QR.cooldown.save(save); - } - if (nCooldowns) { - 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.oekaki = { - menu: { - init: function() { - var a, ref; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Menu'] && Conf['Edit Link'] && Conf['Quick Reply'])) { - return; - } - a = $.el('a', { - className: 'edit-link', - href: 'javascript:;', - textContent: 'Edit image' - }); - $.on(a, 'click', this.editFile); - return Menu.menu.addEntry({ - el: a, - order: 95, - open: function(post) { - var file; - QR.oekaki.menu.post = post; - file = post.file; - return QR.postingIsEnabled && !!file && (file.isImage || file.isVideo); - } - }); - }, - editFile: function() { - var currentTime, isVideo, post, ref; - post = QR.oekaki.menu.post; - QR.quote.call(post.nodes.post); - isVideo = post.file.isVideo; - currentTime = ((ref = post.file.fullImage) != null ? ref.currentTime : void 0) || 0; - return CrossOrigin.file(post.file.url, function(blob) { - var video; - if (!blob) { - return QR.error("Can't load file."); - } else if (isVideo) { - video = $.el('video'); - $.on(video, 'loadedmetadata', function() { - $.on(video, 'seeked', function() { - var canvas; - canvas = $.el('canvas', { - width: video.videoWidth, - height: video.videoHeight - }); - canvas.getContext('2d').drawImage(video, 0, 0); - return canvas.toBlob(function(snapshot) { - snapshot.name = post.file.name.replace(/\.\w+$/, '') + '.png'; - QR.handleFiles([snapshot]); - return QR.oekaki.edit(); - }); - }); - return video.currentTime = currentTime; - }); - return video.src = URL.createObjectURL(blob); - } else { - blob.name = post.file.name; - QR.handleFiles([blob]); - return QR.oekaki.edit(); - } - }); - } - }, - setup: function() { - return $.global(function() { - var FCX; - FCX = window.FCX; - FCX.oekakiCB = function() { - return window.Tegaki.flatten().toBlob(function(file) { - var source; - source = "oekaki-" + (Date.now()); - FCX.oekakiLatest = source; - return document.dispatchEvent(new CustomEvent('QRSetFile', { - bubbles: true, - detail: { - file: file, - name: FCX.oekakiName, - source: source - } - })); - }); - }; - if (window.Tegaki) { - return document.querySelector('#qr .oekaki').hidden = false; - } - }); - }, - load: function(cb) { - var n, onload, script, style; - if ($('script[src^="//s.4cdn.org/js/painter"]', d.head)) { - return cb(); - } else { - style = $.el('link', { - rel: 'stylesheet', - href: "//s.4cdn.org/css/painter." + (Date.now()) + ".css" - }); - script = $.el('script', { - src: "//s.4cdn.org/js/painter.min." + (Date.now()) + ".js" - }); - n = 0; - onload = function() { - if (++n === 2) { - return cb(); - } - }; - $.on(style, 'load', onload); - $.on(script, 'load', onload); - return $.add(d.head, [style, script]); - } - }, - draw: function() { - return $.global(function() { - var FCX, Tegaki; - Tegaki = window.Tegaki, FCX = window.FCX; - if (Tegaki.bg) { - Tegaki.destroy(); - } - FCX.oekakiName = 'tegaki.png'; - return Tegaki.open({ - onDone: FCX.oekakiCB, - onCancel: function() { - return Tegaki.bgColor = '#ffffff'; - }, - width: +document.querySelector('#qr [name=oekaki-width]').value, - height: +document.querySelector('#qr [name=oekaki-height]').value, - bgColor: document.querySelector('#qr [name=oekaki-bg]').checked ? document.querySelector('#qr [name=oekaki-bgcolor]').value : 'transparent' - }); - }); - }, - button: function() { - if (QR.selected.file) { - return QR.oekaki.edit(); - } else { - return QR.oekaki.toggle(); - } - }, - edit: function() { - return QR.oekaki.load(function() { - return $.global(function() { - var FCX, Tegaki, cb, error, name, source; - Tegaki = window.Tegaki, FCX = window.FCX; - name = document.getElementById('qr-filename').value.replace(/\.\w+$/, '') + '.png'; - source = document.getElementById('file-n-submit').dataset.source; - error = function(content) { - return document.dispatchEvent(new CustomEvent('CreateNotification', { - bubbles: true, - detail: { - type: 'warning', - content: content, - lifetime: 20 - } - })); - }; - cb = function(e) { - var file, isVideo; - document.removeEventListener('QRFile', cb, false); - if (!e.detail) { - return error('No file to edit.'); - } - if (!/^(image|video)\//.test(e.detail.type)) { - return error('Not an image.'); - } - isVideo = /^video\//.test(e.detail.type); - file = document.createElement(isVideo ? 'video' : 'img'); - file.addEventListener('error', function() { - return error('Could not open file.', false); - }); - file.addEventListener((isVideo ? 'loadeddata' : 'load'), function() { - if (Tegaki.bg) { - Tegaki.destroy(); - } - FCX.oekakiName = name; - Tegaki.open({ - onDone: FCX.oekakiCB, - onCancel: function() { - return Tegaki.bgColor = '#ffffff'; - }, - width: file.naturalWidth || file.videoWidth, - height: file.naturalHeight || file.videoHeight, - bgColor: 'transparent' - }); - return Tegaki.activeCtx.drawImage(file, 0, 0); - }, false); - return file.src = URL.createObjectURL(e.detail); - }; - if (Tegaki.bg && Tegaki.onDoneCb === FCX.oekakiCB && source === FCX.oekakiLatest) { - FCX.oekakiName = name; - return Tegaki.resume(); - } else { - document.addEventListener('QRFile', cb, false); - return document.dispatchEvent(new CustomEvent('QRGetFile', { - bubbles: true - })); - } - }); - }); - }, - toggle: function() { - return QR.oekaki.load(function() { - return QR.nodes.oekaki.hidden = !QR.nodes.oekaki.hidden; - }); - } - }; - - QR.persona = { - pwd: '', - always: {}, - init: function() { - QR.persona.getPassword(); - return $.get('QR.personas', Conf['QR.personas'], function(arg) { - var arr, item, k, len1, personas, ref, type, types; - personas = arg['QR.personas']; - types = { - name: [], - email: [], - sub: [] - }; - ref = personas.split('\n'); - for (k = 0, len1 = ref.length; k < len1; k++) { - item = ref[k]; - 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, ref, ref1, ref2, type, val; - 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 k, len1, list, val; - list = $("#list-" + type, QR.nodes.el); - for (k = 0, len1 = arr.length; k < len1; k++) { - val = arr[k]; - 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 - }; - return $.set('QR.persona', persona); - }); - } - }; - - QR.post = (function() { - function _Class(select) { - this.select = bind(this.select, this); - var el, event, k, label, len1, len2, prev, q, ref, ref1; - el = $.el('a', { - className: 'qr-preview', - draggable: true, - href: 'javascript:;' - }); - $.extend(el, { - innerHTML: "" - }); - this.nodes = { - el: el, - rm: el.firstChild, - spoiler: $('.qr-preview-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.spoiler, 'change', (function(_this) { - return function(e) { - _this.spoiler = e.target.checked; - if (_this === QR.selected) { - return QR.nodes.spoiler.checked = _this.spoiler; - } - }; - })(this)); - ref = $$('label', el); - for (k = 0, len1 = ref.length; k < len1; k++) { - label = ref[k]; - $.on(label, 'click', function(e) { - return e.stopPropagation(); - }); - } - $.add(QR.nodes.dumpList, el); - ref1 = ['dragStart', 'dragEnter', 'dragLeave', 'dragOver', 'dragEnd', 'drop']; - for (q = 0, len2 = ref1.length; q < len2; q++) { - event = ref1[q]; - $.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 : ''; - _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); - URL.revokeObjectURL(this.URL); - return this.dismissErrors(); - }; - - _Class.prototype.lock = function(lock) { - var k, len1, name, node, ref; - if (lock == null) { - lock = true; - } - this.isLocked = lock; - if (this !== QR.selected) { - return; - } - ref = ['thread', 'name', 'email', 'sub', 'com', 'fileButton', 'filename', 'spoiler']; - for (k = 0, len1 = ref.length; k < len1; k++) { - name = ref[k]; - if (node = QR.nodes[name]) { - node.disabled = lock; - } - } - this.nodes.rm.style.visibility = lock ? 'hidden' : ''; - 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.removeAttribute('id'); - 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 k, len1, name, node, ref; - ref = ['thread', 'name', 'email', 'sub', 'com', 'filename']; - for (k = 0, len1 = ref.length; k < len1; k++) { - name = ref[k]; - if (!(node = QR.nodes[name])) { - continue; - } - node.value = this[name] || node.dataset["default"] || ''; - } - (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.updateComment(); - 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.saveFilename(); - return this.updateFilename(); - case 'name': - return QR.persona.set(this); - } - }; - - _Class.prototype.forceSave = function() { - var k, len1, name, node, ref; - if (this !== QR.selected) { - return; - } - ref = ['thread', 'name', 'email', 'sub', 'com', 'filename', 'spoiler']; - for (k = 0, len1 = ref.length; k < len1; k++) { - name = ref[k]; - if (!(node = QR.nodes[name])) { - continue; - } - this.save(node); - } - }; - - _Class.prototype.setComment = function(com) { - this.com = com || null; - if (this === QR.selected) { - QR.nodes.com.value = this.com; - } - return this.updateComment(); - }; - - _Class.prototype.updateComment = function() { - if (this === QR.selected) { - QR.characterCount(); - } - this.nodes.span.textContent = this.com; - return $.queueTask(function() { - return QR.captcha.onPostChange(); - }); - }; - - _Class.rmErrored = function(e) { - var error, errors, k, len1, post, q, ref; - e.stopPropagation(); - ref = QR.posts; - for (k = ref.length - 1; k >= 0; k += -1) { - post = ref[k]; - if (errors = post.errors) { - for (q = 0, len1 = errors.length; q < len1; q++) { - error = errors[q]; - if (!(doc.contains(error))) { - continue; - } - post.rm(); - break; - } - } - } - }; - - _Class.prototype.error = function(className, message) { - var div, ref, rm, rmAll; - div = $.el('div', { - className: className - }); - $.extend(div, { - innerHTML: E(message) + "
[delete] [delete all]" - }); - (this.errors || (this.errors = [])).push(div); - ref = $$('a', div), rm = ref[0], rmAll = ref[1]; - $.on(div, 'click', (function(_this) { - return function() { - if (indexOf.call(QR.posts, _this) >= 0) { - return _this.select(); - } - }; - })(this)); - $.on(rm, 'click', (function(_this) { - return function(e) { - e.stopPropagation(); - if (indexOf.call(QR.posts, _this) >= 0) { - return _this.rm(); - } - }; - })(this)); - $.on(rmAll, 'click', QR.post.rmErrored); - return QR.error(div, true); - }; - - _Class.prototype.fileError = function(message) { - return this.error('file-error', this.filename + ": " + message); - }; - - _Class.prototype.dismissErrors = function(test) { - var error, k, len1, ref; - if (test == null) { - test = function() { - return true; - }; - } - if (this.errors) { - ref = this.errors; - for (k = 0, len1 = ref.length; k < len1; k++) { - error = ref[k]; - if (doc.contains(error) && test(error)) { - error.parentNode.previousElementSibling.click(); - } - } - } - }; - - _Class.prototype.setFile = function(file1) { - var ext, ref; - this.file = file1; - if (Conf['Randomize Filename'] && g.BOARD.ID !== 'f') { - this.filename = "" + (Date.now() - Math.floor(Math.random() * 365 * $.DAY)); - if (ext = this.file.name.match(QR.validExtension)) { - this.filename += ext[0]; - } - } else { - this.filename = this.file.name; - } - this.filesize = $.bytesToString(this.file.size); - this.checkSize(); - $.addClass(this.nodes.el, 'has-file'); - $.queueTask(function() { - return QR.captcha.onPostChange(); - }); - URL.revokeObjectURL(this.URL); - this.saveFilename(); - if (this === QR.selected) { - this.showFileData(); - } else { - this.updateFilename(); - } - this.nodes.el.style.backgroundImage = null; - if (ref = this.file.type, indexOf.call(QR.mimeTypes, ref) < 0) { - return this.fileError('Unsupported file type.'); - } else if (/^(image|video)\//.test(this.file.type)) { - return this.readFile(); - } - }; - - _Class.prototype.checkSize = function() { - var max; - max = QR.max_size; - if (/^video\//.test(this.file.type)) { - max = Math.min(max, QR.max_size_video); - } - if (this.file.size > max) { - return this.fileError("File too large (file: " + this.filesize + ", max: " + ($.bytesToString(max)) + ")."); - } - }; - - _Class.prototype.readFile = function() { - var el, event, isVideo, onerror, onload; - isVideo = /^video\//.test(this.file.type); - el = $.el(isVideo ? 'video' : 'img'); - if (isVideo && !el.canPlayType(this.file.type)) { - return; - } - event = isVideo ? 'loadeddata' : 'load'; - onload = (function(_this) { - return function() { - $.off(el, event, onload); - $.off(el, 'error', onerror); - _this.checkDimensions(el); - return _this.setThumbnail(el); - }; - })(this); - onerror = (function(_this) { - return function() { - $.off(el, event, onload); - $.off(el, 'error', onerror); - _this.fileError((isVideo ? 'Video' : 'Image') + " appears corrupt"); - return URL.revokeObjectURL(el.src); - }; - })(this); - $.on(el, event, onload); - $.on(el, 'error', onerror); - return el.src = URL.createObjectURL(this.file); - }; - - _Class.prototype.checkDimensions = function(el) { - var duration, height, max_height, max_width, ref, videoHeight, videoWidth, width; - if (el.tagName === 'IMG') { - height = el.height, width = el.width; - if (height > QR.max_height || width > QR.max_width) { - this.fileError("Image too large (image: " + height + "x" + width + "px, max: " + QR.max_height + "x" + QR.max_width + "px)"); - } - if (height < QR.min_height || width < QR.min_width) { - return this.fileError("Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); - } - } else { - videoHeight = el.videoHeight, videoWidth = el.videoWidth, duration = el.duration; - max_height = Math.min(QR.max_height, QR.max_height_video); - max_width = Math.min(QR.max_width, QR.max_width_video); - if (videoHeight > max_height || videoWidth > max_width) { - this.fileError("Video too large (video: " + videoHeight + "x" + videoWidth + "px, max: " + max_height + "x" + max_width + "px)"); - } - if (videoHeight < QR.min_height || videoWidth < QR.min_width) { - this.fileError("Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); - } - if (!isFinite(duration)) { - this.fileError('Video lacks duration metadata (try remuxing)'); - } else if (duration > QR.max_duration_video) { - this.fileError("Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)"); - } - if (((ref = g.BOARD.ID) !== 'gif' && ref !== 'wsg') && $.hasAudio(el)) { - return this.fileError('Audio not allowed'); - } - } - }; - - _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.removeAttribute('title'); - QR.nodes.filename.removeAttribute('title'); - this.nodes.el.style.backgroundImage = null; - $.rmClass(this.nodes.el, 'has-file'); - this.showFileData(); - URL.revokeObjectURL(this.URL); - return this.dismissErrors(function(error) { - return $.hasClass(error, 'file-error'); - }); - }; - - _Class.prototype.saveFilename = function() { - this.file.newName = (this.filename || '').replace(/[\/\\]/g, '-'); - if (!QR.validExtension.test(this.filename)) { - return this.file.newName += "." + (QR.extensionFromType[this.file.type] || 'jpg'); - } - }; - - _Class.prototype.updateFilename = function() { - var long; - long = this.filename + " (" + this.filesize + ")"; - this.nodes.el.title = long; - if (this !== QR.selected) { - return; - } - return QR.nodes.filename.title = long; - }; - - _Class.prototype.showFileData = function() { - var ref; - if (this.file) { - this.updateFilename(); - QR.nodes.filename.value = this.filename; - $.addClass(QR.nodes.oekaki, 'has-file'); - $.addClass(QR.nodes.fileSubmit, 'has-file'); - } else { - $.rmClass(QR.nodes.oekaki, 'has-file'); - $.rmClass(QR.nodes.fileSubmit, 'has-file'); - } - if (((ref = this.file) != null ? ref.source : void 0) != null) { - QR.nodes.fileSubmit.dataset.source = this.file.source; - } else { - QR.nodes.fileSubmit.removeAttribute('data-source'); - } - return QR.nodes.spoiler.checked = this.spoiler; - }; - - _Class.prototype.pasteText = function(file) { - var reader; - this.pasting = true; - reader = new FileReader(); - reader.onload = (function(_this) { - return function(e) { - var result; - result = e.target.result; - _this.setComment((_this.com ? _this.com + "\n" + result : result)); - return delete _this.pasting; - }; - })(this); - return reader.readAsText(file); - }; - - _Class.prototype.dragStart = function(e) { - var left, ref, top; - ref = this.getBoundingClientRect(), left = ref.left, top = ref.top; - e.dataTransfer.setDragImage(this, e.clientX - left, e.clientY - top); - 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, k, lc, len1, ref, ref1, type; - if (!((Conf['Fappe Tyme'] || Conf['Werk Tyme']) && ((ref = g.VIEW) === 'index' || ref === 'thread'))) { - return; - } - this.nodes = {}; - this.enabled = { - fappe: false, - werk: Conf['werk'] - }; - ref1 = ["Fappe", "Werk"]; - for (k = 0, len1 = ref1.length; k < len1; k++) { - type = ref1[k]; - 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() { - return this.nodes.root.classList.toggle('noFile', !this.file); - }, - 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() { - var ref; - if (!((ref = this.file) != null ? ref.thumb : void 0)) { - 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, k, key, len1, len2, menuButton, nodes, post, q, ref, ref1, ref2, ref3, thumb, value; - cb = Gallery.cb; - 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: "
" - }); - 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'); - $.on(nodes.frame, 'click', cb.blank); - if (Conf['Mouse Wheel Volume']) { - $.on(nodes.frame, 'wheel', Volume.wheel); - } - $.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 (k = 0, len1 = ref1.length; k < len1; k++) { - entry = ref1[k]; - entry.order = 0; - nodes.menu.addEntry(entry); - } - $.on(d, 'keydown', cb.keybinds); - if (Conf['Keybinds']) { - $.off(d, 'keydown', Keybinds.keydown); - } - $.on(window, 'resize', Gallery.cb.setHeight); - ref2 = $$('.post .file'); - for (q = 0, len2 = ref2.length; q < len2; q++) { - file = ref2[q]; - post = Get.postFromNode(file); - if (!((ref3 = post.file) != null ? ref3.thumb : void 0)) { - 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.thumb && (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); - }, - load: function(thumb, errorCB) { - var elType, ext, file; - ext = thumb.href.match(/\w*$/); - elType = { - 'webm': 'video', - 'pdf': 'iframe' - }[ext] || 'img'; - file = $.el(elType, { - title: thumb.title - }); - $.extend(file.dataset, thumb.dataset); - $.on(file, 'error', errorCB); - file.src = thumb.href; - return file; - }, - open: function(thumb) { - var el, file, newID, nodes, oldID, post, ref; - nodes = Gallery.nodes; - oldID = +nodes.current.dataset.id; - newID = +thumb.dataset.id; - if (el = Gallery.images[oldID]) { - $.rmClass(el, 'gal-highlight'); - } - $.addClass(thumb, 'gal-highlight'); - nodes.thumbs.scrollTop = thumb.offsetTop + thumb.offsetHeight / 2 - nodes.thumbs.clientHeight / 2; - if (((ref = Gallery.cache) != null ? ref.dataset.id : void 0) === '' + newID) { - file = Gallery.cache; - $.off(file, 'error', Gallery.cacheError); - $.on(file, 'error', Gallery.error); - } else { - file = Gallery.load(thumb, Gallery.error); - } - $.off(nodes.current, 'error', Gallery.error); - ImageCommon.pause(nodes.current); - $.replace(nodes.current, file); - nodes.current = file; - if (file.nodeName === 'VIDEO') { - file.loop = true; - Volume.setup(file); - if (Conf['Autoplay']) { - file.play(); - } - if (Conf['Show Controls']) { - ImageCommon.addControls(file); - } - } - doc.classList.toggle('gal-pdf', file.nodeName === 'IFRAME'); - Gallery.cb.setHeight(); - nodes.count.textContent = +thumb.dataset.id + 1; - nodes.name.download = nodes.name.textContent = thumb.title; - nodes.name.href = thumb.href; - nodes.frame.scrollTop = 0; - nodes.next.focus(); - if (Gallery.slideshow && (newID > oldID || (oldID === Gallery.images.length - 1 && newID === 0))) { - Gallery.setupTimer(); - } else { - Gallery.cb.stop(); - } - if (Conf['Scroll to Post'] && (post = g.posts[file.dataset.post])) { - Header.scrollTo(post.nodes.root); - } - if (isNaN(oldID) || newID === (oldID + 1) % Gallery.images.length) { - return Gallery.cache = Gallery.load(Gallery.images[(newID + 1) % Gallery.images.length], Gallery.cacheError); - } - }, - 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)); - }, - cacheError: function() { - return delete Gallery.cache; - }, - 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 (!Conf['Autoplay'] && 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); - } - $.off(window, 'resize', Gallery.cb.setHeight); - return clearTimeout(Gallery.timeoutID); - }, - setFitness: function() { - return (this.checked ? $.addClass : $.rmClass)(doc, "gal-" + (this.name.toLowerCase().replace(/\s+/g, '-'))); - }, - setHeight: $.debounce(100, function() { - var current, dim, frame, height, minHeight, ref, ref1, ref2, style, width; - ref = Gallery.nodes, current = ref.current, frame = ref.frame; - style = current.style; - if (Conf['Stretch to Fit'] && (dim = (ref1 = g.posts[current.dataset.post]) != null ? ref1.file.dimensions : void 0)) { - ref2 = dim.split('x'), width = ref2[0], height = ref2[1]; - minHeight = Math.min(doc.clientHeight - 25, height / width * frame.clientWidth); - style.minHeight = minHeight + 'px'; - return style.minWidth = (width / height * minHeight) + 'px'; - } else { - return style.minHeight = style.minWidth = null; - } - }), - 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 === 'Hide Thumbnails' || name === 'Fit Width' || name === 'Fit Height') { - $.on(input, 'change', Gallery.cb.setFitness); - } - $.event('change', null, input); - $.on(input, 'change', $.cb.checked); - if (name === 'Hide Thumbnails' || name === 'Fit Width' || name === 'Fit Height' || name === 'Stretch to Fit') { - $.on(input, 'change', Gallery.cb.setHeight); - } - return { - el: label - }; - }, - createSubEntries: function() { - var delayInput, delayLabel, item, subEntries; - subEntries = (function() { - var k, len1, ref, results; - ref = ['Hide Thumbnails', 'Fit Width', 'Fit Height', 'Stretch to Fit', 'Scroll to Post']; - results = []; - for (k = 0, len1 = ref.length; k < len1; k++) { - item = ref[k]; - results.push(Gallery.menu.createSubEntry(item)); - } - return results; - })(); - delayLabel = $.el('label', { - innerHTML: "Slide Delay: " - }); - 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 k, len1, postObj, ref; - if (this.status === 404) { - post.kill(); - } - if (this.status !== 200) { - return redirect(); - } - ref = this.response.posts; - for (k = 0, len1 = ref.length; k < len1; k++) { - postObj = ref[k]; - 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 $.engine !== 'gecko' || (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: " contract" - }); - 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 (!Conf['Autoplay'] && ((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 k, len1, ref; - ref = [post].concat(slice.call(post.clones)); - for (k = 0, len1 = ref.length; k < len1; k++) { - post = ref[k]; - toggle(post); - } - }); - }, - playVideos: function() { - return g.posts.forEach(function(post) { - var file, k, len1, ref, video, visible; - ref = [post].concat(slice.call(post.clones)); - for (k = 0, len1 = ref.length; k < len1; k++) { - post = ref[k]; - 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, k, len1, oldHeight, ref, ref1, scrollY, top, x; - 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'); - $.rm(file.videoControls); - file.thumb.parentNode.href = file.url; - file.thumb.parentNode.target = '_blank'; - ref = ['isExpanding', 'isExpanded', 'videoControls', 'wasPlaying', 'scrollIntoView']; - for (k = 0, len1 = ref.length; k < len1; k++) { - x = ref[k]; - 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, ref, thumb; - 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 = Math.min(doc.clientHeight - file.fullImage.getBoundingClientRect().bottom - 25, Header.getBottomOf(file.fullImage)); - 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, ref, subEntries; - 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; - } - return $.on(this.file.thumb, 'mouseover', ImageHover.mouseover(this)); - }, - catalogNode: function() { - var file; - file = this.thread.OP.file; - if (!(file && (file.isImage || file.isVideo))) { - return; - } - return $.on(this.nodes.thumb, 'mouseover', ImageHover.mouseover(this.thread.OP)); - }, - mouseover: function(post) { - return function(e) { - var el, error, file, height, isVideo, left, maxHeight, maxWidth, ref, ref1, ref2, right, scale, width, x; - 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 k, len1, ref1, results; - ref1 = file.dimensions.split('x'); - results = []; - for (k = 0, len1 = ref1.length; k < len1; k++) { - x = ref1[k]; - results.push(+x); - } - return results; - })(), width = ref1[0], height = ref1[1]; - ref2 = this.getBoundingClientRect(), left = ref2.left, right = ref2.right; - maxWidth = Math.max(left, doc.clientWidth - right); - maxHeight = doc.clientHeight - UI.hover.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', - height: scale * height, - 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)); - }; - } - }; - - 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: " Prefetch Images" - }); - this.el = prefetch.firstElementChild; - $.on(this.el, 'change', this.toggle); - return Header.menu.addEntry({ - el: prefetch, - order: 98 - }); - }, - 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, k, len1, ref, thumb, video; - file = post.file; - thumb = file.thumb; - video = $.el('video', { - preload: 'none', - loop: true, - muted: true, - poster: thumb.src || thumb.dataset.src, - textContent: thumb.alt, - className: thumb.className - }); - video.setAttribute('muted', 'muted'); - video.dataset.md5 = thumb.dataset.md5; - ref = ['height', 'width', 'maxHeight', 'maxWidth']; - for (k = 0, len1 = ref.length; k < len1; k++) { - attr = ref[k]; - video.style[attr] = thumb.style[attr]; - } - video.src = file.url; - $.replace(thumb, video); - file.thumb = video; - return file.videoThumb = true; - }, - prefetch: function(post) { - var clone, el, file, isImage, isVideo, k, len1, match, ref, replace, thumb, type, url; - 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 || thumb.dataset.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 (k = 0, len1 = ref.length; k < len1; k++) { - clone = ref[k]; - clone.file.thumb.preload = 'auto'; - } - thumb.preload = 'auto'; - if ($.engine === 'gecko') { - $.on(thumb, 'loadeddata', function() { - return this.removeAttribute('poster'); - }); - } - return; - } - el = $.el(isImage ? 'img' : 'video'); - if (replace && isImage) { - $.on(el, 'load', function() { - var len2, q, ref1; - ref1 = post.clones; - for (q = 0, len2 = ref1.length; q < len2; q++) { - clone = ref1[q]; - clone.file.thumb.src = url; - } - thumb.src = url; - return thumb.removeAttribute('data-src'); - }); - } - 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 k, len1, ref1, ref2, thumb; - ref1 = [post].concat(slice.call(post.clones)); - for (k = 0, len1 = ref1.length; k < len1; k++) { - post = ref1[k]; - 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: "" - }); - $.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; - if (!(!this.isClone && this.file && this.file.thumb && this.file.isSpoiler)) { - return; - } - thumb = this.file.thumb; - thumb.removeAttribute('style'); - thumb.style.maxHeight = thumb.style.maxWidth = this.isReply ? '125px' : '250px'; - if (thumb.src) { - return thumb.src = this.file.thumbURL; - } else { - return thumb.dataset.src = this.file.thumbURL; - } - } - }; - - Sauce = { - init: function() { - var err, k, len1, link, links, ref, ref1; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Sauce'])) { - return; - } - links = []; - ref1 = Conf['sauces'].split('\n'); - for (k = 0, len1 = ref1.length; k < len1; k++) { - link = ref1[k]; - 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', - className: 'sauce' - }); - return Post.callbacks.push({ - name: 'Sauce', - cb: this.node - }); - }, - sandbox: function(url) { - return E.url({ - innerHTML: "[sb] " + E(url) + "" - }); - }, - rmOrigin: function(e) { - if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) { - return; - } - $.open(this.href); - return e.preventDefault(); - }, - createSauceLink: function(link, post) { - var a, ext, i, k, key, len1, m, part, parts, ref, ref1, ref2, skip, url; - if (!(link = link.trim())) { - return null; - } - parts = {}; - ref = link.split(/;(?=(?:text|boards|types|sandbox):?)/); - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - 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) || '?'); - ext = post.file.url.match(/[^.]*$/)[0]; - skip = false; - for (key in parts) { - parts[key] = parts[key].replace(/%(T?URL|IMG|[sh]?MD5|board|name|%|semi)/g, function(_, parameter) { - var type; - type = Sauce.formatters[parameter](post, ext); - if (type == null) { - skip = true; - return ''; - } - if (key === 'url' && (parameter !== '%' && parameter !== 'semi')) { - if (/^javascript:/i.test(parts['url'])) { - type = JSON.stringify(type); - } - type = encodeURIComponent(type); - } - return type; - }); - } - if (skip) { - return null; - } - if (!(!parts['boards'] || (ref2 = post.board.ID, indexOf.call(parts['boards'].split(','), ref2) >= 0))) { - return null; - } - if (!(!parts['types'] || indexOf.call(parts['types'].split(','), ext) >= 0)) { - return null; - } - url = parts['url']; - if (parts['sandbox'] != null) { - url = Sauce.sandbox(url); - } - a = Sauce.link.cloneNode(true); - a.href = url; - a.textContent = parts['text']; - if (/^javascript:/i.test(parts['url'])) { - a.removeAttribute('target'); - } - if (parts['sandbox'] != null) { - $.on(a, 'click', Sauce.rmOrigin); - } - return a; - }, - node: function() { - var k, len1, link, node, nodes, ref; - if (this.isClone || !this.file) { - return; - } - nodes = []; - ref = Sauce.links; - for (k = 0, len1 = ref.length; k < len1; k++) { - link = ref[k]; - if (node = Sauce.createSauceLink(link, this)) { - nodes.push($.tn('\u00A0'), node); - } - } - return $.add(this.file.text, nodes); - }, - formatters: { - TURL: function(post) { - return post.file.thumbURL; - }, - URL: function(post) { - return post.file.url; - }, - IMG: function(post, ext) { - if (ext === 'gif' || ext === 'jpg' || ext === 'png') { - return post.file.url; - } else { - return post.file.thumbURL; - } - }, - MD5: function(post) { - return post.file.MD5; - }, - sMD5: function(post) { - var ref; - return (ref = post.file.MD5) != null ? ref.replace(/[+\/=]/g, function(c) { - return { - '+': '-', - '/': '_', - '=': '' - }[c]; - }) : void 0; - }, - hMD5: function(post) { - if (post.file.MD5) { - return ((function() { - var k, len1, ref, results; - ref = atob(post.file.MD5); - results = []; - for (k = 0, len1 = ref.length; k < len1; k++) { - c = ref[k]; - results.push(("0" + (c.charCodeAt(0).toString(16))).slice(-2)); - } - return results; - })()).join(''); - } - }, - board: function(post) { - return post.board.ID; - }, - name: function(post) { - return post.file.name; - }, - '%': function() { - return '%'; - }, - semi: function() { - return ';'; - } - } - }; - - Volume = { - init: function() { - var ref, ref1, unmuteEntry, volumeEntry; - 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 (Conf['Mouse Wheel Volume']) { - Post.callbacks.push({ - name: 'Mouse Wheel Volume', - cb: this.node - }); - } - if ((ref1 = g.BOARD.ID) !== 'gif' && ref1 !== 'wsg') { - return; - } - if (Conf['Mouse Wheel Volume']) { - CatalogThread.callbacks.push({ - name: 'Mouse Wheel Volume', - cb: this.catalogNode - }); - } - 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: " 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, key, muted, val, volume; - muted = this.muted, volume = this.volume; - items = { - 'Allow Sound': !muted, - 'Default Volume': volume - }; - for (key in items) { - val = items[key]; - if (Conf[key] === val) { - delete items[key]; - } - } - $.set(items); - $.extend(Conf, items); - if (Volume.inputs) { - Volume.inputs.unmute.checked = !muted; - return Volume.inputs.volume.value = volume; - } - }, - node: function() { - var ref, ref1; - if (!(((ref = this.board.ID) === 'gif' || ref === 'wsg') && ((ref1 = this.file) != null ? ref1.isVideo : void 0))) { - return; - } - $.on(this.file.thumb, 'wheel', Volume.wheel.bind(Header.hover)); - return $.on($('a', this.file.text), 'wheel', Volume.wheel.bind(this.file.thumb.parentNode)); - }, - catalogNode: function() { - var file; - file = this.thread.OP.file; - if (!(file != null ? file.isVideo : void 0)) { - return; - } - return $.on(this.nodes.thumb, 'wheel', Volume.wheel.bind(Header.hover)); - }, - wheel: function(e) { - var el, volume; - if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) { - return; - } - if (!(el = $('video:not([data-md5])', this))) { - 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(); - } - }; - - Embedding = { - init: function() { - var k, len1, ref, type; - if (!(Conf['Embedding'] || Conf['Link Title'])) { - return; - } - this.types = {}; - ref = this.ordered_types; - for (k = 0, len1 = ref.length; k < len1; k++) { - type = ref[k]; - this.types[type.key] = type; - } - if (Conf['Floating Embeds']) { - this.dialog = UI.dialog('embedding', 'top: 50px; right: 0px;', { - innerHTML: "
→×
" - }); - this.media = $('#media-embed', this.dialog); - $.one(d, '4chanXInitFinished', this.ready); - } - if (Conf['Link Title']) { - return $.on(d, '4chanXInitFinished PostsInserted', function() { - var key, ref1, ref2, service; - 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, k, len1, match, ref, type; - href = link.href; - ref = Embedding.ordered_types; - for (k = 0, len1 = ref.length; k < len1; k++) { - type = ref[k]; - if (!(match = type.regExp.exec(href))) { - continue; - } - if (type.dummy) { - return; - } - return { - key: type.key, - uid: match[1], - options: match[2], - link: link - }; - } - }, - embed: function(data) { - var embed, href, key, link, name, options, post, ref, uid, value; - key = data.key, uid = data.uid, options = data.options, link = data.link, post = data.post; - href = link.href; - if (Embedding.types[key].httpOnly && location.protocol !== 'http:') { - return; - } - $.addClass(link, key.toLowerCase()); - embed = $.el('a', { - className: 'embedder', - href: 'javascript:;', - textContent: '(embed)' - }); - ref = { - key: key, - uid: uid, - options: options, - href: href - }; - for (name in ref) { - value = ref[name]; - embed.dataset[name] = value; - } - $.on(embed, 'click', Embedding.cb.toggle); - $.after(link, [$.tn(' '), embed]); - if (Conf['Auto-embed'] && !Conf['Floating Embeds'] && !post.isFetchedQuote && key !== 'TwitchTV') { - 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; - } - $.addClass(link, key.toLowerCase()); - 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) + "] Title Link Blocked (are you using NoScript?)" - }); - } - } - }, - flushTitles: function(service) { - var cb, data, k, len1, queue; - queue = service.queue; - if (!(queue != null ? queue.length : void 0)) { - return; - } - service.queue = []; - cb = function() { - var data, k, len1; - for (k = 0, len1 = queue.length; k < len1; k++) { - data = queue[k]; - Embedding.cb.title(this, data); - } - }; - if (!$.cache(service.api((function() { - var k, len1, results; - results = []; - for (k = 0, len1 = queue.length; k < len1; k++) { - data = queue[k]; - results.push(data.uid); - } - return results; - })()), cb, { - responseType: 'json' - })) { - for (k = 0, len1 = queue.length; k < len1; k++) { - data = queue[k]; - $.extend(data.link, { - innerHTML: "[" + E(data.key) + "] Title Link Blocked (are you using NoScript?)" - }); - } - } - }, - 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: none; width: 640px; height: 360px;'; - return container; - }, - title: function(req, data) { - var base1, k, key, len1, len2, link, link2, options, post, post2, q, ref, ref1, service, status, text, uid; - 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 (k = 0, len1 = ref.length; k < len1; k++) { - post2 = ref[k]; - ref1 = $$('a.linkify', post2.nodes.comment); - for (q = 0, len2 = ref1.length; q < len2; q++) { - link2 = ref1[q]; - if (!(link2.href === link.href)) { - continue; - } - if ((base1 = link2.dataset).original == null) { - base1.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.dataset.href - }); - } - }, { - key: 'Dailymotion', - regExp: /^\w+:\/\/(?:(?:www\.)?dailymotion\.com\/(?:embed\/)?video|dai\.ly)\/([A-Za-z0-9]+)[^?]*(.*)/, - el: function(a) { - var el, options, start; - options = (start = a.dataset.options.match(/[?&](start=\d+)/)) ? "?" + start[1] : ''; - el = $.el('iframe', { - src: "//www.dailymotion.com/embed/video/" + a.dataset.uid + options - }); - el.setAttribute("allowfullscreen", "true"); - return el; - }, - title: { - api: function(uid) { - return "https://api.dailymotion.com/video/" + uid; - }, - text: function(_) { - return _.title; - } - } - }, { - 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: "" + E(a.dataset.uid) + "" - }; - el.src = E.url(content); - 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: "" - }); - } - }, { - 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', { - src: "http://www.liveleak.com/ll_embed?i=" + a.dataset.uid - }); - el.setAttribute("allowfullscreen", "true"); - 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)?)/, - style: 'border: 0; width: 600px; height: 406px;', - el: function(a) { - return $.el('iframe', { - src: "//strawpoll.me/embed_1/" + a.dataset.uid - }); - } - }, { - key: 'TwitchTV', - regExp: /^\w+:\/\/(?:www\.)?twitch\.tv\/(\w[^#\&\?]*)/, - style: "border: none; width: 620px; height: 378px;", - el: function(a) { - var _, channel, flashvars, id, idprefix, k, len1, obj, part, ref, result, seconds, start, type; - if (result = /(\w+)\/([bcv])\/(\d+)/i.exec(a.dataset.uid)) { - _ = result[0], channel = result[1], type = result[2], id = result[3]; - idprefix = type === 'b' ? 'a' : type; - flashvars = "channel=" + channel + "&start_volume=25&auto_play=false&videoId=" + idprefix + id; - if (start = a.dataset.href.match(/\bt=(\w+)/)) { - seconds = 0; - ref = start[1].match(/\d+[hms]/g); - for (k = 0, len1 = ref.length; k < len1; k++) { - part = ref[k]; - seconds += +part.slice(0, -1) * { - 'h': 3600, - 'm': 60, - 's': 1 - }[part.slice(-1)]; - } - flashvars += "&initial_time=" + seconds; - } - } else { - channel = (/(\w+)/.exec(a.dataset.uid))[0]; - flashvars = "channel=" + channel + "&start_volume=25&auto_play=false"; - } - obj = $.el('object', { - data: '//www-cdn.jtvnw.net/swflibs/TwitchPlayer.swf' - }); - $.extend(obj, { - innerHTML: "" - }); - obj.children[1].value = flashvars; - return obj; - } - }, { - key: 'Vocaroo', - regExp: /^\w+:\/\/(?:www\.)?vocaroo\.com\/i\/(\w+)/, - style: '', - el: function(a) { - var el, type; - el = $.el('audio', { - controls: true, - preload: 'auto' - }); - type = el.canPlayType('audio/webm') ? 'webm' : 'mp3'; - el.src = "http://vocaroo.com/media_command.php?media=" + a.dataset.uid + "&command=download_" + type; - return el; - } - }, { - 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=https://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=|\bembed\/|\bv\/))([\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, k, len1, ref; - ref = data.items; - for (k = 0, len1 = ref.length; k < len1; k++) { - item = ref[k]; - if (item.id === uid) { - return item.snippet.title; - } - } - return 'Not Found'; - } - } - }, { - key: 'Loopvid', - regExp: /^\w+:\/\/(?:www\.)?loopvid.appspot.com\/#?((?:pf|kd|lv|gd|gh|db|dx|nn|cp|wu|ig|ky|mf|pc|gc)\/[\w\-\/]+(,[\w\-\/]+)*|fc\/\w+\/\d+)/, - style: 'max-width: 80vw; max-height: 80vh;', - el: function(a) { - var _, base, el, host, k, len1, len2, name, names, q, ref, ref1, type, types, url; - el = $.el('video', { - controls: true, - preload: 'auto', - loop: true - }); - ref = a.dataset.uid.match(/(\w+)\/(.*)/), _ = ref[0], host = ref[1], names = ref[2]; - types = (function() { - switch (host) { - case 'gd': - case 'wu': - case 'fc': - return ['']; - case 'gc': - return ['giant', 'fat', 'zippy']; - default: - return ['.webm', '.mp4']; - } - })(); - ref1 = names.split(','); - for (k = 0, len1 = ref1.length; k < len1; k++) { - name = ref1[k]; - for (q = 0, len2 = types.length; q < len2; q++) { - type = types[q]; - base = "" + name + type; - url = (function() { - switch (host) { - case 'pf': - return "https://web.archive.org/web/2/http://a.pomf.se/" + base; - case 'kd': - return "http://kastden.org/loopvid/" + base; - case 'lv': - return "http://kastden.org/_loopvid_media/lv/" + 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://dl.dropboxusercontent.com/u/" + base; - case 'dx': - return "https://dl.dropboxusercontent.com/" + base; - case 'nn': - return "http://naenara.eu/loopvids/" + base; - case 'cp': - return "https://copy.com/" + base; - case 'wu': - return "http://webmup.com/" + base + "/vid.webm"; - case 'ig': - return "https://i.imgur.com/" + base; - case 'ky': - return "https://kiyo.me/" + base; - case 'mf': - return "https://d.maxfile.ro/" + base; - case 'pc': - return "http://a.pomf.cat/" + base; - case 'fc': - return "//i.4cdn.org/" + base + ".webm"; - case 'gc': - return "https://" + type + ".gfycat.com/" + name + ".webm"; - } - })(); - $.add(el, $.el('source', { - src: url - })); - } - } - return el; - } - }, { - key: 'Clyp', - regExp: /^\w+:\/\/(?:www\.)?clyp\.it\/(\w+)/, - style: '', - el: function(a) { - var el, type; - el = $.el('audio', { - controls: true, - preload: 'auto' - }); - type = el.canPlayType('audio/ogg') ? 'ogg' : 'mp3'; - el.src = "https://clyp.it/" + a.dataset.uid + "." + type; - return el; - } - }, { - 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.dataset.href, - loop: /^https?:\/\/i\.4cdn\.org\//.test(a.dataset.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 k, len1, len2, link, links, q, ref; - if (this.isClone) { - return Embedding.events(this); - } - if (!Linkify.regString.test(this.info.comment)) { - return; - } - ref = $$('a[href^="http://i.4cdn.org/"], a[href^="https://i.4cdn.org/"]', this.nodes.comment); - for (k = 0, len1 = ref.length; k < len1; k++) { - link = ref[k]; - $.addClass(link, 'linkify'); - Embedding.process(link, this); - } - links = Linkify.process(this.nodes.comment); - for (q = 0, len2 = links.length; q < len2; q++) { - link = links[q]; - 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, part1, part2, ref, ref1, 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') { - if ((part1 = word.match(/(https?:\/\/)?([a-z\d-]+\.)*[a-z\d-]+$/i)) && (part2 = (ref = snapshot.snapshotItem(i)) != null ? (ref1 = ref.data) != null ? ref1.match(/^(\.[a-z\d-]+)*\//i) : void 0 : void 0) && (part1[0] + part2[0]).search(Linkify.regString) === 0) { - continue; - } else { - 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|xyz|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, encodedDomain, 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; - } - if (encodedDomain = text.match(/^(https?:\/\/[^\/]*%[0-9a-f]{2})(.*)$/i)) { - text = encodedDomain[1].replace(/%([0-9a-f]{2})/ig, function(x, y) { - if (y === '25') { - return x; - } else { - return String.fromCharCode(parseInt(y, 16)); - } - }) + encodedDomain[2]; - } - a = $.el('a', { - className: 'linkify', - rel: 'nofollow noreferrer', - target: '_blank', - href: text - }); - $.add(a, range.extractContents()); - range.insertNode(a); - return a; - } - }; - - ArchiveLink = { - init: function() { - var div, entry, k, len1, ref, ref1, type; - 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'], ['Capcode', 'capcode'], ['Subject', 'subject'], ['Filename', 'filename'], ['Image MD5', 'MD5']]; - for (k = 0, len1 = ref1.length; k < len1; k++) { - type = ref1[k]; - 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 = { - auto: [{}, {}], - 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:;' - }); - this.nodes = { - menu: div.firstChild, - links: [postEl, fileEl] - }; - postEntry = { - el: postEl, - open: function() { - postEl.textContent = DeleteLink.linkText(false); - $.on(postEl, 'click', DeleteLink.toggle); - return true; - } - }; - fileEntry = { - el: fileEl, - open: function(arg) { - var file; - file = arg.file; - if (!file || file.isDead) { - return false; - } - fileEl.textContent = DeleteLink.linkText(true); - $.on(fileEl, 'click', DeleteLink.toggle); - return true; - } - }; - return Menu.menu.addEntry({ - el: div, - order: 40, - open: function(post) { - if (post.isDead) { - return false; - } - DeleteLink.post = post; - DeleteLink.nodes.menu.textContent = DeleteLink.menuText(); - DeleteLink.cooldown.start(post); - return true; - }, - subEntries: [postEntry, fileEntry] - }); - }, - menuText: function() { - var seconds; - if (seconds = DeleteLink.cooldown.seconds[DeleteLink.post.fullID]) { - return "Delete (" + seconds + ")"; - } else { - return 'Delete'; - } - }, - linkText: function(fileOnly) { - var text; - text = fileOnly ? 'File' : 'Post'; - if (DeleteLink.auto[+fileOnly][DeleteLink.post.fullID]) { - text = "Deleting " + (text.toLowerCase()) + "..."; - } - return text; - }, - toggle: function() { - var auto, fileOnly, post; - post = DeleteLink.post; - fileOnly = $.hasClass(this, 'delete-file'); - auto = DeleteLink.auto[+fileOnly]; - if (auto[post.fullID]) { - delete auto[post.fullID]; - } else { - auto[post.fullID] = true; - } - this.textContent = DeleteLink.linkText(fileOnly); - if (!DeleteLink.cooldown.seconds[post.fullID]) { - return DeleteLink["delete"](post, fileOnly); - } - }, - "delete": function(post, fileOnly) { - var form, link; - link = DeleteLink.nodes.links[+fileOnly]; - delete DeleteLink.auto[+fileOnly][post.fullID]; - if (post.fullID === DeleteLink.post.fullID) { - $.off(link, 'click', DeleteLink.toggle); - } - form = { - mode: 'usrdel', - onlyimgdel: fileOnly, - pwd: QR.persona.getPassword() - }; - form[post.ID] = 'delete'; - 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, post); - } - }, { - form: $.formData(form) - }); - }, - load: function(link, post, fileOnly, resDoc) { - var el, msg; - link.textContent = DeleteLink.linkText(fileOnly); - if (resDoc.title === '4chan - Banned') { - el = $.el('span', { - innerHTML: "You can't delete posts because you are banned." - }); - return new Notice('warning', el, 20); - } else if (msg = resDoc.getElementById('errmsg')) { - new Notice('warning', msg.textContent, 20); - if (post.fullID === DeleteLink.post.fullID) { - $.on(link, 'click', DeleteLink.toggle); - } - if (QR.cooldown.data && Conf['Cooldown'] && /\bwait\b/i.test(msg.textContent)) { - DeleteLink.cooldown.start(post, 5); - DeleteLink.auto[+fileOnly][post.fullID] = true; - return DeleteLink.nodes.links[+fileOnly].textContent = DeleteLink.linkText(fileOnly); - } - } else { - if (!fileOnly) { - QR.cooldown["delete"](post); - } - if (resDoc.title === 'Updating index...') { - (post.origin || post).kill(fileOnly); - } - if (post.fullID === DeleteLink.post.fullID) { - return link.textContent = 'Deleted'; - } - } - }, - error: function(link, post) { - new Notice('warning', 'Connection error, please retry.', 20); - if (post.fullID === DeleteLink.post.fullID) { - return $.on(link, 'click', DeleteLink.toggle); - } - }, - cooldown: { - seconds: {}, - start: function(post, seconds) { - if (DeleteLink.cooldown.seconds[post.fullID] != null) { - return; - } - if (seconds == null) { - seconds = QR.cooldown.secondsDeletion(post); - } - if (seconds > 0) { - DeleteLink.cooldown.seconds[post.fullID] = seconds; - return DeleteLink.cooldown.count(post); - } - }, - count: function(post) { - var fileOnly, k, len1, ref; - if (post.fullID === DeleteLink.post.fullID) { - DeleteLink.nodes.menu.textContent = DeleteLink.menuText(); - } - if (DeleteLink.cooldown.seconds[post.fullID] > 0 && Conf['Cooldown']) { - DeleteLink.cooldown.seconds[post.fullID]--; - setTimeout(DeleteLink.cooldown.count, 1000, post); - } else { - delete DeleteLink.cooldown.seconds[post.fullID]; - ref = [false, true]; - for (k = 0, len1 = ref.length; k < len1; k++) { - fileOnly = ref[k]; - if (DeleteLink.auto[+fileOnly][post.fullID]) { - DeleteLink["delete"](post, fileOnly); - } - } - } - } - } - }; - - 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: "" - }); - 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:;' - }); - $.on(a, 'click', ReportLink.report); - return Menu.menu.addEntry({ - el: a, - order: 10, - open: function(post) { - if (!(post.isDead || (post.thread.isDead && !post.thread.isArchived))) { - a.textContent = 'Report'; - ReportLink.url = "//sys.4chan.org/" + post.board + "/imgboard.php?mode=report&no=" + post; - if ((Conf['Use Recaptcha v1 in Reports'] && Main.jsEnabled) || d.cookie.indexOf('pass_enabled=1') >= 0) { - ReportLink.url += '&altc=1'; - ReportLink.dims = 'width=350,height=275'; - } else { - ReportLink.dims = 'width=400,height=550'; - } - } else if (Conf['Archive Report']) { - a.textContent = 'Report to archive'; - ReportLink.url = Redirect.to('report', { - boardID: post.board.ID, - postID: post.ID - }); - ReportLink.dims = 'width=700,height=475'; - } else { - ReportLink.url = ''; - } - return !!ReportLink.url; - } - }); - }, - report: function() { - var dims, id, set, url; - url = ReportLink.url, dims = ReportLink.dims; - id = Date.now(); - set = "toolbar=0,scrollbars=1,location=0,status=1,menubar=0,resizable=1," + dims; - 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() { - MarkNewIPs.ipCount = this.ipCount; - MarkNewIPs.postCount = this.posts.keys.length; - return $.on(d, 'ThreadUpdate', MarkNewIPs.onUpdate); - }, - onUpdate: function(e) { - var deletedPosts, fullID, i, ipCount, k, len1, len2, newPosts, postCount, q, ref; - ref = e.detail, ipCount = ref.ipCount, postCount = ref.postCount, newPosts = ref.newPosts, deletedPosts = ref.deletedPosts; - if (ipCount == null) { - return; - } - switch (ipCount - MarkNewIPs.ipCount) { - case postCount - MarkNewIPs.postCount + deletedPosts.length: - i = MarkNewIPs.ipCount; - for (k = 0, len1 = newPosts.length; k < len1; k++) { - fullID = newPosts[k]; - MarkNewIPs.markNew(g.posts[fullID], ++i); - } - break; - case -deletedPosts.length: - for (q = 0, len2 = newPosts.length; q < len2; q++) { - fullID = newPosts[q]; - MarkNewIPs.markOld(g.posts[fullID]); - } - } - MarkNewIPs.ipCount = ipCount; - return MarkNewIPs.postCount = postCount; - }, - 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'); - } - }; - - ReplyPruning = { - init: function() { - var el, label; - if (!(g.VIEW === 'thread' && Conf['Reply Pruning'])) { - return; - } - this.active = !(Conf['Quote Threading'] && Conf['Thread Quotes']); - this.container = $.frag(); - this.summary = $.el('span', { - hidden: true, - className: 'summary' - }); - this.summary.style.cursor = 'pointer'; - $.on(this.summary, 'click', (function(_this) { - return function() { - _this.inputs.enabled.checked = !_this.inputs.enabled.checked; - return $.event('change', null, _this.inputs.enabled); - }; - })(this)); - label = UI.checkbox('Prune Replies', 'Show Last', this.active); - el = $.el('span', { - title: 'Maximum number of replies to show.' - }, { - innerHTML: " " - }); - $.prepend(el, label); - this.inputs = { - enabled: label.firstElementChild, - replies: el.lastElementChild - }; - $.on(this.inputs.enabled, 'change', this.setEnabled); - $.on(this.inputs.replies, 'change', $.cb.value); - Header.menu.addEntry({ - el: el, - order: 190 - }); - return Thread.callbacks.push({ - name: 'Reply Pruning', - cb: this.node - }); - }, - position: 0, - hidden: 0, - hiddenFiles: 0, - total: 0, - totalFiles: 0, - setEnabled: function() { - var other; - other = QuoteThreading.input; - if (this.checked && (other != null ? other.checked : void 0)) { - other.checked = false; - $.event('change', null, other); - } - return ReplyPruning.active = this.checked; - }, - showIfHidden: function(id) { - var ref; - if ((ref = ReplyPruning.container) != null ? ref.getElementById(id) : void 0) { - ReplyPruning.inputs.enabled.checked = false; - return $.event('change', null, ReplyPruning.inputs.enabled); - } - }, - node: function() { - var ref; - ReplyPruning.thread = this; - this.posts.forEach(function(post) { - if (post.isReply) { - ReplyPruning.total++; - if (post.file) { - return ReplyPruning.totalFiles++; - } - } - }); - if (ReplyPruning.active && /^#p\d+$/.test(location.hash) && (0 <= (ref = this.posts.keys.indexOf(location.hash.slice(2))) && ref < 1 + Math.max(ReplyPruning.total - +Conf["Max Replies"], 0))) { - ReplyPruning.active = ReplyPruning.inputs.enabled.checked = false; - } - $.after(this.OP.nodes.root, ReplyPruning.summary); - $.on(ReplyPruning.inputs.enabled, 'change', ReplyPruning.update); - $.on(ReplyPruning.inputs.replies, 'change', ReplyPruning.update); - $.on(d, 'ThreadUpdate', ReplyPruning.updateCount); - $.on(d, 'ThreadUpdate', ReplyPruning.update); - return ReplyPruning.update(); - }, - updateCount: function(e) { - var fullID, k, len1, ref; - if (e.detail[404]) { - return; - } - ref = e.detail.newPosts; - for (k = 0, len1 = ref.length; k < len1; k++) { - fullID = ref[k]; - ReplyPruning.total++; - if (g.posts[fullID].file) { - ReplyPruning.totalFiles++; - } - } - }, - update: function() { - var frag, hidden2, post, posts; - hidden2 = ReplyPruning.active ? Math.max(ReplyPruning.total - +Conf["Max Replies"], 0) : 0; - posts = ReplyPruning.thread.posts; - if (ReplyPruning.hidden < hidden2) { - while (ReplyPruning.hidden < hidden2 && ReplyPruning.position < posts.keys.length) { - post = posts[posts.keys[ReplyPruning.position++]]; - if (post.isReply && !post.isFetchedQuote) { - $.add(ReplyPruning.container, post.nodes.root); - ReplyPruning.hidden++; - if (post.file) { - ReplyPruning.hiddenFiles++; - } - } - } - } else if (ReplyPruning.hidden > hidden2) { - frag = $.frag(); - while (ReplyPruning.hidden > hidden2 && ReplyPruning.position > 0) { - post = posts[posts.keys[--ReplyPruning.position]]; - if (post.isReply && !post.isFetchedQuote) { - $.prepend(frag, post.nodes.root); - ReplyPruning.hidden--; - if (post.file) { - ReplyPruning.hiddenFiles--; - } - } - } - $.after(ReplyPruning.summary, frag); - $.event('PostsInserted'); - } - ReplyPruning.summary.textContent = ReplyPruning.active ? Build.summaryText('+', ReplyPruning.hidden, ReplyPruning.hiddenFiles) : Build.summaryText('-', ReplyPruning.total, ReplyPruning.totalFiles); - return ReplyPruning.summary.hidden = ReplyPruning.total <= +Conf["Max Replies"]; - } - }; - - 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: "? / ?" + (Conf["IP Count in Stats"] ? " / ?" : "") + (Conf["Page Count in Stats"] ? " / ?" : "") - }; - statsTitle = 'Posts / Files'; - if (Conf['IP Count in Stats']) { - statsTitle += ' / IPs'; - } - if (Conf['Page Count in Stats']) { - statsTitle += (g.BOARD.ID === 'f' ? ' / Purge Position' : ' / 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: "
" + statsHTML.innerHTML + "
" - }); - $.addClass(doc, 'float'); - $.ready(function() { - return $.add(d.body, sc); - }); - } - this.postCountEl = $('#post-count', sc); - this.fileCountEl = $('#file-count', sc); - this.ipCountEl = $('#ip-count', sc); - this.pageCountEl = $('#page-count', sc); - if (this.pageCountEl) { - $.on(this.pageCountEl, 'click', ThreadStats.fetchPage); - } - 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 (ThreadStats.pageCountEl) { - 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 (!ThreadStats.pageCountEl) { - return; - } - if (newPosts.length) { - ThreadStats.lastPost = g.posts[newPosts[newPosts.length - 1]].info.date; - } - if (g.BOARD.ID !== 'f' && ((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) && ipCountEl) { - ipCountEl.textContent = ipCount; - } - (thread.postLimit && !thread.isSticky ? $.addClass : $.rmClass)(postCountEl, 'warning'); - return (thread.fileLimit && !thread.isSticky ? $.addClass : $.rmClass)(fileCountEl, 'warning'); - }, - fetchPage: function() { - if (!ThreadStats.pageCountEl) { - 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: 'ThreadStats' - }); - }, - onThreadsLoad: function() { - var k, len1, len2, len3, page, purgePos, q, ref, ref1, ref2, thread, u; - if (this.status === 200) { - ref = this.response; - for (k = 0, len1 = ref.length; k < len1; k++) { - page = ref[k]; - if (g.BOARD.ID === 'f') { - purgePos = 1; - ref1 = page.threads; - for (q = 0, len2 = ref1.length; q < len2; q++) { - thread = ref1[q]; - if (thread.no < ThreadStats.thread.ID) { - purgePos++; - } - } - ThreadStats.pageCountEl.textContent = purgePos; - } else { - ref2 = page.threads; - for (u = 0, len3 = ref2.length; u < len3; u++) { - thread = ref2[u]; - 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); - ThreadStats.retry(); - return; - } - } - } - } else if (this.status === 304) { - return ThreadStats.retry(); - } - }, - retry: function() { - var ref; - if (g.BOARD.ID !== 'f' && ThreadStats.lastPost > ThreadStats.lastPageUpdate && ((ref = ThreadStats.pageCountEl) != null ? ref.textContent : void 0) !== '1') { - clearTimeout(ThreadStats.timeout); - return ThreadStats.timeout = setTimeout(ThreadStats.fetchPage, 5 * $.SECOND); - } - } - }; - - ThreadUpdater = { - init: function() { - var conf, el, input, name, ref, sc, subEntries, updateLink; - if (g.VIEW !== 'thread' || !Conf['Thread Updater']) { - return; - } - this.audio = $.el('audio', { - src: ThreadUpdater.beep - }); - if (Conf['Updater and Stats in Header']) { - this.dialog = sc = $.el('span', { - id: 'updater' - }); - $.extend(sc, { - innerHTML: "" - }); - $.ready(function() { - return Header.addShortcut(sc); - }); - } else { - this.dialog = sc = UI.dialog('updater', 'bottom: 0px; left: 0px;', { - innerHTML: "
" - }); - $.addClass(doc, 'float'); - $.ready(function() { - return $.add(d.body, sc); - }); - } - this.checkPostCount = 0; - this.timer = $('#update-timer', sc); - this.status = $('#update-status', sc); - $.on(this.timer, 'click', this.update); - $.on(this.status, 'click', this.update); - updateLink = $.el('span', { - className: 'brackets-wrap updatelink' - }); - $.extend(updateLink, { - innerHTML: "Update" - }); - Main.ready(function() { - var navLinksBot; - if ((navLinksBot = $('.navLinksBot'))) { - 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.setInterval); - } - subEntries.push({ - el: el - }); - } - this.settings = $.el('span', { - innerHTML: "Interval" - }); - $.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.outdateCount = 0; - ThreadUpdater.postIDs = []; - ThreadUpdater.fileIDs = []; - this.posts.forEach(function(post) { - ThreadUpdater.postIDs.push(post.ID); - if (post.file) { - return ThreadUpdater.fileIDs.push(post.ID); - } - }); - ThreadUpdater.cb.interval.call($.el('input', { - value: Conf['Interval'] - })); - $.on(d, 'QRPostSuccessful', ThreadUpdater.cb.checkpost); - $.on(d, 'visibilitychange', ThreadUpdater.cb.visibility); - return ThreadUpdater.setInterval(); - }, - - /* - 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', - playBeep: function() { - var audio; - audio = ThreadUpdater.audio; - if (audio.paused) { - return audio.play(); - } else { - return $.one(audio, 'ended', ThreadUpdater.playBeep); - } - }, - cb: { - checkpost: function(e) { - if (e.detail.threadID !== ThreadUpdater.thread.ID) { - return; - } - ThreadUpdater.postID = e.detail.postID; - ThreadUpdater.checkPostCount = 0; - ThreadUpdater.outdateCount = 0; - return ThreadUpdater.setInterval(); - }, - 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; - }; - }, - 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() { - var req; - req = ThreadUpdater.req; - switch (req.status) { - case 200: - ThreadUpdater.parse(req); - if (ThreadUpdater.thread.isArchived) { - return ThreadUpdater.kill(); - } else { - return ThreadUpdater.setInterval(); - } - break; - case 404: - return $.ajax("//a.4cdn.org/" + ThreadUpdater.thread.board + "/catalog.json", { - onloadend: function() { - var confirmed, k, len1, len2, page, q, ref, ref1, thread; - if (this.status === 200) { - confirmed = true; - ref = this.response; - for (k = 0, len1 = ref.length; k < len1; k++) { - page = ref[k]; - ref1 = page.threads; - for (q = 0, len2 = ref1.length; q < len2; q++) { - thread = ref1[q]; - if (thread.no === ThreadUpdater.thread.ID) { - confirmed = false; - break; - } - } - } - } else { - confirmed = false; - } - if (confirmed) { - return ThreadUpdater.kill(); - } else { - return ThreadUpdater.error(req); - } - } - }); - default: - return ThreadUpdater.error(req); - } - } - }, - kill: function() { - ThreadUpdater.thread.kill(); - ThreadUpdater.setInterval(); - return $.event('ThreadUpdate', { - 404: true, - threadID: ThreadUpdater.thread.fullID - }); - }, - error: function(req) { - if (req.status === 304) { - ThreadUpdater.set('status', ''); - } - ThreadUpdater.setInterval(); - if (!req.status) { - return ThreadUpdater.set('status', 'Connection Failed', 'warning'); - } else if (req.status !== 304) { - return ThreadUpdater.set('status', req.statusText + " (" + req.status + ")", 'warning'); - } - }, - setInterval: function() { - var cur, interval, j, limit; - clearTimeout(ThreadUpdater.timeoutID); - if (ThreadUpdater.thread.isDead) { - ThreadUpdater.set('status', (ThreadUpdater.thread.isArchived ? 'Archived' : '404'), 'warning'); - ThreadUpdater.set('timer', ''); - return; - } - if (ThreadUpdater.postID && ThreadUpdater.checkPostCount < 5) { - ThreadUpdater.set('timer', '...', 'loading'); - ThreadUpdater.timeoutID = setTimeout(ThreadUpdater.update, ++ThreadUpdater.checkPostCount * $.SECOND); - return; - } - if (!Conf['Auto Update']) { - ThreadUpdater.set('timer', 'Update'); - return; - } - interval = ThreadUpdater.interval; - if (Conf['Optional Increase']) { - limit = d.hidden ? 10 : 5; - j = Math.min(ThreadUpdater.outdateCount, limit); - cur = (Math.floor(interval * 0.1) || 1) * j * j; - ThreadUpdater.seconds = $.minmax(cur, interval, 300); - } else { - ThreadUpdater.seconds = interval; - } - return ThreadUpdater.timeout(); - }, - 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; - } - return el.className = klass != null ? klass : (text === '' ? 'empty' : ''); - }, - timeout: function() { - if (ThreadUpdater.seconds) { - ThreadUpdater.set('timer', ThreadUpdater.seconds); - ThreadUpdater.timeoutID = setTimeout(ThreadUpdater.timeout, 1000); - } else { - ThreadUpdater.outdateCount++; - ThreadUpdater.update(); - } - return ThreadUpdater.seconds--; - }, - update: function() { - var ref; - clearTimeout(ThreadUpdater.timeoutID); - ThreadUpdater.set('timer', '...', 'loading'); - 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: 'ThreadUpdater' - }); - }, - 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(req) { - var ID, OP, board, deletedFiles, deletedPosts, files, firstPost, index, ipCountEl, k, lastPost, len1, len2, len3, len4, newPosts, node, post, postObject, postObjects, posts, q, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, scroll, thread, u, unreadCount, unreadQYCount, v; - postObjects = req.response.posts; - OP = postObjects[0]; - thread = ThreadUpdater.thread; - board = thread.board; - ref = ThreadUpdater.postIDs, lastPost = ref[ref.length - 1]; - if (postObjects[postObjects.length - 1].no < lastPost && new Date(req.getResponseHeader('Last-Modified')) - thread.posts[lastPost].info.date < 30 * $.SECOND) { - return; - } - Build.spoilerRange[board] = OP.custom_spoiler; - thread.setStatus('Archived', !!OP.archived); - ThreadUpdater.updateThreadStatus('Sticky', !!OP.sticky); - ThreadUpdater.updateThreadStatus('Closed', !!OP.closed); - thread.postLimit = !!OP.bumplimit; - thread.fileLimit = !!OP.imagelimit; - if (OP.unique_ips != null) { - thread.ipCount = OP.unique_ips; - } - posts = []; - index = []; - files = []; - newPosts = []; - for (k = 0, len1 = postObjects.length; k < len1; k++) { - postObject = postObjects[k]; - ID = postObject.no; - index.push(ID); - if (postObject.fsize) { - files.push(ID); - } - if (ID <= lastPost) { - continue; - } - if ((post = thread.posts[ID]) && !post.isFetchedQuote) { - post.resurrect(); - continue; - } - newPosts.push(board + "." + ID); - node = Build.postFromObject(postObject, board.ID); - posts.push(new Post(node, thread, board)); - if (ThreadUpdater.postID === ID) { - delete ThreadUpdater.postID; - } - } - deletedPosts = []; - ref1 = ThreadUpdater.postIDs; - for (q = 0, len2 = ref1.length; q < len2; q++) { - ID = ref1[q]; - if (!(indexOf.call(index, ID) < 0)) { - continue; - } - thread.posts[ID].kill(); - deletedPosts.push(board + "." + ID); - } - ThreadUpdater.postIDs = index; - deletedFiles = []; - ref2 = ThreadUpdater.fileIDs; - for (u = 0, len3 = ref2.length; u < len3; u++) { - ID = ref2[u]; - if (!(!(indexOf.call(files, ID) >= 0 || (ref3 = board + "." + ID, indexOf.call(deletedPosts, ref3) >= 0)))) { - continue; - } - thread.posts[ID].kill(true); - deletedFiles.push(board + "." + ID); - } - ThreadUpdater.fileIDs = files; - if (!posts.length) { - ThreadUpdater.set('status', ''); - } else { - ThreadUpdater.set('status', "+" + posts.length, 'new'); - ThreadUpdater.outdateCount = 0; - unreadCount = (ref4 = Unread.posts) != null ? ref4.size : void 0; - unreadQYCount = (ref5 = Unread.postsQuotingYou) != null ? ref5.size : void 0; - Main.callbackNodes(Post, posts); - if (d.hidden || !d.hasFocus()) { - if (Conf['Beep Quoting You'] && ((ref6 = Unread.postsQuotingYou) != null ? ref6.size : void 0) > unreadQYCount) { - ThreadUpdater.playBeep(); - if (Conf['Beep']) { - ThreadUpdater.playBeep(); - } - } else if (Conf['Beep'] && ((ref7 = Unread.posts) != null ? ref7.size : void 0) > 0 && unreadCount === 0) { - ThreadUpdater.playBeep(); - } - } - scroll = Conf['Auto Scroll'] && ThreadUpdater.scrollBG() && ThreadUpdater.root.getBoundingClientRect().bottom - doc.clientHeight < 25; - firstPost = null; - for (v = 0, len4 = posts.length; v < len4; v++) { - post = posts[v]; - if (!QuoteThreading.insert(post)) { - firstPost || (firstPost = post.nodes.root); - $.add(ThreadUpdater.root, post.nodes.root); - } - } - $.event('PostsInserted'); - if (scroll) { - if (Conf['Bottom Scroll']) { - window.scrollTo(0, d.body.clientHeight); - } else { - if (firstPost) { - Header.scrollTo(firstPost); - } - } - } - } - 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'); - } - return $.event('ThreadUpdate', { - 404: false, - threadID: thread.fullID, - newPosts: newPosts, - deletedPosts: deletedPosts, - deletedFiles: deletedFiles, - postCount: OP.replies + 1, - fileCount: OP.images + !!OP.fsize, - ipCount: OP.unique_ips - }); - } - }; - - ThreadWatcher = { - init: function() { - var sc; - if (!(this.enabled = 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: "
Thread Watcher ×
" - }); - this.status = $('#watcher-status', this.dialog); - this.list = this.dialog.lastElementChild; - this.refreshButton = $('.refresh', this.dialog); - this.closeButton = $('.move > .close', this.dialog); - this.unreaddb = Unread.db || new DataBoard('lastReadPosts'); - this.unreadEnabled = Conf['Remember Last Read Post']; - $.on(d, 'QRPostSuccessful', this.cb.post); - $.on(sc, 'click', this.toggleWatcher); - $.on(this.refreshButton, 'click', this.buttonFetchAll); - $.on(this.closeButton, '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['Fixed Thread Watcher']) { - $.addClass(doc, 'fixed-watcher'); - } - if (Conf['Toggleable Thread Watcher']) { - this.dialog.hidden = true; - Header.addShortcut(sc); - $.addClass(doc, 'toggleable-watcher'); - } - ThreadWatcher.fetchAuto(); - if (g.VIEW === 'index' && Conf['JSON Index'] && Conf['Menu'] && g.BOARD.ID !== 'f') { - Menu.menu.addEntry({ - el: $.el('a', { - href: 'javascript:;', - className: 'has-shortcut-text' - }, { - innerHTML: "Alt+click" - }), - order: 6, - open: function(arg) { - var thread; - thread = arg.thread; - if (Conf['Index Mode'] !== 'catalog') { - return false; - } - this.el.firstElementChild.textContent = ThreadWatcher.isWatched(thread) ? 'Unwatch' : 'Watch'; - 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('a', { - href: 'javascript:;', - 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'); - } - $.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)); - return $.on(this.nodes.thumb.parentNode, 'mousedown', function(e) { - if (e.button === 0 && e.altKey) { - return e.preventDefault(); - } - }); - }, - ready: function() { - $.off(d, '4chanXInitFinished', ThreadWatcher.ready); - if (!Main.isThisPageLegit()) { - return; - } - ThreadWatcher.refresh(); - $.add(d.body, ThreadWatcher.dialog); - 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, k, len1, ref; - if ($.hasClass(this, 'disabled')) { - return; - } - ref = $$('a[title]', ThreadWatcher.list); - for (k = 0, len1 = ref.length; k < len1; k++) { - a = ref[k]; - $.open(a.href); - } - return $.event('CloseMenu'); - }, - pruneDeads: function() { - var boardID, data, k, len1, ref, ref1, threadID; - if ($.hasClass(this, 'disabled')) { - return; - } - ThreadWatcher.db.forceSync(); - ref = ThreadWatcher.getAll(); - for (k = 0, len1 = ref.length; k < len1; k++) { - ref1 = ref[k], 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, ref, threadID; - ref = this.parentNode.dataset.fullID.split('.'), boardID = ref[0], threadID = ref[1]; - return ThreadWatcher.rm(boardID, +threadID); - }, - post: function(e) { - var boardID, postID, ref, threadID; - 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, ref, threadID; - db = ThreadWatcher.db; - boardID = g.BOARD.ID; - db.forceSync(); - ref = db.data.boards[boardID]; - for (threadID in ref) { - data = ref[threadID]; - if (!(data != null ? data.isDead : void 0) && !(threadID in g.BOARD.threads)) { - if (Conf['Auto Prune'] || !(data && typeof data === 'object')) { - db["delete"]({ - boardID: boardID, - threadID: threadID - }); - } else { - if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { - ThreadWatcher.fetchStatus({ - boardID: boardID, - threadID: threadID, - data: data - }); - } - data.isDead = true; - 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); - } - }, - requests: [], - fetched: 0, - clearRequests: function() { - ThreadWatcher.requests = []; - ThreadWatcher.fetched = 0; - ThreadWatcher.status.textContent = ''; - return $.rmClass(ThreadWatcher.refreshButton, 'fa-spin'); - }, - abort: function() { - var k, len1, ref, req; - ref = ThreadWatcher.requests; - for (k = 0, len1 = ref.length; k < len1; k++) { - req = ref[k]; - if (req.readyState !== 4) { - req.abort(); - } - } - return ThreadWatcher.clearRequests(); - }, - fetchAuto: function() { - var db, interval, now; - clearTimeout(ThreadWatcher.timeout); - if (!Conf['Auto Update Thread Watcher']) { - return; - } - db = ThreadWatcher.db; - interval = ThreadWatcher.unreadEnabled && 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); - }, - buttonFetchAll: function() { - if (ThreadWatcher.requests.length) { - return ThreadWatcher.abort(); - } else { - return ThreadWatcher.fetchAllStatus(); - } - }, - fetchAllStatus: function() { - var k, len1, ref, thread, threads; - ThreadWatcher.db.forceSync(); - ThreadWatcher.unreaddb.forceSync(); - if ((ref = QuoteYou.db) != null) { - ref.forceSync(); - } - if (!(threads = ThreadWatcher.getAll()).length) { - return; - } - for (k = 0, len1 = threads.length; k < len1; k++) { - thread = threads[k]; - ThreadWatcher.fetchStatus(thread); - } - }, - fetchStatus: function(thread, force) { - var boardID, data, req, threadID; - boardID = thread.boardID, threadID = thread.threadID, data = thread.data; - if (data.isDead && !force) { - return; - } - if (ThreadWatcher.requests.length === 0) { - ThreadWatcher.status.textContent = '...'; - $.addClass(ThreadWatcher.refreshButton, 'fa-spin'); - } - req = $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", { - onloadend: function() { - return ThreadWatcher.parseStatus.call(this, thread); - }, - timeout: $.MINUTE - }, { - whenModified: force ? false : 'ThreadWatcher' - }); - return ThreadWatcher.requests.push(req); - }, - parseStatus: function(arg) { - var boardID, data, isDead, k, lastReadPost, len1, match, postObj, quotesYou, quotingYou, ref, ref1, regexp, threadID, unread; - boardID = arg.boardID, threadID = arg.threadID, data = arg.data; - ThreadWatcher.fetched++; - if (ThreadWatcher.fetched === ThreadWatcher.requests.length) { - ThreadWatcher.clearRequests(); - } else { - ThreadWatcher.status.textContent = (Math.round(ThreadWatcher.fetched / ThreadWatcher.requests.length * 100)) + "%"; - } - 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 (k = 0, len1 = ref.length; k < len1; k++) { - postObj = ref[k]; - if (!(postObj.no > lastReadPost)) { - continue; - } - if ((ref1 = QuoteYou.db) != null ? ref1.get({ - boardID: boardID, - threadID: threadID, - postID: postObj.no - }) : void 0) { - continue; - } - unread++; - if (!(QuoteYou.db && postObj.com)) { - continue; - } - quotesYou = false; - regexp = /]*\bhref="(?:\/([^\/]+)\/thread\/)?(\d+)?(?:#p(\d+))?"/g; - while (match = regexp.exec(postObj.com)) { - if (QuoteYou.db.get({ - boardID: match[1] || boardID, - threadID: match[2] || threadID, - postID: match[3] || match[2] || threadID - })) { - quotesYou = true; - break; - } - } - if (quotesYou && !Filter.isHidden(Build.parseJSON(postObj, boardID))) { - quotingYou++; - } - } - 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, ref, threadID, threads; - 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]; - if (data && typeof data === 'object') { - 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 (ThreadWatcher.unreadEnabled && 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 (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { - if (data.unread === 0) { - $.addClass(div, 'replies-read'); - } - 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, k, len1, len2, list, nodes, q, ref, ref1, ref2, refresher, threadID; - nodes = []; - ref = ThreadWatcher.getAll(); - for (k = 0, len1 = ref.length; k < len1; k++) { - ref1 = ref[k], 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, len2, post, q, ref2, toggler; - helper = ThreadWatcher.isWatched(thread) ? ['addClass', 'Unwatch'] : ['rmClass', 'Watch']; - if (thread.OP) { - ref2 = [thread.OP].concat(slice.call(thread.OP.clones)); - for (q = 0, len2 = ref2.length; q < len2; q++) { - post = ref2[q]; - 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 (q = 0, len2 = ref2.length; q < len2; q++) { - refresher = ref2[q]; - refresher(); - } - if (Index.nodes && Conf['Pin Watched Threads']) { - Index.sort(); - return Index.buildIndex(); - } - }, - refreshIcon: function() { - var className, k, len1, ref; - ref = ['replies-unread', 'replies-quoting-you']; - for (k = 0, len1 = ref.length; k < len1; k++) { - className = ref[k]; - ThreadWatcher.shortcut.classList.toggle(className, !!$("." + className, ThreadWatcher.dialog)); - } - }, - update: function(boardID, threadID, newData) { - var data, key, line, n, newLine, ref, val; - 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(); - } - }, - set404: function(boardID, threadID, cb) { - var data, ref; - if (!(data = (ref = ThreadWatcher.db) != null ? ref.get({ - boardID: boardID, - threadID: threadID - }) : void 0)) { - return cb(); - } - if (Conf['Auto Prune']) { - ThreadWatcher.db["delete"]({ - boardID: boardID, - threadID: threadID - }); - return cb(); - } - if (data.isDead && !((data.unread != null) || (data.quotingYou != null))) { - return cb(); - } - data.isDead = true; - delete data.unread; - delete data.quotingYou; - return ThreadWatcher.db.set({ - boardID: boardID, - threadID: threadID, - val: data - }, cb); - }, - 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 (ThreadWatcher.unreadEnabled && 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(); - }, - 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, ref, rmClass, text; - 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, k, len1, name, ref, ref1, refresh, subEntries; - 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 (k = 0, len1 = entries.length; k < len1; k++) { - ref1 = entries[k], 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; - if (name === 'Show Unread Count' && !ThreadWatcher.unreadEnabled) { - input.disabled = true; - $.addClass(entry.el, 'disabled'); - entry.el.title += '\n[Remember Last Read Post is disabled.]'; - } - $.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['Remember Last Read Post'] || Conf['Desktop Notifications'] || Conf['Quote Threading']))) { - return; - } - if (Conf['Remember Last Read Post']) { - $.sync('Remember Last Read Post', function(enabled) { - return Conf['Remember Last Read Post'] = enabled; - }); - 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, k, len1, ref, ref1; - Unread.thread = this; - Unread.title = d.title; - Unread.lastReadPost = ((ref = Unread.db) != null ? ref.get({ - boardID: this.board.ID, - threadID: this.ID - }) : void 0) || 0; - Unread.readCount = 0; - ref1 = this.posts.keys; - for (k = 0, len1 = ref1.length; k < len1; k++) { - ID = ref1[k]; - if (+ID <= Unread.lastReadPost) { - Unread.readCount++; - } - } - $.one(d, '4chanXInitFinished', Unread.ready); - return $.on(d, 'ThreadUpdate', Unread.onUpdate); - }, - ready: function() { - if (Conf['Remember Last Read Post'] && Conf['Scroll to Last Read Post']) { - Unread.scroll(); - } - Unread.setLine(true); - Unread.read(); - Unread.update(); - $.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, ref, root; - if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) { - return; - } - ReplyPruning.showIfHidden((ref = Unread.position) != null ? ref.data.nodes.root.id : void 0); - 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, k, lastReadPost, postIDs, 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 = k = ref = Unread.readCount, ref1 = postIDs.length; k < ref1; i = k += 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 = QuoteYou.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 k, len1, quotelink, ref, ref1; - ref = post.nodes.quotelinks; - for (k = 0, len1 = ref.length; k < len1; k++) { - quotelink = ref[k]; - if (!((ref1 = QuoteYou.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; - } - try { - notif = new Notification(post.info.nameBlock + " replied to you", { - body: post.info.commentDisplay, - icon: Favicon.logo - }); - notif.onclick = function() { - Header.scrollToIfNeeded(post.nodes.root, true); - return $.global(function() { - return window.focus(); - }); - }; - return notif.onshow = function() { - return setTimeout(function() { - return notif.close(); - }, 7 * $.SECOND); - }; - } catch (_error) {} - }, - 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, ref, ref1, root; - if (!Unread.posts.size && Unread.readCount !== Unread.thread.posts.keys.length) { - Unread.saveLastReadPost(); - } - if (d.hidden || !Unread.posts.size) { - return; - } - 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 ((ref1 = QuoteYou.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, k, postIDs, ref, ref1; - $.forceSync('Remember Last Read Post'); - if (!(Conf['Remember Last Read Post'] && Unread.db)) { - return; - } - postIDs = Unread.thread.posts.keys; - for (i = k = ref = Unread.readCount, ref1 = postIDs.length; k < ref1; i = k += 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 (Unread.hr.hidden || 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, isDead, 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; - } - $.forceSync('Remember Last Read Post'); - if (Conf['Remember Last Read Post'] && (!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']) { - isDead = Unread.thread.isDead; - Favicon.el.href = countQuotingYou ? Favicon[isDead ? 'unreadDeadY' : 'unreadY'] : count ? Favicon[isDead ? 'unreadDead' : 'unread'] : Favicon[isDead ? 'dead' : 'default']; - return $.add(d.head, Favicon.el); - } - } - }; - - Redirect = { - init: function() { - var archive, archives, boardID, boards, data, files, id, k, len1, len2, name, o, q, record, ref, ref1, software, type, uid, withCredentials; - o = { - thread: {}, - post: {}, - file: {}, - report: {} - }; - archives = {}; - ref = Redirect.archives; - for (k = 0, len1 = ref.length; k < len1; k++) { - data = ref[k]; - uid = data.uid, name = data.name, boards = data.boards, files = data.files, software = data.software, withCredentials = data.withCredentials; - archives[JSON.stringify(uid != null ? uid : name)] = data; - for (q = 0, len2 = boards.length; q < len2; q++) { - boardID = boards[q]; - if (!withCredentials) { - 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; - } - } - if (name === 'fgts') { - o.report[boardID] = data; - } - } - } - ref1 = Conf['selectedArchives']; - for (boardID in ref1) { - record = ref1[boardID]; - for (type in record) { - id = record[type]; - if (id === null) { - delete o[type][boardID]; - } else if (archive = archives[JSON.stringify(id)]) { - boards = type === 'file' ? archive.files : archive.boards; - if (indexOf.call(boards, boardID) >= 0) { - o[type][boardID] = archive; - } - } - } - } - return Redirect.data = o; - }, - archives: [{"uid":3,"name":"4plebs","domain":"archive.4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["adv","f","hr","o","pol","s4s","sp","tg","trv","tv","x"],"files":["adv","f","hr","o","pol","s4s","sp","tg","trv","tv","x"]},{"uid":4,"name":"Nyafuu Archive","domain":"archive.nyafuu.org","http":true,"https":true,"software":"foolfuuka","boards":["c","e","news","w","wg","wsr"],"files":["c","e","news","w","wg","wsr"]},{"uid":8,"name":"Rebecca Black Tech","domain":"rbt.asia","http":false,"https":true,"software":"fuuka","boards":["cgl","g","mu"],"files":["cgl","g","mu"]},{"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","b","cm","gd","h","hc","hm","n","out","p","po","qa","r","s","soc","toy","vp","y"],"files":["asp","b","cm","gd","h","hc","hm","n","out","p","po","qa","r","s","soc","toy","vp","y"]},{"uid":23,"name":"Desustorage","domain":"desustorage.org","http":true,"https":true,"software":"foolfuuka","boards":["a","aco","an","c","co","d","fit","gif","his","int","k","m","mlp","qa","r9k","tg","trash","vr","wsg"],"files":["a","aco","an","c","co","d","fit","gif","his","int","k","m","mlp","qa","r9k","tg","trash","vr","wsg"]},{"uid":24,"name":"fireden.net","domain":"boards.fireden.net","http":false,"https":true,"software":"foolfuuka","boards":["a","cm","ic","sci","tg","v","vg","y"],"files":["a","cm","ic","sci","tg","v","vg","y"]},{"uid":25,"name":"arch.b4k.co","domain":"arch.b4k.co","http":true,"https":true,"software":"foolfuuka","boards":["g","jp","mlp","v"],"files":[]},{"uid":5,"name":"Love is Over","domain":"deploy.loveisover.me","http":true,"https":false,"software":"foolfuuka","boards":["c","d","e","i","lgbt","t","u"],"files":["c","d","e","i","lgbt","t","u"],"search":[]},{"uid":28,"name":"bstats","domain":"archive.b-stats.org","http":true,"https":true,"software":"foolfuuka","boards":["f","cm","hm","lgbt","news","trash","y"],"files":[]}], - 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 boardID, postID, protocol, url; - boardID = arg.boardID, postID = arg.postID; - protocol = Redirect.protocol(archive); - url = "" + protocol + archive.domain + "/_/api/chan/post/?board=" + boardID + "&num=" + postID; - if (!Redirect.securityCheck(url)) { - return ''; - } - 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 === 'MD5' ? 'image' : type; - if (type === 'capcode') { - value = { - 'Developer': 'dev' - }[value] || value.toLowerCase(); - } else if (type === 'image') { - value = value.replace(/[+\/=]/g, function(c) { - return { - '+': '-', - '/': '_', - '=': '' - }[c]; - }); - } - value = encodeURIComponent(value); - path = archive.software === 'foolfuuka' ? boardID + "/search/" + type + "/" + value + "/" : type === 'image' ? boardID + "/image/" + value : boardID + "/?task=search2&search_" + type + "=" + value; - return "" + (Redirect.protocol(archive)) + archive.domain + "/" + path; - }, - report: function(archive, arg) { - var boardID, postID; - boardID = arg.boardID, postID = arg.postID; - return "https://so.fgts.jp/report/?board=" + boardID + "&no=" + postID; - }, - securityCheck: function(url) { - return /^https:\/\//.test(url) || location.protocol === 'http:' || Conf['Exempt Archives from Encryption']; - }, - navigate: function(dest, data, alternative) { - var url; - if (!Redirect.data) { - Redirect.init(); - } - url = Redirect.to(dest, data); - 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: "[Dismiss]" - }); - $.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() { - 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, k, len1, ref; - if (!Conf['Disable Autoplaying Sounds']) { - return; - } - $.addClass(doc, 'anti-autoplay'); - ref = $$('audio[autoplay]', doc); - for (k = 0, len1 = ref.length; k < len1; k++) { - audio = ref[k]; - 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, k, len1, len2, object, q, ref, ref1; - ref = $$('iframe[src*="youtube"][src*="autoplay=1"]', root); - for (k = 0, len1 = ref.length; k < len1; k++) { - iframe = ref[k]; - iframe.src = iframe.src.replace(/\?autoplay=1&?/, '?').replace('&autoplay=1', ''); - $.addClass(iframe, 'autoplay-removed'); - } - ref1 = $$('object[data*="youtube"][data*="autoplay=1"]', root); - for (q = 0, len2 = ref1.length; q < len2; q++) { - object = ref1[q]; - object.data = object.data.replace(/\?autoplay=1&?/, '?').replace('&autoplay=1', ''); - $.addClass(object, 'autoplay-removed'); - } - } - }; - - 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","79.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","256.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","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 base1, br, k, len1, name1, ref; - if (!(e.ctrlKey || e.metaKey)) { - return; - } - if ((base1 = Banner.original)[name1 = this.className] == null) { - base1[name1] = this.cloneNode(true); - } - this.contentEditable = true; - ref = $$('br', this); - for (k = 0, len1 = ref.length; k < len1; k++) { - br = ref[k]; - $.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, k, len1, ref; - ref = $$('br', this); - for (k = 0, len1 = ref.length; k < len1; k++) { - br = ref[k]; - $.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, k, len1, ref, string, string2; - className = child.className; - child.title = "Ctrl/\u2318+click to edit board " + (className.slice(5).toLowerCase()); - child.spellcheck = false; - ref = ['click', 'keydown', 'blur']; - for (k = 0, len1 = ref.length; k < len1; k++) { - event = ref[k]; - $.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 Index']) && !(Conf['JSON Index'] && 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, k, len1, link, ref; - ref = $$(selector); - for (k = 0, len1 = ref.length; k < len1; k++) { - link = ref[k]; - switch (link.pathname.replace(/\/+/g, '/')) { - case "/" + g.BOARD + "/": - if (Conf['JSON Index']) { - link.textContent = 'Index'; - } - link.href = CatalogLinks.index(); - break; - case "/" + g.BOARD + "/catalog": - link.href = CatalogLinks.catalog(); - } - if (g.VIEW === 'catalog' && Conf['JSON Index'] && 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 Index'] && 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, k, len1, m, ref; - ref = $$('a', this.nodes.comment); - for (k = 0, len1 = ref.length; k < len1; k++) { - a = ref[k]; - if (m = a.href.match(/^https?:\/\/boards\.4chan\.org\/([^\/]+)\/catalog(#s=.*)?/)) { - a.href = "//boards.4chan.org/" + m[1] + "/" + (m[2] || '#catalog'); - } - } - }, - initBoardList: function() { - if (!CatalogLinks.el) { - 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, k, len1, ref, ref1; - ref = $$('a:not([data-only])', Header.boardList).concat($$('a', Header.bottomBoardList)); - for (k = 0, len1 = ref.length; k < len1; k++) { - a = ref[k]; - if (((ref1 = a.hostname) !== 'boards.4chan.org' && ref1 !== 'catalog.neet.tv') || !(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 + "/"; - if (a.dataset.indexOptions && a.hostname === 'boards.4chan.org' && a.pathname.split('/')[2] === '') { - a.href += (a.hash ? '/' : '#') + a.dataset.indexOptions; - } - } - 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 Index'] && 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 Index'] && board !== 'f') { - 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', '#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 Index']) { - 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, k, len1, len2, len3, postObj, posts, q, quote, ref, ref1, spoilerRange, status, u; - 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 (k = 0, len1 = posts.length; k < len1; k++) { - postObj = posts[k]; - 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 (q = 0, len2 = ref.length; q < len2; q++) { - quote = ref[q]; - 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 (u = 0, len3 = ref1.length; u < len3; u++) { - callback = ref1[u]; - callback.call(post); - } - } - }; - - ExpandThread = { - statuses: {}, - init: function() { - if (g.VIEW === 'thread' || !Conf['Thread Expansion']) { - return; - } - if (Conf['JSON Index']) { - 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 = Build.summaryText.apply(Build, ['+'].concat(slice.call(a.textContent.match(/\d+/g)))); - a.style.cursor = 'pointer'; - return $.on(a, 'click', ExpandThread.cbToggle); - }, - disconnect: function(refresh) { - var ref, ref1, status, threadID; - 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); - }); - }, - 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); - } - }, - expand: function(thread, a) { - var status; - ExpandThread.statuses[thread] = status = {}; - a.textContent = Build.summaryText.apply(Build, ['...'].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, k, len1, num, postsCount, replies, reply, status; - status = ExpandThread.statuses[thread]; - delete ExpandThread.statuses[thread]; - if (status.req) { - status.req.abort(); - if (a) { - a.textContent = Build.summaryText.apply(Build, ['+'].concat(slice.call(a.textContent.match(/\d+/g)))); - } - return; - } - replies = $$('.thread > .replyContainer', threadRoot); - if (!Conf['JSON Index'] || 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 (k = 0, len1 = replies.length; k < len1; k++) { - reply = replies[k]; - if (Conf['Quote Inlining']) { - while (inlined = $('.inlined', reply)) { - inlined.click(); - } - } - postsCount++; - if ('file' in Get.postFromRoot(reply)) { - filesCount++; - } - $.rm(reply); - } - return a.textContent = Build.summaryText('+', postsCount, filesCount); - }, - parse: function(req, thread, a) { - var filesCount, k, len1, post, postData, posts, postsCount, postsRoot, ref, ref1, root; - 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 (k = 0, len1 = ref1.length; k < len1; k++) { - postData = ref1[k]; - 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 = Build.summaryText('-', 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() { - var info, oldInfo; - if (!this.file || this.isClone) { - return; - } - oldInfo = $.el('span', { - className: 'fileText-original' - }); - $.prepend(this.file.link.parentNode, oldInfo); - $.add(oldInfo, [this.file.link.previousSibling, this.file.link, this.file.link.nextSibling]); - info = $.el('span', { - className: 'file-info' - }); - FileInfo.format(Conf['fileInfo'], this, info); - return $.prepend(this.file.text, info); - }, - 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: E.cat(output) - }); - }, - formatters: { - t: function() { - return { - innerHTML: E(this.file.url.match(/[^/]*$/)[0]) - }; - }, - T: function() { - return { - innerHTML: "" + FileInfo.formatters.t.call(this).innerHTML + "" - }; - }, - l: function() { - return { - innerHTML: "" + FileInfo.formatters.n.call(this).innerHTML + "" - }; - }, - L: function() { - return { - innerHTML: "" + FileInfo.formatters.N.call(this).innerHTML + "" - }; - }, - 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: "" + E(shortname) + "" + E(fullname) + "" - }; - } - }, - N: function() { - return { - innerHTML: E(this.file.name) - }; - }, - p: function() { - return { - innerHTML: (this.file.isSpoiler ? "Spoiler, " : "") - }; - }, - 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") - }; - }, - g: function() { - return { - innerHTML: (this.file.tag ? ", " + E(this.file.tag) : "") - }; - }, - '%': function() { - return { - innerHTML: "%" - }; - } - } - }; - - Flash = { - init: function() { - if (g.BOARD.ID === 'f' && Conf['Enable Native Flash Embedding']) { - return $.ready(Flash.initReady); - } - }, - initReady: function() { - if ($.hasStorage) { - return $.global(function() { - if (JSON.parse(localStorage['4chan-settings'] || '{}').disableAll) { - return window.SWFEmbed.init(); - } - }); - } else { - if (g.VIEW === 'thread') { - $.global(function() { - return window.Main.tid = location.pathname.split(/\/+/)[3]; - }); - } - return $.global(function() { - return window.SWFEmbed.init(); - }); - } - } - }; - - Fourchan = { - init: function() { - var ref; - if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { - return; - } - if (g.BOARD.ID === 'g') { - $.on(window, 'prettyprint:cb', function(e) { - var post, pre; - if (!(post = g.posts[e.detail.ID])) { - return; - } - if (!(pre = $$('.prettyprint', post.nodes.comment)[e.detail.i])) { - return; - } - if (!$.hasClass(pre, 'prettyprinted')) { - pre.innerHTML = e.detail.html; - return $.addClass(pre, 'prettyprinted'); - } - }); - $.globalEval('window.addEventListener(\'prettyprint\', function(e) {\n window.dispatchEvent(new CustomEvent(\'prettyprint:cb\', {\n detail: {\n ID: e.detail.ID,\n i: e.detail.i,\n html: prettyPrintOne(e.detail.html)\n }\n }));\n}, false);'); - Post.callbacks.push({ - name: 'Parse /g/ code', - cb: this.code - }); - } - if (g.BOARD.ID === 'sci') { - $.global(function() { - return window.addEventListener('mathjax', function(e) { - if (window.MathJax) { - return window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub, e.target]); - } else { - if (!document.querySelector('script[src^="//cdn.mathjax.org/"]')) { - window.loadMathJax(); - window.loadMathJax = function() {}; - } - if (!e.target.classList.contains('postMessage')) { - return document.querySelector('script[src^="//cdn.mathjax.org/"]').addEventListener('load', function() { - return window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub, e.target]); - }, false); - } - } - }, 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 $.global(function() { - var k, len1, node, ref1; - window.clickable_ids = false; - ref1 = document.querySelectorAll('.posteruid, .capcode'); - for (k = 0, len1 = ref1.length; k < len1; k++) { - node = ref1[k]; - node.removeEventListener('click', window.idClick, false); - } - }); - }); - }, - code: function() { - if (this.isClone) { - return; - } - return $.ready((function(_this) { - return function() { - var i, k, len1, pre, ref; - ref = $$('.prettyprint', _this.nodes.comment); - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - pre = ref[i]; - if (!$.hasClass(pre, 'prettyprinted')) { - $.event('prettyprint', { - ID: _this.fullID, - i: i, - html: pre.innerHTML - }, window); - } - } - }; - })(this)); - }, - math: function() { - var cb, k, len1, wbr, wbrs; - if (!/\[(math|eqn)\]/.test(this.nodes.comment.textContent)) { - return; - } - if ((wbrs = $$('wbr', this.nodes.comment)).length) { - for (k = 0, len1 = wbrs.length; k < len1; k++) { - wbr = wbrs[k]; - $.rm(wbr); - } - this.nodes.comment.normalize(); - } - cb = (function(_this) { - return function() { - if (!doc.contains(_this.nodes.comment)) { - return; - } - $.off(d, 'PostsInserted', cb); - return $.event('mathjax', null, _this.nodes.comment); - }; - })(this); - $.on(d, 'PostsInserted', cb); - return cb(); - } - }; - - 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 Config.hotkeys) { - $.sync(hotkey, Keybinds.sync); - } - init = function() { - var k, len1, node, ref; - $.off(d, '4chanXInitFinished', init); - $.on(d, 'keydown', Keybinds.keydown); - ref = $$('[accesskey]'); - for (k = 0, len1 = ref.length; k < len1; k++) { - node = ref[k]; - node.removeAttribute('accesskey'); - } - }; - return $.on(d, '4chanXInitFinished', init); - }, - sync: function(key, hotkey) { - return Conf[hotkey] = key; - }, - keydown: function(e) { - var form, k, key, len1, notification, notifications, op, ref, ref1, ref2, ref3, ref4, ref5, searchInput, target, thread, threadRoot; - 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) && !/^Alt\+(\d|Up|Down|Left|Right)$/.test(key))) { - return; - } - } - if (!(((ref1 = g.VIEW) !== 'index' && ref1 !== 'thread') || g.VIEW === 'index' && Conf['JSON Index'] && Conf['Index Mode'] === 'catalog' || g.VIEW === 'index' && g.BOARD.ID === 'f')) { - 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 (k = 0, len1 = notifications.length; k < len1; k++) { - notification = notifications[k]; - $('.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['SJIS tags']: - if (target.nodeName !== 'TEXTAREA') { - return; - } - Keybinds.tags('sjis', 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 Index'] && g.BOARD.ID !== 'f')) { - return; - } - Index.update(); - break; - default: - return; - } - break; - case Conf['Watch']: - if (!(ThreadWatcher.enabled && thread)) { - return; - } - ThreadWatcher.toggle(thread); - break; - case Conf['Update thread watcher']: - if (!ThreadWatcher.enabled) { - return; - } - ThreadWatcher.buttonFetchAll(); - 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'))) { - return; - } - FappeTyme.toggle('fappe'); - break; - case Conf['werkTyme']: - if (!(Conf['Werk Tyme'] && ((ref3 = g.VIEW) === 'index' || ref3 === 'thread'))) { - return; - } - FappeTyme.toggle('werk'); - break; - case Conf['Front page']: - if (Conf['JSON Index'] && g.VIEW === 'index' && g.BOARD.ID !== 'f') { - 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' && g.BOARD.ID !== 'f')) { - return; - } - if (Conf['JSON Index']) { - 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' && g.BOARD.ID !== 'f')) { - return; - } - if (Conf['JSON Index']) { - 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' && g.BOARD.ID !== 'f')) { - return; - } - searchInput = Conf['JSON Index'] ? Index.searchInput : $.id('search-box'); - Header.scrollToIfNeeded(searchInput); - searchInput.focus(); - break; - case Conf['Paged mode']: - if (!(Conf['JSON Index'] && g.BOARD.ID !== 'f')) { - return; - } - window.location = g.VIEW === 'index' ? '#paged' : "/" + g.BOARD + "/#paged"; - break; - case Conf['Infinite scrolling mode']: - if (!(Conf['JSON Index'] && g.BOARD.ID !== 'f')) { - return; - } - window.location = g.VIEW === 'index' ? '#infinite' : "/" + g.BOARD + "/#infinite"; - break; - case Conf['All pages mode']: - if (!(Conf['JSON Index'] && g.BOARD.ID !== 'f')) { - return; - } - window.location = g.VIEW === 'index' ? '#all-pages' : "/" + g.BOARD + "/#all-pages"; - break; - case Conf['Open catalog']: - if (g.BOARD.ID === 'f') { - return; - } - window.location = CatalogLinks.catalog(); - break; - case Conf['Cycle sort type']: - if (!(Conf['JSON Index'] && g.VIEW === 'index' && g.BOARD.ID !== '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 && QuoteYou.db)) { - return; - } - QuoteYou.cb.seek('preceding'); - break; - case Conf['Next Post Quoting You']: - if (!(threadRoot && QuoteYou.db)) { - 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 32: - return 'Space'; - case 37: - return 'Left'; - case 38: - return 'Up'; - case 39: - return 'Right'; - case 40: - return 'Down'; - case 188: - return 'Comma'; - case 190: - return 'Period'; - case 191: - return 'Slash'; - case 59: - case 186: - return 'Semicolon'; - default: - if ((48 <= kc && kc <= 57) || (65 <= kc && kc <= 90)) { - return String.fromCharCode(kc).toLowerCase(); - } else if ((96 <= kc && kc <= 105)) { - return String.fromCharCode(kc - 48).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'; - case 'sjis': - return g.BOARD.ID === 'jp'; - } - })(); - 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, k, len1, next, postEl, replies, reply, root; - 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 (k = 0, len1 = replies.length; k < len1; k++) { - reply = replies[k]; - 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 k, len1, ref, thread, threadRoot; - ref = $$('.thread'); - for (k = 0, len1 = ref.length; k < len1; k++) { - threadRoot = ref[k]; - 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, ref, thread, top; - 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); - } - } - }; - - NormalizeURL = { - init: function() { - var pathname; - if (!Conf['Normalize URL']) { - return; - } - pathname = location.pathname.split(/\/+/); - switch (g.VIEW) { - case 'thread': - pathname[2] = 'thread'; - pathname = pathname.slice(0, 4); - break; - case 'index': - pathname = pathname.slice(0, 3); - } - pathname = pathname.join('/'); - if (location.pathname !== pathname) { - return history.replaceState(history.state, '', location.protocol + "//" + location.host + pathname + location.hash); - } - } - }; - - 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 Index'] && 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, k, len1, now, ref; - if (d.hidden) { - return; - } - now = new Date(); - ref = RelativeDates.stale; - for (k = 0, len1 = ref.length; k < len1; k++) { - data = ref[k]; - 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, k, len1, ref, relative, singlePost; - 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 (k = 0, len1 = ref.length; k < len1; k++) { - singlePost = ref[k]; - 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() { - return RemoveSpoilers.unspoiler(this.nodes.comment); - }, - unspoiler: function(el) { - var k, len1, span, spoiler, spoilers; - spoilers = $$('s', el); - for (k = 0, len1 = spoilers.length; k < len1; k++) { - spoiler = spoilers[k]; - span = $.el('span', { - className: 'removed-spoiler' - }); - $.replace(spoiler, span); - $.add(span, slice.call(spoiler.childNodes)); - } - } - }; - - Report = { - css: "#g-recaptcha,\n" + -":root:not(.js-enabled) #captchaContainerAlt {\n" + -" height: auto;\n" + -"}\n" + -"#captchaContainerAlt td:nth-child(2) {\n" + -" display: table-cell !important;\n" + -"}", - init: function() { - var match; - if (!(match = location.search.match(/\bno=(\d+)/))) { - return; - } - Captcha.replace.init(); - this.postID = +match[1]; - return $.ready(this.ready); - }, - ready: function() { - var passAd, prev, ref; - $.addStyle(Report.css); - if (Conf['Archive Report']) { - Report.archive(); - } - if ((passAd = $('a[href="https://www.4chan.org/pass"]'))) { - $.extend(passAd, { - textContent: 'Complain', - href: 'https://www.4chan-x.net/captchas.html', - tabIndex: -1 - }); - passAd.parentNode.normalize(); - if (((ref = (prev = passAd.previousSibling)) != null ? ref.nodeType : void 0) === Node.TEXT_NODE) { - prev.nodeValue = prev.nodeValue.replace(/4chan Pass[^\.]*\./i, 'reCAPTCHA malfunctioning?'); - } - $.after(passAd, [ - $.tn('] ['), $.el('a', { - href: 'mailto:4chanpass@4chan.org?subject=4chan%20Pass%20-%20Purchase%20Support', - textContent: 'Email 4chan', - target: '_blank', - tabIndex: -1 - }) - ]); - } - if (!Conf['Use Recaptcha v1 in Reports'] && !Conf['Force Noscript Captcha'] && Main.jsEnabled) { - return new MutationObserver(function() { - Report.fit('iframe[src^="https://www.google.com/recaptcha/api2/frame"]'); - return Report.fit('body'); - }).observe(d.body, { - childList: true, - attributes: true, - subtree: true - }); - } else { - return Report.fit('body'); - } - }, - fit: function(selector) { - var dy, el; - if (!((el = $(selector, doc)) && getComputedStyle(el).visibility !== 'hidden')) { - return; - } - dy = el.getBoundingClientRect().bottom - doc.clientHeight + 8; - if (dy > 0) { - return window.resizeBy(0, dy); - } - }, - archive: function() { - var link, message, types, url; - Redirect.init(); - if (!(url = Redirect.to('report', { - boardID: g.BOARD.ID, - postID: Report.postID - }))) { - return; - } - if ((message = $('h3')) && /Report submitted!/.test(message.textContent)) { - if (location.hash === '#redirect') { - $.globalEval('self.close = function(){};'); - window.resizeTo(700, 475); - location.replace(url); - } - return; - } - link = $.el('a', { - href: url, - textContent: 'Report to archive' - }); - $.on(link, 'click', function(e) { - if (!(e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0)) { - return window.resizeTo(700, 475); - } - }); - $.add(d.body, [$.tn(' ['), link, $.tn(']')]); - if (types = $.id('reportTypes')) { - return $.on(types, 'change', function(e) { - return $('form').action = e.target.value === 'illegal' ? '#redirect' : ''; - }); - } - } - }; - - ThreadLinks = { - init: function() { - if (!(g.VIEW === 'index' && Conf['Open Threads in New Tab'])) { - return; - } - Post.callbacks.push({ - name: 'Thread Links', - cb: this.node - }); - return CatalogThread.callbacks.push({ - name: 'Thread Links', - cb: this.catalogNode - }); - }, - node: function() { - if (this.isReply || this.isClone) { - return; - } - return ThreadLinks.process($('.replylink', this.nodes.info)); - }, - catalogNode: function() { - return ThreadLinks.process(this.nodes.thumb.parentNode); - }, - process: function(link) { - return link.target = '_blank'; - } - }; - - 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']) { - if ($.hasStorage) { - settings = JSON.parse(localStorage.getItem('4chan-settings')) || {}; - if (settings.disableAll) { - return; - } - settings.disableAll = true; - return localStorage.setItem('4chan-settings', JSON.stringify(settings)); - } else { - return $.onExists(doc, 'body', function() { - return $.global(function() { - return window.Config.disableAll = true; - }); - }); - } - } - }, - open: function(openSection) { - var dialog, k, len1, link, links, overlay, ref, section, sectionToOpen; - if (Settings.overlay) { - return; - } - $.event('CloseMenu'); - Settings.dialog = dialog = $.el('div', { - id: 'fourchanx-settings', - className: 'dialog' - }); - $.extend(dialog, { - innerHTML: "
" - }); - 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 (k = 0, len1 = ref.length; k < len1; k++) { - section = ref[k]; - 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); - }, - warnings: { - localStorage: function(cb) { - var why; - if ($.cantSync) { - why = $.cantSet ? 'save your settings' : 'synchronize settings between tabs'; - return cb($.el('li', { - textContent: "4chan X needs local storage to " + why + ".\nEnable it on boards.4chan.org in your browser's privacy settings (may be listed as part of \"local data\" or \"cookies\")." - })); - } - }, - ads: function(cb) { - return $.onExists(doc, '.ad-cnt', function(ad) { - return $.onExists(ad, 'img', function() { - return cb($.el('li', { - innerHTML: "To protect yourself from malicious ads, you should block ads on 4chan." - })); - }); - }); - } - }, - main: function(section) { - var addWarning, arr, button, container, containers, description, div, fs, input, inputs, items, key, level, obj, ref, ref1, warning, warnings; - warnings = $.el('fieldset', { - hidden: true - }, { - innerHTML: "Warnings
    " - }); - addWarning = function(item) { - $.add($('ul', warnings), item); - return warnings.hidden = false; - }; - ref = Settings.warnings; - for (key in ref) { - warning = ref[key]; - warning(addWarning); - } - $.add(section, warnings); - items = {}; - inputs = {}; - ref1 = Config.main; - for (key in ref1) { - obj = ref1[key]; - fs = $.el('fieldset', { - innerHTML: "" + E(key) + "" - }); - containers = [fs]; - for (key in obj) { - arr = obj[key]; - description = arr[1]; - div = $.el('div', { - innerHTML: ": " + E(description) + "" - }); - if ($.engine !== 'gecko' && key === 'Remember QR Size') { - div.hidden = true; - } - 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: ": 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, ref2, ref3, thread; - hiddenThreads = arg.hiddenThreads, hiddenPosts = arg.hiddenPosts; - hiddenNum = 0; - ref2 = hiddenThreads.boards; - for (ID in ref2) { - board = ref2[ID]; - hiddenNum += Object.keys(board).length; - } - ref3 = hiddenPosts.boards; - for (ID in ref3) { - board = ref3[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; - if ($.hasStorage) { - 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) { - 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; - } - this.value = null; - 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 { - return Settings.loadSettings(JSON.parse(e.target.result), function(err) { - if (err) { - return output.textContent = 'Import failed due to an error.'; - } else 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); - }, - convertFrom: { - loadletter: function(data) { - var base1, boardID, convertSettings, key, ref, ref1, threadData, threadID, threads, val; - 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': 'Disable Native Extension', - 'Comment Auto-Expansion': '', - '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', - 'Current Page': 'Page Count in Stats', - 'Current Page Position': '', - 'Alternative captcha': 'Use Recaptcha v1', - 'Auto Submit': 'Post on Captcha Completion', - '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()); - }); - } - } - if (data.WatchedThreads) { - data.Conf['watchedThreads'] = { - boards: {} - }; - ref1 = data.WatchedThreads; - for (boardID in ref1) { - threads = ref1[boardID]; - for (threadID in threads) { - threadData = threads[threadID]; - ((base1 = data.Conf['watchedThreads'].boards)[boardID] || (base1[boardID] = {}))[threadID] = { - excerpt: threadData.textContent - }; - } - } - } - return data; - } - }, - upgrade: function(data, version) { - var boardID, changes, compareString, k, key, len1, name, record, ref, ref1, ref2, ref3, ref4, ref5, rice, set, type, uids, value; - changes = {}; - set = function(key, value) { - return data[key] = changes[key] = value; - }; - compareString = version.replace(/\d+/g, function(x) { - return ('0000' + x).slice(-5); - }); - if (compareString < '00001.00011.00008.00000') { - if (data['Fixed Thread Watcher'] == null) { - set('Fixed Thread Watcher', (ref = data['Toggleable Thread Watcher']) != null ? ref : true); - } - if (data['Exempt Archives from Encryption'] == null) { - set('Exempt Archives from Encryption', (ref1 = data['Except Archives from Encryption']) != null ? ref1 : false); - } - } - if (compareString < '00001.00011.00010.00001') { - if (data['selectedArchives'] != null) { - uids = { - "Moe": 0, - "4plebs Archive": 3, - "Nyafuu Archive": 4, - "Love is Over": 5, - "Rebecca Black Tech": 8, - "warosu": 10, - "fgts": 15, - "not4plebs": 22, - "DesuStorage": 23, - "fireden.net": 24, - "disabled": null - }; - ref2 = data['selectedArchives']; - for (boardID in ref2) { - record = ref2[boardID]; - for (type in record) { - name = record[type]; - if (name in uids) { - record[type] = uids[name]; - } - } - } - set('selectedArchives', data['selectedArchives']); - } - } - if (compareString < '00001.00011.00016.00000') { - if ((rice = Config['usercss'].match(/\/\* Board title rice \*\/(?:\n.+)*/)[0])) { - if ((data['usercss'] != null) && data['usercss'].indexOf(rice) < 0) { - set('usercss', rice + '\n\n' + data['usercss']); - } - } - } - if (compareString < '00001.00011.00017.00000') { - ref3 = ['Persistent QR', 'Color User IDs', 'Fappe Tyme', 'Werk Tyme', 'Highlight Posts Quoting You', 'Highlight Own Posts']; - for (k = 0, len1 = ref3.length; k < len1; k++) { - key = ref3[k]; - if (data[key] == null) { - set(key, key === 'Persistent QR'); - } - } - } - if (compareString < '00001.00011.00017.00006') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/^(#?\s*)http:\/\/iqdb\.org\//mg, '$1//iqdb.org/')); - } - } - if (compareString < '00001.00011.00019.00003' && !Settings.overlay) { - $.queueTask(function() { - return Settings.warnings.ads(function(item) { - return new Notice('warning', slice.call(item.childNodes)); - }); - }); - } - if (compareString < '00001.00011.00020.00003') { - ref4 = { - 'Inline Cross-thread Quotes Only': false, - 'Pass Link': true - }; - for (key in ref4) { - value = ref4[key]; - if (data[key] == null) { - set(key, value); - } - } - } - if (compareString < '00001.00011.00021.00003') { - if (data['Remember Your Posts'] == null) { - set('Remember Your Posts', (ref5 = data['Mark Quotes of You']) != null ? ref5 : true); - } - } - if (compareString < '00001.00011.00022.00000') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/^(#?\s*https:\/\/www\.google\.com\/searchbyimage\?image_url=%(?:IMG|URL))%3Fs\.jpg/mg, '$1')); - set('sauces', data['sauces'].replace(/^#?\s*https:\/\/www\.google\.com\/searchbyimage\?image_url=%(?:IMG|T?URL)(?=$|;)/mg, '$&&safe=off')); - } - } - if (compareString < '00001.00011.00022.00002') { - if ((data['Use Recaptcha v1 in Reports'] == null) && data['Use Recaptcha v1'] && !data['Use Recaptcha v2 in Reports']) { - set('Use Recaptcha v1 in Reports', true); - } - } - if (compareString < '00001.00011.00024.00000') { - if ((data['JSON Navigation'] != null) && (data['JSON Index'] == null)) { - set('JSON Index', data['JSON Navigation']); - } - } - if (compareString < '00001.00011.00026.00000') { - if ((data['Oekaki Links'] != null) && (data['Edit Link'] == null)) { - set('Edit Link', data['Oekaki Links']); - } - if (data['Inline Cross-thread Quotes Only'] == null) { - set('Inline Cross-thread Quotes Only', true); - } - } - if (compareString < '00001.00011.00030.00000') { - if (data['Quote Threading'] && (data['Thread Quotes'] == null)) { - set('Thread Quotes', true); - } - } - return changes; - }, - loadSettings: function(data, cb) { - if (data.version.split('.')[0] === '2') { - data = Settings.convertFrom.loadletter(data); - } else if (data.version !== g.VERSION) { - Settings.upgrade(data.Conf, data.version); - } - return $.clear(function(err) { - if (err) { - return cb(err); - } - return $.set(data.Conf, cb); - }); - }, - reset: function() { - if (confirm('Your current settings will be entirely wiped, are you sure?')) { - return $.clear(function(err) { - if (err) { - return $('.imp-exp-result').textContent = 'Import failed due to an error.'; - } else if (confirm('Reset successful. Reload now?')) { - return window.location.reload(); - } - }); - } - }, - filter: function(section) { - var select; - $.extend(section, { - innerHTML: "
    " - }); - select = $('select', section); - $.on(select, 'change', Settings.selectFilter); - return Settings.selectFilter.call(select); - }, - selectFilter: function() { - var div, name, ta; - div = this.nextElementSibling; - if ((name = this.value) !== 'guide') { - $.rmAll(div); - ta = $.el('textarea', { - name: name, - className: 'field', - spellcheck: false - }); - $.get(name, Conf[name], function(item) { - return ta.value = item[name]; - }); - $.on(ta, 'change', $.cb.value); - $.add(div, ta); - return; - } - $.extend(div, { - innerHTML: "
    Filter is disabled.

    Use regular expressions, one per line.
    Lines starting with a # will be ignored.
    For example, /weeaboo/i will filter posts containing the string \`weeaboo\`, case-insensitive.
    MD5 filtering uses exact string matching, not regular expressions.

      You can use these settings with each regular expression, separate them with semicolons:
    • Per boards, separate them with commas. It is global if not specified.
      For example: boards:a,jp;.
    • In case of a global rule, select boards to be excluded from the filter.
      For example: exclude:vg,v;.
    • Filter OPs only along with their threads (\`only\`), replies only (\`no\`), or both (\`yes\`, this is default).
      For example: op:only;, op:no; or op:yes;.
    • Overrule the \`Show Stubs\` setting if specified: create a stub (\`yes\`) or not (\`no\`).
      For example: stub:yes; or stub:no;.
    • Highlight instead of hiding. You can specify a class name to use with a userstyle.
      For example: highlight; or highlight:wallpaper;.
    • Highlighted OPs will have their threads put on top of the board index by default.
      For example: top:yes; or top:no;.

    Note: If you're using the native catalog rather than 4chan X's catalog, 4chan X's filters do not apply there.
    The native catalog has its own separate filter list.

    " - }); - return $('.warning', div).hidden = Conf['Filter']; - }, - sauce: function(section) { - var ta; - $.extend(section, { - innerHTML: "
    Sauce is disabled.
    Lines starting with a # will be ignored.
    You can specify a display text by appending ;text:[text] to the URL.
    You can specify the applicable boards by appending ;boards:[board1],[board2].
    You can specify the applicable file types by appending ;types:[extension1],[extension2].
    You can open links with scripts and popups disabled by appending ;sandbox.
      These parameters will be replaced by their corresponding values:
    • %TURL: Thumbnail URL.
    • %URL: Full image URL.
    • %IMG: Full image URL for GIF, JPG, and PNG; thumbnail URL for other types.
    • %MD5: MD5 hash in base64.
    • %sMD5: MD5 hash in base64 using - and _.
    • %hMD5: MD5 hash in hexadecimal.
    • %name: Original file name.
    • %board: Current board.
    • %%, %semi: Literal % and ;.
    " - }); - $('.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 aa, ab, applyCSS, archBoards, archive, boardID, boardOptions, boardSelect, boards, customCSS, files, i, input, inputs, interval, item, items, k, len1, len2, len3, len4, len5, len6, len7, name, o, q, ref, ref1, ref2, ref3, ref4, ref5, ref6, row, rows, software, ta, table, u, uid, v, warning, withCredentials, z; - $.extend(section, { - innerHTML: "
    Archiver
    404 Redirect is disabled.
    Thread redirectionPost fetchingFile redirection
    Captcha Language
    Choose from list of language codes. Leave blank to autoselect.
    Custom Board Navigation
    New lines will be converted into spaces.

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

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

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

      You can use these settings with each item, separate them with semicolons:
    • Possible items are: name, options (or equivalently email), subject and password.
    • Wrap values of items with quotes, like this: options:"sage".
    • Force values as defaults with the always keyword, for example: options:"sage";always.
    • Select specific boards for an item, separated with commas, for example: options:"sage";boards:jp;always.
    Unread Favicon is disabled.
    Thread Updater is disabled.
    Interval: seconds
    Custom Cooldown Time
    Seconds:
    " - }); - ref = $$('.warning', section); - for (k = 0, len1 = ref.length; k < len1; k++) { - warning = ref[k]; - warning.hidden = Conf[warning.dataset.feature]; - } - items = {}; - inputs = {}; - ref1 = ['captchaLanguage', 'boardnav', 'time', 'backlink', 'fileInfo', 'favicon', 'usercss', 'customCooldown']; - for (q = 0, len2 = ref1.length; q < len2; q++) { - name = ref1[q]; - 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); - if (name in Settings) { - $.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 in Settings && key !== 'usercss') { - 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 (u = 0, len3 = ref2.length; u < len3; u++) { - ref3 = ref2[u], uid = ref3.uid, name = ref3.name, boards = ref3.boards, files = ref3.files, software = ref3.software, withCredentials = ref3.withCredentials; - for (v = 0, len4 = boards.length; v < len4; v++) { - boardID = boards[v]; - o = archBoards[boardID] || (archBoards[boardID] = { - thread: [[], []], - post: [[], []], - file: [[], []] - }); - i = +(!!withCredentials); - archive = [uid != null ? uid : name, name]; - o.thread[i].push(archive); - if (software === 'foolfuuka') { - o.post[i].push(archive); - } - if (indexOf.call(files, boardID) >= 0) { - o.file[i].push(archive); - } - } - } - for (boardID in archBoards) { - o = archBoards[boardID]; - ref4 = ['thread', 'post', 'file']; - for (z = 0, len5 = ref4.length; z < len5; z++) { - item = ref4[z]; - i = o[item][0].length ? 1 : 0; - o[item][i].push([null, 'disabled']); - o[item] = o[item][0].concat(o[item][1]); - } - } - rows = []; - boardOptions = []; - ref5 = Object.keys(archBoards).sort(); - for (aa = 0, len6 = ref5.length; aa < len6; aa++) { - boardID = ref5[aa]; - 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 (ab = 0, len7 = ref6.length; ab < len7; ab++) { - item = ref6[ab]; - $.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, id, select, selectedArchives, type; - selectedArchives = arg.selectedArchives; - for (boardID in selectedArchives) { - data = selectedArchives[boardID]; - for (type in data) { - id = data[type]; - if (select = $("select[data-boardid='" + boardID + "'][data-type='" + type + "']", section)) { - select.value = JSON.stringify(id); - } - } - } - }); - }, - 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', { - value: JSON.stringify(archive[0]), - textContent: archive[1] - })); - } - $.extend(td, { - innerHTML: "" - }); - select = td.firstElementChild; - if (!(select.disabled = length === 1)) { - select.setAttribute('data-boardid', boardID); - select.setAttribute('data-type', type); - $.on(select, 'change', Settings.saveSelectedArchive); - } - $.add(select, options); - return td; - }, - saveSelectedArchive: function() { - return $.get('selectedArchives', Conf['selectedArchives'], (function(_this) { - return function(arg) { - var name1, selectedArchives; - selectedArchives = arg.selectedArchives; - (selectedArchives[name1 = _this.dataset.boardid] || (selectedArchives[name1] = {}))[_this.dataset.type] = JSON.parse(_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, - isVideo: false, - isSpoiler: true, - tag: 'Loop' - } - }; - 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, ref, tbody, tr; - $.extend(section, { - innerHTML: "
    Keybinds are disabled.
    Allowed keys: a-z, 0-9, Ctrl, Shift, Alt, Meta, Enter, Esc, Up, Down, Right, Left.
    Press Backspace to disable a keybind.
    ActionsKeybinds
    " - }); - $('.warning', section).hidden = Conf['Keybinds']; - tbody = $('tbody', section); - items = {}; - inputs = {}; - ref = Config.hotkeys; - for (key in ref) { - arr = ref[key]; - tr = $.el('tr', { - innerHTML: "" + E(arr[1]) + "" - }); - input = $('input', tr); - input.name = key; - input.spellcheck = false; - items[key] = Conf[key]; - inputs[key] = input; - $.on(input, 'keydown', Settings.keybind); - $.add(tbody, tr); - } - return $.get(items, function(items) { - var val; - for (key in items) { - val = items[key]; - inputs[key].value = val; - } - }); - }, - keybind: function(e) { - var key; - if (e.keyCode === 9) { - return; - } - e.preventDefault(); - e.stopPropagation(); - if ((key = Keybinds.keyCode(e)) == null) { - return; - } - this.value = key; - return $.cb.value.call(this); - } - }; - - Main = { - init: function() { - var db, flatten, items, k, key, len1, ref; - if (d.body && !$('title', d.head)) { - return; - } - if (window['4chan X antidup']) { - return; - } - window['4chan X antidup'] = true; - if (location.hostname === 'www.google.com') { - $.get('Captcha Fixes', true, function(arg) { - var enabled; - enabled = arg['Captcha Fixes']; - if (enabled) { - return $.ready(function() { - return Captcha.fixes.init(); - }); - } - }); - return; - } - $.global(function() { - var k, len1, nuke, prop, ref; - nuke = function(obj, prop) { - try { - return Object.defineProperty(obj, prop, { - configurable: false, - get: function() { - throw new Error(); - }, - set: function() { - throw new Error(); - } - }); - } catch (_error) {} - }; - ref = ['atOptions', 'adsterra_key', 'EpmadsConfig', 'epmads_key', 'EpomConfig', 'epom_key', 'exoDocumentProtocol']; - for (k = 0, len1 = ref.length; k < len1; k++) { - prop = ref[k]; - nuke(window, prop); - } - }); - $.on(window, 'beforescriptexecute', function(e) { - var host, ref, ref1; - host = (ref = e.target.src.split('/')[2]) != null ? (ref1 = ref.match(/[^.]+\.[^.]+$/)) != null ? ref1[0] : void 0 : void 0; - if (host === 'bnhtml.com' || host === 'ecpmrocks.com' || host === 'advertisation.com' || host === 'exoclick.com') { - return e.preventDefault(); - } - }); - $.on(d, '4chanXInitFinished', function() { - if (Main.expectInitFinished) { - return delete Main.expectInitFinished; - } else { - new Notice('error', 'Error: Multiple copies of 4chan X are enabled.'); - return $.addClass(doc, 'tainted'); - } - }); - 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); - ref = DataBoard.keys; - for (k = 0, len1 = ref.length; k < len1; k++) { - db = ref[k]; - Conf[db] = { - boards: {} - }; - } - Conf['selectedArchives'] = {}; - Conf['cooldowns'] = {}; - Conf['Index Sort'] = {}; - Conf['Except Archives from Encryption'] = false; - Conf['JSON Navigation'] = true; - Conf['Oekaki Links'] = true; - items = {}; - for (key in Conf) { - items[key] = void 0; - } - items['previousversion'] = void 0; - return $.get(items, function(items) { - return $.asap((function() { - return doc = d.documentElement; - }), function() { - var ref1, val; - if ($.cantSet) { - - } else if (items.previousversion == null) { - Main.ready(function() { - $.set('previousversion', g.VERSION); - return Settings.open(); - }); - } else if (items.previousversion !== g.VERSION) { - Main.upgrade(items); - } - for (key in Conf) { - val = Conf[key]; - Conf[key] = (ref1 = items[key]) != null ? ref1 : val; - } - return Main.initFeatures(); - }); - }); - }, - upgrade: function(items) { - var changes, previousversion; - previousversion = items.previousversion; - changes = Settings.upgrade(items, previousversion); - items.previousversion = changes.previousversion = g.VERSION; - return $.set(changes, function() { - var el, ref; - if ((ref = items['Show Updated Notifications']) != null ? ref : true) { - el = $.el('span', { - innerHTML: "4chan X has been updated to version " + E(g.VERSION) + "." - }); - return new Notice('info', el, 15); - } - }); - }, - initFeatures: function() { - var err, feature, hostname, k, len1, match, name, pathname, ref, ref1, ref2, ref3, search; - hostname = location.hostname, search = location.search; - pathname = location.pathname.split(/\/+/); - if (hostname !== 'www.4chan.org') { - g.BOARD = new Board(pathname[1]); - } - if (hostname === 'boards.4chan.org' || hostname === 'sys.4chan.org' || hostname === 'www.4chan.org') { - $.global(function() { - document.documentElement.classList.add('js-enabled'); - return window.FCX = {}; - }); - Main.jsEnabled = $.hasClass(doc, 'js-enabled'); - } - switch (hostname) { - case 'www.4chan.org': - $.onExists(doc, 'body', function() { - return $.addStyle(Main.cssWWW); - }); - Captcha.replace.init(); - return; - case 'sys.4chan.org': - if (pathname[2] === 'imgboard.php') { - if (/\bmode=report\b/.test(search)) { - Report.init(); - } else if ((match = search.match(/\bres=(\d+)/))) { - $.ready(function() { - var ref; - if (Conf['404 Redirect'] && ((ref = $.id('errmsg')) != null ? ref.textContent : void 0) === 'Error: Specified thread does not exist.') { - return Redirect.navigate('thread', { - boardID: g.BOARD.ID, - postID: +match[1] - }); - } - }); - } - } else if (pathname[2] === 'post') { - PostSuccessful.init(); - } - return; - case 'i.4cdn.org': - if (!(pathname[2] && !/s\.jpg$/.test(pathname[2]))) { - return; - } - $.asap((function() { - return d.readyState !== 'loading'; - }), function() { - var ref, video; - if (Conf['404 Redirect'] && ((ref = d.title) === '4chan - Temporarily Offline' || ref === '4chan - 404 Not Found')) { - return Redirect.navigate('file', { - boardID: g.BOARD.ID, - filename: pathname[pathname.length - 1] - }); - } 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 ((ref = pathname[2]) === 'thread' || ref === 'res') { - g.VIEW = 'thread'; - g.THREADID = +pathname[3]; - } else if ((ref1 = pathname[2]) === 'catalog' || ref1 === 'archive') { - g.VIEW = pathname[2]; - } else if (pathname[2].match(/^\d*$/)) { - g.VIEW = 'index'; - } else { - return; - } - g.threads = new SimpleDict(); - g.posts = new SimpleDict(); - $.onExists(doc, 'body', Main.initStyle); - ref2 = Main.features; - for (k = 0, len1 = ref2.length; k < len1; k++) { - ref3 = ref2[k], name = ref3[0], feature = ref3[1]; - try { - feature.init(); - } catch (_error) { - err = _error; - Main.handleErrors({ - message: "\"" + name + "\" initialization crashed.", - error: err - }); - } - } - return $.ready(Main.initReady); - }, - initStyle: function() { - var keyboard, ref; - if (!Main.isThisPageLegit()) { - 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); - if ($.engine) { - $.addClass(doc, $.engine); - } - $.onExists(doc, '.ad-cnt', function(ad) { - return $.onExists(ad, 'img', function() { - return $.addClass(doc, 'ads-loaded'); - }); - }); - if (Conf['Autohiding Scrollbar']) { - $.addClass(doc, 'autohiding-scrollbar'); - } - $.ready(function() { - if (d.body.clientHeight > doc.clientHeight && (window.innerWidth === doc.clientWidth) !== Conf['Autohiding Scrollbar']) { - Conf['Autohiding Scrollbar'] = !Conf['Autohiding Scrollbar']; - $.set('Autohiding Scrollbar', Conf['Autohiding Scrollbar']); - return $.toggleClass(doc, 'autohiding-scrollbar'); - } - }); - $.addStyle(Main.css, 'fourchanx-css'); - Main.bgColorStyle = $.el('style', { - id: 'fourchanx-bgcolor-css' - }); - keyboard = false; - $.on(d, 'mousedown', function() { - return keyboard = false; - }); - $.on(d, 'keydown', function(e) { - if (e.keyCode === 9) { - return keyboard = true; - } - }); - window.addEventListener('focus', (function() { - return doc.classList.toggle('keyboard-focus', keyboard); - }), true); - 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 bgColor, div, k, len1, styleSheet; - $.rmClass(doc, style); - style = null; - for (k = 0, len1 = styleSheets.length; k < len1; k++) { - styleSheet = styleSheets[k]; - if (styleSheet.href === (mainStyleSheet != null ? mainStyleSheet.href : void 0)) { - style = styleSheet.title.toLowerCase().replace('new', '').trim().replace(/\s+/g, '-'); - break; - } - } - if (style) { - $.addClass(doc, style); - return $.rm(Main.bgColorStyle); - } else { - div = $.el('div', { - className: 'reply' - }); - div.style.cssText = 'position: absolute; visibility: hidden;'; - $.add(d.body, div); - bgColor = window.getComputedStyle(div).backgroundColor; - $.rm(div); - Main.bgColorStyle.textContent = ".dialog, .suboption-list > div:last-of-type {\n background-color: " + bgColor + ";\n}"; - return $.after($.id('fourchanx-css'), Main.bgColorStyle); - } - }; - setStyle(); - if (!mainStyleSheet) { - return; - } - return new MutationObserver(setStyle).observe(mainStyleSheet, { - attributes: true, - attributeFilter: ['href'] - }); - }, - initReady: function() { - var msg, ref, ref1, ref2; - if (g.VIEW === 'thread' && (((ref = d.title) === '4chan - Temporarily Offline' || ref === '4chan - 404 Not Found') || ($('.board') && !$('.opContainer')))) { - ThreadWatcher.set404(g.BOARD.ID, g.THREADID, function() { - if (Conf['404 Redirect']) { - return Redirect.navigate('thread', { - boardID: g.BOARD.ID, - threadID: g.THREADID, - postID: +location.hash.match(/\d+/) - }, "/" + g.BOARD + "/"); - } - }); - return; - } - if ((ref1 = d.title) === '4chan - Temporarily Offline' || ref1 === '4chan - 404 Not Found') { - return; - } - if (((ref2 = g.VIEW) === 'index' || ref2 === 'thread') && !$('.board + *')) { - msg = $.el('div', { - innerHTML: "The page didn't load completely.
    Some features may not work unless you reload." - }); - $.on($('a', msg), 'click', function() { - return location.reload(); - }); - new Notice('warning', msg); - } - if (!(Conf['JSON Index'] && g.VIEW === 'index')) { - return Main.initThread(); - } else { - Main.expectInitFinished = true; - return $.event('4chanXInitFinished'); - } - }, - initThread: function() { - var board, err, errors, k, len1, len2, m, postRoot, posts, q, ref, ref1, scriptData, thread, threadRoot, threads; - if ((board = $('.board'))) { - threads = []; - posts = []; - ref = $$('.board > .thread', board); - for (k = 0, len1 = ref.length; k < len1; k++) { - threadRoot = ref[k]; - thread = new Thread(+threadRoot.id.slice(1), g.BOARD); - threads.push(thread); - ref1 = $$('.thread > .postContainer', threadRoot); - for (q = 0, len2 = ref1.length; q < len2; q++) { - postRoot = ref1[q]; - if ($('.postMessage', postRoot)) { - 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 len3, post, u; - for (u = 0, len3 = posts.length; u < len3; u++) { - post = posts[u]; - QuoteThreading.insert(post); - } - Main.expectInitFinished = true; - return $.event('4chanXInitFinished'); - }); - } else { - Main.expectInitFinished = true; - 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, k, len1, logs; - if (!(errors instanceof Array)) { - error = errors; - } else if (errors.length === 1) { - error = errors[0]; - } - if (error) { - new Notice('error', Main.parseError(error, Main.reportLink([error])), 15); - return; - } - div = $.el('div', { - innerHTML: E(errors.length) + " errors occurred." + Main.reportLink(errors).innerHTML + " [show]" - }); - $.on(div.lastElementChild, 'click', function() { - var ref; - return ref = this.textContent === 'show' ? ['hide', false] : ['show', true], this.textContent = ref[0], logs.hidden = ref[1], ref; - }); - logs = $.el('div', { - hidden: true - }); - for (k = 0, len1 = errors.length; k < len1; k++) { - error = errors[k]; - $.add(logs, Main.parseError(error)); - } - return new Notice('error', [div, logs], 30); - }, - parseError: function(data, reportLink) { - var context, error, lines, message, ref, ref1; - c.error(data.message, data.error.stack); - message = $.el('div', { - innerHTML: E(data.message) + (reportLink ? reportLink.innerHTML : "") - }); - error = $.el('div', { - textContent: (data.error.name || 'Error') + ": " + (data.error.message || 'see console for details') - }); - lines = ((ref = data.error.stack) != null ? (ref1 = ref.match(/\d+(?=:\d+\)?$)/mg)) != null ? ref1.join().replace(/^/, ' at ') : void 0 : void 0) || ''; - context = $.el('div', { - textContent: "(4chan X ccd0 v" + g.VERSION + " userscript on " + $.engine + lines + ")" - }); - return [message, error, context]; - }, - reportLink: function(errors) { - var data, details, ref, title, url; - data = errors[0]; - title = data.message; - if (errors.length > 1) { - title += " (+" + (errors.length - 1) + " other errors)"; - } - details = "[Please describe the steps needed to reproduce this error.]\n\nScript: 4chan X ccd0 v" + g.VERSION + " userscript\nUser agent: " + navigator.userAgent + "\nURL: " + location.href + "\n\n" + data.error + "\n" + (((ref = data.error.stack) != null ? ref.replace(data.error.toString(), '').trim() : void 0) || ''); - details = details.replace(/file:\/{3}.+\//g, ''); - url = "https://gitreports.com/issue/ccd0/4chan-x?issue_title=" + (encodeURIComponent(title)) + "&details=" + (encodeURIComponent(details)); - return { - innerHTML: " [report]" - }; - }, - 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: "/*!\n" + -" * Font Awesome 4.5.0 by @davegandy - http://fontawesome.io - @fontawesome\n" + +boards: +"/*!\n" + +" * Font Awesome 4.6.1 by @davegandy - http://fontawesome.io - @fontawesome\n" + " * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)\n" + " */\n" + "@font-face {\n" + " font-family: FontAwesome;\n" + -" src: url('data:application/font-woff;base64,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') format('woff');\n" + +" src: url('data:application/font-woff;base64,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') format('woff');\n" + " font-weight: 400;\n" + " font-style: normal;\n" + "}\n" + -".fa::before {\n" + -" font-family: FontAwesome;\n" + -" font-weight: 400;\n" + -" font-style: normal;\n" + -" -webkit-font-smoothing: antialiased;\n" + -" text-decoration: inherit;\n" + -" speak: none;\n" + -" display: inline-block;\n" + -" font-size: 13px;\n" + -" visibility: visible;\n" + -"}\n" + -":root:not(.shortcut-icons) #shortcuts .fa::before {\n" + -" display: none;\n" + -"}\n" + -":root.shortcut-icons #shortcuts .fa::before {\n" + -" font-size: 15px !important;\n" + -" margin-top: -3px !important;\n" + -" position: relative;\n" + -" top: 1px;\n" + -"}\n" + -":root.shortcut-icons #shortcuts .fa, .menu-button .fa {\n" + -" font-size: 0;\n" + -" visibility: hidden;\n" + -"}\n" + -":root.shortcut-icons .shortcut.brackets-wrap::after,\n" + -":root.shortcut-icons .shortcut.brackets-wrap::before {\n" + -" display: none;\n" + -"}\n" + -":root.shortcut-icons #shortcuts a .fa,\n" + -".menu-button .fa,\n" + -".hide-reply-button .fa,\n" + -".hide-thread-button .fa {\n" + -" display: inline;\n" + -"}\n" + ".fa-glass:before {content: \"\\f000\";}\n" + ".fa-music:before {content: \"\\f001\";}\n" + ".fa-search:before {content: \"\\f002\";}\n" + @@ -19237,6 +1099,63 @@ ".fa-bluetooth:before {content: \"\\f293\";}\n" + ".fa-bluetooth-b:before {content: \"\\f294\";}\n" + ".fa-percent:before {content: \"\\f295\";}\n" + +".fa-gitlab:before {content: \"\\f296\";}\n" + +".fa-wpbeginner:before {content: \"\\f297\";}\n" + +".fa-wpforms:before {content: \"\\f298\";}\n" + +".fa-envira:before {content: \"\\f299\";}\n" + +".fa-universal-access:before {content: \"\\f29a\";}\n" + +".fa-wheelchair-alt:before {content: \"\\f29b\";}\n" + +".fa-question-circle-o:before {content: \"\\f29c\";}\n" + +".fa-blind:before {content: \"\\f29d\";}\n" + +".fa-audio-description:before {content: \"\\f29e\";}\n" + +".fa-volume-control-phone:before {content: \"\\f2a0\";}\n" + +".fa-braille:before {content: \"\\f2a1\";}\n" + +".fa-assistive-listening-systems:before {content: \"\\f2a2\";}\n" + +".fa-asl-interpreting:before, .fa-american-sign-language-interpreting:before {content: \"\\f2a3\";}\n" + +".fa-deafness:before, .fa-hard-of-hearing:before, .fa-deaf:before {content: \"\\f2a4\";}\n" + +".fa-glide:before {content: \"\\f2a5\";}\n" + +".fa-glide-g:before {content: \"\\f2a6\";}\n" + +".fa-signing:before, .fa-sign-language:before {content: \"\\f2a7\";}\n" + +".fa-low-vision:before {content: \"\\f2a8\";}\n" + +".fa-viadeo:before {content: \"\\f2a9\";}\n" + +".fa-viadeo-square:before {content: \"\\f2aa\";}\n" + +".fa-snapchat:before {content: \"\\f2ab\";}\n" + +".fa-snapchat-ghost:before {content: \"\\f2ac\";}\n" + +".fa-snapchat-square:before {content: \"\\f2ad\";}\n" + +".fa::before {\n" + +" font-family: FontAwesome;\n" + +" font-weight: 400;\n" + +" font-style: normal;\n" + +" -webkit-font-smoothing: antialiased;\n" + +" text-decoration: inherit;\n" + +" speak: none;\n" + +" display: inline-block;\n" + +" font-size: 13px;\n" + +" visibility: visible;\n" + +"}\n" + +":root:not(.shortcut-icons) #shortcuts .fa::before {\n" + +" display: none;\n" + +"}\n" + +":root.shortcut-icons #shortcuts .fa::before {\n" + +" font-size: 15px !important;\n" + +" margin-top: -3px !important;\n" + +" position: relative;\n" + +" top: 1px;\n" + +"}\n" + +":root.shortcut-icons #shortcuts .fa, .menu-button .fa {\n" + +" font-size: 0;\n" + +" visibility: hidden;\n" + +"}\n" + +":root.shortcut-icons .shortcut.brackets-wrap::after,\n" + +":root.shortcut-icons .shortcut.brackets-wrap::before {\n" + +" display: none;\n" + +"}\n" + +":root.shortcut-icons #shortcuts a .fa,\n" + +".menu-button .fa,\n" + +".hide-reply-button .fa,\n" + +".hide-thread-button .fa {\n" + +" display: inline;\n" + +"}\n" + ".fa-spin::before {\n" + " -webkit-animation:spin 2s infinite linear;\n" + " -moz-animation:spin 2s infinite linear;\n" + @@ -20093,7 +2012,7 @@ ":root.float #updater {\n" + " padding: 0px 3px;\n" + "}\n" + -":root:not(.float) #updater {\n" + +":root:not(.float).shortcut-icons #updater {\n" + " display: inline-block;\n" + " min-width: 12pt;\n" + " text-align: right;\n" + @@ -21046,75 +2965,6 @@ ".boardSubtitle[contenteditable=\"true\"] {\n" + " cursor: text !important;\n" + "}\n" + -"/* Link Title Favicons */\n" + -".linkify.audio {\n" + -" 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;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.clyp {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAwUExURTSY22ey5E2l4KbS75rM7Y3F64C/6f///8zl9nS45r/f9PL5/UGe3bPY8Vqr4v///wNjrzUAAAABYktHRA8YugDZAAAAB3RJTUUH4AINEi85AIH95AAAAE9JREFUCNdjYMAGGBWgDGYHCM2a3hkAZmi0dzSBaKaO9o5moCqmLiCjYzNQyw4QowIodQzI6E0AKcpo72gE6+Jyb1kAMehUA9RktgdYbQYAjGIVNGGXBJkAAAAASUVORK5CYII=') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.dailymotion {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAnUExURQBk3ff6/trp+kKO5wZt3xx54q7P9Ozz/IS17zOG5WKh653E8sbc9/GbbcoAAABZSURBVAjXY2BAASyhDhAGc9oECMOjyAAiESEEYrBYpLWBGcwHxcvBjDDxHelghpF0yDQwY3kVgweEUeEQDWbMEepqAjO8FMsLIeYsU8o+BrbCdWboTAe4AwALXxWGjW41FwAAAABJRU5ErkJggg==') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.gfycat {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAjVBMVEWn3gCo3gSr3w2t4BSu4Bav4Ri35C+45DK45DO55DXA50rA50vB50zC6E/D6FTF6VjG6VvL62vN7G/P7XbQ7XfW74vY8JDa8ZTe8qDe8qLf86Pi9Kzj9K7k9LHp9sDp98Lq98Ps+Mr0++L5/O75/fD6/fH6/fL6/fP7/fT7/fb8/ff8/vj8/vn+/v7///91X4cfAAAAcklEQVR42o3M2xKBUACF4aVQckrIuRJK6H//x2sme4/MuPDfre9i6c/Cc3U5Dj87BuAxsXvGu6JvIIXEHRWwNHCHQNrCzkAFkbSBg4EM8i+Yw7PXBa3zRfuxVyf/Bis7nKwGKAcWxgC8prI5Sc315OlnDfzpDar2S9/oAAAAAElFTkSuQmCC') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.gist {\n" + -" 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;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.image {\n" + -" 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;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.installgentoo {\n" + -" 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;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.liveleak {\n" + -" 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;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.pastebin {\n" + -" 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;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.soundcloud {\n" + -" 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;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.twitchtv {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAYUExURf///2RBpWRBpWRBpWRBpWRBpWRBpf///+zQyUYAAAAGdFJOUwFdZX0lTzs4r5oAAAABYktHRAcWYYjrAAAAB3RJTUUH4AINEi42iSXRNAAAAD1JREFUCNdjYEiDAAZGGIMtjQEEUBlMCWoEGci6mGEMsxQgIy0BiB3AjLS0FAYQIw0kwABipoI1AhkBQBIAFCIXxiHgq80AAAAASUVORK5CYII=') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.twitter {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAEsUExURf///1Cf21Gg3FGi31Gh3VKj4FGh3lKj4VKk4lKl41Ol5FOn51Sp6VSo6FOn5lCf21Gg3FGh3VGi31Gi31Gh3lGg3FGg3FGg3FGg3FGh3lGg3FGi31Kk4lKj4FGh3lGi31Kk4lGh3lGg3FGh3lOm5FOm5VGi31Kj4VSo6FGi31Gh3VGg3FKj4FOn51Gi31So6FWr7VOl5FGi31On51Sq6lKk4lOo51Sp6VOm5FSq61Ws7VOn51Oo51Sq61Ol5FOm5FSq61Wr7VOo51On51Sr7FWs7VSp6lGg3FGh3VOm5FWr7VSp6lKj4VOm5FSo6FSr7FWs7VWs7VWr7VSq6lOo51Om5FOo51So6FOm5VOl5FSq61Ws7VSr7FSp6lSp6VWs7lWr7VKk4lSq6v///6E3MNsAAABVdFJOUwAAAAAAAAAAAAAAAAAAAB0Ii+3xnBVTJhfsMKb+qTEp9GwBF/7lLAbo0m4pLkUTdvk2Ev3+EZnOBo/3Z8ffCRzH/D0OqPxiLnvx3UI8m9n1++GwXQZNS29BAAAAAWJLR0QAiAUdSAAAAAd0SU1FB+ACDRIwBwy67tEAAADKSURBVBjTY2BAB4xogIGRH8IQEBQSFhEVE2eQkJQC8ZmkQ8PCI2Rk5RjkIxUUlRgZlVWioqNjYlXVGNQ14iI1tbR14qLj4+MTdJkZ9PQNosJCE0OjgPz4KEMWBiPjhPiEmKQokIJ4E1MmBmazhHg4MGdlYmCzsLSC8ROsmRkZmFht4Eps7ViADmOzd4DyHZ2YmYACTOzOLmATXd04mIBOd/eQ9owFCXh5c7KB/MLi4+vnHxAYFBzCwcYEEmBi5uLm4eHl42RmAnsSAMZBLgZiFUQ5AAAAAElFTkSuQmCC') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.video {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QAxgDGAP8nNqN7AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gMZBjQQLEEqGwAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAA5SURBVDjLY2AYaMDIwMDwn1JD/lPCZhpwL+B1wf///ykzgBhDiAoDfIYQZQAjIyP5BuDTPJqQqAQAvW0ZAMk8+EEAAAAASUVORK5CYII=') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.vimeo {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAYFBMVEUAAAAIdZUKh6sLlLkLmr4LmsAMp88NrdYVW3MZj7Acstkrt9s1e5E7vN5EfI9JvdtKwuBijp5kpbl30eiDt8aG1uqRr7qTyNehxM+k4PCy3enB3OTg6Ovv9PXw+fz////L9U5WAAAAAXRSTlMAQObYZgAAAIFJREFUeNplz90OwiAMBWAQpAoyxclkP3je/y0H2AQXz0WT8100rRD6kNI9/cRroemQL3hXhoujZYj4OHoAmBvYGcBISwbWBvfXCrytnIDUQMkbsBpagMA7zhtQdyTFQAmIG7IkYniiZuh3XGsPqoOZkMOJOpAcLqUzNFGGu/57fwc1hgtp0mVSyQAAAABJRU5ErkJggg==') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.vine {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAHCUExURQAAAAC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+j////54tRLAAAACUdFJOUwAAAEK+9/e+QQIDAwEqzskfUZmUNHz2mrT++V1w+f5tCanNFUDwfEjtjAyyvg027Hki27QMBJzaHE/1+FkNsN0iZvv6bxyAlB589lQeyud0KB8PQO+ZBUrc+eXgcRG/3CoATe316Wxw/P6BAgBt+fp4IAwh0d4zM9q7Fm76qi605EMSrvfX/PRtAivF9IAJNMLxhA2KYlJ9AAAAAWJLR0SVCGB6gwAAAAd0SU1FB+ACDRI2MOJd7FgAAADrSURBVBjTLY9VWwJgGEPfiYWBha2YYHcHditgd3d3odjdivvBfgK727nYsyPiCrw03j6+fv6AaAMCgyAI1lElJBQSFh6hBxDJqOiY2Lh4SEKiIQlITmFqWrqRJkhGJrOA7Bzm5uUXsBBSVMySUpSVs6KyqrqmFmKuY30D0NjU3NLa1t6h9jvZ1Q30WGi19fb1KzAwyKFhYGSUY+MTkwpMTXNmFpibX+Di0rICWFldW9/A5tb2zu7ePtTrg0MeHePklPYzuDRw7uDF5RWvbwC32O0d7x8en55f4DHF6xv5/vHp6f/k6/vH+evuf1LAObptvSvrAAAAAElFTkSuQmCC') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.vocaroo {\n" + -" 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;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.youtube {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAYAAABr5z2BAAABIklEQVQoz53LvUrDUBjG8bOoOammSf1IoBSvoCB4JeIqOHgBLt6AIMRBBQelWurQ2kERnMRBsBUcIp5FJSBI5oQsJVkkUHh8W0o5nhaFHvjBgef/Mq+Q46RJBMkI/vE+aOus956tnEswIZe1LV0QyJ5sE2GzgZfVMtRNIdiDpccEssdlB1mW4bvTwdvWJtRdErM7U+8S/FJykCRJX5qm+KpVce8UMNLRLbulz4iSjTAMh6Iowsd5BeNadp3nUF0VlxAEwZBotXC0Usa4ll3meZdA1iguwvf9vpvDA2wvmKgYGtSud8suDB4TyGr2PF49D/vra9jRZ1BVdknMzgwuCGSnZEObwu6sBnVTCHZiaC7BhFx2PKdxUidiAH/4lLo9Mv0DELVs9qsOHXwAAAAASUVORK5CYII=') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + "/* Embedding */\n" + "#embedding {\n" + " padding: 1px 4px 1px 4px;\n" + @@ -21874,6 +3724,75 @@ "{\n" + " background-image: url(\"data:image/svg+xml,\");\n" + "}\n" + +"/* Link Title Favicons */\n" + +".linkify.audio {\n" + +" 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;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.clyp {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAwUExURTSY22ey5E2l4KbS75rM7Y3F64C/6f///8zl9nS45r/f9PL5/UGe3bPY8Vqr4v///wNjrzUAAAABYktHRA8YugDZAAAAB3RJTUUH4AINEi85AIH95AAAAE9JREFUCNdjYMAGGBWgDGYHCM2a3hkAZmi0dzSBaKaO9o5moCqmLiCjYzNQyw4QowIodQzI6E0AKcpo72gE6+Jyb1kAMehUA9RktgdYbQYAjGIVNGGXBJkAAAAASUVORK5CYII=') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.dailymotion {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAnUExURQBk3ff6/trp+kKO5wZt3xx54q7P9Ozz/IS17zOG5WKh653E8sbc9/GbbcoAAABZSURBVAjXY2BAASyhDhAGc9oECMOjyAAiESEEYrBYpLWBGcwHxcvBjDDxHelghpF0yDQwY3kVgweEUeEQDWbMEepqAjO8FMsLIeYsU8o+BrbCdWboTAe4AwALXxWGjW41FwAAAABJRU5ErkJggg==') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.gfycat {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAjVBMVEWn3gCo3gSr3w2t4BSu4Bav4Ri35C+45DK45DO55DXA50rA50vB50zC6E/D6FTF6VjG6VvL62vN7G/P7XbQ7XfW74vY8JDa8ZTe8qDe8qLf86Pi9Kzj9K7k9LHp9sDp98Lq98Ps+Mr0++L5/O75/fD6/fH6/fL6/fP7/fT7/fb8/ff8/vj8/vn+/v7///91X4cfAAAAcklEQVR42o3M2xKBUACF4aVQckrIuRJK6H//x2sme4/MuPDfre9i6c/Cc3U5Dj87BuAxsXvGu6JvIIXEHRWwNHCHQNrCzkAFkbSBg4EM8i+Yw7PXBa3zRfuxVyf/Bis7nKwGKAcWxgC8prI5Sc315OlnDfzpDar2S9/oAAAAAElFTkSuQmCC') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.gist {\n" + +" 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;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.image {\n" + +" 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;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.installgentoo {\n" + +" 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;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.liveleak {\n" + +" 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;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.pastebin {\n" + +" 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;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.soundcloud {\n" + +" 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;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.twitchtv {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAYUExURf///2RBpWRBpWRBpWRBpWRBpWRBpf///+zQyUYAAAAGdFJOUwFdZX0lTzs4r5oAAAABYktHRAcWYYjrAAAAB3RJTUUH4AINEi42iSXRNAAAAD1JREFUCNdjYEiDAAZGGIMtjQEEUBlMCWoEGci6mGEMsxQgIy0BiB3AjLS0FAYQIw0kwABipoI1AhkBQBIAFCIXxiHgq80AAAAASUVORK5CYII=') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.twitter {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAEsUExURf///1Cf21Gg3FGi31Gh3VKj4FGh3lKj4VKk4lKl41Ol5FOn51Sp6VSo6FOn5lCf21Gg3FGh3VGi31Gi31Gh3lGg3FGg3FGg3FGg3FGh3lGg3FGi31Kk4lKj4FGh3lGi31Kk4lGh3lGg3FGh3lOm5FOm5VGi31Kj4VSo6FGi31Gh3VGg3FKj4FOn51Gi31So6FWr7VOl5FGi31On51Sq6lKk4lOo51Sp6VOm5FSq61Ws7VOn51Oo51Sq61Ol5FOm5FSq61Wr7VOo51On51Sr7FWs7VSp6lGg3FGh3VOm5FWr7VSp6lKj4VOm5FSo6FSr7FWs7VWs7VWr7VSq6lOo51Om5FOo51So6FOm5VOl5FSq61Ws7VSr7FSp6lSp6VWs7lWr7VKk4lSq6v///6E3MNsAAABVdFJOUwAAAAAAAAAAAAAAAAAAAB0Ii+3xnBVTJhfsMKb+qTEp9GwBF/7lLAbo0m4pLkUTdvk2Ev3+EZnOBo/3Z8ffCRzH/D0OqPxiLnvx3UI8m9n1++GwXQZNS29BAAAAAWJLR0QAiAUdSAAAAAd0SU1FB+ACDRIwBwy67tEAAADKSURBVBjTY2BAB4xogIGRH8IQEBQSFhEVE2eQkJQC8ZmkQ8PCI2Rk5RjkIxUUlRgZlVWioqNjYlXVGNQ14iI1tbR14qLj4+MTdJkZ9PQNosJCE0OjgPz4KEMWBiPjhPiEmKQokIJ4E1MmBmazhHg4MGdlYmCzsLSC8ROsmRkZmFht4Eps7ViADmOzd4DyHZ2YmYACTOzOLmATXd04mIBOd/eQ9owFCXh5c7KB/MLi4+vnHxAYFBzCwcYEEmBi5uLm4eHl42RmAnsSAMZBLgZiFUQ5AAAAAElFTkSuQmCC') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.video {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QAxgDGAP8nNqN7AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gMZBjQQLEEqGwAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAA5SURBVDjLY2AYaMDIwMDwn1JD/lPCZhpwL+B1wf///ykzgBhDiAoDfIYQZQAjIyP5BuDTPJqQqAQAvW0ZAMk8+EEAAAAASUVORK5CYII=') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.vimeo {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAYFBMVEUAAAAIdZUKh6sLlLkLmr4LmsAMp88NrdYVW3MZj7Acstkrt9s1e5E7vN5EfI9JvdtKwuBijp5kpbl30eiDt8aG1uqRr7qTyNehxM+k4PCy3enB3OTg6Ovv9PXw+fz////L9U5WAAAAAXRSTlMAQObYZgAAAIFJREFUeNplz90OwiAMBWAQpAoyxclkP3je/y0H2AQXz0WT8100rRD6kNI9/cRroemQL3hXhoujZYj4OHoAmBvYGcBISwbWBvfXCrytnIDUQMkbsBpagMA7zhtQdyTFQAmIG7IkYniiZuh3XGsPqoOZkMOJOpAcLqUzNFGGu/57fwc1hgtp0mVSyQAAAABJRU5ErkJggg==') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.vine {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAHCUExURQAAAAC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+j////54tRLAAAACUdFJOUwAAAEK+9/e+QQIDAwEqzskfUZmUNHz2mrT++V1w+f5tCanNFUDwfEjtjAyyvg027Hki27QMBJzaHE/1+FkNsN0iZvv6bxyAlB589lQeyud0KB8PQO+ZBUrc+eXgcRG/3CoATe316Wxw/P6BAgBt+fp4IAwh0d4zM9q7Fm76qi605EMSrvfX/PRtAivF9IAJNMLxhA2KYlJ9AAAAAWJLR0SVCGB6gwAAAAd0SU1FB+ACDRI2MOJd7FgAAADrSURBVBjTLY9VWwJgGEPfiYWBha2YYHcHditgd3d3odjdivvBfgK727nYsyPiCrw03j6+fv6AaAMCgyAI1lElJBQSFh6hBxDJqOiY2Lh4SEKiIQlITmFqWrqRJkhGJrOA7Bzm5uUXsBBSVMySUpSVs6KyqrqmFmKuY30D0NjU3NLa1t6h9jvZ1Q30WGi19fb1KzAwyKFhYGSUY+MTkwpMTXNmFpibX+Di0rICWFldW9/A5tb2zu7ePtTrg0MeHePklPYzuDRw7uDF5RWvbwC32O0d7x8en55f4DHF6xv5/vHp6f/k6/vH+evuf1LAObptvSvrAAAAAElFTkSuQmCC') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.vocaroo {\n" + +" 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;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.youtube {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAYAAABr5z2BAAABIklEQVQoz53LvUrDUBjG8bOoOammSf1IoBSvoCB4JeIqOHgBLt6AIMRBBQelWurQ2kERnMRBsBUcIp5FJSBI5oQsJVkkUHh8W0o5nhaFHvjBgef/Mq+Q46RJBMkI/vE+aOus956tnEswIZe1LV0QyJ5sE2GzgZfVMtRNIdiDpccEssdlB1mW4bvTwdvWJtRdErM7U+8S/FJykCRJX5qm+KpVce8UMNLRLbulz4iSjTAMh6Iowsd5BeNadp3nUF0VlxAEwZBotXC0Usa4ll3meZdA1iguwvf9vpvDA2wvmKgYGtSud8suDB4TyGr2PF49D/vra9jRZ1BVdknMzgwuCGSnZEObwu6sBnVTCHZiaC7BhFx2PKdxUidiAH/4lLo9Mv0DELVs9qsOHXwAAAAASUVORK5CYII=') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + "/* XXX Moved to end of stylesheet to avoid breaking whole stylesheet in Maxthon. */\n" + "@supports (text-decoration-style: dashed) or (-moz-text-decoration-style: dashed) {\n" + " .quotelink.forwardlink,\n" + @@ -21883,13 +3802,18839 @@ " text-decoration-style: dashed;\n" + " border-bottom: none;\n" + " }\n" + -"}", - cssWWW: "#captcha-cnt {\n" + +"}\n", + +report: +"#g-recaptcha,\n" + +":root:not(.js-enabled) #captchaContainerAlt {\n" + " height: auto;\n" + -"}", - features: [['Polyfill', Polyfill], ['Normalize URL', NormalizeURL], ['Captcha Configuration', Captcha.replace], ['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], ['Thread Links', ThreadLinks], ['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], ['Cooldown', QR.cooldown], ['Pass Link', PassLink], ['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], ['Edit Link', QR.oekaki.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], ['Flash Features', Flash], ['Reply Pruning', ReplyPruning]] +"}\n" + +"#captchaContainerAlt td:nth-child(2) {\n" + +" display: table-cell !important;\n" + +"}\n", + +www: +"#captcha-cnt {\n" + +" height: auto;\n" + +"}\n" + +}; + +$ = (function() { + var $, + 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; }; + + $ = function(selector, root) { + if (root == null) { + root = d.body; + } + return root.querySelector(selector); }; - Main.init(); + $.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: "4chan X was blocked from loading the following URL:

    [More info]" + }); + $('span', message).textContent = (/^\/\//.test(url) ? location.protocol : '') + url; + return new Notice('warning', message, 30, function() { + return delete blockedURLs[url]; + }); + }; + return function(url, options, extra) { + var err, event, form, i, len, r, ref, ref1, type, upCallbacks, whenModified; + if (options == null) { + options = {}; + } + if (extra == null) { + extra = {}; + } + type = extra.type, whenModified = extra.whenModified, upCallbacks = extra.upCallbacks, form = extra.form; + url = url.replace(/^((?:https?:)?\/\/(?:\w+\.)?4c(?:ha|d)n\.org)\/adv\//, '$1//adv/'); + r = new XMLHttpRequest(); + type || (type = form && 'post' || 'get'); + try { + r.open(type, url, true); + } catch (_error) { + err = _error; + blockedError(url); + ref = ['error', 'loadend']; + for (i = 0, len = ref.length; i < len; i++) { + event = ref[i]; + r["on" + event] = options["on" + event]; + $.queueTask($.event, event, null, r); + } + return; + } + if (whenModified) { + if (((ref1 = lastModified[whenModified]) != null ? ref1[url] : void 0) != null) { + r.setRequestHeader('If-Modified-Since', lastModified[whenModified][url]); + } + $.on(r, 'load', function() { + return (lastModified[whenModified] || (lastModified[whenModified] = {}))[url] = r.getResponseHeader('Last-Modified'); + }); + } + if (/\.json$/.test(url)) { + if (options.responseType == null) { + options.responseType = 'json'; + } + } + $.extend(r, options); + if (options.responseType === 'json' && r.responseType !== 'json' && delete r.response) { + Object.defineProperty(r, 'response', { + configurable: true, + enumerable: true, + get: function() { + return JSON.parse(r.responseText); + } + }); + } + $.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, true); + }); + } 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 fn1, i, len, ref; + this.evt = e; + ref = this.callbacks; + fn1 = (function(_this) { + return function(cb) { + return $.queueTask(function() { + return cb.call(_this, e, false); + }); + }; + })(this); + for (i = 0, len = ref.length; i < len; i++) { + cb = ref[i]; + fn1(cb); + } + 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, cb) { + var el, observer; + if (el = $(selector, root)) { + return cb(el); + } + if ($.engine === 'edge' && d.readyState === 'loading') { + $.asap((function() { + return d.readyState !== 'loading' || $(selector, root); + }), function() { + return $.onExists(root, selector, cb); + }); + return; + } + observer = new MutationObserver(function() { + if (el = $(selector, root)) { + observer.disconnect(); + return cb(el); + } + }); + return observer.observe(root, { + childList: true, + subtree: true + }); + }; + + $.addStyle = function(css, id, test) { + var style; + if (test == null) { + test = 'head'; + } + style = $.el('style', { + textContent: css + }); + if (id != null) { + style.id = id; + } + $.onExists(doc, 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 != null ? el.remove() : void 0; + }; + + $.rmAll = function(root) { + return root.textContent = null; + }; + + $.tn = function(s) { + return d.createTextNode(s); + }; + + $.frag = function() { + return d.createDocumentFragment(); + }; + + $.nodes = function(nodes) { + var frag, i, len, node; + 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, properties2) { + var el; + el = d.createElement(tag); + if (properties) { + $.extend(el, properties); + } + if (properties2) { + $.extend(el, properties2); + } + 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 + })); + }; + + (function() { + var clone, err, ref, unsafeConstructors; + if (!(/PaleMoon\//.test(navigator.userAgent) && +(typeof GM_info !== "undefined" && GM_info !== null ? (ref = GM_info.version) != null ? ref.split('.')[0] : void 0 : void 0) >= 2 && typeof cloneInto === 'undefined')) { + return; + } + try { + return new CustomEvent('x', { + detail: {} + }); + } catch (_error) { + err = _error; + unsafeConstructors = { + Object: unsafeWindow.Object, + Array: unsafeWindow.Array + }; + clone = function(obj) { + var constructor, key, obj2, val; + if ((obj != null) && typeof obj === 'object' && (constructor = unsafeConstructors[obj.constructor.name])) { + obj2 = new constructor(); + for (key in obj) { + val = obj[key]; + obj2[key] = clone(val); + } + return obj2; + } else { + return obj; + } + }; + return $.event = function(event, detail, root) { + if (root == null) { + root = d; + } + return root.dispatchEvent(new CustomEvent(event, { + bubbles: true, + detail: clone(detail) + })); + }; + } + })(); + + $.open = typeof GM_openInTab !== "undefined" && GM_openInTab !== null ? GM_openInTab : function(url) { + return window.open(url, '_blank'); + }; + + $.debounce = function(wait, fn) { + var args, exec, lastCall, that, timeout; + lastCall = 0; + timeout = null; + that = null; + args = null; + exec = function() { + lastCall = Date.now(); + return fn.apply(that, args); + }; + return function() { + args = arguments; + that = this; + if (lastCall < Date.now() - wait) { + return exec(); + } + clearTimeout(timeout); + return timeout = setTimeout(exec, wait); + }; + }; + + $.queueTask = (function() { + var execTask, taskChannel, taskQueue; + taskQueue = []; + execTask = function() { + var args, func, task; + task = taskQueue.shift(); + func = task[0]; + args = Array.prototype.slice.call(task, 1); + return func.apply(func, args); + }; + if (window.MessageChannel) { + taskChannel = new MessageChannel(); + taskChannel.port1.onmessage = execTask; + return function() { + taskQueue.push(arguments); + return taskChannel.port2.postMessage(null); + }; + } else { + return function() { + taskQueue.push(arguments); + return setTimeout(execTask, 0); + }; + } + })(); + + $.globalEval = function(code) { + var script; + script = $.el('script', { + textContent: code + }); + $.add(d.head || doc, script); + return $.rm(script); + }; + + $.global = function(fn) { + if (doc) { + return $.globalEval("(" + fn + ")();"); + } else { + return fn(); + } + }; + + $.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; + }; + + $.engine = (function() { + if (/Edge\//.test(navigator.userAgent)) { + return 'edge'; + } + if (/Chrome\//.test(navigator.userAgent)) { + return 'blink'; + } + if (/WebKit\//.test(navigator.userAgent)) { + return 'webkit'; + } + if (/Gecko\/|Goanna/.test(navigator.userAgent)) { + return 'gecko'; + } + })(); + + $.platform = 'userscript'; + + try { + localStorage.getItem('x'); + $.hasStorage = true; + } catch (_error) { + $.hasStorage = false; + } + + $.item = function(key, val) { + var item; + item = {}; + item[key] = val; + return item; + }; + + $.syncing = {}; + + if (typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null) { + $.getValue = GM_getValue; + $.listValues = function() { + return GM_listValues(); + }; + } else if ($.hasStorage) { + $.getValue = function(key) { + return localStorage[key]; + }; + $.listValues = function() { + var key, results; + results = []; + for (key in localStorage) { + if (key.slice(0, g.NAMESPACE.length) === g.NAMESPACE) { + results.push(key); + } + } + return results; + }; + } else { + $.getValue = function() {}; + $.listValues = function() { + return []; + }; + } + + if (typeof GM_addValueChangeListener !== "undefined" && GM_addValueChangeListener !== null) { + $.setValue = GM_setValue; + $.deleteValue = GM_deleteValue; + } else if (typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null) { + $.oldValue = {}; + $.setValue = function(key, val) { + GM_setValue(key, val); + if (key in $.syncing) { + $.oldValue[key] = val; + if ($.hasStorage) { + return localStorage[key] = val; + } + } + }; + $.deleteValue = function(key) { + GM_deleteValue(key); + if (key in $.syncing) { + delete $.oldValue[key]; + if ($.hasStorage) { + return localStorage.removeItem(key); + } + } + }; + if (!$.hasStorage) { + $.cantSync = true; + } + } else if ($.hasStorage) { + $.oldValue = {}; + $.setValue = function(key, val) { + if (key in $.syncing) { + $.oldValue[key] = val; + } + return localStorage[key] = val; + }; + $.deleteValue = function(key) { + if (key in $.syncing) { + delete $.oldValue[key]; + } + return localStorage.removeItem(key); + }; + } else { + $.setValue = function() {}; + $.deleteValue = function() {}; + $.cantSync = $.cantSet = true; + } + + if (typeof GM_addValueChangeListener !== "undefined" && GM_addValueChangeListener !== null) { + $.sync = function(key, cb) { + return $.syncing[key] = GM_addValueChangeListener(g.NAMESPACE + key, function(key2, oldValue, newValue, remote) { + if (remote) { + if (newValue !== void 0) { + newValue = JSON.parse(newValue); + } + return cb(newValue, key); + } + }); + }; + $.forceSync = function() {}; + } else if ((typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null) || $.hasStorage) { + $.sync = function(key, cb) { + key = g.NAMESPACE + key; + $.syncing[key] = cb; + return $.oldValue[key] = $.getValue(key); + }; + (function() { + var onChange; + onChange = function(arg) { + var cb, key, newValue; + key = arg.key, newValue = arg.newValue; + if (!(cb = $.syncing[key])) { + return; + } + if (newValue != null) { + if (newValue === $.oldValue[key]) { + return; + } + $.oldValue[key] = newValue; + return cb(JSON.parse(newValue), key.slice(g.NAMESPACE.length)); + } else { + if ($.oldValue[key] == null) { + return; + } + delete $.oldValue[key]; + return cb(void 0, key.slice(g.NAMESPACE.length)); + } + }; + $.on(window, 'storage', onChange); + return $.forceSync = function(key) { + key = g.NAMESPACE + key; + return onChange({ + key: key, + newValue: $.getValue(key) + }); + }; + })(); + } else { + $.sync = function() {}; + $.forceSync = function() {}; + } + + $["delete"] = function(keys) { + var i, key, len; + if (!(keys instanceof Array)) { + keys = [keys]; + } + for (i = 0, len = keys.length; i < len; i++) { + key = keys[i]; + $.deleteValue(g.NAMESPACE + 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 = $.getValue(g.NAMESPACE + key)) { + items[key] = JSON.parse(val); + } + } + return cb(items); + }); + }; + + $.set = function(keys, val, cb) { + var key, value; + if (typeof keys === 'string') { + $.setValue(g.NAMESPACE + keys, JSON.stringify(val)); + } else { + for (key in keys) { + value = keys[key]; + $.setValue(g.NAMESPACE + key, JSON.stringify(value)); + } + cb = val; + } + return typeof cb === "function" ? cb() : void 0; + }; + + $.clear = function(cb) { + var id; + $["delete"](Object.keys(Conf)); + $["delete"](['previousversion', 'AutoWatch', '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; + })()); + try { + $["delete"]($.listValues().map(function(key) { + return key.replace(g.NAMESPACE, ''); + })); + } catch (_error) {} + return typeof cb === "function" ? cb() : void 0; + }; + + return $; + +}).call(this); + +$$ = (function() { + var slice = [].slice; + + return function(selector, root) { + if (root == null) { + root = d.body; + } + return slice.call(root.querySelectorAll(selector)); + }; + +}).call(this); + +CrossOrigin = (function() { + var CrossOrigin; + + CrossOrigin = { + binary: function(url, cb, headers) { + var options, ref, workaround; + if (headers == null) { + headers = {}; + } + url = url.replace(/^((?:https?:)?\/\/(?:\w+\.)?4c(?:ha|d)n\.org)\/adv\//, '$1//adv/'); + workaround = $.engine === 'gecko' && (typeof GM_info !== "undefined" && GM_info !== null) && /^[0-2]\.|^3\.[01](?!\d)/.test(GM_info.version); + workaround || (workaround = /PaleMoon\//.test(navigator.userAgent)); + workaround || (workaround = (typeof GM_info !== "undefined" && GM_info !== null ? (ref = GM_info.script) != null ? ref.includeJSB : void 0 : void 0) != null); + options = { + method: "GET", + url: url, + headers: headers, + onload: function(xhr) { + var contentDisposition, contentType, data, i, r, ref1, ref2; + if (workaround) { + r = xhr.responseText; + data = new Uint8Array(r.length); + i = 0; + while (i < r.length) { + data[i] = r.charCodeAt(i); + i++; + } + } else { + data = new Uint8Array(xhr.response); + } + if (typeof xhr.responseHeaders === 'object') { + contentType = xhr.responseHeaders['Content-Type']; + contentDisposition = xhr.responseHeaders['Content-Disposition']; + } else { + contentType = (ref1 = xhr.responseHeaders.match(/Content-Type:\s*(.*)/i)) != null ? ref1[1] : void 0; + contentDisposition = (ref2 = xhr.responseHeaders.match(/Content-Disposition:\s*(.*)/i)) != null ? ref2[1] : void 0; + } + return cb(data, contentType, contentDisposition); + }, + onerror: function() { + return cb(null); + }, + onabort: function() { + return cb(null); + } + }; + if (workaround) { + options.overrideMimeType = options.mimeType = 'text/plain; charset=x-user-defined'; + } else { + options.responseType = 'arraybuffer'; + } + return GM_xmlhttpRequest(options); + }, + file: function(url, cb) { + return CrossOrigin.binary(url, function(data, contentType, contentDisposition) { + var blob, match, mime, name, ref, ref1, ref2, ref3; + 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, '"'); + } + if ((typeof GM_info !== "undefined" && GM_info !== null ? (ref3 = GM_info.script) != null ? ref3.includeJSB : void 0 : void 0) != null) { + mime = QR.typeFromExtension[name.match(/[^.]*$/)[0].toLowerCase()] || 'application/octet-stream'; + } + 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 j, len, ref, response; + response = JSON.parse(xhr.responseText); + ref = callbacks[url]; + for (j = 0, len = ref.length; j < len; j++) { + cb = ref[j]; + cb(response); + } + delete callbacks[url]; + return responses[url] = response; + }, + onerror: function() { + return delete callbacks[url]; + }, + onabort: function() { + return delete callbacks[url]; + } + }); + }; + })() + }; + + return CrossOrigin; + +}).call(this); + +Board = (function() { + var Board; + + 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; + + })(); + + return Board; + +}).call(this); + +Callbacks = (function() { + var Callbacks; + + Callbacks = (function() { + Callbacks.Post = new Callbacks('Post'); + + Callbacks.Thread = new Callbacks('Thread'); + + Callbacks.CatalogThread = new Callbacks('Catalog Thread'); + + 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, keys) { + var err, errors, i, len, name, ref; + if (keys == null) { + keys = this.keys; + } + for (i = 0, len = keys.length; i < len; i++) { + name = keys[i]; + try { + if ((ref = this[name]) != null) { + ref.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; + + })(); + + return Callbacks; + +}).call(this); + +CatalogThread = (function() { + var CatalogThread; + + CatalogThread = (function() { + 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; + + })(); + + return CatalogThread; + +}).call(this); + +Connection = (function() { + var Connection, + bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + + Connection = (function() { + function Connection(target, origin, cb) { + this.target = target; + this.origin = origin; + this.cb = cb != null ? cb : {}; + this.onMessage = bind(this.onMessage, this); + this.send = bind(this.send, this); + $.on(window, 'message', this.onMessage); + } + + Connection.prototype.targetWindow = function() { + if (this.target instanceof window.HTMLIFrameElement) { + return this.target.contentWindow; + } else { + return this.target; + } + }; + + Connection.prototype.send = function(data) { + return this.targetWindow().postMessage("" + g.NAMESPACE + (JSON.stringify(data)), this.origin); + }; + + Connection.prototype.onMessage = function(e) { + var base, data, type, value; + if (!(e.source === this.targetWindow() && 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; + + })(); + + return Connection; + +}).call(this); + +DataBoard = (function() { + var DataBoard, + bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + + 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[this.key]; + $.sync(this.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(cb) { + return $.set(this.key, this.data, cb); + }; + + DataBoard.prototype["delete"] = function(arg) { + var boardID, postID, ref, threadID; + 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, cb) { + var base, base1, base2, boardID, postID, threadID, val; + 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(cb); + }; + + DataBoard.prototype.get = function(arg) { + var ID, board, boardID, defaultValue, i, len, postID, thread, threadID, val; + boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, defaultValue = arg.defaultValue; + if (board = this.data.boards[boardID]) { + if (threadID == null) { + if (postID != null) { + 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 != null ? thread[postID] : thread; + } + } + return val || defaultValue; + }; + + DataBoard.prototype.forceSync = function() { + return $.forceSync(this.key); + }; + + DataBoard.prototype.clean = function() { + var boardID, now, ref, val; + $.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) { + this.ajaxClean(boardID); + } + } + }; + + DataBoard.prototype.ajaxClean = function(boardID) { + return $.cache("//a.4cdn.org/" + boardID + "/threads.json", (function(_this) { + return function(e1) { + var ref; + if ((ref = e1.target.status) !== 200 && ref !== 404) { + return; + } + return $.cache("//a.4cdn.org/" + boardID + "/archive.json", function(e2) { + var ref1; + if ((ref1 = e2.target.status) !== 200 && ref1 !== 404) { + return; + } + return _this.ajaxCleanParse(boardID, e1.target.response, e2.target.response); + }); + }; + })(this)); + }; + + DataBoard.prototype.ajaxCleanParse = function(boardID, response1, response2) { + var ID, board, i, j, k, len, len1, len2, page, ref, thread, threads; + if (!(board = this.data.boards[boardID])) { + return; + } + threads = {}; + if (response1) { + for (i = 0, len = response1.length; i < len; i++) { + page = response1[i]; + ref = page.threads; + for (j = 0, len1 = ref.length; j < len1; j++) { + thread = ref[j]; + ID = thread.no; + if (ID in board) { + threads[ID] = board[ID]; + } + } + } + } + if (response2) { + for (k = 0, len2 = response2.length; k < len2; k++) { + ID = response2[k]; + if (ID in board) { + threads[ID] = board[ID]; + } + } + } + this.data.boards[boardID] = threads; + this.deleteIfEmpty({ + boardID: boardID + }); + return this.save(); + }; + + DataBoard.prototype.onSync = function(data) { + this.data = data || { + boards: {} + }; + return typeof this.sync === "function" ? this.sync() : void 0; + }; + + return DataBoard; + + })(); + + return DataBoard; + +}).call(this); + +Fetcher = (function() { + var Fetcher, + slice = [].slice; + + Fetcher = (function() { + function Fetcher(boardID1, threadID, postID1, root, quoter) { + var post; + this.boardID = boardID1; + this.threadID = threadID; + this.postID = postID1; + this.root = root; + this.quoter = quoter; + 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(_this) { + return function(e, isCached) { + return _this.fetchedPost(e.target, isCached); + }; + })(this)); + } else { + this.archivedPost(); + } + } + + Fetcher.prototype.insert = function(post) { + var boardID, clone, k, len, nodes, postID, quote, ref, ref1; + if (!this.root.parentNode) { + return; + } + clone = post.addClone(this.quoter.context, $.hasClass(this.root, 'dialog')); + Main.callbackNodes('Post', [clone]); + nodes = clone.nodes; + $.rmAll(nodes.root); + $.add(nodes.root, nodes.post); + ref = clone.nodes.quotelinks.concat(slice.call(clone.nodes.backlinks)); + for (k = 0, len = ref.length; k < len; k++) { + quote = ref[k]; + ref1 = Get.postDataFromLink(quote), boardID = ref1.boardID, postID = ref1.postID; + if (postID === this.quoter.ID && boardID === this.quoter.board.ID) { + $.addClass(quote, 'forwardlink'); + } + } + $.rmAll(this.root); + $.add(this.root, nodes.root); + return $.event('PostsInserted'); + }; + + Fetcher.prototype.fetchedPost = function(req, isCached) { + var api, board, k, len, post, posts, status, thread; + 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 (k = 0, len = posts.length; k < len; k++) { + post = posts[k]; + if (post.no === this.postID) { + break; + } + } + if (post.no !== this.postID) { + if (isCached) { + api = "//a.4cdn.org/" + this.boardID + "/thread/" + this.threadID + ".json"; + $.cleanCache(function(url) { + return url === api; + }); + $.cache(api, (function(_this) { + return function(e) { + return _this.fetchedPost(e.target, false); + }; + })(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 archive, url; + if (!Conf['Resurrect Quotes']) { + return false; + } + if (!(url = Redirect.to('post', { + boardID: this.boardID, + postID: this.postID + }))) { + return false; + } + archive = Redirect.data.post[this.boardID]; + if (/^https:\/\//.test(url) || location.protocol === 'http:') { + $.cache(url, (function(_this) { + return function(e) { + return _this.parseArchivedPost(e.target.response, url, archive); + }; + })(this), { + responseType: 'json', + withCredentials: archive.withCredentials + }); + return true; + } else if (Conf['Exempt 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 (!((ref = media[key]) != null ? ref.match(/^http:\/\//) : void 0)) { + delete media[key]; + } + } + } + } + return _this.parseArchivedPost(response, url, archive); + }; + })(this)); + return true; + } + return false; + }; + + Fetcher.prototype.parseArchivedPost = function(data, url, archive) { + var board, comment, greentext, i, j, key, o, post, ref, ref1, text, text2, thread, val; + if (post = g.posts[this.boardID + "." + this.postID]) { + this.insert(post); + return; + } + if (data == null) { + $.addClass(this.root, 'warning'); + this.root.textContent = "Error fetching Post No." + this.postID + " from " + archive.name + "."; + 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 k, len, results; + results = []; + for (i = k = 0, len = comment.length; k < len; i = ++k) { + text = comment[i]; + if (i % 2 === 1) { + results.push(this.archiveTags[text]); + } else { + greentext = text[0] === '>'; + text = text.replace(/(\[\/?[a-z]+):lit(\])/g, '$1$2'); + text = (function() { + var l, len1, ref, results1; + ref = text.split(/(>>(?:>\/[a-z\d]+\/)?\d+)/g); + results1 = []; + for (j = l = 0, len1 = ref.length; l < len1; j = ++l) { + text2 = ref[j]; + results1.push({ + innerHTML: ((j % 2) ? "" + E(text2) + "" : E(text2)) + }); + } + return results1; + })(); + text = { + innerHTML: ((greentext) ? "" + E.cat(text) + "" : E.cat(text)) + }; + results.push(text); + } + } + return results; + }).call(this); + comment = { + innerHTML: E.cat(comment) + }; + this.threadID = +data.thread_num; + o = { + postID: this.postID, + threadID: this.threadID, + boardID: this.boardID, + isReply: this.postID !== this.threadID + }; + o.info = { + subject: data.title, + email: data.email, + name: data.name || '', + tripcode: data.trip, + capcode: (function() { + switch (data.capcode) { + case 'M': + return 'Mod'; + case 'A': + return 'Admin'; + case 'D': + return 'Developer'; + } + })(), + uniqueID: data.poster_hash, + flagCode: data.poster_country, + flag: data.poster_country_name, + dateUTC: data.timestamp, + dateText: data.fourchan_date, + commentHTML: comment + }; + if (o.info.capcode) { + delete o.info.uniqueID; + } + if ((ref = data.media) != null ? ref.media_filename : void 0) { + ref1 = data.media; + for (key in ref1) { + val = ref1[key]; + if (/_link$/.test(key) && (val != null ? val[0] : void 0) === '/') { + data.media[key] = url.split('/', 3).join('/') + val; + } + } + o.file = { + name: data.media.media_filename, + url: data.media.media_link || data.media.remote_media_link || (location.protocol + "//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: $.bytesToString(data.media.media_size), + thumbURL: data.media.thumb_link || (location.protocol + "//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 (!/\.pdf$/.test(o.file.url)) { + o.file.dimensions = o.file.width + "x" + o.file.height; + } + if (this.boardID === 'f' && data.media.exif) { + 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); + post.kill(); + if (post.file) { + post.file.thumbURL = o.file.thumbURL; + } + post.isFetchedQuote = true; + Main.callbackNodes('Post', [post]); + return this.insert(post); + }; + + Fetcher.prototype.archiveTags = { + '\n': { + innerHTML: "
    " + }, + '[b]': { + innerHTML: "" + }, + '[/b]': { + innerHTML: "" + }, + '[spoiler]': { + innerHTML: "" + }, + '[/spoiler]': { + innerHTML: "" + }, + '[code]': { + innerHTML: "
    "
    +      },
    +      '[/code]': {
    +        innerHTML: "
    " + }, + '[moot]': { + innerHTML: "
    " + }, + '[/moot]': { + innerHTML: "
    " + }, + '[banned]': { + innerHTML: "" + }, + '[/banned]': { + innerHTML: "" + } + }; + + return Fetcher; + + })(); + + return Fetcher; + +}).call(this); + +Notice = (function() { + var Notice, + bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + + 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: "
    " + }); + 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 (this.closed) { + return; + } + 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() { + this.closed = true; + $.off(d, 'visibilitychange', this.add); + $.rm(this.el); + return typeof this.onclose === "function" ? this.onclose() : void 0; + }; + + return Notice; + + })(); + + return Notice; + +}).call(this); + +Post = (function() { + var Post, + 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; }; + + Post = (function() { + Post.prototype.toString = function() { + return this.ID; + }; + + function Post(root, thread, board) { + var capcode, clone, date, email, flag, info, j, len, name, post, ref, subject, tripcode, uniqueID; + this.thread = thread; + this.board = board; + this.ID = +root.id.slice(2); + this.fullID = this.board + "." + this.ID; + this.context = this; + root.dataset.fullID = this.fullID; + 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: [] + }; + if ($.engine === 'edge') { + Object.defineProperty(this.nodes, 'backlinks', { + configurable: true, + enumerable: true, + get: function() { + return info.getElementsByClassName('backlink'); + } + }); + } else { + this.nodes.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 || void 0; + } + 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(); + 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 (j = 0, len = ref.length; j < len; j++) { + clone = ref[j]; + clone.origin = this; + } + } + this.board.posts.push(this.ID, this); + this.thread.posts.push(this.ID, this); + g.posts.push(this.fullID, this); + } + + Post.prototype.parseComment = function() { + var abbr, bq, commentDisplay, j, k, len, len1, node, ref, spoilers; + this.nodes.comment.normalize(); + bq = this.nodes.comment.cloneNode(true); + ref = $$('.abbr + br, .exif, b, .fortune', bq); + for (j = 0, len = ref.length; j < len; j++) { + node = ref[j]; + $.rm(node); + } + if (abbr = $('.abbr', bq)) { + $.rm(abbr); + } + this.info.comment = this.nodesToText(bq); + if (abbr) { + this.info.comment = this.info.comment.replace(/\n\n$/, ''); + } + commentDisplay = this.info.comment; + if (!(Conf['Remove Spoilers'] || Conf['Reveal Spoilers'])) { + spoilers = $$('s', bq); + if (spoilers.length) { + for (k = 0, len1 = spoilers.length; k < len1; k++) { + node = spoilers[k]; + $.replace(node, $.tn('[spoiler]')); + } + commentDisplay = this.nodesToText(bq); + } + } + return this.info.commentDisplay = commentDisplay.trim().replace(/\s+$/gm, ''); + }; + + 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; + }; + + Post.prototype.parseQuotes = function() { + var j, len, quotelink, ref; + this.quotes = []; + ref = $$(':not(pre) > .quotelink', this.nodes.comment); + for (j = 0, len = ref.length; j < len; j++) { + quotelink = ref[j]; + this.parseQuote(quotelink); + } + }; + + Post.prototype.parseQuote = function(quotelink) { + var fullID, match; + match = quotelink.href.match(/^https?:\/\/boards\.4chan\.org\/+([^\/]+)\/+(?:res|thread)\/+\d+(?:\/[^#]*)?#p(\d+)$/); + if (!(match || (this.isClone && quotelink.dataset.postID))) { + 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() { + var fileEl, fileText, info, link, m, ref, ref1, ref2, size, thumb, unit; + if (!(fileEl = $('.file', this.nodes.post))) { + return; + } + if (!(link = $('.fileText > a, .fileText-original > a', fileEl))) { + return; + } + if (!(info = (ref = link.nextSibling) != null ? ref.textContent.match(/\(([\d.]+ [KMG]?B).*\)/) : void 0)) { + return; + } + fileText = fileEl.firstElementChild; + this.file = { + text: fileText, + link: link, + url: link.href, + name: fileText.title || link.title || link.textContent, + size: info[1], + isImage: /(jpg|png|gif)$/i.test(link.href), + isVideo: /webm$/i.test(link.href), + dimensions: (ref1 = info[0].match(/\d+x\d+/)) != null ? ref1[0] : void 0, + tag: (ref2 = info[0].match(/,[^,]*, ([a-z]+)\)/i)) != null ? ref2[1] : void 0 + }; + 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; + if ((thumb = $('.fileThumb > [data-md5]', fileEl))) { + return $.extend(this.file, { + thumb: thumb, + thumbURL: (m = link.href.match(/\d+(?=\.\w+$)/)) ? location.protocol + "//i.4cdn.org/" + this.board + "/" + m[0] + "s.jpg" : void 0, + MD5: thumb.dataset.md5, + isSpoiler: $.hasClass(thumb.parentNode, 'imgspoiler') + }); + } + }; + + Post.prototype.kill = function(file) { + var clone, j, k, len, len1, quotelink, ref, ref1, strong; + if (file) { + if (this.isDead || this.file.isDead) { + return; + } + this.file.isDead = true; + $.addClass(this.nodes.root, 'deleted-file'); + } else { + if (this.isDead) { + return; + } + this.isDead = true; + $.rmClass(this.nodes.root, 'deleted-file'); + $.addClass(this.nodes.root, 'deleted-post'); + } + if (!(strong = $('strong.warning', this.nodes.info))) { + strong = $.el('strong', { + className: 'warning' + }); + $.after($('input', this.nodes.info), strong); + } + strong.textContent = file ? '[File deleted]' : '[Deleted]'; + if (this.isClone) { + return; + } + ref = this.clones; + for (j = 0, len = ref.length; j < len; j++) { + clone = ref[j]; + clone.kill(file); + } + if (file) { + return; + } + ref1 = Get.allQuotelinksLinkingTo(this); + for (k = 0, len1 = ref1.length; k < len1; k++) { + quotelink = ref1[k]; + if (!(!$.hasClass(quotelink, 'deadlink'))) { + continue; + } + quotelink.textContent = quotelink.textContent + '\u00A0(Dead)'; + $.addClass(quotelink, 'deadlink'); + } + }; + + Post.prototype.resurrect = function() { + var clone, j, k, len, len1, quotelink, ref, ref1, strong; + this.isDead = false; + $.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 (j = 0, len = ref.length; j < len; j++) { + clone = ref[j]; + clone.resurrect(); + } + ref1 = Get.allQuotelinksLinkingTo(this); + for (k = 0, len1 = ref1.length; k < len1; k++) { + quotelink = ref1[k]; + if (!($.hasClass(quotelink, 'deadlink'))) { + continue; + } + quotelink.textContent = quotelink.textContent.replace('\u00A0(Dead)', ''); + $.rmClass(quotelink, 'deadlink'); + } + }; + + Post.prototype.collect = function() { + g.posts.rm(this.fullID); + this.thread.posts.rm(this); + return this.board.posts.rm(this); + }; + + Post.prototype.addClone = function(context, contractThumb) { + return new Post.Clone(this, context, contractThumb); + }; + + Post.prototype.rmClone = function(index) { + var clone, j, len, ref; + this.clones.splice(index, 1); + ref = this.clones.slice(index); + for (j = 0, len = ref.length; j < len; j++) { + clone = ref[j]; + clone.nodes.root.dataset.clone = index++; + } + }; + + return Post; + + })(); + + return Post; + +}).call(this); + +(function() { + var extend = 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; }, + hasProp = {}.hasOwnProperty, + slice = [].slice; + + Post.Clone = (function(superClass) { + extend(_Class, superClass); + + _Class.prototype.isClone = true; + + function _Class(origin, context, contractThumb) { + var base, file, i, info, inline, inlined, j, k, key, l, len, len1, len2, len3, node, nodes, post, ref, ref1, ref2, ref3, ref4, ref5, root, val; + 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] = this.origin[key]; + } + nodes = this.origin.nodes; + root = contractThumb ? this.cloneWithoutVideo(nodes.root) : nodes.root.cloneNode(true); + (base = Post.Clone).prefix || (base.prefix = 0); + ref1 = [root].concat(slice.call($$('[id]', root))); + for (j = 0, len1 = ref1.length; j < len1; j++) { + node = ref1[j]; + node.id = Post.Clone.prefix + node.id; + } + Post.Clone.prefix++; + 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: [] + }; + if ($.engine === 'edge') { + Object.defineProperty(this.nodes, 'backlinks', { + configurable: true, + enumerable: true, + get: function() { + return info.getElementsByClassName('backlink'); + } + }); + } else { + this.nodes.backlinks = info.getElementsByClassName('backlink'); + } + ref2 = $$('.inline', post); + for (k = 0, len2 = ref2.length; k < len2; k++) { + inline = ref2[k]; + $.rm(inline); + } + ref3 = $$('.inlined', post); + for (l = 0, len3 = ref3.length; l < len3; l++) { + inlined = ref3[l]; + $.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(); + this.quotes = slice.call(this.origin.quotes); + if (this.origin.file) { + this.file = {}; + ref4 = this.origin.file; + for (key in ref4) { + val = ref4[key]; + this.file[key] = val; + } + file = $('.file', post); + this.file.text = file.firstElementChild; + this.file.link = $('.fileText > a, .fileText-original', file); + 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 ((ref5 = this.file.thumb) != null ? ref5.dataset.src : void 0) { + this.file.thumb.src = this.file.thumb.dataset.src; + this.file.thumb.removeAttribute('data-src'); + } + if (this.file.thumb && contractThumb) { + ImageExpand.contract(this); + } + } + if (this.origin.isDead) { + this.isDead = true; + } + root.dataset.clone = this.origin.clones.push(this) - 1; + } + + _Class.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 _Class; + + })(Post); + +}).call(this); + +RandomAccessList = (function() { + var RandomAccessList; + + RandomAccessList = (function() { + function RandomAccessList(items) { + var i, item, 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; + + })(); + + return RandomAccessList; + +}).call(this); + +ShimSet = (function() { + var ShimSet; + + 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; + } + + return ShimSet; + +}).call(this); + +SimpleDict = (function() { + var SimpleDict, + slice = [].slice; + + 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 j, key, len, ref; + ref = slice.call(this.keys); + for (j = 0, len = ref.length; j < len; j++) { + key = ref[j]; + fn(this[key]); + } + }; + + return SimpleDict; + + })(); + + return SimpleDict; + +}).call(this); + +Thread = (function() { + var Thread; + + Thread = (function() { + 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; + this.board.threads.push(this.ID, this); + g.threads.push(this.fullID, 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; + + })(); + + return Thread; + +}).call(this); + +Redirect = (function() { + var Redirect, + 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; }; + + Redirect = { + init: function() { + var archive, archives, boardID, boards, data, files, i, id, j, len, len1, name, o, record, ref, ref1, software, type, uid, withCredentials; + o = { + thread: {}, + post: {}, + file: {}, + report: {} + }; + archives = {}; + ref = Redirect.archives; + for (i = 0, len = ref.length; i < len; i++) { + data = ref[i]; + uid = data.uid, name = data.name, boards = data.boards, files = data.files, software = data.software, withCredentials = data.withCredentials; + archives[JSON.stringify(uid != null ? uid : name)] = data; + for (j = 0, len1 = boards.length; j < len1; j++) { + boardID = boards[j]; + if (!withCredentials) { + 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; + } + } + if (name === 'fgts') { + o.report[boardID] = data; + } + } + } + ref1 = Conf['selectedArchives']; + for (boardID in ref1) { + record = ref1[boardID]; + for (type in record) { + id = record[type]; + if (id === null) { + delete o[type][boardID]; + } else if (archive = archives[JSON.stringify(id)]) { + boards = type === 'file' ? archive.files : archive.boards; + if (indexOf.call(boards, boardID) >= 0) { + o[type][boardID] = archive; + } + } + } + } + return Redirect.data = o; + }, + archives: [ + { "uid": 3, "name": "4plebs", "domain": "archive.4plebs.org", "http": true, "https": true, "software": "foolfuuka", "boards": [ "adv", "f", "hr", "o", "pol", "s4s", "sp", "tg", "trv", "tv", "x" ], "files": [ "adv", "f", "hr", "o", "pol", "s4s", "sp", "tg", "trv", "tv", "x" ] }, + { "uid": 4, "name": "Nyafuu Archive", "domain": "archive.nyafuu.org", "http": true, "https": true, "software": "foolfuuka", "boards": [ "c", "e", "news", "w", "wg", "wsr" ], "files": [ "c", "e", "news", "w", "wg", "wsr" ] }, + { "uid": 8, "name": "Rebecca Black Tech", "domain": "rbt.asia", "http": false, "https": true, "software": "fuuka", "boards": [ "cgl", "g", "mu" ], "files": [ "cgl", "g", "mu" ] }, + { "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", "b", "cm", "gd", "h", "hc", "hm", "n", "out", "p", "po", "qa", "r", "s", "soc", "toy", "vp", "y" ], "files": [ "asp", "b", "cm", "gd", "h", "hc", "hm", "n", "out", "p", "po", "qa", "r", "s", "soc", "toy", "vp", "y" ] }, + { "uid": 23, "name": "Desustorage", "domain": "desustorage.org", "http": true, "https": true, "software": "foolfuuka", "boards": [ "a", "aco", "an", "c", "co", "d", "fit", "gif", "his", "int", "k", "m", "mlp", "qa", "r9k", "tg", "trash", "vr", "wsg" ], "files": [ "a", "aco", "an", "c", "co", "d", "fit", "gif", "his", "int", "k", "m", "mlp", "qa", "r9k", "tg", "trash", "vr", "wsg" ] }, + { "uid": 24, "name": "fireden.net", "domain": "boards.fireden.net", "http": false, "https": true, "software": "foolfuuka", "boards": [ "a", "cm", "ic", "sci", "tg", "v", "vg", "y" ], "files": [ "a", "cm", "ic", "sci", "tg", "v", "vg", "y" ] }, + { "uid": 25, "name": "arch.b4k.co", "domain": "arch.b4k.co", "http": true, "https": true, "software": "foolfuuka", "boards": [ "g", "jp", "mlp", "v" ], "files": [] }, + { "uid": 5, "name": "Love is Over", "domain": "deploy.loveisover.me", "http": true, "https": false, "software": "foolfuuka", "boards": [ "c", "d", "e", "i", "lgbt", "t", "u" ], "files": [ "c", "d", "e", "i", "lgbt", "t", "u" ], "search": [] }, + { "uid": 28, "name": "bstats", "domain": "archive.b-stats.org", "http": true, "https": true, "software": "foolfuuka", "boards": [ "f", "cm", "hm", "lgbt", "news", "trash", "y" ], "files": [] } + ], + 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 boardID, postID, protocol, url; + boardID = arg.boardID, postID = arg.postID; + protocol = Redirect.protocol(archive); + url = "" + protocol + archive.domain + "/_/api/chan/post/?board=" + boardID + "&num=" + postID; + if (!Redirect.securityCheck(url)) { + return ''; + } + 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 === 'MD5' ? 'image' : type; + if (type === 'capcode') { + value = { + 'Developer': 'dev' + }[value] || value.toLowerCase(); + } else if (type === 'image') { + value = value.replace(/[+\/=]/g, function(c) { + return { + '+': '-', + '/': '_', + '=': '' + }[c]; + }); + } + value = encodeURIComponent(value); + path = archive.software === 'foolfuuka' ? boardID + "/search/" + type + "/" + value + "/" : type === 'image' ? boardID + "/image/" + value : boardID + "/?task=search2&search_" + type + "=" + value; + return "" + (Redirect.protocol(archive)) + archive.domain + "/" + path; + }, + report: function(archive, arg) { + var boardID, postID; + boardID = arg.boardID, postID = arg.postID; + return "https://so.fgts.jp/report/?board=" + boardID + "&no=" + postID; + }, + securityCheck: function(url) { + return /^https:\/\//.test(url) || location.protocol === 'http:' || Conf['Exempt Archives from Encryption']; + }, + navigate: function(dest, data, alternative) { + var url; + if (!Redirect.data) { + Redirect.init(); + } + url = Redirect.to(dest, data); + 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); + } + } + }; + + return Redirect; + +}).call(this); + +Anonymize = (function() { + var Anonymize; + + 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 Callbacks.Post.push({ + name: 'Anonymize', + cb: this.node + }); + }, + node: function() { + var email, name, ref, tripcode; + 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 i, j, len, len1, name, ref, ref1, trip; + 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); + } + }); + } + }; + + return Anonymize; + +}).call(this); + +Filter = (function() { + var Filter, + 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; }; + + Filter = { + filters: {}, + init: function() { + var boards, err, excludes, filter, hl, i, key, len, line, op, ref, ref1, ref2, ref3, ref4, ref5, ref6, regexp, stub, top; + 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'; + boards = boards === 'global' ? null : boards.split(','); + if (boards === null) { + excludes = ((ref3 = filter.match(/exclude:([^;]+)/)) != null ? ref3[1].toLowerCase().split(',') : void 0) || null; + } + 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, boards, excludes, op, stub, hl, top)); + } + if (!this.filters[key].length) { + delete this.filters[key]; + } + } + if (!Object.keys(this.filters).length) { + return; + } + return Callbacks.Post.push({ + name: 'Filter', + cb: this.node + }); + }, + createFilter: function(regexp, boards, excludes, 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, boardID, isReply) { + if (boards && indexOf.call(boards, boardID) < 0) { + return false; + } + if (excludes && indexOf.call(excludes, boardID) >= 0) { + return false; + } + if (isReply && op === 'only' || !isReply && op === 'no') { + return false; + } + if (!test(value)) { + return false; + } + return settings; + }; + }, + node: function() { + var filter, i, key, len, ref, ref1, result, value; + if (this.isClone) { + return; + } + for (key in Filter.filters) { + if ((value = Filter[key](this)) != null) { + ref = Filter.filters[key]; + for (i = 0, len = ref.length; i < len; i++) { + filter = ref[i]; + if (!(result = filter(value, this.board.ID, this.isReply))) { + continue; + } + if (result.hide && !this.isFetchedQuote) { + 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; + } + } + } + } + }, + isHidden: function(post) { + var filter, i, key, len, ref, result, value; + for (key in Filter.filters) { + if ((value = Filter[key](post)) != null) { + ref = Filter.filters[key]; + for (i = 0, len = ref.length; i < len; i++) { + filter = ref[i]; + if (result = filter(value, post.boardID, post.isReply)) { + if (result.hide) { + return true; + } + } + } + } + } + return false; + }, + postID: function(post) { + var ref; + return "" + ((ref = post.ID) != null ? ref : post.postID); + }, + name: function(post) { + return post.info.name; + }, + uniqueID: function(post) { + return post.info.uniqueID; + }, + tripcode: function(post) { + return post.info.tripcode; + }, + capcode: function(post) { + return post.info.capcode; + }, + subject: function(post) { + return post.info.subject; + }, + comment: function(post) { + var base; + return (base = post.info).comment != null ? base.comment : base.comment = Build.parseComment(post.info.commentHTML.innerHTML); + }, + flag: function(post) { + return post.info.flag; + }, + filename: function(post) { + var ref; + return (ref = post.file) != null ? ref.name : void 0; + }, + dimensions: function(post) { + var ref; + return (ref = post.file) != null ? ref.dimensions : void 0; + }, + filesize: function(post) { + var ref; + return (ref = post.file) != null ? ref.size : void 0; + }, + MD5: function(post) { + var ref; + return (ref = post.file) != null ? ref.MD5 : void 0; + }, + menu: { + init: function() { + var div, entry, i, len, ref, ref1, type; + 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 != null; + } + }; + }, + 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(); + }); + } + } + }; + + return Filter; + +}).call(this); + +PostHiding = (function() { + var PostHiding; + + 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 Callbacks.Post.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, ref, replies, thisPost; + if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Menu'] || !Conf['Reply Hiding Link']) { + return; + } + div = $.el('div', { + className: 'hide-reply-link', + textContent: 'Hide' + }); + 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' + }); + 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, i, len, quotelink, 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 i, len, quotelink, 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'); + } + } + }; + + return PostHiding; + +}).call(this); + +Recursive = (function() { + var Recursive, + 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; }; + + Recursive = { + recursives: {}, + init: function() { + var ref; + if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { + return; + } + return Callbacks.Post.push({ + name: 'Recursive', + cb: this.node + }); + }, + node: function() { + var i, j, k, len, len1, obj, quote, recursive, ref, ref1; + if (this.isClone || this.isFetchedQuote) { + return; + } + ref = this.quotes; + for (j = 0, len = ref.length; j < len; j++) { + quote = ref[j]; + if (obj = Recursive.recursives[quote]) { + ref1 = obj.recursives; + for (i = k = 0, len1 = ref1.length; k < len1; i = ++k) { + recursive = ref1[i]; + recursive.apply(null, [this].concat(slice.call(obj.args[i]))); + } + } + } + }, + add: function() { + var args, base, name, obj, post, recursive; + 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, j, len, obj, rec, ref; + if (!(obj = Recursive.recursives[post.fullID])) { + return; + } + ref = obj.recursives; + for (i = j = 0, len = ref.length; j < len; i = ++j) { + 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))); + } + }); + } + }; + + return Recursive; + +}).call(this); + +ThreadHiding = (function() { + var ThreadHiding; + + ThreadHiding = { + init: function() { + var ref; + if (((ref = g.VIEW) !== 'index' && ref !== 'catalog') || !Conf['Thread Hiding Buttons'] && !(Conf['Menu'] && Conf['Thread Hiding Link']) && !Conf['JSON Index']) { + return; + } + this.db = new DataBoard('hiddenThreads'); + if (g.VIEW === 'catalog') { + return this.catalogWatch(); + } + this.catalogSet(g.BOARD); + return Callbacks.Post.push({ + name: 'Thread Hiding', + cb: this.node + }); + }, + catalogSet: function(board) { + var hiddenThreads, threadID; + if (!$.hasStorage) { + return; + } + 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() { + if (!$.hasStorage) { + return; + } + this.hiddenThreads = JSON.parse(localStorage.getItem("4chan-hide-t-" + g.BOARD)) || {}; + return Main.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 (this.isReply || this.isClone || this.isFetchedQuote) { + return; + } + if (data = ThreadHiding.db.get({ + boardID: this.board.ID, + threadID: this.ID + })) { + ThreadHiding.hide(this.thread, data.makeStub); + } + if (!Conf['Thread Hiding Buttons']) { + return; + } + return $.prepend(this.nodes.root, ThreadHiding.makeButton(this.thread, 'hide')); + }, + onIndexBuild: function(nodes) { + var i, len, root, thread; + 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' + }); + 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 Index'] && 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', + 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 Index'] && 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 Index'] && 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: "" + }); + 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 Index']) { + 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 Index']) { + return Index.updateHideLabel(); + } + } + }; + + return ThreadHiding; + +}).call(this); + +Build = (function() { + var Build, + slice = [].slice; + + 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|#44);/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; + } + }, + spoilerThumb: function(boardID) { + var spoilerRange; + if (spoilerRange = Build.spoilerRange[boardID]) { + return Build.staticPath + "spoiler-" + boardID + (Math.floor(1 + spoilerRange * Math.random())) + ".png"; + } else { + return Build.staticPath + "spoiler.png"; + } + }, + 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; + } + }, + parseJSON: function(data, boardID) { + var o; + o = { + postID: data.no, + threadID: data.resto || data.no, + boardID: boardID, + isReply: !!data.resto, + isSticky: !!data.sticky, + isClosed: !!data.closed, + isArchived: !!data.archived, + fileDeleted: !!data.filedeleted + }; + o.info = { + subject: Build.unescape(data.sub), + email: Build.unescape(data.email), + name: Build.unescape(data.name) || '', + tripcode: data.trip, + uniqueID: data.id, + flagCode: data.country, + flag: Build.unescape(data.country_name), + dateUTC: data.time, + dateText: data.now, + commentHTML: { + innerHTML: data.com || '' + } + }; + if (data.capcode) { + o.info.capcode = data.capcode.replace(/_highlight$/, '').replace(/_/g, ' ').replace(/\b\w/g, function(c) { + return c.toUpperCase(); + }); + o.capcodeHighlight = /_highlight$/.test(data.capcode); + delete o.info.uniqueID; + } + if (data.ext) { + o.file = { + name: (Build.unescape(data.filename)) + data.ext, + url: boardID === 'f' ? location.protocol + "//i.4cdn.org/" + boardID + "/" + (encodeURIComponent(data.filename)) + data.ext : location.protocol + "//i.4cdn.org/" + boardID + "/" + data.tim + data.ext, + height: data.h, + width: data.w, + MD5: data.md5, + size: $.bytesToString(data.fsize), + thumbURL: location.protocol + "//i.4cdn.org/" + boardID + "/" + data.tim + "s.jpg", + theight: data.tn_h, + twidth: data.tn_w, + isSpoiler: !!data.spoiler, + tag: data.tag + }; + if (!/\.pdf$/.test(o.file.url)) { + o.file.dimensions = o.file.width + "x" + o.file.height; + } + } + return o; + }, + parseComment: function(html) { + html = html.replace(//gi, '\n').replace(/\n\nRolled [^<]*<\/b>/i, '').replace(/]*>/g, ''); + return Build.unescape(html); + }, + postFromObject: function(data, boardID, suppressThumb) { + var o; + o = Build.parseJSON(data, boardID); + return Build.post(o, suppressThumb); + }, + post: function(o, suppressThumb) { + var boardID, capcode, capcodeDescription, capcodeLC, capcodeLong, capcodePlural, commentHTML, container, dateText, dateUTC, email, file, fileBlock, fileThumb, fileURL, flag, flagCode, gifIcon, href, i, len, match, name, postClass, postID, postInfo, postLink, protocol, quote, quoteLink, ref, ref1, shortFilename, staticPath, subject, threadID, tripcode, uniqueID, wholePost; + postID = o.postID, threadID = o.threadID, boardID = o.boardID, file = o.file; + ref = o.info, subject = ref.subject, email = ref.email, name = ref.name, tripcode = ref.tripcode, capcode = ref.capcode, uniqueID = ref.uniqueID, flagCode = ref.flagCode, flag = ref.flag, dateUTC = ref.dateUTC, dateText = ref.dateText, commentHTML = ref.commentHTML; + staticPath = Build.staticPath, gifIcon = Build.gifIcon; + + /* Post Info */ + if (capcode) { + capcodeLC = capcode.toLowerCase(); + if (capcode === 'Founder') { + capcodePlural = 'the Founder'; + capcodeDescription = "4chan's Founder"; + } else { + capcodeLong = { + 'Admin': 'Administrator', + 'Mod': 'Moderator' + }[capcode] || capcode; + capcodePlural = capcodeLong + "s"; + capcodeDescription = "a 4chan " + capcodeLong; + } + } + postLink = Build.postURL(boardID, threadID, postID); + quoteLink = Build.sameThread(boardID, threadID) ? "javascript:quote('" + (+postID) + "');" : "/" + boardID + "/thread/" + threadID + "#q" + postID; + postInfo = { + innerHTML: "
    " + ((!o.isReply || boardID === "f" || subject) ? "" + E(subject || "") + " " : "") + "" + ((email) ? "" : "") + "" + E(name) + "" + ((tripcode) ? " " + E(tripcode) + "" : "") + ((capcode) ? " ## " + E(capcode) + "" : "") + ((email) ? "" : "") + ((boardID === "f" && !o.isReply || capcode) ? "" : " ") + ((capcode) ? " \""" : "") + ((uniqueID && !capcode) ? " (ID: " + E(uniqueID) + ")" : "") + ((flagCode) ? " " : "") + " " + E(dateText) + " No." + E(postID) + "" + ((o.isSticky) ? " \"Sticky\"" : "") + ((o.isClosed && !o.isArchived) ? " \"Closed\"" : "") + ((o.isArchived) ? " \"Archived\"" : "") + ((!o.isReply && g.VIEW === "index") ? "   [Reply]" : "") + "
    " + }; + + /* File Info */ + if (file) { + protocol = /^https?:(?=\/\/i\.4cdn\.org\/)/; + fileURL = file.url.replace(protocol, ''); + shortFilename = Build.shortFilename(file.name); + fileThumb = file.isSpoiler ? Build.spoilerThumb(boardID) : file.thumbURL.replace(protocol, ''); + } + fileBlock = { + innerHTML: ((file) ? "
    " + ((boardID === "f") ? "
    File: " + E(file.name) + "-(" + E(file.size) + ", " + E(file.dimensions) + ((file.tag) ? ", " + E(file.tag) : "") + ")
    " : "
    File: " + ((file.isSpoiler) ? "Spoiler Image" : E(shortFilename)) + " (" + E(file.size) + ", " + E(file.dimensions || "PDF") + ")
    ") + "
    " : ((o.fileDeleted) ? "
    \"File
    " : "")) + }; + + /* Whole Post */ + postClass = o.isReply ? 'reply' : 'op'; + wholePost = { + innerHTML: ((o.isReply) ? "
    >>
    " : "") + "
    " + ((o.isReply) ? (postInfo).innerHTML + (fileBlock).innerHTML : (fileBlock).innerHTML + (postInfo).innerHTML) + "
    " + (commentHTML).innerHTML + "
    " + }; + container = $.el('div', { + className: "postContainer " + postClass + "Container", + id: "pc" + postID + }); + $.extend(container, wholePost); + ref1 = $$('.quotelink', container); + for (i = 0, len = ref1.length; i < len; i++) { + quote = ref1[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] || '#'; + } else if (/^\d+(#|$)/.test(href) && !(g.VIEW === 'thread' && g.BOARD.ID === boardID)) { + quote.href = "/" + boardID + "/thread/" + href; + } + } + return container; + }, + summaryText: function(status, posts, files) { + var text; + text = ''; + if (status) { + text += status + " "; + } + text += posts + " post" + (posts > 1 ? 's' : ''); + if (+files) { + text += " and " + files + " image repl" + (files > 1 ? 'ies' : 'y'); + } + return text += " " + (status === '-' ? 'shown' : 'omitted') + "."; + }, + summary: function(boardID, threadID, posts, files) { + return $.el('a', { + className: 'summary', + textContent: Build.summaryText('', posts, files), + href: "/" + boardID + "/thread/" + threadID + }); + }, + thread: function(board, data, full) { + var OP, root; + Build.spoilerRange[board] = data.custom_spoiler; + if (OP = board.posts[data.no]) { + if (OP.isFetchedQuote) { + OP = null; + } + } + if (OP && (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, true)]; + 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, i, imgClass, j, k, l, len, len1, len2, len3, pageCount, postCount, pp, quote, ref, ref1, ref2, ref3, ref4, root, spoilerRange, src, staticPath; + 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'; + } + postCount = data.replies + 1; + fileCount = data.images + !!data.ext; + pageCount = Math.floor(Index.liveThreadIDs.indexOf(thread.ID) / Index.threadsNumPerPage) + 1; + comment = { + innerHTML: data.com || '' + }; + root = $.el('div', { + className: 'catalog-thread' + }); + $.extend(root, { + innerHTML: "
    " + E(postCount) + " / " + E(fileCount) + " / " + E(pageCount) + "
    " + ((thread.OP.info.subject) ? "
    " + E(thread.OP.info.subject) + "
    " : "") + "
    " + (comment).innerHTML + "
    " + }); + 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; + } + }; + + return Build; + +}).call(this); + +(function() { + + +}).call(this); + +Get = (function() { + var Get, + 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; }; + + 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.commentDisplay.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 index, post; + if (root == null) { + return null; + } + post = g.posts[root.dataset.fullID]; + index = root.dataset.clone; + 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)); + }, + postDataFromLink: function(link) { + var boardID, path, postID, ref, threadID; + 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, i, len, posts, qPost, quote, quotelinks, 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 i, len, ref, script; + 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 ''; + } + }; + + return Get; + +}).call(this); + +Header = (function() { + var Header; + + 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: "" + }); + 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 popstate', 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 absbot, oldFooter; + if ((oldFooter = $.id('boardNavDesktopFoot'))) { + return $.replace($('.boardList', oldFooter), Header.bottomBoardList); + } else if ((absbot = $.id('absbot'))) { + $.before(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, i, j, len, len1, node, nodes, ref, ref1, spacer, span; + Header.boardList = boardList = $.el('span', { + id: 'board-list' + }); + $.extend(boardList, { + innerHTML: "" + }); + 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|(mode|sort|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, indexOptions, 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 ''; + }); + indexOptions = []; + t = t.replace(/-(?:mode|sort):"([^"]+)"/g, function(m0, m1) { + indexOptions.push(m1.toLowerCase().replace(/\ /g, '-')); + return ''; + }); + indexOptions = indexOptions.join('/'); + 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)/)) { + if (!(boardID === 'f' && m[1] === 'catalog')) { + a.dataset.only = m[1]; + a.href = CatalogLinks[m[1]](boardID); + if (m[1] === 'catalog') { + $.addClass(a, 'catalog'); + } + } else { + return a.firstChild; + } + } + if (Conf['JSON Index'] && indexOptions) { + a.dataset.indexOptions = indexOptions; + if (a.hostname === 'boards.4chan.org' && a.pathname.split('/')[2] === '') { + a.href += (a.hash ? '/' : '#') + indexOptions; + } + } + 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' && boardID !== 'trash') { + 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() { + 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(e) { + var el, hash; + if (e) { + if (e.state) { + return; + } + if (!history.state) { + history.replaceState({}, ''); + } + } + if ((hash = location.hash.slice(1))) { + ReplyPruning.showIfHidden(hash); + if ((el = $.id(hash))) { + return $.queueTask(function() { + return Header.scrollTo(el); + }); + } + } + }, + scrollTo: function(root, down, needed) { + var height, x; + if (!root.offsetParent) { + return; + } + if (down) { + x = Header.getBottomOf(root); + if (Conf['Fixed Header'] && 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['Fixed Header'] && 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['Fixed Header'] && 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, ref, type; + 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: "4chan X needs your permission to show desktop notifications. [FAQ]
    or " + }); + 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); + } + }; + + return Header; + +}).call(this); + +Index = (function() { + var Index, + 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; }; + + Index = { + showHiddenThreads: false, + changed: {}, + init: function() { + var anchorEntry, input, j, k, label, len, len1, name, pinEntry, ref, ref1, ref2, ref3, ref4, ref5, ref6, refNavEntry, repliesEntry, select, sortEntry; + if (g.BOARD.ID === 'f' || !Conf['JSON Index'] || g.VIEW !== 'index') { + return; + } + Callbacks.CatalogThread.push({ + name: 'Catalog Features', + cb: this.catalogNode + }); + this.search = ((ref = history.state) != null ? ref.searched : void 0) || ''; + if ((ref1 = history.state) != null ? ref1.mode : void 0) { + Conf['Index Mode'] = (ref2 = history.state) != null ? ref2.mode : void 0; + } + this.currentSort = (ref3 = history.state) != null ? ref3.sort : void 0; + this.currentSort || (this.currentSort = typeof Conf['Index Sort'] === 'object' ? Conf['Index Sort'][g.BOARD.ID] || 'bump' : Conf['Index Sort']); + this.currentPage = this.getCurrentPage(); + this.processHash(); + $.addClass(doc, 'index-loading', (Conf['Index Mode'].replace(/\ /g, '-')) + "-mode"); + $.on(window, 'popstate', this.cb.popstate); + $.on(d, 'scroll', Index.scroll); + 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') + }; + sortEntry = { + el: UI.checkbox('Per-Board Sort Type', 'Per-board sort type', typeof Conf['Index Sort'] === 'object') + }; + 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') + }; + sortEntry.el.title = 'Set the sorting order of each board independently.'; + 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 (j = 0, len = ref4.length; j < len; j++) { + label = ref4[j]; + 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.resort); + } + } + $.on(sortEntry.el.firstChild, 'change', this.cb.perBoardSort); + Header.menu.addEntry({ + el: $.el('span', { + textContent: 'Index Navigation' + }), + order: 100, + subEntries: [repliesEntry, sortEntry, pinEntry, anchorEntry, refNavEntry] + }); + this.navLinks = $.el('div', { + className: 'navLinks json-index' + }); + $.extend(this.navLinks, { + innerHTML: "Index Catalog Archive Bottom ×" + }); + $('.cataloglink a', this.navLinks).href = CatalogLinks.catalog(); + if ((ref5 = g.BOARD.ID) === 'b' || ref5 === 'trash') { + $('.archlistlink', this.navLinks).hidden = true; + } + $.on($('#index-last-refresh a', this.navLinks), 'click', this.cb.refreshFront); + this.searchInput = $('#index-search', this.navLinks); + this.setupSearch(); + $.on(this.searchInput, 'input', this.onSearchInput); + $.on($('#index-search-clear', this.navLinks), 'click', this.clearSearch); + this.hideLabel = $('#hidden-label', this.navLinks); + $.on($('#hidden-toggle a', this.navLinks), 'click', this.cb.toggleHiddenThreads); + this.selectMode = $('#index-mode', this.navLinks); + this.selectSort = $('#index-sort', this.navLinks); + this.selectSize = $('#index-size', this.navLinks); + $.on(this.selectMode, 'change', this.cb.mode); + $.on(this.selectSort, 'change', this.cb.sort); + $.on(this.selectSize, 'change', $.cb.value); + $.on(this.selectSize, 'change', this.cb.size); + ref6 = [this.selectMode, this.selectSize]; + for (k = 0, len1 = ref6.length; k < len1; k++) { + select = ref6[k]; + select.value = Conf[select.name]; + } + this.selectSort.value = Index.currentSort; + this.root = $.el('div', { + className: 'board json-index' + }); + this.cb.size(); + this.pagelist = $.el('div', { + className: 'pagelist json-index' + }); + $.extend(this.pagelist, { + innerHTML: "
    " + }); + $('.cataloglink a', this.pagelist).href = CatalogLinks.catalog(); + $.on(this.pagelist, 'click', this.cb.pageNav); + this.update(true); + $.onExists(doc, 'title + *', function() { + return d.title = d.title.replace(/\ -\ Page\ \d+/, ''); + }); + $.onExists(doc, '.board > .thread > .postContainer, .board + *', function() { + var board, el, l, len2, len3, m, ref7, ref8, threadRoot, topNavPos; + Index.hat = $('.board > .thread > img:first-child'); + if (Index.hat) { + if (Index.nodes) { + ref7 = Index.nodes; + for (l = 0, len2 = ref7.length; l < len2; l++) { + threadRoot = ref7[l]; + $.prepend(threadRoot, Index.hat.cloneNode(false)); + } + } + $.addClass(doc, 'hats-enabled'); + $.addStyle(".catalog-thread::after {background-image: url(" + Index.hat.src + ");}"); + } + board = $('.board'); + $.replace(board, Index.root); + $.event('PostsInserted'); + try { + d.implementation.createDocument(null, null, null).appendChild(board); + } catch (_error) {} + ref8 = $$('.navLinks'); + for (m = 0, len3 = ref8.length; m < len3; m++) { + el = ref8[m]; + $.rm(el); + } + $.rm($.id('ctrl-top')); + topNavPos = $.id('delform').previousElementSibling; + $.before(topNavPos, $.el('hr')); + return $.before(topNavPos, Index.navLinks); + }); + return Main.ready(function() { + var pagelist; + if ((pagelist = $('.pagelist'))) { + $.replace(pagelist, Index.pagelist); + } + return $.rmClass(doc, 'index-loading'); + }); + }, + scroll: function() { + var nodes, pageNum; + if (Index.req || !Index.liveThreadData || Conf['Index Mode'] !== 'infinite' || (window.scrollY <= doc.scrollHeight - (300 + window.innerHeight))) { + return; + } + if (Index.pageNum == null) { + Index.pageNum = Index.currentPage; + } + 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 Index'] || !Conf['Menu'] || !Conf['Thread Hiding Link'] || g.BOARD.ID === 'f') { + return; + } + return Menu.menu.addEntry({ + el: $.el('a', { + href: 'javascript:;', + className: 'has-shortcut-text' + }, { + innerHTML: "Shift+click" + }), + order: 20, + open: function(arg) { + var thread; + thread = arg.thread; + if (Conf['Index Mode'] !== 'catalog') { + return false; + } + this.el.firstElementChild.textContent = thread.isHidden ? 'Unhide' : 'Hide'; + 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, j, len, type, types; + types = slice.call(Index.selectSort.options).filter(function(option) { + return !option.disabled; + }); + for (i = j = 0, len = types.length; j < len; i = ++j) { + 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() { + Index.pushState({ + mode: this.value + }); + return Index.pageLoad(false); + }, + sort: function() { + Index.pushState({ + sort: this.value + }); + return Index.pageLoad(false); + }, + resort: function() { + Index.sort(); + return Index.buildIndex(); + }, + perBoardSort: function() { + Conf['Index Sort'] = this.checked ? {} : ''; + return Index.saveSort(); + }, + 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, nCommands, page, ref, searched, sort; + if (e != null ? e.state : void 0) { + ref = e.state, searched = ref.searched, mode = ref.mode, sort = ref.sort; + page = Index.getCurrentPage(); + Index.setState({ + search: searched, + mode: mode, + sort: sort, + page: page + }); + return Index.pageLoad(false); + } else { + nCommands = Index.processHash(); + if (Conf['Refreshed Navigation'] && nCommands) { + return Index.update(); + } else { + return Index.pageLoad(); + } + } + }, + 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); + }, + refreshFront: function() { + Index.pushState({ + page: 1 + }); + return Index.update(); + } + }, + scrollToIndex: function() { + return Header.scrollToIfNeeded((Index.navLinks.getBoundingClientRect().height ? Index.navLinks : Index.root)); + }, + getCurrentPage: function() { + return +window.location.pathname.split(/\/+/)[2] || 1; + }, + userPageNav: function(page) { + Index.pushState({ + page: page + }); + if (Conf['Refreshed Navigation']) { + return Index.update(); + } else { + return Index.pageLoad(); + } + }, + hashCommands: { + mode: { + 'paged': 'paged', + 'infinite-scrolling': 'infinite', + 'infinite': 'infinite', + 'all-threads': 'all pages', + 'all-pages': 'all pages', + 'catalog': 'catalog' + }, + sort: { + 'bump-order': 'bump', + 'last-reply': 'lastreply', + 'last-long-reply': 'lastlong', + 'creation-date': 'birth', + 'reply-count': 'replycount', + 'file-count': 'filecount' + } + }, + processHash: function() { + var command, commands, hash, j, leftover, len, mode, ref, sort, state; + hash = ((ref = location.href.match(/#.*/)) != null ? ref[0] : void 0) || ''; + state = { + replace: true + }; + commands = hash.slice(1).split('/'); + leftover = []; + for (j = 0, len = commands.length; j < len; j++) { + command = commands[j]; + if ((mode = Index.hashCommands.mode[command])) { + state.mode = mode; + } else if (command === 'index') { + state.mode = Conf['Previous Index Mode']; + state.page = 1; + } else if ((sort = Index.hashCommands.sort[command])) { + state.sort = sort; + } else if (/^s=/.test(command)) { + state.search = decodeURIComponent(command.slice(2)).replace(/\+/g, ' ').trim(); + } else { + leftover.push(command); + } + } + hash = leftover.join('/'); + if (hash) { + state.hash = "#" + hash; + } + Index.pushState(state); + return commands.length - leftover.length; + }, + pushState: function(state) { + var hash, pageBeforeSearch, pathname, ref, replace, search; + search = state.search, hash = state.hash, replace = state.replace; + pageBeforeSearch = (ref = history.state) != null ? ref.oldpage : void 0; + if ((search != null) && search !== Index.search) { + state.page = search ? 1 : pageBeforeSearch || 1; + if (!search) { + pageBeforeSearch = void 0; + } else if (!Index.search) { + pageBeforeSearch = Index.currentPage; + } + } + Index.setState(state); + pathname = Index.currentPage === 1 ? "/" + g.BOARD + "/" : "/" + g.BOARD + "/" + Index.currentPage; + hash || (hash = ''); + return history[replace ? 'replaceState' : 'pushState']({ + mode: Conf['Index Mode'], + sort: Index.currentSort, + searched: Index.search, + oldpage: pageBeforeSearch + }, '', location.protocol + "//" + location.host + pathname + hash); + }, + setState: function(arg) { + var hash, mode, page, ref, search, sort; + search = arg.search, mode = arg.mode, sort = arg.sort, page = arg.page, hash = arg.hash; + if ((search != null) && search !== Index.search) { + Index.changed.search = true; + Index.search = search; + } + if ((mode != null) && mode !== Conf['Index Mode']) { + Index.changed.mode = true; + Conf['Index Mode'] = mode; + $.set('Index Mode', mode); + if (!(mode === 'catalog' || Conf['Previous Index Mode'] === mode)) { + Conf['Previous Index Mode'] = mode; + $.set('Previous Index Mode', mode); + } + } + if ((sort != null) && sort !== Index.currentSort) { + Index.changed.sort = true; + Index.currentSort = sort; + Index.saveSort(); + } + if ((ref = Conf['Index Mode']) === 'all pages' || ref === 'catalog') { + page = 1; + } + if ((page != null) && page !== Index.currentPage) { + Index.changed.page = true; + Index.currentPage = page; + } + if (hash != null) { + return Index.changed.hash = true; + } + }, + saveSort: function() { + if (typeof Conf['Index Sort'] === 'object') { + Conf['Index Sort'][g.BOARD.ID] = Index.currentSort; + } else { + Conf['Index Sort'] = Index.currentSort; + } + return $.set('Index Sort', Conf['Index Sort']); + }, + pageLoad: function(scroll) { + var hash, mode, page, ref, search, sort, threads; + if (scroll == null) { + scroll = true; + } + if (!Index.liveThreadData) { + return; + } + ref = Index.changed, threads = ref.threads, search = ref.search, mode = ref.mode, sort = ref.sort, page = ref.page, hash = ref.hash; + if (threads || search || sort) { + Index.sort(); + } + if (threads || search) { + Index.buildPagelist(); + } + if (search) { + Index.setupSearch(); + } + if (mode) { + Index.setupMode(); + } + if (sort) { + Index.setupSort(); + } + if (threads || search || mode || page || sort) { + Index.buildIndex(); + } + if (threads || search || mode || page) { + Index.setPage(); + } + if (scroll && !hash) { + Index.scrollToIndex(); + } + if (hash) { + Header.hashScroll(); + } + return Index.changed = {}; + }, + setupMode: function() { + var j, len, mode, ref; + ref = ['paged', 'infinite', 'all pages', 'catalog']; + for (j = 0, len = ref.length; j < len; j++) { + mode = ref[j]; + $[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'; + }, + setupSort: function() { + return Index.selectSort.value = Index.currentSort; + }, + 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, j, maxPageNum, nodes, pagesRoot, ref; + pagesRoot = $('.pages', Index.pagelist); + maxPageNum = Index.getMaxPageNum(); + if (pagesRoot.childElementCount !== maxPageNum) { + nodes = []; + for (i = j = 1, ref = maxPageNum; j <= ref; i = j += 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.currentPage; + 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, ref, ref1, thread, threadID; + 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(firstTime) { + var now, ref, ref1; + if ((ref = Index.req) != null) { + ref.abort(); + } + if ((ref1 = Index.notice) != null) { + ref1.close(); + } + if (Conf['Index Refresh Notifications'] && d.readyState !== 'loading') { + Index.notice = new Notice('info', 'Refreshing index...'); + } else { + now = Date.now(); + $.ready(function() { + return Index.nTimeout = setTimeout((function() { + if (Index.req && !Index.notice) { + return Index.notice = new Notice('info', 'Refreshing index...'); + } + }), 3 * $.SECOND - (Date.now() - now)); + }); + } + if (!firstTime && d.readyState !== 'loading' && !$('.board + *')) { + location.reload(); + return; + } + Index.req = $.ajax("//a.4cdn.org/" + g.BOARD + "/catalog.json", { + onabort: Index.load, + onloadend: Index.load + }, { + whenModified: 'Index' + }); + return $.addClass(Index.button, 'fa-spin'); + }, + load: function(e) { + var err, nTimeout, notice, ref, req, timeEl; + $.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; + if (notice != 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); + } else if (req.status === 304) { + Index.pageLoad(); + } + } 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; + } + if (notice) { + if (Conf['Index Refresh Notifications']) { + notice.setType('success'); + notice.el.lastElementChild.textContent = 'Index refreshed!'; + setTimeout(notice.close, $.SECOND); + } else { + notice.close(); + } + } + timeEl = $('#index-last-refresh time', Index.navLinks); + timeEl.dataset.utc = Date.parse(req.getResponseHeader('Last-Modified')); + return RelativeDates.update(timeEl); + }, + parse: function(pages) { + $.cleanCache(function(url) { + return /^\/\/a\.4cdn\.org\//.test(url); + }); + Index.parseThreadList(pages); + Index.buildThreads(); + Index.changed.threads = true; + return Index.pageLoad(); + }, + parseThreadList: function(pages) { + var ref; + Index.pagesNum = pages.length; + Index.threadsNumPerPage = ((ref = pages[0]) != null ? ref.threads.length : void 0) || 1; + 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 ref1; + if (ref1 = thread.ID, indexOf.call(Index.liveThreadIDs, ref1) < 0) { + return thread.collect(); + } + }); + }, + buildThreads: function() { + var err, errors, i, j, len, posts, ref, thread, threadData, threadRoot, threads; + if (!Index.liveThreadData) { + return; + } + Index.nodes = []; + threads = []; + posts = []; + ref = Index.liveThreadData; + for (i = j = 0, len = ref.length; j < len; i = ++j) { + 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.OP && !thread.OP.isFetchedQuote)) { + 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, j, k, lastReplies, len, len1, node, nodes, post, posts, thread, threadRoot; + posts = []; + for (j = 0, len = threadRoots.length; j < len; j++) { + threadRoot = threadRoots[j]; + thread = Get.threadFromRoot(threadRoot); + i = Index.liveThreadIDs.indexOf(thread.ID); + if (!(lastReplies = Index.liveThreadData[i].last_replies)) { + continue; + } + nodes = []; + for (k = 0, len1 = lastReplies.length; k < len1; k++) { + data = lastReplies[k]; + if ((post = thread.posts[data.no]) && !post.isFetchedQuote) { + 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, j, len, thread, threads; + threads = Index.sortedNodes.map(function(threadRoot) { + return Get.threadFromRoot(threadRoot); + }).filter(function(thread) { + return !thread.isHidden !== Index.showHiddenThreads; + }); + catalogThreads = []; + for (j = 0, len = threads.length; j < len; j++) { + thread = threads[j]; + 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, j, len, node, ratio, ref, size, thumb, width; + size = Conf['Index Size'] === 'small' ? 150 : 250; + for (j = 0, len = nodes.length; j < len; j++) { + node = nodes[j]; + 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 j, lastlong, len, liveThreadData, liveThreadIDs, nodes, sortedNodes, sortedThreadIDs, threadID; + liveThreadIDs = Index.liveThreadIDs, liveThreadData = Index.liveThreadData; + if (!liveThreadData) { + return; + } + sortedThreadIDs = (function() { + switch (Index.currentSort) { + case 'lastreply': + return 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; + }); + case 'lastlong': + lastlong = function(thread) { + var i, j, r, ref; + ref = thread.last_replies || []; + for (i = j = ref.length - 1; j >= 0; i = j += -1) { + r = ref[i]; + if (r.com && Build.parseComment(r.com).replace(/[^a-z]/ig, '').length >= 100) { + return r; + } + } + return thread; + }; + return slice.call(liveThreadData).sort(function(a, b) { + return lastlong(b).no - lastlong(a).no; + }).map(function(post) { + return post.no; + }); + case 'bump': + return liveThreadIDs; + case 'birth': + return slice.call(liveThreadIDs).sort(function(a, b) { + return b - a; + }); + case 'replycount': + return slice.call(liveThreadData).sort(function(a, b) { + return b.replies - a.replies; + }).map(function(post) { + return post.no; + }); + case 'filecount': + return slice.call(liveThreadData).sort(function(a, b) { + return b.images - a.images; + }).map(function(post) { + return post.no; + }); + } + })(); + Index.sortedNodes = sortedNodes = []; + nodes = Index.nodes; + for (j = 0, len = sortedThreadIDs.length; j < len; j++) { + threadID = sortedThreadIDs[j]; + 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, j, len, ref, threadRoot, topNodes; + topNodes = []; + bottomNodes = []; + ref = Index.sortedNodes; + for (j = 0, len = ref.length; j < len; j++) { + threadRoot = ref[j]; + (match(Get.threadFromRoot(threadRoot)) ? topNodes : bottomNodes).push(threadRoot); + } + return Index.sortedNodes = topNodes.concat(bottomNodes); + }, + buildIndex: function() { + var i, nodes, page, post; + if (!Index.liveThreadData) { + return; + } + 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.currentPage) { + Index.currentPage = page; + Index.pushState({ + page: page + }); + Index.setPage(); + } + } + nodes = Index.buildSinglePage(Index.currentPage); + } + delete Index.pageNum; + $.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 j, len, node, thumb; + for (j = 0, len = nodes.length; j < len; j++) { + node = nodes[j]; + if (thumb = $('img[data-src]', node)) { + thumb.src = thumb.dataset.src; + thumb.removeAttribute('data-src'); + } + $.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() { + 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; + } + Index.pushState({ + search: search, + replace: !!search === !!Index.search + }); + return Index.pageLoad(false); + }, + 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, j, k, key, keyword, len, len1, ref, ref1, text; + ref = thread.OP, info = ref.info, file = ref.file; + text = []; + ref1 = ['comment', 'subject', 'name', 'tripcode', 'email']; + for (j = 0, len = ref1.length; j < len; j++) { + key = ref1[j]; + if (key in info) { + text.push(info[key]); + } + } + if (file) { + text.push(file.name); + } + text = text.join(' ').toLowerCase(); + for (k = 0, len1 = keywords.length; k < len1; k++) { + keyword = keywords[k]; + if (-1 === text.indexOf(keyword)) { + return false; + } + } + return true; + } + }; + + return Index; + +}).call(this); + +Polyfill = (function() { + var Polyfill; + + Polyfill = { + init: function() { + return this.toBlob(); + }, + toBlob: function() { + if (HTMLCanvasElement.prototype.toBlob) { + return; + } + HTMLCanvasElement.prototype.toBlob = function(cb, type, encoderOptions) { + var data, i, j, l, ref, ui8a, url; + if (type == null) { + type = 'image/png'; + } + url = this.toDataURL(type, encoderOptions); + data = atob(url.slice(url.indexOf(',') + 1)); + l = data.length; + ui8a = new Uint8Array(l); + for (i = j = 0, ref = l; j < ref; i = j += 1) { + ui8a[i] = data.charCodeAt(i); + } + return cb(new Blob([ui8a], { + type: type + })); + }; + return $.globalEval("HTMLCanvasElement.prototype.toBlob = (" + HTMLCanvasElement.prototype.toBlob + ");"); + } + }; + + return Polyfill; + +}).call(this); + +Settings = (function() { + var Settings, + 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; }; + + 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']) { + if ($.hasStorage) { + settings = JSON.parse(localStorage.getItem('4chan-settings')) || {}; + if (settings.disableAll) { + return; + } + settings.disableAll = true; + return localStorage.setItem('4chan-settings', JSON.stringify(settings)); + } else { + return $.onExists(doc, 'body', function() { + return $.global(function() { + return window.Config.disableAll = true; + }); + }); + } + } + }, + open: function(openSection) { + var dialog, j, len, link, links, overlay, ref, section, sectionToOpen; + if (Settings.overlay) { + return; + } + $.event('CloseMenu'); + Settings.dialog = dialog = $.el('div', { + id: 'fourchanx-settings', + className: 'dialog' + }); + $.extend(dialog, { + innerHTML: "
    " + }); + 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 (j = 0, len = ref.length; j < len; j++) { + section = ref[j]; + 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); + }, + warnings: { + localStorage: function(cb) { + var why; + if ($.cantSync) { + why = $.cantSet ? 'save your settings' : 'synchronize settings between tabs'; + return cb($.el('li', { + textContent: "4chan X needs local storage to " + why + ".\nEnable it on boards.4chan.org in your browser's privacy settings (may be listed as part of \"local data\" or \"cookies\")." + })); + } + }, + ads: function(cb) { + return $.onExists(doc, '.ad-cnt', function(ad) { + return $.onExists(ad, 'img', function() { + return cb($.el('li', { + innerHTML: "To protect yourself from malicious ads, you should block ads on 4chan." + })); + }); + }); + } + }, + main: function(section) { + var addWarning, arr, button, container, containers, description, div, fs, input, inputs, items, key, level, obj, ref, ref1, warning, warnings; + warnings = $.el('fieldset', { + hidden: true + }, { + innerHTML: "Warnings
      " + }); + addWarning = function(item) { + $.add($('ul', warnings), item); + return warnings.hidden = false; + }; + ref = Settings.warnings; + for (key in ref) { + warning = ref[key]; + warning(addWarning); + } + $.add(section, warnings); + items = {}; + inputs = {}; + ref1 = Config.main; + for (key in ref1) { + obj = ref1[key]; + fs = $.el('fieldset', { + innerHTML: "" + E(key) + "" + }); + containers = [fs]; + for (key in obj) { + arr = obj[key]; + description = arr[1]; + div = $.el('div', { + innerHTML: ": " + E(description) + "" + }); + if ($.engine !== 'gecko' && key === 'Remember QR Size') { + div.hidden = true; + } + 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: ": 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, ref2, ref3, thread; + hiddenThreads = arg.hiddenThreads, hiddenPosts = arg.hiddenPosts; + hiddenNum = 0; + ref2 = hiddenThreads.boards; + for (ID in ref2) { + board = ref2[ID]; + hiddenNum += Object.keys(board).length; + } + ref3 = hiddenPosts.boards; + for (ID in ref3) { + board = ref3[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; + if ($.hasStorage) { + 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) { + 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; + } + this.value = null; + 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 { + return Settings.loadSettings(JSON.parse(e.target.result), function(err) { + if (err) { + return output.textContent = 'Import failed due to an error.'; + } else 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); + }, + convertFrom: { + loadletter: function(data) { + var base, boardID, convertSettings, key, ref, ref1, threadData, threadID, threads, val; + 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': 'Disable Native Extension', + 'Comment Auto-Expansion': '', + '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', + 'Current Page': 'Page Count in Stats', + 'Current Page Position': '', + 'Alternative captcha': 'Use Recaptcha v1', + 'Auto Submit': 'Post on Captcha Completion', + '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()); + }); + } + } + if (data.WatchedThreads) { + data.Conf['watchedThreads'] = { + boards: {} + }; + ref1 = data.WatchedThreads; + for (boardID in ref1) { + threads = ref1[boardID]; + for (threadID in threads) { + threadData = threads[threadID]; + ((base = data.Conf['watchedThreads'].boards)[boardID] || (base[boardID] = {}))[threadID] = { + excerpt: threadData.textContent + }; + } + } + } + return data; + } + }, + upgrade: function(data, version) { + var boardID, changes, compareString, j, key, len, name, record, ref, ref1, ref2, ref3, ref4, ref5, rice, set, type, uids, value; + changes = {}; + set = function(key, value) { + return data[key] = changes[key] = value; + }; + compareString = version.replace(/\d+/g, function(x) { + return ('0000' + x).slice(-5); + }); + if (compareString < '00001.00011.00008.00000') { + if (data['Fixed Thread Watcher'] == null) { + set('Fixed Thread Watcher', (ref = data['Toggleable Thread Watcher']) != null ? ref : true); + } + if (data['Exempt Archives from Encryption'] == null) { + set('Exempt Archives from Encryption', (ref1 = data['Except Archives from Encryption']) != null ? ref1 : false); + } + } + if (compareString < '00001.00011.00010.00001') { + if (data['selectedArchives'] != null) { + uids = { + "Moe": 0, + "4plebs Archive": 3, + "Nyafuu Archive": 4, + "Love is Over": 5, + "Rebecca Black Tech": 8, + "warosu": 10, + "fgts": 15, + "not4plebs": 22, + "DesuStorage": 23, + "fireden.net": 24, + "disabled": null + }; + ref2 = data['selectedArchives']; + for (boardID in ref2) { + record = ref2[boardID]; + for (type in record) { + name = record[type]; + if (name in uids) { + record[type] = uids[name]; + } + } + } + set('selectedArchives', data['selectedArchives']); + } + } + if (compareString < '00001.00011.00016.00000') { + if ((rice = Config['usercss'].match(/\/\* Board title rice \*\/(?:\n.+)*/)[0])) { + if ((data['usercss'] != null) && data['usercss'].indexOf(rice) < 0) { + set('usercss', rice + '\n\n' + data['usercss']); + } + } + } + if (compareString < '00001.00011.00017.00000') { + ref3 = ['Persistent QR', 'Color User IDs', 'Fappe Tyme', 'Werk Tyme', 'Highlight Posts Quoting You', 'Highlight Own Posts']; + for (j = 0, len = ref3.length; j < len; j++) { + key = ref3[j]; + if (data[key] == null) { + set(key, key === 'Persistent QR'); + } + } + } + if (compareString < '00001.00011.00017.00006') { + if (data['sauces'] != null) { + set('sauces', data['sauces'].replace(/^(#?\s*)http:\/\/iqdb\.org\//mg, '$1//iqdb.org/')); + } + } + if (compareString < '00001.00011.00019.00003' && !Settings.overlay) { + $.queueTask(function() { + return Settings.warnings.ads(function(item) { + return new Notice('warning', slice.call(item.childNodes)); + }); + }); + } + if (compareString < '00001.00011.00020.00003') { + ref4 = { + 'Inline Cross-thread Quotes Only': false, + 'Pass Link': true + }; + for (key in ref4) { + value = ref4[key]; + if (data[key] == null) { + set(key, value); + } + } + } + if (compareString < '00001.00011.00021.00003') { + if (data['Remember Your Posts'] == null) { + set('Remember Your Posts', (ref5 = data['Mark Quotes of You']) != null ? ref5 : true); + } + } + if (compareString < '00001.00011.00022.00000') { + if (data['sauces'] != null) { + set('sauces', data['sauces'].replace(/^(#?\s*https:\/\/www\.google\.com\/searchbyimage\?image_url=%(?:IMG|URL))%3Fs\.jpg/mg, '$1')); + set('sauces', data['sauces'].replace(/^#?\s*https:\/\/www\.google\.com\/searchbyimage\?image_url=%(?:IMG|T?URL)(?=$|;)/mg, '$&&safe=off')); + } + } + if (compareString < '00001.00011.00022.00002') { + if ((data['Use Recaptcha v1 in Reports'] == null) && data['Use Recaptcha v1'] && !data['Use Recaptcha v2 in Reports']) { + set('Use Recaptcha v1 in Reports', true); + } + } + if (compareString < '00001.00011.00024.00000') { + if ((data['JSON Navigation'] != null) && (data['JSON Index'] == null)) { + set('JSON Index', data['JSON Navigation']); + } + } + if (compareString < '00001.00011.00026.00000') { + if ((data['Oekaki Links'] != null) && (data['Edit Link'] == null)) { + set('Edit Link', data['Oekaki Links']); + } + if (data['Inline Cross-thread Quotes Only'] == null) { + set('Inline Cross-thread Quotes Only', true); + } + } + if (compareString < '00001.00011.00030.00000') { + if (data['Quote Threading'] && (data['Thread Quotes'] == null)) { + set('Thread Quotes', true); + } + } + return changes; + }, + loadSettings: function(data, cb) { + if (data.version.split('.')[0] === '2') { + data = Settings.convertFrom.loadletter(data); + } else if (data.version !== g.VERSION) { + Settings.upgrade(data.Conf, data.version); + } + return $.clear(function(err) { + if (err) { + return cb(err); + } + return $.set(data.Conf, cb); + }); + }, + reset: function() { + if (confirm('Your current settings will be entirely wiped, are you sure?')) { + return $.clear(function(err) { + if (err) { + return $('.imp-exp-result').textContent = 'Import failed due to an error.'; + } else if (confirm('Reset successful. Reload now?')) { + return window.location.reload(); + } + }); + } + }, + filter: function(section) { + var select; + $.extend(section, { + innerHTML: "
      " + }); + select = $('select', section); + $.on(select, 'change', Settings.selectFilter); + return Settings.selectFilter.call(select); + }, + selectFilter: function() { + var div, name, ta; + div = this.nextElementSibling; + if ((name = this.value) !== 'guide') { + $.rmAll(div); + ta = $.el('textarea', { + name: name, + className: 'field', + spellcheck: false + }); + $.get(name, Conf[name], function(item) { + return ta.value = item[name]; + }); + $.on(ta, 'change', $.cb.value); + $.add(div, ta); + return; + } + $.extend(div, { + innerHTML: "
      Filter is disabled.

      Use regular expressions, one per line.
      Lines starting with a # will be ignored.
      For example, /weeaboo/i will filter posts containing the string \`weeaboo\`, case-insensitive.
      MD5 filtering uses exact string matching, not regular expressions.

        You can use these settings with each regular expression, separate them with semicolons:
      • Per boards, separate them with commas. It is global if not specified.
        For example: boards:a,jp;.
      • In case of a global rule, select boards to be excluded from the filter.
        For example: exclude:vg,v;.
      • Filter OPs only along with their threads (\`only\`), replies only (\`no\`), or both (\`yes\`, this is default).
        For example: op:only;, op:no; or op:yes;.
      • Overrule the \`Show Stubs\` setting if specified: create a stub (\`yes\`) or not (\`no\`).
        For example: stub:yes; or stub:no;.
      • Highlight instead of hiding. You can specify a class name to use with a userstyle.
        For example: highlight; or highlight:wallpaper;.
      • Highlighted OPs will have their threads put on top of the board index by default.
        For example: top:yes; or top:no;.

      Note: If you're using the native catalog rather than 4chan X's catalog, 4chan X's filters do not apply there.
      The native catalog has its own separate filter list.

      " + }); + return $('.warning', div).hidden = Conf['Filter']; + }, + sauce: function(section) { + var ta; + $.extend(section, { + innerHTML: "
      Sauce is disabled.
      Lines starting with a # will be ignored.
      You can specify a display text by appending ;text:[text] to the URL.
      You can specify the applicable boards by appending ;boards:[board1],[board2].
      You can specify the applicable file types by appending ;types:[extension1],[extension2].
      You can open links with scripts and popups disabled by appending ;sandbox.
        These parameters will be replaced by their corresponding values:
      • %TURL: Thumbnail URL.
      • %URL: Full image URL.
      • %IMG: Full image URL for GIF, JPG, and PNG; thumbnail URL for other types.
      • %MD5: MD5 hash in base64.
      • %sMD5: MD5 hash in base64 using - and _.
      • %hMD5: MD5 hash in hexadecimal.
      • %name: Original file name.
      • %board: Current board.
      • %%, %semi: Literal % and ;.
      " + }); + $('.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, archive, boardID, boardOptions, boardSelect, boards, customCSS, files, i, input, inputs, interval, item, items, j, k, l, len, len1, len2, len3, len4, len5, len6, m, n, name, o, q, r, ref, ref1, ref2, ref3, ref4, ref5, ref6, row, rows, software, ta, table, uid, warning, withCredentials; + $.extend(section, { + innerHTML: "
      Archiver
      404 Redirect is disabled.
      Thread redirectionPost fetchingFile redirection
      Captcha Language
      Choose from list of language codes. Leave blank to autoselect.
      Custom Board Navigation
      New lines will be converted into spaces.

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

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

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

        You can use these settings with each item, separate them with semicolons:
      • Possible items are: name, options (or equivalently email), subject and password.
      • Wrap values of items with quotes, like this: options:"sage".
      • Force values as defaults with the always keyword, for example: options:"sage";always.
      • Select specific boards for an item, separated with commas, for example: options:"sage";boards:jp;always.
      Unread Favicon is disabled.
      Thread Updater is disabled.
      Interval: seconds
      Custom Cooldown Time
      Seconds:
      " + }); + ref = $$('.warning', section); + for (j = 0, len = ref.length; j < len; j++) { + warning = ref[j]; + warning.hidden = Conf[warning.dataset.feature]; + } + items = {}; + inputs = {}; + ref1 = ['captchaLanguage', 'boardnav', 'time', 'backlink', 'fileInfo', 'favicon', 'usercss', 'customCooldown']; + for (k = 0, len1 = ref1.length; k < len1; k++) { + name = ref1[k]; + 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); + if (name in Settings) { + $.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 in Settings && key !== 'usercss') { + 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 (l = 0, len2 = ref2.length; l < len2; l++) { + ref3 = ref2[l], uid = ref3.uid, name = ref3.name, boards = ref3.boards, files = ref3.files, software = ref3.software, withCredentials = ref3.withCredentials; + for (m = 0, len3 = boards.length; m < len3; m++) { + boardID = boards[m]; + o = archBoards[boardID] || (archBoards[boardID] = { + thread: [[], []], + post: [[], []], + file: [[], []] + }); + i = +(!!withCredentials); + archive = [uid != null ? uid : name, name]; + o.thread[i].push(archive); + if (software === 'foolfuuka') { + o.post[i].push(archive); + } + if (indexOf.call(files, boardID) >= 0) { + o.file[i].push(archive); + } + } + } + for (boardID in archBoards) { + o = archBoards[boardID]; + ref4 = ['thread', 'post', 'file']; + for (n = 0, len4 = ref4.length; n < len4; n++) { + item = ref4[n]; + i = o[item][0].length ? 1 : 0; + o[item][i].push([null, 'disabled']); + o[item] = o[item][0].concat(o[item][1]); + } + } + rows = []; + boardOptions = []; + ref5 = Object.keys(archBoards).sort(); + for (q = 0, len5 = ref5.length; q < len5; q++) { + boardID = ref5[q]; + 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 (r = 0, len6 = ref6.length; r < len6; r++) { + item = ref6[r]; + $.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, id, select, selectedArchives, type; + selectedArchives = arg.selectedArchives; + for (boardID in selectedArchives) { + data = selectedArchives[boardID]; + for (type in data) { + id = data[type]; + if (select = $("select[data-boardid='" + boardID + "'][data-type='" + type + "']", section)) { + select.value = JSON.stringify(id); + } + } + } + }); + }, + 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', { + value: JSON.stringify(archive[0]), + textContent: archive[1] + })); + } + $.extend(td, { + innerHTML: "" + }); + select = td.firstElementChild; + if (!(select.disabled = length === 1)) { + select.setAttribute('data-boardid', boardID); + select.setAttribute('data-type', type); + $.on(select, 'change', Settings.saveSelectedArchive); + } + $.add(select, options); + return td; + }, + saveSelectedArchive: function() { + return $.get('selectedArchives', Conf['selectedArchives'], (function(_this) { + return function(arg) { + var name1, selectedArchives; + selectedArchives = arg.selectedArchives; + (selectedArchives[name1 = _this.dataset.boardid] || (selectedArchives[name1] = {}))[_this.dataset.type] = JSON.parse(_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, + isVideo: false, + isSpoiler: true, + tag: 'Loop' + } + }; + 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, ref, tbody, tr; + $.extend(section, { + innerHTML: "
      Keybinds are disabled.
      Allowed keys: a-z, 0-9, Ctrl, Shift, Alt, Meta, Enter, Esc, Up, Down, Right, Left.
      Press Backspace to disable a keybind.
      ActionsKeybinds
      " + }); + $('.warning', section).hidden = Conf['Keybinds']; + tbody = $('tbody', section); + items = {}; + inputs = {}; + ref = Config.hotkeys; + for (key in ref) { + arr = ref[key]; + tr = $.el('tr', { + innerHTML: "" + E(arr[1]) + "" + }); + input = $('input', tr); + input.name = key; + input.spellcheck = false; + items[key] = Conf[key]; + inputs[key] = input; + $.on(input, 'keydown', Settings.keybind); + $.add(tbody, tr); + } + return $.get(items, function(items) { + var val; + for (key in items) { + val = items[key]; + inputs[key].value = val; + } + }); + }, + keybind: function(e) { + var key; + if (e.keyCode === 9) { + return; + } + e.preventDefault(); + e.stopPropagation(); + if ((key = Keybinds.keyCode(e)) == null) { + return; + } + this.value = key; + return $.cb.value.call(this); + } + }; + + return Settings; + +}).call(this); + +UI = (function() { + var Menu, checkbox, dialog, drag, dragend, dragstart, hover, hoverend, hoverstart, touchend, touchmove, + bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, + slice = [].slice; + + dialog = function(id, position, properties) { + var child, el, i, len, move, 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); + this.setPosition = bind(this.setPosition, 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 entry, i, len, menu, ref; + 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 CloseMenu', this.close); + $.on(d, 'scroll', this.setPosition); + $.on(window, 'resize', this.setPosition); + $.add(button, menu); + this.setPosition(); + entry = $('.entry', menu); + this.focus(entry); + return menu.focus(); + }; + + Menu.prototype.setPosition = function() { + var bLeft, bRect, bTop, bottom, cHeight, cWidth, left, mRect, ref, ref1, right, top; + mRect = this.menu.getBoundingClientRect(); + bRect = lastToggledButton.getBoundingClientRect(); + bTop = window.scrollY + bRect.top; + bLeft = window.scrollX + bRect.left; + cHeight = doc.clientHeight; + cWidth = doc.clientWidth; + ref = bRect.top + bRect.height + mRect.height < cHeight ? [bRect.bottom + "px", ''] : ['', (cHeight - bRect.top) + "px"], top = ref[0], bottom = ref[1]; + ref1 = bRect.left + mRect.width < cWidth ? [bRect.left + "px", ''] : ['', (cWidth - bRect.right) + "px"], left = ref1[0], right = ref1[1]; + $.extend(this.menu.style, { + top: top, + right: right, + bottom: bottom, + left: left + }); + return this.menu.classList.toggle('left', right); + }; + + Menu.prototype.insertEntry = function(entry, parent, data) { + var err, i, len, ref, subEntry, submenu; + if (typeof entry.open === 'function') { + try { + if (!entry.open(data)) { + return; + } + } catch (_error) { + err = _error; + Main.handleErrors({ + message: "Error in building the " + this.type + " menu.", + error: err + }); + 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; + $.off(d, 'click scroll CloseMenu', this.close); + $.off(d, 'scroll', this.setPosition); + return $.off(window, 'resize', this.setPosition); + }; + + 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, i, left, len, ref, ref1, ref2, right, sRect, style, submenu, top; + 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, i, len, subEntries, subEntry; + 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, ref, screenHeight, screenWidth; + 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 i, len, ref, touch; + 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 i, len, ref, touch; + 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 cb, el, endEvents, height, latestEvent, noRemove, o, ref, root; + root = arg.root, el = arg.el, latestEvent = arg.latestEvent, endEvents = arg.endEvents, 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); + o.hover(o.latestEvent); + new MutationObserver(function() { + if (el.parentNode) { + return o.hover(o.latestEvent); + } + }).observe(el, { + childList: true + }); + $.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); + }; + + hoverstart.padding = 25; + + hover = function(e) { + var clientX, clientY, height, left, ref, right, style, threshold, top; + this.latestEvent = e; + height = (this.height || this.el.offsetHeight) + hoverstart.padding; + 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 + }; + +}).call(this); + +FappeTyme = (function() { + var FappeTyme; + + FappeTyme = { + init: function() { + var el, i, lc, len, ref, ref1, type; + if (!((Conf['Fappe Tyme'] || Conf['Werk Tyme']) && ((ref = g.VIEW) === 'index' || ref === 'thread'))) { + 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')); + } + Callbacks.Post.push({ + name: 'Fappe Tyme', + cb: this.node + }); + return Callbacks.CatalogThread.push({ + name: 'Werk Tyme', + cb: this.catalogNode + }); + }, + node: function() { + return this.nodes.root.classList.toggle('noFile', !this.file); + }, + 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]); + } + } + }; + + return FappeTyme; + +}).call(this); + +Gallery = (function() { + var Gallery; + + 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 Callbacks.Post.push({ + name: 'Gallery', + cb: this.node + }); + }, + node: function() { + var ref; + if (!((ref = this.file) != null ? ref.thumb : void 0)) { + 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, i, j, key, len, len1, menuButton, nodes, post, ref, ref1, ref2, ref3, thumb, value; + cb = Gallery.cb; + 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: "
      " + }); + 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'); + $.on(nodes.frame, 'click', cb.blank); + if (Conf['Mouse Wheel Volume']) { + $.on(nodes.frame, 'wheel', Volume.wheel); + } + $.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); + } + $.on(window, 'resize', Gallery.cb.setHeight); + ref2 = $$('.post .file'); + for (j = 0, len1 = ref2.length; j < len1; j++) { + file = ref2[j]; + post = Get.postFromNode(file); + if (!((ref3 = post.file) != null ? ref3.thumb : void 0)) { + 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.thumb && (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); + }, + load: function(thumb, errorCB) { + var elType, ext, file; + ext = thumb.href.match(/\w*$/); + elType = { + 'webm': 'video', + 'pdf': 'iframe' + }[ext] || 'img'; + file = $.el(elType, { + title: thumb.title + }); + $.extend(file.dataset, thumb.dataset); + $.on(file, 'error', errorCB); + file.src = thumb.href; + return file; + }, + open: function(thumb) { + var el, file, newID, nodes, oldID, post, ref; + nodes = Gallery.nodes; + oldID = +nodes.current.dataset.id; + newID = +thumb.dataset.id; + if (el = Gallery.images[oldID]) { + $.rmClass(el, 'gal-highlight'); + } + $.addClass(thumb, 'gal-highlight'); + nodes.thumbs.scrollTop = thumb.offsetTop + thumb.offsetHeight / 2 - nodes.thumbs.clientHeight / 2; + if (((ref = Gallery.cache) != null ? ref.dataset.id : void 0) === '' + newID) { + file = Gallery.cache; + $.off(file, 'error', Gallery.cacheError); + $.on(file, 'error', Gallery.error); + } else { + file = Gallery.load(thumb, Gallery.error); + } + $.off(nodes.current, 'error', Gallery.error); + ImageCommon.pause(nodes.current); + $.replace(nodes.current, file); + nodes.current = file; + if (file.nodeName === 'VIDEO') { + file.loop = true; + Volume.setup(file); + if (Conf['Autoplay']) { + file.play(); + } + if (Conf['Show Controls']) { + ImageCommon.addControls(file); + } + } + doc.classList.toggle('gal-pdf', file.nodeName === 'IFRAME'); + Gallery.cb.setHeight(); + nodes.count.textContent = +thumb.dataset.id + 1; + nodes.name.download = nodes.name.textContent = thumb.title; + nodes.name.href = thumb.href; + nodes.frame.scrollTop = 0; + nodes.next.focus(); + if (Gallery.slideshow && (newID > oldID || (oldID === Gallery.images.length - 1 && newID === 0))) { + Gallery.setupTimer(); + } else { + Gallery.cb.stop(); + } + if (Conf['Scroll to Post'] && (post = g.posts[file.dataset.post])) { + Header.scrollTo(post.nodes.root); + } + if (isNaN(oldID) || newID === (oldID + 1) % Gallery.images.length) { + return Gallery.cache = Gallery.load(Gallery.images[(newID + 1) % Gallery.images.length], Gallery.cacheError); + } + }, + 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)); + }, + cacheError: function() { + return delete Gallery.cache; + }, + 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 (!Conf['Autoplay'] && 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); + } + $.off(window, 'resize', Gallery.cb.setHeight); + return clearTimeout(Gallery.timeoutID); + }, + setFitness: function() { + return (this.checked ? $.addClass : $.rmClass)(doc, "gal-" + (this.name.toLowerCase().replace(/\s+/g, '-'))); + }, + setHeight: $.debounce(100, function() { + var current, dim, frame, height, minHeight, ref, ref1, ref2, style, width; + ref = Gallery.nodes, current = ref.current, frame = ref.frame; + style = current.style; + if (Conf['Stretch to Fit'] && (dim = (ref1 = g.posts[current.dataset.post]) != null ? ref1.file.dimensions : void 0)) { + ref2 = dim.split('x'), width = ref2[0], height = ref2[1]; + minHeight = Math.min(doc.clientHeight - 25, height / width * frame.clientWidth); + style.minHeight = minHeight + 'px'; + return style.minWidth = (width / height * minHeight) + 'px'; + } else { + return style.minHeight = style.minWidth = null; + } + }), + 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 === 'Hide Thumbnails' || name === 'Fit Width' || name === 'Fit Height') { + $.on(input, 'change', Gallery.cb.setFitness); + } + $.event('change', null, input); + $.on(input, 'change', $.cb.checked); + if (name === 'Hide Thumbnails' || name === 'Fit Width' || name === 'Fit Height' || name === 'Stretch to Fit') { + $.on(input, 'change', Gallery.cb.setHeight); + } + return { + el: label + }; + }, + createSubEntries: function() { + var delayInput, delayLabel, item, subEntries; + subEntries = (function() { + var i, len, ref, results; + ref = ['Hide Thumbnails', 'Fit Width', 'Fit Height', 'Stretch to Fit', '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: " + }); + delayInput = delayLabel.firstElementChild; + delayInput.value = Gallery.delay; + $.on(delayInput, 'change', Gallery.cb.setDelay); + $.on(delayInput, 'change', $.cb.value); + subEntries.push({ + el: delayLabel + }); + return subEntries; + } + } + }; + + return Gallery; + +}).call(this); + +ImageCommon = (function() { + var ImageCommon; + + 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 i, len, postObj, ref; + if (this.status === 404) { + post.kill(!post.isClone); + } + 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 $.engine !== 'gecko' || (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)); + } + }; + + return ImageCommon; + +}).call(this); + +ImageExpand = (function() { + var ImageExpand, + slice = [].slice; + + 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: " contract" + }); + return Callbacks.Post.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 (!Conf['Autoplay'] && ((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() { + return g.posts.forEach(function(post) { + var file, i, len, ref, video, visible; + 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, i, len, oldHeight, ref, ref1, scrollY, top, x; + 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'); + $.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, ref, thumb; + 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 = Math.min(doc.clientHeight - file.fullImage.getBoundingClientRect().bottom - 25, Header.getBottomOf(file.fullImage)); + 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, ref, subEntries; + 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 + }; + } + } + }; + + return ImageExpand; + +}).call(this); + +ImageHover = (function() { + var ImageHover; + + ImageHover = { + init: function() { + var ref; + if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { + return; + } + if (Conf['Image Hover']) { + Callbacks.Post.push({ + name: 'Image Hover', + cb: this.node + }); + } + if (Conf['Image Hover in Catalog']) { + return Callbacks.CatalogThread.push({ + name: 'Image Hover', + cb: this.catalogNode + }); + } + }, + node: function() { + if (!(this.file && (this.file.isImage || this.file.isVideo))) { + return; + } + return $.on(this.file.thumb, 'mouseover', ImageHover.mouseover(this)); + }, + catalogNode: function() { + var file; + file = this.thread.OP.file; + if (!(file && (file.isImage || file.isVideo))) { + return; + } + return $.on(this.nodes.thumb, 'mouseover', ImageHover.mouseover(this.thread.OP)); + }, + mouseover: function(post) { + return function(e) { + var el, error, file, height, isVideo, left, maxHeight, maxWidth, ref, ref1, ref2, right, scale, width, x; + 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; + maxWidth = Math.max(left, doc.clientWidth - right); + maxHeight = doc.clientHeight - UI.hover.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', + height: scale * height, + 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)); + }; + } + }; + + return ImageHover; + +}).call(this); + +ImageLoader = (function() { + var ImageLoader, + slice = [].slice; + + 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; + } + Callbacks.Post.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: " Prefetch Images" + }); + this.el = prefetch.firstElementChild; + $.on(this.el, 'change', this.toggle); + return Header.menu.addEntry({ + el: prefetch, + order: 98 + }); + }, + 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, i, len, ref, thumb, video; + file = post.file; + thumb = file.thumb; + video = $.el('video', { + preload: 'none', + loop: true, + muted: true, + poster: thumb.src || thumb.dataset.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 clone, el, file, i, isImage, isVideo, len, match, ref, replace, thumb, type, url; + 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 || thumb.dataset.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 ($.engine === 'gecko') { + $.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; + } + thumb.src = url; + return thumb.removeAttribute('data-src'); + }); + } + 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 i, len, ref1, ref2, thumb; + 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(); + } + } + }); + } + }; + + return ImageLoader; + +}).call(this); + +Metadata = (function() { + var Metadata; + + Metadata = { + init: function() { + var ref; + if (!(Conf['WEBM Metadata'] && ((ref = g.VIEW) === 'index' || ref === 'thread') && g.BOARD.ID !== 'f')) { + return; + } + return Callbacks.Post.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: "" + }); + $.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; + } + }; + + return Metadata; + +}).call(this); + +RevealSpoilers = (function() { + var RevealSpoilers; + + RevealSpoilers = { + init: function() { + var ref; + if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Reveal Spoiler Thumbnails'])) { + return; + } + return Callbacks.Post.push({ + name: 'Reveal Spoiler Thumbnails', + cb: this.node + }); + }, + node: function() { + var thumb; + if (!(!this.isClone && this.file && this.file.thumb && this.file.isSpoiler)) { + return; + } + thumb = this.file.thumb; + thumb.removeAttribute('style'); + thumb.style.maxHeight = thumb.style.maxWidth = this.isReply ? '125px' : '250px'; + if (thumb.src) { + return thumb.src = this.file.thumbURL; + } else { + return thumb.dataset.src = this.file.thumbURL; + } + } + }; + + return RevealSpoilers; + +}).call(this); + +Sauce = (function() { + var Sauce, + 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; }; + + Sauce = { + init: function() { + var err, j, len, link, links, ref, ref1; + if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Sauce'])) { + return; + } + links = []; + ref1 = Conf['sauces'].split('\n'); + for (j = 0, len = ref1.length; j < len; j++) { + link = ref1[j]; + 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', + className: 'sauce' + }); + return Callbacks.Post.push({ + name: 'Sauce', + cb: this.node + }); + }, + sandbox: function(url) { + return E.url({ + innerHTML: "[sb] " + E(url) + "" + }); + }, + rmOrigin: function(e) { + if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) { + return; + } + $.open(this.href); + return e.preventDefault(); + }, + createSauceLink: function(link, post) { + var a, ext, i, j, key, len, m, part, parts, ref, ref1, ref2, skip, url; + if (!(link = link.trim())) { + return null; + } + parts = {}; + ref = link.split(/;(?=(?:text|boards|types|sandbox):?)/); + for (i = j = 0, len = ref.length; j < len; i = ++j) { + 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) || '?'); + ext = post.file.url.match(/[^.]*$/)[0]; + skip = false; + for (key in parts) { + parts[key] = parts[key].replace(/%(T?URL|IMG|[sh]?MD5|board|name|%|semi)/g, function(_, parameter) { + var type; + type = Sauce.formatters[parameter](post, ext); + if (type == null) { + skip = true; + return ''; + } + if (key === 'url' && (parameter !== '%' && parameter !== 'semi')) { + if (/^javascript:/i.test(parts['url'])) { + type = JSON.stringify(type); + } + type = encodeURIComponent(type); + } + return type; + }); + } + if (skip) { + return null; + } + if (!(!parts['boards'] || (ref2 = post.board.ID, indexOf.call(parts['boards'].split(','), ref2) >= 0))) { + return null; + } + if (!(!parts['types'] || indexOf.call(parts['types'].split(','), ext) >= 0)) { + return null; + } + url = parts['url']; + if (parts['sandbox'] != null) { + url = Sauce.sandbox(url); + } + a = Sauce.link.cloneNode(true); + a.href = url; + a.textContent = parts['text']; + if (/^javascript:/i.test(parts['url'])) { + a.removeAttribute('target'); + } + if (parts['sandbox'] != null) { + $.on(a, 'click', Sauce.rmOrigin); + } + return a; + }, + node: function() { + var j, len, link, node, nodes, ref; + if (this.isClone || !this.file) { + return; + } + nodes = []; + ref = Sauce.links; + for (j = 0, len = ref.length; j < len; j++) { + link = ref[j]; + if (node = Sauce.createSauceLink(link, this)) { + nodes.push($.tn('\u00A0'), node); + } + } + return $.add(this.file.text, nodes); + }, + formatters: { + TURL: function(post) { + return post.file.thumbURL; + }, + URL: function(post) { + return post.file.url; + }, + IMG: function(post, ext) { + if (ext === 'gif' || ext === 'jpg' || ext === 'png') { + return post.file.url; + } else { + return post.file.thumbURL; + } + }, + MD5: function(post) { + return post.file.MD5; + }, + sMD5: function(post) { + var ref; + return (ref = post.file.MD5) != null ? ref.replace(/[+\/=]/g, function(c) { + return { + '+': '-', + '/': '_', + '=': '' + }[c]; + }) : void 0; + }, + hMD5: function(post) { + var c; + if (post.file.MD5) { + return ((function() { + var j, len, ref, results; + ref = atob(post.file.MD5); + results = []; + for (j = 0, len = ref.length; j < len; j++) { + c = ref[j]; + results.push(("0" + (c.charCodeAt(0).toString(16))).slice(-2)); + } + return results; + })()).join(''); + } + }, + board: function(post) { + return post.board.ID; + }, + name: function(post) { + return post.file.name; + }, + '%': function() { + return '%'; + }, + semi: function() { + return ';'; + } + } + }; + + return Sauce; + +}).call(this); + +Volume = (function() { + var Volume; + + Volume = { + init: function() { + var ref, ref1, unmuteEntry, volumeEntry; + 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 (Conf['Mouse Wheel Volume']) { + Callbacks.Post.push({ + name: 'Mouse Wheel Volume', + cb: this.node + }); + } + if ((ref1 = g.BOARD.ID) !== 'gif' && ref1 !== 'wsg') { + return; + } + if (Conf['Mouse Wheel Volume']) { + Callbacks.CatalogThread.push({ + name: 'Mouse Wheel Volume', + cb: this.catalogNode + }); + } + 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: " 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, key, muted, val, volume; + muted = this.muted, volume = this.volume; + items = { + 'Allow Sound': !muted, + 'Default Volume': volume + }; + for (key in items) { + val = items[key]; + if (Conf[key] === val) { + delete items[key]; + } + } + $.set(items); + $.extend(Conf, items); + if (Volume.inputs) { + Volume.inputs.unmute.checked = !muted; + return Volume.inputs.volume.value = volume; + } + }, + node: function() { + var ref, ref1; + if (!(((ref = this.board.ID) === 'gif' || ref === 'wsg') && ((ref1 = this.file) != null ? ref1.isVideo : void 0))) { + return; + } + $.on(this.file.thumb, 'wheel', Volume.wheel.bind(Header.hover)); + return $.on($('a', this.file.text), 'wheel', Volume.wheel.bind(this.file.thumb.parentNode)); + }, + catalogNode: function() { + var file; + file = this.thread.OP.file; + if (!(file != null ? file.isVideo : void 0)) { + return; + } + return $.on(this.nodes.thumb, 'wheel', Volume.wheel.bind(Header.hover)); + }, + wheel: function(e) { + var el, volume; + if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) { + return; + } + if (!(el = $('video:not([data-md5])', this))) { + 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(); + } + }; + + return Volume; + +}).call(this); + +Embedding = (function() { + var Embedding; + + Embedding = { + init: function() { + var j, len, ref, type; + if (!(Conf['Embedding'] || Conf['Link Title'])) { + return; + } + this.types = {}; + ref = this.ordered_types; + for (j = 0, len = ref.length; j < len; j++) { + type = ref[j]; + this.types[type.key] = type; + } + if (Conf['Floating Embeds']) { + this.dialog = UI.dialog('embedding', 'top: 50px; right: 0px;', { + innerHTML: "
      " + }); + this.media = $('#media-embed', this.dialog); + $.one(d, '4chanXInitFinished', this.ready); + } + if (Conf['Link Title']) { + return $.on(d, '4chanXInitFinished PostsInserted', function() { + var key, ref1, ref2, service; + 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, j, len, match, ref, type; + href = link.href; + ref = Embedding.ordered_types; + for (j = 0, len = ref.length; j < len; j++) { + type = ref[j]; + if (!(match = type.regExp.exec(href))) { + continue; + } + if (type.dummy) { + return; + } + return { + key: type.key, + uid: match[1], + options: match[2], + link: link + }; + } + }, + embed: function(data) { + var embed, href, key, link, name, options, post, ref, uid, value; + key = data.key, uid = data.uid, options = data.options, link = data.link, post = data.post; + href = link.href; + if (Embedding.types[key].httpOnly && location.protocol !== 'http:') { + return; + } + $.addClass(link, key.toLowerCase()); + embed = $.el('a', { + className: 'embedder', + href: 'javascript:;', + textContent: '(embed)' + }); + ref = { + key: key, + uid: uid, + options: options, + href: href + }; + for (name in ref) { + value = ref[name]; + embed.dataset[name] = value; + } + $.on(embed, 'click', Embedding.cb.toggle); + $.after(link, [$.tn(' '), embed]); + if (Conf['Auto-embed'] && !Conf['Floating Embeds'] && !post.isFetchedQuote && key !== 'TwitchTV') { + 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; + } + $.addClass(link, key.toLowerCase()); + 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) + "] Title Link Blocked (are you using NoScript?)" + }); + } + } + }, + flushTitles: function(service) { + var cb, data, j, len, queue; + queue = service.queue; + if (!(queue != null ? queue.length : void 0)) { + return; + } + service.queue = []; + cb = function() { + var data, j, len; + for (j = 0, len = queue.length; j < len; j++) { + data = queue[j]; + Embedding.cb.title(this, data); + } + }; + if (!$.cache(service.api((function() { + var j, len, results; + results = []; + for (j = 0, len = queue.length; j < len; j++) { + data = queue[j]; + results.push(data.uid); + } + return results; + })()), cb, { + responseType: 'json' + })) { + for (j = 0, len = queue.length; j < len; j++) { + data = queue[j]; + $.extend(data.link, { + innerHTML: "[" + E(data.key) + "] Title Link Blocked (are you using NoScript?)" + }); + } + } + }, + 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: none; width: 640px; height: 360px;'; + return container; + }, + title: function(req, data) { + var base1, j, k, key, len, len1, link, link2, options, post, post2, ref, ref1, service, status, text, uid; + 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 (j = 0, len = ref.length; j < len; j++) { + post2 = ref[j]; + ref1 = $$('a.linkify', post2.nodes.comment); + for (k = 0, len1 = ref1.length; k < len1; k++) { + link2 = ref1[k]; + if (!(link2.href === link.href)) { + continue; + } + if ((base1 = link2.dataset).original == null) { + base1.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.dataset.href + }); + } + }, { + key: 'Dailymotion', + regExp: /^\w+:\/\/(?:(?:www\.)?dailymotion\.com\/(?:embed\/)?video|dai\.ly)\/([A-Za-z0-9]+)[^?]*(.*)/, + el: function(a) { + var el, options, start; + options = (start = a.dataset.options.match(/[?&](start=\d+)/)) ? "?" + start[1] : ''; + el = $.el('iframe', { + src: "//www.dailymotion.com/embed/video/" + a.dataset.uid + options + }); + el.setAttribute("allowfullscreen", "true"); + return el; + }, + title: { + api: function(uid) { + return "https://api.dailymotion.com/video/" + uid; + }, + text: function(_) { + return _.title; + } + } + }, { + 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: "" + E(a.dataset.uid) + "" + }; + el.src = E.url(content); + 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: "" + }); + } + }, { + 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', { + src: "http://www.liveleak.com/ll_embed?i=" + a.dataset.uid + }); + el.setAttribute("allowfullscreen", "true"); + 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)?)/, + style: 'border: 0; width: 600px; height: 406px;', + el: function(a) { + return $.el('iframe', { + src: "//strawpoll.me/embed_1/" + a.dataset.uid + }); + } + }, { + key: 'TwitchTV', + regExp: /^\w+:\/\/(?:www\.)?twitch\.tv\/(\w[^#\&\?]*)/, + style: "border: none; width: 620px; height: 378px;", + el: function(a) { + var _, channel, flashvars, id, idprefix, j, len, obj, part, ref, result, seconds, start, type; + if (result = /(\w+)\/([bcv])\/(\d+)/i.exec(a.dataset.uid)) { + _ = result[0], channel = result[1], type = result[2], id = result[3]; + idprefix = type === 'b' ? 'a' : type; + flashvars = "channel=" + channel + "&start_volume=25&auto_play=false&videoId=" + idprefix + id; + if (start = a.dataset.href.match(/\bt=(\w+)/)) { + seconds = 0; + ref = start[1].match(/\d+[hms]/g); + for (j = 0, len = ref.length; j < len; j++) { + part = ref[j]; + seconds += +part.slice(0, -1) * { + 'h': 3600, + 'm': 60, + 's': 1 + }[part.slice(-1)]; + } + flashvars += "&initial_time=" + seconds; + } + } else { + channel = (/(\w+)/.exec(a.dataset.uid))[0]; + flashvars = "channel=" + channel + "&start_volume=25&auto_play=false"; + } + obj = $.el('object', { + data: '//www-cdn.jtvnw.net/swflibs/TwitchPlayer.swf' + }); + $.extend(obj, { + innerHTML: "" + }); + obj.children[1].value = flashvars; + return obj; + } + }, { + key: 'Vocaroo', + regExp: /^\w+:\/\/(?:www\.)?vocaroo\.com\/i\/(\w+)/, + style: '', + el: function(a) { + var el, type; + el = $.el('audio', { + controls: true, + preload: 'auto' + }); + type = el.canPlayType('audio/webm') ? 'webm' : 'mp3'; + el.src = "http://vocaroo.com/media_command.php?media=" + a.dataset.uid + "&command=download_" + type; + return el; + } + }, { + 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=https://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=|\bembed\/|\bv\/))([\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, j, len, ref; + ref = data.items; + for (j = 0, len = ref.length; j < len; j++) { + item = ref[j]; + if (item.id === uid) { + return item.snippet.title; + } + } + return 'Not Found'; + } + } + }, { + key: 'Loopvid', + regExp: /^\w+:\/\/(?:www\.)?loopvid.appspot.com\/#?((?:pf|kd|lv|gd|gh|db|dx|nn|cp|wu|ig|ky|mf|pc|gc)\/[\w\-\/]+(,[\w\-\/]+)*|fc\/\w+\/\d+)/, + style: 'max-width: 80vw; max-height: 80vh;', + el: function(a) { + var _, base, el, host, j, k, len, len1, name, names, ref, ref1, type, types, url; + el = $.el('video', { + controls: true, + preload: 'auto', + loop: true + }); + ref = a.dataset.uid.match(/(\w+)\/(.*)/), _ = ref[0], host = ref[1], names = ref[2]; + types = (function() { + switch (host) { + case 'gd': + case 'wu': + case 'fc': + return ['']; + case 'gc': + return ['giant', 'fat', 'zippy']; + default: + return ['.webm', '.mp4']; + } + })(); + ref1 = names.split(','); + for (j = 0, len = ref1.length; j < len; j++) { + name = ref1[j]; + for (k = 0, len1 = types.length; k < len1; k++) { + type = types[k]; + base = "" + name + type; + url = (function() { + switch (host) { + case 'pf': + return "https://web.archive.org/web/2/http://a.pomf.se/" + base; + case 'kd': + return "http://kastden.org/loopvid/" + base; + case 'lv': + return "http://kastden.org/_loopvid_media/lv/" + 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://dl.dropboxusercontent.com/u/" + base; + case 'dx': + return "https://dl.dropboxusercontent.com/" + base; + case 'nn': + return "http://naenara.eu/loopvids/" + base; + case 'cp': + return "https://copy.com/" + base; + case 'wu': + return "http://webmup.com/" + base + "/vid.webm"; + case 'ig': + return "https://i.imgur.com/" + base; + case 'ky': + return "https://kiyo.me/" + base; + case 'mf': + return "https://d.maxfile.ro/" + base; + case 'pc': + return "http://a.pomf.cat/" + base; + case 'fc': + return "//i.4cdn.org/" + base + ".webm"; + case 'gc': + return "https://" + type + ".gfycat.com/" + name + ".webm"; + } + })(); + $.add(el, $.el('source', { + src: url + })); + } + } + return el; + } + }, { + key: 'Clyp', + regExp: /^\w+:\/\/(?:www\.)?clyp\.it\/(\w+)/, + style: '', + el: function(a) { + var el, type; + el = $.el('audio', { + controls: true, + preload: 'auto' + }); + type = el.canPlayType('audio/ogg') ? 'ogg' : 'mp3'; + el.src = "https://clyp.it/" + a.dataset.uid + "." + type; + return el; + } + }, { + 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.dataset.href, + loop: /^https?:\/\/i\.4cdn\.org\//.test(a.dataset.href) + }); + } + } + ] + }; + + return Embedding; + +}).call(this); + +Linkify = (function() { + var Linkify; + + Linkify = { + init: function() { + var ref; + if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Linkify']) { + return; + } + if (Conf['Comment Expansion']) { + ExpandComment.callbacks.push(this.node); + } + Callbacks.Post.push({ + name: 'Linkify', + cb: this.node + }); + Callbacks.CatalogThread.push({ + name: 'Linkify', + cb: this.catalogNode + }); + return Embedding.init(); + }, + node: function() { + var j, k, len, len1, link, links, ref; + if (this.isClone) { + return Embedding.events(this); + } + if (!Linkify.regString.test(this.info.comment)) { + return; + } + ref = $$('a[href^="http://i.4cdn.org/"], a[href^="https://i.4cdn.org/"]', this.nodes.comment); + for (j = 0, len = ref.length; j < len; j++) { + link = ref[j]; + $.addClass(link, 'linkify'); + Embedding.process(link, this); + } + links = Linkify.process(this.nodes.comment); + for (k = 0, len1 = links.length; k < len1; k++) { + link = links[k]; + 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, part1, part2, ref, ref1, 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') { + if ((part1 = word.match(/(https?:\/\/)?([a-z\d-]+\.)*[a-z\d-]+$/i)) && (part2 = (ref = snapshot.snapshotItem(i)) != null ? (ref1 = ref.data) != null ? ref1.match(/^(\.[a-z\d-]+)*\//i) : void 0 : void 0) && (part1[0] + part2[0]).search(Linkify.regString) === 0) { + continue; + } else { + 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|xyz|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, encodedDomain, 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; + } + if (encodedDomain = text.match(/^(https?:\/\/[^\/]*%[0-9a-f]{2})(.*)$/i)) { + text = encodedDomain[1].replace(/%([0-9a-f]{2})/ig, function(x, y) { + if (y === '25') { + return x; + } else { + return String.fromCharCode(parseInt(y, 16)); + } + }) + encodedDomain[2]; + } + a = $.el('a', { + className: 'linkify', + rel: 'nofollow noreferrer', + target: '_blank', + href: text + }); + $.add(a, range.extractContents()); + range.insertNode(a); + return a; + } + }; + + return Linkify; + +}).call(this); + +ArchiveLink = (function() { + var ArchiveLink; + + ArchiveLink = { + init: function() { + var div, entry, i, len, ref, ref1, type; + 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'], ['Capcode', 'capcode'], ['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 + }; + } + }; + + return ArchiveLink; + +}).call(this); + +DeleteLink = (function() { + var DeleteLink; + + DeleteLink = { + auto: [{}, {}], + 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:;' + }); + this.nodes = { + menu: div.firstChild, + links: [postEl, fileEl] + }; + postEntry = { + el: postEl, + open: function() { + postEl.textContent = DeleteLink.linkText(false); + $.on(postEl, 'click', DeleteLink.toggle); + return true; + } + }; + fileEntry = { + el: fileEl, + open: function(arg) { + var file; + file = arg.file; + if (!file || file.isDead) { + return false; + } + fileEl.textContent = DeleteLink.linkText(true); + $.on(fileEl, 'click', DeleteLink.toggle); + return true; + } + }; + return Menu.menu.addEntry({ + el: div, + order: 40, + open: function(post) { + if (post.isDead) { + return false; + } + DeleteLink.post = post; + DeleteLink.nodes.menu.textContent = DeleteLink.menuText(); + DeleteLink.cooldown.start(post); + return true; + }, + subEntries: [postEntry, fileEntry] + }); + }, + menuText: function() { + var seconds; + if (seconds = DeleteLink.cooldown.seconds[DeleteLink.post.fullID]) { + return "Delete (" + seconds + ")"; + } else { + return 'Delete'; + } + }, + linkText: function(fileOnly) { + var text; + text = fileOnly ? 'File' : 'Post'; + if (DeleteLink.auto[+fileOnly][DeleteLink.post.fullID]) { + text = "Deleting " + (text.toLowerCase()) + "..."; + } + return text; + }, + toggle: function() { + var auto, fileOnly, post; + post = DeleteLink.post; + fileOnly = $.hasClass(this, 'delete-file'); + auto = DeleteLink.auto[+fileOnly]; + if (auto[post.fullID]) { + delete auto[post.fullID]; + } else { + auto[post.fullID] = true; + } + this.textContent = DeleteLink.linkText(fileOnly); + if (!DeleteLink.cooldown.seconds[post.fullID]) { + return DeleteLink["delete"](post, fileOnly); + } + }, + "delete": function(post, fileOnly) { + var form, link; + link = DeleteLink.nodes.links[+fileOnly]; + delete DeleteLink.auto[+fileOnly][post.fullID]; + if (post.fullID === DeleteLink.post.fullID) { + $.off(link, 'click', DeleteLink.toggle); + } + form = { + mode: 'usrdel', + onlyimgdel: fileOnly, + pwd: QR.persona.getPassword() + }; + form[post.ID] = 'delete'; + 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, post); + } + }, { + form: $.formData(form) + }); + }, + load: function(link, post, fileOnly, resDoc) { + var el, msg; + link.textContent = DeleteLink.linkText(fileOnly); + if (resDoc.title === '4chan - Banned') { + el = $.el('span', { + innerHTML: "You can't delete posts because you are banned." + }); + return new Notice('warning', el, 20); + } else if (msg = resDoc.getElementById('errmsg')) { + new Notice('warning', msg.textContent, 20); + if (post.fullID === DeleteLink.post.fullID) { + $.on(link, 'click', DeleteLink.toggle); + } + if (QR.cooldown.data && Conf['Cooldown'] && /\bwait\b/i.test(msg.textContent)) { + DeleteLink.cooldown.start(post, 5); + DeleteLink.auto[+fileOnly][post.fullID] = true; + return DeleteLink.nodes.links[+fileOnly].textContent = DeleteLink.linkText(fileOnly); + } + } else { + if (!fileOnly) { + QR.cooldown["delete"](post); + } + if (resDoc.title === 'Updating index...') { + (post.origin || post).kill(fileOnly); + } + if (post.fullID === DeleteLink.post.fullID) { + return link.textContent = 'Deleted'; + } + } + }, + error: function(link, post) { + new Notice('warning', 'Connection error, please retry.', 20); + if (post.fullID === DeleteLink.post.fullID) { + return $.on(link, 'click', DeleteLink.toggle); + } + }, + cooldown: { + seconds: {}, + start: function(post, seconds) { + if (DeleteLink.cooldown.seconds[post.fullID] != null) { + return; + } + if (seconds == null) { + seconds = QR.cooldown.secondsDeletion(post); + } + if (seconds > 0) { + DeleteLink.cooldown.seconds[post.fullID] = seconds; + return DeleteLink.cooldown.count(post); + } + }, + count: function(post) { + var fileOnly, i, len, ref; + if (post.fullID === DeleteLink.post.fullID) { + DeleteLink.nodes.menu.textContent = DeleteLink.menuText(); + } + if (DeleteLink.cooldown.seconds[post.fullID] > 0 && Conf['Cooldown']) { + DeleteLink.cooldown.seconds[post.fullID]--; + setTimeout(DeleteLink.cooldown.count, 1000, post); + } else { + delete DeleteLink.cooldown.seconds[post.fullID]; + ref = [false, true]; + for (i = 0, len = ref.length; i < len; i++) { + fileOnly = ref[i]; + if (DeleteLink.auto[+fileOnly][post.fullID]) { + DeleteLink["delete"](post, fileOnly); + } + } + } + } + } + }; + + return DeleteLink; + +}).call(this); + +DownloadLink = (function() { + var DownloadLink; + + 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; + } + }); + } + }; + + return DownloadLink; + +}).call(this); + +Menu = (function() { + var Menu; + + 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: "" + }); + this.menu = new UI.Menu('post'); + Callbacks.Post.push({ + name: 'Menu', + cb: this.node + }); + return Callbacks.CatalogThread.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; + } + }; + + return Menu; + +}).call(this); + +ReportLink = (function() { + var ReportLink; + + 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:;' + }); + $.on(a, 'click', ReportLink.report); + return Menu.menu.addEntry({ + el: a, + order: 10, + open: function(post) { + if (!(post.isDead || (post.thread.isDead && !post.thread.isArchived))) { + a.textContent = 'Report'; + ReportLink.url = "//sys.4chan.org/" + post.board + "/imgboard.php?mode=report&no=" + post; + if ((Conf['Use Recaptcha v1 in Reports'] && Main.jsEnabled) || d.cookie.indexOf('pass_enabled=1') >= 0) { + ReportLink.url += '&altc=1'; + ReportLink.dims = 'width=350,height=275'; + } else { + ReportLink.dims = 'width=400,height=550'; + } + } else if (Conf['Archive Report']) { + a.textContent = 'Report to archive'; + ReportLink.url = Redirect.to('report', { + boardID: post.board.ID, + postID: post.ID + }); + ReportLink.dims = 'width=700,height=475'; + } else { + ReportLink.url = ''; + } + return !!ReportLink.url; + } + }); + }, + report: function() { + var dims, id, set, url; + url = ReportLink.url, dims = ReportLink.dims; + id = Date.now(); + set = "toolbar=0,scrollbars=1,location=0,status=1,menubar=0,resizable=1," + dims; + return window.open(url, id, set); + } + }; + + return ReportLink; + +}).call(this); + +AntiAutoplay = (function() { + var AntiAutoplay; + + 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); + Callbacks.Post.push({ + name: 'Disable Autoplaying Sounds', + cb: this.node + }); + Callbacks.CatalogThread.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 i, iframe, j, len, len1, object, 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', ''); + $.addClass(iframe, 'autoplay-removed'); + } + 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', ''); + $.addClass(object, 'autoplay-removed'); + } + } + }; + + return AntiAutoplay; + +}).call(this); + +Banner = (function() { + var Banner, + slice = [].slice; + + 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","79.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","256.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","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 base, br, j, 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 (j = 0, len = ref.length; j < len; j++) { + br = ref[j]; + $.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, j, len, ref; + ref = $$('br', this); + for (j = 0, len = ref.length; j < len; j++) { + br = ref[j]; + $.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, j, len, ref, string, string2; + className = child.className; + child.title = "Ctrl/\u2318+click to edit board " + (className.slice(5).toLowerCase()); + child.spellcheck = false; + ref = ['click', 'keydown', 'blur']; + for (j = 0, len = ref.length; j < len; j++) { + event = ref[j]; + $.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 + }); + } + } + } + }; + + return Banner; + +}).call(this); + +CatalogLinks = (function() { + var CatalogLinks; + + CatalogLinks = { + init: function() { + var el, input, selector; + if ((Conf['External Catalog'] || Conf['JSON Index']) && !(Conf['JSON Index'] && 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, i, len, link, ref; + ref = $$(selector); + for (i = 0, len = ref.length; i < len; i++) { + link = ref[i]; + switch (link.pathname.replace(/\/+/g, '/')) { + case "/" + g.BOARD + "/": + if (Conf['JSON Index']) { + link.textContent = 'Index'; + } + link.href = CatalogLinks.index(); + break; + case "/" + g.BOARD + "/catalog": + link.href = CatalogLinks.catalog(); + } + if (g.VIEW === 'catalog' && Conf['JSON Index'] && 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 Index'] && Conf['Use 4chan X Catalog']) { + Callbacks.Post.push({ + name: 'Catalog Link Rewrite', + cb: this.node + }); + Callbacks.CatalogThread.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, i, len, m, 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 (!CatalogLinks.el) { + 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') || !(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 + "/"; + if (a.dataset.indexOptions && a.hostname === 'boards.4chan.org' && a.pathname.split('/')[2] === '') { + a.href += (a.hash ? '/' : '#') + a.dataset.indexOptions; + } + } + 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 Index'] && 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 Index'] && board !== 'f') { + if (g.BOARD.ID === board && g.VIEW === 'index') { + return '#index'; + } else { + return "/" + board + "/#index"; + } + } else { + return "/" + board + "/"; + } + } + }; + + return CatalogLinks; + +}).call(this); + +CustomCSS = (function() { + var CustomCSS; + + CustomCSS = { + init: function() { + if (!Conf['Custom CSS']) { + return; + } + return this.addStyle(); + }, + addStyle: function() { + return this.style = $.addStyle(Conf['usercss'], 'custom-css', '#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']; + } + }; + + return CustomCSS; + +}).call(this); + +ExpandComment = (function() { + var ExpandComment; + + ExpandComment = { + init: function() { + if (g.VIEW !== 'index' || !Conf['Comment Expansion'] || Conf['JSON Index']) { + return; + } + if (g.BOARD.ID === 'g') { + this.callbacks.push(Fourchan.code); + } + if (g.BOARD.ID === 'sci') { + this.callbacks.push(Fourchan.math); + } + return Callbacks.Post.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, i, j, k, len, len1, len2, postObj, posts, quote, ref, ref1, spoilerRange, status; + 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); + } + } + }; + + return ExpandComment; + +}).call(this); + +ExpandThread = (function() { + var ExpandThread, + slice = [].slice; + + ExpandThread = { + statuses: {}, + init: function() { + if (g.VIEW === 'thread' || !Conf['Thread Expansion']) { + return; + } + if (Conf['JSON Index']) { + return $.on(d, 'IndexRefresh', this.onIndexRefresh); + } else { + return Callbacks.Thread.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 = Build.summaryText.apply(Build, ['+'].concat(slice.call(a.textContent.match(/\d+/g)))); + a.style.cursor = 'pointer'; + return $.on(a, 'click', ExpandThread.cbToggle); + }, + disconnect: function(refresh) { + var ref, ref1, status, threadID; + 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); + }); + }, + 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); + } + }, + expand: function(thread, a) { + var status; + ExpandThread.statuses[thread] = status = {}; + a.textContent = Build.summaryText.apply(Build, ['...'].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, i, inlined, len, num, postsCount, replies, reply, status; + status = ExpandThread.statuses[thread]; + delete ExpandThread.statuses[thread]; + if (status.req) { + status.req.abort(); + if (a) { + a.textContent = Build.summaryText.apply(Build, ['+'].concat(slice.call(a.textContent.match(/\d+/g)))); + } + return; + } + replies = $$('.thread > .replyContainer', threadRoot); + if (!Conf['JSON Index'] || 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 = Build.summaryText('+', postsCount, filesCount); + }, + parse: function(req, thread, a) { + var filesCount, i, len, post, postData, posts, postsCount, postsRoot, ref, ref1, root; + 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 = Build.summaryText('-', postsCount, filesCount); + } + }; + + return ExpandThread; + +}).call(this); + +FileInfo = (function() { + var FileInfo; + + FileInfo = { + init: function() { + var ref; + if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['File Info Formatting']) { + return; + } + return Callbacks.Post.push({ + name: 'File Info Formatting', + cb: this.node + }); + }, + node: function() { + var info, oldInfo; + if (!this.file || this.isClone) { + return; + } + oldInfo = $.el('span', { + className: 'fileText-original' + }); + $.prepend(this.file.link.parentNode, oldInfo); + $.add(oldInfo, [this.file.link.previousSibling, this.file.link, this.file.link.nextSibling]); + info = $.el('span', { + className: 'file-info' + }); + FileInfo.format(Conf['fileInfo'], this, info); + return $.prepend(this.file.text, info); + }, + 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: E.cat(output) + }); + }, + formatters: { + t: function() { + return { + innerHTML: E(this.file.url.match(/[^/]*$/)[0]) + }; + }, + T: function() { + return { + innerHTML: "" + (FileInfo.formatters.t.call(this)).innerHTML + "" + }; + }, + l: function() { + return { + innerHTML: "" + (FileInfo.formatters.n.call(this)).innerHTML + "" + }; + }, + L: function() { + return { + innerHTML: "" + (FileInfo.formatters.N.call(this)).innerHTML + "" + }; + }, + 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: "" + E(shortname) + "" + E(fullname) + "" + }; + } + }, + N: function() { + return { + innerHTML: E(this.file.name) + }; + }, + p: function() { + return { + innerHTML: ((this.file.isSpoiler) ? "Spoiler, " : "") + }; + }, + 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") + }; + }, + g: function() { + return { + innerHTML: ((this.file.tag) ? ", " + E(this.file.tag) : "") + }; + }, + '%': function() { + return { + innerHTML: "%" + }; + } + } + }; + + return FileInfo; + +}).call(this); + +Flash = (function() { + var Flash; + + Flash = { + init: function() { + if (g.BOARD.ID === 'f' && Conf['Enable Native Flash Embedding']) { + return $.ready(Flash.initReady); + } + }, + initReady: function() { + if ($.hasStorage) { + return $.global(function() { + if (JSON.parse(localStorage['4chan-settings'] || '{}').disableAll) { + return window.SWFEmbed.init(); + } + }); + } else { + if (g.VIEW === 'thread') { + $.global(function() { + return window.Main.tid = location.pathname.split(/\/+/)[3]; + }); + } + return $.global(function() { + return window.SWFEmbed.init(); + }); + } + } + }; + + return Flash; + +}).call(this); + +Fourchan = (function() { + var Fourchan; + + Fourchan = { + init: function() { + var ref; + if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { + return; + } + if (g.BOARD.ID === 'g') { + $.on(window, 'prettyprint:cb', function(e) { + var post, pre; + if (!(post = g.posts[e.detail.ID])) { + return; + } + if (!(pre = $$('.prettyprint', post.nodes.comment)[e.detail.i])) { + return; + } + if (!$.hasClass(pre, 'prettyprinted')) { + pre.innerHTML = e.detail.html; + return $.addClass(pre, 'prettyprinted'); + } + }); + $.globalEval('window.addEventListener(\'prettyprint\', function(e) {\n window.dispatchEvent(new CustomEvent(\'prettyprint:cb\', {\n detail: {\n ID: e.detail.ID,\n i: e.detail.i,\n html: prettyPrintOne(e.detail.html)\n }\n }));\n}, false);'); + Callbacks.Post.push({ + name: 'Parse /g/ code', + cb: this.code + }); + } + if (g.BOARD.ID === 'sci') { + $.global(function() { + return window.addEventListener('mathjax', function(e) { + if (window.MathJax) { + return window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub, e.target]); + } else { + if (!document.querySelector('script[src^="//cdn.mathjax.org/"]')) { + window.loadMathJax(); + window.loadMathJax = function() {}; + } + if (!e.target.classList.contains('postMessage')) { + return document.querySelector('script[src^="//cdn.mathjax.org/"]').addEventListener('load', function() { + return window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub, e.target]); + }, false); + } + } + }, false); + }); + Callbacks.Post.push({ + name: 'Parse /sci/ math', + cb: this.math + }); + Callbacks.CatalogThread.push({ + name: 'Parse /sci/ math', + cb: this.math + }); + } + return Main.ready(function() { + return $.global(function() { + var j, len, node, ref1; + window.clickable_ids = false; + ref1 = document.querySelectorAll('.posteruid, .capcode'); + for (j = 0, len = ref1.length; j < len; j++) { + node = ref1[j]; + node.removeEventListener('click', window.idClick, false); + } + }); + }); + }, + code: function() { + if (this.isClone) { + return; + } + return $.ready((function(_this) { + return function() { + var i, j, len, pre, ref; + ref = $$('.prettyprint', _this.nodes.comment); + for (i = j = 0, len = ref.length; j < len; i = ++j) { + pre = ref[i]; + if (!$.hasClass(pre, 'prettyprinted')) { + $.event('prettyprint', { + ID: _this.fullID, + i: i, + html: pre.innerHTML + }, window); + } + } + }; + })(this)); + }, + math: function() { + var cb, j, len, wbr, wbrs; + if (!/\[(math|eqn)\]/.test(this.nodes.comment.textContent)) { + return; + } + if ((wbrs = $$('wbr', this.nodes.comment)).length) { + for (j = 0, len = wbrs.length; j < len; j++) { + wbr = wbrs[j]; + $.rm(wbr); + } + this.nodes.comment.normalize(); + } + cb = (function(_this) { + return function() { + if (!doc.contains(_this.nodes.comment)) { + return; + } + $.off(d, 'PostsInserted', cb); + return $.event('mathjax', null, _this.nodes.comment); + }; + })(this); + $.on(d, 'PostsInserted', cb); + return cb(); + } + }; + + return Fourchan; + +}).call(this); + +IDColor = (function() { + var IDColor; + + 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 Callbacks.Post.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; + } + }; + + return IDColor; + +}).call(this); + +IDHighlight = (function() { + var IDHighlight; + + IDHighlight = { + init: function() { + var ref; + if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { + return; + } + return Callbacks.Post.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); + }; + } + }; + + return IDHighlight; + +}).call(this); + +Keybinds = (function() { + var Keybinds; + + Keybinds = { + init: function() { + var hotkey, init; + if (!Conf['Keybinds']) { + return; + } + for (hotkey in Config.hotkeys) { + $.sync(hotkey, Keybinds.sync); + } + init = function() { + var i, len, node, 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, i, key, len, notification, notifications, op, ref, ref1, ref2, ref3, ref4, ref5, searchInput, target, thread, threadRoot; + 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) && !/^Alt\+(\d|Up|Down|Left|Right)$/.test(key))) { + return; + } + } + if (!(((ref1 = g.VIEW) !== 'index' && ref1 !== 'thread') || g.VIEW === 'index' && Conf['JSON Index'] && Conf['Index Mode'] === 'catalog' || g.VIEW === 'index' && g.BOARD.ID === 'f')) { + 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['SJIS tags']: + if (target.nodeName !== 'TEXTAREA') { + return; + } + Keybinds.tags('sjis', 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 Index'] && g.BOARD.ID !== 'f')) { + return; + } + Index.update(); + break; + default: + return; + } + break; + case Conf['Watch']: + if (!(ThreadWatcher.enabled && thread)) { + return; + } + ThreadWatcher.toggle(thread); + break; + case Conf['Update thread watcher']: + if (!ThreadWatcher.enabled) { + return; + } + ThreadWatcher.buttonFetchAll(); + 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'))) { + return; + } + FappeTyme.toggle('fappe'); + break; + case Conf['werkTyme']: + if (!(Conf['Werk Tyme'] && ((ref3 = g.VIEW) === 'index' || ref3 === 'thread'))) { + return; + } + FappeTyme.toggle('werk'); + break; + case Conf['Front page']: + if (Conf['JSON Index'] && g.VIEW === 'index' && g.BOARD.ID !== 'f') { + 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' && g.BOARD.ID !== 'f')) { + return; + } + if (Conf['JSON Index']) { + 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' && g.BOARD.ID !== 'f')) { + return; + } + if (Conf['JSON Index']) { + 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' && g.BOARD.ID !== 'f')) { + return; + } + searchInput = Conf['JSON Index'] ? Index.searchInput : $.id('search-box'); + Header.scrollToIfNeeded(searchInput); + searchInput.focus(); + break; + case Conf['Paged mode']: + if (!(Conf['JSON Index'] && g.BOARD.ID !== 'f')) { + return; + } + window.location = g.VIEW === 'index' ? '#paged' : "/" + g.BOARD + "/#paged"; + break; + case Conf['Infinite scrolling mode']: + if (!(Conf['JSON Index'] && g.BOARD.ID !== 'f')) { + return; + } + window.location = g.VIEW === 'index' ? '#infinite' : "/" + g.BOARD + "/#infinite"; + break; + case Conf['All pages mode']: + if (!(Conf['JSON Index'] && g.BOARD.ID !== 'f')) { + return; + } + window.location = g.VIEW === 'index' ? '#all-pages' : "/" + g.BOARD + "/#all-pages"; + break; + case Conf['Open catalog']: + if (g.BOARD.ID === 'f') { + return; + } + window.location = CatalogLinks.catalog(); + break; + case Conf['Cycle sort type']: + if (!(Conf['JSON Index'] && g.VIEW === 'index' && g.BOARD.ID !== '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 && QuoteYou.db)) { + return; + } + QuoteYou.cb.seek('preceding'); + break; + case Conf['Next Post Quoting You']: + if (!(threadRoot && QuoteYou.db)) { + 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 32: + return 'Space'; + case 37: + return 'Left'; + case 38: + return 'Up'; + case 39: + return 'Right'; + case 40: + return 'Down'; + case 188: + return 'Comma'; + case 190: + return 'Period'; + case 191: + return 'Slash'; + case 59: + case 186: + return 'Semicolon'; + default: + if ((48 <= kc && kc <= 57) || (65 <= kc && kc <= 90)) { + return String.fromCharCode(kc).toLowerCase(); + } else if ((96 <= kc && kc <= 105)) { + return String.fromCharCode(kc - 48).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'; + case 'sjis': + return g.BOARD.ID === 'jp'; + } + })(); + 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, i, len, next, postEl, replies, reply, root; + 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'); + } + }; + + return Keybinds; + +}).call(this); + +Nav = (function() { + var Nav; + + 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 i, len, ref, thread, threadRoot; + 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, ref, thread, top; + 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); + } + } + }; + + return Nav; + +}).call(this); + +NormalizeURL = (function() { + var NormalizeURL; + + NormalizeURL = { + init: function() { + var pathname; + if (!Conf['Normalize URL']) { + return; + } + pathname = location.pathname.split(/\/+/); + switch (g.VIEW) { + case 'thread': + pathname[2] = 'thread'; + pathname = pathname.slice(0, 4); + break; + case 'index': + pathname = pathname.slice(0, 3); + } + pathname = pathname.join('/'); + if (location.pathname !== pathname) { + return history.replaceState(history.state, '', location.protocol + "//" + location.host + pathname + location.hash); + } + } + }; + + return NormalizeURL; + +}).call(this); + +PSAHiding = (function() { + var PSAHiding; + + 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: "[Dismiss]" + }); + $.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() { + 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; + } + } + }; + + return PSAHiding; + +}).call(this); + +RelativeDates = (function() { + var RelativeDates, + 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; }; + + 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 Index'] && g.BOARD.ID !== 'f') { + this.flush(); + $.on(d, 'visibilitychange ThreadUpdate', this.flush); + } + if (Conf['Relative Post Dates']) { + return Callbacks.Post.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, i, len, now, 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, i, isPost, len, ref, relative, singlePost; + 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); + } + }; + + return RelativeDates; + +}).call(this); + +RemoveSpoilers = (function() { + var RemoveSpoilers, + slice = [].slice; + + RemoveSpoilers = { + init: function() { + if (Conf['Reveal Spoilers']) { + $.addClass(doc, 'reveal-spoilers'); + } + if (!Conf['Remove Spoilers']) { + return; + } + Callbacks.Post.push({ + name: 'Reveal Spoilers', + cb: this.node + }); + Callbacks.CatalogThread.push({ + name: 'Reveal Spoilers', + cb: this.node + }); + if (g.VIEW === 'archive') { + return $.ready(function() { + return RemoveSpoilers.unspoiler($.id('arc-list')); + }); + } + }, + node: function() { + return RemoveSpoilers.unspoiler(this.nodes.comment); + }, + unspoiler: function(el) { + var i, len, span, spoiler, spoilers; + 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)); + } + } + }; + + return RemoveSpoilers; + +}).call(this); + +Report = (function() { + var Report; + + Report = { + init: function() { + var match; + if (!(match = location.search.match(/\bno=(\d+)/))) { + return; + } + Captcha.replace.init(); + this.postID = +match[1]; + return $.ready(this.ready); + }, + ready: function() { + var passAd, prev, ref; + $.addStyle(CSS.report); + if (Conf['Archive Report']) { + Report.archive(); + } + if ((passAd = $('a[href="https://www.4chan.org/pass"]'))) { + $.extend(passAd, { + textContent: 'Complain', + href: 'https://www.4chan-x.net/captchas.html', + tabIndex: -1 + }); + passAd.parentNode.normalize(); + if (((ref = (prev = passAd.previousSibling)) != null ? ref.nodeType : void 0) === Node.TEXT_NODE) { + prev.nodeValue = prev.nodeValue.replace(/4chan Pass[^\.]*\./i, 'reCAPTCHA malfunctioning?'); + } + $.after(passAd, [ + $.tn('] ['), $.el('a', { + href: 'mailto:4chanpass@4chan.org?subject=4chan%20Pass%20-%20Purchase%20Support', + textContent: 'Email 4chan', + target: '_blank', + tabIndex: -1 + }) + ]); + } + if (!Conf['Use Recaptcha v1 in Reports'] && !Conf['Force Noscript Captcha'] && Main.jsEnabled) { + return new MutationObserver(function() { + Report.fit('iframe[src^="https://www.google.com/recaptcha/api2/frame"]'); + return Report.fit('body'); + }).observe(d.body, { + childList: true, + attributes: true, + subtree: true + }); + } else { + return Report.fit('body'); + } + }, + fit: function(selector) { + var dy, el; + if (!((el = $(selector, doc)) && getComputedStyle(el).visibility !== 'hidden')) { + return; + } + dy = el.getBoundingClientRect().bottom - doc.clientHeight + 8; + if (dy > 0) { + return window.resizeBy(0, dy); + } + }, + archive: function() { + var link, message, types, url; + Redirect.init(); + if (!(url = Redirect.to('report', { + boardID: g.BOARD.ID, + postID: Report.postID + }))) { + return; + } + if ((message = $('h3')) && /Report submitted!/.test(message.textContent)) { + if (location.hash === '#redirect') { + $.globalEval('self.close = function(){};'); + window.resizeTo(700, 475); + location.replace(url); + } + return; + } + link = $.el('a', { + href: url, + textContent: 'Report to archive' + }); + $.on(link, 'click', function(e) { + if (!(e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0)) { + return window.resizeTo(700, 475); + } + }); + $.add(d.body, [$.tn(' ['), link, $.tn(']')]); + if (types = $.id('reportTypes')) { + return $.on(types, 'change', function(e) { + return $('form').action = e.target.value === 'illegal' ? '#redirect' : ''; + }); + } + } + }; + + return Report; + +}).call(this); + +ThreadLinks = (function() { + var ThreadLinks; + + ThreadLinks = { + init: function() { + if (!(g.VIEW === 'index' && Conf['Open Threads in New Tab'])) { + return; + } + Callbacks.Post.push({ + name: 'Thread Links', + cb: this.node + }); + return Callbacks.CatalogThread.push({ + name: 'Thread Links', + cb: this.catalogNode + }); + }, + node: function() { + if (this.isReply || this.isClone) { + return; + } + return ThreadLinks.process($('.replylink', this.nodes.info)); + }, + catalogNode: function() { + return ThreadLinks.process(this.nodes.thumb.parentNode); + }, + process: function(link) { + return link.target = '_blank'; + } + }; + + return ThreadLinks; + +}).call(this); + +Time = (function() { + var Time; + + Time = { + init: function() { + var ref; + if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Time Formatting'])) { + return; + } + return Callbacks.Post.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 '%'; + } + } + }; + + return Time; + +}).call(this); + +Favicon = (function() { + var Favicon; + + 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==' + }; + + return Favicon; + +}).call(this); + +MarkNewIPs = (function() { + var MarkNewIPs; + + MarkNewIPs = { + init: function() { + if (g.VIEW !== 'thread' || !Conf['Mark New IPs']) { + return; + } + return Callbacks.Thread.push({ + name: 'Mark New IPs', + cb: this.node + }); + }, + node: function() { + MarkNewIPs.ipCount = this.ipCount; + MarkNewIPs.postCount = this.posts.keys.length; + return $.on(d, 'ThreadUpdate', MarkNewIPs.onUpdate); + }, + onUpdate: function(e) { + var deletedPosts, fullID, i, ipCount, j, k, len, len1, newPosts, postCount, ref; + ref = e.detail, ipCount = ref.ipCount, postCount = ref.postCount, newPosts = ref.newPosts, deletedPosts = ref.deletedPosts; + if (ipCount == null) { + return; + } + switch (ipCount - MarkNewIPs.ipCount) { + case postCount - MarkNewIPs.postCount + deletedPosts.length: + i = MarkNewIPs.ipCount; + for (j = 0, len = newPosts.length; j < len; j++) { + fullID = newPosts[j]; + MarkNewIPs.markNew(g.posts[fullID], ++i); + } + break; + case -deletedPosts.length: + for (k = 0, len1 = newPosts.length; k < len1; k++) { + fullID = newPosts[k]; + MarkNewIPs.markOld(g.posts[fullID]); + } + } + MarkNewIPs.ipCount = ipCount; + return MarkNewIPs.postCount = postCount; + }, + 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'); + } + }; + + return MarkNewIPs; + +}).call(this); + +ReplyPruning = (function() { + var ReplyPruning; + + ReplyPruning = { + init: function() { + var el, label; + if (!(g.VIEW === 'thread' && Conf['Reply Pruning'])) { + return; + } + this.active = !(Conf['Quote Threading'] && Conf['Thread Quotes']); + this.container = $.frag(); + this.summary = $.el('span', { + hidden: true, + className: 'summary' + }); + this.summary.style.cursor = 'pointer'; + $.on(this.summary, 'click', (function(_this) { + return function() { + _this.inputs.enabled.checked = !_this.inputs.enabled.checked; + return $.event('change', null, _this.inputs.enabled); + }; + })(this)); + label = UI.checkbox('Prune Replies', 'Show Last', this.active); + el = $.el('span', { + title: 'Maximum number of replies to show.' + }, { + innerHTML: " " + }); + $.prepend(el, label); + this.inputs = { + enabled: label.firstElementChild, + replies: el.lastElementChild + }; + $.on(this.inputs.enabled, 'change', this.setEnabled); + $.on(this.inputs.replies, 'change', $.cb.value); + Header.menu.addEntry({ + el: el, + order: 190 + }); + return Callbacks.Thread.push({ + name: 'Reply Pruning', + cb: this.node + }); + }, + position: 0, + hidden: 0, + hiddenFiles: 0, + total: 0, + totalFiles: 0, + setEnabled: function() { + var other; + other = QuoteThreading.input; + if (this.checked && (other != null ? other.checked : void 0)) { + other.checked = false; + $.event('change', null, other); + } + return ReplyPruning.active = this.checked; + }, + showIfHidden: function(id) { + var ref; + if ((ref = ReplyPruning.container) != null ? ref.getElementById(id) : void 0) { + ReplyPruning.inputs.enabled.checked = false; + return $.event('change', null, ReplyPruning.inputs.enabled); + } + }, + node: function() { + var ref; + ReplyPruning.thread = this; + this.posts.forEach(function(post) { + if (post.isReply) { + ReplyPruning.total++; + if (post.file) { + return ReplyPruning.totalFiles++; + } + } + }); + if (ReplyPruning.active && /^#p\d+$/.test(location.hash) && (0 <= (ref = this.posts.keys.indexOf(location.hash.slice(2))) && ref < 1 + Math.max(ReplyPruning.total - +Conf["Max Replies"], 0))) { + ReplyPruning.active = ReplyPruning.inputs.enabled.checked = false; + } + $.after(this.OP.nodes.root, ReplyPruning.summary); + $.on(ReplyPruning.inputs.enabled, 'change', ReplyPruning.update); + $.on(ReplyPruning.inputs.replies, 'change', ReplyPruning.update); + $.on(d, 'ThreadUpdate', ReplyPruning.updateCount); + $.on(d, 'ThreadUpdate', ReplyPruning.update); + return ReplyPruning.update(); + }, + updateCount: function(e) { + var fullID, i, len, ref; + if (e.detail[404]) { + return; + } + ref = e.detail.newPosts; + for (i = 0, len = ref.length; i < len; i++) { + fullID = ref[i]; + ReplyPruning.total++; + if (g.posts[fullID].file) { + ReplyPruning.totalFiles++; + } + } + }, + update: function() { + var boardTop, frag, hidden2, oldPos, post, posts; + hidden2 = ReplyPruning.active ? Math.max(ReplyPruning.total - +Conf["Max Replies"], 0) : 0; + oldPos = d.body.clientHeight - window.scrollY; + posts = ReplyPruning.thread.posts; + if (ReplyPruning.hidden < hidden2) { + while (ReplyPruning.hidden < hidden2 && ReplyPruning.position < posts.keys.length) { + post = posts[posts.keys[ReplyPruning.position++]]; + if (post.isReply && !post.isFetchedQuote) { + $.add(ReplyPruning.container, post.nodes.root); + ReplyPruning.hidden++; + if (post.file) { + ReplyPruning.hiddenFiles++; + } + } + } + } else if (ReplyPruning.hidden > hidden2) { + frag = $.frag(); + while (ReplyPruning.hidden > hidden2 && ReplyPruning.position > 0) { + post = posts[posts.keys[--ReplyPruning.position]]; + if (post.isReply && !post.isFetchedQuote) { + $.prepend(frag, post.nodes.root); + ReplyPruning.hidden--; + if (post.file) { + ReplyPruning.hiddenFiles--; + } + } + } + $.after(ReplyPruning.summary, frag); + $.event('PostsInserted'); + } + ReplyPruning.summary.textContent = ReplyPruning.active ? Build.summaryText('+', ReplyPruning.hidden, ReplyPruning.hiddenFiles) : Build.summaryText('-', ReplyPruning.total, ReplyPruning.totalFiles); + ReplyPruning.summary.hidden = ReplyPruning.total <= +Conf["Max Replies"]; + if ((boardTop = Header.getTopOf($('.board'))) < 0) { + return window.scroll(window.scrollX, Math.max(d.body.clientHeight - oldPos, window.scrollY + boardTop)); + } + } + }; + + return ReplyPruning; + +}).call(this); + +ThreadExcerpt = (function() { + var ThreadExcerpt; + + ThreadExcerpt = { + init: function() { + if (g.BOARD.ID !== 'f' || g.VIEW !== 'thread' || !Conf['Thread Excerpt']) { + return; + } + return Callbacks.Thread.push({ + name: 'Thread Excerpt', + cb: this.node + }); + }, + node: function() { + return d.title = Get.threadExcerpt(this); + } + }; + + return ThreadExcerpt; + +}).call(this); + +ThreadStats = (function() { + var ThreadStats; + + ThreadStats = { + init: function() { + var sc, statsHTML, statsTitle; + if (g.VIEW !== 'thread' || !Conf['Thread Stats']) { + return; + } + statsHTML = { + innerHTML: "? / ?" + ((Conf["IP Count in Stats"]) ? " / ?" : "") + ((Conf["Page Count in Stats"]) ? " / ?" : "") + }; + statsTitle = 'Posts / Files'; + if (Conf['IP Count in Stats']) { + statsTitle += ' / IPs'; + } + if (Conf['Page Count in Stats']) { + statsTitle += (g.BOARD.ID === 'f' ? ' / Purge Position' : ' / 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: "
      " + (statsHTML).innerHTML + "
      " + }); + $.addClass(doc, 'float'); + $.ready(function() { + return $.add(d.body, sc); + }); + } + this.postCountEl = $('#post-count', sc); + this.fileCountEl = $('#file-count', sc); + this.ipCountEl = $('#ip-count', sc); + this.pageCountEl = $('#page-count', sc); + if (this.pageCountEl) { + $.on(this.pageCountEl, 'click', ThreadStats.fetchPage); + } + return Callbacks.Thread.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 (ThreadStats.pageCountEl) { + 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 (!ThreadStats.pageCountEl) { + return; + } + if (newPosts.length) { + ThreadStats.lastPost = g.posts[newPosts[newPosts.length - 1]].info.date; + } + if (g.BOARD.ID !== 'f' && ((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) && ipCountEl) { + ipCountEl.textContent = ipCount; + } + (thread.postLimit && !thread.isSticky ? $.addClass : $.rmClass)(postCountEl, 'warning'); + return (thread.fileLimit && !thread.isSticky ? $.addClass : $.rmClass)(fileCountEl, 'warning'); + }, + fetchPage: function() { + if (!ThreadStats.pageCountEl) { + 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: 'ThreadStats' + }); + }, + onThreadsLoad: function() { + var i, j, k, len, len1, len2, page, purgePos, ref, ref1, ref2, thread; + if (this.status === 200) { + ref = this.response; + for (i = 0, len = ref.length; i < len; i++) { + page = ref[i]; + if (g.BOARD.ID === 'f') { + purgePos = 1; + ref1 = page.threads; + for (j = 0, len1 = ref1.length; j < len1; j++) { + thread = ref1[j]; + if (thread.no < ThreadStats.thread.ID) { + purgePos++; + } + } + ThreadStats.pageCountEl.textContent = purgePos; + } else { + ref2 = page.threads; + for (k = 0, len2 = ref2.length; k < len2; k++) { + thread = ref2[k]; + 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); + ThreadStats.retry(); + return; + } + } + } + } else if (this.status === 304) { + return ThreadStats.retry(); + } + }, + retry: function() { + var ref; + if (g.BOARD.ID !== 'f' && ThreadStats.lastPost > ThreadStats.lastPageUpdate && ((ref = ThreadStats.pageCountEl) != null ? ref.textContent : void 0) !== '1') { + clearTimeout(ThreadStats.timeout); + return ThreadStats.timeout = setTimeout(ThreadStats.fetchPage, 5 * $.SECOND); + } + } + }; + + return ThreadStats; + +}).call(this); + +ThreadUpdater = (function() { + var ThreadUpdater, + 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; }; + + ThreadUpdater = { + init: function() { + var conf, el, input, name, ref, sc, subEntries, updateLink; + if (g.VIEW !== 'thread' || !Conf['Thread Updater']) { + return; + } + this.audio = $.el('audio', { + src: ThreadUpdater.beep + }); + if (Conf['Updater and Stats in Header']) { + this.dialog = sc = $.el('span', { + id: 'updater' + }); + $.extend(sc, { + innerHTML: "" + }); + $.ready(function() { + return Header.addShortcut(sc); + }); + } else { + this.dialog = sc = UI.dialog('updater', 'bottom: 0px; left: 0px;', { + innerHTML: "
      " + }); + $.addClass(doc, 'float'); + $.ready(function() { + return $.add(d.body, sc); + }); + } + this.checkPostCount = 0; + this.timer = $('#update-timer', sc); + this.status = $('#update-status', sc); + $.on(this.timer, 'click', this.update); + $.on(this.status, 'click', this.update); + updateLink = $.el('span', { + className: 'brackets-wrap updatelink' + }); + $.extend(updateLink, { + innerHTML: "Update" + }); + Main.ready(function() { + var navLinksBot; + if ((navLinksBot = $('.navLinksBot'))) { + 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.setInterval); + } + subEntries.push({ + el: el + }); + } + this.settings = $.el('span', { + innerHTML: "Interval" + }); + $.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 Callbacks.Thread.push({ + name: 'Thread Updater', + cb: this.node + }); + }, + node: function() { + ThreadUpdater.thread = this; + ThreadUpdater.root = this.OP.nodes.root.parentNode; + ThreadUpdater.outdateCount = 0; + ThreadUpdater.postIDs = []; + ThreadUpdater.fileIDs = []; + this.posts.forEach(function(post) { + ThreadUpdater.postIDs.push(post.ID); + if (post.file) { + return ThreadUpdater.fileIDs.push(post.ID); + } + }); + ThreadUpdater.cb.interval.call($.el('input', { + value: Conf['Interval'] + })); + $.on(d, 'QRPostSuccessful', ThreadUpdater.cb.checkpost); + $.on(d, 'visibilitychange', ThreadUpdater.cb.visibility); + return ThreadUpdater.setInterval(); + }, + + /* + 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', + playBeep: function() { + var audio; + audio = ThreadUpdater.audio; + if (audio.paused) { + return audio.play(); + } else { + return $.one(audio, 'ended', ThreadUpdater.playBeep); + } + }, + cb: { + checkpost: function(e) { + if (e.detail.threadID !== ThreadUpdater.thread.ID) { + return; + } + ThreadUpdater.postID = e.detail.postID; + ThreadUpdater.checkPostCount = 0; + ThreadUpdater.outdateCount = 0; + return ThreadUpdater.setInterval(); + }, + 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; + }; + }, + 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() { + var req; + req = ThreadUpdater.req; + switch (req.status) { + case 200: + ThreadUpdater.parse(req); + if (ThreadUpdater.thread.isArchived) { + return ThreadUpdater.kill(); + } else { + return ThreadUpdater.setInterval(); + } + break; + case 404: + return $.ajax("//a.4cdn.org/" + ThreadUpdater.thread.board + "/catalog.json", { + onloadend: function() { + var confirmed, i, k, len, len1, page, ref, ref1, thread; + 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 (k = 0, len1 = ref1.length; k < len1; k++) { + thread = ref1[k]; + if (thread.no === ThreadUpdater.thread.ID) { + confirmed = false; + break; + } + } + } + } else { + confirmed = false; + } + if (confirmed) { + return ThreadUpdater.kill(); + } else { + return ThreadUpdater.error(req); + } + } + }); + default: + return ThreadUpdater.error(req); + } + } + }, + kill: function() { + ThreadUpdater.thread.kill(); + ThreadUpdater.setInterval(); + return $.event('ThreadUpdate', { + 404: true, + threadID: ThreadUpdater.thread.fullID + }); + }, + error: function(req) { + if (req.status === 304) { + ThreadUpdater.set('status', ''); + } + ThreadUpdater.setInterval(); + if (!req.status) { + return ThreadUpdater.set('status', 'Connection Failed', 'warning'); + } else if (req.status !== 304) { + return ThreadUpdater.set('status', req.statusText + " (" + req.status + ")", 'warning'); + } + }, + setInterval: function() { + var cur, interval, j, limit; + clearTimeout(ThreadUpdater.timeoutID); + if (ThreadUpdater.thread.isDead) { + ThreadUpdater.set('status', (ThreadUpdater.thread.isArchived ? 'Archived' : '404'), 'warning'); + ThreadUpdater.set('timer', ''); + return; + } + if (ThreadUpdater.postID && ThreadUpdater.checkPostCount < 5) { + ThreadUpdater.set('timer', '...', 'loading'); + ThreadUpdater.timeoutID = setTimeout(ThreadUpdater.update, ++ThreadUpdater.checkPostCount * $.SECOND); + return; + } + if (!Conf['Auto Update']) { + ThreadUpdater.set('timer', 'Update'); + return; + } + interval = ThreadUpdater.interval; + if (Conf['Optional Increase']) { + limit = d.hidden ? 10 : 5; + j = Math.min(ThreadUpdater.outdateCount, limit); + cur = (Math.floor(interval * 0.1) || 1) * j * j; + ThreadUpdater.seconds = $.minmax(cur, interval, 300); + } else { + ThreadUpdater.seconds = interval; + } + return ThreadUpdater.timeout(); + }, + 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; + } + return el.className = klass != null ? klass : (text === '' ? 'empty' : ''); + }, + timeout: function() { + if (ThreadUpdater.seconds) { + ThreadUpdater.set('timer', ThreadUpdater.seconds); + ThreadUpdater.timeoutID = setTimeout(ThreadUpdater.timeout, 1000); + } else { + ThreadUpdater.outdateCount++; + ThreadUpdater.update(); + } + return ThreadUpdater.seconds--; + }, + update: function() { + var ref; + clearTimeout(ThreadUpdater.timeoutID); + ThreadUpdater.set('timer', '...', 'loading'); + 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: 'ThreadUpdater' + }); + }, + 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(req) { + var ID, OP, board, deletedFiles, deletedPosts, files, firstPost, i, index, ipCountEl, k, l, lastPost, len, len1, len2, len3, m, newPosts, node, post, postObject, postObjects, posts, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, scroll, thread, unreadCount, unreadQYCount; + postObjects = req.response.posts; + OP = postObjects[0]; + thread = ThreadUpdater.thread; + board = thread.board; + ref = ThreadUpdater.postIDs, lastPost = ref[ref.length - 1]; + if (postObjects[postObjects.length - 1].no < lastPost && new Date(req.getResponseHeader('Last-Modified')) - thread.posts[lastPost].info.date < 30 * $.SECOND) { + return; + } + Build.spoilerRange[board] = OP.custom_spoiler; + thread.setStatus('Archived', !!OP.archived); + ThreadUpdater.updateThreadStatus('Sticky', !!OP.sticky); + ThreadUpdater.updateThreadStatus('Closed', !!OP.closed); + thread.postLimit = !!OP.bumplimit; + thread.fileLimit = !!OP.imagelimit; + if (OP.unique_ips != null) { + thread.ipCount = OP.unique_ips; + } + posts = []; + index = []; + files = []; + newPosts = []; + for (i = 0, len = postObjects.length; i < len; i++) { + postObject = postObjects[i]; + ID = postObject.no; + index.push(ID); + if (postObject.fsize) { + files.push(ID); + } + if (ID <= lastPost) { + continue; + } + if ((post = thread.posts[ID]) && !post.isFetchedQuote) { + post.resurrect(); + continue; + } + newPosts.push(board + "." + ID); + node = Build.postFromObject(postObject, board.ID); + posts.push(new Post(node, thread, board)); + if (ThreadUpdater.postID === ID) { + delete ThreadUpdater.postID; + } + } + deletedPosts = []; + ref1 = ThreadUpdater.postIDs; + for (k = 0, len1 = ref1.length; k < len1; k++) { + ID = ref1[k]; + if (!(indexOf.call(index, ID) < 0)) { + continue; + } + thread.posts[ID].kill(); + deletedPosts.push(board + "." + ID); + } + ThreadUpdater.postIDs = index; + deletedFiles = []; + ref2 = ThreadUpdater.fileIDs; + for (l = 0, len2 = ref2.length; l < len2; l++) { + ID = ref2[l]; + if (!(!(indexOf.call(files, ID) >= 0 || (ref3 = board + "." + ID, indexOf.call(deletedPosts, ref3) >= 0)))) { + continue; + } + thread.posts[ID].kill(true); + deletedFiles.push(board + "." + ID); + } + ThreadUpdater.fileIDs = files; + if (!posts.length) { + ThreadUpdater.set('status', ''); + } else { + ThreadUpdater.set('status', "+" + posts.length, 'new'); + ThreadUpdater.outdateCount = 0; + unreadCount = (ref4 = Unread.posts) != null ? ref4.size : void 0; + unreadQYCount = (ref5 = Unread.postsQuotingYou) != null ? ref5.size : void 0; + Main.callbackNodes('Post', posts); + if (d.hidden || !d.hasFocus()) { + if (Conf['Beep Quoting You'] && ((ref6 = Unread.postsQuotingYou) != null ? ref6.size : void 0) > unreadQYCount) { + ThreadUpdater.playBeep(); + if (Conf['Beep']) { + ThreadUpdater.playBeep(); + } + } else if (Conf['Beep'] && ((ref7 = Unread.posts) != null ? ref7.size : void 0) > 0 && unreadCount === 0) { + ThreadUpdater.playBeep(); + } + } + scroll = Conf['Auto Scroll'] && ThreadUpdater.scrollBG() && ThreadUpdater.root.getBoundingClientRect().bottom - doc.clientHeight < 25; + firstPost = null; + for (m = 0, len3 = posts.length; m < len3; m++) { + post = posts[m]; + if (!QuoteThreading.insert(post)) { + firstPost || (firstPost = post.nodes.root); + $.add(ThreadUpdater.root, post.nodes.root); + } + } + $.event('PostsInserted'); + if (scroll) { + if (Conf['Bottom Scroll']) { + window.scrollTo(0, d.body.clientHeight); + } else { + if (firstPost) { + Header.scrollTo(firstPost); + } + } + } + } + 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'); + } + return $.event('ThreadUpdate', { + 404: false, + threadID: thread.fullID, + newPosts: newPosts, + deletedPosts: deletedPosts, + deletedFiles: deletedFiles, + postCount: OP.replies + 1, + fileCount: OP.images + !!OP.fsize, + ipCount: OP.unique_ips + }); + } + }; + + return ThreadUpdater; + +}).call(this); + +ThreadWatcher = (function() { + var ThreadWatcher, + slice = [].slice; + + ThreadWatcher = { + init: function() { + var sc; + if (!(this.enabled = 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: "
      Thread Watcher ×
      " + }); + this.status = $('#watcher-status', this.dialog); + this.list = this.dialog.lastElementChild; + this.refreshButton = $('.refresh', this.dialog); + this.closeButton = $('.move > .close', this.dialog); + this.unreaddb = Unread.db || new DataBoard('lastReadPosts'); + this.unreadEnabled = Conf['Remember Last Read Post']; + $.on(d, 'QRPostSuccessful', this.cb.post); + $.on(sc, 'click', this.toggleWatcher); + $.on(this.refreshButton, 'click', this.buttonFetchAll); + $.on(this.closeButton, '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['Fixed Thread Watcher']) { + $.addClass(doc, 'fixed-watcher'); + } + if (Conf['Toggleable Thread Watcher']) { + this.dialog.hidden = true; + Header.addShortcut(sc); + $.addClass(doc, 'toggleable-watcher'); + } + ThreadWatcher.fetchAuto(); + if (g.VIEW === 'index' && Conf['JSON Index'] && Conf['Menu'] && g.BOARD.ID !== 'f') { + Menu.menu.addEntry({ + el: $.el('a', { + href: 'javascript:;', + className: 'has-shortcut-text' + }, { + innerHTML: "Alt+click" + }), + order: 6, + open: function(arg) { + var thread; + thread = arg.thread; + if (Conf['Index Mode'] !== 'catalog') { + return false; + } + this.el.firstElementChild.textContent = ThreadWatcher.isWatched(thread) ? 'Unwatch' : 'Watch'; + 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; + } + }); + } + Callbacks.Post.push({ + name: 'Thread Watcher', + cb: this.node + }); + return Callbacks.CatalogThread.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('a', { + href: 'javascript:;', + 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'); + } + $.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)); + return $.on(this.nodes.thumb.parentNode, 'mousedown', function(e) { + if (e.button === 0 && e.altKey) { + return e.preventDefault(); + } + }); + }, + ready: function() { + $.off(d, '4chanXInitFinished', ThreadWatcher.ready); + if (!Main.isThisPageLegit()) { + return; + } + ThreadWatcher.refresh(); + $.add(d.body, ThreadWatcher.dialog); + 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, i, len, ref, ref1, threadID; + if ($.hasClass(this, 'disabled')) { + return; + } + ThreadWatcher.db.forceSync(); + 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, ref, threadID; + ref = this.parentNode.dataset.fullID.split('.'), boardID = ref[0], threadID = ref[1]; + return ThreadWatcher.rm(boardID, +threadID); + }, + post: function(e) { + var boardID, postID, ref, threadID; + 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, ref, threadID; + db = ThreadWatcher.db; + boardID = g.BOARD.ID; + db.forceSync(); + ref = db.data.boards[boardID]; + for (threadID in ref) { + data = ref[threadID]; + if (!(data != null ? data.isDead : void 0) && !(threadID in g.BOARD.threads)) { + if (Conf['Auto Prune'] || !(data && typeof data === 'object')) { + db["delete"]({ + boardID: boardID, + threadID: threadID + }); + } else { + if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { + ThreadWatcher.fetchStatus({ + boardID: boardID, + threadID: threadID, + data: data + }); + } + data.isDead = true; + 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); + } + }, + requests: [], + fetched: 0, + clearRequests: function() { + ThreadWatcher.requests = []; + ThreadWatcher.fetched = 0; + ThreadWatcher.status.textContent = ''; + return $.rmClass(ThreadWatcher.refreshButton, 'fa-spin'); + }, + abort: function() { + var i, len, ref, req; + ref = ThreadWatcher.requests; + for (i = 0, len = ref.length; i < len; i++) { + req = ref[i]; + if (req.readyState !== 4) { + req.abort(); + } + } + return ThreadWatcher.clearRequests(); + }, + fetchAuto: function() { + var db, interval, now; + clearTimeout(ThreadWatcher.timeout); + if (!Conf['Auto Update Thread Watcher']) { + return; + } + db = ThreadWatcher.db; + interval = ThreadWatcher.unreadEnabled && 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); + }, + buttonFetchAll: function() { + if (ThreadWatcher.requests.length) { + return ThreadWatcher.abort(); + } else { + return ThreadWatcher.fetchAllStatus(); + } + }, + fetchAllStatus: function() { + var i, len, ref, thread, threads; + ThreadWatcher.db.forceSync(); + ThreadWatcher.unreaddb.forceSync(); + if ((ref = QuoteYou.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, req, threadID; + boardID = thread.boardID, threadID = thread.threadID, data = thread.data; + if (data.isDead && !force) { + return; + } + if (ThreadWatcher.requests.length === 0) { + ThreadWatcher.status.textContent = '...'; + $.addClass(ThreadWatcher.refreshButton, 'fa-spin'); + } + req = $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", { + onloadend: function() { + return ThreadWatcher.parseStatus.call(this, thread); + }, + timeout: $.MINUTE + }, { + whenModified: force ? false : 'ThreadWatcher' + }); + return ThreadWatcher.requests.push(req); + }, + parseStatus: function(arg) { + var boardID, data, i, isDead, lastReadPost, len, match, postObj, quotesYou, quotingYou, ref, ref1, regexp, threadID, unread; + boardID = arg.boardID, threadID = arg.threadID, data = arg.data; + ThreadWatcher.fetched++; + if (ThreadWatcher.fetched === ThreadWatcher.requests.length) { + ThreadWatcher.clearRequests(); + } else { + ThreadWatcher.status.textContent = (Math.round(ThreadWatcher.fetched / ThreadWatcher.requests.length * 100)) + "%"; + } + 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 = QuoteYou.db) != null ? ref1.get({ + boardID: boardID, + threadID: threadID, + postID: postObj.no + }) : void 0) { + continue; + } + unread++; + if (!(QuoteYou.db && postObj.com)) { + continue; + } + quotesYou = false; + regexp = /]*\bhref="(?:\/([^\/]+)\/thread\/)?(\d+)?(?:#p(\d+))?"/g; + while (match = regexp.exec(postObj.com)) { + if (QuoteYou.db.get({ + boardID: match[1] || boardID, + threadID: match[2] || threadID, + postID: match[3] || match[2] || threadID + })) { + quotesYou = true; + break; + } + } + if (quotesYou && !Filter.isHidden(Build.parseJSON(postObj, boardID))) { + quotingYou++; + } + } + 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, ref, threadID, threads; + 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]; + if (data && typeof data === 'object') { + 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 (ThreadWatcher.unreadEnabled && 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 (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { + if (data.unread === 0) { + $.addClass(div, 'replies-read'); + } + 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, i, j, len, len1, list, nodes, ref, ref1, ref2, refresher, threadID; + 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, j, len1, post, ref2, toggler; + 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, ref, val; + 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(); + } + }, + set404: function(boardID, threadID, cb) { + var data, ref; + if (!(data = (ref = ThreadWatcher.db) != null ? ref.get({ + boardID: boardID, + threadID: threadID + }) : void 0)) { + return cb(); + } + if (Conf['Auto Prune']) { + ThreadWatcher.db["delete"]({ + boardID: boardID, + threadID: threadID + }); + return cb(); + } + if (data.isDead && !((data.unread != null) || (data.quotingYou != null))) { + return cb(); + } + data.isDead = true; + delete data.unread; + delete data.quotingYou; + return ThreadWatcher.db.set({ + boardID: boardID, + threadID: threadID, + val: data + }, cb); + }, + 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 (ThreadWatcher.unreadEnabled && 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(); + }, + 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, ref, rmClass, text; + 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, i, len, name, ref, ref1, refresh, subEntries; + 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; + if (name === 'Show Unread Count' && !ThreadWatcher.unreadEnabled) { + input.disabled = true; + $.addClass(entry.el, 'disabled'); + entry.el.title += '\n[Remember Last Read Post is disabled.]'; + } + $.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; + } + } + }; + + return ThreadWatcher; + +}).call(this); + +Unread = (function() { + var Unread; + + Unread = { + init: function() { + if (!(g.VIEW === 'thread' && (Conf['Unread Count'] || Conf['Unread Favicon'] || Conf['Unread Line'] || Conf['Remember Last Read Post'] || Conf['Desktop Notifications'] || Conf['Quote Threading']))) { + return; + } + if (Conf['Remember Last Read Post']) { + $.sync('Remember Last Read Post', function(enabled) { + return Conf['Remember Last Read Post'] = enabled; + }); + 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; + Callbacks.Thread.push({ + name: 'Unread', + cb: this.node + }); + return Callbacks.Post.push({ + name: 'Unread', + cb: this.addPost + }); + }, + node: function() { + var ID, j, len, ref, ref1; + Unread.thread = this; + Unread.title = d.title; + Unread.lastReadPost = ((ref = Unread.db) != null ? ref.get({ + boardID: this.board.ID, + threadID: this.ID + }) : void 0) || 0; + Unread.readCount = 0; + ref1 = this.posts.keys; + for (j = 0, len = ref1.length; j < len; j++) { + ID = ref1[j]; + if (+ID <= Unread.lastReadPost) { + Unread.readCount++; + } + } + $.one(d, '4chanXInitFinished', Unread.ready); + return $.on(d, 'ThreadUpdate', Unread.onUpdate); + }, + ready: function() { + if (Conf['Remember Last Read Post'] && Conf['Scroll to Last Read Post']) { + Unread.scroll(); + } + Unread.setLine(true); + Unread.read(); + Unread.update(); + $.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, ref, root; + if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) { + return; + } + ReplyPruning.showIfHidden((ref = Unread.position) != null ? ref.data.nodes.root.id : void 0); + 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, j, lastReadPost, postIDs, 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 = j = ref = Unread.readCount, ref1 = postIDs.length; j < ref1; i = j += 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 = QuoteYou.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 j, len, quotelink, ref, ref1; + ref = post.nodes.quotelinks; + for (j = 0, len = ref.length; j < len; j++) { + quotelink = ref[j]; + if (!((ref1 = QuoteYou.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; + } + try { + notif = new Notification(post.info.nameBlock + " replied to you", { + body: post.info.commentDisplay, + icon: Favicon.logo + }); + notif.onclick = function() { + Header.scrollToIfNeeded(post.nodes.root, true); + return $.global(function() { + return window.focus(); + }); + }; + return notif.onshow = function() { + return setTimeout(function() { + return notif.close(); + }, 7 * $.SECOND); + }; + } catch (_error) {} + }, + 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, ref, ref1, root; + if (!Unread.posts.size && Unread.readCount !== Unread.thread.posts.keys.length) { + Unread.saveLastReadPost(); + } + if (d.hidden || !Unread.posts.size) { + return; + } + 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 ((ref1 = QuoteYou.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, j, postIDs, ref, ref1; + $.forceSync('Remember Last Read Post'); + if (!(Conf['Remember Last Read Post'] && Unread.db)) { + return; + } + postIDs = Unread.thread.posts.keys; + for (i = j = ref = Unread.readCount, ref1 = postIDs.length; j < ref1; i = j += 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 (Unread.hr.hidden || 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, isDead, 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; + } + $.forceSync('Remember Last Read Post'); + if (Conf['Remember Last Read Post'] && (!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']) { + isDead = Unread.thread.isDead; + Favicon.el.href = countQuotingYou ? Favicon[isDead ? 'unreadDeadY' : 'unreadY'] : count ? Favicon[isDead ? 'unreadDead' : 'unread'] : Favicon[isDead ? 'dead' : 'default']; + return $.add(d.head, Favicon.el); + } + } + }; + + return Unread; + +}).call(this); + +Captcha = {}; + +(function() { + Captcha.fixes = { + imageKeys: '789456123uiojklm'.split('').concat(['Comma', 'Period']), + imageKeys16: '7890uiopjkl'.split('').concat(['Semicolon', 'm', 'Comma', 'Period', 'Slash']), + css: '.rc-imageselect-target > div:focus, .rc-image-tile-target:focus {\n outline: 2px solid #4a90e2;\n}\n.rc-imageselect-target td:focus {\n box-shadow: inset 0 0 0 2px #4a90e2;\n outline: none;\n}\n.rc-button-default:focus {\n box-shadow: inset 0 0 0 2px #0063d6;\n}', + cssNoscript: '.fbc-payload-imageselect {\n position: relative;\n}\n.fbc-payload-imageselect > label {\n position: absolute;\n display: block;\n height: 93.3px;\n width: 93.3px;\n}\nlabel[data-row="0"] {top: 0px;}\nlabel[data-row="1"] {top: 93.3px;}\nlabel[data-row="2"] {top: 186.6px;}\nlabel[data-col="0"] {left: 0px;}\nlabel[data-col="1"] {left: 93.3px;}\nlabel[data-col="2"] {left: 186.6px;}\n.fbc-payload-imageselect > input:focus + label {\n outline: 2px solid #4a90e2;\n}\n.fbc-button-verify input:focus {\n box-shadow: inset 0 0 0 2px #0063d6;\n}\nbody.focus .fbc {\n box-shadow: inset 0 0 0 2px #4a90e2;\n}', + init: function() { + switch (location.pathname.split('/')[3]) { + case 'anchor': + return this.initMain(); + case 'frame': + return this.initPopup(); + case 'fallback': + return this.initNoscript(); + } + }, + initMain: function() { + var a, j, len, ref; + $.onExists(d.body, '#recaptcha-anchor', function(checkbox) { + var focus; + focus = function() { + var ref; + if (d.hasFocus() && ((ref = d.activeElement) === d.documentElement || ref === d.body)) { + return checkbox.focus(); + } + }; + focus(); + return $.on(window, 'focus', function() { + return $.queueTask(focus); + }); + }); + ref = $$('.rc-anchor-pt a'); + for (j = 0, len = ref.length; j < len; j++) { + a = ref[j]; + a.tabIndex = -1; + } + }, + initPopup: function() { + $.addStyle(this.css); + this.fixImages(); + new MutationObserver((function(_this) { + return function() { + return _this.fixImages(); + }; + })(this)).observe(d.body, { + childList: true, + subtree: true + }); + return $.on(d, 'keydown', this.keybinds.bind(this)); + }, + initNoscript: function() { + var data, ref, token; + this.noscript = true; + data = (token = (ref = $('.fbc-verification-token > textarea')) != null ? ref.value : void 0) ? { + token: token + } : { + working: true + }; + new Connection(window.parent, '*').send(data); + d.body.classList.toggle('focus', d.hasFocus()); + $.on(window, 'focus blur', function() { + return d.body.classList.toggle('focus', d.hasFocus()); + }); + this.images = $$('.fbc-payload-imageselect > input'); + this.width = 3; + if (this.images.length !== 9) { + return; + } + $.addStyle(this.cssNoscript); + this.addLabels(); + $.on(d, 'keydown', this.keybinds.bind(this)); + return $.on($('.fbc-imageselect-challenge > form'), 'submit', this.checkForm.bind(this)); + }, + fixImages: function() { + var img, j, len, ref; + this.images = $$('.rc-image-tile-target'); + if (!this.images.length) { + this.images = $$('.rc-imageselect-target > div, .rc-imageselect-target td'); + } + this.width = $$('.rc-imageselect-target tr:first-of-type td').length || Math.round(Math.sqrt(this.images.length)); + ref = this.images; + for (j = 0, len = ref.length; j < len; j++) { + img = ref[j]; + img.tabIndex = 0; + } + if (this.images.length === 9) { + this.addTooltips(this.images); + } else { + this.addTooltips16(this.images); + } + return this.complaintLinks(); + }, + complaintLinks: function() { + var errmsg, j, len, link, ref; + ref = $$('.rc-imageselect-incorrect-response, .rc-imageselect-error-select-one, .rc-imageselect-error-select-more, .rc-imageselect-error-dynamic-more'); + for (j = 0, len = ref.length; j < len; j++) { + errmsg = ref[j]; + if (!$('a', errmsg)) { + link = $.el('a', { + href: 'https://www.4chan-x.net/captchas.html', + target: '_blank', + textContent: '[complain]' + }); + $.add(errmsg, [$.tn(' '), link]); + } + } + }, + addLabels: function() { + var checkbox, i, imageSelect, label, labels; + imageSelect = $('.fbc-payload-imageselect'); + labels = (function() { + var j, len, ref, results; + ref = this.images; + results = []; + for (i = j = 0, len = ref.length; j < len; i = ++j) { + checkbox = ref[i]; + checkbox.id = "checkbox-" + i; + label = $.el('label', { + htmlFor: checkbox.id + }); + label.dataset.row = Math.floor(i / 3); + label.dataset.col = i % 3; + $.after(checkbox, label); + results.push(label); + } + return results; + }).call(this); + return this.addTooltips(labels); + }, + addTooltips: function(nodes) { + var i, j, len, node; + for (i = j = 0, len = nodes.length; j < len; i = ++j) { + node = nodes[i]; + node.title = this.imageKeys[i] + " or " + (this.imageKeys[i + 9][0].toUpperCase()) + this.imageKeys[i + 9].slice(1); + } + }, + addTooltips16: function(nodes) { + var i, j, key, len, node, ref; + ref = this.imageKeys16; + for (i = j = 0, len = ref.length; j < len; i = ++j) { + key = ref[i]; + if (i % 4 < this.width && (node = nodes[nodes.length - (4 - Math.floor(i / 4)) * this.width + (i % 4)])) { + node.title = "" + (key[0].toUpperCase()) + key.slice(1); + } + } + }, + checkForm: function(e) { + var checkbox, j, len, n, ref; + n = 0; + ref = this.images; + for (j = 0, len = ref.length; j < len; j++) { + checkbox = ref[j]; + if (checkbox.checked) { + n++; + } + } + if (n === 0) { + return e.preventDefault(); + } + }, + keybinds: function(e) { + var dx, i, img, key, last, n, reload, verify, w, x; + if (!(this.images && doc.contains(this.images[0]))) { + return; + } + n = this.images.length; + w = this.width; + last = n + w - 1; + reload = $('#recaptcha-reload-button, .fbc-button-reload'); + verify = $('#recaptcha-verify-button, .fbc-button-verify > input'); + x = this.images.indexOf(d.activeElement); + if (x < 0) { + x = d.activeElement === verify ? last : n; + } + key = Keybinds.keyCode(e); + if (!this.noscript && key === 'Space' && x < n) { + this.images[x].click(); + } else if (n === 9 && (i = this.imageKeys.indexOf(key)) >= 0) { + this.images[i % 9].click(); + verify.focus(); + } else if (n !== 9 && (i = this.imageKeys16.indexOf(key)) >= 0 && i % 4 < w && (img = this.images[n - (4 - Math.floor(i / 4)) * w + (i % 4)])) { + img.click(); + verify.focus(); + } else if (dx = { + 'Up': n, + 'Down': w, + 'Left': last, + 'Right': 1 + }[key]) { + x = (x + dx) % (n + w); + if ((n < x && x < last)) { + x = dx === last ? n : last; + } + (this.images[x] || (x === n ? reload : void 0) || (x === last ? verify : void 0)).focus(); + } else { + return; + } + e.preventDefault(); + return e.stopPropagation(); + } + }; + +}).call(this); + +(function() { + Captcha.replace = { + init: function() { + if (!(d.cookie.indexOf('pass_enabled=1') < 0)) { + return; + } + if (location.hostname === 'sys.4chan.org' && /[?&]altc\b/.test(location.search) && Main.jsEnabled) { + $.onExists(doc, 'script[src="//www.google.com/recaptcha/api/js/recaptcha_ajax.js"]', function() { + $.global(function() { + return window.el.onload = null; + }); + return Captcha.v1.create(); + }); + return; + } + if (((Conf['Use Recaptcha v1'] && location.hostname === 'boards.4chan.org') || (Conf['Use Recaptcha v1 in Reports'] && location.hostname === 'sys.4chan.org')) && Main.jsEnabled) { + $.ready(Captcha.replace.v1); + return; + } + if (Conf['Force Noscript Captcha'] && Main.jsEnabled) { + $.ready(Captcha.replace.noscript); + return; + } + if (Conf['captchaLanguage'].trim() || Conf['Captcha Fixes']) { + if (location.hostname === 'boards.4chan.org') { + return $.onExists(doc, '#captchaFormPart', function(node) { + return $.onExists(node, 'iframe', Captcha.replace.iframe); + }); + } else { + return $.onExists(doc, 'iframe', Captcha.replace.iframe); + } + } + }, + noscript: function() { + var insert, noscript, original, span, toggle; + if (!((original = $('#g-recaptcha, #captchaContainerAlt')) && (noscript = $('noscript')))) { + return; + } + span = $.el('span', { + id: 'captcha-forced-noscript' + }); + $.replace(noscript, span); + $.rm(original); + insert = function() { + span.innerHTML = noscript.textContent; + return Captcha.replace.iframe($('iframe', span)); + }; + if ((toggle = $('#togglePostFormLink a, #form-link'))) { + return $.on(toggle, 'click', insert); + } else { + return insert(); + } + }, + v1: function() { + var form, link; + if (!$.id('g-recaptcha')) { + return; + } + Captcha.v1.replace(); + if ((link = $.id('form-link'))) { + return $.on(link, 'click', function() { + return Captcha.v1.create(); + }); + } else if (location.hostname === 'boards.4chan.org') { + form = $.id('postForm'); + return form.addEventListener('focus', (function() { + return Captcha.v1.create(); + }), true); + } else { + return Captcha.v1.create(); + } + }, + iframe: function(iframe) { + var lang, src; + if ((lang = Conf['captchaLanguage'].trim())) { + src = /[?&]hl=/.test(iframe.src) ? iframe.src.replace(/([?&]hl=)[^&]*/, '$1' + encodeURIComponent(lang)) : iframe.src + ("&hl=" + (encodeURIComponent(lang))); + if (iframe.src !== src) { + iframe.src = src; + } + } + return Captcha.replace.autocopy(iframe); + }, + autocopy: function(iframe) { + if (!(Conf['Captcha Fixes'] && /^https:\/\/www\.google\.com\/recaptcha\/api\/fallback\?/.test(iframe.src))) { + return; + } + return new Connection(iframe, 'https://www.google.com', { + working: function() { + var ref, ref1; + if ((ref = $.id('qr')) != null ? ref.contains(iframe) : void 0) { + return (ref1 = $('#qr .captcha-container textarea')) != null ? ref1.parentNode.hidden = true : void 0; + } + }, + token: function(token) { + var node, textarea; + node = iframe; + while ((node = node.parentNode)) { + if ((textarea = $('textarea', node))) { + break; + } + } + textarea.value = token; + return $.event('input', null, textarea); + } + }); + } + }; + +}).call(this); + +(function() { + Captcha.v1 = { + blank: "data:image/svg+xml,", + init: function() { + var imgContainer, input; + if (d.cookie.indexOf('pass_enabled=1') >= 0) { + return; + } + if (!(this.isEnabled = !!$('#g-recaptcha, #captchaContainerAlt'))) { + return; + } + imgContainer = $.el('div', { + className: 'captcha-img', + title: 'Reload reCAPTCHA' + }); + $.extend(imgContainer, { + innerHTML: "" + }); + input = $.el('input', { + className: 'captcha-input field', + title: 'Verification', + autocomplete: 'off', + spellcheck: false + }); + this.nodes = { + img: imgContainer.firstChild, + input: input + }; + $.on(input, 'blur', QR.focusout); + $.on(input, 'focus', QR.focusin); + $.on(input, 'keydown', QR.captcha.keydown.bind(QR.captcha)); + $.on(this.nodes.img.parentNode, 'click', QR.captcha.reload.bind(QR.captcha)); + $.addClass(QR.nodes.el, 'has-captcha', 'captcha-v1'); + $.after(QR.nodes.com.parentNode, [imgContainer, 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.replace(); + this.beforeSetup(); + if (Conf['Auto-load captcha']) { + this.setup(); + } + new MutationObserver(this.afterSetup).observe($.id('captchaContainerAlt'), { + childList: true + }); + return this.afterSetup(); + }, + replace: function() { + var container, old; + if (this.script) { + return; + } + if (!(this.script = $('script[src="//www.google.com/recaptcha/api/js/recaptcha_ajax.js"]', d.head))) { + this.script = $.el('script', { + src: '//www.google.com/recaptcha/api/js/recaptcha_ajax.js' + }); + $.add(d.head, this.script); + } + if (old = $.id('g-recaptcha')) { + container = $.el('div', { + id: 'captchaContainerAlt' + }); + return $.replace(old, container); + } + }, + create: function() { + var cont, lang; + cont = $.id('captchaContainerAlt'); + if (this.occupied) { + return; + } + this.occupied = true; + if ((lang = Conf['captchaLanguage'].trim())) { + cont.dataset.lang = lang; + } + $.onExists(cont, '#recaptcha_image', function(image) { + return $.on(image, 'click', function() { + if ($.id('recaptcha_challenge_image')) { + return $.global(function() { + return window.Recaptcha.reload(); + }); + } + }); + }); + $.onExists(cont, '#recaptcha_response_field', function(field) { + $.on(field, 'keydown', function(e) { + if (e.keyCode === 8 && !field.value) { + return $.global(function() { + return window.Recaptcha.reload(); + }); + } + }); + if (location.hostname === 'sys.4chan.org') { + return field.focus(); + } + }); + return $.global(function() { + var container, options, script; + container = document.getElementById('captchaContainerAlt'); + options = { + theme: 'clean', + tabindex: { + "boards.4chan.org": 5 + }[location.hostname], + lang: container.dataset.lang + }; + if (window.Recaptcha) { + return window.Recaptcha.create('6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc', container, options); + } else { + script = document.head.querySelector('script[src="//www.google.com/recaptcha/api/js/recaptcha_ajax.js"]'); + return script.addEventListener('load', function() { + return window.Recaptcha.create('6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc', container, options); + }, false); + } + }); + }, + cb: { + focus: function() { + return QR.captcha.setup(false, true); + } + }, + beforeSetup: function() { + var img, input, ref; + ref = this.nodes, img = ref.img, input = ref.input; + img.parentNode.hidden = true; + img.src = this.blank; + 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 && (force || this.needed()))) { + return; + } + this.create(); + if (focus) { + $.addClass(QR.nodes.el, 'focus'); + return this.nodes.input.focus(); + } + }, + afterSetup: function() { + var challenge, img, input, ref, setLifetime; + if (!(challenge = $.id('recaptcha_challenge_field_holder'))) { + return; + } + if (challenge === QR.captcha.nodes.challenge) { + return; + } + setLifetime = function(e) { + return QR.captcha.lifetime = e.detail; + }; + $.on(window, 'captcha:timeout', setLifetime); + $.global(function() { + return window.dispatchEvent(new CustomEvent('captcha:timeout', { + detail: window.RecaptchaState.timeout + })); + }); + $.off(window, 'captcha:timeout', setLifetime); + ref = QR.captcha.nodes, img = ref.img, input = ref.input; + img.parentNode.hidden = false; + input.placeholder = 'Verification'; + QR.captcha.count(); + $.off(input, 'focus click', QR.captcha.cb.focus); + QR.captcha.nodes.challenge = challenge; + new MutationObserver(QR.captcha.load.bind(QR.captcha)).observe(challenge, { + childList: true, + subtree: true, + attributes: true + }); + QR.captcha.load(); + if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) { + QR.nodes.el.style.top = null; + return QR.nodes.el.style.bottom = '0px'; + } + }, + destroy: function() { + if (!this.script) { + return; + } + $.global(function() { + return window.Recaptcha.destroy(); + }); + delete this.occupied; + if (this.nodes) { + return this.beforeSetup(); + } + }, + sync: function(captchas) { + if (captchas == null) { + captchas = []; + } + QR.captcha.captchas = captchas; + return QR.captcha.count(); + }, + getOne: function() { + var captcha, challenge, response, timeout; + this.clear(); + if (captcha = this.captchas.shift()) { + this.count(); + $.set('captchas', this.captchas); + return captcha; + } else { + challenge = this.nodes.img.alt; + timeout = this.timeout; + if (/\S/.test(response = this.nodes.input.value)) { + this.destroy(); + return { + challenge: challenge, + response: response, + timeout: timeout + }; + } else { + return null; + } + } + }, + save: function() { + var response; + if (!/\S/.test(response = this.nodes.input.value)) { + return; + } + this.nodes.input.value = ''; + this.captchas.push({ + challenge: this.nodes.img.alt, + response: response, + timeout: this.timeout + }); + this.captchas.sort(function(a, b) { + return a.timeout - b.timeout; + }); + this.count(); + this.destroy(); + this.setup(false, true); + return $.set('captchas', this.captchas); + }, + clear: function() { + var captcha, i, j, len, now, ref; + if (!this.captchas.length) { + return; + } + $.forceSync('captchas'); + now = Date.now(); + ref = this.captchas; + for (i = j = 0, len = ref.length; j < len; i = ++j) { + captcha = ref[i]; + if (captcha.timeout > now) { + break; + } + } + if (!i) { + return; + } + this.captchas = this.captchas.slice(i); + this.count(); + return $.set('captchas', this.captchas); + }, + load: function() { + var challenge, challenge_image; + if ($('#captchaContainerAlt[class~="recaptcha_is_showing_audio"]')) { + this.nodes.img.src = this.blank; + return; + } + if (!this.nodes.challenge.firstChild) { + return; + } + if (!(challenge_image = $.id('recaptcha_challenge_image'))) { + return; + } + this.timeout = Date.now() + this.lifetime * $.SECOND - $.MINUTE; + challenge = this.nodes.challenge.firstChild.value; + this.nodes.img.alt = challenge; + this.nodes.img.src = challenge_image.src; + this.nodes.input.value = ''; + return this.clear(); + }, + 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.timer); + if (count) { + return this.timer = setTimeout(this.clear.bind(this), this.captchas[0].timeout - Date.now()); + } + }, + reload: function(focus) { + $.global(function() { + if (window.Recaptcha.type === 'image') { + window.Recaptcha.reload(); + } else { + window.Recaptcha.switch_type('image'); + } + return window.Recaptcha.should_focus = false; + }); + if (focus) { + return this.nodes.input.focus(); + } + }, + keydown: function(e) { + if (e.keyCode === 8 && !this.nodes.input.value) { + this.reload(); + } else if (e.keyCode === 13 && e.shiftKey) { + this.save(); + } else { + return; + } + return e.preventDefault(); + } + }; + +}).call(this); + +(function() { + Captcha.v2 = { + lifetime: 2 * $.MINUTE, + init: function() { + var counter, root; + if (d.cookie.indexOf('pass_enabled=1') >= 0) { + return; + } + if (!(this.isEnabled = !!$('#g-recaptcha, #captchaContainerAlt, #captcha-forced-noscript'))) { + return; + } + if ((this.noscript = Conf['Force Noscript Captcha'] || !Main.jsEnabled)) { + $.addClass(QR.nodes.el, 'noscript-captcha'); + } + 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: "
      " + }); + counter = $('.captcha-counter > a', root); + this.nodes = { + root: root, + counter: counter + }; + this.count(); + $.addClass(QR.nodes.el, 'has-captcha', 'captcha-v2'); + $.after(QR.nodes.com.parentNode, root); + $.on(counter, 'click', this.toggle.bind(this)); + $.on(counter, 'keydown', (function(_this) { + return function(e) { + if (Keybinds.keyCode(e) !== 'Space') { + return; + } + _this.toggle(); + e.preventDefault(); + return e.stopPropagation(); + }; + })(this)); + return $.on(window, 'captcha:success', (function(_this) { + return function() { + return $.queueTask(function() { + return _this.save(false); + }); + }; + })(this)); + }, + timeouts: {}, + postsCount: 0, + noscriptURL: function() { + var lang, url; + url = 'https://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc'; + if ((lang = Conf['captchaLanguage'].trim())) { + url += "&hl=" + (encodeURIComponent(lang)); + } + return url; + }, + 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) { + if (!(this.isEnabled && (this.needed() || force))) { + return; + } + if (focus) { + $.addClass(QR.nodes.el, 'focus'); + this.nodes.counter.focus(); + } + if (this.timeouts.destroy) { + clearTimeout(this.timeouts.destroy); + delete this.timeouts.destroy; + return this.reload(); + } + if (this.nodes.container) { + $.queueTask((function(_this) { + return function() { + var iframe; + if (_this.nodes.container && d.activeElement === _this.nodes.counter && (iframe = $('iframe', _this.nodes.container))) { + iframe.focus(); + return QR.focus(); + } + }; + })(this)); + 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 + }); + if (this.noscript) { + return this.setupNoscript(); + } else { + return this.setupJS(); + } + }, + setupNoscript: function() { + var div, iframe, textarea; + iframe = $.el('iframe', { + id: 'qr-captcha-iframe', + src: this.noscriptURL() + }); + div = $.el('div'); + textarea = $.el('textarea'); + $.add(div, textarea); + return $.add(this.nodes.container, [iframe, div]); + }, + setupJS: function() { + return $.global(function() { + var cbNative, render; + render = function() { + var classList, container; + classList = document.documentElement.classList; + container = document.querySelector('#qr .captcha-container'); + return container.dataset.widgetID = window.grecaptcha.render(container, { + sitekey: '6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc', + theme: classList.contains('tomorrow') || classList.contains('dark-captcha') ? 'dark' : 'light', + callback: function(response) { + return window.dispatchEvent(new CustomEvent('captcha:success', { + detail: response + })); + } + }); + }; + if (window.grecaptcha) { + return render(); + } else { + cbNative = window.onRecaptchaLoaded; + return window.onRecaptchaLoaded = function() { + render(); + return cbNative(); + }; + } + }); + }, + afterSetup: function(mutations) { + var iframe, j, k, len, len1, mutation, node, ref, textarea; + for (j = 0, len = mutations.length; j < len; j++) { + mutation = mutations[j]; + ref = mutation.addedNodes; + for (k = 0, len1 = ref.length; k < len1; k++) { + node = ref[k]; + 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) { + if (!doc.contains(iframe)) { + return; + } + Captcha.replace.iframe(iframe); + $.addClass(QR.nodes.el, 'captcha-open'); + this.fixQRPosition(); + $.on(iframe, 'load', this.fixQRPosition); + if (d.activeElement === this.nodes.counter) { + iframe.focus(); + } + return $.global(function() { + var f; + f = document.querySelector('#qr iframe'); + return f.focus = f.blur = function() {}; + }); + }, + fixQRPosition: function() { + if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) { + QR.nodes.el.style.top = null; + return QR.nodes.el.style.bottom = '0px'; + } + }, + setupTextArea: function(textarea) { + return $.one(textarea, 'input', (function(_this) { + return function() { + return _this.save(true); + }; + })(this)); + }, + destroy: function() { + var garbage, i, ins, node, ref; + if (!this.isEnabled) { + return; + } + delete this.timeouts.destroy; + $.rmClass(QR.nodes.el, 'captcha-open'); + if (this.nodes.container) { + $.rm(this.nodes.container); + } + delete this.nodes.container; + garbage = $.X('//iframe[starts-with(@src, "https://www.google.com/recaptcha/api2/frame")]/ancestor-or-self::*[parent::body]'); + i = 0; + while (node = garbage.snapshotItem(i++)) { + if (((ref = (ins = node.nextSibling)) != null ? ref.nodeName : void 0) === 'INS') { + $.rm(ins); + } + $.rm(node); + } + }, + 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; + } else { + return null; + } + }, + save: function(pasted, token) { + var base, focus, ref; + $.forceSync('captchas'); + this.captchas.push({ + response: token || $('textarea', this.nodes.container).value, + timeout: Date.now() + this.lifetime + }); + this.captchas.sort(function(a, b) { + return a.timeout - b.timeout; + }); + $.set('captchas', this.captchas); + this.count(); + focus = ((ref = d.activeElement) != null ? ref.nodeName : void 0) === 'IFRAME' && /https?:\/\/www\.google\.com\/recaptcha\//.test(d.activeElement.src); + if (this.needed()) { + if (focus) { + if (QR.cooldown.auto || Conf['Post on Captcha Completion']) { + this.nodes.counter.focus(); + } 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); + } + } + if (focus) { + QR.nodes.status.focus(); + } + } + if (Conf['Post on Captcha Completion'] && !QR.cooldown.auto) { + return QR.submit(); + } + }, + clear: function() { + var captcha, i, j, len, now, ref; + if (!this.captchas.length) { + return; + } + $.forceSync('captchas'); + now = Date.now(); + ref = this.captchas; + for (i = j = 0, len = ref.length; j < len; i = ++j) { + 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(d.activeElement === QR.nodes.status); + }, + 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() { + if ($('iframe[src^="https://www.google.com/recaptcha/api/fallback?"]', this.nodes.container)) { + this.destroy(); + return this.setup(false, true); + } else { + return $.global(function() { + var container; + container = document.querySelector('#qr .captcha-container'); + return window.grecaptcha.reset(container.dataset.widgetID); + }); + } + } + }; + +}).call(this); + +PassLink = (function() { + var PassLink; + + PassLink = { + init: function() { + if (!Conf['Pass Link']) { + return; + } + return Main.ready(this.ready); + }, + ready: function() { + var passLink, styleSelector; + if (!(styleSelector = $.id('styleSelector'))) { + return; + } + passLink = $.el('span', { + className: 'brackets-wrap pass-link-container' + }); + $.extend(passLink, { + innerHTML: "4chan Pass" + }); + $.on(passLink.firstElementChild, 'click', function() { + return window.open('//sys.4chan.org/auth', Date.now(), 'width=500,height=280,toolbar=0'); + }); + return $.before(styleSelector.previousSibling, [passLink, $.tn('\u00A0\u00A0')]); + } + }; + + return PassLink; + +}).call(this); + +PostSuccessful = (function() { + var PostSuccessful; + + PostSuccessful = { + init: function() { + if (!Conf['Remember Your Posts']) { + return; + } + return $.ready(this.ready); + }, + ready: function() { + var _, db, postID, ref, threadID; + if (d.title !== 'Post successful!') { + return; + } + ref = $('h1').nextSibling.textContent.match(/thread:(\d+),no:(\d+)/), _ = ref[0], threadID = ref[1], postID = ref[2]; + postID = +postID; + threadID = +threadID || postID; + db = new DataBoard('yourPosts'); + return db.set({ + boardID: g.BOARD.ID, + threadID: threadID, + postID: postID, + val: true + }); + } + }; + + return PostSuccessful; + +}).call(this); + +QR = (function() { + var QR, + indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, + slice = [].slice; + + QR = { + mimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'application/pdf', 'application/vnd.adobe.flash.movie', 'application/x-shockwave-flash', 'video/webm'], + validExtension: /\.(jpe?g|png|gif|pdf|swf|webm)$/i, + typeFromExtension: { + 'jpg': 'image/jpeg', + 'jpeg': 'image/jpeg', + 'png': 'image/png', + 'gif': 'image/gif', + 'pdf': 'application/pdf', + 'swf': 'application/vnd.adobe.flash.movie', + 'webm': 'video/webm' + }, + extensionFromType: { + 'image/jpeg': 'jpg', + 'image/png': 'png', + 'image/gif': 'gif', + 'application/pdf': 'pdf', + 'application/vnd.adobe.flash.movie': 'swf', + 'application/x-shockwave-flash': 'swf', + 'video/webm': 'webm' + }, + init: function() { + var sc, version; + if (!Conf['Quick Reply']) { + return; + } + this.posts = []; + if (g.VIEW === 'archive') { + return; + } + version = Conf['Use Recaptcha v1'] && Main.jsEnabled ? 'v1' : 'v2'; + this.captcha = Captcha[version]; + $.on(d, '4chanXInitFinished', this.initReady); + Callbacks.Post.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(); + } + }); + return Header.addShortcut(sc); + } + }, + initReady: function() { + var link, linkBot, navLinksBot, origToggle; + $.off(d, '4chanXInitFinished', this.initReady); + QR.postingIsEnabled = !!$.id('postForm'); + if (!QR.postingIsEnabled) { + return; + } + link = $.el('h1', { + className: "qr-link-container" + }); + $.extend(link, { + innerHTML: "" + ((g.VIEW === "thread") ? "Reply to Thread" : "Start a Thread") + "" + }); + 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: "Reply to Thread" + }); + $.on(linkBot.firstElementChild, 'click', function() { + QR.open(); + return QR.nodes.com.focus(); + }); + if ((navLinksBot = $('.navLinksBot'))) { + $.prepend(navLinksBot, linkBot); + } + } + origToggle = $.id('togglePostFormLink'); + $.before(origToggle, link); + origToggle.firstElementChild.textContent = 'Original Form'; + $.on(d, 'QRGetFile', QR.getFile); + $.on(d, 'QRSetFile', QR.setFile); + $.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 j, len, post, 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 (j = 0, len = ref.length; j < len; j++) { + post = ref[j]; + post["delete"](); + } + QR.cooldown.auto = false; + QR.status(); + return QR.captcha.destroy(); + }, + focus: function() { + return $.queueTask(function() { + if (!QR.inBubble()) { + QR.hasFocus = d.activeElement && QR.nodes.el.contains(d.activeElement); + return QR.nodes.el.classList.toggle('focus', QR.hasFocus); + } + }); + }, + inBubble: function() { + var bubbles, ref; + bubbles = $$('iframe[src^="https://www.google.com/recaptcha/api2/frame"]'); + return (ref = d.activeElement, indexOf.call(bubbles, ref) >= 0) || bubbles.some(function(el) { + return getComputedStyle(el).visibility !== 'hidden' && el.getBoundingClientRect().bottom > 0; + }); + }, + 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(); + } + }, + toggleSJIS: function(e) { + e.preventDefault(); + Conf['sjisPreview'] = !Conf['sjisPreview']; + $.set('sjisPreview', Conf['sjisPreview']); + return QR.nodes.el.classList.toggle('sjis-preview', Conf['sjisPreview']); + }, + texPreviewShow: function() { + if ($.hasClass(QR.nodes.el, 'tex-preview')) { + return QR.texPreviewHide(); + } + $.addClass(QR.nodes.el, 'tex-preview'); + QR.nodes.texPreview.textContent = QR.nodes.com.value; + return $.event('mathjax', null, QR.nodes.texPreview); + }, + texPreviewHide: function() { + return $.rmClass(QR.nodes.el, 'tex-preview'); + }, + setCustomCooldown: function(enabled) { + Conf['customCooldownEnabled'] = enabled; + QR.cooldown.customCooldown = enabled; + return QR.nodes.customCooldown.classList.toggle('disabled', !enabled); + }, + toggleCustomCooldown: function() { + var enabled; + enabled = $.hasClass(this, 'disabled'); + QR.setCustomCooldown(enabled); + return $.set('customCooldownEnabled', enabled); + }, + error: function(err, focusOverride) { + var el, notice, notif; + QR.open(); + if (typeof err === 'string') { + el = $.tn(err); + } else { + el = err; + el.removeAttribute('style'); + } + notice = new Notice('warning', el); + QR.notifications.push(notice); + if (!Header.areNotificationsEnabled) { + if (d.hidden && !QR.cooldown.auto) { + return alert(el.textContent); + } + } else if (d.hidden || !(focusOverride || d.hasFocus())) { + try { + notif = new Notification(el.textContent, { + body: el.textContent, + icon: Favicon.logo + }); + notif.onclick = function() { + return $.global(function() { + return window.focus(); + }); + }; + if ($.engine !== 'gecko') { + notif.onclose = function() { + return notice.close(); + }; + return notif.onshow = function() { + return setTimeout(function() { + notif.onclose = null; + return notif.close(); + }, 7 * $.SECOND); + }; + } + } catch (_error) {} + } + }, + notifications: [], + cleanNotifications: function() { + var j, len, notification, ref; + ref = QR.notifications; + for (j = 0, len = ref.length; j < len; j++) { + notification = ref[j]; + 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; + }, + openPost: function() { + var index; + 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'); + return QR.cooldown.auto = true; + } + }, + quote: function(e) { + var ancestor, caretPos, com, frag, insideCode, j, k, l, len, len1, len2, len3, len4, len5, n, node, o, post, q, range, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, sel, text, thread; + 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 (j = 0, len = ref.length; j < len; j++) { + node = ref[j]; + $.replace(node, $.tn('\n')); + } + ref1 = $$('br', frag); + for (k = 0, len1 = ref1.length; k < len1; k++) { + node = ref1[k]; + if (node !== frag.lastChild) { + $.replace(node, $.tn('\n>')); + } + } + ref2 = $$('s, .removed-spoiler', frag); + for (l = 0, len2 = ref2.length; l < len2; l++) { + node = ref2[l]; + $.replace(node, [$.tn('[spoiler]')].concat(slice.call(node.childNodes), [$.tn('[/spoiler]')])); + } + ref3 = $$('.prettyprint', frag); + for (n = 0, len3 = ref3.length; n < len3; n++) { + node = ref3[n]; + $.replace(node, [$.tn('[code]')].concat(slice.call(node.childNodes), [$.tn('[/code]')])); + } + ref4 = $$('.linkify[data-original]', frag); + for (o = 0, len4 = ref4.length; o < len4; o++) { + node = ref4[o]; + $.replace(node, $.tn(node.dataset.original)); + } + ref5 = $$('.embedder', frag); + for (q = 0, len5 = ref5.length; q < len5; q++) { + node = ref5[q]; + if (((ref6 = node.previousSibling) != null ? ref6.nodeValue : void 0) === ' ') { + $.rm(node.previousSibling); + } + $.rm(node); + } + text += ">" + (frag.textContent.trim()) + "\n"; + } + QR.openPost(); + 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.value.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '_').length; + counter.textContent = count; + counter.hidden = count < QR.max_comment / 2; + return (count > QR.max_comment ? $.addClass : $.rmClass)(counter, 'warning'); + }, + getFile: function() { + var ref; + return $.event('QRFile', (ref = QR.selected) != null ? ref.file : void 0); + }, + setFile: function(e) { + var file, name, ref, source; + ref = e.detail, file = ref.file, name = ref.name, source = ref.source; + if (name != null) { + file.name = name; + } + if (source != null) { + file.source = source; + } + QR.open(); + return QR.handleFiles([file]); + }, + 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, j, len, ref; + if (!e.clipboardData.items) { + return; + } + files = []; + ref = e.clipboardData.items; + for (j = 0, len = ref.length; j < len; j++) { + item = ref[j]; + 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'); + }, + pasteFF: function() { + var arr, blob, bstr, i, images, img, j, k, len, m, pasteArea, ref, src; + pasteArea = QR.nodes.pasteArea; + if (!pasteArea.childNodes.length) { + return; + } + images = $$('img', pasteArea); + $.rmAll(pasteArea); + for (j = 0, len = images.length; j < len; j++) { + img = images[j]; + src = img.src; + if (m = src.match(/data:(image\/(\w+));base64,(.+)/)) { + bstr = atob(m[3]); + arr = new Uint8Array(bstr.length); + for (i = k = 0, ref = bstr.length; 0 <= ref ? k < ref : k > ref; i = 0 <= ref ? ++k : --k) { + arr[i] = bstr.charCodeAt(i); + } + blob = new Blob([arr], { + type: m[1] + }); + blob.name = "file." + m[2]; + QR.handleFiles([blob]); + } else if (/^https?:\/\//.test(src)) { + QR.handleUrl(src); + } + } + }, + handleUrl: function(urlDefault) { + var url; + url = prompt('Enter a URL:', urlDefault); + if (url === null) { + return; + } + QR.nodes.fileButton.focus(); + return CrossOrigin.file(url, function(blob) { + if (blob && !/^text\//.test(blob.type)) { + return QR.handleFiles([blob]); + } else { + return QR.error("Can't load file."); + } + }); + }, + handleFiles: function(files) { + var file, j, len; + if (this !== QR) { + files = slice.call(this.files); + this.value = null; + } + if (!files.length) { + return; + } + QR.cleanNotifications(); + for (j = 0, len = files.length; j < len; j++) { + file = files[j]; + QR.handleFile(file, files.length); + } + if (files.length !== 1) { + $.addClass(QR.nodes.el, 'dump'); + } + if (d.activeElement === QR.nodes.fileButton && $.hasClass(QR.nodes.fileSubmit, 'has-file')) { + return QR.nodes.filename.focus(); + } + }, + handleFile: function(file, nfiles) { + var isText, post; + isText = /^text\//.test(file.type); + if (nfiles === 1) { + post = QR.selected; + } else { + post = QR.posts[QR.posts.length - 1]; + if ((isText ? post.com || post.pasting : post.file)) { + post = new QR.post(); + } + } + return post[isText ? 'pasteText' : 'setFile'](file); + }, + openFileInput: function() { + if (QR.nodes.fileButton.disabled) { + return; + } + QR.nodes.fileInput.click(); + return QR.nodes.fileButton.focus(); + }, + generatePostableThreadsList: function() { + var j, len, list, options, ref, thread, val; + if (!QR.nodes) { + return; + } + list = QR.nodes.thread; + options = [list.firstElementChild]; + ref = g.BOARD.threads.keys; + for (j = 0, len = ref.length; j < len; j++) { + thread = ref[j]; + options.push($.el('option', { + value: thread, + textContent: "Thread " + 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, ref, rules, save, scriptData, setNode; + QR.nodes = nodes = { + el: dialog = UI.dialog('qr', 'top: 50px; right: 0px;', { + innerHTML: "
      ×
      No selected file
      " + }) + }; + setNode = function(name, query) { + return nodes[name] = $(query, dialog); + }; + setNode('move', '.move'); + setNode('autohide', '#autohide'); + setNode('close', '.close'); + setNode('thread', 'select'); + setNode('form', 'form'); + setNode('sjisToggle', '#sjis-toggle'); + setNode('texButton', '#tex-preview-button'); + setNode('name', '[data-name=name]'); + setNode('email', '[data-name=email]'); + setNode('sub', '[data-name=sub]'); + setNode('com', '[data-name=com]'); + setNode('charCount', '#char-count'); + setNode('texPreview', '#tex-preview'); + setNode('dumpList', '#dump-list'); + setNode('addPost', '#add-post'); + setNode('oekaki', '.oekaki'); + setNode('drawButton', '#qr-draw-button'); + setNode('fileSubmit', '#file-n-submit'); + setNode('fileButton', '#qr-file-button'); + setNode('noFile', '#qr-no-file'); + setNode('filename', '#qr-filename'); + setNode('spoiler', '#qr-file-spoiler'); + setNode('oekakiButton', '#qr-oekaki-button'); + setNode('fileRM', '#qr-filerm'); + setNode('urlButton', '#url-button'); + setNode('pasteArea', '#paste-area'); + setNode('customCooldown', '#custom-cooldown-button'); + setNode('dumpButton', '#dump-button'); + setNode('status', '[type=submit]'); + setNode('flashTag', '[name=filetag]'); + 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; + scriptData = Get.scriptData(); + QR.max_size = (m = scriptData.match(/\bmaxFilesize *= *(\d+)\b/)) ? +m[1] : 4194304; + QR.max_size_video = (m = scriptData.match(/\bmaxWebmFilesize *= *(\d+)\b/)) ? +m[1] : QR.max_size; + QR.max_comment = (m = scriptData.match(/\bcomlen *= *(\d+)\b/)) ? +m[1] : 2000; + 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'); + } + if (g.BOARD.ID === 'jp' && Conf['sjisPreview']) { + $.addClass(QR.nodes.el, 'sjis-preview'); + } + if (parseInt(Conf['customCooldown'], 10) > 0) { + $.addClass(QR.nodes.fileSubmit, 'custom-cooldown'); + $.get('customCooldownEnabled', Conf['customCooldownEnabled'], function(arg) { + var customCooldownEnabled; + customCooldownEnabled = arg.customCooldownEnabled; + QR.setCustomCooldown(customCooldownEnabled); + return $.sync('customCooldownEnabled', QR.setCustomCooldown); + }); + } + $.on(nodes.autohide, 'change', QR.toggleHide); + $.on(nodes.close, 'click', QR.close); + $.on(nodes.form, 'submit', QR.submit); + $.on(nodes.sjisToggle, 'click', QR.toggleSJIS); + $.on(nodes.texButton, 'mousedown', QR.texPreviewShow); + $.on(nodes.texButton, 'mouseup', QR.texPreviewHide); + $.on(nodes.addPost, 'click', function() { + return new QR.post(true); + }); + $.on(nodes.drawButton, 'click', QR.oekaki.draw); + $.on(nodes.fileButton, 'click', QR.openFileInput); + $.on(nodes.noFile, 'click', QR.openFileInput); + $.on(nodes.filename, 'focus', function() { + return $.addClass(this.parentNode, 'focus'); + }); + $.on(nodes.filename, 'blur', function() { + return $.rmClass(this.parentNode, 'focus'); + }); + $.on(nodes.spoiler, 'change', function() { + return QR.selected.nodes.spoiler.click(); + }); + $.on(nodes.oekakiButton, 'click', QR.oekaki.button); + $.on(nodes.fileRM, 'click', function() { + return QR.selected.rmFile(); + }); + $.on(nodes.urlButton, 'click', function() { + return QR.handleUrl(''); + }); + $.on(nodes.customCooldown, 'click', QR.toggleCustomCooldown); + $.on(nodes.dumpButton, 'click', function() { + return nodes.el.classList.toggle('dump'); + }); + $.on(nodes.fileInput, 'change', QR.handleFiles); + window.addEventListener('focus', QR.focus, true); + window.addEventListener('blur', QR.focus, true); + $.on(d, 'click', QR.focus); + if ($.engine === 'gecko') { + nodes.pasteArea.hidden = false; + new MutationObserver(QR.pasteFF).observe(nodes.pasteArea, { + childList: true + }); + } + 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 ($.engine === 'gecko' && 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.load(); + new QR.post(true); + QR.status(); + QR.cooldown.setup(); + QR.captcha.init(); + $.add(d.body, dialog); + QR.captcha.setup(); + QR.oekaki.setup(); + return $.event('QRDialogCreation', null, dialog); + }, + submit: function(e) { + var captcha, cb, err, extra, filetag, formData, options, post, ref, 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(); + threadID = post.thread; + thread = g.BOARD.threads[threadID]; + if (g.BOARD.ID === 'f' && threadID === 'new') { + filetag = QR.nodes.flashTag.value; + } + if (threadID === 'new') { + threadID = null; + if (g.BOARD.ID === 'vg' && !post.sub) { + err = 'New threads require a subject.'; + } else if (!($.hasClass(d.body, 'text_only') || 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 comment or file.'; + } else if (post.file && thread.fileLimit) { + err = 'Max limit of image replies has been reached.'; + } + if (g.BOARD.ID === 'r9k' && !((ref = post.com) != null ? ref.match(/[a-z-]/i) : void 0)) { + err || (err = 'Original comment required.'); + } + if (QR.captcha.isEnabled && !err) { + captcha = QR.captcha.getOne(); + if (!captcha) { + err = 'No valid captcha.'; + QR.captcha.setup(!QR.cooldown.auto || d.activeElement === QR.nodes.status); + } + } + 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.getPassword() + }; + 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: "Connection error while posting. [More info]" + })); + } + }; + extra = { + form: $.formData(formData), + upCallbacks: { + onload: function() { + QR.req.isUploadFinished = true; + 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) { + if (response.challenge != null) { + extra.form.append('recaptcha_challenge_field', response.challenge); + extra.form.append('recaptcha_response_field', response.response); + } else { + extra.form.append('g-recaptcha-response', 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, err, h1, isReply, lastPostToThread, m, open, post, postID, postsCount, ref, ref1, ref2, req, resDoc, seconds, threadID; + 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 + "! ;_;
      Click here to see the reason." + } : { + innerHTML: "You were issued a warning on " + ($(".board", resDoc)).innerHTML + " as " + ($(".nameBlock", resDoc)).innerHTML + ".
      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 = $.el('span', { + innerHTML: "You mistyped the CAPTCHA, or the CAPTCHA malfunctioned [complain here]." + }); + } else if (/expired/i.test(err.textContent)) { + err = 'This CAPTCHA is no longer valid because it has expired.'; + } + QR.cooldown.auto = QR.captcha.isEnabled || err === 'Connection error with sys.4chan.org.'; + QR.cooldown.addDelay(post, 2); + } else if (err.textContent && (m = err.textContent.match(/(?:(\d+)\s+minutes?\s+)?(\d+)\s+second/i)) && !/duplicate|hour/i.test(err.textContent)) { + QR.cooldown.auto = !/have\s+been\s+muted/i.test(err.textContent); + seconds = 60 * (+(m[1] || 0)) + (+m[2]); + if (/muted/i.test(err.textContent)) { + QR.cooldown.addMute(seconds); + } else { + QR.cooldown.addDelay(post, seconds); + } + } else { + QR.cooldown.auto = false; + } + QR.captcha.setup(QR.cooldown.auto && ((ref1 = d.activeElement) === QR.nodes.status || ref1 === d.body)); + if (QR.captcha.isEnabled && !QR.captcha.captchas.length) { + 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)); + } + ref2 = h1.nextSibling.textContent.match(/thread:(\d+),no:(\d+)/), _ = ref2[0], threadID = ref2[1], postID = ref2[2]; + postID = +postID; + threadID = +threadID || postID; + isReply = threadID !== 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; + lastPostToThread = !((function() { + var j, len, p, ref3; + ref3 = QR.posts.slice(1); + for (j = 0, len = ref3.length; j < len; j++) { + p = ref3[j]; + if (p.thread === post.thread) { + return true; + } + } + })()); + if (!(Conf['Persistent QR'] || postsCount)) { + QR.close(); + } else { + post.rm(); + QR.captcha.setup(d.activeElement === QR.nodes.status); + } + QR.cooldown.add(threadID, postID); + URL = threadID === postID ? window.location.origin + "/" + g.BOARD + "/thread/" + threadID : g.VIEW === 'index' && lastPostToThread && Conf['Open Post in New Tab'] ? window.location.origin + "/" + g.BOARD + "/thread/" + threadID + "#p" + postID : void 0; + if (URL) { + open = Conf['Open Post in New Tab'] || postsCount ? function() { + return $.open(URL); + } : function() { + return window.location = URL; + }; + if (threadID === postID) { + QR.waitForThread(URL, open); + } else { + open(); + } + } + return QR.status(); + }, + waitForThread: function(url, cb) { + var attempts, check; + attempts = 0; + check = function() { + return $.ajax(url, { + onloadend: function() { + attempts++; + if (attempts >= 6 || this.status === 200) { + return cb(); + } else { + return setTimeout(check, attempts * $.SECOND); + } + } + }, { + type: 'HEAD' + }); + }; + return check(); + }, + 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(); + } + }; + + return QR; + +}).call(this); + +(function() { + QR.cooldown = { + seconds: 0, + delays: { + thread: 0, + reply: 0, + image: 0, + reply_intra: 0, + image_intra: 0, + deletion: 60, + thread_global: 300 + }, + init: function() { + if (!Conf['Quick Reply']) { + return; + } + this.data = Conf['cooldowns']; + return $.sync('cooldowns', this.sync); + }, + setup: function() { + var delay, m, ref, type; + if (m = Get.scriptData().match(/\bcooldowns *= *({[^}]+})/)) { + $.extend(QR.cooldown.delays, JSON.parse(m[1])); + } + QR.cooldown.maxDelay = 0; + ref = QR.cooldown.delays; + for (type in ref) { + delay = ref[type]; + if (type !== 'thread' && type !== 'thread_global') { + QR.cooldown.maxDelay = Math.max(QR.cooldown.maxDelay, delay); + } + } + QR.cooldown.isSetup = true; + return QR.cooldown.start(); + }, + start: function() { + var data; + data = QR.cooldown.data; + if (!(Conf['Cooldown'] && QR.cooldown.isSetup && !QR.cooldown.isCounting && Object.keys(data[g.BOARD.ID] || {}).length + Object.keys(data.global || {}).length > 0)) { + return; + } + QR.cooldown.isCounting = true; + return QR.cooldown.count(); + }, + sync: function(data) { + QR.cooldown.data = data || {}; + return QR.cooldown.start(); + }, + add: function(threadID, postID) { + var boardID, start; + if (!Conf['Cooldown']) { + return; + } + start = Date.now(); + boardID = g.BOARD.ID; + QR.cooldown.set(boardID, 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(g.BOARD.ID, Date.now(), cooldown); + return QR.cooldown.start(); + }, + addMute: function(delay) { + if (!Conf['Cooldown']) { + return; + } + QR.cooldown.set(g.BOARD.ID, Date.now(), { + type: 'mute', + delay: delay + }); + return QR.cooldown.start(); + }, + "delete": function(post) { + var base, cooldown, cooldowns, id, name; + if (!QR.cooldown.data) { + return; + } + $.forceSync('cooldowns'); + cooldowns = ((base = QR.cooldown.data)[name = post.board.ID] || (base[name] = {})); + for (id in cooldowns) { + cooldown = cooldowns[id]; + if ((cooldown.delay == null) && cooldown.threadID === post.thread.ID && cooldown.postID === post.ID) { + delete cooldowns[id]; + } + } + return QR.cooldown.save([post.board.ID]); + }, + secondsDeletion: function(post) { + var cooldown, cooldowns, seconds, start; + if (!(QR.cooldown.data && Conf['Cooldown'])) { + return 0; + } + cooldowns = QR.cooldown.data[post.board.ID] || {}; + for (start in cooldowns) { + cooldown = cooldowns[start]; + if ((cooldown.delay == null) && cooldown.threadID === post.thread.ID && cooldown.postID === post.ID) { + seconds = QR.cooldown.delays.deletion - Math.floor((Date.now() - start) / $.SECOND); + return Math.max(seconds, 0); + } + } + return 0; + }, + 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) { + var base, cooldowns; + $.forceSync('cooldowns'); + cooldowns = ((base = QR.cooldown.data)[scope] || (base[scope] = {})); + cooldowns[id] = value; + return $.set('cooldowns', QR.cooldown.data); + }, + save: function(scopes) { + var data, i, len, scope; + data = QR.cooldown.data; + for (i = 0, len = scopes.length; i < len; i++) { + scope = scopes[i]; + if (scope in data && !Object.keys(data[scope]).length) { + delete data[scope]; + } + } + return $.set('cooldowns', data); + }, + count: function() { + var base, cooldown, cooldowns, elapsed, i, len, maxDelay, nCooldowns, now, ref, ref1, save, scope, seconds, start, suffix, threadID, type, update; + $.forceSync('cooldowns'); + save = []; + nCooldowns = 0; + now = Date.now(); + ref = QR.cooldown.categorize(QR.posts[0]), type = ref.type, threadID = ref.threadID; + seconds = 0; + if (Conf['Cooldown']) { + ref1 = [g.BOARD.ID, 'global']; + for (i = 0, len = ref1.length; i < len; i++) { + scope = ref1[i]; + cooldowns = ((base = QR.cooldown.data)[scope] || (base[scope] = {})); + for (start in cooldowns) { + cooldown = cooldowns[start]; + start = +start; + elapsed = Math.floor((now - start) / $.SECOND); + if (elapsed < 0) { + delete cooldowns[start]; + save.push(scope); + continue; + } + if (cooldown.delay != null) { + if (cooldown.delay <= elapsed) { + delete cooldowns[start]; + save.push(scope); + } else if ((cooldown.type === type && cooldown.threadID === threadID) || cooldown.type === 'mute') { + 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 (QR.cooldown.customCooldown) { + maxDelay = Math.max(maxDelay, parseInt(Conf['customCooldown'], 10)); + } + if (maxDelay <= elapsed) { + delete cooldowns[start]; + save.push(scope); + 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 (QR.cooldown.customCooldown) { + seconds = Math.max(seconds, parseInt(Conf['customCooldown'], 10) - elapsed); + } + } + nCooldowns += Object.keys(cooldowns).length; + } + } + if (save.length) { + QR.cooldown.save(save); + } + if (nCooldowns) { + 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(); + } + } + }; + +}).call(this); + +(function() { + QR.oekaki = { + menu: { + init: function() { + var a, ref; + if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Menu'] && Conf['Edit Link'] && Conf['Quick Reply'])) { + return; + } + a = $.el('a', { + className: 'edit-link', + href: 'javascript:;', + textContent: 'Edit image' + }); + $.on(a, 'click', this.editFile); + return Menu.menu.addEntry({ + el: a, + order: 95, + open: function(post) { + var file; + QR.oekaki.menu.post = post; + file = post.file; + return QR.postingIsEnabled && !!file && (file.isImage || file.isVideo); + } + }); + }, + editFile: function() { + var currentTime, isVideo, post, ref; + post = QR.oekaki.menu.post; + QR.quote.call(post.nodes.post); + isVideo = post.file.isVideo; + currentTime = ((ref = post.file.fullImage) != null ? ref.currentTime : void 0) || 0; + return CrossOrigin.file(post.file.url, function(blob) { + var video; + if (!blob) { + return QR.error("Can't load file."); + } else if (isVideo) { + video = $.el('video'); + $.on(video, 'loadedmetadata', function() { + $.on(video, 'seeked', function() { + var canvas; + canvas = $.el('canvas', { + width: video.videoWidth, + height: video.videoHeight + }); + canvas.getContext('2d').drawImage(video, 0, 0); + return canvas.toBlob(function(snapshot) { + snapshot.name = post.file.name.replace(/\.\w+$/, '') + '.png'; + QR.handleFiles([snapshot]); + return QR.oekaki.edit(); + }); + }); + return video.currentTime = currentTime; + }); + return video.src = URL.createObjectURL(blob); + } else { + blob.name = post.file.name; + QR.handleFiles([blob]); + return QR.oekaki.edit(); + } + }); + } + }, + setup: function() { + return $.global(function() { + var FCX; + FCX = window.FCX; + FCX.oekakiCB = function() { + return window.Tegaki.flatten().toBlob(function(file) { + var source; + source = "oekaki-" + (Date.now()); + FCX.oekakiLatest = source; + return document.dispatchEvent(new CustomEvent('QRSetFile', { + bubbles: true, + detail: { + file: file, + name: FCX.oekakiName, + source: source + } + })); + }); + }; + if (window.Tegaki) { + return document.querySelector('#qr .oekaki').hidden = false; + } + }); + }, + load: function(cb) { + var n, onload, script, style; + if ($('script[src^="//s.4cdn.org/js/painter"]', d.head)) { + return cb(); + } else { + style = $.el('link', { + rel: 'stylesheet', + href: "//s.4cdn.org/css/painter." + (Date.now()) + ".css" + }); + script = $.el('script', { + src: "//s.4cdn.org/js/painter.min." + (Date.now()) + ".js" + }); + n = 0; + onload = function() { + if (++n === 2) { + return cb(); + } + }; + $.on(style, 'load', onload); + $.on(script, 'load', onload); + return $.add(d.head, [style, script]); + } + }, + draw: function() { + return $.global(function() { + var FCX, Tegaki; + Tegaki = window.Tegaki, FCX = window.FCX; + if (Tegaki.bg) { + Tegaki.destroy(); + } + FCX.oekakiName = 'tegaki.png'; + return Tegaki.open({ + onDone: FCX.oekakiCB, + onCancel: function() { + return Tegaki.bgColor = '#ffffff'; + }, + width: +document.querySelector('#qr [name=oekaki-width]').value, + height: +document.querySelector('#qr [name=oekaki-height]').value, + bgColor: document.querySelector('#qr [name=oekaki-bg]').checked ? document.querySelector('#qr [name=oekaki-bgcolor]').value : 'transparent' + }); + }); + }, + button: function() { + if (QR.selected.file) { + return QR.oekaki.edit(); + } else { + return QR.oekaki.toggle(); + } + }, + edit: function() { + return QR.oekaki.load(function() { + return $.global(function() { + var FCX, Tegaki, cb, error, name, source; + Tegaki = window.Tegaki, FCX = window.FCX; + name = document.getElementById('qr-filename').value.replace(/\.\w+$/, '') + '.png'; + source = document.getElementById('file-n-submit').dataset.source; + error = function(content) { + return document.dispatchEvent(new CustomEvent('CreateNotification', { + bubbles: true, + detail: { + type: 'warning', + content: content, + lifetime: 20 + } + })); + }; + cb = function(e) { + var file, isVideo; + document.removeEventListener('QRFile', cb, false); + if (!e.detail) { + return error('No file to edit.'); + } + if (!/^(image|video)\//.test(e.detail.type)) { + return error('Not an image.'); + } + isVideo = /^video\//.test(e.detail.type); + file = document.createElement(isVideo ? 'video' : 'img'); + file.addEventListener('error', function() { + return error('Could not open file.', false); + }); + file.addEventListener((isVideo ? 'loadeddata' : 'load'), function() { + if (Tegaki.bg) { + Tegaki.destroy(); + } + FCX.oekakiName = name; + Tegaki.open({ + onDone: FCX.oekakiCB, + onCancel: function() { + return Tegaki.bgColor = '#ffffff'; + }, + width: file.naturalWidth || file.videoWidth, + height: file.naturalHeight || file.videoHeight, + bgColor: 'transparent' + }); + return Tegaki.activeCtx.drawImage(file, 0, 0); + }, false); + return file.src = URL.createObjectURL(e.detail); + }; + if (Tegaki.bg && Tegaki.onDoneCb === FCX.oekakiCB && source === FCX.oekakiLatest) { + FCX.oekakiName = name; + return Tegaki.resume(); + } else { + document.addEventListener('QRFile', cb, false); + return document.dispatchEvent(new CustomEvent('QRGetFile', { + bubbles: true + })); + } + }); + }); + }, + toggle: function() { + return QR.oekaki.load(function() { + return QR.nodes.oekaki.hidden = !QR.nodes.oekaki.hidden; + }); + } + }; + +}).call(this); + +(function() { + var 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; }; + + QR.persona = { + always: {}, + types: { + name: [], + email: [], + sub: [] + }, + init: function() { + var i, item, len, ref; + if (!(Conf['Quick Reply'] || (Conf['Menu'] && Conf['Delete Link']))) { + return; + } + ref = Conf['QR.personas'].split('\n'); + for (i = 0, len = ref.length; i < len; i++) { + item = ref[i]; + QR.persona.parseItem(item.trim()); + } + }, + parseItem: function(item) { + var boards, match, ref, ref1, ref2, type, val; + 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(QR.persona.types[type], val) < 0) { + return QR.persona.types[type].push(val); + } + }, + load: function() { + var arr, i, len, list, ref, type, val; + ref = QR.persona.types; + for (type in ref) { + arr = ref[type]; + 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 m; + if (QR.persona.pwd != null) { + return QR.persona.pwd; + } else if ((m = d.cookie.match(/4chan_pass=([^;]+)/))) { + return decodeURIComponent(m[1]); + } else { + return ''; + } + }, + 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 + }; + return $.set('QR.persona', persona); + }); + } + }; + +}).call(this); + +(function() { + var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, + indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, + slice = [].slice; + + QR.post = (function() { + function _Class(select) { + this.select = bind(this.select, this); + var el, event, i, j, label, len, len1, prev, ref, ref1; + el = $.el('a', { + className: 'qr-preview', + draggable: true, + href: 'javascript:;' + }); + $.extend(el, { + innerHTML: "" + }); + this.nodes = { + el: el, + rm: el.firstChild, + spoiler: $('.qr-preview-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.spoiler, 'change', (function(_this) { + return function(e) { + _this.spoiler = e.target.checked; + if (_this === QR.selected) { + return QR.nodes.spoiler.checked = _this.spoiler; + } + }; + })(this)); + ref = $$('label', el); + for (i = 0, len = ref.length; i < len; i++) { + label = ref[i]; + $.on(label, 'click', function(e) { + return e.stopPropagation(); + }); + } + $.add(QR.nodes.dumpList, el); + ref1 = ['dragStart', 'dragEnter', 'dragLeave', 'dragOver', 'dragEnd', 'drop']; + for (j = 0, len1 = ref1.length; j < len1; j++) { + event = ref1[j]; + $.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 : ''; + _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); + URL.revokeObjectURL(this.URL); + return this.dismissErrors(); + }; + + _Class.prototype.lock = function(lock) { + var i, len, name, node, 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' : ''; + 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.removeAttribute('id'); + 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 i, len, name, node, 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"] || ''; + } + (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.updateComment(); + 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.saveFilename(); + return this.updateFilename(); + case 'name': + return QR.persona.set(this); + } + }; + + _Class.prototype.forceSave = function() { + var i, len, name, node, 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.setComment = function(com) { + this.com = com || null; + if (this === QR.selected) { + QR.nodes.com.value = this.com; + } + return this.updateComment(); + }; + + _Class.prototype.updateComment = function() { + if (this === QR.selected) { + QR.characterCount(); + } + this.nodes.span.textContent = this.com; + return $.queueTask(function() { + return QR.captcha.onPostChange(); + }); + }; + + _Class.rmErrored = function(e) { + var error, errors, i, j, len, post, ref; + e.stopPropagation(); + ref = QR.posts; + for (i = ref.length - 1; i >= 0; i += -1) { + post = ref[i]; + if (errors = post.errors) { + for (j = 0, len = errors.length; j < len; j++) { + error = errors[j]; + if (!(doc.contains(error))) { + continue; + } + post.rm(); + break; + } + } + } + }; + + _Class.prototype.error = function(className, message) { + var div, ref, rm, rmAll; + div = $.el('div', { + className: className + }); + $.extend(div, { + innerHTML: E(message) + "
      [delete] [delete all]" + }); + (this.errors || (this.errors = [])).push(div); + ref = $$('a', div), rm = ref[0], rmAll = ref[1]; + $.on(div, 'click', (function(_this) { + return function() { + if (indexOf.call(QR.posts, _this) >= 0) { + return _this.select(); + } + }; + })(this)); + $.on(rm, 'click', (function(_this) { + return function(e) { + e.stopPropagation(); + if (indexOf.call(QR.posts, _this) >= 0) { + return _this.rm(); + } + }; + })(this)); + $.on(rmAll, 'click', QR.post.rmErrored); + return QR.error(div, true); + }; + + _Class.prototype.fileError = function(message) { + return this.error('file-error', this.filename + ": " + message); + }; + + _Class.prototype.dismissErrors = function(test) { + var error, i, len, ref; + if (test == null) { + test = function() { + return true; + }; + } + if (this.errors) { + ref = this.errors; + for (i = 0, len = ref.length; i < len; i++) { + error = ref[i]; + if (doc.contains(error) && test(error)) { + error.parentNode.previousElementSibling.click(); + } + } + } + }; + + _Class.prototype.setFile = function(file1) { + var ext, ref; + this.file = file1; + if (Conf['Randomize Filename'] && g.BOARD.ID !== 'f') { + this.filename = "" + (Date.now() - Math.floor(Math.random() * 365 * $.DAY)); + if (ext = this.file.name.match(QR.validExtension)) { + this.filename += ext[0]; + } + } else { + this.filename = this.file.name; + } + this.filesize = $.bytesToString(this.file.size); + this.checkSize(); + $.addClass(this.nodes.el, 'has-file'); + $.queueTask(function() { + return QR.captcha.onPostChange(); + }); + URL.revokeObjectURL(this.URL); + this.saveFilename(); + if (this === QR.selected) { + this.showFileData(); + } else { + this.updateFilename(); + } + this.nodes.el.style.backgroundImage = null; + if (ref = this.file.type, indexOf.call(QR.mimeTypes, ref) < 0) { + return this.fileError('Unsupported file type.'); + } else if (/^(image|video)\//.test(this.file.type)) { + return this.readFile(); + } + }; + + _Class.prototype.checkSize = function() { + var max; + max = QR.max_size; + if (/^video\//.test(this.file.type)) { + max = Math.min(max, QR.max_size_video); + } + if (this.file.size > max) { + return this.fileError("File too large (file: " + this.filesize + ", max: " + ($.bytesToString(max)) + ")."); + } + }; + + _Class.prototype.readFile = function() { + var el, event, isVideo, onerror, onload; + isVideo = /^video\//.test(this.file.type); + el = $.el(isVideo ? 'video' : 'img'); + if (isVideo && !el.canPlayType(this.file.type)) { + return; + } + event = isVideo ? 'loadeddata' : 'load'; + onload = (function(_this) { + return function() { + $.off(el, event, onload); + $.off(el, 'error', onerror); + _this.checkDimensions(el); + return _this.setThumbnail(el); + }; + })(this); + onerror = (function(_this) { + return function() { + $.off(el, event, onload); + $.off(el, 'error', onerror); + _this.fileError((isVideo ? 'Video' : 'Image') + " appears corrupt"); + return URL.revokeObjectURL(el.src); + }; + })(this); + $.on(el, event, onload); + $.on(el, 'error', onerror); + return el.src = URL.createObjectURL(this.file); + }; + + _Class.prototype.checkDimensions = function(el) { + var duration, height, max_height, max_width, ref, videoHeight, videoWidth, width; + if (el.tagName === 'IMG') { + height = el.height, width = el.width; + if (height > QR.max_height || width > QR.max_width) { + this.fileError("Image too large (image: " + height + "x" + width + "px, max: " + QR.max_height + "x" + QR.max_width + "px)"); + } + if (height < QR.min_height || width < QR.min_width) { + return this.fileError("Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); + } + } else { + videoHeight = el.videoHeight, videoWidth = el.videoWidth, duration = el.duration; + max_height = Math.min(QR.max_height, QR.max_height_video); + max_width = Math.min(QR.max_width, QR.max_width_video); + if (videoHeight > max_height || videoWidth > max_width) { + this.fileError("Video too large (video: " + videoHeight + "x" + videoWidth + "px, max: " + max_height + "x" + max_width + "px)"); + } + if (videoHeight < QR.min_height || videoWidth < QR.min_width) { + this.fileError("Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); + } + if (!isFinite(duration)) { + this.fileError('Video lacks duration metadata (try remuxing)'); + } else if (duration > QR.max_duration_video) { + this.fileError("Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)"); + } + if (((ref = g.BOARD.ID) !== 'gif' && ref !== 'wsg') && $.hasAudio(el)) { + return this.fileError('Audio not allowed'); + } + } + }; + + _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.removeAttribute('title'); + QR.nodes.filename.removeAttribute('title'); + this.nodes.el.style.backgroundImage = null; + $.rmClass(this.nodes.el, 'has-file'); + this.showFileData(); + URL.revokeObjectURL(this.URL); + return this.dismissErrors(function(error) { + return $.hasClass(error, 'file-error'); + }); + }; + + _Class.prototype.saveFilename = function() { + this.file.newName = (this.filename || '').replace(/[\/\\]/g, '-'); + if (!QR.validExtension.test(this.filename)) { + return this.file.newName += "." + (QR.extensionFromType[this.file.type] || 'jpg'); + } + }; + + _Class.prototype.updateFilename = function() { + var long; + long = this.filename + " (" + this.filesize + ")"; + this.nodes.el.title = long; + if (this !== QR.selected) { + return; + } + return QR.nodes.filename.title = long; + }; + + _Class.prototype.showFileData = function() { + var ref; + if (this.file) { + this.updateFilename(); + QR.nodes.filename.value = this.filename; + $.addClass(QR.nodes.oekaki, 'has-file'); + $.addClass(QR.nodes.fileSubmit, 'has-file'); + } else { + $.rmClass(QR.nodes.oekaki, 'has-file'); + $.rmClass(QR.nodes.fileSubmit, 'has-file'); + } + if (((ref = this.file) != null ? ref.source : void 0) != null) { + QR.nodes.fileSubmit.dataset.source = this.file.source; + } else { + QR.nodes.fileSubmit.removeAttribute('data-source'); + } + return QR.nodes.spoiler.checked = this.spoiler; + }; + + _Class.prototype.pasteText = function(file) { + var reader; + this.pasting = true; + reader = new FileReader(); + reader.onload = (function(_this) { + return function(e) { + var result; + result = e.target.result; + _this.setComment((_this.com ? _this.com + "\n" + result : result)); + return delete _this.pasting; + }; + })(this); + return reader.readAsText(file); + }; + + _Class.prototype.dragStart = function(e) { + var left, ref, top; + ref = this.getBoundingClientRect(), left = ref.left, top = ref.top; + e.dataTransfer.setDragImage(this, e.clientX - left, e.clientY - top); + 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; + + })(); + +}).call(this); + +QuoteBacklink = (function() { + var QuoteBacklink; + + QuoteBacklink = { + containers: {}, + init: function() { + var ref; + if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Quote Backlinks']) { + return; + } + Callbacks.Post.push({ + name: 'Quote Backlinking Part 1', + cb: this.firstNode + }); + return Callbacks.Post.push({ + name: 'Quote Backlinking Part 2', + cb: this.secondNode + }); + }, + firstNode: function() { + var a, clone, container, containers, hash, i, j, k, len, len1, len2, link, markYours, nodes, post, quote, ref, ref1, ref2; + if (this.isClone || !this.quotes.length || this.isRebuilt) { + return; + } + markYours = Conf['Mark Quotes of You'] && ((ref = QuoteYou.db) != null ? ref.get({ + boardID: this.board.ID, + threadID: this.thread.ID, + postID: this.ID + }) : void 0); + 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)' : '') + }); + ref1 = this.quotes; + for (i = 0, len = ref1.length; i < len; i++) { + quote = ref1[i]; + containers = [QuoteBacklink.getContainer(quote)]; + if ((post = g.posts[quote]) && post.nodes.backlinkContainer) { + ref2 = post.clones; + for (j = 0, len1 = ref2.length; j < len1; j++) { + clone = ref2[j]; + containers.push(clone.nodes.backlinkContainer); + } + } + for (k = 0, len2 = containers.length; k < len2; k++) { + container = containers[k]; + link = a.cloneNode(true); + nodes = container.firstChild ? [$.tn(' '), link] : [link]; + 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' + })); + } + }; + + return QuoteBacklink; + +}).call(this); + +QuoteCT = (function() { + var QuoteCT; + + 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 Callbacks.Post.push({ + name: 'Mark Cross-thread Quotes', + cb: this.node + }); + }, + node: function() { + var board, boardID, i, len, quotelink, ref, ref1, ref2, thread, threadID; + if (this.isClone && this.thread === this.context.thread) { + return; + } + ref = this.context, 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)); + } + } + } + }; + + return QuoteCT; + +}).call(this); + +QuoteInline = (function() { + var QuoteInline; + + QuoteInline = { + init: function() { + var ref; + if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Quote Inlining']) { + return; + } + if (Conf['Comment Expansion']) { + ExpandComment.callbacks.push(this.node); + } + return Callbacks.Post.push({ + name: 'Quote Inlining', + cb: this.node + }); + }, + node: function() { + var i, isClone, j, len, len1, link, process, 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); + } + }, + process: function(link, clone) { + if (Conf['Quote Hash Navigation']) { + if (!clone) { + $.after(link, QuoteInline.qiQuote(link, $.hasClass(link, 'filtered'))); + } + } + return $.on(link, 'click', QuoteInline.toggle); + }, + 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, quoter, ref, ref1, threadID; + if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) { + return; + } + ref = Get.postDataFromLink(this), boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; + if (Conf['Inline Cross-thread Quotes Only'] && g.VIEW === 'thread' && ((ref1 = g.posts[boardID + "." + postID]) != null ? ref1.nodes.root.offsetParent : void 0)) { + return; + } + e.preventDefault(); + quoter = Get.postFromNode(this); + context = quoter.context; + if ($.hasClass(this, 'inlined')) { + QuoteInline.rm(this, boardID, threadID, postID, context); + } else { + if ($.x("ancestor::div[@data-full-i-d='" + boardID + "." + postID + "']", this)) { + return; + } + QuoteInline.add(this, boardID, threadID, postID, context, quoter); + } + 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, quoter) { + var inline, isBacklink, post, qroot, root; + isBacklink = $.hasClass(quotelink, 'backlink'); + inline = $.el('div', { + className: 'inline' + }); + inline.dataset.fullID = boardID + "." + postID; + 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, quoter); + 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, ref, root; + isBacklink = $.hasClass(quotelink, 'backlink'); + root = QuoteInline.findRoot(quotelink, isBacklink); + root = $.x("following-sibling::div[@data-full-i-d='" + boardID + "." + 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'); + } + } + }; + + return QuoteInline; + +}).call(this); + +QuoteOP = (function() { + var QuoteOP, + 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; }; + + 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 Callbacks.Post.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.context.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)); + } + } + } + }; + + return QuoteOP; + +}).call(this); + +QuotePreview = (function() { + var QuotePreview, + slice = [].slice; + + 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 Callbacks.Post.push({ + name: 'Quote Previewing', + cb: this.node + }); + }, + node: function() { + var i, len, link, 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, i, len, origin, post, postID, posts, qp, ref, threadID; + if ($.hasClass(this, 'inlined') || !d.contains(this)) { + 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.postFromNode(this)); + UI.hover({ + root: this, + el: qp, + latestEvent: e, + endEvents: 'mouseout click', + cb: QuotePreview.mouseout + }); + if (Conf['Quote Highlighting'] && (origin = g.posts[boardID + "." + postID])) { + posts = [origin].concat(origin.clones); + posts.pop(); + for (i = 0, len = posts.length; i < len; i++) { + post = posts[i]; + $.addClass(post.nodes.post, 'qphl'); + } + } + }, + mouseout: function() { + var clone, i, len, post, ref, root; + 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'); + } + } + }; + + return QuotePreview; + +}).call(this); + +QuoteStrikeThrough = (function() { + var QuoteStrikeThrough; + + 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 Callbacks.Post.push({ + name: 'Strike-through Quotes', + cb: this.node + }); + }, + node: function() { + var boardID, i, len, postID, quotelink, 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'); + } + } + } + }; + + return QuoteStrikeThrough; + +}).call(this); + +QuoteThreading = +/* + <3 aeosynth + */ + +(function() { + var QuoteThreading; + + QuoteThreading = { + init: function() { + if (!(Conf['Quote Threading'] && g.VIEW === 'thread')) { + return; + } + this.controls = $.el('label', { + innerHTML: " Threading" + }); + this.threadNewLink = $.el('span', { + className: 'brackets-wrap threadnewlink', + hidden: true + }); + $.extend(this.threadNewLink, { + innerHTML: "Thread New Posts" + }); + this.input = $('input', this.controls); + this.input.checked = Conf['Thread Quotes']; + $.on(this.input, 'change', this.setEnabled); + $.on(this.input, 'change', this.rethread); + $.on(this.threadNewLink.firstElementChild, 'click', this.rethread); + $.on(d, '4chanXInitFinished', (function(_this) { + return function() { + return _this.ready = true; + }; + })(this)); + Header.menu.addEntry(this.entry = { + el: this.controls, + order: 99 + }); + Callbacks.Thread.push({ + name: 'Quote Threading', + cb: this.setThread + }); + return Callbacks.Post.push({ + name: 'Quote Threading', + cb: this.node + }); + }, + parent: {}, + children: {}, + inserted: {}, + setEnabled: function() { + var other, ref; + other = (ref = ReplyPruning.inputs) != null ? ref.enabled : void 0; + if (this.checked && (other != null ? other.checked : void 0)) { + other.checked = false; + $.event('change', null, other); + } + return $.cb.checked.call(this); + }, + setThread: function() { + QuoteThreading.thread = this; + return $.asap((function() { + return !Conf['Thread Updater'] || $('.navLinksBot > .updatelink'); + }), function() { + var navLinksBot; + if ((navLinksBot = $('.navLinksBot'))) { + return $.add(navLinksBot, [$.tn(' '), QuoteThreading.threadNewLink]); + } + }); + }, + node: function() { + var ancestor, j, lastParent, len, parent, parents, quote, ref; + if (this.isFetchedQuote || this.isClone || !this.isReply) { + return; + } + parents = new Set(); + lastParent = null; + ref = this.quotes; + for (j = 0, len = ref.length; j < len; j++) { + quote = ref[j]; + 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, j, len, posts; + posts = [post]; + if (children = QuoteThreading.children[post.fullID]) { + for (j = 0, len = children.length; j < len; j++) { + child = children[j]; + posts = posts.concat(QuoteThreading.descendants(child)); + } + } + return posts; + }, + insert: function(post) { + var base, child, children, descendants, i, j, k, l, len, name, next, nodes, order, parent, prev, prev2, threadContainer, x; + if (!(Conf['Thread Quotes'] && (parent = QuoteThreading.parent[post.fullID]) && !QuoteThreading.inserted[post.fullID])) { + return false; + } + descendants = QuoteThreading.descendants(post); + if (!Unread.posts.has(parent.ID)) { + if ((function() { + var j, len, x; + for (j = 0, len = descendants.length; j < len; j++) { + x = descendants[j]; + 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 (j = children.length - 1; j >= 0; j += -1) { + child = children[j]; + if (child.ID >= post.ID) { + i--; + } + } + if (i !== children.length) { + next = children[i]; + for (k = 0, len = descendants.length; k < len; k++) { + x = descendants[k]; + 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 (l = descendants.length - 1; l >= 0; l += -1) { + x = descendants[l]; + 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; + if (!QuoteThreading.ready) { + return; + } + thread = QuoteThreading.thread; + posts = thread.posts; + QuoteThreading.threadNewLink.hidden = true; + if (Conf['Thread Quotes']) { + 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(); + } + }; + + return QuoteThreading; + +}).call(this); + +QuoteYou = (function() { + var QuoteYou; + + QuoteYou = { + init: function() { + var ref; + if (!Conf['Remember Your Posts']) { + return; + } + this.db = new DataBoard('yourPosts'); + $.sync('Remember Your Posts', function(enabled) { + return Conf['Remember Your Posts'] = enabled; + }); + $.on(d, 'QRPostSuccessful', function(e) { + var boardID, postID, ref, threadID; + $.forceSync('Remember Your Posts'); + if (Conf['Remember Your Posts']) { + ref = e.detail, boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; + return QuoteYou.db.set({ + boardID: boardID, + threadID: threadID, + postID: postID, + val: true + }); + } + }); + if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { + 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 Callbacks.Post.push({ + name: 'Mark Quotes of You', + cb: this.node + }); + }, + node: function() { + var i, len, quotelink, ref; + if (this.isClone) { + return; + } + if (QuoteYou.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 (!(QuoteYou.db.get(Get.postDataFromLink(quotelink)))) { + continue; + } + if (Conf['Mark Quotes of You']) { + $.add(quotelink, $.tn(QuoteYou.text)); + } + $.addClass(quotelink, 'you'); + $.addClass(this.nodes.root, 'quotesYou'); + } + }, + cb: { + seek: function(type) { + var highlight, post, posts, result, str; + if (highlight = $('.highlight')) { + $.rmClass(highlight, 'highlight'); + } + if (!(QuoteYou.lastRead && doc.contains(QuoteYou.lastRead) && $.hasClass(QuoteYou.lastRead, 'quotesYou'))) { + 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(root) { + var post; + post = $('.post', root); + if (!post.getBoundingClientRect().height) { + return false; + } else { + QuoteYou.lastRead = root; + window.location = "#" + post.id; + Header.scrollTo(post); + $.addClass(post, 'highlight'); + return true; + } + } + } + }; + + return QuoteYou; + +}).call(this); + +Quotify = (function() { + var Quotify, + indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, + slice = [].slice; + + 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 Callbacks.Post.push({ + name: 'Resurrect Quotes', + cb: this.node + }); + }, + node: function() { + var deadlink, i, len, ref; + if (this.isClone) { + return; + } + ref = $$('.deadlink', this.nodes.comment); + for (i = 0, len = ref.length; i < len; i++) { + deadlink = ref[i]; + 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', + 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', + 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)); + } + }; + + return Quotify; + +}).call(this); + +Main = (function() { + var Main; + + Main = { + init: function() { + var db, flatten, items, j, key, len, ref; + if (d.body && !$('title', d.head)) { + return; + } + if (window['4chan X antidup']) { + return; + } + window['4chan X antidup'] = true; + if (location.hostname === 'www.google.com') { + $.get('Captcha Fixes', true, function(arg) { + var enabled; + enabled = arg['Captcha Fixes']; + if (enabled) { + return $.ready(function() { + return Captcha.fixes.init(); + }); + } + }); + return; + } + $.global(function() { + var j, len, nuke, prop, ref; + nuke = function(obj, prop) { + try { + return Object.defineProperty(obj, prop, { + configurable: false, + get: function() { + throw new Error(); + }, + set: function() { + throw new Error(); + } + }); + } catch (_error) {} + }; + ref = ['atOptions', 'adsterra_key', 'EpmadsConfig', 'epmads_key', 'EpomConfig', 'epom_key', 'exoDocumentProtocol']; + for (j = 0, len = ref.length; j < len; j++) { + prop = ref[j]; + nuke(window, prop); + } + }); + $.on(window, 'beforescriptexecute', function(e) { + var host, ref, ref1; + host = (ref = e.target.src.split('/')[2]) != null ? (ref1 = ref.match(/[^.]+\.[^.]+$/)) != null ? ref1[0] : void 0 : void 0; + if (host === 'bnhtml.com' || host === 'ecpmrocks.com' || host === 'advertisation.com' || host === 'exoclick.com') { + return e.preventDefault(); + } + }); + $.on(d, '4chanXInitFinished', function() { + if (Main.expectInitFinished) { + return delete Main.expectInitFinished; + } else { + new Notice('error', 'Error: Multiple copies of 4chan X are enabled.'); + return $.addClass(doc, 'tainted'); + } + }); + 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); + ref = DataBoard.keys; + for (j = 0, len = ref.length; j < len; j++) { + db = ref[j]; + Conf[db] = { + boards: {} + }; + } + Conf['selectedArchives'] = {}; + Conf['cooldowns'] = {}; + Conf['Index Sort'] = {}; + Conf['Except Archives from Encryption'] = false; + Conf['JSON Navigation'] = true; + Conf['Oekaki Links'] = true; + items = {}; + for (key in Conf) { + items[key] = void 0; + } + items['previousversion'] = void 0; + return $.get(items, function(items) { + return $.asap((function() { + var doc; + return doc = d.documentElement; + }), function() { + var ref1, val; + if ($.cantSet) { + + } else if (items.previousversion == null) { + Main.ready(function() { + $.set('previousversion', g.VERSION); + return Settings.open(); + }); + } else if (items.previousversion !== g.VERSION) { + Main.upgrade(items); + } + for (key in Conf) { + val = Conf[key]; + Conf[key] = (ref1 = items[key]) != null ? ref1 : val; + } + return Main.initFeatures(); + }); + }); + }, + upgrade: function(items) { + var changes, previousversion; + previousversion = items.previousversion; + changes = Settings.upgrade(items, previousversion); + items.previousversion = changes.previousversion = g.VERSION; + return $.set(changes, function() { + var el, ref; + if ((ref = items['Show Updated Notifications']) != null ? ref : true) { + el = $.el('span', { + innerHTML: "4chan X has been updated to version " + E(g.VERSION) + "." + }); + return new Notice('info', el, 15); + } + }); + }, + initFeatures: function() { + var err, feature, hostname, j, len, match, name, pathname, ref, ref1, ref2, ref3, search; + hostname = location.hostname, search = location.search; + pathname = location.pathname.split(/\/+/); + if (hostname !== 'www.4chan.org') { + g.BOARD = new Board(pathname[1]); + } + if (hostname === 'boards.4chan.org' || hostname === 'sys.4chan.org' || hostname === 'www.4chan.org') { + $.global(function() { + document.documentElement.classList.add('js-enabled'); + return window.FCX = {}; + }); + Main.jsEnabled = $.hasClass(doc, 'js-enabled'); + } + switch (hostname) { + case 'www.4chan.org': + $.onExists(doc, 'body', function() { + return $.addStyle(CSS.www); + }); + Captcha.replace.init(); + return; + case 'sys.4chan.org': + if (pathname[2] === 'imgboard.php') { + if (/\bmode=report\b/.test(search)) { + Report.init(); + } else if ((match = search.match(/\bres=(\d+)/))) { + $.ready(function() { + var ref; + if (Conf['404 Redirect'] && ((ref = $.id('errmsg')) != null ? ref.textContent : void 0) === 'Error: Specified thread does not exist.') { + return Redirect.navigate('thread', { + boardID: g.BOARD.ID, + postID: +match[1] + }); + } + }); + } + } else if (pathname[2] === 'post') { + PostSuccessful.init(); + } + return; + case 'i.4cdn.org': + if (!(pathname[2] && !/s\.jpg$/.test(pathname[2]))) { + return; + } + $.asap((function() { + return d.readyState !== 'loading'; + }), function() { + var ref, video; + if (Conf['404 Redirect'] && ((ref = d.title) === '4chan - Temporarily Offline' || ref === '4chan - 404 Not Found')) { + return Redirect.navigate('file', { + boardID: g.BOARD.ID, + filename: pathname[pathname.length - 1] + }); + } 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 ((ref = pathname[2]) === 'thread' || ref === 'res') { + g.VIEW = 'thread'; + g.THREADID = +pathname[3]; + } else if ((ref1 = pathname[2]) === 'catalog' || ref1 === 'archive') { + g.VIEW = pathname[2]; + } else if (pathname[2].match(/^\d*$/)) { + g.VIEW = 'index'; + } else { + return; + } + g.threads = new SimpleDict(); + g.posts = new SimpleDict(); + $.onExists(doc, 'body', Main.initStyle); + ref2 = Main.features; + for (j = 0, len = ref2.length; j < len; j++) { + ref3 = ref2[j], name = ref3[0], feature = ref3[1]; + try { + feature.init(); + } catch (_error) { + err = _error; + Main.handleErrors({ + message: "\"" + name + "\" initialization crashed.", + error: err + }); + } + } + return $.ready(Main.initReady); + }, + initStyle: function() { + var keyboard, ref; + if (!Main.isThisPageLegit()) { + 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); + if ($.engine) { + $.addClass(doc, $.engine); + } + $.onExists(doc, '.ad-cnt', function(ad) { + return $.onExists(ad, 'img', function() { + return $.addClass(doc, 'ads-loaded'); + }); + }); + if (Conf['Autohiding Scrollbar']) { + $.addClass(doc, 'autohiding-scrollbar'); + } + $.ready(function() { + if (d.body.clientHeight > doc.clientHeight && (window.innerWidth === doc.clientWidth) !== Conf['Autohiding Scrollbar']) { + Conf['Autohiding Scrollbar'] = !Conf['Autohiding Scrollbar']; + $.set('Autohiding Scrollbar', Conf['Autohiding Scrollbar']); + return $.toggleClass(doc, 'autohiding-scrollbar'); + } + }); + $.addStyle(CSS.boards, 'fourchanx-css'); + Main.bgColorStyle = $.el('style', { + id: 'fourchanx-bgcolor-css' + }); + keyboard = false; + $.on(d, 'mousedown', function() { + return keyboard = false; + }); + $.on(d, 'keydown', function(e) { + if (e.keyCode === 9) { + return keyboard = true; + } + }); + window.addEventListener('focus', (function() { + return doc.classList.toggle('keyboard-focus', keyboard); + }), true); + 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 bgColor, div, j, len, styleSheet; + $.rmClass(doc, style); + style = null; + for (j = 0, len = styleSheets.length; j < len; j++) { + styleSheet = styleSheets[j]; + if (styleSheet.href === (mainStyleSheet != null ? mainStyleSheet.href : void 0)) { + style = styleSheet.title.toLowerCase().replace('new', '').trim().replace(/\s+/g, '-'); + break; + } + } + if (style) { + $.addClass(doc, style); + return $.rm(Main.bgColorStyle); + } else { + div = $.el('div', { + className: 'reply' + }); + div.style.cssText = 'position: absolute; visibility: hidden;'; + $.add(d.body, div); + bgColor = window.getComputedStyle(div).backgroundColor; + $.rm(div); + Main.bgColorStyle.textContent = ".dialog, .suboption-list > div:last-of-type {\n background-color: " + bgColor + ";\n}"; + return $.after($.id('fourchanx-css'), Main.bgColorStyle); + } + }; + setStyle(); + if (!mainStyleSheet) { + return; + } + return new MutationObserver(setStyle).observe(mainStyleSheet, { + attributes: true, + attributeFilter: ['href'] + }); + }, + initReady: function() { + var msg, ref, ref1, ref2; + if (g.VIEW === 'thread' && (((ref = d.title) === '4chan - Temporarily Offline' || ref === '4chan - 404 Not Found') || ($('.board') && !$('.opContainer')))) { + ThreadWatcher.set404(g.BOARD.ID, g.THREADID, function() { + if (Conf['404 Redirect']) { + return Redirect.navigate('thread', { + boardID: g.BOARD.ID, + threadID: g.THREADID, + postID: +location.hash.match(/\d+/) + }, "/" + g.BOARD + "/"); + } + }); + return; + } + if ((ref1 = d.title) === '4chan - Temporarily Offline' || ref1 === '4chan - 404 Not Found') { + return; + } + if (((ref2 = g.VIEW) === 'index' || ref2 === 'thread') && !$('.board + *')) { + msg = $.el('div', { + innerHTML: "The page didn't load completely.
      Some features may not work unless you reload." + }); + $.on($('a', msg), 'click', function() { + return location.reload(); + }); + new Notice('warning', msg); + } + if (!(Conf['JSON Index'] && g.VIEW === 'index')) { + return Main.initThread(); + } else { + Main.expectInitFinished = true; + return $.event('4chanXInitFinished'); + } + }, + initThread: function() { + var board, err, errors, j, k, len, len1, m, postRoot, posts, ref, ref1, scriptData, thread, threadRoot, threads; + if ((board = $('.board'))) { + threads = []; + posts = []; + ref = $$('.board > .thread', board); + for (j = 0, len = ref.length; j < len; j++) { + threadRoot = ref[j]; + thread = new Thread(+threadRoot.id.slice(1), g.BOARD); + threads.push(thread); + ref1 = $$('.thread > .postContainer', threadRoot); + for (k = 0, len1 = ref1.length; k < len1; k++) { + postRoot = ref1[k]; + if ($('.postMessage', postRoot)) { + 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 l, len2, post; + for (l = 0, len2 = posts.length; l < len2; l++) { + post = posts[l]; + QuoteThreading.insert(post); + } + Main.expectInitFinished = true; + return $.event('4chanXInitFinished'); + }); + } else { + Main.expectInitFinished = true; + return $.event('4chanXInitFinished'); + } + }, + callbackNodes: function(klass, nodes) { + var cb, i, node; + i = 0; + cb = Callbacks[klass]; + while (node = nodes[i++]) { + cb.execute(node); + } + }, + callbackNodesDB: function(klass, nodes, cb) { + var cbs, fn, i, softTask; + i = 0; + cbs = Callbacks[klass]; + 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, j, len, logs; + if (!(errors instanceof Array)) { + error = errors; + } else if (errors.length === 1) { + error = errors[0]; + } + if (error) { + new Notice('error', Main.parseError(error, Main.reportLink([error])), 15); + return; + } + div = $.el('div', { + innerHTML: E(errors.length) + " errors occurred." + (Main.reportLink(errors)).innerHTML + " [show]" + }); + $.on(div.lastElementChild, 'click', function() { + var ref; + return ref = this.textContent === 'show' ? ['hide', false] : ['show', true], this.textContent = ref[0], logs.hidden = ref[1], ref; + }); + logs = $.el('div', { + hidden: true + }); + for (j = 0, len = errors.length; j < len; j++) { + error = errors[j]; + $.add(logs, Main.parseError(error)); + } + return new Notice('error', [div, logs], 30); + }, + parseError: function(data, reportLink) { + var context, error, lines, message, ref, ref1; + c.error(data.message, data.error.stack); + message = $.el('div', { + innerHTML: E(data.message) + ((reportLink) ? (reportLink).innerHTML : "") + }); + error = $.el('div', { + textContent: (data.error.name || 'Error') + ": " + (data.error.message || 'see console for details') + }); + lines = ((ref = data.error.stack) != null ? (ref1 = ref.match(/\d+(?=:\d+\)?$)/mg)) != null ? ref1.join().replace(/^/, ' at ') : void 0 : void 0) || ''; + context = $.el('div', { + textContent: "(4chan X ccd0 v" + g.VERSION + " " + $.platform + " on " + $.engine + lines + ")" + }); + return [message, error, context]; + }, + reportLink: function(errors) { + var data, details, ref, title, url; + data = errors[0]; + title = data.message; + if (errors.length > 1) { + title += " (+" + (errors.length - 1) + " other errors)"; + } + details = "[Please describe the steps needed to reproduce this error.]\n\nScript: 4chan X ccd0 v" + g.VERSION + " " + $.platform + "\nUser agent: " + navigator.userAgent + "\nURL: " + location.href + "\n\n" + data.error + "\n" + (((ref = data.error.stack) != null ? ref.replace(data.error.toString(), '').trim() : void 0) || ''); + details = details.replace(/file:\/{3}.+\//g, ''); + url = "https://gitreports.com/issue/ccd0/4chan-x?issue_title=" + (encodeURIComponent(title)) + "&details=" + (encodeURIComponent(details)); + return { + innerHTML: " [report]" + }; + }, + 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(); + } + }); + }, + features: [['Polyfill', Polyfill], ['Normalize URL', NormalizeURL], ['Captcha Configuration', Captcha.replace], ['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], ['Thread Links', ThreadLinks], ['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 Personas', QR.persona], ['Quick Reply', QR], ['Cooldown', QR.cooldown], ['Pass Link', PassLink], ['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], ['Edit Link', QR.oekaki.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], ['Flash Features', Flash], ['Reply Pruning', ReplyPruning]] + }; + + return Main; + +}).call(this); + +Main.init(); }).call(this); diff --git a/builds/4chan-X-noupdate.crx b/builds/4chan-X-noupdate.crx index 41f0d6c28..2eebf6d96 100644 Binary files a/builds/4chan-X-noupdate.crx and b/builds/4chan-X-noupdate.crx differ diff --git a/builds/4chan-X-noupdate.user.js b/builds/4chan-X-noupdate.user.js index be59133ab..ae3d5477b 100644 --- a/builds/4chan-X-noupdate.user.js +++ b/builds/4chan-X-noupdate.user.js @@ -1,7 +1,6 @@ -// Generated by CoffeeScript // ==UserScript== // @name 4chan X -// @version 1.11.30.3 +// @version 1.11.31.0 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X @@ -107,7 +106,7 @@ /* * Contains data from external sources: * -* audio/beep.wav from http://freesound.org/people/pierrecartoons1979/sounds/90112/ +* src/Monitoring/ThreadUpdater/beep.wav from http://freesound.org/people/pierrecartoons1979/sounds/90112/ * cc-by-nc-3.0 * * Font Awesome by Dave Gandy (http://fontawesome.io) @@ -119,12 +118,56 @@ '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, Flash, Fourchan, Gallery, Get, Header, IDColor, IDHighlight, ImageCommon, ImageExpand, ImageHover, ImageLoader, Index, Keybinds, Linkify, Main, MarkNewIPs, Menu, Metadata, Nav, NormalizeURL, Notice, PSAHiding, PassLink, Polyfill, Post, PostHiding, PostSuccessful, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, RandomAccessList, Recursive, Redirect, RelativeDates, RemoveSpoilers, ReplyPruning, Report, ReportLink, RevealSpoilers, Sauce, Settings, ShimSet, SimpleDict, Thread, ThreadExcerpt, ThreadHiding, ThreadLinks, 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; }, - extend = 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; }, - hasProp = {}.hasOwnProperty, - bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + +var $, $$, Anonymize, AntiAutoplay, ArchiveLink, Banner, Board, Build, CSS, Callbacks, Captcha, CatalogLinks, CatalogThread, Config, Connection, CrossOrigin, CustomCSS, DataBoard, DeleteLink, DownloadLink, Embedding, ExpandComment, ExpandThread, FappeTyme, Favicon, Fetcher, FileInfo, Filter, Flash, Fourchan, Gallery, Get, Header, IDColor, IDHighlight, ImageCommon, ImageExpand, ImageHover, ImageLoader, Index, Keybinds, Linkify, Main, MarkNewIPs, Menu, Metadata, Nav, NormalizeURL, Notice, PSAHiding, PassLink, Polyfill, Post, PostHiding, PostSuccessful, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, RandomAccessList, Recursive, Redirect, RelativeDates, RemoveSpoilers, ReplyPruning, Report, ReportLink, RevealSpoilers, Sauce, Settings, ShimSet, SimpleDict, Thread, ThreadExcerpt, ThreadHiding, ThreadLinks, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, Volume; + +var Conf, E, c, d, doc, g; + +Conf = {}; +c = console; +d = document; +doc = d.documentElement; + +g = { + VERSION: '1.11.31.0', + NAMESPACE: '4chan X.', + 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); + }; +})(); + +E.cat = function(templates) { + var html, i, len; + html = ''; + for (i = 0, len = templates.length; i < len; i++) { + html += templates[i].innerHTML; + } + return html; +}; + +E.url = function(content) { + return "data:text/html;charset=utf-8," + encodeURIComponent(content.innerHTML); +}; + +Config = (function() { + var Config; Config = { main: { @@ -368,7 +411,7 @@ ":root.tomorrow div.boardTitle {\n" + " font-family: sans-serif !important;\n" + " text-shadow: 1px 1px 1px rgba(167,170,168,0.6);\n" + -"}", +"}\n", hotkeys: { 'Toggle board list': ['Ctrl+b', 'Toggle the full board list.'], 'Toggle header': ['Shift+h', 'Toggle the auto-hide option of the header.'], @@ -434,18204 +477,23 @@ 'Autohiding Scrollbar': false }; - Conf = {}; + return Config; - c = console; +}).call(this); - d = document; +CSS = { - doc = d.documentElement; - - g = { - VERSION: '1.11.30.3', - NAMESPACE: '4chan X.', - 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); - }; - })(); - - E.cat = function(templates) { - var html, k, len1, x; - html = ''; - for (k = 0, len1 = templates.length; k < len1; k++) { - x = templates[k]; - html += x.innerHTML; - } - return html; - }; - - E.url = function(content) { - return "data:text/html;charset=utf-8," + (encodeURIComponent(content.innerHTML)); - }; - - $ = 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: "4chan X was blocked from loading the following URL:

      [More info]" - }); - $('span', message).textContent = (/^\/\//.test(url) ? location.protocol : '') + url; - return new Notice('warning', message, 30, function() { - return delete blockedURLs[url]; - }); - }; - return function(url, options, extra) { - var err, event, form, k, len1, r, ref, ref1, type, upCallbacks, whenModified; - if (options == null) { - options = {}; - } - if (extra == null) { - extra = {}; - } - type = extra.type, whenModified = extra.whenModified, upCallbacks = extra.upCallbacks, form = extra.form; - url = url.replace(/^((?:https?:)?\/\/(?:\w+\.)?4c(?:ha|d)n\.org)\/adv\//, '$1//adv/'); - r = new XMLHttpRequest(); - type || (type = form && 'post' || 'get'); - try { - r.open(type, url, true); - } catch (_error) { - err = _error; - blockedError(url); - ref = ['error', 'loadend']; - for (k = 0, len1 = ref.length; k < len1; k++) { - event = ref[k]; - r["on" + event] = options["on" + event]; - $.queueTask($.event, event, null, r); - } - return; - } - if (whenModified) { - if (((ref1 = lastModified[whenModified]) != null ? ref1[url] : void 0) != null) { - r.setRequestHeader('If-Modified-Since', lastModified[whenModified][url]); - } - $.on(r, 'load', function() { - return (lastModified[whenModified] || (lastModified[whenModified] = {}))[url] = r.getResponseHeader('Last-Modified'); - }); - } - if (/\.json$/.test(url)) { - if (options.responseType == null) { - options.responseType = 'json'; - } - } - $.extend(r, options); - if (options.responseType === 'json' && r.responseType !== 'json' && delete r.response) { - Object.defineProperty(r, 'response', { - configurable: true, - enumerable: true, - get: function() { - return JSON.parse(r.responseText); - } - }); - } - $.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, true); - }); - } 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 fn1, k, len1, ref; - this.evt = e; - ref = this.callbacks; - fn1 = (function(_this) { - return function(cb) { - return $.queueTask(function() { - return cb.call(_this, e, false); - }); - }; - })(this); - for (k = 0, len1 = ref.length; k < len1; k++) { - cb = ref[k]; - fn1(cb); - } - 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, cb) { - var el, observer; - if (el = $(selector, root)) { - return cb(el); - } - if ($.engine === 'edge' && d.readyState === 'loading') { - $.asap((function() { - return d.readyState !== 'loading' || $(selector, root); - }), function() { - return $.onExists(root, selector, cb); - }); - return; - } - observer = new MutationObserver(function() { - if (el = $(selector, root)) { - observer.disconnect(); - return cb(el); - } - }); - return observer.observe(root, { - childList: true, - subtree: true - }); - }; - - $.addStyle = function(css, id, test) { - var style; - if (test == null) { - test = 'head'; - } - style = $.el('style', { - textContent: css - }); - if (id != null) { - style.id = id; - } - $.onExists(doc, 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, k, len1; - el = arguments[0], classNames = 2 <= arguments.length ? slice.call(arguments, 1) : []; - for (k = 0, len1 = classNames.length; k < len1; k++) { - className = classNames[k]; - el.classList.add(className); - } - }; - - $.rmClass = function() { - var className, classNames, el, k, len1; - el = arguments[0], classNames = 2 <= arguments.length ? slice.call(arguments, 1) : []; - for (k = 0, len1 = classNames.length; k < len1; k++) { - className = classNames[k]; - 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 != null ? el.remove() : void 0; - }; - - $.rmAll = function(root) { - return root.textContent = null; - }; - - $.tn = function(s) { - return d.createTextNode(s); - }; - - $.frag = function() { - return d.createDocumentFragment(); - }; - - $.nodes = function(nodes) { - var frag, k, len1, node; - if (!(nodes instanceof Array)) { - return nodes; - } - frag = $.frag(); - for (k = 0, len1 = nodes.length; k < len1; k++) { - node = nodes[k]; - 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, properties2) { - var el; - el = d.createElement(tag); - if (properties) { - $.extend(el, properties); - } - if (properties2) { - $.extend(el, properties2); - } - return el; - }; - - $.on = function(el, events, handler) { - var event, k, len1, ref; - ref = events.split(' '); - for (k = 0, len1 = ref.length; k < len1; k++) { - event = ref[k]; - el.addEventListener(event, handler, false); - } - }; - - $.off = function(el, events, handler) { - var event, k, len1, ref; - ref = events.split(' '); - for (k = 0, len1 = ref.length; k < len1; k++) { - event = ref[k]; - 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 - })); - }; - - (function() { - var clone, err, ref, unsafeConstructors; - if (!(/PaleMoon\//.test(navigator.userAgent) && +(typeof GM_info !== "undefined" && GM_info !== null ? (ref = GM_info.version) != null ? ref.split('.')[0] : void 0 : void 0) >= 2 && typeof cloneInto === 'undefined')) { - return; - } - try { - return new CustomEvent('x', { - detail: {} - }); - } catch (_error) { - err = _error; - unsafeConstructors = { - Object: unsafeWindow.Object, - Array: unsafeWindow.Array - }; - clone = function(obj) { - var constructor, key, obj2, val; - if ((obj != null) && typeof obj === 'object' && (constructor = unsafeConstructors[obj.constructor.name])) { - obj2 = new constructor(); - for (key in obj) { - val = obj[key]; - obj2[key] = clone(val); - } - return obj2; - } else { - return obj; - } - }; - return $.event = function(event, detail, root) { - if (root == null) { - root = d; - } - return root.dispatchEvent(new CustomEvent(event, { - bubbles: true, - detail: clone(detail) - })); - }; - } - })(); - - $.open = typeof GM_openInTab !== "undefined" && GM_openInTab !== null ? GM_openInTab : function(url) { - return window.open(url, '_blank'); - }; - - $.debounce = function(wait, fn) { - var args, exec, lastCall, that, timeout; - lastCall = 0; - timeout = null; - that = null; - args = null; - exec = function() { - lastCall = Date.now(); - return fn.apply(that, args); - }; - return function() { - args = arguments; - that = this; - if (lastCall < Date.now() - wait) { - return exec(); - } - clearTimeout(timeout); - return timeout = setTimeout(exec, wait); - }; - }; - - $.queueTask = (function() { - var execTask, taskChannel, taskQueue; - taskQueue = []; - execTask = function() { - var args, func, task; - task = taskQueue.shift(); - func = task[0]; - args = Array.prototype.slice.call(task, 1); - return func.apply(func, args); - }; - if (window.MessageChannel) { - taskChannel = new MessageChannel(); - taskChannel.port1.onmessage = execTask; - return function() { - taskQueue.push(arguments); - return taskChannel.port2.postMessage(null); - }; - } else { - return function() { - taskQueue.push(arguments); - return setTimeout(execTask, 0); - }; - } - })(); - - $.globalEval = function(code) { - var script; - script = $.el('script', { - textContent: code - }); - $.add(d.head || doc, script); - return $.rm(script); - }; - - $.global = function(fn) { - if (doc) { - return $.globalEval("(" + fn + ")();"); - } else { - return fn(); - } - }; - - $.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; - }; - - $.engine = (function() { - if (/Edge\//.test(navigator.userAgent)) { - return 'edge'; - } - if (/Chrome\//.test(navigator.userAgent)) { - return 'blink'; - } - if (/WebKit\//.test(navigator.userAgent)) { - return 'webkit'; - } - if (/Gecko\/|Goanna/.test(navigator.userAgent)) { - return 'gecko'; - } - })(); - - try { - localStorage.getItem('x'); - $.hasStorage = true; - } catch (_error) { - $.hasStorage = false; - } - - $.item = function(key, val) { - var item; - item = {}; - item[key] = val; - return item; - }; - - $.syncing = {}; - - if (typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null) { - $.getValue = GM_getValue; - $.listValues = function() { - return GM_listValues(); - }; - } else if ($.hasStorage) { - $.getValue = function(key) { - return localStorage[key]; - }; - $.listValues = function() { - var key, results; - results = []; - for (key in localStorage) { - if (key.slice(0, g.NAMESPACE.length) === g.NAMESPACE) { - results.push(key); - } - } - return results; - }; - } else { - $.getValue = function() {}; - $.listValues = function() { - return []; - }; - } - - if (typeof GM_addValueChangeListener !== "undefined" && GM_addValueChangeListener !== null) { - $.setValue = GM_setValue; - $.deleteValue = GM_deleteValue; - } else if (typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null) { - $.oldValue = {}; - $.setValue = function(key, val) { - GM_setValue(key, val); - if (key in $.syncing) { - $.oldValue[key] = val; - if ($.hasStorage) { - return localStorage[key] = val; - } - } - }; - $.deleteValue = function(key) { - GM_deleteValue(key); - if (key in $.syncing) { - delete $.oldValue[key]; - if ($.hasStorage) { - return localStorage.removeItem(key); - } - } - }; - if (!$.hasStorage) { - $.cantSync = true; - } - } else if ($.hasStorage) { - $.oldValue = {}; - $.setValue = function(key, val) { - if (key in $.syncing) { - $.oldValue[key] = val; - } - return localStorage[key] = val; - }; - $.deleteValue = function(key) { - if (key in $.syncing) { - delete $.oldValue[key]; - } - return localStorage.removeItem(key); - }; - } else { - $.setValue = function() {}; - $.deleteValue = function() {}; - $.cantSync = $.cantSet = true; - } - - if (typeof GM_addValueChangeListener !== "undefined" && GM_addValueChangeListener !== null) { - $.sync = function(key, cb) { - return $.syncing[key] = GM_addValueChangeListener(g.NAMESPACE + key, function(key2, oldValue, newValue, remote) { - if (remote) { - if (newValue !== void 0) { - newValue = JSON.parse(newValue); - } - return cb(newValue, key); - } - }); - }; - $.forceSync = function() {}; - } else if ((typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null) || $.hasStorage) { - $.sync = function(key, cb) { - key = g.NAMESPACE + key; - $.syncing[key] = cb; - return $.oldValue[key] = $.getValue(key); - }; - (function() { - var onChange; - onChange = function(arg) { - var cb, key, newValue; - key = arg.key, newValue = arg.newValue; - if (!(cb = $.syncing[key])) { - return; - } - if (newValue != null) { - if (newValue === $.oldValue[key]) { - return; - } - $.oldValue[key] = newValue; - return cb(JSON.parse(newValue), key.slice(g.NAMESPACE.length)); - } else { - if ($.oldValue[key] == null) { - return; - } - delete $.oldValue[key]; - return cb(void 0, key.slice(g.NAMESPACE.length)); - } - }; - $.on(window, 'storage', onChange); - return $.forceSync = function(key) { - key = g.NAMESPACE + key; - return onChange({ - key: key, - newValue: $.getValue(key) - }); - }; - })(); - } else { - $.sync = function() {}; - $.forceSync = function() {}; - } - - $["delete"] = function(keys) { - var k, key, len1; - if (!(keys instanceof Array)) { - keys = [keys]; - } - for (k = 0, len1 = keys.length; k < len1; k++) { - key = keys[k]; - $.deleteValue(g.NAMESPACE + 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 = $.getValue(g.NAMESPACE + key)) { - items[key] = JSON.parse(val); - } - } - return cb(items); - }); - }; - - $.set = function(keys, val, cb) { - var key, value; - if (typeof keys === 'string') { - $.setValue(g.NAMESPACE + keys, JSON.stringify(val)); - } else { - for (key in keys) { - value = keys[key]; - $.setValue(g.NAMESPACE + key, JSON.stringify(value)); - } - cb = val; - } - return typeof cb === "function" ? cb() : void 0; - }; - - $.clear = function(cb) { - var id; - $["delete"](Object.keys(Conf)); - $["delete"](['previousversion', 'AutoWatch', 'QR Size', 'captchas', 'QR.persona', 'hiddenPSA']); - $["delete"]((function() { - var k, len1, ref, results; - ref = ['embedding', 'updater', 'thread-stats', 'thread-watcher', 'qr']; - results = []; - for (k = 0, len1 = ref.length; k < len1; k++) { - id = ref[k]; - results.push(id + ".position"); - } - return results; - })()); - try { - $["delete"]($.listValues().map(function(key) { - return key.replace(g.NAMESPACE, ''); - })); - } catch (_error) {} - 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(type1) { - this.type = type1; - 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, keys) { - var err, errors, k, len1, name, ref; - if (keys == null) { - keys = this.keys; - } - for (k = 0, len1 = keys.length; k < len1; k++) { - name = keys[k]; - try { - if ((ref = this[name]) != null) { - ref.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(ID1) { - this.ID = ID1; - 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(ID1, board1) { - this.ID = ID1; - this.board = board1; - 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; - this.board.threads.push(this.ID, this); - g.threads.push(this.fullID, 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, thread1) { - this.thread = thread1; - 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, thread1, board1) { - var capcode, clone, date, email, flag, info, k, len1, name, post, ref, subject, tripcode, uniqueID; - this.thread = thread1; - this.board = board1; - this.ID = +root.id.slice(2); - this.fullID = this.board + "." + this.ID; - this.context = this; - root.dataset.fullID = this.fullID; - 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: [] - }; - if ($.engine === 'edge') { - Object.defineProperty(this.nodes, 'backlinks', { - configurable: true, - enumerable: true, - get: function() { - return info.getElementsByClassName('backlink'); - } - }); - } else { - this.nodes.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 || void 0; - } - 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(); - 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 (k = 0, len1 = ref.length; k < len1; k++) { - clone = ref[k]; - clone.origin = this; - } - } - this.board.posts.push(this.ID, this); - this.thread.posts.push(this.ID, this); - g.posts.push(this.fullID, this); - } - - Post.prototype.parseComment = function() { - var abbr, bq, commentDisplay, k, len1, len2, node, q, ref, spoilers; - this.nodes.comment.normalize(); - bq = this.nodes.comment.cloneNode(true); - ref = $$('.abbr + br, .exif, b, .fortune', bq); - for (k = 0, len1 = ref.length; k < len1; k++) { - node = ref[k]; - $.rm(node); - } - if (abbr = $('.abbr', bq)) { - $.rm(abbr); - } - this.info.comment = this.nodesToText(bq); - if (abbr) { - this.info.comment = this.info.comment.replace(/\n\n$/, ''); - } - commentDisplay = this.info.comment; - if (!(Conf['Remove Spoilers'] || Conf['Reveal Spoilers'])) { - spoilers = $$('s', bq); - if (spoilers.length) { - for (q = 0, len2 = spoilers.length; q < len2; q++) { - node = spoilers[q]; - $.replace(node, $.tn('[spoiler]')); - } - commentDisplay = this.nodesToText(bq); - } - } - return this.info.commentDisplay = commentDisplay.trim().replace(/\s+$/gm, ''); - }; - - 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; - }; - - Post.prototype.parseQuotes = function() { - var k, len1, quotelink, ref; - this.quotes = []; - ref = $$(':not(pre) > .quotelink', this.nodes.comment); - for (k = 0, len1 = ref.length; k < len1; k++) { - quotelink = ref[k]; - this.parseQuote(quotelink); - } - }; - - Post.prototype.parseQuote = function(quotelink) { - var fullID, match; - match = quotelink.href.match(/^https?:\/\/boards\.4chan\.org\/+([^\/]+)\/+(?:res|thread)\/+\d+(?:\/[^#]*)?#p(\d+)$/); - if (!(match || (this.isClone && quotelink.dataset.postID))) { - 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() { - var fileEl, fileText, info, link, m, ref, ref1, ref2, size, thumb, unit; - if (!(fileEl = $('.file', this.nodes.post))) { - return; - } - if (!(link = $('.fileText > a, .fileText-original > a', fileEl))) { - return; - } - if (!(info = (ref = link.nextSibling) != null ? ref.textContent.match(/\(([\d.]+ [KMG]?B).*\)/) : void 0)) { - return; - } - fileText = fileEl.firstElementChild; - this.file = { - text: fileText, - link: link, - url: link.href, - name: fileText.title || link.title || link.textContent, - size: info[1], - isImage: /(jpg|png|gif)$/i.test(link.href), - isVideo: /webm$/i.test(link.href), - dimensions: (ref1 = info[0].match(/\d+x\d+/)) != null ? ref1[0] : void 0, - tag: (ref2 = info[0].match(/,[^,]*, ([a-z]+)\)/i)) != null ? ref2[1] : void 0 - }; - 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; - if ((thumb = $('.fileThumb > [data-md5]', fileEl))) { - return $.extend(this.file, { - thumb: thumb, - thumbURL: (m = link.href.match(/\d+(?=\.\w+$)/)) ? location.protocol + "//i.4cdn.org/" + this.board + "/" + m[0] + "s.jpg" : void 0, - MD5: thumb.dataset.md5, - isSpoiler: $.hasClass(thumb.parentNode, 'imgspoiler') - }); - } - }; - - Post.prototype.kill = function(file) { - var clone, k, len1, len2, q, quotelink, ref, ref1, strong; - 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 (k = 0, len1 = ref.length; k < len1; k++) { - clone = ref[k]; - clone.kill(file); - } - if (file) { - return; - } - ref1 = Get.allQuotelinksLinkingTo(this); - for (q = 0, len2 = ref1.length; q < len2; q++) { - quotelink = ref1[q]; - if (!(!$.hasClass(quotelink, 'deadlink'))) { - continue; - } - quotelink.textContent = quotelink.textContent + '\u00A0(Dead)'; - $.addClass(quotelink, 'deadlink'); - } - }; - - Post.prototype.resurrect = function() { - var clone, k, len1, len2, q, quotelink, ref, ref1, strong; - this.isDead = false; - $.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 (k = 0, len1 = ref.length; k < len1; k++) { - clone = ref[k]; - clone.resurrect(); - } - ref1 = Get.allQuotelinksLinkingTo(this); - for (q = 0, len2 = ref1.length; q < len2; q++) { - quotelink = ref1[q]; - if (!($.hasClass(quotelink, 'deadlink'))) { - continue; - } - quotelink.textContent = quotelink.textContent.replace('\u00A0(Dead)', ''); - $.rmClass(quotelink, 'deadlink'); - } - }; - - Post.prototype.collect = function() { - 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, k, len1, ref; - this.clones.splice(index, 1); - ref = this.clones.slice(index); - for (k = 0, len1 = ref.length; k < len1; k++) { - clone = ref[k]; - clone.nodes.root.dataset.clone = index++; - } - }; - - return Post; - - })(); - - Clone = (function(superClass) { - extend(Clone, superClass); - - Clone.prototype.isClone = true; - - function Clone(origin1, context1, contractThumb) { - var file, info, inline, inlined, k, key, len1, len2, len3, len4, node, nodes, post, q, ref, ref1, ref2, ref3, ref4, ref5, root, u, v, val; - this.origin = origin1; - this.context = context1; - ref = ['ID', 'fullID', 'board', 'thread', 'info', 'quotes', 'isReply']; - for (k = 0, len1 = ref.length; k < len1; k++) { - key = ref[k]; - this[key] = this.origin[key]; - } - nodes = this.origin.nodes; - root = contractThumb ? this.cloneWithoutVideo(nodes.root) : nodes.root.cloneNode(true); - Clone.prefix || (Clone.prefix = 0); - ref1 = [root].concat(slice.call($$('[id]', root))); - for (q = 0, len2 = ref1.length; q < len2; q++) { - node = ref1[q]; - node.id = Clone.prefix + node.id; - } - Clone.prefix++; - 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: [] - }; - if ($.engine === 'edge') { - Object.defineProperty(this.nodes, 'backlinks', { - configurable: true, - enumerable: true, - get: function() { - return info.getElementsByClassName('backlink'); - } - }); - } else { - this.nodes.backlinks = info.getElementsByClassName('backlink'); - } - ref2 = $$('.inline', post); - for (u = 0, len3 = ref2.length; u < len3; u++) { - inline = ref2[u]; - $.rm(inline); - } - ref3 = $$('.inlined', post); - for (v = 0, len4 = ref3.length; v < len4; v++) { - inlined = ref3[v]; - $.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(); - this.quotes = slice.call(this.origin.quotes); - if (this.origin.file) { - this.file = {}; - ref4 = this.origin.file; - for (key in ref4) { - val = ref4[key]; - this.file[key] = val; - } - file = $('.file', post); - this.file.text = file.firstElementChild; - this.file.link = $('.fileText > a, .fileText-original', file); - 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 ((ref5 = this.file.thumb) != null ? ref5.dataset.src : void 0) { - this.file.thumb.src = this.file.thumb.dataset.src; - this.file.thumb.removeAttribute('data-src'); - } - if (this.file.thumb && contractThumb) { - ImageExpand.contract(this); - } - } - if (this.origin.isDead) { - this.isDead = true; - } - root.dataset.clone = this.origin.clones.push(this) - 1; - } - - Clone.prototype.cloneWithoutVideo = function(node) { - var child, clone, k, len1, 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 (k = 0, len1 = ref.length; k < len1; k++) { - child = ref[k]; - $.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(key1, sync, dontClean) { - var init; - this.key = key1; - this.onSync = bind(this.onSync, this); - this.data = Conf[this.key]; - $.sync(this.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(cb) { - return $.set(this.key, this.data, cb); - }; - - DataBoard.prototype["delete"] = function(arg) { - var boardID, postID, ref, threadID; - 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, cb) { - var base1, base2, base3, boardID, postID, threadID, val; - boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, val = arg.val; - $.forceSync(this.key); - if (postID !== void 0) { - ((base1 = ((base2 = this.data.boards)[boardID] || (base2[boardID] = {})))[threadID] || (base1[threadID] = {}))[postID] = val; - } else if (threadID !== void 0) { - ((base3 = this.data.boards)[boardID] || (base3[boardID] = {}))[threadID] = val; - } else { - this.data.boards[boardID] = val; - } - return this.save(cb); - }; - - DataBoard.prototype.get = function(arg) { - var ID, board, boardID, defaultValue, k, len1, postID, thread, threadID, val; - boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, defaultValue = arg.defaultValue; - if (board = this.data.boards[boardID]) { - if (threadID == null) { - if (postID != null) { - for (thread = k = 0, len1 = board.length; k < len1; thread = ++k) { - ID = board[thread]; - if (postID in thread) { - val = thread[postID]; - break; - } - } - } else { - val = board; - } - } else if (thread = board[threadID]) { - val = postID != null ? thread[postID] : thread; - } - } - return val || defaultValue; - }; - - DataBoard.prototype.forceSync = function() { - return $.forceSync(this.key); - }; - - DataBoard.prototype.clean = function() { - var boardID, now, ref, val; - $.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) { - this.ajaxClean(boardID); - } - } - }; - - DataBoard.prototype.ajaxClean = function(boardID) { - return $.cache("//a.4cdn.org/" + boardID + "/threads.json", (function(_this) { - return function(e1) { - var ref; - if ((ref = e1.target.status) !== 200 && ref !== 404) { - return; - } - return $.cache("//a.4cdn.org/" + boardID + "/archive.json", function(e2) { - var ref1; - if ((ref1 = e2.target.status) !== 200 && ref1 !== 404) { - return; - } - return _this.ajaxCleanParse(boardID, e1.target.response, e2.target.response); - }); - }; - })(this)); - }; - - DataBoard.prototype.ajaxCleanParse = function(boardID, response1, response2) { - var ID, board, k, len1, len2, len3, page, q, ref, thread, threads, u; - if (!(board = this.data.boards[boardID])) { - return; - } - threads = {}; - if (response1) { - for (k = 0, len1 = response1.length; k < len1; k++) { - page = response1[k]; - ref = page.threads; - for (q = 0, len2 = ref.length; q < len2; q++) { - thread = ref[q]; - ID = thread.no; - if (ID in board) { - threads[ID] = board[ID]; - } - } - } - } - if (response2) { - for (u = 0, len3 = response2.length; u < len3; u++) { - ID = response2[u]; - if (ID in board) { - threads[ID] = board[ID]; - } - } - } - this.data.boards[boardID] = threads; - this.deleteIfEmpty({ - boardID: boardID - }); - return this.save(); - }; - - 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, timeout1, onclose) { - this.timeout = timeout1; - this.onclose = onclose; - this.close = bind(this.close, this); - this.add = bind(this.add, this); - this.el = $.el('div', { - innerHTML: "
      " - }); - this.el.style.opacity = 0; - this.setType(type); - $.on(this.el.firstElementChild, 'click', this.close); - if (typeof content === 'string') { - content = $.tn(content); - } - $.add(this.el.lastElementChild, content); - $.ready(this.add); - } - - 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, k, len1; - this.length = 0; - if (items) { - for (k = 0, len1 = items.length; k < len1; k++) { - item = items[k]; - 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 k, key, len1, ref; - ref = slice.call(this.keys); - for (k = 0, len1 = ref.length; k < len1; k++) { - key = ref[k]; - 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(target1, origin1, cb1) { - this.target = target1; - this.origin = origin1; - this.cb = cb1 != null ? cb1 : {}; - this.onMessage = bind(this.onMessage, this); - this.send = bind(this.send, this); - $.on(window, 'message', this.onMessage); - } - - Connection.prototype.targetWindow = function() { - if (this.target instanceof window.HTMLIFrameElement) { - return this.target.contentWindow; - } else { - return this.target; - } - }; - - Connection.prototype.send = function(data) { - return this.targetWindow().postMessage("" + g.NAMESPACE + (JSON.stringify(data)), this.origin); - }; - - Connection.prototype.onMessage = function(e) { - var base1, data, type, value; - if (!(e.source === this.targetWindow() && 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 (base1 = this.cb)[type] === "function") { - base1[type](value); - } - } - }; - - return Connection; - - })(); - - Fetcher = (function() { - function Fetcher(boardID1, threadID1, postID1, root1, quoter1) { - var post; - this.boardID = boardID1; - this.threadID = threadID1; - this.postID = postID1; - this.root = root1; - this.quoter = quoter1; - 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(_this) { - return function(e, isCached) { - return _this.fetchedPost(e.target, isCached); - }; - })(this)); - } else { - this.archivedPost(); - } - } - - Fetcher.prototype.insert = function(post) { - var boardID, clone, k, len1, nodes, postID, quote, ref, ref1; - if (!this.root.parentNode) { - return; - } - clone = post.addClone(this.quoter.context, $.hasClass(this.root, 'dialog')); - Main.callbackNodes(Clone, [clone]); - nodes = clone.nodes; - $.rmAll(nodes.root); - $.add(nodes.root, nodes.post); - ref = clone.nodes.quotelinks.concat(slice.call(clone.nodes.backlinks)); - for (k = 0, len1 = ref.length; k < len1; k++) { - quote = ref[k]; - ref1 = Get.postDataFromLink(quote), boardID = ref1.boardID, postID = ref1.postID; - if (postID === this.quoter.ID && boardID === this.quoter.board.ID) { - $.addClass(quote, 'forwardlink'); - } - } - $.rmAll(this.root); - $.add(this.root, nodes.root); - return $.event('PostsInserted'); - }; - - Fetcher.prototype.fetchedPost = function(req, isCached) { - var api, board, k, len1, post, posts, status, thread; - 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 (k = 0, len1 = posts.length; k < len1; k++) { - post = posts[k]; - if (post.no === this.postID) { - break; - } - } - if (post.no !== this.postID) { - if (isCached) { - api = "//a.4cdn.org/" + this.boardID + "/thread/" + this.threadID + ".json"; - $.cleanCache(function(url) { - return url === api; - }); - $.cache(api, (function(_this) { - return function(e) { - return _this.fetchedPost(e.target, false); - }; - })(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 archive, url; - if (!Conf['Resurrect Quotes']) { - return false; - } - if (!(url = Redirect.to('post', { - boardID: this.boardID, - postID: this.postID - }))) { - return false; - } - archive = Redirect.data.post[this.boardID]; - if (/^https:\/\//.test(url) || location.protocol === 'http:') { - $.cache(url, (function(_this) { - return function(e) { - return _this.parseArchivedPost(e.target.response, url, archive); - }; - })(this), { - responseType: 'json', - withCredentials: archive.withCredentials - }); - return true; - } else if (Conf['Exempt 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 (!((ref = media[key]) != null ? ref.match(/^http:\/\//) : void 0)) { - delete media[key]; - } - } - } - } - return _this.parseArchivedPost(response, url, archive); - }; - })(this)); - return true; - } - return false; - }; - - Fetcher.prototype.parseArchivedPost = function(data, url, archive) { - var board, comment, greentext, i, j, key, o, post, ref, ref1, text, text2, thread, val; - if (post = g.posts[this.boardID + "." + this.postID]) { - this.insert(post); - return; - } - if (data == null) { - $.addClass(this.root, 'warning'); - this.root.textContent = "Error fetching Post No." + this.postID + " from " + archive.name + "."; - 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 k, len1, results; - results = []; - for (i = k = 0, len1 = comment.length; k < len1; i = ++k) { - text = comment[i]; - if (i % 2 === 1) { - results.push(this.archiveTags[text]); - } else { - greentext = text[0] === '>'; - text = text.replace(/(\[\/?[a-z]+):lit(\])/g, '$1$2'); - text = (function() { - var len2, q, ref, results1; - ref = text.split(/(>>(?:>\/[a-z\d]+\/)?\d+)/g); - results1 = []; - for (j = q = 0, len2 = ref.length; q < len2; j = ++q) { - text2 = ref[j]; - results1.push({ - innerHTML: (j % 2 ? "" + E(text2) + "" : E(text2)) - }); - } - return results1; - })(); - text = { - innerHTML: (greentext ? "" + E.cat(text) + "" : E.cat(text)) - }; - results.push(text); - } - } - return results; - }).call(this); - comment = { - innerHTML: E.cat(comment) - }; - this.threadID = +data.thread_num; - o = { - postID: this.postID, - threadID: this.threadID, - boardID: this.boardID, - isReply: this.postID !== this.threadID - }; - o.info = { - subject: data.title, - email: data.email, - name: data.name || '', - tripcode: data.trip, - capcode: (function() { - switch (data.capcode) { - case 'M': - return 'Mod'; - case 'A': - return 'Admin'; - case 'D': - return 'Developer'; - } - })(), - uniqueID: data.poster_hash, - flagCode: data.poster_country, - flag: data.poster_country_name, - dateUTC: data.timestamp, - dateText: data.fourchan_date, - commentHTML: comment - }; - if (o.info.capcode) { - delete o.info.uniqueID; - } - if ((ref = data.media) != null ? ref.media_filename : void 0) { - ref1 = data.media; - for (key in ref1) { - val = ref1[key]; - if (/_link$/.test(key) && (val != null ? val[0] : void 0) === '/') { - data.media[key] = url.split('/', 3).join('/') + val; - } - } - o.file = { - name: data.media.media_filename, - url: data.media.media_link || data.media.remote_media_link || (location.protocol + "//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: $.bytesToString(data.media.media_size), - thumbURL: data.media.thumb_link || (location.protocol + "//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 (!/\.pdf$/.test(o.file.url)) { - o.file.dimensions = o.file.width + "x" + o.file.height; - } - if (this.boardID === 'f' && data.media.exif) { - 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); - post.kill(); - if (post.file) { - post.file.thumbURL = o.file.thumbURL; - } - post.isFetchedQuote = true; - Main.callbackNodes(Post, [post]); - return this.insert(post); - }; - - Fetcher.prototype.archiveTags = { - '\n': { - innerHTML: "
      " - }, - '[b]': { - innerHTML: "" - }, - '[/b]': { - innerHTML: "" - }, - '[spoiler]': { - innerHTML: "" - }, - '[/spoiler]': { - innerHTML: "" - }, - '[code]': { - innerHTML: "
      "
      -      },
      -      '[/code]': {
      -        innerHTML: "
      " - }, - '[moot]': { - innerHTML: "
      " - }, - '[/moot]': { - innerHTML: "
      " - }, - '[banned]': { - innerHTML: "" - }, - '[/banned]': { - innerHTML: "" - } - }; - - return Fetcher; - - })(); - - Polyfill = { - init: function() { - return this.toBlob(); - }, - toBlob: function() { - if (HTMLCanvasElement.prototype.toBlob) { - return; - } - HTMLCanvasElement.prototype.toBlob = function(cb, type, encoderOptions) { - var data, i, k, l, ref, ui8a, url; - if (type == null) { - type = 'image/png'; - } - url = this.toDataURL(type, encoderOptions); - data = atob(url.slice(url.indexOf(',') + 1)); - l = data.length; - ui8a = new Uint8Array(l); - for (i = k = 0, ref = l; k < ref; i = k += 1) { - ui8a[i] = data.charCodeAt(i); - } - return cb(new Blob([ui8a], { - type: type - })); - }; - return $.globalEval("HTMLCanvasElement.prototype.toBlob = (" + HTMLCanvasElement.prototype.toBlob + ");"); - } - }; - - 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: "" - }); - 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 popstate', 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 absbot, oldFooter; - if ((oldFooter = $.id('boardNavDesktopFoot'))) { - return $.replace($('.boardList', oldFooter), Header.bottomBoardList); - } else if ((absbot = $.id('absbot'))) { - $.before(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, k, len1, len2, node, nodes, q, ref, ref1, spacer, span; - Header.boardList = boardList = $.el('span', { - id: 'board-list' - }); - $.extend(boardList, { - innerHTML: "" - }); - btn = $('.hide-board-list-button', boardList); - $.on(btn, 'click', Header.toggleBoardList); - nodes = []; - spacer = function() { - return $.el('span', { - className: 'spacer' - }); - }; - ref = $('#boardNavDesktop > .boardList').childNodes; - for (k = 0, len1 = ref.length; k < len1; k++) { - node = ref[k]; - switch (node.nodeName) { - case '#text': - ref1 = node.nodeValue; - for (q = 0, len2 = ref1.length; q < len2; q++) { - chr = ref1[q]; - 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|(mode|sort|text):"[^"]+"(,"[^"]+")?))*|[^\w@]+/g; - nodes = (function() { - var k, len1, ref, results; - ref = boardnav.match(re); - results = []; - for (k = 0, len1 = ref.length; k < len1; k++) { - t = ref[k]; - results.push(Header.mapCustomNavigation(t, as)); - } - return results; - })(); - $.add(list, nodes); - return $.ready(CatalogLinks.initBoardList); - }, - mapCustomNavigation: function(t, as) { - var a, boardID, href, indexOptions, 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 ''; - }); - indexOptions = []; - t = t.replace(/-(?:mode|sort):"([^"]+)"/g, function(m0, m1) { - indexOptions.push(m1.toLowerCase().replace(/\ /g, '-')); - return ''; - }); - indexOptions = indexOptions.join('/'); - 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 k, len1, ref; - if (boardID === '@') { - return $.el('a', { - href: 'https://twitter.com/4chan', - title: '4chan Twitter', - textContent: '@' - }); - } - for (k = 0, len1 = as.length; k < len1; k++) { - a = as[k]; - 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)/)) { - if (!(boardID === 'f' && m[1] === 'catalog')) { - a.dataset.only = m[1]; - a.href = CatalogLinks[m[1]](boardID); - if (m[1] === 'catalog') { - $.addClass(a, 'catalog'); - } - } else { - return a.firstChild; - } - } - if (Conf['JSON Index'] && indexOptions) { - a.dataset.indexOptions = indexOptions; - if (a.hostname === 'boards.4chan.org' && a.pathname.split('/')[2] === '') { - a.href += (a.hash ? '/' : '#') + indexOptions; - } - } - 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' && boardID !== 'trash') { - 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() { - 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(e) { - var el, hash; - if (e) { - if (e.state) { - return; - } - if (!history.state) { - history.replaceState({}, ''); - } - } - if ((hash = location.hash.slice(1))) { - ReplyPruning.showIfHidden(hash); - if ((el = $.id(hash))) { - return $.queueTask(function() { - return Header.scrollTo(el); - }); - } - } - }, - scrollTo: function(root, down, needed) { - var height, x; - if (!root.offsetParent) { - return; - } - if (down) { - x = Header.getBottomOf(root); - if (Conf['Fixed Header'] && 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['Fixed Header'] && 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['Fixed Header'] && 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, ref, type; - 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: "4chan X needs your permission to show desktop notifications. [FAQ]
      or " - }); - 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, - changed: {}, - init: function() { - var anchorEntry, input, k, label, len1, len2, name, pinEntry, q, ref, ref1, ref2, ref3, ref4, ref5, ref6, refNavEntry, repliesEntry, select, sortEntry; - if (g.BOARD.ID === 'f' || !Conf['JSON Index'] || g.VIEW !== 'index') { - return; - } - CatalogThread.callbacks.push({ - name: 'Catalog Features', - cb: this.catalogNode - }); - this.search = ((ref = history.state) != null ? ref.searched : void 0) || ''; - if ((ref1 = history.state) != null ? ref1.mode : void 0) { - Conf['Index Mode'] = (ref2 = history.state) != null ? ref2.mode : void 0; - } - this.currentSort = (ref3 = history.state) != null ? ref3.sort : void 0; - this.currentSort || (this.currentSort = typeof Conf['Index Sort'] === 'object' ? Conf['Index Sort'][g.BOARD.ID] || 'bump' : Conf['Index Sort']); - this.currentPage = this.getCurrentPage(); - this.processHash(); - $.addClass(doc, 'index-loading', (Conf['Index Mode'].replace(/\ /g, '-')) + "-mode"); - $.on(window, 'popstate', this.cb.popstate); - $.on(d, 'scroll', Index.scroll); - 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') - }; - sortEntry = { - el: UI.checkbox('Per-Board Sort Type', 'Per-board sort type', typeof Conf['Index Sort'] === 'object') - }; - 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') - }; - sortEntry.el.title = 'Set the sorting order of each board independently.'; - 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 (k = 0, len1 = ref4.length; k < len1; k++) { - label = ref4[k]; - 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.resort); - } - } - $.on(sortEntry.el.firstChild, 'change', this.cb.perBoardSort); - Header.menu.addEntry({ - el: $.el('span', { - textContent: 'Index Navigation' - }), - order: 100, - subEntries: [repliesEntry, sortEntry, pinEntry, anchorEntry, refNavEntry] - }); - this.navLinks = $.el('div', { - className: 'navLinks json-index' - }); - $.extend(this.navLinks, { - innerHTML: "Index Catalog Archive Bottom ×" - }); - $('.cataloglink a', this.navLinks).href = CatalogLinks.catalog(); - if ((ref5 = g.BOARD.ID) === 'b' || ref5 === 'trash') { - $('.archlistlink', this.navLinks).hidden = true; - } - $.on($('#index-last-refresh a', this.navLinks), 'click', this.cb.refreshFront); - this.searchInput = $('#index-search', this.navLinks); - this.setupSearch(); - $.on(this.searchInput, 'input', this.onSearchInput); - $.on($('#index-search-clear', this.navLinks), 'click', this.clearSearch); - this.hideLabel = $('#hidden-label', this.navLinks); - $.on($('#hidden-toggle a', this.navLinks), 'click', this.cb.toggleHiddenThreads); - this.selectMode = $('#index-mode', this.navLinks); - this.selectSort = $('#index-sort', this.navLinks); - this.selectSize = $('#index-size', this.navLinks); - $.on(this.selectMode, 'change', this.cb.mode); - $.on(this.selectSort, 'change', this.cb.sort); - $.on(this.selectSize, 'change', $.cb.value); - $.on(this.selectSize, 'change', this.cb.size); - ref6 = [this.selectMode, this.selectSize]; - for (q = 0, len2 = ref6.length; q < len2; q++) { - select = ref6[q]; - select.value = Conf[select.name]; - } - this.selectSort.value = Index.currentSort; - this.root = $.el('div', { - className: 'board json-index' - }); - this.cb.size(); - this.pagelist = $.el('div', { - className: 'pagelist json-index' - }); - $.extend(this.pagelist, { - innerHTML: "
      " - }); - $('.cataloglink a', this.pagelist).href = CatalogLinks.catalog(); - $.on(this.pagelist, 'click', this.cb.pageNav); - this.update(true); - $.onExists(doc, 'title + *', function() { - return d.title = d.title.replace(/\ -\ Page\ \d+/, ''); - }); - $.onExists(doc, '.board > .thread > .postContainer, .board + *', function() { - var board, el, len3, len4, ref7, ref8, threadRoot, topNavPos, u, v; - Index.hat = $('.board > .thread > img:first-child'); - if (Index.hat) { - if (Index.nodes) { - ref7 = Index.nodes; - for (u = 0, len3 = ref7.length; u < len3; u++) { - threadRoot = ref7[u]; - $.prepend(threadRoot, Index.hat.cloneNode(false)); - } - } - $.addClass(doc, 'hats-enabled'); - $.addStyle(".catalog-thread::after {background-image: url(" + Index.hat.src + ");}"); - } - board = $('.board'); - $.replace(board, Index.root); - $.event('PostsInserted'); - try { - d.implementation.createDocument(null, null, null).appendChild(board); - } catch (_error) {} - ref8 = $$('.navLinks'); - for (v = 0, len4 = ref8.length; v < len4; v++) { - el = ref8[v]; - $.rm(el); - } - $.rm($.id('ctrl-top')); - topNavPos = $.id('delform').previousElementSibling; - $.before(topNavPos, $.el('hr')); - return $.before(topNavPos, Index.navLinks); - }); - return Main.ready(function() { - var pagelist; - if ((pagelist = $('.pagelist'))) { - $.replace(pagelist, Index.pagelist); - } - return $.rmClass(doc, 'index-loading'); - }); - }, - scroll: function() { - var nodes, pageNum; - if (Index.req || !Index.liveThreadData || Conf['Index Mode'] !== 'infinite' || (window.scrollY <= doc.scrollHeight - (300 + window.innerHeight))) { - return; - } - if (Index.pageNum == null) { - Index.pageNum = Index.currentPage; - } - 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 Index'] || !Conf['Menu'] || !Conf['Thread Hiding Link'] || g.BOARD.ID === 'f') { - return; - } - return Menu.menu.addEntry({ - el: $.el('a', { - href: 'javascript:;', - className: 'has-shortcut-text' - }, { - innerHTML: "Shift+click" - }), - order: 20, - open: function(arg) { - var thread; - thread = arg.thread; - if (Conf['Index Mode'] !== 'catalog') { - return false; - } - this.el.firstElementChild.textContent = thread.isHidden ? 'Unhide' : 'Hide'; - 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, k, len1, type, types; - types = slice.call(Index.selectSort.options).filter(function(option) { - return !option.disabled; - }); - for (i = k = 0, len1 = types.length; k < len1; i = ++k) { - 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() { - Index.pushState({ - mode: this.value - }); - return Index.pageLoad(false); - }, - sort: function() { - Index.pushState({ - sort: this.value - }); - return Index.pageLoad(false); - }, - resort: function() { - Index.sort(); - return Index.buildIndex(); - }, - perBoardSort: function() { - Conf['Index Sort'] = this.checked ? {} : ''; - return Index.saveSort(); - }, - 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, nCommands, page, ref, searched, sort; - if (e != null ? e.state : void 0) { - ref = e.state, searched = ref.searched, mode = ref.mode, sort = ref.sort; - page = Index.getCurrentPage(); - Index.setState({ - search: searched, - mode: mode, - sort: sort, - page: page - }); - return Index.pageLoad(false); - } else { - nCommands = Index.processHash(); - if (Conf['Refreshed Navigation'] && nCommands) { - return Index.update(); - } else { - return Index.pageLoad(); - } - } - }, - 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); - }, - refreshFront: function() { - Index.pushState({ - page: 1 - }); - return Index.update(); - } - }, - scrollToIndex: function() { - return Header.scrollToIfNeeded((Index.navLinks.getBoundingClientRect().height ? Index.navLinks : Index.root)); - }, - getCurrentPage: function() { - return +window.location.pathname.split(/\/+/)[2] || 1; - }, - userPageNav: function(page) { - Index.pushState({ - page: page - }); - if (Conf['Refreshed Navigation']) { - return Index.update(); - } else { - return Index.pageLoad(); - } - }, - hashCommands: { - mode: { - 'paged': 'paged', - 'infinite-scrolling': 'infinite', - 'infinite': 'infinite', - 'all-threads': 'all pages', - 'all-pages': 'all pages', - 'catalog': 'catalog' - }, - sort: { - 'bump-order': 'bump', - 'last-reply': 'lastreply', - 'last-long-reply': 'lastlong', - 'creation-date': 'birth', - 'reply-count': 'replycount', - 'file-count': 'filecount' - } - }, - processHash: function() { - var command, commands, hash, k, leftover, len1, mode, ref, sort, state; - hash = ((ref = location.href.match(/#.*/)) != null ? ref[0] : void 0) || ''; - state = { - replace: true - }; - commands = hash.slice(1).split('/'); - leftover = []; - for (k = 0, len1 = commands.length; k < len1; k++) { - command = commands[k]; - if ((mode = Index.hashCommands.mode[command])) { - state.mode = mode; - } else if (command === 'index') { - state.mode = Conf['Previous Index Mode']; - state.page = 1; - } else if ((sort = Index.hashCommands.sort[command])) { - state.sort = sort; - } else if (/^s=/.test(command)) { - state.search = decodeURIComponent(command.slice(2)).replace(/\+/g, ' ').trim(); - } else { - leftover.push(command); - } - } - hash = leftover.join('/'); - if (hash) { - state.hash = "#" + hash; - } - Index.pushState(state); - return commands.length - leftover.length; - }, - pushState: function(state) { - var hash, pageBeforeSearch, pathname, ref, replace, search; - search = state.search, hash = state.hash, replace = state.replace; - pageBeforeSearch = (ref = history.state) != null ? ref.oldpage : void 0; - if ((search != null) && search !== Index.search) { - state.page = search ? 1 : pageBeforeSearch || 1; - if (!search) { - pageBeforeSearch = void 0; - } else if (!Index.search) { - pageBeforeSearch = Index.currentPage; - } - } - Index.setState(state); - pathname = Index.currentPage === 1 ? "/" + g.BOARD + "/" : "/" + g.BOARD + "/" + Index.currentPage; - hash || (hash = ''); - return history[replace ? 'replaceState' : 'pushState']({ - mode: Conf['Index Mode'], - sort: Index.currentSort, - searched: Index.search, - oldpage: pageBeforeSearch - }, '', location.protocol + "//" + location.host + pathname + hash); - }, - setState: function(arg) { - var hash, mode, page, ref, search, sort; - search = arg.search, mode = arg.mode, sort = arg.sort, page = arg.page, hash = arg.hash; - if ((search != null) && search !== Index.search) { - Index.changed.search = true; - Index.search = search; - } - if ((mode != null) && mode !== Conf['Index Mode']) { - Index.changed.mode = true; - Conf['Index Mode'] = mode; - $.set('Index Mode', mode); - if (!(mode === 'catalog' || Conf['Previous Index Mode'] === mode)) { - Conf['Previous Index Mode'] = mode; - $.set('Previous Index Mode', mode); - } - } - if ((sort != null) && sort !== Index.currentSort) { - Index.changed.sort = true; - Index.currentSort = sort; - Index.saveSort(); - } - if ((ref = Conf['Index Mode']) === 'all pages' || ref === 'catalog') { - page = 1; - } - if ((page != null) && page !== Index.currentPage) { - Index.changed.page = true; - Index.currentPage = page; - } - if (hash != null) { - return Index.changed.hash = true; - } - }, - saveSort: function() { - if (typeof Conf['Index Sort'] === 'object') { - Conf['Index Sort'][g.BOARD.ID] = Index.currentSort; - } else { - Conf['Index Sort'] = Index.currentSort; - } - return $.set('Index Sort', Conf['Index Sort']); - }, - pageLoad: function(scroll) { - var hash, mode, page, ref, search, sort, threads; - if (scroll == null) { - scroll = true; - } - if (!Index.liveThreadData) { - return; - } - ref = Index.changed, threads = ref.threads, search = ref.search, mode = ref.mode, sort = ref.sort, page = ref.page, hash = ref.hash; - if (threads || search || sort) { - Index.sort(); - } - if (threads || search) { - Index.buildPagelist(); - } - if (search) { - Index.setupSearch(); - } - if (mode) { - Index.setupMode(); - } - if (sort) { - Index.setupSort(); - } - if (threads || search || mode || page || sort) { - Index.buildIndex(); - } - if (threads || search || mode || page) { - Index.setPage(); - } - if (scroll && !hash) { - Index.scrollToIndex(); - } - if (hash) { - Header.hashScroll(); - } - return Index.changed = {}; - }, - setupMode: function() { - var k, len1, mode, ref; - ref = ['paged', 'infinite', 'all pages', 'catalog']; - for (k = 0, len1 = ref.length; k < len1; k++) { - mode = ref[k]; - $[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'; - }, - setupSort: function() { - return Index.selectSort.value = Index.currentSort; - }, - 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, k, maxPageNum, nodes, pagesRoot, ref; - pagesRoot = $('.pages', Index.pagelist); - maxPageNum = Index.getMaxPageNum(); - if (pagesRoot.childElementCount !== maxPageNum) { - nodes = []; - for (i = k = 1, ref = maxPageNum; k <= ref; i = k += 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.currentPage; - 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, ref, ref1, thread, threadID; - 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(firstTime) { - var now, ref, ref1; - if ((ref = Index.req) != null) { - ref.abort(); - } - if ((ref1 = Index.notice) != null) { - ref1.close(); - } - if (Conf['Index Refresh Notifications'] && d.readyState !== 'loading') { - Index.notice = new Notice('info', 'Refreshing index...'); - } else { - now = Date.now(); - $.ready(function() { - return Index.nTimeout = setTimeout((function() { - if (Index.req && !Index.notice) { - return Index.notice = new Notice('info', 'Refreshing index...'); - } - }), 3 * $.SECOND - (Date.now() - now)); - }); - } - if (!firstTime && d.readyState !== 'loading' && !$('.board + *')) { - location.reload(); - return; - } - Index.req = $.ajax("//a.4cdn.org/" + g.BOARD + "/catalog.json", { - onabort: Index.load, - onloadend: Index.load - }, { - whenModified: 'Index' - }); - return $.addClass(Index.button, 'fa-spin'); - }, - load: function(e) { - var err, nTimeout, notice, ref, req, timeEl; - $.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; - if (notice != 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); - } else if (req.status === 304) { - Index.pageLoad(); - } - } 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; - } - if (notice) { - if (Conf['Index Refresh Notifications']) { - notice.setType('success'); - notice.el.lastElementChild.textContent = 'Index refreshed!'; - setTimeout(notice.close, $.SECOND); - } else { - notice.close(); - } - } - timeEl = $('#index-last-refresh time', Index.navLinks); - timeEl.dataset.utc = Date.parse(req.getResponseHeader('Last-Modified')); - return RelativeDates.update(timeEl); - }, - parse: function(pages) { - $.cleanCache(function(url) { - return /^\/\/a\.4cdn\.org\//.test(url); - }); - Index.parseThreadList(pages); - Index.buildThreads(); - Index.changed.threads = true; - return Index.pageLoad(); - }, - parseThreadList: function(pages) { - var ref; - Index.pagesNum = pages.length; - Index.threadsNumPerPage = ((ref = pages[0]) != null ? ref.threads.length : void 0) || 1; - 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 ref1; - if (ref1 = thread.ID, indexOf.call(Index.liveThreadIDs, ref1) < 0) { - return thread.collect(); - } - }); - }, - buildThreads: function() { - var err, errors, i, k, len1, posts, ref, thread, threadData, threadRoot, threads; - if (!Index.liveThreadData) { - return; - } - Index.nodes = []; - threads = []; - posts = []; - ref = Index.liveThreadData; - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - 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.OP && !thread.OP.isFetchedQuote)) { - 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, k, lastReplies, len1, len2, node, nodes, post, posts, q, thread, threadRoot; - posts = []; - for (k = 0, len1 = threadRoots.length; k < len1; k++) { - threadRoot = threadRoots[k]; - thread = Get.threadFromRoot(threadRoot); - i = Index.liveThreadIDs.indexOf(thread.ID); - if (!(lastReplies = Index.liveThreadData[i].last_replies)) { - continue; - } - nodes = []; - for (q = 0, len2 = lastReplies.length; q < len2; q++) { - data = lastReplies[q]; - if ((post = thread.posts[data.no]) && !post.isFetchedQuote) { - 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, k, len1, thread, threads; - threads = Index.sortedNodes.map(function(threadRoot) { - return Get.threadFromRoot(threadRoot); - }).filter(function(thread) { - return !thread.isHidden !== Index.showHiddenThreads; - }); - catalogThreads = []; - for (k = 0, len1 = threads.length; k < len1; k++) { - thread = threads[k]; - 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, k, len1, node, ratio, ref, size, thumb, width; - size = Conf['Index Size'] === 'small' ? 150 : 250; - for (k = 0, len1 = nodes.length; k < len1; k++) { - node = nodes[k]; - 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 k, lastlong, len1, liveThreadData, liveThreadIDs, nodes, sortedNodes, sortedThreadIDs, threadID; - liveThreadIDs = Index.liveThreadIDs, liveThreadData = Index.liveThreadData; - if (!liveThreadData) { - return; - } - sortedThreadIDs = (function() { - switch (Index.currentSort) { - case 'lastreply': - return 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; - }); - case 'lastlong': - lastlong = function(thread) { - var i, k, r, ref; - ref = thread.last_replies || []; - for (i = k = ref.length - 1; k >= 0; i = k += -1) { - r = ref[i]; - if (r.com && Build.parseComment(r.com).replace(/[^a-z]/ig, '').length >= 100) { - return r; - } - } - return thread; - }; - return slice.call(liveThreadData).sort(function(a, b) { - return lastlong(b).no - lastlong(a).no; - }).map(function(post) { - return post.no; - }); - case 'bump': - return liveThreadIDs; - case 'birth': - return slice.call(liveThreadIDs).sort(function(a, b) { - return b - a; - }); - case 'replycount': - return slice.call(liveThreadData).sort(function(a, b) { - return b.replies - a.replies; - }).map(function(post) { - return post.no; - }); - case 'filecount': - return slice.call(liveThreadData).sort(function(a, b) { - return b.images - a.images; - }).map(function(post) { - return post.no; - }); - } - })(); - Index.sortedNodes = sortedNodes = []; - nodes = Index.nodes; - for (k = 0, len1 = sortedThreadIDs.length; k < len1; k++) { - threadID = sortedThreadIDs[k]; - 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, k, len1, ref, threadRoot, topNodes; - topNodes = []; - bottomNodes = []; - ref = Index.sortedNodes; - for (k = 0, len1 = ref.length; k < len1; k++) { - threadRoot = ref[k]; - (match(Get.threadFromRoot(threadRoot)) ? topNodes : bottomNodes).push(threadRoot); - } - return Index.sortedNodes = topNodes.concat(bottomNodes); - }, - buildIndex: function() { - var i, nodes, page, post; - if (!Index.liveThreadData) { - return; - } - 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.currentPage) { - Index.currentPage = page; - Index.pushState({ - page: page - }); - Index.setPage(); - } - } - nodes = Index.buildSinglePage(Index.currentPage); - } - delete Index.pageNum; - $.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 k, len1, node, thumb; - for (k = 0, len1 = nodes.length; k < len1; k++) { - node = nodes[k]; - if (thumb = $('img[data-src]', node)) { - thumb.src = thumb.dataset.src; - thumb.removeAttribute('data-src'); - } - $.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() { - 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; - } - Index.pushState({ - search: search, - replace: !!search === !!Index.search - }); - return Index.pageLoad(false); - }, - 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, k, key, keyword, len1, len2, q, ref, ref1, text; - ref = thread.OP, info = ref.info, file = ref.file; - text = []; - ref1 = ['comment', 'subject', 'name', 'tripcode', 'email']; - for (k = 0, len1 = ref1.length; k < len1; k++) { - key = ref1[k]; - if (key in info) { - text.push(info[key]); - } - } - if (file) { - text.push(file.name); - } - text = text.join(' ').toLowerCase(); - for (q = 0, len2 = keywords.length; q < len2; q++) { - keyword = keywords[q]; - 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|#44);/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; - } - }, - spoilerThumb: function(boardID) { - var spoilerRange; - if (spoilerRange = Build.spoilerRange[boardID]) { - return Build.staticPath + "spoiler-" + boardID + (Math.floor(1 + spoilerRange * Math.random())) + ".png"; - } else { - return Build.staticPath + "spoiler.png"; - } - }, - 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; - } - }, - parseJSON: function(data, boardID) { - var o; - o = { - postID: data.no, - threadID: data.resto || data.no, - boardID: boardID, - isReply: !!data.resto, - isSticky: !!data.sticky, - isClosed: !!data.closed, - isArchived: !!data.archived, - fileDeleted: !!data.filedeleted - }; - o.info = { - subject: Build.unescape(data.sub), - email: Build.unescape(data.email), - name: Build.unescape(data.name) || '', - tripcode: data.trip, - uniqueID: data.id, - flagCode: data.country, - flag: Build.unescape(data.country_name), - dateUTC: data.time, - dateText: data.now, - commentHTML: { - innerHTML: data.com || '' - } - }; - if (data.capcode) { - o.info.capcode = data.capcode.replace(/_highlight$/, '').replace(/_/g, ' ').replace(/\b\w/g, function(c) { - return c.toUpperCase(); - }); - o.capcodeHighlight = /_highlight$/.test(data.capcode); - delete o.info.uniqueID; - } - if (data.ext) { - o.file = { - name: (Build.unescape(data.filename)) + data.ext, - url: boardID === 'f' ? location.protocol + "//i.4cdn.org/" + boardID + "/" + (encodeURIComponent(data.filename)) + data.ext : location.protocol + "//i.4cdn.org/" + boardID + "/" + data.tim + data.ext, - height: data.h, - width: data.w, - MD5: data.md5, - size: $.bytesToString(data.fsize), - thumbURL: location.protocol + "//i.4cdn.org/" + boardID + "/" + data.tim + "s.jpg", - theight: data.tn_h, - twidth: data.tn_w, - isSpoiler: !!data.spoiler, - tag: data.tag - }; - if (!/\.pdf$/.test(o.file.url)) { - o.file.dimensions = o.file.width + "x" + o.file.height; - } - } - return o; - }, - parseComment: function(html) { - html = html.replace(//gi, '\n').replace(/\n\nRolled [^<]*<\/b>/i, '').replace(/]*>/g, ''); - return Build.unescape(html); - }, - postFromObject: function(data, boardID, suppressThumb) { - var o; - o = Build.parseJSON(data, boardID); - return Build.post(o, suppressThumb); - }, - post: function(o, suppressThumb) { - var boardID, capcode, capcodeDescription, capcodeLC, capcodeLong, capcodePlural, commentHTML, container, dateText, dateUTC, email, file, fileBlock, fileThumb, fileURL, flag, flagCode, gifIcon, href, k, len1, match, name, postClass, postID, postInfo, postLink, protocol, quote, quoteLink, ref, ref1, shortFilename, staticPath, subject, threadID, tripcode, uniqueID, wholePost; - postID = o.postID, threadID = o.threadID, boardID = o.boardID, file = o.file; - ref = o.info, subject = ref.subject, email = ref.email, name = ref.name, tripcode = ref.tripcode, capcode = ref.capcode, uniqueID = ref.uniqueID, flagCode = ref.flagCode, flag = ref.flag, dateUTC = ref.dateUTC, dateText = ref.dateText, commentHTML = ref.commentHTML; - staticPath = Build.staticPath, gifIcon = Build.gifIcon; - - /* Post Info */ - if (capcode) { - capcodeLC = capcode.toLowerCase(); - if (capcode === 'Founder') { - capcodePlural = 'the Founder'; - capcodeDescription = "4chan's Founder"; - } else { - capcodeLong = { - 'Admin': 'Administrator', - 'Mod': 'Moderator' - }[capcode] || capcode; - capcodePlural = capcodeLong + "s"; - capcodeDescription = "a 4chan " + capcodeLong; - } - } - postLink = Build.postURL(boardID, threadID, postID); - quoteLink = Build.sameThread(boardID, threadID) ? "javascript:quote('" + (+postID) + "');" : "/" + boardID + "/thread/" + threadID + "#q" + postID; - postInfo = { - innerHTML: "
      " + (!o.isReply || boardID === "f" || subject ? "" + E(subject || "") + " " : "") + "" + (email ? "" : "") + "" + E(name) + "" + (tripcode ? " " + E(tripcode) + "" : "") + (capcode ? " ## " + E(capcode) + "" : "") + (email ? "" : "") + (boardID === "f" && !o.isReply || capcode ? "" : " ") + (capcode ? " \""" : "") + (uniqueID && !capcode ? " (ID: " + E(uniqueID) + ")" : "") + (flagCode ? " " : "") + " " + E(dateText) + " No." + E(postID) + "" + (o.isSticky ? " \"Sticky\"" : "") + (o.isClosed && !o.isArchived ? " \"Closed\"" : "") + (o.isArchived ? " \"Archived\"" : "") + (!o.isReply && g.VIEW === "index" ? "   [Reply]" : "") + "
      " - }; - - /* File Info */ - if (file) { - protocol = /^https?:(?=\/\/i\.4cdn\.org\/)/; - fileURL = file.url.replace(protocol, ''); - shortFilename = Build.shortFilename(file.name); - fileThumb = file.isSpoiler ? Build.spoilerThumb(boardID) : file.thumbURL.replace(protocol, ''); - } - fileBlock = { - innerHTML: (file ? "
      " + (boardID === "f" ? "
      File: " + E(file.name) + "-(" + E(file.size) + ", " + E(file.dimensions) + (file.tag ? ", " + E(file.tag) : "") + ")
      " : "
      File: " + (file.isSpoiler ? "Spoiler Image" : E(shortFilename)) + " (" + E(file.size) + ", " + E(file.dimensions || "PDF") + ")
      ") + "
      " : (o.fileDeleted ? "
      \"File
      " : "")) - }; - - /* Whole Post */ - postClass = o.isReply ? 'reply' : 'op'; - wholePost = { - innerHTML: (o.isReply ? "
      >>
      " : "") + "
      " + (o.isReply ? postInfo.innerHTML + fileBlock.innerHTML : fileBlock.innerHTML + postInfo.innerHTML) + "
      " + commentHTML.innerHTML + "
      " - }; - container = $.el('div', { - className: "postContainer " + postClass + "Container", - id: "pc" + postID - }); - $.extend(container, wholePost); - ref1 = $$('.quotelink', container); - for (k = 0, len1 = ref1.length; k < len1; k++) { - quote = ref1[k]; - 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] || '#'; - } else if (/^\d+(#|$)/.test(href) && !(g.VIEW === 'thread' && g.BOARD.ID === boardID)) { - quote.href = "/" + boardID + "/thread/" + href; - } - } - return container; - }, - summaryText: function(status, posts, files) { - var text; - text = ''; - if (status) { - text += status + " "; - } - text += posts + " post" + (posts > 1 ? 's' : ''); - if (+files) { - text += " and " + files + " image repl" + (files > 1 ? 'ies' : 'y'); - } - return text += " " + (status === '-' ? 'shown' : 'omitted') + "."; - }, - summary: function(boardID, threadID, posts, files) { - return $.el('a', { - className: 'summary', - textContent: Build.summaryText('', posts, files), - href: "/" + boardID + "/thread/" + threadID - }); - }, - thread: function(board, data, full) { - var OP, root; - Build.spoilerRange[board] = data.custom_spoiler; - if (OP = board.posts[data.no]) { - if (OP.isFetchedQuote) { - OP = null; - } - } - if (OP && (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, true)]; - 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, k, len1, len2, len3, len4, pageCount, postCount, pp, q, quote, ref, ref1, ref2, ref3, ref4, root, spoilerRange, src, staticPath, u, v; - 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'; - } - postCount = data.replies + 1; - fileCount = data.images + !!data.ext; - pageCount = Math.floor(Index.liveThreadIDs.indexOf(thread.ID) / Index.threadsNumPerPage) + 1; - comment = { - innerHTML: data.com || '' - }; - root = $.el('div', { - className: 'catalog-thread' - }); - $.extend(root, { - innerHTML: "
      " + E(postCount) + " / " + E(fileCount) + " / " + E(pageCount) + "
      " + (thread.OP.info.subject ? "
      " + E(thread.OP.info.subject) + "
      " : "") + "
      " + comment.innerHTML + "
      " - }); - root.dataset.fullID = thread.fullID; - if (thread.OP.highlights) { - $.addClass.apply($, [root].concat(slice.call(thread.OP.highlights))); - } - ref = $$('.quotelink', root.lastElementChild); - for (k = 0, len1 = ref.length; k < len1; k++) { - quote = ref[k]; - href = quote.getAttribute('href'); - if (href[0] === '#') { - quote.href = ("/" + thread.board + "/thread/" + thread.ID) + href; - } - } - ref1 = $$('.abbr, .exif', root.lastElementChild); - for (q = 0, len2 = ref1.length; q < len2; q++) { - exif = ref1[q]; - $.rm(exif); - } - ref2 = $$('.prettyprint', root.lastElementChild); - for (u = 0, len3 = ref2.length; u < len3; u++) { - pp = ref2[u]; - cc = $.el('span', { - className: 'catalog-code' - }); - $.add(cc, slice.call(pp.childNodes)); - $.replace(pp, cc); - } - ref3 = $$('br', root.lastElementChild); - for (v = 0, len4 = ref3.length; v < len4; v++) { - br = ref3[v]; - 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.commentDisplay.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 index, post; - if (root == null) { - return null; - } - post = g.posts[root.dataset.fullID]; - index = root.dataset.clone; - 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)); - }, - postDataFromLink: function(link) { - var boardID, path, postID, ref, threadID; - 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, k, len1, posts, qPost, quote, quotelinks, ref; - quotelinks = []; - posts = g.posts; - fullID = post.fullID; - handleQuotes = function(qPost, type) { - var clone, k, len1, ref; - quotelinks.push.apply(quotelinks, qPost.nodes[type]); - ref = qPost.clones; - for (k = 0, len1 = ref.length; k < len1; k++) { - clone = ref[k]; - 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 (k = 0, len1 = ref.length; k < len1; k++) { - quote = ref[k]; - 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 k, len1, ref, script; - ref = $$('script:not([src])', d.head); - for (k = 0, len1 = ref.length; k < len1; k++) { - script = ref[k]; - 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, k, len1, move, 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 (k = 0, len1 = ref.length; k < len1; k++) { - child = ref[k]; - 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(type1) { - this.type = type1; - 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, k, left, len1, mRect, menu, ref, ref1, ref2, right, style, top; - menu = this.menu = this.makeMenu(); - currentMenu = this; - lastToggledButton = button; - this.entries.sort(function(first, second) { - return first.order - second.order; - }); - ref = this.entries; - for (k = 0, len1 = ref.length; k < len1; k++) { - entry = ref[k]; - this.insertEntry(entry, menu, data); - } - $.addClass(lastToggledButton, 'active'); - $.on(d, 'click CloseMenu', this.close); - if (this.type !== 'gallery') { - $.on(d, 'scroll', 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 err, k, len1, ref, subEntry, submenu; - if (typeof entry.open === 'function') { - try { - if (!entry.open(data)) { - return; - } - } catch (_error) { - err = _error; - Main.handleErrors({ - message: "Error in building the " + this.type + " menu.", - error: err - }); - 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 (k = 0, len1 = ref.length; k < len1; k++) { - subEntry = ref[k]; - 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, k, left, len1, ref, ref1, ref2, right, sRect, style, submenu, top; - while (focused = $.x('parent::*/child::*[contains(@class,"focused")]', entry)) { - $.rmClass(focused, 'focused'); - } - ref = $$('.focused', entry); - for (k = 0, len1 = ref.length; k < len1; k++) { - focused = ref[k]; - $.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, k, len1, subEntries, subEntry; - 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 (k = 0, len1 = subEntries.length; k < len1; k++) { - subEntry = subEntries[k]; - this.parseEntry(subEntry); - } - }; - - return Menu; - - })(); - dragstart = function(e) { - var el, isTouching, o, rect, ref, screenHeight, screenWidth; - 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 k, len1, ref, touch; - ref = e.changedTouches; - for (k = 0, len1 = ref.length; k < len1; k++) { - touch = ref[k]; - 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 k, len1, ref, touch; - ref = e.changedTouches; - for (k = 0, len1 = ref.length; k < len1; k++) { - touch = ref[k]; - 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 cb, el, endEvents, height, latestEvent, noRemove, o, ref, root; - root = arg.root, el = arg.el, latestEvent = arg.latestEvent, endEvents = arg.endEvents, 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); - o.hover(o.latestEvent); - new MutationObserver(function() { - if (el.parentNode) { - return o.hover(o.latestEvent); - } - }).observe(el, { - childList: true - }); - $.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); - }; - hoverstart.padding = 25; - hover = function(e) { - var clientX, clientY, height, left, ref, right, style, threshold, top; - this.latestEvent = e; - height = (this.height || this.el.offsetHeight) + hoverstart.padding; - 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) { - var options, ref, workaround; - if (headers == null) { - headers = {}; - } - url = url.replace(/^((?:https?:)?\/\/(?:\w+\.)?4c(?:ha|d)n\.org)\/adv\//, '$1//adv/'); - workaround = $.engine === 'gecko' && (typeof GM_info !== "undefined" && GM_info !== null) && /^[0-2]\.|^3\.[01](?!\d)/.test(GM_info.version); - workaround || (workaround = /PaleMoon\//.test(navigator.userAgent)); - workaround || (workaround = (typeof GM_info !== "undefined" && GM_info !== null ? (ref = GM_info.script) != null ? ref.includeJSB : void 0 : void 0) != null); - options = { - method: "GET", - url: url, - headers: headers, - onload: function(xhr) { - var contentDisposition, contentType, data, i, r, ref1, ref2; - if (workaround) { - r = xhr.responseText; - data = new Uint8Array(r.length); - i = 0; - while (i < r.length) { - data[i] = r.charCodeAt(i); - i++; - } - } else { - data = new Uint8Array(xhr.response); - } - if (typeof xhr.responseHeaders === 'object') { - contentType = xhr.responseHeaders['Content-Type']; - contentDisposition = xhr.responseHeaders['Content-Disposition']; - } else { - contentType = (ref1 = xhr.responseHeaders.match(/Content-Type:\s*(.*)/i)) != null ? ref1[1] : void 0; - contentDisposition = (ref2 = xhr.responseHeaders.match(/Content-Disposition:\s*(.*)/i)) != null ? ref2[1] : void 0; - } - return cb(data, contentType, contentDisposition); - }, - onerror: function() { - return cb(null); - }, - onabort: function() { - return cb(null); - } - }; - if (workaround) { - options.overrideMimeType = options.mimeType = 'text/plain; charset=x-user-defined'; - } else { - options.responseType = 'arraybuffer'; - } - return GM_xmlhttpRequest(options); - }, - file: function(url, cb) { - return CrossOrigin.binary(url, function(data, contentType, contentDisposition) { - var blob, match, mime, name, ref, ref1, ref2, ref3; - 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, '"'); - } - if ((typeof GM_info !== "undefined" && GM_info !== null ? (ref3 = GM_info.script) != null ? ref3.includeJSB : void 0 : void 0) != null) { - mime = QR.typeFromExtension[name.match(/[^.]*$/)[0].toLowerCase()] || 'application/octet-stream'; - } - 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 k, len1, ref, response; - response = JSON.parse(xhr.responseText); - ref = callbacks[url]; - for (k = 0, len1 = ref.length; k < len1; k++) { - cb = ref[k]; - 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, ref, tripcode; - 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 k, len1, len2, name, q, ref, ref1, trip; - ref = $$('.name'); - for (k = 0, len1 = ref.length; k < len1; k++) { - name = ref[k]; - name.textContent = 'Anonymous'; - } - ref1 = $$('.postertrip'); - for (q = 0, len2 = ref1.length; q < len2; q++) { - trip = ref1[q]; - $.rm(trip); - } - }); - } - }; - - Filter = { - filters: {}, - init: function() { - var boards, err, excludes, filter, hl, k, key, len1, line, op, ref, ref1, ref2, ref3, ref4, ref5, ref6, regexp, stub, top; - 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 (k = 0, len1 = ref1.length; k < len1; k++) { - line = ref1[k]; - 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'; - boards = boards === 'global' ? null : boards.split(','); - if (boards === null) { - excludes = ((ref3 = filter.match(/exclude:([^;]+)/)) != null ? ref3[1].toLowerCase().split(',') : void 0) || null; - } - 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, boards, excludes, 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, boards, excludes, 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, boardID, isReply) { - if (boards && indexOf.call(boards, boardID) < 0) { - return false; - } - if (excludes && indexOf.call(excludes, boardID) >= 0) { - return false; - } - if (isReply && op === 'only' || !isReply && op === 'no') { - return false; - } - if (!test(value)) { - return false; - } - return settings; - }; - }, - node: function() { - var filter, k, key, len1, ref, ref1, result, value; - if (this.isClone) { - return; - } - for (key in Filter.filters) { - if ((value = Filter[key](this)) != null) { - ref = Filter.filters[key]; - for (k = 0, len1 = ref.length; k < len1; k++) { - filter = ref[k]; - if (!(result = filter(value, this.board.ID, this.isReply))) { - continue; - } - if (result.hide && !this.isFetchedQuote) { - 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; - } - } - } - } - }, - isHidden: function(post) { - var filter, k, key, len1, ref, result, value; - for (key in Filter.filters) { - if ((value = Filter[key](post)) != null) { - ref = Filter.filters[key]; - for (k = 0, len1 = ref.length; k < len1; k++) { - filter = ref[k]; - if (result = filter(value, post.boardID, post.isReply)) { - if (result.hide) { - return true; - } - } - } - } - } - return false; - }, - postID: function(post) { - var ref; - return "" + ((ref = post.ID) != null ? ref : post.postID); - }, - name: function(post) { - return post.info.name; - }, - uniqueID: function(post) { - return post.info.uniqueID; - }, - tripcode: function(post) { - return post.info.tripcode; - }, - capcode: function(post) { - return post.info.capcode; - }, - subject: function(post) { - return post.info.subject; - }, - comment: function(post) { - var base1; - return (base1 = post.info).comment != null ? base1.comment : base1.comment = Build.parseComment(post.info.commentHTML.innerHTML); - }, - flag: function(post) { - return post.info.flag; - }, - filename: function(post) { - var ref; - return (ref = post.file) != null ? ref.name : void 0; - }, - dimensions: function(post) { - var ref; - return (ref = post.file) != null ? ref.dimensions : void 0; - }, - filesize: function(post) { - var ref; - return (ref = post.file) != null ? ref.size : void 0; - }, - MD5: function(post) { - var ref; - return (ref = post.file) != null ? ref.MD5 : void 0; - }, - menu: { - init: function() { - var div, entry, k, len1, ref, ref1, type; - 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 (k = 0, len1 = ref1.length; k < len1; k++) { - type = ref1[k]; - 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 != null; - } - }; - }, - 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, ref, replies, thisPost; - if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Menu'] || !Conf['Reply Hiding Link']) { - return; - } - div = $.el('div', { - className: 'hide-reply-link', - textContent: 'Hide' - }); - 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' - }); - 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, k, len1, quotelink, 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 (k = 0, len1 = ref.length; k < len1; k++) { - quotelink = ref[k]; - $.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 k, len1, quotelink, 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 (k = 0, len1 = ref.length; k < len1; k++) { - quotelink = ref[k]; - $.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, k, len1, len2, obj, q, quote, recursive, ref, ref1; - if (this.isClone || this.isFetchedQuote) { - return; - } - ref = this.quotes; - for (k = 0, len1 = ref.length; k < len1; k++) { - quote = ref[k]; - if (obj = Recursive.recursives[quote]) { - ref1 = obj.recursives; - for (i = q = 0, len2 = ref1.length; q < len2; i = ++q) { - recursive = ref1[i]; - recursive.apply(null, [this].concat(slice.call(obj.args[i]))); - } - } - } - }, - add: function() { - var args, base1, name1, obj, post, recursive; - recursive = arguments[0], post = arguments[1], args = 3 <= arguments.length ? slice.call(arguments, 2) : []; - obj = (base1 = Recursive.recursives)[name1 = post.fullID] || (base1[name1] = { - recursives: [], - args: [] - }); - obj.recursives.push(recursive); - return obj.args.push(args); - }, - rm: function(recursive, post) { - var i, k, len1, obj, rec, ref; - if (!(obj = Recursive.recursives[post.fullID])) { - return; - } - ref = obj.recursives; - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - 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 Index']) { - return; - } - this.db = new DataBoard('hiddenThreads'); - if (g.VIEW === 'catalog') { - return this.catalogWatch(); - } - this.catalogSet(g.BOARD); - return Post.callbacks.push({ - name: 'Thread Hiding', - cb: this.node - }); - }, - catalogSet: function(board) { - var hiddenThreads, threadID; - if (!$.hasStorage) { - return; - } - 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() { - if (!$.hasStorage) { - return; - } - this.hiddenThreads = JSON.parse(localStorage.getItem("4chan-hide-t-" + g.BOARD)) || {}; - return Main.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 (this.isReply || this.isClone || this.isFetchedQuote) { - return; - } - if (data = ThreadHiding.db.get({ - boardID: this.board.ID, - threadID: this.ID - })) { - ThreadHiding.hide(this.thread, data.makeStub); - } - if (!Conf['Thread Hiding Buttons']) { - return; - } - return $.prepend(this.nodes.root, ThreadHiding.makeButton(this.thread, 'hide')); - }, - onIndexBuild: function(nodes) { - var k, len1, root, thread; - for (k = 0, len1 = nodes.length; k < len1; k++) { - root = nodes[k]; - 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' - }); - 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 Index'] && 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', - 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 Index'] && 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 Index'] && 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: "" - }); - 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 Index']) { - 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 Index']) { - 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, k, len1, len2, len3, link, markYours, nodes, post, q, quote, ref, ref1, ref2, u; - if (this.isClone || !this.quotes.length || this.isRebuilt) { - return; - } - markYours = Conf['Mark Quotes of You'] && ((ref = QuoteYou.db) != null ? ref.get({ - boardID: this.board.ID, - threadID: this.thread.ID, - postID: this.ID - }) : void 0); - 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)' : '') - }); - ref1 = this.quotes; - for (k = 0, len1 = ref1.length; k < len1; k++) { - quote = ref1[k]; - containers = [QuoteBacklink.getContainer(quote)]; - if ((post = g.posts[quote]) && post.nodes.backlinkContainer) { - ref2 = post.clones; - for (q = 0, len2 = ref2.length; q < len2; q++) { - clone = ref2[q]; - containers.push(clone.nodes.backlinkContainer); - } - } - for (u = 0, len3 = containers.length; u < len3; u++) { - container = containers[u]; - link = a.cloneNode(true); - nodes = container.firstChild ? [$.tn(' '), link] : [link]; - 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 base1; - return (base1 = this.containers)[id] || (base1[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, k, len1, quotelink, ref, ref1, ref2, thread, threadID; - if (this.isClone && this.thread === this.context.thread) { - return; - } - ref = this.context, board = ref.board, thread = ref.thread; - ref1 = this.nodes.quotelinks; - for (k = 0, len1 = ref1.length; k < len1; k++) { - quotelink = ref1[k]; - 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; - } - if (Conf['Comment Expansion']) { - ExpandComment.callbacks.push(this.node); - } - return Post.callbacks.push({ - name: 'Quote Inlining', - cb: this.node - }); - }, - node: function() { - var isClone, k, len1, len2, link, process, q, ref, ref1; - process = QuoteInline.process; - isClone = this.isClone; - ref = this.nodes.quotelinks; - for (k = 0, len1 = ref.length; k < len1; k++) { - link = ref[k]; - process(link, isClone); - } - ref1 = this.nodes.backlinks; - for (q = 0, len2 = ref1.length; q < len2; q++) { - link = ref1[q]; - process(link, isClone); - } - }, - process: function(link, clone) { - if (Conf['Quote Hash Navigation']) { - if (!clone) { - $.after(link, QuoteInline.qiQuote(link, $.hasClass(link, 'filtered'))); - } - } - return $.on(link, 'click', QuoteInline.toggle); - }, - 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, quoter, ref, ref1, threadID; - if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) { - return; - } - ref = Get.postDataFromLink(this), boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; - if (Conf['Inline Cross-thread Quotes Only'] && g.VIEW === 'thread' && ((ref1 = g.posts[boardID + "." + postID]) != null ? ref1.nodes.root.offsetParent : void 0)) { - return; - } - e.preventDefault(); - quoter = Get.postFromNode(this); - context = quoter.context; - if ($.hasClass(this, 'inlined')) { - QuoteInline.rm(this, boardID, threadID, postID, context); - } else { - if ($.x("ancestor::div[@data-full-i-d='" + boardID + "." + postID + "']", this)) { - return; - } - QuoteInline.add(this, boardID, threadID, postID, context, quoter); - } - 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, quoter) { - var inline, isBacklink, post, qroot, root; - isBacklink = $.hasClass(quotelink, 'backlink'); - inline = $.el('div', { - className: 'inline' - }); - inline.dataset.fullID = boardID + "." + postID; - 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, quoter); - 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, ref, root; - isBacklink = $.hasClass(quotelink, 'backlink'); - root = QuoteInline.findRoot(quotelink, isBacklink); - root = $.x("following-sibling::div[@data-full-i-d='" + boardID + "." + 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.context.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 k, len1, link, ref; - ref = this.nodes.quotelinks.concat(slice.call(this.nodes.backlinks)); - for (k = 0, len1 = ref.length; k < len1; k++) { - link = ref[k]; - $.on(link, 'mouseover', QuotePreview.mouseover); - } - }, - mouseover: function(e) { - var boardID, k, len1, origin, post, postID, posts, qp, ref, threadID; - if ($.hasClass(this, 'inlined') || !d.contains(this)) { - 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.postFromNode(this)); - UI.hover({ - root: this, - el: qp, - latestEvent: e, - endEvents: 'mouseout click', - cb: QuotePreview.mouseout - }); - if (Conf['Quote Highlighting'] && (origin = g.posts[boardID + "." + postID])) { - posts = [origin].concat(origin.clones); - posts.pop(); - for (k = 0, len1 = posts.length; k < len1; k++) { - post = posts[k]; - $.addClass(post.nodes.post, 'qphl'); - } - } - }, - mouseout: function() { - var clone, k, len1, post, ref, root; - 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 (k = 0, len1 = ref.length; k < len1; k++) { - post = ref[k]; - $.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, k, len1, postID, quotelink, ref, ref1, ref2; - if (this.isClone) { - return; - } - ref = this.nodes.quotelinks; - for (k = 0, len1 = ref.length; k < len1; k++) { - quotelink = ref[k]; - 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.controls = $.el('label', { - innerHTML: " Threading" - }); - this.threadNewLink = $.el('span', { - className: 'brackets-wrap threadnewlink', - hidden: true - }); - $.extend(this.threadNewLink, { - innerHTML: "Thread New Posts" - }); - this.input = $('input', this.controls); - this.input.checked = Conf['Thread Quotes']; - $.on(this.input, 'change', this.setEnabled); - $.on(this.input, 'change', this.rethread); - $.on(this.threadNewLink.firstElementChild, 'click', this.rethread); - $.on(d, '4chanXInitFinished', (function(_this) { - return function() { - return _this.ready = true; - }; - })(this)); - Header.menu.addEntry(this.entry = { - el: this.controls, - order: 99 - }); - Thread.callbacks.push({ - name: 'Quote Threading', - cb: this.setThread - }); - return Post.callbacks.push({ - name: 'Quote Threading', - cb: this.node - }); - }, - parent: {}, - children: {}, - inserted: {}, - setEnabled: function() { - var other, ref; - other = (ref = ReplyPruning.inputs) != null ? ref.enabled : void 0; - if (this.checked && (other != null ? other.checked : void 0)) { - other.checked = false; - $.event('change', null, other); - } - return $.cb.checked.call(this); - }, - setThread: function() { - QuoteThreading.thread = this; - return $.asap((function() { - return !Conf['Thread Updater'] || $('.navLinksBot > .updatelink'); - }), function() { - var navLinksBot; - if ((navLinksBot = $('.navLinksBot'))) { - return $.add(navLinksBot, [$.tn(' '), QuoteThreading.threadNewLink]); - } - }); - }, - node: function() { - var ancestor, k, lastParent, len1, parent, parents, quote, ref; - if (this.isFetchedQuote || this.isClone || !this.isReply) { - return; - } - parents = new Set(); - lastParent = null; - ref = this.quotes; - for (k = 0, len1 = ref.length; k < len1; k++) { - quote = ref[k]; - 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, k, len1, posts; - posts = [post]; - if (children = QuoteThreading.children[post.fullID]) { - for (k = 0, len1 = children.length; k < len1; k++) { - child = children[k]; - posts = posts.concat(QuoteThreading.descendants(child)); - } - } - return posts; - }, - insert: function(post) { - var base1, child, children, descendants, i, k, len1, name1, next, nodes, order, parent, prev, prev2, q, threadContainer, u, x; - if (!(Conf['Thread Quotes'] && (parent = QuoteThreading.parent[post.fullID]) && !QuoteThreading.inserted[post.fullID])) { - return false; - } - descendants = QuoteThreading.descendants(post); - if (!Unread.posts.has(parent.ID)) { - if ((function() { - var k, len1, x; - for (k = 0, len1 = descendants.length; k < len1; k++) { - x = descendants[k]; - if (Unread.posts.has(x.ID)) { - return true; - } - } - })()) { - QuoteThreading.threadNewLink.hidden = false; - return false; - } - } - order = Unread.order; - children = ((base1 = QuoteThreading.children)[name1 = parent.fullID] || (base1[name1] = [])); - 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 (k = children.length - 1; k >= 0; k += -1) { - child = children[k]; - if (child.ID >= post.ID) { - i--; - } - } - if (i !== children.length) { - next = children[i]; - for (q = 0, len1 = descendants.length; q < len1; q++) { - x = descendants[q]; - 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 (u = descendants.length - 1; u >= 0; u += -1) { - x = descendants[u]; - 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; - if (!QuoteThreading.ready) { - return; - } - thread = QuoteThreading.thread; - posts = thread.posts; - QuoteThreading.threadNewLink.hidden = true; - if (Conf['Thread Quotes']) { - 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 (!Conf['Remember Your Posts']) { - return; - } - this.db = new DataBoard('yourPosts'); - $.sync('Remember Your Posts', function(enabled) { - return Conf['Remember Your Posts'] = enabled; - }); - $.on(d, 'QRPostSuccessful', function(e) { - var boardID, postID, ref, threadID; - $.forceSync('Remember Your Posts'); - if (Conf['Remember Your Posts']) { - ref = e.detail, boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; - return QuoteYou.db.set({ - boardID: boardID, - threadID: threadID, - postID: postID, - val: true - }); - } - }); - if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { - 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 k, len1, quotelink, ref; - if (this.isClone) { - return; - } - if (QuoteYou.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 (k = 0, len1 = ref.length; k < len1; k++) { - quotelink = ref[k]; - if (!(QuoteYou.db.get(Get.postDataFromLink(quotelink)))) { - continue; - } - if (Conf['Mark Quotes of You']) { - $.add(quotelink, $.tn(QuoteYou.text)); - } - $.addClass(quotelink, 'you'); - $.addClass(this.nodes.root, 'quotesYou'); - } - }, - cb: { - seek: function(type) { - var highlight, post, posts, result, str; - if (highlight = $('.highlight')) { - $.rmClass(highlight, 'highlight'); - } - if (!(QuoteYou.lastRead && doc.contains(QuoteYou.lastRead) && $.hasClass(QuoteYou.lastRead, 'quotesYou'))) { - 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(root) { - var post; - post = $('.post', root); - if (!post.getBoundingClientRect().height) { - return false; - } else { - QuoteYou.lastRead = root; - window.location = "#" + post.id; - Header.scrollTo(post); - $.addClass(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, k, len1, ref; - if (this.isClone) { - return; - } - ref = $$('.deadlink', this.nodes.comment); - for (k = 0, len1 = ref.length; k < len1; k++) { - deadlink = ref[k]; - 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', - 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', - 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'], - validExtension: /\.(jpe?g|png|gif|pdf|swf|webm)$/i, - typeFromExtension: { - 'jpg': 'image/jpeg', - 'jpeg': 'image/jpeg', - 'png': 'image/png', - 'gif': 'image/gif', - 'pdf': 'application/pdf', - 'swf': 'application/vnd.adobe.flash.movie', - 'webm': 'video/webm' - }, - extensionFromType: { - 'image/jpeg': 'jpg', - 'image/png': 'png', - 'image/gif': 'gif', - 'application/pdf': 'pdf', - 'application/vnd.adobe.flash.movie': 'swf', - 'application/x-shockwave-flash': 'swf', - 'video/webm': 'webm' - }, - init: function() { - var sc, version; - if (!Conf['Quick Reply']) { - return; - } - this.posts = []; - if (g.VIEW === 'archive') { - return; - } - version = Conf['Use Recaptcha v1'] && Main.jsEnabled ? 'v1' : 'v2'; - this.captcha = Captcha[version]; - $.on(d, '4chanXInitFinished', this.initReady); - 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(); - } - }); - return Header.addShortcut(sc); - } - }, - initReady: function() { - var link, linkBot, navLinksBot, origToggle; - $.off(d, '4chanXInitFinished', this.initReady); - QR.postingIsEnabled = !!$.id('postForm'); - if (!QR.postingIsEnabled) { - return; - } - link = $.el('h1', { - className: "qr-link-container" - }); - $.extend(link, { - innerHTML: "" + (g.VIEW === "thread" ? "Reply to Thread" : "Start a Thread") + "" - }); - 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: "Reply to Thread" - }); - $.on(linkBot.firstElementChild, 'click', function() { - QR.open(); - return QR.nodes.com.focus(); - }); - if ((navLinksBot = $('.navLinksBot'))) { - $.prepend(navLinksBot, linkBot); - } - } - origToggle = $.id('togglePostFormLink'); - $.before(origToggle, link); - origToggle.firstElementChild.textContent = 'Original Form'; - $.on(d, 'QRGetFile', QR.getFile); - $.on(d, 'QRSetFile', QR.setFile); - $.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 k, len1, post, 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 (k = 0, len1 = ref.length; k < len1; k++) { - post = ref[k]; - post["delete"](); - } - QR.cooldown.auto = false; - QR.status(); - return QR.captcha.destroy(); - }, - focus: function() { - return $.queueTask(function() { - if (!QR.inBubble()) { - QR.hasFocus = d.activeElement && QR.nodes.el.contains(d.activeElement); - return QR.nodes.el.classList.toggle('focus', QR.hasFocus); - } - }); - }, - inBubble: function() { - var bubbles, ref; - bubbles = $$('iframe[src^="https://www.google.com/recaptcha/api2/frame"]'); - return (ref = d.activeElement, indexOf.call(bubbles, ref) >= 0) || bubbles.some(function(el) { - return getComputedStyle(el).visibility !== 'hidden' && el.getBoundingClientRect().bottom > 0; - }); - }, - 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(); - } - }, - toggleSJIS: function(e) { - e.preventDefault(); - Conf['sjisPreview'] = !Conf['sjisPreview']; - $.set('sjisPreview', Conf['sjisPreview']); - return QR.nodes.el.classList.toggle('sjis-preview', Conf['sjisPreview']); - }, - texPreviewShow: function() { - if ($.hasClass(QR.nodes.el, 'tex-preview')) { - return QR.texPreviewHide(); - } - $.addClass(QR.nodes.el, 'tex-preview'); - QR.nodes.texPreview.textContent = QR.nodes.com.value; - return $.event('mathjax', null, QR.nodes.texPreview); - }, - texPreviewHide: function() { - return $.rmClass(QR.nodes.el, 'tex-preview'); - }, - setCustomCooldown: function(enabled) { - Conf['customCooldownEnabled'] = enabled; - QR.cooldown.customCooldown = enabled; - return QR.nodes.customCooldown.classList.toggle('disabled', !enabled); - }, - toggleCustomCooldown: function() { - var enabled; - enabled = $.hasClass(this, 'disabled'); - QR.setCustomCooldown(enabled); - return $.set('customCooldownEnabled', enabled); - }, - error: function(err, focusOverride) { - var el, notice, notif; - QR.open(); - if (typeof err === 'string') { - el = $.tn(err); - } else { - el = err; - el.removeAttribute('style'); - } - notice = new Notice('warning', el); - QR.notifications.push(notice); - if (!Header.areNotificationsEnabled) { - if (d.hidden && !QR.cooldown.auto) { - return alert(el.textContent); - } - } else if (d.hidden || !(focusOverride || d.hasFocus())) { - try { - notif = new Notification(el.textContent, { - body: el.textContent, - icon: Favicon.logo - }); - notif.onclick = function() { - return $.global(function() { - return window.focus(); - }); - }; - if ($.engine !== 'gecko') { - notif.onclose = function() { - return notice.close(); - }; - return notif.onshow = function() { - return setTimeout(function() { - notif.onclose = null; - return notif.close(); - }, 7 * $.SECOND); - }; - } - } catch (_error) {} - } - }, - notifications: [], - cleanNotifications: function() { - var k, len1, notification, ref; - ref = QR.notifications; - for (k = 0, len1 = ref.length; k < len1; k++) { - notification = ref[k]; - 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; - }, - openPost: function() { - var index; - 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'); - return QR.cooldown.auto = true; - } - }, - quote: function(e) { - var aa, ancestor, caretPos, com, frag, insideCode, k, len1, len2, len3, len4, len5, len6, node, post, q, range, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, sel, text, thread, u, v, z; - 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 (k = 0, len1 = ref.length; k < len1; k++) { - node = ref[k]; - $.replace(node, $.tn('\n')); - } - ref1 = $$('br', frag); - for (q = 0, len2 = ref1.length; q < len2; q++) { - node = ref1[q]; - if (node !== frag.lastChild) { - $.replace(node, $.tn('\n>')); - } - } - ref2 = $$('s, .removed-spoiler', frag); - for (u = 0, len3 = ref2.length; u < len3; u++) { - node = ref2[u]; - $.replace(node, [$.tn('[spoiler]')].concat(slice.call(node.childNodes), [$.tn('[/spoiler]')])); - } - ref3 = $$('.prettyprint', frag); - for (v = 0, len4 = ref3.length; v < len4; v++) { - node = ref3[v]; - $.replace(node, [$.tn('[code]')].concat(slice.call(node.childNodes), [$.tn('[/code]')])); - } - ref4 = $$('.linkify[data-original]', frag); - for (z = 0, len5 = ref4.length; z < len5; z++) { - node = ref4[z]; - $.replace(node, $.tn(node.dataset.original)); - } - ref5 = $$('.embedder', frag); - for (aa = 0, len6 = ref5.length; aa < len6; aa++) { - node = ref5[aa]; - if (((ref6 = node.previousSibling) != null ? ref6.nodeValue : void 0) === ' ') { - $.rm(node.previousSibling); - } - $.rm(node); - } - text += ">" + (frag.textContent.trim()) + "\n"; - } - QR.openPost(); - 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.value.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '_').length; - counter.textContent = count; - counter.hidden = count < QR.max_comment / 2; - return (count > QR.max_comment ? $.addClass : $.rmClass)(counter, 'warning'); - }, - getFile: function() { - var ref; - return $.event('QRFile', (ref = QR.selected) != null ? ref.file : void 0); - }, - setFile: function(e) { - var file, name, ref, source; - ref = e.detail, file = ref.file, name = ref.name, source = ref.source; - if (name != null) { - file.name = name; - } - if (source != null) { - file.source = source; - } - QR.open(); - return QR.handleFiles([file]); - }, - 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, k, len1, ref; - if (!e.clipboardData.items) { - return; - } - files = []; - ref = e.clipboardData.items; - for (k = 0, len1 = ref.length; k < len1; k++) { - item = ref[k]; - 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'); - }, - pasteFF: function() { - var arr, blob, bstr, i, images, img, k, len1, m, pasteArea, q, ref, src; - pasteArea = QR.nodes.pasteArea; - if (!pasteArea.childNodes.length) { - return; - } - images = $$('img', pasteArea); - $.rmAll(pasteArea); - for (k = 0, len1 = images.length; k < len1; k++) { - img = images[k]; - src = img.src; - if (m = src.match(/data:(image\/(\w+));base64,(.+)/)) { - bstr = atob(m[3]); - arr = new Uint8Array(bstr.length); - for (i = q = 0, ref = bstr.length; 0 <= ref ? q < ref : q > ref; i = 0 <= ref ? ++q : --q) { - arr[i] = bstr.charCodeAt(i); - } - blob = new Blob([arr], { - type: m[1] - }); - blob.name = "file." + m[2]; - QR.handleFiles([blob]); - } else if (/^https?:\/\//.test(src)) { - QR.handleUrl(src); - } - } - }, - handleUrl: function(urlDefault) { - var url; - url = prompt('Enter a URL:', urlDefault); - if (url === null) { - return; - } - QR.nodes.fileButton.focus(); - return CrossOrigin.file(url, function(blob) { - if (blob && !/^text\//.test(blob.type)) { - return QR.handleFiles([blob]); - } else { - return QR.error("Can't load file."); - } - }); - }, - handleFiles: function(files) { - var file, k, len1; - if (this !== QR) { - files = slice.call(this.files); - this.value = null; - } - if (!files.length) { - return; - } - QR.cleanNotifications(); - for (k = 0, len1 = files.length; k < len1; k++) { - file = files[k]; - QR.handleFile(file, files.length); - } - if (files.length !== 1) { - $.addClass(QR.nodes.el, 'dump'); - } - if (d.activeElement === QR.nodes.fileButton && $.hasClass(QR.nodes.fileSubmit, 'has-file')) { - return QR.nodes.filename.focus(); - } - }, - handleFile: function(file, nfiles) { - var isText, post; - isText = /^text\//.test(file.type); - if (nfiles === 1) { - post = QR.selected; - } else { - post = QR.posts[QR.posts.length - 1]; - if ((isText ? post.com || post.pasting : post.file)) { - post = new QR.post(); - } - } - return post[isText ? 'pasteText' : 'setFile'](file); - }, - openFileInput: function() { - if (QR.nodes.fileButton.disabled) { - return; - } - QR.nodes.fileInput.click(); - return QR.nodes.fileButton.focus(); - }, - generatePostableThreadsList: function() { - var k, len1, list, options, ref, thread, val; - if (!QR.nodes) { - return; - } - list = QR.nodes.thread; - options = [list.firstElementChild]; - ref = g.BOARD.threads.keys; - for (k = 0, len1 = ref.length; k < len1; k++) { - thread = ref[k]; - options.push($.el('option', { - value: thread, - textContent: "Thread " + 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, ref, rules, save, scriptData, setNode; - QR.nodes = nodes = { - el: dialog = UI.dialog('qr', 'top: 50px; right: 0px;', { - innerHTML: "
      ×
      No selected file
      " - }) - }; - setNode = function(name, query) { - return nodes[name] = $(query, dialog); - }; - setNode('move', '.move'); - setNode('autohide', '#autohide'); - setNode('close', '.close'); - setNode('thread', 'select'); - setNode('form', 'form'); - setNode('sjisToggle', '#sjis-toggle'); - setNode('texButton', '#tex-preview-button'); - setNode('name', '[data-name=name]'); - setNode('email', '[data-name=email]'); - setNode('sub', '[data-name=sub]'); - setNode('com', '[data-name=com]'); - setNode('charCount', '#char-count'); - setNode('texPreview', '#tex-preview'); - setNode('dumpList', '#dump-list'); - setNode('addPost', '#add-post'); - setNode('oekaki', '.oekaki'); - setNode('drawButton', '#qr-draw-button'); - setNode('fileSubmit', '#file-n-submit'); - setNode('fileButton', '#qr-file-button'); - setNode('noFile', '#qr-no-file'); - setNode('filename', '#qr-filename'); - setNode('spoiler', '#qr-file-spoiler'); - setNode('oekakiButton', '#qr-oekaki-button'); - setNode('fileRM', '#qr-filerm'); - setNode('urlButton', '#url-button'); - setNode('pasteArea', '#paste-area'); - setNode('customCooldown', '#custom-cooldown-button'); - setNode('dumpButton', '#dump-button'); - setNode('status', '[type=submit]'); - setNode('flashTag', '[name=filetag]'); - 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; - scriptData = Get.scriptData(); - QR.max_size = (m = scriptData.match(/\bmaxFilesize *= *(\d+)\b/)) ? +m[1] : 4194304; - QR.max_size_video = (m = scriptData.match(/\bmaxWebmFilesize *= *(\d+)\b/)) ? +m[1] : QR.max_size; - QR.max_comment = (m = scriptData.match(/\bcomlen *= *(\d+)\b/)) ? +m[1] : 2000; - 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'); - } - if (g.BOARD.ID === 'jp' && Conf['sjisPreview']) { - $.addClass(QR.nodes.el, 'sjis-preview'); - } - if (parseInt(Conf['customCooldown'], 10) > 0) { - $.addClass(QR.nodes.fileSubmit, 'custom-cooldown'); - $.get('customCooldownEnabled', Conf['customCooldownEnabled'], function(arg) { - var customCooldownEnabled; - customCooldownEnabled = arg.customCooldownEnabled; - QR.setCustomCooldown(customCooldownEnabled); - return $.sync('customCooldownEnabled', QR.setCustomCooldown); - }); - } - $.on(nodes.autohide, 'change', QR.toggleHide); - $.on(nodes.close, 'click', QR.close); - $.on(nodes.form, 'submit', QR.submit); - $.on(nodes.sjisToggle, 'click', QR.toggleSJIS); - $.on(nodes.texButton, 'mousedown', QR.texPreviewShow); - $.on(nodes.texButton, 'mouseup', QR.texPreviewHide); - $.on(nodes.addPost, 'click', function() { - return new QR.post(true); - }); - $.on(nodes.drawButton, 'click', QR.oekaki.draw); - $.on(nodes.fileButton, 'click', QR.openFileInput); - $.on(nodes.noFile, 'click', QR.openFileInput); - $.on(nodes.filename, 'focus', function() { - return $.addClass(this.parentNode, 'focus'); - }); - $.on(nodes.filename, 'blur', function() { - return $.rmClass(this.parentNode, 'focus'); - }); - $.on(nodes.spoiler, 'change', function() { - return QR.selected.nodes.spoiler.click(); - }); - $.on(nodes.oekakiButton, 'click', QR.oekaki.button); - $.on(nodes.fileRM, 'click', function() { - return QR.selected.rmFile(); - }); - $.on(nodes.urlButton, 'click', function() { - return QR.handleUrl(''); - }); - $.on(nodes.customCooldown, 'click', QR.toggleCustomCooldown); - $.on(nodes.dumpButton, 'click', function() { - return nodes.el.classList.toggle('dump'); - }); - $.on(nodes.fileInput, 'change', QR.handleFiles); - window.addEventListener('focus', QR.focus, true); - window.addEventListener('blur', QR.focus, true); - $.on(d, 'click', QR.focus); - if ($.engine === 'gecko') { - nodes.pasteArea.hidden = false; - new MutationObserver(QR.pasteFF).observe(nodes.pasteArea, { - childList: true - }); - } - 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 ($.engine === 'gecko' && 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.setup(); - QR.captcha.init(); - $.add(d.body, dialog); - QR.captcha.setup(); - QR.oekaki.setup(); - return $.event('QRDialogCreation', null, dialog); - }, - submit: function(e) { - var captcha, cb, err, extra, filetag, formData, options, post, ref, 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(); - threadID = post.thread; - thread = g.BOARD.threads[threadID]; - if (g.BOARD.ID === 'f' && threadID === 'new') { - filetag = QR.nodes.flashTag.value; - } - if (threadID === 'new') { - threadID = null; - if (g.BOARD.ID === 'vg' && !post.sub) { - err = 'New threads require a subject.'; - } else if (!($.hasClass(d.body, 'text_only') || 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 comment or file.'; - } else if (post.file && thread.fileLimit) { - err = 'Max limit of image replies has been reached.'; - } - if (g.BOARD.ID === 'r9k' && !((ref = post.com) != null ? ref.match(/[a-z-]/i) : void 0)) { - err || (err = 'Original comment required.'); - } - if (QR.captcha.isEnabled && !err) { - captcha = QR.captcha.getOne(); - if (!captcha) { - err = 'No valid captcha.'; - QR.captcha.setup(!QR.cooldown.auto || d.activeElement === QR.nodes.status); - } - } - 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. [Banned?] [More info]" - })); - } - }; - extra = { - form: $.formData(formData), - upCallbacks: { - onload: function() { - QR.req.isUploadFinished = true; - 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) { - if (response.challenge != null) { - extra.form.append('recaptcha_challenge_field', response.challenge); - extra.form.append('recaptcha_response_field', response.response); - } else { - extra.form.append('g-recaptcha-response', 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, err, h1, isReply, lastPostToThread, m, open, post, postID, postsCount, ref, ref1, ref2, req, resDoc, seconds, threadID; - 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 + "! ;_;
      Click here to see the reason." - } : { - innerHTML: "You were issued a warning on " + $(".board", resDoc).innerHTML + " as " + $(".nameBlock", resDoc).innerHTML + ".
      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 = $.el('span', { - innerHTML: "You mistyped the CAPTCHA, or the CAPTCHA malfunctioned [complain here]." - }); - } else if (/expired/i.test(err.textContent)) { - err = 'This CAPTCHA is no longer valid because it has expired.'; - } - QR.cooldown.auto = QR.captcha.isEnabled || err === 'Connection error with sys.4chan.org.'; - QR.cooldown.addDelay(post, 2); - } else if (err.textContent && (m = err.textContent.match(/(?:(\d+)\s+minutes?\s+)?(\d+)\s+second/i)) && !/duplicate|hour/i.test(err.textContent)) { - QR.cooldown.auto = !/have\s+been\s+muted/i.test(err.textContent); - seconds = 60 * (+(m[1] || 0)) + (+m[2]); - if (/muted/i.test(err.textContent)) { - QR.cooldown.addMute(seconds); - } else { - QR.cooldown.addDelay(post, seconds); - } - } else { - QR.cooldown.auto = false; - } - QR.captcha.setup(QR.cooldown.auto && ((ref1 = d.activeElement) === QR.nodes.status || ref1 === d.body)); - if (QR.captcha.isEnabled && !QR.captcha.captchas.length) { - 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)); - } - ref2 = h1.nextSibling.textContent.match(/thread:(\d+),no:(\d+)/), _ = ref2[0], threadID = ref2[1], postID = ref2[2]; - postID = +postID; - threadID = +threadID || postID; - isReply = threadID !== 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; - lastPostToThread = !((function() { - var k, len1, p, ref3; - ref3 = QR.posts.slice(1); - for (k = 0, len1 = ref3.length; k < len1; k++) { - p = ref3[k]; - if (p.thread === post.thread) { - return true; - } - } - })()); - if (!(Conf['Persistent QR'] || postsCount)) { - QR.close(); - } else { - post.rm(); - QR.captcha.setup(d.activeElement === QR.nodes.status); - } - QR.cooldown.add(threadID, postID); - URL = threadID === postID ? window.location.origin + "/" + g.BOARD + "/thread/" + threadID : g.VIEW === 'index' && lastPostToThread && Conf['Open Post in New Tab'] ? window.location.origin + "/" + g.BOARD + "/thread/" + threadID + "#p" + postID : void 0; - if (URL) { - open = Conf['Open Post in New Tab'] || postsCount ? function() { - return $.open(URL); - } : function() { - return window.location = URL; - }; - if (threadID === postID) { - QR.waitForThread(URL, open); - } else { - open(); - } - } - return QR.status(); - }, - waitForThread: function(url, cb) { - var attempts, check; - attempts = 0; - check = function() { - return $.ajax(url, { - onloadend: function() { - attempts++; - if (attempts >= 6 || this.status === 200) { - return cb(); - } else { - return setTimeout(check, attempts * $.SECOND); - } - } - }, { - type: 'HEAD' - }); - }; - return check(); - }, - 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.fixes = { - imageKeys: '789456123uiojklm'.split('').concat(['Comma', 'Period']), - imageKeys16: '7890uiopjkl'.split('').concat(['Semicolon', 'm', 'Comma', 'Period', 'Slash']), - css: '.rc-imageselect-target > div:focus, .rc-image-tile-target:focus {\n outline: 2px solid #4a90e2;\n}\n.rc-imageselect-target td:focus {\n box-shadow: inset 0 0 0 2px #4a90e2;\n outline: none;\n}\n.rc-button-default:focus {\n box-shadow: inset 0 0 0 2px #0063d6;\n}', - cssNoscript: '.fbc-payload-imageselect {\n position: relative;\n}\n.fbc-payload-imageselect > label {\n position: absolute;\n display: block;\n height: 93.3px;\n width: 93.3px;\n}\nlabel[data-row="0"] {top: 0px;}\nlabel[data-row="1"] {top: 93.3px;}\nlabel[data-row="2"] {top: 186.6px;}\nlabel[data-col="0"] {left: 0px;}\nlabel[data-col="1"] {left: 93.3px;}\nlabel[data-col="2"] {left: 186.6px;}\n.fbc-payload-imageselect > input:focus + label {\n outline: 2px solid #4a90e2;\n}\n.fbc-button-verify input:focus {\n box-shadow: inset 0 0 0 2px #0063d6;\n}\nbody.focus .fbc {\n box-shadow: inset 0 0 0 2px #4a90e2;\n}', - init: function() { - switch (location.pathname.split('/')[3]) { - case 'anchor': - return this.initMain(); - case 'frame': - return this.initPopup(); - case 'fallback': - return this.initNoscript(); - } - }, - initMain: function() { - var a, k, len1, ref; - $.onExists(d.body, '#recaptcha-anchor', function(checkbox) { - var focus; - focus = function() { - var ref; - if (d.hasFocus() && ((ref = d.activeElement) === d.documentElement || ref === d.body)) { - return checkbox.focus(); - } - }; - focus(); - return $.on(window, 'focus', function() { - return $.queueTask(focus); - }); - }); - ref = $$('.rc-anchor-pt a'); - for (k = 0, len1 = ref.length; k < len1; k++) { - a = ref[k]; - a.tabIndex = -1; - } - }, - initPopup: function() { - $.addStyle(this.css); - this.fixImages(); - new MutationObserver((function(_this) { - return function() { - return _this.fixImages(); - }; - })(this)).observe(d.body, { - childList: true, - subtree: true - }); - return $.on(d, 'keydown', this.keybinds.bind(this)); - }, - initNoscript: function() { - var data, ref, token; - this.noscript = true; - data = (token = (ref = $('.fbc-verification-token > textarea')) != null ? ref.value : void 0) ? { - token: token - } : { - working: true - }; - new Connection(window.parent, '*').send(data); - d.body.classList.toggle('focus', d.hasFocus()); - $.on(window, 'focus blur', function() { - return d.body.classList.toggle('focus', d.hasFocus()); - }); - this.images = $$('.fbc-payload-imageselect > input'); - this.width = 3; - if (this.images.length !== 9) { - return; - } - $.addStyle(this.cssNoscript); - this.addLabels(); - $.on(d, 'keydown', this.keybinds.bind(this)); - return $.on($('.fbc-imageselect-challenge > form'), 'submit', this.checkForm.bind(this)); - }, - fixImages: function() { - var img, k, len1, ref; - this.images = $$('.rc-image-tile-target'); - if (!this.images.length) { - this.images = $$('.rc-imageselect-target > div, .rc-imageselect-target td'); - } - this.width = $$('.rc-imageselect-target tr:first-of-type td').length || Math.round(Math.sqrt(this.images.length)); - ref = this.images; - for (k = 0, len1 = ref.length; k < len1; k++) { - img = ref[k]; - img.tabIndex = 0; - } - if (this.images.length === 9) { - this.addTooltips(this.images); - } else { - this.addTooltips16(this.images); - } - return this.complaintLinks(); - }, - complaintLinks: function() { - var errmsg, k, len1, link, ref; - ref = $$('.rc-imageselect-incorrect-response, .rc-imageselect-error-select-one, .rc-imageselect-error-select-more, .rc-imageselect-error-dynamic-more'); - for (k = 0, len1 = ref.length; k < len1; k++) { - errmsg = ref[k]; - if (!$('a', errmsg)) { - link = $.el('a', { - href: 'https://www.4chan-x.net/captchas.html', - target: '_blank', - textContent: '[complain]' - }); - $.add(errmsg, [$.tn(' '), link]); - } - } - }, - addLabels: function() { - var checkbox, i, imageSelect, label, labels; - imageSelect = $('.fbc-payload-imageselect'); - labels = (function() { - var k, len1, ref, results; - ref = this.images; - results = []; - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - checkbox = ref[i]; - checkbox.id = "checkbox-" + i; - label = $.el('label', { - htmlFor: checkbox.id - }); - label.dataset.row = Math.floor(i / 3); - label.dataset.col = i % 3; - $.after(checkbox, label); - results.push(label); - } - return results; - }).call(this); - return this.addTooltips(labels); - }, - addTooltips: function(nodes) { - var i, k, len1, node; - for (i = k = 0, len1 = nodes.length; k < len1; i = ++k) { - node = nodes[i]; - node.title = this.imageKeys[i] + " or " + (this.imageKeys[i + 9][0].toUpperCase()) + this.imageKeys[i + 9].slice(1); - } - }, - addTooltips16: function(nodes) { - var i, k, key, len1, node, ref; - ref = this.imageKeys16; - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - key = ref[i]; - if (i % 4 < this.width && (node = nodes[nodes.length - (4 - Math.floor(i / 4)) * this.width + (i % 4)])) { - node.title = "" + (key[0].toUpperCase()) + key.slice(1); - } - } - }, - checkForm: function(e) { - var checkbox, k, len1, n, ref; - n = 0; - ref = this.images; - for (k = 0, len1 = ref.length; k < len1; k++) { - checkbox = ref[k]; - if (checkbox.checked) { - n++; - } - } - if (n === 0) { - return e.preventDefault(); - } - }, - keybinds: function(e) { - var dx, i, img, key, last, n, reload, verify, w, x; - if (!(this.images && doc.contains(this.images[0]))) { - return; - } - n = this.images.length; - w = this.width; - last = n + w - 1; - reload = $('#recaptcha-reload-button, .fbc-button-reload'); - verify = $('#recaptcha-verify-button, .fbc-button-verify > input'); - x = this.images.indexOf(d.activeElement); - if (x < 0) { - x = d.activeElement === verify ? last : n; - } - key = Keybinds.keyCode(e); - if (!this.noscript && key === 'Space' && x < n) { - this.images[x].click(); - } else if (n === 9 && (i = this.imageKeys.indexOf(key)) >= 0) { - this.images[i % 9].click(); - verify.focus(); - } else if (n !== 9 && (i = this.imageKeys16.indexOf(key)) >= 0 && i % 4 < w && (img = this.images[n - (4 - Math.floor(i / 4)) * w + (i % 4)])) { - img.click(); - verify.focus(); - } else if (dx = { - 'Up': n, - 'Down': w, - 'Left': last, - 'Right': 1 - }[key]) { - x = (x + dx) % (n + w); - if ((n < x && x < last)) { - x = dx === last ? n : last; - } - (this.images[x] || (x === n ? reload : void 0) || (x === last ? verify : void 0)).focus(); - } else { - return; - } - e.preventDefault(); - return e.stopPropagation(); - } - }; - - Captcha.replace = { - init: function() { - if (!(d.cookie.indexOf('pass_enabled=1') < 0)) { - return; - } - if (location.hostname === 'sys.4chan.org' && /[?&]altc\b/.test(location.search) && Main.jsEnabled) { - $.onExists(doc, 'script[src="//www.google.com/recaptcha/api/js/recaptcha_ajax.js"]', function() { - $.global(function() { - return window.el.onload = null; - }); - return Captcha.v1.create(); - }); - return; - } - if (((Conf['Use Recaptcha v1'] && location.hostname === 'boards.4chan.org') || (Conf['Use Recaptcha v1 in Reports'] && location.hostname === 'sys.4chan.org')) && Main.jsEnabled) { - $.ready(Captcha.replace.v1); - return; - } - if (Conf['Force Noscript Captcha'] && Main.jsEnabled) { - $.ready(Captcha.replace.noscript); - return; - } - if (Conf['captchaLanguage'].trim() || Conf['Captcha Fixes']) { - if (location.hostname === 'boards.4chan.org') { - return $.onExists(doc, '#captchaFormPart', function(node) { - return $.onExists(node, 'iframe', Captcha.replace.iframe); - }); - } else { - return $.onExists(doc, 'iframe', Captcha.replace.iframe); - } - } - }, - noscript: function() { - var insert, noscript, original, span, toggle; - if (!((original = $('#g-recaptcha, #captchaContainerAlt')) && (noscript = $('noscript')))) { - return; - } - span = $.el('span', { - id: 'captcha-forced-noscript' - }); - $.replace(noscript, span); - $.rm(original); - insert = function() { - span.innerHTML = noscript.textContent; - return Captcha.replace.iframe($('iframe', span)); - }; - if ((toggle = $('#togglePostFormLink a, #form-link'))) { - return $.on(toggle, 'click', insert); - } else { - return insert(); - } - }, - v1: function() { - var form, link; - if (!$.id('g-recaptcha')) { - return; - } - Captcha.v1.replace(); - if ((link = $.id('form-link'))) { - return $.on(link, 'click', function() { - return Captcha.v1.create(); - }); - } else if (location.hostname === 'boards.4chan.org') { - form = $.id('postForm'); - return form.addEventListener('focus', (function() { - return Captcha.v1.create(); - }), true); - } else { - return Captcha.v1.create(); - } - }, - iframe: function(iframe) { - var lang, src; - if ((lang = Conf['captchaLanguage'].trim())) { - src = /[?&]hl=/.test(iframe.src) ? iframe.src.replace(/([?&]hl=)[^&]*/, '$1' + encodeURIComponent(lang)) : iframe.src + ("&hl=" + (encodeURIComponent(lang))); - if (iframe.src !== src) { - iframe.src = src; - } - } - return Captcha.replace.autocopy(iframe); - }, - autocopy: function(iframe) { - if (!(Conf['Captcha Fixes'] && /^https:\/\/www\.google\.com\/recaptcha\/api\/fallback\?/.test(iframe.src))) { - return; - } - return new Connection(iframe, 'https://www.google.com', { - working: function() { - var ref, ref1; - if ((ref = $.id('qr')) != null ? ref.contains(iframe) : void 0) { - return (ref1 = $('#qr .captcha-container textarea')) != null ? ref1.parentNode.hidden = true : void 0; - } - }, - token: function(token) { - var node, textarea; - node = iframe; - while ((node = node.parentNode)) { - if ((textarea = $('textarea', node))) { - break; - } - } - textarea.value = token; - return $.event('input', null, textarea); - } - }); - } - }; - - Captcha.v1 = { - blank: "data:image/svg+xml,", - init: function() { - var imgContainer, input; - if (d.cookie.indexOf('pass_enabled=1') >= 0) { - return; - } - if (!(this.isEnabled = !!$('#g-recaptcha, #captchaContainerAlt'))) { - return; - } - imgContainer = $.el('div', { - className: 'captcha-img', - title: 'Reload reCAPTCHA' - }); - $.extend(imgContainer, { - innerHTML: "" - }); - input = $.el('input', { - className: 'captcha-input field', - title: 'Verification', - autocomplete: 'off', - spellcheck: false - }); - this.nodes = { - img: imgContainer.firstChild, - input: input - }; - $.on(input, 'blur', QR.focusout); - $.on(input, 'focus', QR.focusin); - $.on(input, 'keydown', QR.captcha.keydown.bind(QR.captcha)); - $.on(this.nodes.img.parentNode, 'click', QR.captcha.reload.bind(QR.captcha)); - $.addClass(QR.nodes.el, 'has-captcha', 'captcha-v1'); - $.after(QR.nodes.com.parentNode, [imgContainer, 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.replace(); - this.beforeSetup(); - if (Conf['Auto-load captcha']) { - this.setup(); - } - new MutationObserver(this.afterSetup).observe($.id('captchaContainerAlt'), { - childList: true - }); - return this.afterSetup(); - }, - replace: function() { - var container, old; - if (this.script) { - return; - } - if (!(this.script = $('script[src="//www.google.com/recaptcha/api/js/recaptcha_ajax.js"]', d.head))) { - this.script = $.el('script', { - src: '//www.google.com/recaptcha/api/js/recaptcha_ajax.js' - }); - $.add(d.head, this.script); - } - if (old = $.id('g-recaptcha')) { - container = $.el('div', { - id: 'captchaContainerAlt' - }); - return $.replace(old, container); - } - }, - create: function() { - var cont, lang; - cont = $.id('captchaContainerAlt'); - if (this.occupied) { - return; - } - this.occupied = true; - if ((lang = Conf['captchaLanguage'].trim())) { - cont.dataset.lang = lang; - } - $.onExists(cont, '#recaptcha_image', function(image) { - return $.on(image, 'click', function() { - if ($.id('recaptcha_challenge_image')) { - return $.global(function() { - return window.Recaptcha.reload(); - }); - } - }); - }); - $.onExists(cont, '#recaptcha_response_field', function(field) { - $.on(field, 'keydown', function(e) { - if (e.keyCode === 8 && !field.value) { - return $.global(function() { - return window.Recaptcha.reload(); - }); - } - }); - if (location.hostname === 'sys.4chan.org') { - return field.focus(); - } - }); - return $.global(function() { - var container, options, script; - container = document.getElementById('captchaContainerAlt'); - options = { - theme: 'clean', - tabindex: { - "boards.4chan.org": 5 - }[location.hostname], - lang: container.dataset.lang - }; - if (window.Recaptcha) { - return window.Recaptcha.create('6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc', container, options); - } else { - script = document.head.querySelector('script[src="//www.google.com/recaptcha/api/js/recaptcha_ajax.js"]'); - return script.addEventListener('load', function() { - return window.Recaptcha.create('6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc', container, options); - }, false); - } - }); - }, - cb: { - focus: function() { - return QR.captcha.setup(false, true); - } - }, - beforeSetup: function() { - var img, input, ref; - ref = this.nodes, img = ref.img, input = ref.input; - img.parentNode.hidden = true; - img.src = this.blank; - 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 && (force || this.needed()))) { - return; - } - this.create(); - if (focus) { - $.addClass(QR.nodes.el, 'focus'); - return this.nodes.input.focus(); - } - }, - afterSetup: function() { - var challenge, img, input, ref, setLifetime; - if (!(challenge = $.id('recaptcha_challenge_field_holder'))) { - return; - } - if (challenge === QR.captcha.nodes.challenge) { - return; - } - setLifetime = function(e) { - return QR.captcha.lifetime = e.detail; - }; - $.on(window, 'captcha:timeout', setLifetime); - $.global(function() { - return window.dispatchEvent(new CustomEvent('captcha:timeout', { - detail: window.RecaptchaState.timeout - })); - }); - $.off(window, 'captcha:timeout', setLifetime); - ref = QR.captcha.nodes, img = ref.img, input = ref.input; - img.parentNode.hidden = false; - input.placeholder = 'Verification'; - QR.captcha.count(); - $.off(input, 'focus click', QR.captcha.cb.focus); - QR.captcha.nodes.challenge = challenge; - new MutationObserver(QR.captcha.load.bind(QR.captcha)).observe(challenge, { - childList: true, - subtree: true, - attributes: true - }); - QR.captcha.load(); - if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) { - QR.nodes.el.style.top = null; - return QR.nodes.el.style.bottom = '0px'; - } - }, - destroy: function() { - if (!this.script) { - return; - } - $.global(function() { - return window.Recaptcha.destroy(); - }); - delete this.occupied; - if (this.nodes) { - return this.beforeSetup(); - } - }, - sync: function(captchas) { - if (captchas == null) { - captchas = []; - } - QR.captcha.captchas = captchas; - return QR.captcha.count(); - }, - getOne: function() { - var captcha, challenge, response, timeout; - this.clear(); - if (captcha = this.captchas.shift()) { - this.count(); - $.set('captchas', this.captchas); - return captcha; - } else { - challenge = this.nodes.img.alt; - timeout = this.timeout; - if (/\S/.test(response = this.nodes.input.value)) { - this.destroy(); - return { - challenge: challenge, - response: response, - timeout: timeout - }; - } else { - return null; - } - } - }, - save: function() { - var response; - if (!/\S/.test(response = this.nodes.input.value)) { - return; - } - this.nodes.input.value = ''; - this.captchas.push({ - challenge: this.nodes.img.alt, - response: response, - timeout: this.timeout - }); - this.captchas.sort(function(a, b) { - return a.timeout - b.timeout; - }); - this.count(); - this.destroy(); - this.setup(false, true); - return $.set('captchas', this.captchas); - }, - clear: function() { - var captcha, i, k, len1, now, ref; - if (!this.captchas.length) { - return; - } - $.forceSync('captchas'); - now = Date.now(); - ref = this.captchas; - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - captcha = ref[i]; - if (captcha.timeout > now) { - break; - } - } - if (!i) { - return; - } - this.captchas = this.captchas.slice(i); - this.count(); - return $.set('captchas', this.captchas); - }, - load: function() { - var challenge, challenge_image; - if ($('#captchaContainerAlt[class~="recaptcha_is_showing_audio"]')) { - this.nodes.img.src = this.blank; - return; - } - if (!this.nodes.challenge.firstChild) { - return; - } - if (!(challenge_image = $.id('recaptcha_challenge_image'))) { - return; - } - this.timeout = Date.now() + this.lifetime * $.SECOND - $.MINUTE; - challenge = this.nodes.challenge.firstChild.value; - this.nodes.img.alt = challenge; - this.nodes.img.src = challenge_image.src; - this.nodes.input.value = ''; - return this.clear(); - }, - 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.timer); - if (count) { - return this.timer = setTimeout(this.clear.bind(this), this.captchas[0].timeout - Date.now()); - } - }, - reload: function(focus) { - $.global(function() { - if (window.Recaptcha.type === 'image') { - window.Recaptcha.reload(); - } else { - window.Recaptcha.switch_type('image'); - } - return window.Recaptcha.should_focus = false; - }); - if (focus) { - return this.nodes.input.focus(); - } - }, - keydown: function(e) { - if (e.keyCode === 8 && !this.nodes.input.value) { - this.reload(); - } else if (e.keyCode === 13 && e.shiftKey) { - this.save(); - } else { - return; - } - return e.preventDefault(); - } - }; - - Captcha.v2 = { - lifetime: 2 * $.MINUTE, - init: function() { - var counter, root; - if (d.cookie.indexOf('pass_enabled=1') >= 0) { - return; - } - if (!(this.isEnabled = !!$('#g-recaptcha, #captchaContainerAlt, #captcha-forced-noscript'))) { - return; - } - if ((this.noscript = Conf['Force Noscript Captcha'] || !Main.jsEnabled)) { - $.addClass(QR.nodes.el, 'noscript-captcha'); - } - 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: "
      " - }); - counter = $('.captcha-counter > a', root); - this.nodes = { - root: root, - counter: counter - }; - this.count(); - $.addClass(QR.nodes.el, 'has-captcha', 'captcha-v2'); - $.after(QR.nodes.com.parentNode, root); - $.on(counter, 'click', this.toggle.bind(this)); - $.on(counter, 'keydown', (function(_this) { - return function(e) { - if (Keybinds.keyCode(e) !== 'Space') { - return; - } - _this.toggle(); - e.preventDefault(); - return e.stopPropagation(); - }; - })(this)); - return $.on(window, 'captcha:success', (function(_this) { - return function() { - return $.queueTask(function() { - return _this.save(false); - }); - }; - })(this)); - }, - timeouts: {}, - postsCount: 0, - noscriptURL: function() { - var lang, url; - url = 'https://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc'; - if ((lang = Conf['captchaLanguage'].trim())) { - url += "&hl=" + (encodeURIComponent(lang)); - } - return url; - }, - 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) { - if (!(this.isEnabled && (this.needed() || force))) { - return; - } - if (focus) { - $.addClass(QR.nodes.el, 'focus'); - this.nodes.counter.focus(); - } - if (this.timeouts.destroy) { - clearTimeout(this.timeouts.destroy); - delete this.timeouts.destroy; - return this.reload(); - } - if (this.nodes.container) { - $.queueTask((function(_this) { - return function() { - var iframe; - if (_this.nodes.container && d.activeElement === _this.nodes.counter && (iframe = $('iframe', _this.nodes.container))) { - iframe.focus(); - return QR.focus(); - } - }; - })(this)); - 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 - }); - if (this.noscript) { - return this.setupNoscript(); - } else { - return this.setupJS(); - } - }, - setupNoscript: function() { - var div, iframe, textarea; - iframe = $.el('iframe', { - id: 'qr-captcha-iframe', - src: this.noscriptURL() - }); - div = $.el('div'); - textarea = $.el('textarea'); - $.add(div, textarea); - return $.add(this.nodes.container, [iframe, div]); - }, - setupJS: function() { - return $.global(function() { - var cbNative, render; - render = function() { - var classList, container; - classList = document.documentElement.classList; - container = document.querySelector('#qr .captcha-container'); - return container.dataset.widgetID = window.grecaptcha.render(container, { - sitekey: '6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc', - theme: classList.contains('tomorrow') || classList.contains('dark-captcha') ? 'dark' : 'light', - callback: function(response) { - return window.dispatchEvent(new CustomEvent('captcha:success', { - detail: response - })); - } - }); - }; - if (window.grecaptcha) { - return render(); - } else { - cbNative = window.onRecaptchaLoaded; - return window.onRecaptchaLoaded = function() { - render(); - return cbNative(); - }; - } - }); - }, - afterSetup: function(mutations) { - var iframe, k, len1, len2, mutation, node, q, ref, textarea; - for (k = 0, len1 = mutations.length; k < len1; k++) { - mutation = mutations[k]; - ref = mutation.addedNodes; - for (q = 0, len2 = ref.length; q < len2; q++) { - node = ref[q]; - 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) { - if (!doc.contains(iframe)) { - return; - } - Captcha.replace.iframe(iframe); - $.addClass(QR.nodes.el, 'captcha-open'); - this.fixQRPosition(); - $.on(iframe, 'load', this.fixQRPosition); - if (d.activeElement === this.nodes.counter) { - iframe.focus(); - } - return $.global(function() { - var f; - f = document.querySelector('#qr iframe'); - return f.focus = f.blur = function() {}; - }); - }, - fixQRPosition: function() { - if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) { - QR.nodes.el.style.top = null; - return QR.nodes.el.style.bottom = '0px'; - } - }, - setupTextArea: function(textarea) { - return $.one(textarea, 'input', (function(_this) { - return function() { - return _this.save(true); - }; - })(this)); - }, - destroy: function() { - var garbage, i, ins, node, ref; - if (!this.isEnabled) { - return; - } - delete this.timeouts.destroy; - $.rmClass(QR.nodes.el, 'captcha-open'); - if (this.nodes.container) { - $.rm(this.nodes.container); - } - delete this.nodes.container; - garbage = $.X('//iframe[starts-with(@src, "https://www.google.com/recaptcha/api2/frame")]/ancestor-or-self::*[parent::body]'); - i = 0; - while (node = garbage.snapshotItem(i++)) { - if (((ref = (ins = node.nextSibling)) != null ? ref.nodeName : void 0) === 'INS') { - $.rm(ins); - } - $.rm(node); - } - }, - 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; - } else { - return null; - } - }, - save: function(pasted, token) { - var base1, focus, ref; - $.forceSync('captchas'); - this.captchas.push({ - response: token || $('textarea', this.nodes.container).value, - timeout: Date.now() + this.lifetime - }); - this.captchas.sort(function(a, b) { - return a.timeout - b.timeout; - }); - $.set('captchas', this.captchas); - this.count(); - focus = ((ref = d.activeElement) != null ? ref.nodeName : void 0) === 'IFRAME' && /https?:\/\/www\.google\.com\/recaptcha\//.test(d.activeElement.src); - if (this.needed()) { - if (focus) { - if (QR.cooldown.auto || Conf['Post on Captcha Completion']) { - this.nodes.counter.focus(); - } else { - QR.nodes.status.focus(); - } - } - this.reload(); - } else { - if (pasted) { - this.destroy(); - } else { - if ((base1 = this.timeouts).destroy == null) { - base1.destroy = setTimeout(this.destroy.bind(this), 3 * $.SECOND); - } - } - if (focus) { - QR.nodes.status.focus(); - } - } - if (Conf['Post on Captcha Completion'] && !QR.cooldown.auto) { - return QR.submit(); - } - }, - clear: function() { - var captcha, i, k, len1, now, ref; - if (!this.captchas.length) { - return; - } - $.forceSync('captchas'); - now = Date.now(); - ref = this.captchas; - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - 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(d.activeElement === QR.nodes.status); - }, - 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() { - if ($('iframe[src^="https://www.google.com/recaptcha/api/fallback?"]', this.nodes.container)) { - this.destroy(); - return this.setup(false, true); - } else { - return $.global(function() { - var container; - container = document.querySelector('#qr .captcha-container'); - return window.grecaptcha.reset(container.dataset.widgetID); - }); - } - } - }; - - PassLink = { - init: function() { - if (!Conf['Pass Link']) { - return; - } - return Main.ready(this.ready); - }, - ready: function() { - var passLink, styleSelector; - if (!(styleSelector = $.id('styleSelector'))) { - return; - } - passLink = $.el('span', { - className: 'brackets-wrap pass-link-container' - }); - $.extend(passLink, { - innerHTML: "4chan Pass" - }); - $.on(passLink.firstElementChild, 'click', function() { - return window.open('//sys.4chan.org/auth', Date.now(), 'width=500,height=280,toolbar=0'); - }); - return $.before(styleSelector.previousSibling, [passLink, $.tn('\u00A0\u00A0')]); - } - }; - - PostSuccessful = { - init: function() { - if (!Conf['Remember Your Posts']) { - return; - } - return $.ready(this.ready); - }, - ready: function() { - var _, db, postID, ref, threadID; - if (d.title !== 'Post successful!') { - return; - } - ref = $('h1').nextSibling.textContent.match(/thread:(\d+),no:(\d+)/), _ = ref[0], threadID = ref[1], postID = ref[2]; - postID = +postID; - threadID = +threadID || postID; - db = new DataBoard('yourPosts'); - return db.set({ - boardID: g.BOARD.ID, - threadID: threadID, - postID: postID, - val: true - }); - } - }; - - QR.cooldown = { - seconds: 0, - delays: { - thread: 0, - reply: 0, - image: 0, - reply_intra: 0, - image_intra: 0, - deletion: 60, - thread_global: 300 - }, - init: function() { - if (!Conf['Quick Reply']) { - return; - } - this.data = Conf['cooldowns']; - return $.sync('cooldowns', this.sync); - }, - setup: function() { - var delay, m, ref, type; - if (m = Get.scriptData().match(/\bcooldowns *= *({[^}]+})/)) { - $.extend(QR.cooldown.delays, JSON.parse(m[1])); - } - QR.cooldown.maxDelay = 0; - ref = QR.cooldown.delays; - for (type in ref) { - delay = ref[type]; - if (type !== 'thread' && type !== 'thread_global') { - QR.cooldown.maxDelay = Math.max(QR.cooldown.maxDelay, delay); - } - } - QR.cooldown.isSetup = true; - return QR.cooldown.start(); - }, - start: function() { - var data; - data = QR.cooldown.data; - if (!(Conf['Cooldown'] && QR.cooldown.isSetup && !QR.cooldown.isCounting && Object.keys(data[g.BOARD.ID] || {}).length + Object.keys(data.global || {}).length > 0)) { - return; - } - QR.cooldown.isCounting = true; - return QR.cooldown.count(); - }, - sync: function(data) { - QR.cooldown.data = data || {}; - return QR.cooldown.start(); - }, - add: function(threadID, postID) { - var boardID, start; - if (!Conf['Cooldown']) { - return; - } - start = Date.now(); - boardID = g.BOARD.ID; - QR.cooldown.set(boardID, 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(g.BOARD.ID, Date.now(), cooldown); - return QR.cooldown.start(); - }, - addMute: function(delay) { - if (!Conf['Cooldown']) { - return; - } - QR.cooldown.set(g.BOARD.ID, Date.now(), { - type: 'mute', - delay: delay - }); - return QR.cooldown.start(); - }, - "delete": function(post) { - var base1, cooldown, cooldowns, id, name1; - if (!QR.cooldown.data) { - return; - } - $.forceSync('cooldowns'); - cooldowns = ((base1 = QR.cooldown.data)[name1 = post.board.ID] || (base1[name1] = {})); - for (id in cooldowns) { - cooldown = cooldowns[id]; - if ((cooldown.delay == null) && cooldown.threadID === post.thread.ID && cooldown.postID === post.ID) { - delete cooldowns[id]; - } - } - return QR.cooldown.save([post.board.ID]); - }, - secondsDeletion: function(post) { - var cooldown, cooldowns, seconds, start; - if (!(QR.cooldown.data && Conf['Cooldown'])) { - return 0; - } - cooldowns = QR.cooldown.data[post.board.ID] || {}; - for (start in cooldowns) { - cooldown = cooldowns[start]; - if ((cooldown.delay == null) && cooldown.threadID === post.thread.ID && cooldown.postID === post.ID) { - seconds = QR.cooldown.delays.deletion - Math.floor((Date.now() - start) / $.SECOND); - return Math.max(seconds, 0); - } - } - return 0; - }, - 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) { - var base1, cooldowns; - $.forceSync('cooldowns'); - cooldowns = ((base1 = QR.cooldown.data)[scope] || (base1[scope] = {})); - cooldowns[id] = value; - return $.set('cooldowns', QR.cooldown.data); - }, - save: function(scopes) { - var data, k, len1, scope; - data = QR.cooldown.data; - for (k = 0, len1 = scopes.length; k < len1; k++) { - scope = scopes[k]; - if (scope in data && !Object.keys(data[scope]).length) { - delete data[scope]; - } - } - return $.set('cooldowns', data); - }, - count: function() { - var base1, cooldown, cooldowns, elapsed, k, len1, maxDelay, nCooldowns, now, ref, ref1, save, scope, seconds, start, suffix, threadID, type, update; - $.forceSync('cooldowns'); - save = []; - nCooldowns = 0; - now = Date.now(); - ref = QR.cooldown.categorize(QR.posts[0]), type = ref.type, threadID = ref.threadID; - seconds = 0; - if (Conf['Cooldown']) { - ref1 = [g.BOARD.ID, 'global']; - for (k = 0, len1 = ref1.length; k < len1; k++) { - scope = ref1[k]; - cooldowns = ((base1 = QR.cooldown.data)[scope] || (base1[scope] = {})); - for (start in cooldowns) { - cooldown = cooldowns[start]; - start = +start; - elapsed = Math.floor((now - start) / $.SECOND); - if (elapsed < 0) { - delete cooldowns[start]; - save.push(scope); - continue; - } - if (cooldown.delay != null) { - if (cooldown.delay <= elapsed) { - delete cooldowns[start]; - save.push(scope); - } else if ((cooldown.type === type && cooldown.threadID === threadID) || cooldown.type === 'mute') { - 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 (QR.cooldown.customCooldown) { - maxDelay = Math.max(maxDelay, parseInt(Conf['customCooldown'], 10)); - } - if (maxDelay <= elapsed) { - delete cooldowns[start]; - save.push(scope); - 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 (QR.cooldown.customCooldown) { - seconds = Math.max(seconds, parseInt(Conf['customCooldown'], 10) - elapsed); - } - } - nCooldowns += Object.keys(cooldowns).length; - } - } - if (save.length) { - QR.cooldown.save(save); - } - if (nCooldowns) { - 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.oekaki = { - menu: { - init: function() { - var a, ref; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Menu'] && Conf['Edit Link'] && Conf['Quick Reply'])) { - return; - } - a = $.el('a', { - className: 'edit-link', - href: 'javascript:;', - textContent: 'Edit image' - }); - $.on(a, 'click', this.editFile); - return Menu.menu.addEntry({ - el: a, - order: 95, - open: function(post) { - var file; - QR.oekaki.menu.post = post; - file = post.file; - return QR.postingIsEnabled && !!file && (file.isImage || file.isVideo); - } - }); - }, - editFile: function() { - var currentTime, isVideo, post, ref; - post = QR.oekaki.menu.post; - QR.quote.call(post.nodes.post); - isVideo = post.file.isVideo; - currentTime = ((ref = post.file.fullImage) != null ? ref.currentTime : void 0) || 0; - return CrossOrigin.file(post.file.url, function(blob) { - var video; - if (!blob) { - return QR.error("Can't load file."); - } else if (isVideo) { - video = $.el('video'); - $.on(video, 'loadedmetadata', function() { - $.on(video, 'seeked', function() { - var canvas; - canvas = $.el('canvas', { - width: video.videoWidth, - height: video.videoHeight - }); - canvas.getContext('2d').drawImage(video, 0, 0); - return canvas.toBlob(function(snapshot) { - snapshot.name = post.file.name.replace(/\.\w+$/, '') + '.png'; - QR.handleFiles([snapshot]); - return QR.oekaki.edit(); - }); - }); - return video.currentTime = currentTime; - }); - return video.src = URL.createObjectURL(blob); - } else { - blob.name = post.file.name; - QR.handleFiles([blob]); - return QR.oekaki.edit(); - } - }); - } - }, - setup: function() { - return $.global(function() { - var FCX; - FCX = window.FCX; - FCX.oekakiCB = function() { - return window.Tegaki.flatten().toBlob(function(file) { - var source; - source = "oekaki-" + (Date.now()); - FCX.oekakiLatest = source; - return document.dispatchEvent(new CustomEvent('QRSetFile', { - bubbles: true, - detail: { - file: file, - name: FCX.oekakiName, - source: source - } - })); - }); - }; - if (window.Tegaki) { - return document.querySelector('#qr .oekaki').hidden = false; - } - }); - }, - load: function(cb) { - var n, onload, script, style; - if ($('script[src^="//s.4cdn.org/js/painter"]', d.head)) { - return cb(); - } else { - style = $.el('link', { - rel: 'stylesheet', - href: "//s.4cdn.org/css/painter." + (Date.now()) + ".css" - }); - script = $.el('script', { - src: "//s.4cdn.org/js/painter.min." + (Date.now()) + ".js" - }); - n = 0; - onload = function() { - if (++n === 2) { - return cb(); - } - }; - $.on(style, 'load', onload); - $.on(script, 'load', onload); - return $.add(d.head, [style, script]); - } - }, - draw: function() { - return $.global(function() { - var FCX, Tegaki; - Tegaki = window.Tegaki, FCX = window.FCX; - if (Tegaki.bg) { - Tegaki.destroy(); - } - FCX.oekakiName = 'tegaki.png'; - return Tegaki.open({ - onDone: FCX.oekakiCB, - onCancel: function() { - return Tegaki.bgColor = '#ffffff'; - }, - width: +document.querySelector('#qr [name=oekaki-width]').value, - height: +document.querySelector('#qr [name=oekaki-height]').value, - bgColor: document.querySelector('#qr [name=oekaki-bg]').checked ? document.querySelector('#qr [name=oekaki-bgcolor]').value : 'transparent' - }); - }); - }, - button: function() { - if (QR.selected.file) { - return QR.oekaki.edit(); - } else { - return QR.oekaki.toggle(); - } - }, - edit: function() { - return QR.oekaki.load(function() { - return $.global(function() { - var FCX, Tegaki, cb, error, name, source; - Tegaki = window.Tegaki, FCX = window.FCX; - name = document.getElementById('qr-filename').value.replace(/\.\w+$/, '') + '.png'; - source = document.getElementById('file-n-submit').dataset.source; - error = function(content) { - return document.dispatchEvent(new CustomEvent('CreateNotification', { - bubbles: true, - detail: { - type: 'warning', - content: content, - lifetime: 20 - } - })); - }; - cb = function(e) { - var file, isVideo; - document.removeEventListener('QRFile', cb, false); - if (!e.detail) { - return error('No file to edit.'); - } - if (!/^(image|video)\//.test(e.detail.type)) { - return error('Not an image.'); - } - isVideo = /^video\//.test(e.detail.type); - file = document.createElement(isVideo ? 'video' : 'img'); - file.addEventListener('error', function() { - return error('Could not open file.', false); - }); - file.addEventListener((isVideo ? 'loadeddata' : 'load'), function() { - if (Tegaki.bg) { - Tegaki.destroy(); - } - FCX.oekakiName = name; - Tegaki.open({ - onDone: FCX.oekakiCB, - onCancel: function() { - return Tegaki.bgColor = '#ffffff'; - }, - width: file.naturalWidth || file.videoWidth, - height: file.naturalHeight || file.videoHeight, - bgColor: 'transparent' - }); - return Tegaki.activeCtx.drawImage(file, 0, 0); - }, false); - return file.src = URL.createObjectURL(e.detail); - }; - if (Tegaki.bg && Tegaki.onDoneCb === FCX.oekakiCB && source === FCX.oekakiLatest) { - FCX.oekakiName = name; - return Tegaki.resume(); - } else { - document.addEventListener('QRFile', cb, false); - return document.dispatchEvent(new CustomEvent('QRGetFile', { - bubbles: true - })); - } - }); - }); - }, - toggle: function() { - return QR.oekaki.load(function() { - return QR.nodes.oekaki.hidden = !QR.nodes.oekaki.hidden; - }); - } - }; - - QR.persona = { - pwd: '', - always: {}, - init: function() { - QR.persona.getPassword(); - return $.get('QR.personas', Conf['QR.personas'], function(arg) { - var arr, item, k, len1, personas, ref, type, types; - personas = arg['QR.personas']; - types = { - name: [], - email: [], - sub: [] - }; - ref = personas.split('\n'); - for (k = 0, len1 = ref.length; k < len1; k++) { - item = ref[k]; - 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, ref, ref1, ref2, type, val; - 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 k, len1, list, val; - list = $("#list-" + type, QR.nodes.el); - for (k = 0, len1 = arr.length; k < len1; k++) { - val = arr[k]; - 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 - }; - return $.set('QR.persona', persona); - }); - } - }; - - QR.post = (function() { - function _Class(select) { - this.select = bind(this.select, this); - var el, event, k, label, len1, len2, prev, q, ref, ref1; - el = $.el('a', { - className: 'qr-preview', - draggable: true, - href: 'javascript:;' - }); - $.extend(el, { - innerHTML: "" - }); - this.nodes = { - el: el, - rm: el.firstChild, - spoiler: $('.qr-preview-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.spoiler, 'change', (function(_this) { - return function(e) { - _this.spoiler = e.target.checked; - if (_this === QR.selected) { - return QR.nodes.spoiler.checked = _this.spoiler; - } - }; - })(this)); - ref = $$('label', el); - for (k = 0, len1 = ref.length; k < len1; k++) { - label = ref[k]; - $.on(label, 'click', function(e) { - return e.stopPropagation(); - }); - } - $.add(QR.nodes.dumpList, el); - ref1 = ['dragStart', 'dragEnter', 'dragLeave', 'dragOver', 'dragEnd', 'drop']; - for (q = 0, len2 = ref1.length; q < len2; q++) { - event = ref1[q]; - $.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 : ''; - _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); - URL.revokeObjectURL(this.URL); - return this.dismissErrors(); - }; - - _Class.prototype.lock = function(lock) { - var k, len1, name, node, ref; - if (lock == null) { - lock = true; - } - this.isLocked = lock; - if (this !== QR.selected) { - return; - } - ref = ['thread', 'name', 'email', 'sub', 'com', 'fileButton', 'filename', 'spoiler']; - for (k = 0, len1 = ref.length; k < len1; k++) { - name = ref[k]; - if (node = QR.nodes[name]) { - node.disabled = lock; - } - } - this.nodes.rm.style.visibility = lock ? 'hidden' : ''; - 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.removeAttribute('id'); - 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 k, len1, name, node, ref; - ref = ['thread', 'name', 'email', 'sub', 'com', 'filename']; - for (k = 0, len1 = ref.length; k < len1; k++) { - name = ref[k]; - if (!(node = QR.nodes[name])) { - continue; - } - node.value = this[name] || node.dataset["default"] || ''; - } - (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.updateComment(); - 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.saveFilename(); - return this.updateFilename(); - case 'name': - return QR.persona.set(this); - } - }; - - _Class.prototype.forceSave = function() { - var k, len1, name, node, ref; - if (this !== QR.selected) { - return; - } - ref = ['thread', 'name', 'email', 'sub', 'com', 'filename', 'spoiler']; - for (k = 0, len1 = ref.length; k < len1; k++) { - name = ref[k]; - if (!(node = QR.nodes[name])) { - continue; - } - this.save(node); - } - }; - - _Class.prototype.setComment = function(com) { - this.com = com || null; - if (this === QR.selected) { - QR.nodes.com.value = this.com; - } - return this.updateComment(); - }; - - _Class.prototype.updateComment = function() { - if (this === QR.selected) { - QR.characterCount(); - } - this.nodes.span.textContent = this.com; - return $.queueTask(function() { - return QR.captcha.onPostChange(); - }); - }; - - _Class.rmErrored = function(e) { - var error, errors, k, len1, post, q, ref; - e.stopPropagation(); - ref = QR.posts; - for (k = ref.length - 1; k >= 0; k += -1) { - post = ref[k]; - if (errors = post.errors) { - for (q = 0, len1 = errors.length; q < len1; q++) { - error = errors[q]; - if (!(doc.contains(error))) { - continue; - } - post.rm(); - break; - } - } - } - }; - - _Class.prototype.error = function(className, message) { - var div, ref, rm, rmAll; - div = $.el('div', { - className: className - }); - $.extend(div, { - innerHTML: E(message) + "
      [delete] [delete all]" - }); - (this.errors || (this.errors = [])).push(div); - ref = $$('a', div), rm = ref[0], rmAll = ref[1]; - $.on(div, 'click', (function(_this) { - return function() { - if (indexOf.call(QR.posts, _this) >= 0) { - return _this.select(); - } - }; - })(this)); - $.on(rm, 'click', (function(_this) { - return function(e) { - e.stopPropagation(); - if (indexOf.call(QR.posts, _this) >= 0) { - return _this.rm(); - } - }; - })(this)); - $.on(rmAll, 'click', QR.post.rmErrored); - return QR.error(div, true); - }; - - _Class.prototype.fileError = function(message) { - return this.error('file-error', this.filename + ": " + message); - }; - - _Class.prototype.dismissErrors = function(test) { - var error, k, len1, ref; - if (test == null) { - test = function() { - return true; - }; - } - if (this.errors) { - ref = this.errors; - for (k = 0, len1 = ref.length; k < len1; k++) { - error = ref[k]; - if (doc.contains(error) && test(error)) { - error.parentNode.previousElementSibling.click(); - } - } - } - }; - - _Class.prototype.setFile = function(file1) { - var ext, ref; - this.file = file1; - if (Conf['Randomize Filename'] && g.BOARD.ID !== 'f') { - this.filename = "" + (Date.now() - Math.floor(Math.random() * 365 * $.DAY)); - if (ext = this.file.name.match(QR.validExtension)) { - this.filename += ext[0]; - } - } else { - this.filename = this.file.name; - } - this.filesize = $.bytesToString(this.file.size); - this.checkSize(); - $.addClass(this.nodes.el, 'has-file'); - $.queueTask(function() { - return QR.captcha.onPostChange(); - }); - URL.revokeObjectURL(this.URL); - this.saveFilename(); - if (this === QR.selected) { - this.showFileData(); - } else { - this.updateFilename(); - } - this.nodes.el.style.backgroundImage = null; - if (ref = this.file.type, indexOf.call(QR.mimeTypes, ref) < 0) { - return this.fileError('Unsupported file type.'); - } else if (/^(image|video)\//.test(this.file.type)) { - return this.readFile(); - } - }; - - _Class.prototype.checkSize = function() { - var max; - max = QR.max_size; - if (/^video\//.test(this.file.type)) { - max = Math.min(max, QR.max_size_video); - } - if (this.file.size > max) { - return this.fileError("File too large (file: " + this.filesize + ", max: " + ($.bytesToString(max)) + ")."); - } - }; - - _Class.prototype.readFile = function() { - var el, event, isVideo, onerror, onload; - isVideo = /^video\//.test(this.file.type); - el = $.el(isVideo ? 'video' : 'img'); - if (isVideo && !el.canPlayType(this.file.type)) { - return; - } - event = isVideo ? 'loadeddata' : 'load'; - onload = (function(_this) { - return function() { - $.off(el, event, onload); - $.off(el, 'error', onerror); - _this.checkDimensions(el); - return _this.setThumbnail(el); - }; - })(this); - onerror = (function(_this) { - return function() { - $.off(el, event, onload); - $.off(el, 'error', onerror); - _this.fileError((isVideo ? 'Video' : 'Image') + " appears corrupt"); - return URL.revokeObjectURL(el.src); - }; - })(this); - $.on(el, event, onload); - $.on(el, 'error', onerror); - return el.src = URL.createObjectURL(this.file); - }; - - _Class.prototype.checkDimensions = function(el) { - var duration, height, max_height, max_width, ref, videoHeight, videoWidth, width; - if (el.tagName === 'IMG') { - height = el.height, width = el.width; - if (height > QR.max_height || width > QR.max_width) { - this.fileError("Image too large (image: " + height + "x" + width + "px, max: " + QR.max_height + "x" + QR.max_width + "px)"); - } - if (height < QR.min_height || width < QR.min_width) { - return this.fileError("Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); - } - } else { - videoHeight = el.videoHeight, videoWidth = el.videoWidth, duration = el.duration; - max_height = Math.min(QR.max_height, QR.max_height_video); - max_width = Math.min(QR.max_width, QR.max_width_video); - if (videoHeight > max_height || videoWidth > max_width) { - this.fileError("Video too large (video: " + videoHeight + "x" + videoWidth + "px, max: " + max_height + "x" + max_width + "px)"); - } - if (videoHeight < QR.min_height || videoWidth < QR.min_width) { - this.fileError("Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); - } - if (!isFinite(duration)) { - this.fileError('Video lacks duration metadata (try remuxing)'); - } else if (duration > QR.max_duration_video) { - this.fileError("Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)"); - } - if (((ref = g.BOARD.ID) !== 'gif' && ref !== 'wsg') && $.hasAudio(el)) { - return this.fileError('Audio not allowed'); - } - } - }; - - _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.removeAttribute('title'); - QR.nodes.filename.removeAttribute('title'); - this.nodes.el.style.backgroundImage = null; - $.rmClass(this.nodes.el, 'has-file'); - this.showFileData(); - URL.revokeObjectURL(this.URL); - return this.dismissErrors(function(error) { - return $.hasClass(error, 'file-error'); - }); - }; - - _Class.prototype.saveFilename = function() { - this.file.newName = (this.filename || '').replace(/[\/\\]/g, '-'); - if (!QR.validExtension.test(this.filename)) { - return this.file.newName += "." + (QR.extensionFromType[this.file.type] || 'jpg'); - } - }; - - _Class.prototype.updateFilename = function() { - var long; - long = this.filename + " (" + this.filesize + ")"; - this.nodes.el.title = long; - if (this !== QR.selected) { - return; - } - return QR.nodes.filename.title = long; - }; - - _Class.prototype.showFileData = function() { - var ref; - if (this.file) { - this.updateFilename(); - QR.nodes.filename.value = this.filename; - $.addClass(QR.nodes.oekaki, 'has-file'); - $.addClass(QR.nodes.fileSubmit, 'has-file'); - } else { - $.rmClass(QR.nodes.oekaki, 'has-file'); - $.rmClass(QR.nodes.fileSubmit, 'has-file'); - } - if (((ref = this.file) != null ? ref.source : void 0) != null) { - QR.nodes.fileSubmit.dataset.source = this.file.source; - } else { - QR.nodes.fileSubmit.removeAttribute('data-source'); - } - return QR.nodes.spoiler.checked = this.spoiler; - }; - - _Class.prototype.pasteText = function(file) { - var reader; - this.pasting = true; - reader = new FileReader(); - reader.onload = (function(_this) { - return function(e) { - var result; - result = e.target.result; - _this.setComment((_this.com ? _this.com + "\n" + result : result)); - return delete _this.pasting; - }; - })(this); - return reader.readAsText(file); - }; - - _Class.prototype.dragStart = function(e) { - var left, ref, top; - ref = this.getBoundingClientRect(), left = ref.left, top = ref.top; - e.dataTransfer.setDragImage(this, e.clientX - left, e.clientY - top); - 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, k, lc, len1, ref, ref1, type; - if (!((Conf['Fappe Tyme'] || Conf['Werk Tyme']) && ((ref = g.VIEW) === 'index' || ref === 'thread'))) { - return; - } - this.nodes = {}; - this.enabled = { - fappe: false, - werk: Conf['werk'] - }; - ref1 = ["Fappe", "Werk"]; - for (k = 0, len1 = ref1.length; k < len1; k++) { - type = ref1[k]; - 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() { - return this.nodes.root.classList.toggle('noFile', !this.file); - }, - 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() { - var ref; - if (!((ref = this.file) != null ? ref.thumb : void 0)) { - 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, k, key, len1, len2, menuButton, nodes, post, q, ref, ref1, ref2, ref3, thumb, value; - cb = Gallery.cb; - 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: "
      " - }); - 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'); - $.on(nodes.frame, 'click', cb.blank); - if (Conf['Mouse Wheel Volume']) { - $.on(nodes.frame, 'wheel', Volume.wheel); - } - $.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 (k = 0, len1 = ref1.length; k < len1; k++) { - entry = ref1[k]; - entry.order = 0; - nodes.menu.addEntry(entry); - } - $.on(d, 'keydown', cb.keybinds); - if (Conf['Keybinds']) { - $.off(d, 'keydown', Keybinds.keydown); - } - $.on(window, 'resize', Gallery.cb.setHeight); - ref2 = $$('.post .file'); - for (q = 0, len2 = ref2.length; q < len2; q++) { - file = ref2[q]; - post = Get.postFromNode(file); - if (!((ref3 = post.file) != null ? ref3.thumb : void 0)) { - 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.thumb && (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); - }, - load: function(thumb, errorCB) { - var elType, ext, file; - ext = thumb.href.match(/\w*$/); - elType = { - 'webm': 'video', - 'pdf': 'iframe' - }[ext] || 'img'; - file = $.el(elType, { - title: thumb.title - }); - $.extend(file.dataset, thumb.dataset); - $.on(file, 'error', errorCB); - file.src = thumb.href; - return file; - }, - open: function(thumb) { - var el, file, newID, nodes, oldID, post, ref; - nodes = Gallery.nodes; - oldID = +nodes.current.dataset.id; - newID = +thumb.dataset.id; - if (el = Gallery.images[oldID]) { - $.rmClass(el, 'gal-highlight'); - } - $.addClass(thumb, 'gal-highlight'); - nodes.thumbs.scrollTop = thumb.offsetTop + thumb.offsetHeight / 2 - nodes.thumbs.clientHeight / 2; - if (((ref = Gallery.cache) != null ? ref.dataset.id : void 0) === '' + newID) { - file = Gallery.cache; - $.off(file, 'error', Gallery.cacheError); - $.on(file, 'error', Gallery.error); - } else { - file = Gallery.load(thumb, Gallery.error); - } - $.off(nodes.current, 'error', Gallery.error); - ImageCommon.pause(nodes.current); - $.replace(nodes.current, file); - nodes.current = file; - if (file.nodeName === 'VIDEO') { - file.loop = true; - Volume.setup(file); - if (Conf['Autoplay']) { - file.play(); - } - if (Conf['Show Controls']) { - ImageCommon.addControls(file); - } - } - doc.classList.toggle('gal-pdf', file.nodeName === 'IFRAME'); - Gallery.cb.setHeight(); - nodes.count.textContent = +thumb.dataset.id + 1; - nodes.name.download = nodes.name.textContent = thumb.title; - nodes.name.href = thumb.href; - nodes.frame.scrollTop = 0; - nodes.next.focus(); - if (Gallery.slideshow && (newID > oldID || (oldID === Gallery.images.length - 1 && newID === 0))) { - Gallery.setupTimer(); - } else { - Gallery.cb.stop(); - } - if (Conf['Scroll to Post'] && (post = g.posts[file.dataset.post])) { - Header.scrollTo(post.nodes.root); - } - if (isNaN(oldID) || newID === (oldID + 1) % Gallery.images.length) { - return Gallery.cache = Gallery.load(Gallery.images[(newID + 1) % Gallery.images.length], Gallery.cacheError); - } - }, - 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)); - }, - cacheError: function() { - return delete Gallery.cache; - }, - 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 (!Conf['Autoplay'] && 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); - } - $.off(window, 'resize', Gallery.cb.setHeight); - return clearTimeout(Gallery.timeoutID); - }, - setFitness: function() { - return (this.checked ? $.addClass : $.rmClass)(doc, "gal-" + (this.name.toLowerCase().replace(/\s+/g, '-'))); - }, - setHeight: $.debounce(100, function() { - var current, dim, frame, height, minHeight, ref, ref1, ref2, style, width; - ref = Gallery.nodes, current = ref.current, frame = ref.frame; - style = current.style; - if (Conf['Stretch to Fit'] && (dim = (ref1 = g.posts[current.dataset.post]) != null ? ref1.file.dimensions : void 0)) { - ref2 = dim.split('x'), width = ref2[0], height = ref2[1]; - minHeight = Math.min(doc.clientHeight - 25, height / width * frame.clientWidth); - style.minHeight = minHeight + 'px'; - return style.minWidth = (width / height * minHeight) + 'px'; - } else { - return style.minHeight = style.minWidth = null; - } - }), - 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 === 'Hide Thumbnails' || name === 'Fit Width' || name === 'Fit Height') { - $.on(input, 'change', Gallery.cb.setFitness); - } - $.event('change', null, input); - $.on(input, 'change', $.cb.checked); - if (name === 'Hide Thumbnails' || name === 'Fit Width' || name === 'Fit Height' || name === 'Stretch to Fit') { - $.on(input, 'change', Gallery.cb.setHeight); - } - return { - el: label - }; - }, - createSubEntries: function() { - var delayInput, delayLabel, item, subEntries; - subEntries = (function() { - var k, len1, ref, results; - ref = ['Hide Thumbnails', 'Fit Width', 'Fit Height', 'Stretch to Fit', 'Scroll to Post']; - results = []; - for (k = 0, len1 = ref.length; k < len1; k++) { - item = ref[k]; - results.push(Gallery.menu.createSubEntry(item)); - } - return results; - })(); - delayLabel = $.el('label', { - innerHTML: "Slide Delay: " - }); - 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 k, len1, postObj, ref; - if (this.status === 404) { - post.kill(); - } - if (this.status !== 200) { - return redirect(); - } - ref = this.response.posts; - for (k = 0, len1 = ref.length; k < len1; k++) { - postObj = ref[k]; - 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 $.engine !== 'gecko' || (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: " contract" - }); - 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 (!Conf['Autoplay'] && ((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 k, len1, ref; - ref = [post].concat(slice.call(post.clones)); - for (k = 0, len1 = ref.length; k < len1; k++) { - post = ref[k]; - toggle(post); - } - }); - }, - playVideos: function() { - return g.posts.forEach(function(post) { - var file, k, len1, ref, video, visible; - ref = [post].concat(slice.call(post.clones)); - for (k = 0, len1 = ref.length; k < len1; k++) { - post = ref[k]; - 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, k, len1, oldHeight, ref, ref1, scrollY, top, x; - 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'); - $.rm(file.videoControls); - file.thumb.parentNode.href = file.url; - file.thumb.parentNode.target = '_blank'; - ref = ['isExpanding', 'isExpanded', 'videoControls', 'wasPlaying', 'scrollIntoView']; - for (k = 0, len1 = ref.length; k < len1; k++) { - x = ref[k]; - 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, ref, thumb; - 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 = Math.min(doc.clientHeight - file.fullImage.getBoundingClientRect().bottom - 25, Header.getBottomOf(file.fullImage)); - 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, ref, subEntries; - 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; - } - return $.on(this.file.thumb, 'mouseover', ImageHover.mouseover(this)); - }, - catalogNode: function() { - var file; - file = this.thread.OP.file; - if (!(file && (file.isImage || file.isVideo))) { - return; - } - return $.on(this.nodes.thumb, 'mouseover', ImageHover.mouseover(this.thread.OP)); - }, - mouseover: function(post) { - return function(e) { - var el, error, file, height, isVideo, left, maxHeight, maxWidth, ref, ref1, ref2, right, scale, width, x; - 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 k, len1, ref1, results; - ref1 = file.dimensions.split('x'); - results = []; - for (k = 0, len1 = ref1.length; k < len1; k++) { - x = ref1[k]; - results.push(+x); - } - return results; - })(), width = ref1[0], height = ref1[1]; - ref2 = this.getBoundingClientRect(), left = ref2.left, right = ref2.right; - maxWidth = Math.max(left, doc.clientWidth - right); - maxHeight = doc.clientHeight - UI.hover.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', - height: scale * height, - 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)); - }; - } - }; - - 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: " Prefetch Images" - }); - this.el = prefetch.firstElementChild; - $.on(this.el, 'change', this.toggle); - return Header.menu.addEntry({ - el: prefetch, - order: 98 - }); - }, - 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, k, len1, ref, thumb, video; - file = post.file; - thumb = file.thumb; - video = $.el('video', { - preload: 'none', - loop: true, - muted: true, - poster: thumb.src || thumb.dataset.src, - textContent: thumb.alt, - className: thumb.className - }); - video.setAttribute('muted', 'muted'); - video.dataset.md5 = thumb.dataset.md5; - ref = ['height', 'width', 'maxHeight', 'maxWidth']; - for (k = 0, len1 = ref.length; k < len1; k++) { - attr = ref[k]; - video.style[attr] = thumb.style[attr]; - } - video.src = file.url; - $.replace(thumb, video); - file.thumb = video; - return file.videoThumb = true; - }, - prefetch: function(post) { - var clone, el, file, isImage, isVideo, k, len1, match, ref, replace, thumb, type, url; - 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 || thumb.dataset.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 (k = 0, len1 = ref.length; k < len1; k++) { - clone = ref[k]; - clone.file.thumb.preload = 'auto'; - } - thumb.preload = 'auto'; - if ($.engine === 'gecko') { - $.on(thumb, 'loadeddata', function() { - return this.removeAttribute('poster'); - }); - } - return; - } - el = $.el(isImage ? 'img' : 'video'); - if (replace && isImage) { - $.on(el, 'load', function() { - var len2, q, ref1; - ref1 = post.clones; - for (q = 0, len2 = ref1.length; q < len2; q++) { - clone = ref1[q]; - clone.file.thumb.src = url; - } - thumb.src = url; - return thumb.removeAttribute('data-src'); - }); - } - 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 k, len1, ref1, ref2, thumb; - ref1 = [post].concat(slice.call(post.clones)); - for (k = 0, len1 = ref1.length; k < len1; k++) { - post = ref1[k]; - 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: "" - }); - $.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; - if (!(!this.isClone && this.file && this.file.thumb && this.file.isSpoiler)) { - return; - } - thumb = this.file.thumb; - thumb.removeAttribute('style'); - thumb.style.maxHeight = thumb.style.maxWidth = this.isReply ? '125px' : '250px'; - if (thumb.src) { - return thumb.src = this.file.thumbURL; - } else { - return thumb.dataset.src = this.file.thumbURL; - } - } - }; - - Sauce = { - init: function() { - var err, k, len1, link, links, ref, ref1; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Sauce'])) { - return; - } - links = []; - ref1 = Conf['sauces'].split('\n'); - for (k = 0, len1 = ref1.length; k < len1; k++) { - link = ref1[k]; - 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', - className: 'sauce' - }); - return Post.callbacks.push({ - name: 'Sauce', - cb: this.node - }); - }, - sandbox: function(url) { - return E.url({ - innerHTML: "[sb] " + E(url) + "" - }); - }, - rmOrigin: function(e) { - if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) { - return; - } - $.open(this.href); - return e.preventDefault(); - }, - createSauceLink: function(link, post) { - var a, ext, i, k, key, len1, m, part, parts, ref, ref1, ref2, skip, url; - if (!(link = link.trim())) { - return null; - } - parts = {}; - ref = link.split(/;(?=(?:text|boards|types|sandbox):?)/); - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - 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) || '?'); - ext = post.file.url.match(/[^.]*$/)[0]; - skip = false; - for (key in parts) { - parts[key] = parts[key].replace(/%(T?URL|IMG|[sh]?MD5|board|name|%|semi)/g, function(_, parameter) { - var type; - type = Sauce.formatters[parameter](post, ext); - if (type == null) { - skip = true; - return ''; - } - if (key === 'url' && (parameter !== '%' && parameter !== 'semi')) { - if (/^javascript:/i.test(parts['url'])) { - type = JSON.stringify(type); - } - type = encodeURIComponent(type); - } - return type; - }); - } - if (skip) { - return null; - } - if (!(!parts['boards'] || (ref2 = post.board.ID, indexOf.call(parts['boards'].split(','), ref2) >= 0))) { - return null; - } - if (!(!parts['types'] || indexOf.call(parts['types'].split(','), ext) >= 0)) { - return null; - } - url = parts['url']; - if (parts['sandbox'] != null) { - url = Sauce.sandbox(url); - } - a = Sauce.link.cloneNode(true); - a.href = url; - a.textContent = parts['text']; - if (/^javascript:/i.test(parts['url'])) { - a.removeAttribute('target'); - } - if (parts['sandbox'] != null) { - $.on(a, 'click', Sauce.rmOrigin); - } - return a; - }, - node: function() { - var k, len1, link, node, nodes, ref; - if (this.isClone || !this.file) { - return; - } - nodes = []; - ref = Sauce.links; - for (k = 0, len1 = ref.length; k < len1; k++) { - link = ref[k]; - if (node = Sauce.createSauceLink(link, this)) { - nodes.push($.tn('\u00A0'), node); - } - } - return $.add(this.file.text, nodes); - }, - formatters: { - TURL: function(post) { - return post.file.thumbURL; - }, - URL: function(post) { - return post.file.url; - }, - IMG: function(post, ext) { - if (ext === 'gif' || ext === 'jpg' || ext === 'png') { - return post.file.url; - } else { - return post.file.thumbURL; - } - }, - MD5: function(post) { - return post.file.MD5; - }, - sMD5: function(post) { - var ref; - return (ref = post.file.MD5) != null ? ref.replace(/[+\/=]/g, function(c) { - return { - '+': '-', - '/': '_', - '=': '' - }[c]; - }) : void 0; - }, - hMD5: function(post) { - if (post.file.MD5) { - return ((function() { - var k, len1, ref, results; - ref = atob(post.file.MD5); - results = []; - for (k = 0, len1 = ref.length; k < len1; k++) { - c = ref[k]; - results.push(("0" + (c.charCodeAt(0).toString(16))).slice(-2)); - } - return results; - })()).join(''); - } - }, - board: function(post) { - return post.board.ID; - }, - name: function(post) { - return post.file.name; - }, - '%': function() { - return '%'; - }, - semi: function() { - return ';'; - } - } - }; - - Volume = { - init: function() { - var ref, ref1, unmuteEntry, volumeEntry; - 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 (Conf['Mouse Wheel Volume']) { - Post.callbacks.push({ - name: 'Mouse Wheel Volume', - cb: this.node - }); - } - if ((ref1 = g.BOARD.ID) !== 'gif' && ref1 !== 'wsg') { - return; - } - if (Conf['Mouse Wheel Volume']) { - CatalogThread.callbacks.push({ - name: 'Mouse Wheel Volume', - cb: this.catalogNode - }); - } - 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: " 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, key, muted, val, volume; - muted = this.muted, volume = this.volume; - items = { - 'Allow Sound': !muted, - 'Default Volume': volume - }; - for (key in items) { - val = items[key]; - if (Conf[key] === val) { - delete items[key]; - } - } - $.set(items); - $.extend(Conf, items); - if (Volume.inputs) { - Volume.inputs.unmute.checked = !muted; - return Volume.inputs.volume.value = volume; - } - }, - node: function() { - var ref, ref1; - if (!(((ref = this.board.ID) === 'gif' || ref === 'wsg') && ((ref1 = this.file) != null ? ref1.isVideo : void 0))) { - return; - } - $.on(this.file.thumb, 'wheel', Volume.wheel.bind(Header.hover)); - return $.on($('a', this.file.text), 'wheel', Volume.wheel.bind(this.file.thumb.parentNode)); - }, - catalogNode: function() { - var file; - file = this.thread.OP.file; - if (!(file != null ? file.isVideo : void 0)) { - return; - } - return $.on(this.nodes.thumb, 'wheel', Volume.wheel.bind(Header.hover)); - }, - wheel: function(e) { - var el, volume; - if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) { - return; - } - if (!(el = $('video:not([data-md5])', this))) { - 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(); - } - }; - - Embedding = { - init: function() { - var k, len1, ref, type; - if (!(Conf['Embedding'] || Conf['Link Title'])) { - return; - } - this.types = {}; - ref = this.ordered_types; - for (k = 0, len1 = ref.length; k < len1; k++) { - type = ref[k]; - this.types[type.key] = type; - } - if (Conf['Floating Embeds']) { - this.dialog = UI.dialog('embedding', 'top: 50px; right: 0px;', { - innerHTML: "
      " - }); - this.media = $('#media-embed', this.dialog); - $.one(d, '4chanXInitFinished', this.ready); - } - if (Conf['Link Title']) { - return $.on(d, '4chanXInitFinished PostsInserted', function() { - var key, ref1, ref2, service; - 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, k, len1, match, ref, type; - href = link.href; - ref = Embedding.ordered_types; - for (k = 0, len1 = ref.length; k < len1; k++) { - type = ref[k]; - if (!(match = type.regExp.exec(href))) { - continue; - } - if (type.dummy) { - return; - } - return { - key: type.key, - uid: match[1], - options: match[2], - link: link - }; - } - }, - embed: function(data) { - var embed, href, key, link, name, options, post, ref, uid, value; - key = data.key, uid = data.uid, options = data.options, link = data.link, post = data.post; - href = link.href; - if (Embedding.types[key].httpOnly && location.protocol !== 'http:') { - return; - } - $.addClass(link, key.toLowerCase()); - embed = $.el('a', { - className: 'embedder', - href: 'javascript:;', - textContent: '(embed)' - }); - ref = { - key: key, - uid: uid, - options: options, - href: href - }; - for (name in ref) { - value = ref[name]; - embed.dataset[name] = value; - } - $.on(embed, 'click', Embedding.cb.toggle); - $.after(link, [$.tn(' '), embed]); - if (Conf['Auto-embed'] && !Conf['Floating Embeds'] && !post.isFetchedQuote && key !== 'TwitchTV') { - 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; - } - $.addClass(link, key.toLowerCase()); - 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) + "] Title Link Blocked (are you using NoScript?)" - }); - } - } - }, - flushTitles: function(service) { - var cb, data, k, len1, queue; - queue = service.queue; - if (!(queue != null ? queue.length : void 0)) { - return; - } - service.queue = []; - cb = function() { - var data, k, len1; - for (k = 0, len1 = queue.length; k < len1; k++) { - data = queue[k]; - Embedding.cb.title(this, data); - } - }; - if (!$.cache(service.api((function() { - var k, len1, results; - results = []; - for (k = 0, len1 = queue.length; k < len1; k++) { - data = queue[k]; - results.push(data.uid); - } - return results; - })()), cb, { - responseType: 'json' - })) { - for (k = 0, len1 = queue.length; k < len1; k++) { - data = queue[k]; - $.extend(data.link, { - innerHTML: "[" + E(data.key) + "] Title Link Blocked (are you using NoScript?)" - }); - } - } - }, - 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: none; width: 640px; height: 360px;'; - return container; - }, - title: function(req, data) { - var base1, k, key, len1, len2, link, link2, options, post, post2, q, ref, ref1, service, status, text, uid; - 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 (k = 0, len1 = ref.length; k < len1; k++) { - post2 = ref[k]; - ref1 = $$('a.linkify', post2.nodes.comment); - for (q = 0, len2 = ref1.length; q < len2; q++) { - link2 = ref1[q]; - if (!(link2.href === link.href)) { - continue; - } - if ((base1 = link2.dataset).original == null) { - base1.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.dataset.href - }); - } - }, { - key: 'Dailymotion', - regExp: /^\w+:\/\/(?:(?:www\.)?dailymotion\.com\/(?:embed\/)?video|dai\.ly)\/([A-Za-z0-9]+)[^?]*(.*)/, - el: function(a) { - var el, options, start; - options = (start = a.dataset.options.match(/[?&](start=\d+)/)) ? "?" + start[1] : ''; - el = $.el('iframe', { - src: "//www.dailymotion.com/embed/video/" + a.dataset.uid + options - }); - el.setAttribute("allowfullscreen", "true"); - return el; - }, - title: { - api: function(uid) { - return "https://api.dailymotion.com/video/" + uid; - }, - text: function(_) { - return _.title; - } - } - }, { - 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: "" + E(a.dataset.uid) + "" - }; - el.src = E.url(content); - 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: "" - }); - } - }, { - 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', { - src: "http://www.liveleak.com/ll_embed?i=" + a.dataset.uid - }); - el.setAttribute("allowfullscreen", "true"); - 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)?)/, - style: 'border: 0; width: 600px; height: 406px;', - el: function(a) { - return $.el('iframe', { - src: "//strawpoll.me/embed_1/" + a.dataset.uid - }); - } - }, { - key: 'TwitchTV', - regExp: /^\w+:\/\/(?:www\.)?twitch\.tv\/(\w[^#\&\?]*)/, - style: "border: none; width: 620px; height: 378px;", - el: function(a) { - var _, channel, flashvars, id, idprefix, k, len1, obj, part, ref, result, seconds, start, type; - if (result = /(\w+)\/([bcv])\/(\d+)/i.exec(a.dataset.uid)) { - _ = result[0], channel = result[1], type = result[2], id = result[3]; - idprefix = type === 'b' ? 'a' : type; - flashvars = "channel=" + channel + "&start_volume=25&auto_play=false&videoId=" + idprefix + id; - if (start = a.dataset.href.match(/\bt=(\w+)/)) { - seconds = 0; - ref = start[1].match(/\d+[hms]/g); - for (k = 0, len1 = ref.length; k < len1; k++) { - part = ref[k]; - seconds += +part.slice(0, -1) * { - 'h': 3600, - 'm': 60, - 's': 1 - }[part.slice(-1)]; - } - flashvars += "&initial_time=" + seconds; - } - } else { - channel = (/(\w+)/.exec(a.dataset.uid))[0]; - flashvars = "channel=" + channel + "&start_volume=25&auto_play=false"; - } - obj = $.el('object', { - data: '//www-cdn.jtvnw.net/swflibs/TwitchPlayer.swf' - }); - $.extend(obj, { - innerHTML: "" - }); - obj.children[1].value = flashvars; - return obj; - } - }, { - key: 'Vocaroo', - regExp: /^\w+:\/\/(?:www\.)?vocaroo\.com\/i\/(\w+)/, - style: '', - el: function(a) { - var el, type; - el = $.el('audio', { - controls: true, - preload: 'auto' - }); - type = el.canPlayType('audio/webm') ? 'webm' : 'mp3'; - el.src = "http://vocaroo.com/media_command.php?media=" + a.dataset.uid + "&command=download_" + type; - return el; - } - }, { - 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=https://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=|\bembed\/|\bv\/))([\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, k, len1, ref; - ref = data.items; - for (k = 0, len1 = ref.length; k < len1; k++) { - item = ref[k]; - if (item.id === uid) { - return item.snippet.title; - } - } - return 'Not Found'; - } - } - }, { - key: 'Loopvid', - regExp: /^\w+:\/\/(?:www\.)?loopvid.appspot.com\/#?((?:pf|kd|lv|gd|gh|db|dx|nn|cp|wu|ig|ky|mf|pc|gc)\/[\w\-\/]+(,[\w\-\/]+)*|fc\/\w+\/\d+)/, - style: 'max-width: 80vw; max-height: 80vh;', - el: function(a) { - var _, base, el, host, k, len1, len2, name, names, q, ref, ref1, type, types, url; - el = $.el('video', { - controls: true, - preload: 'auto', - loop: true - }); - ref = a.dataset.uid.match(/(\w+)\/(.*)/), _ = ref[0], host = ref[1], names = ref[2]; - types = (function() { - switch (host) { - case 'gd': - case 'wu': - case 'fc': - return ['']; - case 'gc': - return ['giant', 'fat', 'zippy']; - default: - return ['.webm', '.mp4']; - } - })(); - ref1 = names.split(','); - for (k = 0, len1 = ref1.length; k < len1; k++) { - name = ref1[k]; - for (q = 0, len2 = types.length; q < len2; q++) { - type = types[q]; - base = "" + name + type; - url = (function() { - switch (host) { - case 'pf': - return "https://web.archive.org/web/2/http://a.pomf.se/" + base; - case 'kd': - return "http://kastden.org/loopvid/" + base; - case 'lv': - return "http://kastden.org/_loopvid_media/lv/" + 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://dl.dropboxusercontent.com/u/" + base; - case 'dx': - return "https://dl.dropboxusercontent.com/" + base; - case 'nn': - return "http://naenara.eu/loopvids/" + base; - case 'cp': - return "https://copy.com/" + base; - case 'wu': - return "http://webmup.com/" + base + "/vid.webm"; - case 'ig': - return "https://i.imgur.com/" + base; - case 'ky': - return "https://kiyo.me/" + base; - case 'mf': - return "https://d.maxfile.ro/" + base; - case 'pc': - return "http://a.pomf.cat/" + base; - case 'fc': - return "//i.4cdn.org/" + base + ".webm"; - case 'gc': - return "https://" + type + ".gfycat.com/" + name + ".webm"; - } - })(); - $.add(el, $.el('source', { - src: url - })); - } - } - return el; - } - }, { - key: 'Clyp', - regExp: /^\w+:\/\/(?:www\.)?clyp\.it\/(\w+)/, - style: '', - el: function(a) { - var el, type; - el = $.el('audio', { - controls: true, - preload: 'auto' - }); - type = el.canPlayType('audio/ogg') ? 'ogg' : 'mp3'; - el.src = "https://clyp.it/" + a.dataset.uid + "." + type; - return el; - } - }, { - 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.dataset.href, - loop: /^https?:\/\/i\.4cdn\.org\//.test(a.dataset.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 k, len1, len2, link, links, q, ref; - if (this.isClone) { - return Embedding.events(this); - } - if (!Linkify.regString.test(this.info.comment)) { - return; - } - ref = $$('a[href^="http://i.4cdn.org/"], a[href^="https://i.4cdn.org/"]', this.nodes.comment); - for (k = 0, len1 = ref.length; k < len1; k++) { - link = ref[k]; - $.addClass(link, 'linkify'); - Embedding.process(link, this); - } - links = Linkify.process(this.nodes.comment); - for (q = 0, len2 = links.length; q < len2; q++) { - link = links[q]; - 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, part1, part2, ref, ref1, 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') { - if ((part1 = word.match(/(https?:\/\/)?([a-z\d-]+\.)*[a-z\d-]+$/i)) && (part2 = (ref = snapshot.snapshotItem(i)) != null ? (ref1 = ref.data) != null ? ref1.match(/^(\.[a-z\d-]+)*\//i) : void 0 : void 0) && (part1[0] + part2[0]).search(Linkify.regString) === 0) { - continue; - } else { - 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|xyz|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, encodedDomain, 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; - } - if (encodedDomain = text.match(/^(https?:\/\/[^\/]*%[0-9a-f]{2})(.*)$/i)) { - text = encodedDomain[1].replace(/%([0-9a-f]{2})/ig, function(x, y) { - if (y === '25') { - return x; - } else { - return String.fromCharCode(parseInt(y, 16)); - } - }) + encodedDomain[2]; - } - a = $.el('a', { - className: 'linkify', - rel: 'nofollow noreferrer', - target: '_blank', - href: text - }); - $.add(a, range.extractContents()); - range.insertNode(a); - return a; - } - }; - - ArchiveLink = { - init: function() { - var div, entry, k, len1, ref, ref1, type; - 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'], ['Capcode', 'capcode'], ['Subject', 'subject'], ['Filename', 'filename'], ['Image MD5', 'MD5']]; - for (k = 0, len1 = ref1.length; k < len1; k++) { - type = ref1[k]; - 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 = { - auto: [{}, {}], - 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:;' - }); - this.nodes = { - menu: div.firstChild, - links: [postEl, fileEl] - }; - postEntry = { - el: postEl, - open: function() { - postEl.textContent = DeleteLink.linkText(false); - $.on(postEl, 'click', DeleteLink.toggle); - return true; - } - }; - fileEntry = { - el: fileEl, - open: function(arg) { - var file; - file = arg.file; - if (!file || file.isDead) { - return false; - } - fileEl.textContent = DeleteLink.linkText(true); - $.on(fileEl, 'click', DeleteLink.toggle); - return true; - } - }; - return Menu.menu.addEntry({ - el: div, - order: 40, - open: function(post) { - if (post.isDead) { - return false; - } - DeleteLink.post = post; - DeleteLink.nodes.menu.textContent = DeleteLink.menuText(); - DeleteLink.cooldown.start(post); - return true; - }, - subEntries: [postEntry, fileEntry] - }); - }, - menuText: function() { - var seconds; - if (seconds = DeleteLink.cooldown.seconds[DeleteLink.post.fullID]) { - return "Delete (" + seconds + ")"; - } else { - return 'Delete'; - } - }, - linkText: function(fileOnly) { - var text; - text = fileOnly ? 'File' : 'Post'; - if (DeleteLink.auto[+fileOnly][DeleteLink.post.fullID]) { - text = "Deleting " + (text.toLowerCase()) + "..."; - } - return text; - }, - toggle: function() { - var auto, fileOnly, post; - post = DeleteLink.post; - fileOnly = $.hasClass(this, 'delete-file'); - auto = DeleteLink.auto[+fileOnly]; - if (auto[post.fullID]) { - delete auto[post.fullID]; - } else { - auto[post.fullID] = true; - } - this.textContent = DeleteLink.linkText(fileOnly); - if (!DeleteLink.cooldown.seconds[post.fullID]) { - return DeleteLink["delete"](post, fileOnly); - } - }, - "delete": function(post, fileOnly) { - var form, link; - link = DeleteLink.nodes.links[+fileOnly]; - delete DeleteLink.auto[+fileOnly][post.fullID]; - if (post.fullID === DeleteLink.post.fullID) { - $.off(link, 'click', DeleteLink.toggle); - } - form = { - mode: 'usrdel', - onlyimgdel: fileOnly, - pwd: QR.persona.getPassword() - }; - form[post.ID] = 'delete'; - 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, post); - } - }, { - form: $.formData(form) - }); - }, - load: function(link, post, fileOnly, resDoc) { - var el, msg; - link.textContent = DeleteLink.linkText(fileOnly); - if (resDoc.title === '4chan - Banned') { - el = $.el('span', { - innerHTML: "You can't delete posts because you are banned." - }); - return new Notice('warning', el, 20); - } else if (msg = resDoc.getElementById('errmsg')) { - new Notice('warning', msg.textContent, 20); - if (post.fullID === DeleteLink.post.fullID) { - $.on(link, 'click', DeleteLink.toggle); - } - if (QR.cooldown.data && Conf['Cooldown'] && /\bwait\b/i.test(msg.textContent)) { - DeleteLink.cooldown.start(post, 5); - DeleteLink.auto[+fileOnly][post.fullID] = true; - return DeleteLink.nodes.links[+fileOnly].textContent = DeleteLink.linkText(fileOnly); - } - } else { - if (!fileOnly) { - QR.cooldown["delete"](post); - } - if (resDoc.title === 'Updating index...') { - (post.origin || post).kill(fileOnly); - } - if (post.fullID === DeleteLink.post.fullID) { - return link.textContent = 'Deleted'; - } - } - }, - error: function(link, post) { - new Notice('warning', 'Connection error, please retry.', 20); - if (post.fullID === DeleteLink.post.fullID) { - return $.on(link, 'click', DeleteLink.toggle); - } - }, - cooldown: { - seconds: {}, - start: function(post, seconds) { - if (DeleteLink.cooldown.seconds[post.fullID] != null) { - return; - } - if (seconds == null) { - seconds = QR.cooldown.secondsDeletion(post); - } - if (seconds > 0) { - DeleteLink.cooldown.seconds[post.fullID] = seconds; - return DeleteLink.cooldown.count(post); - } - }, - count: function(post) { - var fileOnly, k, len1, ref; - if (post.fullID === DeleteLink.post.fullID) { - DeleteLink.nodes.menu.textContent = DeleteLink.menuText(); - } - if (DeleteLink.cooldown.seconds[post.fullID] > 0 && Conf['Cooldown']) { - DeleteLink.cooldown.seconds[post.fullID]--; - setTimeout(DeleteLink.cooldown.count, 1000, post); - } else { - delete DeleteLink.cooldown.seconds[post.fullID]; - ref = [false, true]; - for (k = 0, len1 = ref.length; k < len1; k++) { - fileOnly = ref[k]; - if (DeleteLink.auto[+fileOnly][post.fullID]) { - DeleteLink["delete"](post, fileOnly); - } - } - } - } - } - }; - - 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: "" - }); - 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:;' - }); - $.on(a, 'click', ReportLink.report); - return Menu.menu.addEntry({ - el: a, - order: 10, - open: function(post) { - if (!(post.isDead || (post.thread.isDead && !post.thread.isArchived))) { - a.textContent = 'Report'; - ReportLink.url = "//sys.4chan.org/" + post.board + "/imgboard.php?mode=report&no=" + post; - if ((Conf['Use Recaptcha v1 in Reports'] && Main.jsEnabled) || d.cookie.indexOf('pass_enabled=1') >= 0) { - ReportLink.url += '&altc=1'; - ReportLink.dims = 'width=350,height=275'; - } else { - ReportLink.dims = 'width=400,height=550'; - } - } else if (Conf['Archive Report']) { - a.textContent = 'Report to archive'; - ReportLink.url = Redirect.to('report', { - boardID: post.board.ID, - postID: post.ID - }); - ReportLink.dims = 'width=700,height=475'; - } else { - ReportLink.url = ''; - } - return !!ReportLink.url; - } - }); - }, - report: function() { - var dims, id, set, url; - url = ReportLink.url, dims = ReportLink.dims; - id = Date.now(); - set = "toolbar=0,scrollbars=1,location=0,status=1,menubar=0,resizable=1," + dims; - 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() { - MarkNewIPs.ipCount = this.ipCount; - MarkNewIPs.postCount = this.posts.keys.length; - return $.on(d, 'ThreadUpdate', MarkNewIPs.onUpdate); - }, - onUpdate: function(e) { - var deletedPosts, fullID, i, ipCount, k, len1, len2, newPosts, postCount, q, ref; - ref = e.detail, ipCount = ref.ipCount, postCount = ref.postCount, newPosts = ref.newPosts, deletedPosts = ref.deletedPosts; - if (ipCount == null) { - return; - } - switch (ipCount - MarkNewIPs.ipCount) { - case postCount - MarkNewIPs.postCount + deletedPosts.length: - i = MarkNewIPs.ipCount; - for (k = 0, len1 = newPosts.length; k < len1; k++) { - fullID = newPosts[k]; - MarkNewIPs.markNew(g.posts[fullID], ++i); - } - break; - case -deletedPosts.length: - for (q = 0, len2 = newPosts.length; q < len2; q++) { - fullID = newPosts[q]; - MarkNewIPs.markOld(g.posts[fullID]); - } - } - MarkNewIPs.ipCount = ipCount; - return MarkNewIPs.postCount = postCount; - }, - 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'); - } - }; - - ReplyPruning = { - init: function() { - var el, label; - if (!(g.VIEW === 'thread' && Conf['Reply Pruning'])) { - return; - } - this.active = !(Conf['Quote Threading'] && Conf['Thread Quotes']); - this.container = $.frag(); - this.summary = $.el('span', { - hidden: true, - className: 'summary' - }); - this.summary.style.cursor = 'pointer'; - $.on(this.summary, 'click', (function(_this) { - return function() { - _this.inputs.enabled.checked = !_this.inputs.enabled.checked; - return $.event('change', null, _this.inputs.enabled); - }; - })(this)); - label = UI.checkbox('Prune Replies', 'Show Last', this.active); - el = $.el('span', { - title: 'Maximum number of replies to show.' - }, { - innerHTML: " " - }); - $.prepend(el, label); - this.inputs = { - enabled: label.firstElementChild, - replies: el.lastElementChild - }; - $.on(this.inputs.enabled, 'change', this.setEnabled); - $.on(this.inputs.replies, 'change', $.cb.value); - Header.menu.addEntry({ - el: el, - order: 190 - }); - return Thread.callbacks.push({ - name: 'Reply Pruning', - cb: this.node - }); - }, - position: 0, - hidden: 0, - hiddenFiles: 0, - total: 0, - totalFiles: 0, - setEnabled: function() { - var other; - other = QuoteThreading.input; - if (this.checked && (other != null ? other.checked : void 0)) { - other.checked = false; - $.event('change', null, other); - } - return ReplyPruning.active = this.checked; - }, - showIfHidden: function(id) { - var ref; - if ((ref = ReplyPruning.container) != null ? ref.getElementById(id) : void 0) { - ReplyPruning.inputs.enabled.checked = false; - return $.event('change', null, ReplyPruning.inputs.enabled); - } - }, - node: function() { - var ref; - ReplyPruning.thread = this; - this.posts.forEach(function(post) { - if (post.isReply) { - ReplyPruning.total++; - if (post.file) { - return ReplyPruning.totalFiles++; - } - } - }); - if (ReplyPruning.active && /^#p\d+$/.test(location.hash) && (0 <= (ref = this.posts.keys.indexOf(location.hash.slice(2))) && ref < 1 + Math.max(ReplyPruning.total - +Conf["Max Replies"], 0))) { - ReplyPruning.active = ReplyPruning.inputs.enabled.checked = false; - } - $.after(this.OP.nodes.root, ReplyPruning.summary); - $.on(ReplyPruning.inputs.enabled, 'change', ReplyPruning.update); - $.on(ReplyPruning.inputs.replies, 'change', ReplyPruning.update); - $.on(d, 'ThreadUpdate', ReplyPruning.updateCount); - $.on(d, 'ThreadUpdate', ReplyPruning.update); - return ReplyPruning.update(); - }, - updateCount: function(e) { - var fullID, k, len1, ref; - if (e.detail[404]) { - return; - } - ref = e.detail.newPosts; - for (k = 0, len1 = ref.length; k < len1; k++) { - fullID = ref[k]; - ReplyPruning.total++; - if (g.posts[fullID].file) { - ReplyPruning.totalFiles++; - } - } - }, - update: function() { - var frag, hidden2, post, posts; - hidden2 = ReplyPruning.active ? Math.max(ReplyPruning.total - +Conf["Max Replies"], 0) : 0; - posts = ReplyPruning.thread.posts; - if (ReplyPruning.hidden < hidden2) { - while (ReplyPruning.hidden < hidden2 && ReplyPruning.position < posts.keys.length) { - post = posts[posts.keys[ReplyPruning.position++]]; - if (post.isReply && !post.isFetchedQuote) { - $.add(ReplyPruning.container, post.nodes.root); - ReplyPruning.hidden++; - if (post.file) { - ReplyPruning.hiddenFiles++; - } - } - } - } else if (ReplyPruning.hidden > hidden2) { - frag = $.frag(); - while (ReplyPruning.hidden > hidden2 && ReplyPruning.position > 0) { - post = posts[posts.keys[--ReplyPruning.position]]; - if (post.isReply && !post.isFetchedQuote) { - $.prepend(frag, post.nodes.root); - ReplyPruning.hidden--; - if (post.file) { - ReplyPruning.hiddenFiles--; - } - } - } - $.after(ReplyPruning.summary, frag); - $.event('PostsInserted'); - } - ReplyPruning.summary.textContent = ReplyPruning.active ? Build.summaryText('+', ReplyPruning.hidden, ReplyPruning.hiddenFiles) : Build.summaryText('-', ReplyPruning.total, ReplyPruning.totalFiles); - return ReplyPruning.summary.hidden = ReplyPruning.total <= +Conf["Max Replies"]; - } - }; - - 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: "? / ?" + (Conf["IP Count in Stats"] ? " / ?" : "") + (Conf["Page Count in Stats"] ? " / ?" : "") - }; - statsTitle = 'Posts / Files'; - if (Conf['IP Count in Stats']) { - statsTitle += ' / IPs'; - } - if (Conf['Page Count in Stats']) { - statsTitle += (g.BOARD.ID === 'f' ? ' / Purge Position' : ' / 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: "
      " + statsHTML.innerHTML + "
      " - }); - $.addClass(doc, 'float'); - $.ready(function() { - return $.add(d.body, sc); - }); - } - this.postCountEl = $('#post-count', sc); - this.fileCountEl = $('#file-count', sc); - this.ipCountEl = $('#ip-count', sc); - this.pageCountEl = $('#page-count', sc); - if (this.pageCountEl) { - $.on(this.pageCountEl, 'click', ThreadStats.fetchPage); - } - 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 (ThreadStats.pageCountEl) { - 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 (!ThreadStats.pageCountEl) { - return; - } - if (newPosts.length) { - ThreadStats.lastPost = g.posts[newPosts[newPosts.length - 1]].info.date; - } - if (g.BOARD.ID !== 'f' && ((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) && ipCountEl) { - ipCountEl.textContent = ipCount; - } - (thread.postLimit && !thread.isSticky ? $.addClass : $.rmClass)(postCountEl, 'warning'); - return (thread.fileLimit && !thread.isSticky ? $.addClass : $.rmClass)(fileCountEl, 'warning'); - }, - fetchPage: function() { - if (!ThreadStats.pageCountEl) { - 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: 'ThreadStats' - }); - }, - onThreadsLoad: function() { - var k, len1, len2, len3, page, purgePos, q, ref, ref1, ref2, thread, u; - if (this.status === 200) { - ref = this.response; - for (k = 0, len1 = ref.length; k < len1; k++) { - page = ref[k]; - if (g.BOARD.ID === 'f') { - purgePos = 1; - ref1 = page.threads; - for (q = 0, len2 = ref1.length; q < len2; q++) { - thread = ref1[q]; - if (thread.no < ThreadStats.thread.ID) { - purgePos++; - } - } - ThreadStats.pageCountEl.textContent = purgePos; - } else { - ref2 = page.threads; - for (u = 0, len3 = ref2.length; u < len3; u++) { - thread = ref2[u]; - 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); - ThreadStats.retry(); - return; - } - } - } - } else if (this.status === 304) { - return ThreadStats.retry(); - } - }, - retry: function() { - var ref; - if (g.BOARD.ID !== 'f' && ThreadStats.lastPost > ThreadStats.lastPageUpdate && ((ref = ThreadStats.pageCountEl) != null ? ref.textContent : void 0) !== '1') { - clearTimeout(ThreadStats.timeout); - return ThreadStats.timeout = setTimeout(ThreadStats.fetchPage, 5 * $.SECOND); - } - } - }; - - ThreadUpdater = { - init: function() { - var conf, el, input, name, ref, sc, subEntries, updateLink; - if (g.VIEW !== 'thread' || !Conf['Thread Updater']) { - return; - } - this.audio = $.el('audio', { - src: ThreadUpdater.beep - }); - if (Conf['Updater and Stats in Header']) { - this.dialog = sc = $.el('span', { - id: 'updater' - }); - $.extend(sc, { - innerHTML: "" - }); - $.ready(function() { - return Header.addShortcut(sc); - }); - } else { - this.dialog = sc = UI.dialog('updater', 'bottom: 0px; left: 0px;', { - innerHTML: "
      " - }); - $.addClass(doc, 'float'); - $.ready(function() { - return $.add(d.body, sc); - }); - } - this.checkPostCount = 0; - this.timer = $('#update-timer', sc); - this.status = $('#update-status', sc); - $.on(this.timer, 'click', this.update); - $.on(this.status, 'click', this.update); - updateLink = $.el('span', { - className: 'brackets-wrap updatelink' - }); - $.extend(updateLink, { - innerHTML: "Update" - }); - Main.ready(function() { - var navLinksBot; - if ((navLinksBot = $('.navLinksBot'))) { - 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.setInterval); - } - subEntries.push({ - el: el - }); - } - this.settings = $.el('span', { - innerHTML: "Interval" - }); - $.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.outdateCount = 0; - ThreadUpdater.postIDs = []; - ThreadUpdater.fileIDs = []; - this.posts.forEach(function(post) { - ThreadUpdater.postIDs.push(post.ID); - if (post.file) { - return ThreadUpdater.fileIDs.push(post.ID); - } - }); - ThreadUpdater.cb.interval.call($.el('input', { - value: Conf['Interval'] - })); - $.on(d, 'QRPostSuccessful', ThreadUpdater.cb.checkpost); - $.on(d, 'visibilitychange', ThreadUpdater.cb.visibility); - return ThreadUpdater.setInterval(); - }, - - /* - 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', - playBeep: function() { - var audio; - audio = ThreadUpdater.audio; - if (audio.paused) { - return audio.play(); - } else { - return $.one(audio, 'ended', ThreadUpdater.playBeep); - } - }, - cb: { - checkpost: function(e) { - if (e.detail.threadID !== ThreadUpdater.thread.ID) { - return; - } - ThreadUpdater.postID = e.detail.postID; - ThreadUpdater.checkPostCount = 0; - ThreadUpdater.outdateCount = 0; - return ThreadUpdater.setInterval(); - }, - 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; - }; - }, - 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() { - var req; - req = ThreadUpdater.req; - switch (req.status) { - case 200: - ThreadUpdater.parse(req); - if (ThreadUpdater.thread.isArchived) { - return ThreadUpdater.kill(); - } else { - return ThreadUpdater.setInterval(); - } - break; - case 404: - return $.ajax("//a.4cdn.org/" + ThreadUpdater.thread.board + "/catalog.json", { - onloadend: function() { - var confirmed, k, len1, len2, page, q, ref, ref1, thread; - if (this.status === 200) { - confirmed = true; - ref = this.response; - for (k = 0, len1 = ref.length; k < len1; k++) { - page = ref[k]; - ref1 = page.threads; - for (q = 0, len2 = ref1.length; q < len2; q++) { - thread = ref1[q]; - if (thread.no === ThreadUpdater.thread.ID) { - confirmed = false; - break; - } - } - } - } else { - confirmed = false; - } - if (confirmed) { - return ThreadUpdater.kill(); - } else { - return ThreadUpdater.error(req); - } - } - }); - default: - return ThreadUpdater.error(req); - } - } - }, - kill: function() { - ThreadUpdater.thread.kill(); - ThreadUpdater.setInterval(); - return $.event('ThreadUpdate', { - 404: true, - threadID: ThreadUpdater.thread.fullID - }); - }, - error: function(req) { - if (req.status === 304) { - ThreadUpdater.set('status', ''); - } - ThreadUpdater.setInterval(); - if (!req.status) { - return ThreadUpdater.set('status', 'Connection Failed', 'warning'); - } else if (req.status !== 304) { - return ThreadUpdater.set('status', req.statusText + " (" + req.status + ")", 'warning'); - } - }, - setInterval: function() { - var cur, interval, j, limit; - clearTimeout(ThreadUpdater.timeoutID); - if (ThreadUpdater.thread.isDead) { - ThreadUpdater.set('status', (ThreadUpdater.thread.isArchived ? 'Archived' : '404'), 'warning'); - ThreadUpdater.set('timer', ''); - return; - } - if (ThreadUpdater.postID && ThreadUpdater.checkPostCount < 5) { - ThreadUpdater.set('timer', '...', 'loading'); - ThreadUpdater.timeoutID = setTimeout(ThreadUpdater.update, ++ThreadUpdater.checkPostCount * $.SECOND); - return; - } - if (!Conf['Auto Update']) { - ThreadUpdater.set('timer', 'Update'); - return; - } - interval = ThreadUpdater.interval; - if (Conf['Optional Increase']) { - limit = d.hidden ? 10 : 5; - j = Math.min(ThreadUpdater.outdateCount, limit); - cur = (Math.floor(interval * 0.1) || 1) * j * j; - ThreadUpdater.seconds = $.minmax(cur, interval, 300); - } else { - ThreadUpdater.seconds = interval; - } - return ThreadUpdater.timeout(); - }, - 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; - } - return el.className = klass != null ? klass : (text === '' ? 'empty' : ''); - }, - timeout: function() { - if (ThreadUpdater.seconds) { - ThreadUpdater.set('timer', ThreadUpdater.seconds); - ThreadUpdater.timeoutID = setTimeout(ThreadUpdater.timeout, 1000); - } else { - ThreadUpdater.outdateCount++; - ThreadUpdater.update(); - } - return ThreadUpdater.seconds--; - }, - update: function() { - var ref; - clearTimeout(ThreadUpdater.timeoutID); - ThreadUpdater.set('timer', '...', 'loading'); - 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: 'ThreadUpdater' - }); - }, - 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(req) { - var ID, OP, board, deletedFiles, deletedPosts, files, firstPost, index, ipCountEl, k, lastPost, len1, len2, len3, len4, newPosts, node, post, postObject, postObjects, posts, q, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, scroll, thread, u, unreadCount, unreadQYCount, v; - postObjects = req.response.posts; - OP = postObjects[0]; - thread = ThreadUpdater.thread; - board = thread.board; - ref = ThreadUpdater.postIDs, lastPost = ref[ref.length - 1]; - if (postObjects[postObjects.length - 1].no < lastPost && new Date(req.getResponseHeader('Last-Modified')) - thread.posts[lastPost].info.date < 30 * $.SECOND) { - return; - } - Build.spoilerRange[board] = OP.custom_spoiler; - thread.setStatus('Archived', !!OP.archived); - ThreadUpdater.updateThreadStatus('Sticky', !!OP.sticky); - ThreadUpdater.updateThreadStatus('Closed', !!OP.closed); - thread.postLimit = !!OP.bumplimit; - thread.fileLimit = !!OP.imagelimit; - if (OP.unique_ips != null) { - thread.ipCount = OP.unique_ips; - } - posts = []; - index = []; - files = []; - newPosts = []; - for (k = 0, len1 = postObjects.length; k < len1; k++) { - postObject = postObjects[k]; - ID = postObject.no; - index.push(ID); - if (postObject.fsize) { - files.push(ID); - } - if (ID <= lastPost) { - continue; - } - if ((post = thread.posts[ID]) && !post.isFetchedQuote) { - post.resurrect(); - continue; - } - newPosts.push(board + "." + ID); - node = Build.postFromObject(postObject, board.ID); - posts.push(new Post(node, thread, board)); - if (ThreadUpdater.postID === ID) { - delete ThreadUpdater.postID; - } - } - deletedPosts = []; - ref1 = ThreadUpdater.postIDs; - for (q = 0, len2 = ref1.length; q < len2; q++) { - ID = ref1[q]; - if (!(indexOf.call(index, ID) < 0)) { - continue; - } - thread.posts[ID].kill(); - deletedPosts.push(board + "." + ID); - } - ThreadUpdater.postIDs = index; - deletedFiles = []; - ref2 = ThreadUpdater.fileIDs; - for (u = 0, len3 = ref2.length; u < len3; u++) { - ID = ref2[u]; - if (!(!(indexOf.call(files, ID) >= 0 || (ref3 = board + "." + ID, indexOf.call(deletedPosts, ref3) >= 0)))) { - continue; - } - thread.posts[ID].kill(true); - deletedFiles.push(board + "." + ID); - } - ThreadUpdater.fileIDs = files; - if (!posts.length) { - ThreadUpdater.set('status', ''); - } else { - ThreadUpdater.set('status', "+" + posts.length, 'new'); - ThreadUpdater.outdateCount = 0; - unreadCount = (ref4 = Unread.posts) != null ? ref4.size : void 0; - unreadQYCount = (ref5 = Unread.postsQuotingYou) != null ? ref5.size : void 0; - Main.callbackNodes(Post, posts); - if (d.hidden || !d.hasFocus()) { - if (Conf['Beep Quoting You'] && ((ref6 = Unread.postsQuotingYou) != null ? ref6.size : void 0) > unreadQYCount) { - ThreadUpdater.playBeep(); - if (Conf['Beep']) { - ThreadUpdater.playBeep(); - } - } else if (Conf['Beep'] && ((ref7 = Unread.posts) != null ? ref7.size : void 0) > 0 && unreadCount === 0) { - ThreadUpdater.playBeep(); - } - } - scroll = Conf['Auto Scroll'] && ThreadUpdater.scrollBG() && ThreadUpdater.root.getBoundingClientRect().bottom - doc.clientHeight < 25; - firstPost = null; - for (v = 0, len4 = posts.length; v < len4; v++) { - post = posts[v]; - if (!QuoteThreading.insert(post)) { - firstPost || (firstPost = post.nodes.root); - $.add(ThreadUpdater.root, post.nodes.root); - } - } - $.event('PostsInserted'); - if (scroll) { - if (Conf['Bottom Scroll']) { - window.scrollTo(0, d.body.clientHeight); - } else { - if (firstPost) { - Header.scrollTo(firstPost); - } - } - } - } - 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'); - } - return $.event('ThreadUpdate', { - 404: false, - threadID: thread.fullID, - newPosts: newPosts, - deletedPosts: deletedPosts, - deletedFiles: deletedFiles, - postCount: OP.replies + 1, - fileCount: OP.images + !!OP.fsize, - ipCount: OP.unique_ips - }); - } - }; - - ThreadWatcher = { - init: function() { - var sc; - if (!(this.enabled = 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: "
      Thread Watcher ×
      " - }); - this.status = $('#watcher-status', this.dialog); - this.list = this.dialog.lastElementChild; - this.refreshButton = $('.refresh', this.dialog); - this.closeButton = $('.move > .close', this.dialog); - this.unreaddb = Unread.db || new DataBoard('lastReadPosts'); - this.unreadEnabled = Conf['Remember Last Read Post']; - $.on(d, 'QRPostSuccessful', this.cb.post); - $.on(sc, 'click', this.toggleWatcher); - $.on(this.refreshButton, 'click', this.buttonFetchAll); - $.on(this.closeButton, '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['Fixed Thread Watcher']) { - $.addClass(doc, 'fixed-watcher'); - } - if (Conf['Toggleable Thread Watcher']) { - this.dialog.hidden = true; - Header.addShortcut(sc); - $.addClass(doc, 'toggleable-watcher'); - } - ThreadWatcher.fetchAuto(); - if (g.VIEW === 'index' && Conf['JSON Index'] && Conf['Menu'] && g.BOARD.ID !== 'f') { - Menu.menu.addEntry({ - el: $.el('a', { - href: 'javascript:;', - className: 'has-shortcut-text' - }, { - innerHTML: "Alt+click" - }), - order: 6, - open: function(arg) { - var thread; - thread = arg.thread; - if (Conf['Index Mode'] !== 'catalog') { - return false; - } - this.el.firstElementChild.textContent = ThreadWatcher.isWatched(thread) ? 'Unwatch' : 'Watch'; - 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('a', { - href: 'javascript:;', - 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'); - } - $.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)); - return $.on(this.nodes.thumb.parentNode, 'mousedown', function(e) { - if (e.button === 0 && e.altKey) { - return e.preventDefault(); - } - }); - }, - ready: function() { - $.off(d, '4chanXInitFinished', ThreadWatcher.ready); - if (!Main.isThisPageLegit()) { - return; - } - ThreadWatcher.refresh(); - $.add(d.body, ThreadWatcher.dialog); - 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, k, len1, ref; - if ($.hasClass(this, 'disabled')) { - return; - } - ref = $$('a[title]', ThreadWatcher.list); - for (k = 0, len1 = ref.length; k < len1; k++) { - a = ref[k]; - $.open(a.href); - } - return $.event('CloseMenu'); - }, - pruneDeads: function() { - var boardID, data, k, len1, ref, ref1, threadID; - if ($.hasClass(this, 'disabled')) { - return; - } - ThreadWatcher.db.forceSync(); - ref = ThreadWatcher.getAll(); - for (k = 0, len1 = ref.length; k < len1; k++) { - ref1 = ref[k], 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, ref, threadID; - ref = this.parentNode.dataset.fullID.split('.'), boardID = ref[0], threadID = ref[1]; - return ThreadWatcher.rm(boardID, +threadID); - }, - post: function(e) { - var boardID, postID, ref, threadID; - 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, ref, threadID; - db = ThreadWatcher.db; - boardID = g.BOARD.ID; - db.forceSync(); - ref = db.data.boards[boardID]; - for (threadID in ref) { - data = ref[threadID]; - if (!(data != null ? data.isDead : void 0) && !(threadID in g.BOARD.threads)) { - if (Conf['Auto Prune'] || !(data && typeof data === 'object')) { - db["delete"]({ - boardID: boardID, - threadID: threadID - }); - } else { - if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { - ThreadWatcher.fetchStatus({ - boardID: boardID, - threadID: threadID, - data: data - }); - } - data.isDead = true; - 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); - } - }, - requests: [], - fetched: 0, - clearRequests: function() { - ThreadWatcher.requests = []; - ThreadWatcher.fetched = 0; - ThreadWatcher.status.textContent = ''; - return $.rmClass(ThreadWatcher.refreshButton, 'fa-spin'); - }, - abort: function() { - var k, len1, ref, req; - ref = ThreadWatcher.requests; - for (k = 0, len1 = ref.length; k < len1; k++) { - req = ref[k]; - if (req.readyState !== 4) { - req.abort(); - } - } - return ThreadWatcher.clearRequests(); - }, - fetchAuto: function() { - var db, interval, now; - clearTimeout(ThreadWatcher.timeout); - if (!Conf['Auto Update Thread Watcher']) { - return; - } - db = ThreadWatcher.db; - interval = ThreadWatcher.unreadEnabled && 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); - }, - buttonFetchAll: function() { - if (ThreadWatcher.requests.length) { - return ThreadWatcher.abort(); - } else { - return ThreadWatcher.fetchAllStatus(); - } - }, - fetchAllStatus: function() { - var k, len1, ref, thread, threads; - ThreadWatcher.db.forceSync(); - ThreadWatcher.unreaddb.forceSync(); - if ((ref = QuoteYou.db) != null) { - ref.forceSync(); - } - if (!(threads = ThreadWatcher.getAll()).length) { - return; - } - for (k = 0, len1 = threads.length; k < len1; k++) { - thread = threads[k]; - ThreadWatcher.fetchStatus(thread); - } - }, - fetchStatus: function(thread, force) { - var boardID, data, req, threadID; - boardID = thread.boardID, threadID = thread.threadID, data = thread.data; - if (data.isDead && !force) { - return; - } - if (ThreadWatcher.requests.length === 0) { - ThreadWatcher.status.textContent = '...'; - $.addClass(ThreadWatcher.refreshButton, 'fa-spin'); - } - req = $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", { - onloadend: function() { - return ThreadWatcher.parseStatus.call(this, thread); - }, - timeout: $.MINUTE - }, { - whenModified: force ? false : 'ThreadWatcher' - }); - return ThreadWatcher.requests.push(req); - }, - parseStatus: function(arg) { - var boardID, data, isDead, k, lastReadPost, len1, match, postObj, quotesYou, quotingYou, ref, ref1, regexp, threadID, unread; - boardID = arg.boardID, threadID = arg.threadID, data = arg.data; - ThreadWatcher.fetched++; - if (ThreadWatcher.fetched === ThreadWatcher.requests.length) { - ThreadWatcher.clearRequests(); - } else { - ThreadWatcher.status.textContent = (Math.round(ThreadWatcher.fetched / ThreadWatcher.requests.length * 100)) + "%"; - } - 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 (k = 0, len1 = ref.length; k < len1; k++) { - postObj = ref[k]; - if (!(postObj.no > lastReadPost)) { - continue; - } - if ((ref1 = QuoteYou.db) != null ? ref1.get({ - boardID: boardID, - threadID: threadID, - postID: postObj.no - }) : void 0) { - continue; - } - unread++; - if (!(QuoteYou.db && postObj.com)) { - continue; - } - quotesYou = false; - regexp = /]*\bhref="(?:\/([^\/]+)\/thread\/)?(\d+)?(?:#p(\d+))?"/g; - while (match = regexp.exec(postObj.com)) { - if (QuoteYou.db.get({ - boardID: match[1] || boardID, - threadID: match[2] || threadID, - postID: match[3] || match[2] || threadID - })) { - quotesYou = true; - break; - } - } - if (quotesYou && !Filter.isHidden(Build.parseJSON(postObj, boardID))) { - quotingYou++; - } - } - 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, ref, threadID, threads; - 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]; - if (data && typeof data === 'object') { - 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 (ThreadWatcher.unreadEnabled && 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 (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { - if (data.unread === 0) { - $.addClass(div, 'replies-read'); - } - 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, k, len1, len2, list, nodes, q, ref, ref1, ref2, refresher, threadID; - nodes = []; - ref = ThreadWatcher.getAll(); - for (k = 0, len1 = ref.length; k < len1; k++) { - ref1 = ref[k], 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, len2, post, q, ref2, toggler; - helper = ThreadWatcher.isWatched(thread) ? ['addClass', 'Unwatch'] : ['rmClass', 'Watch']; - if (thread.OP) { - ref2 = [thread.OP].concat(slice.call(thread.OP.clones)); - for (q = 0, len2 = ref2.length; q < len2; q++) { - post = ref2[q]; - 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 (q = 0, len2 = ref2.length; q < len2; q++) { - refresher = ref2[q]; - refresher(); - } - if (Index.nodes && Conf['Pin Watched Threads']) { - Index.sort(); - return Index.buildIndex(); - } - }, - refreshIcon: function() { - var className, k, len1, ref; - ref = ['replies-unread', 'replies-quoting-you']; - for (k = 0, len1 = ref.length; k < len1; k++) { - className = ref[k]; - ThreadWatcher.shortcut.classList.toggle(className, !!$("." + className, ThreadWatcher.dialog)); - } - }, - update: function(boardID, threadID, newData) { - var data, key, line, n, newLine, ref, val; - 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(); - } - }, - set404: function(boardID, threadID, cb) { - var data, ref; - if (!(data = (ref = ThreadWatcher.db) != null ? ref.get({ - boardID: boardID, - threadID: threadID - }) : void 0)) { - return cb(); - } - if (Conf['Auto Prune']) { - ThreadWatcher.db["delete"]({ - boardID: boardID, - threadID: threadID - }); - return cb(); - } - if (data.isDead && !((data.unread != null) || (data.quotingYou != null))) { - return cb(); - } - data.isDead = true; - delete data.unread; - delete data.quotingYou; - return ThreadWatcher.db.set({ - boardID: boardID, - threadID: threadID, - val: data - }, cb); - }, - 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 (ThreadWatcher.unreadEnabled && 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(); - }, - 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, ref, rmClass, text; - 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, k, len1, name, ref, ref1, refresh, subEntries; - 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 (k = 0, len1 = entries.length; k < len1; k++) { - ref1 = entries[k], 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; - if (name === 'Show Unread Count' && !ThreadWatcher.unreadEnabled) { - input.disabled = true; - $.addClass(entry.el, 'disabled'); - entry.el.title += '\n[Remember Last Read Post is disabled.]'; - } - $.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['Remember Last Read Post'] || Conf['Desktop Notifications'] || Conf['Quote Threading']))) { - return; - } - if (Conf['Remember Last Read Post']) { - $.sync('Remember Last Read Post', function(enabled) { - return Conf['Remember Last Read Post'] = enabled; - }); - 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, k, len1, ref, ref1; - Unread.thread = this; - Unread.title = d.title; - Unread.lastReadPost = ((ref = Unread.db) != null ? ref.get({ - boardID: this.board.ID, - threadID: this.ID - }) : void 0) || 0; - Unread.readCount = 0; - ref1 = this.posts.keys; - for (k = 0, len1 = ref1.length; k < len1; k++) { - ID = ref1[k]; - if (+ID <= Unread.lastReadPost) { - Unread.readCount++; - } - } - $.one(d, '4chanXInitFinished', Unread.ready); - return $.on(d, 'ThreadUpdate', Unread.onUpdate); - }, - ready: function() { - if (Conf['Remember Last Read Post'] && Conf['Scroll to Last Read Post']) { - Unread.scroll(); - } - Unread.setLine(true); - Unread.read(); - Unread.update(); - $.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, ref, root; - if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) { - return; - } - ReplyPruning.showIfHidden((ref = Unread.position) != null ? ref.data.nodes.root.id : void 0); - 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, k, lastReadPost, postIDs, 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 = k = ref = Unread.readCount, ref1 = postIDs.length; k < ref1; i = k += 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 = QuoteYou.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 k, len1, quotelink, ref, ref1; - ref = post.nodes.quotelinks; - for (k = 0, len1 = ref.length; k < len1; k++) { - quotelink = ref[k]; - if (!((ref1 = QuoteYou.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; - } - try { - notif = new Notification(post.info.nameBlock + " replied to you", { - body: post.info.commentDisplay, - icon: Favicon.logo - }); - notif.onclick = function() { - Header.scrollToIfNeeded(post.nodes.root, true); - return $.global(function() { - return window.focus(); - }); - }; - return notif.onshow = function() { - return setTimeout(function() { - return notif.close(); - }, 7 * $.SECOND); - }; - } catch (_error) {} - }, - 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, ref, ref1, root; - if (!Unread.posts.size && Unread.readCount !== Unread.thread.posts.keys.length) { - Unread.saveLastReadPost(); - } - if (d.hidden || !Unread.posts.size) { - return; - } - 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 ((ref1 = QuoteYou.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, k, postIDs, ref, ref1; - $.forceSync('Remember Last Read Post'); - if (!(Conf['Remember Last Read Post'] && Unread.db)) { - return; - } - postIDs = Unread.thread.posts.keys; - for (i = k = ref = Unread.readCount, ref1 = postIDs.length; k < ref1; i = k += 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 (Unread.hr.hidden || 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, isDead, 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; - } - $.forceSync('Remember Last Read Post'); - if (Conf['Remember Last Read Post'] && (!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']) { - isDead = Unread.thread.isDead; - Favicon.el.href = countQuotingYou ? Favicon[isDead ? 'unreadDeadY' : 'unreadY'] : count ? Favicon[isDead ? 'unreadDead' : 'unread'] : Favicon[isDead ? 'dead' : 'default']; - return $.add(d.head, Favicon.el); - } - } - }; - - Redirect = { - init: function() { - var archive, archives, boardID, boards, data, files, id, k, len1, len2, name, o, q, record, ref, ref1, software, type, uid, withCredentials; - o = { - thread: {}, - post: {}, - file: {}, - report: {} - }; - archives = {}; - ref = Redirect.archives; - for (k = 0, len1 = ref.length; k < len1; k++) { - data = ref[k]; - uid = data.uid, name = data.name, boards = data.boards, files = data.files, software = data.software, withCredentials = data.withCredentials; - archives[JSON.stringify(uid != null ? uid : name)] = data; - for (q = 0, len2 = boards.length; q < len2; q++) { - boardID = boards[q]; - if (!withCredentials) { - 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; - } - } - if (name === 'fgts') { - o.report[boardID] = data; - } - } - } - ref1 = Conf['selectedArchives']; - for (boardID in ref1) { - record = ref1[boardID]; - for (type in record) { - id = record[type]; - if (id === null) { - delete o[type][boardID]; - } else if (archive = archives[JSON.stringify(id)]) { - boards = type === 'file' ? archive.files : archive.boards; - if (indexOf.call(boards, boardID) >= 0) { - o[type][boardID] = archive; - } - } - } - } - return Redirect.data = o; - }, - archives: [{"uid":3,"name":"4plebs","domain":"archive.4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["adv","f","hr","o","pol","s4s","sp","tg","trv","tv","x"],"files":["adv","f","hr","o","pol","s4s","sp","tg","trv","tv","x"]},{"uid":4,"name":"Nyafuu Archive","domain":"archive.nyafuu.org","http":true,"https":true,"software":"foolfuuka","boards":["c","e","news","w","wg","wsr"],"files":["c","e","news","w","wg","wsr"]},{"uid":8,"name":"Rebecca Black Tech","domain":"rbt.asia","http":false,"https":true,"software":"fuuka","boards":["cgl","g","mu"],"files":["cgl","g","mu"]},{"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","b","cm","gd","h","hc","hm","n","out","p","po","qa","r","s","soc","toy","vp","y"],"files":["asp","b","cm","gd","h","hc","hm","n","out","p","po","qa","r","s","soc","toy","vp","y"]},{"uid":23,"name":"Desustorage","domain":"desustorage.org","http":true,"https":true,"software":"foolfuuka","boards":["a","aco","an","c","co","d","fit","gif","his","int","k","m","mlp","qa","r9k","tg","trash","vr","wsg"],"files":["a","aco","an","c","co","d","fit","gif","his","int","k","m","mlp","qa","r9k","tg","trash","vr","wsg"]},{"uid":24,"name":"fireden.net","domain":"boards.fireden.net","http":false,"https":true,"software":"foolfuuka","boards":["a","cm","ic","sci","tg","v","vg","y"],"files":["a","cm","ic","sci","tg","v","vg","y"]},{"uid":25,"name":"arch.b4k.co","domain":"arch.b4k.co","http":true,"https":true,"software":"foolfuuka","boards":["g","jp","mlp","v"],"files":[]},{"uid":5,"name":"Love is Over","domain":"deploy.loveisover.me","http":true,"https":false,"software":"foolfuuka","boards":["c","d","e","i","lgbt","t","u"],"files":["c","d","e","i","lgbt","t","u"],"search":[]},{"uid":28,"name":"bstats","domain":"archive.b-stats.org","http":true,"https":true,"software":"foolfuuka","boards":["f","cm","hm","lgbt","news","trash","y"],"files":[]}], - 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 boardID, postID, protocol, url; - boardID = arg.boardID, postID = arg.postID; - protocol = Redirect.protocol(archive); - url = "" + protocol + archive.domain + "/_/api/chan/post/?board=" + boardID + "&num=" + postID; - if (!Redirect.securityCheck(url)) { - return ''; - } - 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 === 'MD5' ? 'image' : type; - if (type === 'capcode') { - value = { - 'Developer': 'dev' - }[value] || value.toLowerCase(); - } else if (type === 'image') { - value = value.replace(/[+\/=]/g, function(c) { - return { - '+': '-', - '/': '_', - '=': '' - }[c]; - }); - } - value = encodeURIComponent(value); - path = archive.software === 'foolfuuka' ? boardID + "/search/" + type + "/" + value + "/" : type === 'image' ? boardID + "/image/" + value : boardID + "/?task=search2&search_" + type + "=" + value; - return "" + (Redirect.protocol(archive)) + archive.domain + "/" + path; - }, - report: function(archive, arg) { - var boardID, postID; - boardID = arg.boardID, postID = arg.postID; - return "https://so.fgts.jp/report/?board=" + boardID + "&no=" + postID; - }, - securityCheck: function(url) { - return /^https:\/\//.test(url) || location.protocol === 'http:' || Conf['Exempt Archives from Encryption']; - }, - navigate: function(dest, data, alternative) { - var url; - if (!Redirect.data) { - Redirect.init(); - } - url = Redirect.to(dest, data); - 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: "[Dismiss]" - }); - $.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() { - 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, k, len1, ref; - if (!Conf['Disable Autoplaying Sounds']) { - return; - } - $.addClass(doc, 'anti-autoplay'); - ref = $$('audio[autoplay]', doc); - for (k = 0, len1 = ref.length; k < len1; k++) { - audio = ref[k]; - 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, k, len1, len2, object, q, ref, ref1; - ref = $$('iframe[src*="youtube"][src*="autoplay=1"]', root); - for (k = 0, len1 = ref.length; k < len1; k++) { - iframe = ref[k]; - iframe.src = iframe.src.replace(/\?autoplay=1&?/, '?').replace('&autoplay=1', ''); - $.addClass(iframe, 'autoplay-removed'); - } - ref1 = $$('object[data*="youtube"][data*="autoplay=1"]', root); - for (q = 0, len2 = ref1.length; q < len2; q++) { - object = ref1[q]; - object.data = object.data.replace(/\?autoplay=1&?/, '?').replace('&autoplay=1', ''); - $.addClass(object, 'autoplay-removed'); - } - } - }; - - 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","79.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","256.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","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 base1, br, k, len1, name1, ref; - if (!(e.ctrlKey || e.metaKey)) { - return; - } - if ((base1 = Banner.original)[name1 = this.className] == null) { - base1[name1] = this.cloneNode(true); - } - this.contentEditable = true; - ref = $$('br', this); - for (k = 0, len1 = ref.length; k < len1; k++) { - br = ref[k]; - $.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, k, len1, ref; - ref = $$('br', this); - for (k = 0, len1 = ref.length; k < len1; k++) { - br = ref[k]; - $.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, k, len1, ref, string, string2; - className = child.className; - child.title = "Ctrl/\u2318+click to edit board " + (className.slice(5).toLowerCase()); - child.spellcheck = false; - ref = ['click', 'keydown', 'blur']; - for (k = 0, len1 = ref.length; k < len1; k++) { - event = ref[k]; - $.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 Index']) && !(Conf['JSON Index'] && 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, k, len1, link, ref; - ref = $$(selector); - for (k = 0, len1 = ref.length; k < len1; k++) { - link = ref[k]; - switch (link.pathname.replace(/\/+/g, '/')) { - case "/" + g.BOARD + "/": - if (Conf['JSON Index']) { - link.textContent = 'Index'; - } - link.href = CatalogLinks.index(); - break; - case "/" + g.BOARD + "/catalog": - link.href = CatalogLinks.catalog(); - } - if (g.VIEW === 'catalog' && Conf['JSON Index'] && 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 Index'] && 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, k, len1, m, ref; - ref = $$('a', this.nodes.comment); - for (k = 0, len1 = ref.length; k < len1; k++) { - a = ref[k]; - if (m = a.href.match(/^https?:\/\/boards\.4chan\.org\/([^\/]+)\/catalog(#s=.*)?/)) { - a.href = "//boards.4chan.org/" + m[1] + "/" + (m[2] || '#catalog'); - } - } - }, - initBoardList: function() { - if (!CatalogLinks.el) { - 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, k, len1, ref, ref1; - ref = $$('a:not([data-only])', Header.boardList).concat($$('a', Header.bottomBoardList)); - for (k = 0, len1 = ref.length; k < len1; k++) { - a = ref[k]; - if (((ref1 = a.hostname) !== 'boards.4chan.org' && ref1 !== 'catalog.neet.tv') || !(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 + "/"; - if (a.dataset.indexOptions && a.hostname === 'boards.4chan.org' && a.pathname.split('/')[2] === '') { - a.href += (a.hash ? '/' : '#') + a.dataset.indexOptions; - } - } - 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 Index'] && 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 Index'] && board !== 'f') { - 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', '#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 Index']) { - 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, k, len1, len2, len3, postObj, posts, q, quote, ref, ref1, spoilerRange, status, u; - 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 (k = 0, len1 = posts.length; k < len1; k++) { - postObj = posts[k]; - 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 (q = 0, len2 = ref.length; q < len2; q++) { - quote = ref[q]; - 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 (u = 0, len3 = ref1.length; u < len3; u++) { - callback = ref1[u]; - callback.call(post); - } - } - }; - - ExpandThread = { - statuses: {}, - init: function() { - if (g.VIEW === 'thread' || !Conf['Thread Expansion']) { - return; - } - if (Conf['JSON Index']) { - 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 = Build.summaryText.apply(Build, ['+'].concat(slice.call(a.textContent.match(/\d+/g)))); - a.style.cursor = 'pointer'; - return $.on(a, 'click', ExpandThread.cbToggle); - }, - disconnect: function(refresh) { - var ref, ref1, status, threadID; - 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); - }); - }, - 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); - } - }, - expand: function(thread, a) { - var status; - ExpandThread.statuses[thread] = status = {}; - a.textContent = Build.summaryText.apply(Build, ['...'].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, k, len1, num, postsCount, replies, reply, status; - status = ExpandThread.statuses[thread]; - delete ExpandThread.statuses[thread]; - if (status.req) { - status.req.abort(); - if (a) { - a.textContent = Build.summaryText.apply(Build, ['+'].concat(slice.call(a.textContent.match(/\d+/g)))); - } - return; - } - replies = $$('.thread > .replyContainer', threadRoot); - if (!Conf['JSON Index'] || 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 (k = 0, len1 = replies.length; k < len1; k++) { - reply = replies[k]; - if (Conf['Quote Inlining']) { - while (inlined = $('.inlined', reply)) { - inlined.click(); - } - } - postsCount++; - if ('file' in Get.postFromRoot(reply)) { - filesCount++; - } - $.rm(reply); - } - return a.textContent = Build.summaryText('+', postsCount, filesCount); - }, - parse: function(req, thread, a) { - var filesCount, k, len1, post, postData, posts, postsCount, postsRoot, ref, ref1, root; - 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 (k = 0, len1 = ref1.length; k < len1; k++) { - postData = ref1[k]; - 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 = Build.summaryText('-', 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() { - var info, oldInfo; - if (!this.file || this.isClone) { - return; - } - oldInfo = $.el('span', { - className: 'fileText-original' - }); - $.prepend(this.file.link.parentNode, oldInfo); - $.add(oldInfo, [this.file.link.previousSibling, this.file.link, this.file.link.nextSibling]); - info = $.el('span', { - className: 'file-info' - }); - FileInfo.format(Conf['fileInfo'], this, info); - return $.prepend(this.file.text, info); - }, - 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: E.cat(output) - }); - }, - formatters: { - t: function() { - return { - innerHTML: E(this.file.url.match(/[^/]*$/)[0]) - }; - }, - T: function() { - return { - innerHTML: "" + FileInfo.formatters.t.call(this).innerHTML + "" - }; - }, - l: function() { - return { - innerHTML: "" + FileInfo.formatters.n.call(this).innerHTML + "" - }; - }, - L: function() { - return { - innerHTML: "" + FileInfo.formatters.N.call(this).innerHTML + "" - }; - }, - 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: "" + E(shortname) + "" + E(fullname) + "" - }; - } - }, - N: function() { - return { - innerHTML: E(this.file.name) - }; - }, - p: function() { - return { - innerHTML: (this.file.isSpoiler ? "Spoiler, " : "") - }; - }, - 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") - }; - }, - g: function() { - return { - innerHTML: (this.file.tag ? ", " + E(this.file.tag) : "") - }; - }, - '%': function() { - return { - innerHTML: "%" - }; - } - } - }; - - Flash = { - init: function() { - if (g.BOARD.ID === 'f' && Conf['Enable Native Flash Embedding']) { - return $.ready(Flash.initReady); - } - }, - initReady: function() { - if ($.hasStorage) { - return $.global(function() { - if (JSON.parse(localStorage['4chan-settings'] || '{}').disableAll) { - return window.SWFEmbed.init(); - } - }); - } else { - if (g.VIEW === 'thread') { - $.global(function() { - return window.Main.tid = location.pathname.split(/\/+/)[3]; - }); - } - return $.global(function() { - return window.SWFEmbed.init(); - }); - } - } - }; - - Fourchan = { - init: function() { - var ref; - if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { - return; - } - if (g.BOARD.ID === 'g') { - $.on(window, 'prettyprint:cb', function(e) { - var post, pre; - if (!(post = g.posts[e.detail.ID])) { - return; - } - if (!(pre = $$('.prettyprint', post.nodes.comment)[e.detail.i])) { - return; - } - if (!$.hasClass(pre, 'prettyprinted')) { - pre.innerHTML = e.detail.html; - return $.addClass(pre, 'prettyprinted'); - } - }); - $.globalEval('window.addEventListener(\'prettyprint\', function(e) {\n window.dispatchEvent(new CustomEvent(\'prettyprint:cb\', {\n detail: {\n ID: e.detail.ID,\n i: e.detail.i,\n html: prettyPrintOne(e.detail.html)\n }\n }));\n}, false);'); - Post.callbacks.push({ - name: 'Parse /g/ code', - cb: this.code - }); - } - if (g.BOARD.ID === 'sci') { - $.global(function() { - return window.addEventListener('mathjax', function(e) { - if (window.MathJax) { - return window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub, e.target]); - } else { - if (!document.querySelector('script[src^="//cdn.mathjax.org/"]')) { - window.loadMathJax(); - window.loadMathJax = function() {}; - } - if (!e.target.classList.contains('postMessage')) { - return document.querySelector('script[src^="//cdn.mathjax.org/"]').addEventListener('load', function() { - return window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub, e.target]); - }, false); - } - } - }, 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 $.global(function() { - var k, len1, node, ref1; - window.clickable_ids = false; - ref1 = document.querySelectorAll('.posteruid, .capcode'); - for (k = 0, len1 = ref1.length; k < len1; k++) { - node = ref1[k]; - node.removeEventListener('click', window.idClick, false); - } - }); - }); - }, - code: function() { - if (this.isClone) { - return; - } - return $.ready((function(_this) { - return function() { - var i, k, len1, pre, ref; - ref = $$('.prettyprint', _this.nodes.comment); - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - pre = ref[i]; - if (!$.hasClass(pre, 'prettyprinted')) { - $.event('prettyprint', { - ID: _this.fullID, - i: i, - html: pre.innerHTML - }, window); - } - } - }; - })(this)); - }, - math: function() { - var cb, k, len1, wbr, wbrs; - if (!/\[(math|eqn)\]/.test(this.nodes.comment.textContent)) { - return; - } - if ((wbrs = $$('wbr', this.nodes.comment)).length) { - for (k = 0, len1 = wbrs.length; k < len1; k++) { - wbr = wbrs[k]; - $.rm(wbr); - } - this.nodes.comment.normalize(); - } - cb = (function(_this) { - return function() { - if (!doc.contains(_this.nodes.comment)) { - return; - } - $.off(d, 'PostsInserted', cb); - return $.event('mathjax', null, _this.nodes.comment); - }; - })(this); - $.on(d, 'PostsInserted', cb); - return cb(); - } - }; - - 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 Config.hotkeys) { - $.sync(hotkey, Keybinds.sync); - } - init = function() { - var k, len1, node, ref; - $.off(d, '4chanXInitFinished', init); - $.on(d, 'keydown', Keybinds.keydown); - ref = $$('[accesskey]'); - for (k = 0, len1 = ref.length; k < len1; k++) { - node = ref[k]; - node.removeAttribute('accesskey'); - } - }; - return $.on(d, '4chanXInitFinished', init); - }, - sync: function(key, hotkey) { - return Conf[hotkey] = key; - }, - keydown: function(e) { - var form, k, key, len1, notification, notifications, op, ref, ref1, ref2, ref3, ref4, ref5, searchInput, target, thread, threadRoot; - 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) && !/^Alt\+(\d|Up|Down|Left|Right)$/.test(key))) { - return; - } - } - if (!(((ref1 = g.VIEW) !== 'index' && ref1 !== 'thread') || g.VIEW === 'index' && Conf['JSON Index'] && Conf['Index Mode'] === 'catalog' || g.VIEW === 'index' && g.BOARD.ID === 'f')) { - 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 (k = 0, len1 = notifications.length; k < len1; k++) { - notification = notifications[k]; - $('.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['SJIS tags']: - if (target.nodeName !== 'TEXTAREA') { - return; - } - Keybinds.tags('sjis', 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 Index'] && g.BOARD.ID !== 'f')) { - return; - } - Index.update(); - break; - default: - return; - } - break; - case Conf['Watch']: - if (!(ThreadWatcher.enabled && thread)) { - return; - } - ThreadWatcher.toggle(thread); - break; - case Conf['Update thread watcher']: - if (!ThreadWatcher.enabled) { - return; - } - ThreadWatcher.buttonFetchAll(); - 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'))) { - return; - } - FappeTyme.toggle('fappe'); - break; - case Conf['werkTyme']: - if (!(Conf['Werk Tyme'] && ((ref3 = g.VIEW) === 'index' || ref3 === 'thread'))) { - return; - } - FappeTyme.toggle('werk'); - break; - case Conf['Front page']: - if (Conf['JSON Index'] && g.VIEW === 'index' && g.BOARD.ID !== 'f') { - 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' && g.BOARD.ID !== 'f')) { - return; - } - if (Conf['JSON Index']) { - 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' && g.BOARD.ID !== 'f')) { - return; - } - if (Conf['JSON Index']) { - 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' && g.BOARD.ID !== 'f')) { - return; - } - searchInput = Conf['JSON Index'] ? Index.searchInput : $.id('search-box'); - Header.scrollToIfNeeded(searchInput); - searchInput.focus(); - break; - case Conf['Paged mode']: - if (!(Conf['JSON Index'] && g.BOARD.ID !== 'f')) { - return; - } - window.location = g.VIEW === 'index' ? '#paged' : "/" + g.BOARD + "/#paged"; - break; - case Conf['Infinite scrolling mode']: - if (!(Conf['JSON Index'] && g.BOARD.ID !== 'f')) { - return; - } - window.location = g.VIEW === 'index' ? '#infinite' : "/" + g.BOARD + "/#infinite"; - break; - case Conf['All pages mode']: - if (!(Conf['JSON Index'] && g.BOARD.ID !== 'f')) { - return; - } - window.location = g.VIEW === 'index' ? '#all-pages' : "/" + g.BOARD + "/#all-pages"; - break; - case Conf['Open catalog']: - if (g.BOARD.ID === 'f') { - return; - } - window.location = CatalogLinks.catalog(); - break; - case Conf['Cycle sort type']: - if (!(Conf['JSON Index'] && g.VIEW === 'index' && g.BOARD.ID !== '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 && QuoteYou.db)) { - return; - } - QuoteYou.cb.seek('preceding'); - break; - case Conf['Next Post Quoting You']: - if (!(threadRoot && QuoteYou.db)) { - 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 32: - return 'Space'; - case 37: - return 'Left'; - case 38: - return 'Up'; - case 39: - return 'Right'; - case 40: - return 'Down'; - case 188: - return 'Comma'; - case 190: - return 'Period'; - case 191: - return 'Slash'; - case 59: - case 186: - return 'Semicolon'; - default: - if ((48 <= kc && kc <= 57) || (65 <= kc && kc <= 90)) { - return String.fromCharCode(kc).toLowerCase(); - } else if ((96 <= kc && kc <= 105)) { - return String.fromCharCode(kc - 48).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'; - case 'sjis': - return g.BOARD.ID === 'jp'; - } - })(); - 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, k, len1, next, postEl, replies, reply, root; - 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 (k = 0, len1 = replies.length; k < len1; k++) { - reply = replies[k]; - 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 k, len1, ref, thread, threadRoot; - ref = $$('.thread'); - for (k = 0, len1 = ref.length; k < len1; k++) { - threadRoot = ref[k]; - 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, ref, thread, top; - 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); - } - } - }; - - NormalizeURL = { - init: function() { - var pathname; - if (!Conf['Normalize URL']) { - return; - } - pathname = location.pathname.split(/\/+/); - switch (g.VIEW) { - case 'thread': - pathname[2] = 'thread'; - pathname = pathname.slice(0, 4); - break; - case 'index': - pathname = pathname.slice(0, 3); - } - pathname = pathname.join('/'); - if (location.pathname !== pathname) { - return history.replaceState(history.state, '', location.protocol + "//" + location.host + pathname + location.hash); - } - } - }; - - 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 Index'] && 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, k, len1, now, ref; - if (d.hidden) { - return; - } - now = new Date(); - ref = RelativeDates.stale; - for (k = 0, len1 = ref.length; k < len1; k++) { - data = ref[k]; - 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, k, len1, ref, relative, singlePost; - 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 (k = 0, len1 = ref.length; k < len1; k++) { - singlePost = ref[k]; - 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() { - return RemoveSpoilers.unspoiler(this.nodes.comment); - }, - unspoiler: function(el) { - var k, len1, span, spoiler, spoilers; - spoilers = $$('s', el); - for (k = 0, len1 = spoilers.length; k < len1; k++) { - spoiler = spoilers[k]; - span = $.el('span', { - className: 'removed-spoiler' - }); - $.replace(spoiler, span); - $.add(span, slice.call(spoiler.childNodes)); - } - } - }; - - Report = { - css: "#g-recaptcha,\n" + -":root:not(.js-enabled) #captchaContainerAlt {\n" + -" height: auto;\n" + -"}\n" + -"#captchaContainerAlt td:nth-child(2) {\n" + -" display: table-cell !important;\n" + -"}", - init: function() { - var match; - if (!(match = location.search.match(/\bno=(\d+)/))) { - return; - } - Captcha.replace.init(); - this.postID = +match[1]; - return $.ready(this.ready); - }, - ready: function() { - var passAd, prev, ref; - $.addStyle(Report.css); - if (Conf['Archive Report']) { - Report.archive(); - } - if ((passAd = $('a[href="https://www.4chan.org/pass"]'))) { - $.extend(passAd, { - textContent: 'Complain', - href: 'https://www.4chan-x.net/captchas.html', - tabIndex: -1 - }); - passAd.parentNode.normalize(); - if (((ref = (prev = passAd.previousSibling)) != null ? ref.nodeType : void 0) === Node.TEXT_NODE) { - prev.nodeValue = prev.nodeValue.replace(/4chan Pass[^\.]*\./i, 'reCAPTCHA malfunctioning?'); - } - $.after(passAd, [ - $.tn('] ['), $.el('a', { - href: 'mailto:4chanpass@4chan.org?subject=4chan%20Pass%20-%20Purchase%20Support', - textContent: 'Email 4chan', - target: '_blank', - tabIndex: -1 - }) - ]); - } - if (!Conf['Use Recaptcha v1 in Reports'] && !Conf['Force Noscript Captcha'] && Main.jsEnabled) { - return new MutationObserver(function() { - Report.fit('iframe[src^="https://www.google.com/recaptcha/api2/frame"]'); - return Report.fit('body'); - }).observe(d.body, { - childList: true, - attributes: true, - subtree: true - }); - } else { - return Report.fit('body'); - } - }, - fit: function(selector) { - var dy, el; - if (!((el = $(selector, doc)) && getComputedStyle(el).visibility !== 'hidden')) { - return; - } - dy = el.getBoundingClientRect().bottom - doc.clientHeight + 8; - if (dy > 0) { - return window.resizeBy(0, dy); - } - }, - archive: function() { - var link, message, types, url; - Redirect.init(); - if (!(url = Redirect.to('report', { - boardID: g.BOARD.ID, - postID: Report.postID - }))) { - return; - } - if ((message = $('h3')) && /Report submitted!/.test(message.textContent)) { - if (location.hash === '#redirect') { - $.globalEval('self.close = function(){};'); - window.resizeTo(700, 475); - location.replace(url); - } - return; - } - link = $.el('a', { - href: url, - textContent: 'Report to archive' - }); - $.on(link, 'click', function(e) { - if (!(e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0)) { - return window.resizeTo(700, 475); - } - }); - $.add(d.body, [$.tn(' ['), link, $.tn(']')]); - if (types = $.id('reportTypes')) { - return $.on(types, 'change', function(e) { - return $('form').action = e.target.value === 'illegal' ? '#redirect' : ''; - }); - } - } - }; - - ThreadLinks = { - init: function() { - if (!(g.VIEW === 'index' && Conf['Open Threads in New Tab'])) { - return; - } - Post.callbacks.push({ - name: 'Thread Links', - cb: this.node - }); - return CatalogThread.callbacks.push({ - name: 'Thread Links', - cb: this.catalogNode - }); - }, - node: function() { - if (this.isReply || this.isClone) { - return; - } - return ThreadLinks.process($('.replylink', this.nodes.info)); - }, - catalogNode: function() { - return ThreadLinks.process(this.nodes.thumb.parentNode); - }, - process: function(link) { - return link.target = '_blank'; - } - }; - - 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']) { - if ($.hasStorage) { - settings = JSON.parse(localStorage.getItem('4chan-settings')) || {}; - if (settings.disableAll) { - return; - } - settings.disableAll = true; - return localStorage.setItem('4chan-settings', JSON.stringify(settings)); - } else { - return $.onExists(doc, 'body', function() { - return $.global(function() { - return window.Config.disableAll = true; - }); - }); - } - } - }, - open: function(openSection) { - var dialog, k, len1, link, links, overlay, ref, section, sectionToOpen; - if (Settings.overlay) { - return; - } - $.event('CloseMenu'); - Settings.dialog = dialog = $.el('div', { - id: 'fourchanx-settings', - className: 'dialog' - }); - $.extend(dialog, { - innerHTML: "
      " - }); - 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 (k = 0, len1 = ref.length; k < len1; k++) { - section = ref[k]; - 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); - }, - warnings: { - localStorage: function(cb) { - var why; - if ($.cantSync) { - why = $.cantSet ? 'save your settings' : 'synchronize settings between tabs'; - return cb($.el('li', { - textContent: "4chan X needs local storage to " + why + ".\nEnable it on boards.4chan.org in your browser's privacy settings (may be listed as part of \"local data\" or \"cookies\")." - })); - } - }, - ads: function(cb) { - return $.onExists(doc, '.ad-cnt', function(ad) { - return $.onExists(ad, 'img', function() { - return cb($.el('li', { - innerHTML: "To protect yourself from malicious ads, you should block ads on 4chan." - })); - }); - }); - } - }, - main: function(section) { - var addWarning, arr, button, container, containers, description, div, fs, input, inputs, items, key, level, obj, ref, ref1, warning, warnings; - warnings = $.el('fieldset', { - hidden: true - }, { - innerHTML: "Warnings
        " - }); - addWarning = function(item) { - $.add($('ul', warnings), item); - return warnings.hidden = false; - }; - ref = Settings.warnings; - for (key in ref) { - warning = ref[key]; - warning(addWarning); - } - $.add(section, warnings); - items = {}; - inputs = {}; - ref1 = Config.main; - for (key in ref1) { - obj = ref1[key]; - fs = $.el('fieldset', { - innerHTML: "" + E(key) + "" - }); - containers = [fs]; - for (key in obj) { - arr = obj[key]; - description = arr[1]; - div = $.el('div', { - innerHTML: ": " + E(description) + "" - }); - if ($.engine !== 'gecko' && key === 'Remember QR Size') { - div.hidden = true; - } - 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: ": 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, ref2, ref3, thread; - hiddenThreads = arg.hiddenThreads, hiddenPosts = arg.hiddenPosts; - hiddenNum = 0; - ref2 = hiddenThreads.boards; - for (ID in ref2) { - board = ref2[ID]; - hiddenNum += Object.keys(board).length; - } - ref3 = hiddenPosts.boards; - for (ID in ref3) { - board = ref3[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; - if ($.hasStorage) { - 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) { - 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; - } - this.value = null; - 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 { - return Settings.loadSettings(JSON.parse(e.target.result), function(err) { - if (err) { - return output.textContent = 'Import failed due to an error.'; - } else 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); - }, - convertFrom: { - loadletter: function(data) { - var base1, boardID, convertSettings, key, ref, ref1, threadData, threadID, threads, val; - 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': 'Disable Native Extension', - 'Comment Auto-Expansion': '', - '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', - 'Current Page': 'Page Count in Stats', - 'Current Page Position': '', - 'Alternative captcha': 'Use Recaptcha v1', - 'Auto Submit': 'Post on Captcha Completion', - '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()); - }); - } - } - if (data.WatchedThreads) { - data.Conf['watchedThreads'] = { - boards: {} - }; - ref1 = data.WatchedThreads; - for (boardID in ref1) { - threads = ref1[boardID]; - for (threadID in threads) { - threadData = threads[threadID]; - ((base1 = data.Conf['watchedThreads'].boards)[boardID] || (base1[boardID] = {}))[threadID] = { - excerpt: threadData.textContent - }; - } - } - } - return data; - } - }, - upgrade: function(data, version) { - var boardID, changes, compareString, k, key, len1, name, record, ref, ref1, ref2, ref3, ref4, ref5, rice, set, type, uids, value; - changes = {}; - set = function(key, value) { - return data[key] = changes[key] = value; - }; - compareString = version.replace(/\d+/g, function(x) { - return ('0000' + x).slice(-5); - }); - if (compareString < '00001.00011.00008.00000') { - if (data['Fixed Thread Watcher'] == null) { - set('Fixed Thread Watcher', (ref = data['Toggleable Thread Watcher']) != null ? ref : true); - } - if (data['Exempt Archives from Encryption'] == null) { - set('Exempt Archives from Encryption', (ref1 = data['Except Archives from Encryption']) != null ? ref1 : false); - } - } - if (compareString < '00001.00011.00010.00001') { - if (data['selectedArchives'] != null) { - uids = { - "Moe": 0, - "4plebs Archive": 3, - "Nyafuu Archive": 4, - "Love is Over": 5, - "Rebecca Black Tech": 8, - "warosu": 10, - "fgts": 15, - "not4plebs": 22, - "DesuStorage": 23, - "fireden.net": 24, - "disabled": null - }; - ref2 = data['selectedArchives']; - for (boardID in ref2) { - record = ref2[boardID]; - for (type in record) { - name = record[type]; - if (name in uids) { - record[type] = uids[name]; - } - } - } - set('selectedArchives', data['selectedArchives']); - } - } - if (compareString < '00001.00011.00016.00000') { - if ((rice = Config['usercss'].match(/\/\* Board title rice \*\/(?:\n.+)*/)[0])) { - if ((data['usercss'] != null) && data['usercss'].indexOf(rice) < 0) { - set('usercss', rice + '\n\n' + data['usercss']); - } - } - } - if (compareString < '00001.00011.00017.00000') { - ref3 = ['Persistent QR', 'Color User IDs', 'Fappe Tyme', 'Werk Tyme', 'Highlight Posts Quoting You', 'Highlight Own Posts']; - for (k = 0, len1 = ref3.length; k < len1; k++) { - key = ref3[k]; - if (data[key] == null) { - set(key, key === 'Persistent QR'); - } - } - } - if (compareString < '00001.00011.00017.00006') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/^(#?\s*)http:\/\/iqdb\.org\//mg, '$1//iqdb.org/')); - } - } - if (compareString < '00001.00011.00019.00003' && !Settings.overlay) { - $.queueTask(function() { - return Settings.warnings.ads(function(item) { - return new Notice('warning', slice.call(item.childNodes)); - }); - }); - } - if (compareString < '00001.00011.00020.00003') { - ref4 = { - 'Inline Cross-thread Quotes Only': false, - 'Pass Link': true - }; - for (key in ref4) { - value = ref4[key]; - if (data[key] == null) { - set(key, value); - } - } - } - if (compareString < '00001.00011.00021.00003') { - if (data['Remember Your Posts'] == null) { - set('Remember Your Posts', (ref5 = data['Mark Quotes of You']) != null ? ref5 : true); - } - } - if (compareString < '00001.00011.00022.00000') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/^(#?\s*https:\/\/www\.google\.com\/searchbyimage\?image_url=%(?:IMG|URL))%3Fs\.jpg/mg, '$1')); - set('sauces', data['sauces'].replace(/^#?\s*https:\/\/www\.google\.com\/searchbyimage\?image_url=%(?:IMG|T?URL)(?=$|;)/mg, '$&&safe=off')); - } - } - if (compareString < '00001.00011.00022.00002') { - if ((data['Use Recaptcha v1 in Reports'] == null) && data['Use Recaptcha v1'] && !data['Use Recaptcha v2 in Reports']) { - set('Use Recaptcha v1 in Reports', true); - } - } - if (compareString < '00001.00011.00024.00000') { - if ((data['JSON Navigation'] != null) && (data['JSON Index'] == null)) { - set('JSON Index', data['JSON Navigation']); - } - } - if (compareString < '00001.00011.00026.00000') { - if ((data['Oekaki Links'] != null) && (data['Edit Link'] == null)) { - set('Edit Link', data['Oekaki Links']); - } - if (data['Inline Cross-thread Quotes Only'] == null) { - set('Inline Cross-thread Quotes Only', true); - } - } - if (compareString < '00001.00011.00030.00000') { - if (data['Quote Threading'] && (data['Thread Quotes'] == null)) { - set('Thread Quotes', true); - } - } - return changes; - }, - loadSettings: function(data, cb) { - if (data.version.split('.')[0] === '2') { - data = Settings.convertFrom.loadletter(data); - } else if (data.version !== g.VERSION) { - Settings.upgrade(data.Conf, data.version); - } - return $.clear(function(err) { - if (err) { - return cb(err); - } - return $.set(data.Conf, cb); - }); - }, - reset: function() { - if (confirm('Your current settings will be entirely wiped, are you sure?')) { - return $.clear(function(err) { - if (err) { - return $('.imp-exp-result').textContent = 'Import failed due to an error.'; - } else if (confirm('Reset successful. Reload now?')) { - return window.location.reload(); - } - }); - } - }, - filter: function(section) { - var select; - $.extend(section, { - innerHTML: "
        " - }); - select = $('select', section); - $.on(select, 'change', Settings.selectFilter); - return Settings.selectFilter.call(select); - }, - selectFilter: function() { - var div, name, ta; - div = this.nextElementSibling; - if ((name = this.value) !== 'guide') { - $.rmAll(div); - ta = $.el('textarea', { - name: name, - className: 'field', - spellcheck: false - }); - $.get(name, Conf[name], function(item) { - return ta.value = item[name]; - }); - $.on(ta, 'change', $.cb.value); - $.add(div, ta); - return; - } - $.extend(div, { - innerHTML: "
        Filter is disabled.

        Use regular expressions, one per line.
        Lines starting with a # will be ignored.
        For example, /weeaboo/i will filter posts containing the string \`weeaboo\`, case-insensitive.
        MD5 filtering uses exact string matching, not regular expressions.

          You can use these settings with each regular expression, separate them with semicolons:
        • Per boards, separate them with commas. It is global if not specified.
          For example: boards:a,jp;.
        • In case of a global rule, select boards to be excluded from the filter.
          For example: exclude:vg,v;.
        • Filter OPs only along with their threads (\`only\`), replies only (\`no\`), or both (\`yes\`, this is default).
          For example: op:only;, op:no; or op:yes;.
        • Overrule the \`Show Stubs\` setting if specified: create a stub (\`yes\`) or not (\`no\`).
          For example: stub:yes; or stub:no;.
        • Highlight instead of hiding. You can specify a class name to use with a userstyle.
          For example: highlight; or highlight:wallpaper;.
        • Highlighted OPs will have their threads put on top of the board index by default.
          For example: top:yes; or top:no;.

        Note: If you're using the native catalog rather than 4chan X's catalog, 4chan X's filters do not apply there.
        The native catalog has its own separate filter list.

        " - }); - return $('.warning', div).hidden = Conf['Filter']; - }, - sauce: function(section) { - var ta; - $.extend(section, { - innerHTML: "
        Sauce is disabled.
        Lines starting with a # will be ignored.
        You can specify a display text by appending ;text:[text] to the URL.
        You can specify the applicable boards by appending ;boards:[board1],[board2].
        You can specify the applicable file types by appending ;types:[extension1],[extension2].
        You can open links with scripts and popups disabled by appending ;sandbox.
          These parameters will be replaced by their corresponding values:
        • %TURL: Thumbnail URL.
        • %URL: Full image URL.
        • %IMG: Full image URL for GIF, JPG, and PNG; thumbnail URL for other types.
        • %MD5: MD5 hash in base64.
        • %sMD5: MD5 hash in base64 using - and _.
        • %hMD5: MD5 hash in hexadecimal.
        • %name: Original file name.
        • %board: Current board.
        • %%, %semi: Literal % and ;.
        " - }); - $('.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 aa, ab, applyCSS, archBoards, archive, boardID, boardOptions, boardSelect, boards, customCSS, files, i, input, inputs, interval, item, items, k, len1, len2, len3, len4, len5, len6, len7, name, o, q, ref, ref1, ref2, ref3, ref4, ref5, ref6, row, rows, software, ta, table, u, uid, v, warning, withCredentials, z; - $.extend(section, { - innerHTML: "
        Archiver
        404 Redirect is disabled.
        Thread redirectionPost fetchingFile redirection
        Captcha Language
        Choose from list of language codes. Leave blank to autoselect.
        Custom Board Navigation
        New lines will be converted into spaces.

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

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

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

          You can use these settings with each item, separate them with semicolons:
        • Possible items are: name, options (or equivalently email), subject and password.
        • Wrap values of items with quotes, like this: options:"sage".
        • Force values as defaults with the always keyword, for example: options:"sage";always.
        • Select specific boards for an item, separated with commas, for example: options:"sage";boards:jp;always.
        Unread Favicon is disabled.
        Thread Updater is disabled.
        Interval: seconds
        Custom Cooldown Time
        Seconds:
        " - }); - ref = $$('.warning', section); - for (k = 0, len1 = ref.length; k < len1; k++) { - warning = ref[k]; - warning.hidden = Conf[warning.dataset.feature]; - } - items = {}; - inputs = {}; - ref1 = ['captchaLanguage', 'boardnav', 'time', 'backlink', 'fileInfo', 'favicon', 'usercss', 'customCooldown']; - for (q = 0, len2 = ref1.length; q < len2; q++) { - name = ref1[q]; - 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); - if (name in Settings) { - $.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 in Settings && key !== 'usercss') { - 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 (u = 0, len3 = ref2.length; u < len3; u++) { - ref3 = ref2[u], uid = ref3.uid, name = ref3.name, boards = ref3.boards, files = ref3.files, software = ref3.software, withCredentials = ref3.withCredentials; - for (v = 0, len4 = boards.length; v < len4; v++) { - boardID = boards[v]; - o = archBoards[boardID] || (archBoards[boardID] = { - thread: [[], []], - post: [[], []], - file: [[], []] - }); - i = +(!!withCredentials); - archive = [uid != null ? uid : name, name]; - o.thread[i].push(archive); - if (software === 'foolfuuka') { - o.post[i].push(archive); - } - if (indexOf.call(files, boardID) >= 0) { - o.file[i].push(archive); - } - } - } - for (boardID in archBoards) { - o = archBoards[boardID]; - ref4 = ['thread', 'post', 'file']; - for (z = 0, len5 = ref4.length; z < len5; z++) { - item = ref4[z]; - i = o[item][0].length ? 1 : 0; - o[item][i].push([null, 'disabled']); - o[item] = o[item][0].concat(o[item][1]); - } - } - rows = []; - boardOptions = []; - ref5 = Object.keys(archBoards).sort(); - for (aa = 0, len6 = ref5.length; aa < len6; aa++) { - boardID = ref5[aa]; - 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 (ab = 0, len7 = ref6.length; ab < len7; ab++) { - item = ref6[ab]; - $.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, id, select, selectedArchives, type; - selectedArchives = arg.selectedArchives; - for (boardID in selectedArchives) { - data = selectedArchives[boardID]; - for (type in data) { - id = data[type]; - if (select = $("select[data-boardid='" + boardID + "'][data-type='" + type + "']", section)) { - select.value = JSON.stringify(id); - } - } - } - }); - }, - 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', { - value: JSON.stringify(archive[0]), - textContent: archive[1] - })); - } - $.extend(td, { - innerHTML: "" - }); - select = td.firstElementChild; - if (!(select.disabled = length === 1)) { - select.setAttribute('data-boardid', boardID); - select.setAttribute('data-type', type); - $.on(select, 'change', Settings.saveSelectedArchive); - } - $.add(select, options); - return td; - }, - saveSelectedArchive: function() { - return $.get('selectedArchives', Conf['selectedArchives'], (function(_this) { - return function(arg) { - var name1, selectedArchives; - selectedArchives = arg.selectedArchives; - (selectedArchives[name1 = _this.dataset.boardid] || (selectedArchives[name1] = {}))[_this.dataset.type] = JSON.parse(_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, - isVideo: false, - isSpoiler: true, - tag: 'Loop' - } - }; - 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, ref, tbody, tr; - $.extend(section, { - innerHTML: "
        Keybinds are disabled.
        Allowed keys: a-z, 0-9, Ctrl, Shift, Alt, Meta, Enter, Esc, Up, Down, Right, Left.
        Press Backspace to disable a keybind.
        ActionsKeybinds
        " - }); - $('.warning', section).hidden = Conf['Keybinds']; - tbody = $('tbody', section); - items = {}; - inputs = {}; - ref = Config.hotkeys; - for (key in ref) { - arr = ref[key]; - tr = $.el('tr', { - innerHTML: "" + E(arr[1]) + "" - }); - input = $('input', tr); - input.name = key; - input.spellcheck = false; - items[key] = Conf[key]; - inputs[key] = input; - $.on(input, 'keydown', Settings.keybind); - $.add(tbody, tr); - } - return $.get(items, function(items) { - var val; - for (key in items) { - val = items[key]; - inputs[key].value = val; - } - }); - }, - keybind: function(e) { - var key; - if (e.keyCode === 9) { - return; - } - e.preventDefault(); - e.stopPropagation(); - if ((key = Keybinds.keyCode(e)) == null) { - return; - } - this.value = key; - return $.cb.value.call(this); - } - }; - - Main = { - init: function() { - var db, flatten, items, k, key, len1, ref; - if (d.body && !$('title', d.head)) { - return; - } - if (window['4chan X antidup']) { - return; - } - window['4chan X antidup'] = true; - if (location.hostname === 'www.google.com') { - $.get('Captcha Fixes', true, function(arg) { - var enabled; - enabled = arg['Captcha Fixes']; - if (enabled) { - return $.ready(function() { - return Captcha.fixes.init(); - }); - } - }); - return; - } - $.global(function() { - var k, len1, nuke, prop, ref; - nuke = function(obj, prop) { - try { - return Object.defineProperty(obj, prop, { - configurable: false, - get: function() { - throw new Error(); - }, - set: function() { - throw new Error(); - } - }); - } catch (_error) {} - }; - ref = ['atOptions', 'adsterra_key', 'EpmadsConfig', 'epmads_key', 'EpomConfig', 'epom_key', 'exoDocumentProtocol']; - for (k = 0, len1 = ref.length; k < len1; k++) { - prop = ref[k]; - nuke(window, prop); - } - }); - $.on(window, 'beforescriptexecute', function(e) { - var host, ref, ref1; - host = (ref = e.target.src.split('/')[2]) != null ? (ref1 = ref.match(/[^.]+\.[^.]+$/)) != null ? ref1[0] : void 0 : void 0; - if (host === 'bnhtml.com' || host === 'ecpmrocks.com' || host === 'advertisation.com' || host === 'exoclick.com') { - return e.preventDefault(); - } - }); - $.on(d, '4chanXInitFinished', function() { - if (Main.expectInitFinished) { - return delete Main.expectInitFinished; - } else { - new Notice('error', 'Error: Multiple copies of 4chan X are enabled.'); - return $.addClass(doc, 'tainted'); - } - }); - 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); - ref = DataBoard.keys; - for (k = 0, len1 = ref.length; k < len1; k++) { - db = ref[k]; - Conf[db] = { - boards: {} - }; - } - Conf['selectedArchives'] = {}; - Conf['cooldowns'] = {}; - Conf['Index Sort'] = {}; - Conf['Except Archives from Encryption'] = false; - Conf['JSON Navigation'] = true; - Conf['Oekaki Links'] = true; - items = {}; - for (key in Conf) { - items[key] = void 0; - } - items['previousversion'] = void 0; - return $.get(items, function(items) { - return $.asap((function() { - return doc = d.documentElement; - }), function() { - var ref1, val; - if ($.cantSet) { - - } else if (items.previousversion == null) { - Main.ready(function() { - $.set('previousversion', g.VERSION); - return Settings.open(); - }); - } else if (items.previousversion !== g.VERSION) { - Main.upgrade(items); - } - for (key in Conf) { - val = Conf[key]; - Conf[key] = (ref1 = items[key]) != null ? ref1 : val; - } - return Main.initFeatures(); - }); - }); - }, - upgrade: function(items) { - var changes, previousversion; - previousversion = items.previousversion; - changes = Settings.upgrade(items, previousversion); - items.previousversion = changes.previousversion = g.VERSION; - return $.set(changes, function() { - var el, ref; - if ((ref = items['Show Updated Notifications']) != null ? ref : true) { - el = $.el('span', { - innerHTML: "4chan X has been updated to version " + E(g.VERSION) + "." - }); - return new Notice('info', el, 15); - } - }); - }, - initFeatures: function() { - var err, feature, hostname, k, len1, match, name, pathname, ref, ref1, ref2, ref3, search; - hostname = location.hostname, search = location.search; - pathname = location.pathname.split(/\/+/); - if (hostname !== 'www.4chan.org') { - g.BOARD = new Board(pathname[1]); - } - if (hostname === 'boards.4chan.org' || hostname === 'sys.4chan.org' || hostname === 'www.4chan.org') { - $.global(function() { - document.documentElement.classList.add('js-enabled'); - return window.FCX = {}; - }); - Main.jsEnabled = $.hasClass(doc, 'js-enabled'); - } - switch (hostname) { - case 'www.4chan.org': - $.onExists(doc, 'body', function() { - return $.addStyle(Main.cssWWW); - }); - Captcha.replace.init(); - return; - case 'sys.4chan.org': - if (pathname[2] === 'imgboard.php') { - if (/\bmode=report\b/.test(search)) { - Report.init(); - } else if ((match = search.match(/\bres=(\d+)/))) { - $.ready(function() { - var ref; - if (Conf['404 Redirect'] && ((ref = $.id('errmsg')) != null ? ref.textContent : void 0) === 'Error: Specified thread does not exist.') { - return Redirect.navigate('thread', { - boardID: g.BOARD.ID, - postID: +match[1] - }); - } - }); - } - } else if (pathname[2] === 'post') { - PostSuccessful.init(); - } - return; - case 'i.4cdn.org': - if (!(pathname[2] && !/s\.jpg$/.test(pathname[2]))) { - return; - } - $.asap((function() { - return d.readyState !== 'loading'; - }), function() { - var ref, video; - if (Conf['404 Redirect'] && ((ref = d.title) === '4chan - Temporarily Offline' || ref === '4chan - 404 Not Found')) { - return Redirect.navigate('file', { - boardID: g.BOARD.ID, - filename: pathname[pathname.length - 1] - }); - } 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 ((ref = pathname[2]) === 'thread' || ref === 'res') { - g.VIEW = 'thread'; - g.THREADID = +pathname[3]; - } else if ((ref1 = pathname[2]) === 'catalog' || ref1 === 'archive') { - g.VIEW = pathname[2]; - } else if (pathname[2].match(/^\d*$/)) { - g.VIEW = 'index'; - } else { - return; - } - g.threads = new SimpleDict(); - g.posts = new SimpleDict(); - $.onExists(doc, 'body', Main.initStyle); - ref2 = Main.features; - for (k = 0, len1 = ref2.length; k < len1; k++) { - ref3 = ref2[k], name = ref3[0], feature = ref3[1]; - try { - feature.init(); - } catch (_error) { - err = _error; - Main.handleErrors({ - message: "\"" + name + "\" initialization crashed.", - error: err - }); - } - } - return $.ready(Main.initReady); - }, - initStyle: function() { - var keyboard, ref; - if (!Main.isThisPageLegit()) { - 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); - if ($.engine) { - $.addClass(doc, $.engine); - } - $.onExists(doc, '.ad-cnt', function(ad) { - return $.onExists(ad, 'img', function() { - return $.addClass(doc, 'ads-loaded'); - }); - }); - if (Conf['Autohiding Scrollbar']) { - $.addClass(doc, 'autohiding-scrollbar'); - } - $.ready(function() { - if (d.body.clientHeight > doc.clientHeight && (window.innerWidth === doc.clientWidth) !== Conf['Autohiding Scrollbar']) { - Conf['Autohiding Scrollbar'] = !Conf['Autohiding Scrollbar']; - $.set('Autohiding Scrollbar', Conf['Autohiding Scrollbar']); - return $.toggleClass(doc, 'autohiding-scrollbar'); - } - }); - $.addStyle(Main.css, 'fourchanx-css'); - Main.bgColorStyle = $.el('style', { - id: 'fourchanx-bgcolor-css' - }); - keyboard = false; - $.on(d, 'mousedown', function() { - return keyboard = false; - }); - $.on(d, 'keydown', function(e) { - if (e.keyCode === 9) { - return keyboard = true; - } - }); - window.addEventListener('focus', (function() { - return doc.classList.toggle('keyboard-focus', keyboard); - }), true); - 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 bgColor, div, k, len1, styleSheet; - $.rmClass(doc, style); - style = null; - for (k = 0, len1 = styleSheets.length; k < len1; k++) { - styleSheet = styleSheets[k]; - if (styleSheet.href === (mainStyleSheet != null ? mainStyleSheet.href : void 0)) { - style = styleSheet.title.toLowerCase().replace('new', '').trim().replace(/\s+/g, '-'); - break; - } - } - if (style) { - $.addClass(doc, style); - return $.rm(Main.bgColorStyle); - } else { - div = $.el('div', { - className: 'reply' - }); - div.style.cssText = 'position: absolute; visibility: hidden;'; - $.add(d.body, div); - bgColor = window.getComputedStyle(div).backgroundColor; - $.rm(div); - Main.bgColorStyle.textContent = ".dialog, .suboption-list > div:last-of-type {\n background-color: " + bgColor + ";\n}"; - return $.after($.id('fourchanx-css'), Main.bgColorStyle); - } - }; - setStyle(); - if (!mainStyleSheet) { - return; - } - return new MutationObserver(setStyle).observe(mainStyleSheet, { - attributes: true, - attributeFilter: ['href'] - }); - }, - initReady: function() { - var msg, ref, ref1, ref2; - if (g.VIEW === 'thread' && (((ref = d.title) === '4chan - Temporarily Offline' || ref === '4chan - 404 Not Found') || ($('.board') && !$('.opContainer')))) { - ThreadWatcher.set404(g.BOARD.ID, g.THREADID, function() { - if (Conf['404 Redirect']) { - return Redirect.navigate('thread', { - boardID: g.BOARD.ID, - threadID: g.THREADID, - postID: +location.hash.match(/\d+/) - }, "/" + g.BOARD + "/"); - } - }); - return; - } - if ((ref1 = d.title) === '4chan - Temporarily Offline' || ref1 === '4chan - 404 Not Found') { - return; - } - if (((ref2 = g.VIEW) === 'index' || ref2 === 'thread') && !$('.board + *')) { - msg = $.el('div', { - innerHTML: "The page didn't load completely.
        Some features may not work unless you reload." - }); - $.on($('a', msg), 'click', function() { - return location.reload(); - }); - new Notice('warning', msg); - } - if (!(Conf['JSON Index'] && g.VIEW === 'index')) { - return Main.initThread(); - } else { - Main.expectInitFinished = true; - return $.event('4chanXInitFinished'); - } - }, - initThread: function() { - var board, err, errors, k, len1, len2, m, postRoot, posts, q, ref, ref1, scriptData, thread, threadRoot, threads; - if ((board = $('.board'))) { - threads = []; - posts = []; - ref = $$('.board > .thread', board); - for (k = 0, len1 = ref.length; k < len1; k++) { - threadRoot = ref[k]; - thread = new Thread(+threadRoot.id.slice(1), g.BOARD); - threads.push(thread); - ref1 = $$('.thread > .postContainer', threadRoot); - for (q = 0, len2 = ref1.length; q < len2; q++) { - postRoot = ref1[q]; - if ($('.postMessage', postRoot)) { - 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 len3, post, u; - for (u = 0, len3 = posts.length; u < len3; u++) { - post = posts[u]; - QuoteThreading.insert(post); - } - Main.expectInitFinished = true; - return $.event('4chanXInitFinished'); - }); - } else { - Main.expectInitFinished = true; - 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, k, len1, logs; - if (!(errors instanceof Array)) { - error = errors; - } else if (errors.length === 1) { - error = errors[0]; - } - if (error) { - new Notice('error', Main.parseError(error, Main.reportLink([error])), 15); - return; - } - div = $.el('div', { - innerHTML: E(errors.length) + " errors occurred." + Main.reportLink(errors).innerHTML + " [show]" - }); - $.on(div.lastElementChild, 'click', function() { - var ref; - return ref = this.textContent === 'show' ? ['hide', false] : ['show', true], this.textContent = ref[0], logs.hidden = ref[1], ref; - }); - logs = $.el('div', { - hidden: true - }); - for (k = 0, len1 = errors.length; k < len1; k++) { - error = errors[k]; - $.add(logs, Main.parseError(error)); - } - return new Notice('error', [div, logs], 30); - }, - parseError: function(data, reportLink) { - var context, error, lines, message, ref, ref1; - c.error(data.message, data.error.stack); - message = $.el('div', { - innerHTML: E(data.message) + (reportLink ? reportLink.innerHTML : "") - }); - error = $.el('div', { - textContent: (data.error.name || 'Error') + ": " + (data.error.message || 'see console for details') - }); - lines = ((ref = data.error.stack) != null ? (ref1 = ref.match(/\d+(?=:\d+\)?$)/mg)) != null ? ref1.join().replace(/^/, ' at ') : void 0 : void 0) || ''; - context = $.el('div', { - textContent: "(4chan X ccd0 v" + g.VERSION + " userscript on " + $.engine + lines + ")" - }); - return [message, error, context]; - }, - reportLink: function(errors) { - var data, details, ref, title, url; - data = errors[0]; - title = data.message; - if (errors.length > 1) { - title += " (+" + (errors.length - 1) + " other errors)"; - } - details = "[Please describe the steps needed to reproduce this error.]\n\nScript: 4chan X ccd0 v" + g.VERSION + " userscript\nUser agent: " + navigator.userAgent + "\nURL: " + location.href + "\n\n" + data.error + "\n" + (((ref = data.error.stack) != null ? ref.replace(data.error.toString(), '').trim() : void 0) || ''); - details = details.replace(/file:\/{3}.+\//g, ''); - url = "https://gitreports.com/issue/ccd0/4chan-x?issue_title=" + (encodeURIComponent(title)) + "&details=" + (encodeURIComponent(details)); - return { - innerHTML: " [report]" - }; - }, - 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: "/*!\n" + -" * Font Awesome 4.5.0 by @davegandy - http://fontawesome.io - @fontawesome\n" + +boards: +"/*!\n" + +" * Font Awesome 4.6.1 by @davegandy - http://fontawesome.io - @fontawesome\n" + " * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)\n" + " */\n" + "@font-face {\n" + " font-family: FontAwesome;\n" + -" src: url('data:application/font-woff;base64,d09GRgABAAAAAUaEAA4AAAACKvgAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAABRAAAABwAAAAcagNvKUdERUYAAAFgAAAAHwAAACACtAAET1MvMgAAAYAAAAA/AAAAYIhZeh5jbWFwAAABwAAAAXcAAALyp8d/bWdhc3AAAAM4AAAACAAAAAj//wADZ2x5ZgAAA0AAASr8AAH7LBMsk3FoZWFkAAEuPAAAADEAAAA2DQzHVWhoZWEAAS5wAAAAHwAAACQPAwpbaG10eAABLpAAAAK8AAAKCpMpFypsb2NhAAExTAAABPUAAAUQaY3nVm1heHAAATZEAAAAHwAAACAC8AIcbmFtZQABNmQAAAGhAAADiDNGhcdwb3N0AAE4CAAADnIAABggxzdjQXdlYmYAAUZ8AAAABgAAAAaOKlZPAAAAAQAAAADMPaLPAAAAAMtQjbAAAAAA0nU+qXjaY2BkYGDgA2IJBhBgYmBkYGRqA5IsYB4DAAokALsAeNpjYGZzZ5zAwMrAwtLDYszAwNAGoZmKGRgYuxjwgILKomIGBwaFrwxsDP+BfDYGRmUgxYikRIGBEQDIZghzAHjazZI/a9pxEMbvZ4xJE+pd/jWxDfan0DWVvAARsotDlgy1Dp3FVyBOHcVXII7tIlI6hAwlU8bgWAIaIYP5Y9J7rk3SNtZvfqkQaKFLh9KDe44HHu4DxxHRBI17lbxAyRsEzvvpw147mCXK0CSlyKcGvaUmvac9+ujP+M/9l4lkMp4sPBtqVOOa1qzmtahlrWpdm/pO97WrFzpCFHGsIY0s8iiijCrqaOID9tHFBUYWtbilLWt5K1rZqla/JOcC8h3xzT2RfiGSiiY0ozktaEkrWtOGtnRX29pTBUHgI4UMciighApqaKCFXbTRgxqZWMIylrOClaxitTuiO3Kv3Au35TbdhlvvzR72D7e7V52bzs7BU1mVJxKTFVmWR7Iki7Ig8zInYZmQkHhC7HjEP3jIN/ydv/FXvuYrvuQv/JmNwcqf+JwHfManfMLH3H/4enztf1tehO6xXiiQ0O+B8Sv8DzUVWZmefPxgJvbHRPiv9t4CzlS31QAAAAAB//8AAnjavL0JfFTV2TB+zzl3mX3mzp0tk8lkJrMmgSTMGrIOYScB2QQExIiiCC6oIIgLo1AVxA0UqVaNWlG6vXaxX6viO920m9S21G5+/WJb275VW9+2P1shc/k/59yZySQkon3/3weZe8++Puec53nO8zyXw9wWjiM2ER6cxHHZoBwkclAeRgU1twUPbRECJ7eI3EmO/kNc1b9p1H/+aU58UshzdeBxSEgOJlwOMRRsiKYyyaCMoulUD0oGE34kPtlcvAPlvNGodyRPnyhXvKM5HHcLeXc8LMwJQXSRi6ai8Ec4vKM55K7V6WpZnVAHB3U0g0d2WHBDC0714GTCLQtjvalMFmWSCZfIzdp46epLN86C19TLVhbHeqN+kjPZ4u1C4NRQYlGz09m86GJ4xXDNu8XO6gDySn3SgDi+ncOsDXlog8QFoes2LkB/CLraEEPwCEexzZ4JB3iX3QnD4OLz6gfq3eoHSELXEGkglQmrR7/8xj3qqWNXXXUMCciPhGNX3YhWRjAkQJKWWM2nBqJoxY2jKa46pp66540vq0cjdHa403mJEzjOy3VzCzkuIosSL1lwM4wAikUj0ZjscMFYZ+Qu3EJgDkSnw+1y+/lOnOgh2Uy2B2VlbXLSMp0eGKh8IKL+49Fk7oo2hNquyCUfVf8RCShmoWBWkCCadCdzZuXgN14TOxqyLQ6EHC3Zhg7xtW9kzs+v6zuZ61u3rk8o9K0LEC7sP76nuW3atLbmPcf94SJnVhQ+ju16WWcQFPMzWw8/JUzzRuz2iHea8NTh5vsGTxVobp6Woc0x7Vue83EcD0PawqehhQk/dvcQmFA6puShlL14ryE00NWqDvfcctXicHjxVbf0DKtvFe/L2/FqXfiCi++e+ca/mufnwuHc/OZ/vfG/3yo+o5X9eZi7Ya5Bg1EFiqPzFhHgCQCaVSiYZiNKJuFWBBgTr/rACuR0KE61V+2FCXXiFer9Ne3o/TeVLuVN9H47ud7lVR9VTZLZWWd65x1TnVO0oH+g9bXOiH4+eqWxUZ0+X0+XCK7UrafQq0cRI0wtiQjldkzeDP5qlFBXHzumrkaJ+Wgnuh69wtrVOHmzsAM19qCb1Vt71J+ra155hRjKzUx8SCtpGwGyYezruRhAVQlCUj0CHf8EXVl+gbOJgagtExDyB64fOXT9AckZyMzZ0K3vW/aJ2z6xrE/fvWFOJuCU1MKb6jfffBP17N5x55070hu2XXzBzHhzuhn+4jMvuHjbBvJHLf5NjjPSNSXReq1QcyvXy53DXcBdxe3i7uEe4/6D44R0KtqMGsQ65HB1IgDrs/iRnIoyqC8tAzQ+/mOmP1t94xcTyke9bGeb5MFzUW+Rox4CzxFuNEaoyqnmq1OdrUxYhh+whSTCQspVotBDEzmLXswKVumTHw0/Neok1UnUh85S4PMnWd0CW8Q8BXixej7pbj1mhGrQuBE7SzzhBlIqlxoYSGH2HHWT/GQxmKPb6EAK0Sf+YZVn5IeTxXBssbL950xY5JBTa1U30lolj/Oj/8v+8fVhrj2uFuLt7XGUo89RN85X+4r5yeM+espqNwowJ32gX1ScxVEnmTD0rAmqCgMQmnAu/n+fhY8+qgLEjLAwAmGnuMnjqt3/5liNGQo4u67nLOLt/Jc4F/jgzJDEhlaEoqleBKeEHh71SLzdV5xyh2+x7w71kM9HHSiK76V+8rfFLMp3B9pE/T6f+kt8H3ih3CtP/0Ww8we4EMeFHVYkNsT0iJYdTWX1Y8t3OSQ9EuysZPVX6q+0klAUXKXaULRU+q8g9ENjfZVSNHxG2y9CcDbO0ma4WXvQaQlpc9MJ2zI8Eq46BAcRKmFe3GSYF88p5mHFDGjLMKAgo84x+Fh/ejJ8DA+fkZM6/1CFpD23qX8SJK26T1bOzbWdAbUfrf3FAq0V5z5eq1l7P3JLS+e+SJdbI5emmBEW+QC0Jp2yZzMut0uULNB6hgHAwRdrQYA/ul12umdrOzTFs3ceV3+vflf9/fGdjx9ovqw+YG1av3nJvmOvHdu3ZPP6JmugflPTgceL+YGNA/CH85+iKXceR75PfRX1XRGwNDddFljw+vUbITnk2nj96wsClzU1WwJXqC/hBUW2QWO2QcM/oYIjju4LXKQCLhqQRGTNT9s3kR+dzc/ZLQWLnT1Q/uO5B8sO+zUqc6IcPP9WZG5M3eiaEfqyEBqE/naSeQTqGZ0PRmNcCf5UtEF0uBIUgmB9SjAjDpiREKxRUYL/tNWwXGMSBaRojKKOgN9DUAuigwELOFsOTcIqzgD+z3oIC9qdBdQaKAOKVluQBEF+gLtDJw4dOoEP2UxfVxyheQZ97b0uk2XflFabWar7jcWJfNMa7zJYLcabY5LOOs9ea/lfZpvN+LylJj7ToPfe5zKbxya+W281m24Js8ReKyTGLlrDIXTFb0wu7MtEEqtMXkPkbv3lbusdCZ9s/prNuVlvvCZjMJuMzjU1iWm12GlmaVtapi8xmQzm8D2GzdWJDduTOouWuM2HnezsKOGyGox0cjO5SzU8pHqWhbP4FaB/HX5Kt/YgFITRDYqSwCCtgrCEyms6y+hbGEN2htgtbE7hgSZx50fyFishOWK1FAdRoU0yqN8ySOQqu2VwXd8I4FODDHTSc6yL6AmzyDoHpS12EqgCI8sk7qKffGVkAGBejvALtukx1j8AwSMDy67ftox8jdX+dCSVijxt19a/FwbsEoFwClv/rGvQ8RL+ldYjVxYALcROhhiFNUpdAyiV9mOn7IZNBfBTNX8acC7AVXEv7kX/p0dnJmZdcaA4YDKZdT06bMA/CqwK/IMtjV8bMA6oAYrYUkQXDSMeoV+pUTxjgR5LeEbxP3UI6xcYanV4pdf7w2/Rvqkbv0r5ANreSqdYgZbDuQVQ6xyHQLolORiNwZmj9SIoCy/64u3xk+xMJfn4oG8P2mEwqa+Y0EXqICA+HL/HNxg/lafxIpzdcd8s9Y46E5puOmnn4WxHQ4zxQSpr0wF795RRzFbbd0pgw9laUMCCbH4UyHA2DLspbO2wsxPYJLQdYVgDh6EDJ9VfnDxw4CSKn0TXHFcfU9epjx0/ji5ET6ALybBagRsKC0UVUh0o5cAXVCc9fpzNYwLwpUWwPcoA7RxKkxZEyRSJOEWNznGEgLqJQTCldiQiArXTABsDopDbQDcXlozuHCE6hsjFr/Qgh/l5swN5kN30D5Mdv99SzJntyAHB6nsQ7kB2czHX4kWP68IOtAxCrBByBJJYIQla5gjr0ONe7OMRO5nUAm+y2YDeVMyIsgbMp+E5P9PDOxSfYtb2TTM4T73TU6YjRIoEWrkI1w0YSmkvLL+VMdPudiV66epDLoniMSiapawnDSCccjAhaFwlFGWvIwAODElDP76941Mdd6DX4u3qC3K9mrNn7GquXpabEJBmiBJfXNORlJaL/qHAKN53Rzv8YbmxTs0pCirUNcZQgdFNuSpY8XBhhgM4Ku2qgIpTTsJ2UQKWHmSL8lXwwg8a1G8YPUa1YNXpXAW2cODvhxWYOXDgDKjBgyaT+g29HuVsioPBjUUdsuNEFaQdOwN0Jmirtsdpm6HGlqCYIJq8reuqWmhAvdBslLP+5EOber9DHWKb3KDdYjKhXr1eLdjQBx/SVMxggqIAZrbygy0oRoIEDq+gOxgZhYasou3GbsVFTqMuRNCJYtcJeKGuC1AOD0a9J2GjqvmLIe0lOW/a8JcanCMGgt5TbdiEC0+ofsaZ/G1PN47XNDTUFH/RXTVGVq6WckgoHs4OXVphBsZmkmXPDwWKw1bZZgsEgvU48KGLHj+1wK4W9DolgvMRxa6ohR982KpHlTYlK3tRLNqLoqEGCwacLZmg532CHuySyFeQzGSCh7MfUDuOQmqTLNfvu/97ZeRr+4n5ks1i3KtHuivU739uFFU7iJTNtwKEC5ya80bjMf++vSUUb+MFBqzfp6sx7LmPpkTtyHd851UbboFFVI3PhLm5bBVgLtgQBoRldL8GygOO2UQFOSkv7BTrSgXP6UZ2LsjaDmf1H1FO3aj+5YD61823KCk6XbDylL1zv3LhbX+aY2wCcDQrNbR/EArdKwW+YlZmoIeQcgA5Nt8K2dCwgNV/qF++8pJbFK2IaErZ2zfv1mvki90KUWh2CNm3VwswS8iEFkLXlCgFRd2k/AIOjcNI02fxj6dL02fxK+O4VsoZXCiNEJjswUP8CPMQRmZM7IZEJ5mHcoLH8HrRYKW4v0/gKv79w6OThLlHaH38wmomMFvjvMZjr6drPE13e2c1j4jSgnD+UkrQBcuZoqwkVya6A0iHtiBdIN5OuMKmQ4c2qcNFtl9jiC58DenUf32t0E7hMleiI2Quy+CysuHBdpfRsEGKVbfgUIPGm6XrnOLMgDInGUMUas+xDuX6N/ULhZranz/UfdPaO+cX1Pdkmzda7+x45+ubn785msjsOn+Z2RsVuHnRUxbacf5v0Xnp/v5tRaGm1rJ1SmrKAX3Ui/8QcFvqdnR0Kk2ppmj5noXRkf20hVYMiL9zLI5aBz9YEOkUhq0GOx319DivoGZlGAMaAUOvSgSmmO9yfN21d9UoNjr3uoZZdc+qP1e/pP782bpZDdfNHY1btdf1dUfXbcMohQZQavg2vO/I/dOCyzYHRpHPwNwu0wXr70fipz6lnrx//QWmrrmBUaQ0sHlZcNr9Rx5Enld37nxV/ZPWrwDh+GHA4di+BcdiBXbhoHEROKsV9cvqSbYPi2ghLFV+6BRd4WghhFA0c6G2Bim8BPg8K2vqxKVx2kRSZjZJtRB2peCesA6UP3eOweqNehoaPPQX9VoNcyaoWLUf3u0TIrXOOmdNy6yWGnjXRoRaBrqw330d5mwua898bvPHaRMcqaVQdk8D9DYj3sbHAYUHgGi34RglyCspPnKP0Lmf2W821UZj7Y4Fy5YtcLTHol6zeT/6jPpTM4BpTKqXWsI37Nt3Q7gFnCzypx99FLLqcbXYKUS9MUedNfPk157MWOscMYD+zq+qKXXXGogJu3kzX+Ndg2wogWxrvDXgdYchyRrOxIh8CvP0HtIIO6vCueHErYcTvxXOObpWnaG0Ar8g/BCjVeQgfQO6L6NSONBu6ZAckoPOZBppSWSUh38kD6QXJTvoj3D0eZor5vl8nkarefYuwn8BfjSIcDTbCEK7UCkfjcV5lYVTPjMEYpaQBtMfx+4Gy2fDmf2Icc2lvnRS/ngyJCeV/8GvF/4FAuvq6x+Bv56em+vre9nfI7298Hcz+1vX23ts3TqarLdXyJ+8Rdj1b/3ovGhn+gPC22yPrqviUZQwIqAgKpQYcqECbI79m/jrIqozlkpHiuloeiCFhtL5KP5BhDfSyH41l46ojkgE/zCST6Oh1EA6WszEyrjpA9LmUl3ps9UmaKFA/cGeSONCyY/QCpRnweEWP3o9QuPy6eGP0L4UC/TVQyaoDH8/mtaaTTgD4DzXQ5uXcxdzWwFigSaxULoLlnM2BWs3mu3BbBlH6XO8A6JEt8S6VMoniW52zAMaHnMJInP3okx0lJSr8ouXxl3qu8q1M0Y2LLzH53GJCM5EbHKK7ik6ImDiI84mHkk8H+aVVh7pMLa4RJ1sVhzBmA9FzfiDBYtd6l/Cc88febjWaDR4dpCH6zI6NEXC0VPv8iYLHjTX8E5wFIfAsfGMEL5h+ryR63IrNy+a2cW3WHS1otFRa4hujhriOmODGN7SoG8RzCHBuy2qC+l1Dq/OFAnGalxIJPotC0au2z7baqudU+8lv3aFrP4K2qIWKk7tPvdBoXRXjBJujQvA2GB6BhcaWMB5ze93O4OxWFCpaQupc9W54VbN73QLeb25veHkPxvazboAekZdFaR+QQ9+fXkvz4vaXmQCmr+L4xq1zYTxfYJlUMzKJZa1hqGFysdzCSzrGYuCoguw+4zAb4jetfB5jRBVzMMa7jJsVq4+B/AYPBQf9B32xXPnXI04uue0x4eKGu2ZUwfNyhDFZoaAhB4652ocoMyKw77B+Gnu6pJsgEYzB7lG6AEVwwA8uoQMjCJQFXZViQ9tI/P/cvToX46SYYoynczT53BS2ZDGXHqDkixeOspPJoNHaVI8/9CmEZaOwPOOaXPnTrvjVB5V5BhGecsaLrcYZokkAHHKRqF2PqugTkQJNDvMHBVPQJQPKTobAOHnJUD8Ez1COgWHW0QErMZPkpRLSSPFkIh/9pngj6Yr0ZUj38fuvrZk1PQu8vSndeTV4IFG64o6h1XZZxVRr5obUP8c43cjt86pNws9S5Ha493g64wOEIQ7/qtDFyGLyY/VHh4XR647RzIalFg93ohPWCQ1sEj95AUN/7tjqslaJ0YV3s7bLKg55BPgDDaYdLbHv0lwh/pujaveDtRaTG936CwlOpqdXU7Y4S/kuIgrGZBTsRagvSTonEP0I8JwR+gapmGszw628Hv4LpS2QdpWREk0SOYnToeFSAA88AqxkcHNC/rQjsba2X0XzO+Y70MY6cSmmUt3rk92XLy1L7FYh4q/x9b9YckoCsjFh9MtSYFfj36/273GNecTN65tD05d3pN+6NU52x57Zu2UZ6dsUq+0BtA51/RN6QrKvCF9IqXbvuB8/Lrk7d26fM5lnT5z4vvJ2k3elpEt63iP1eSP+FqdCYG83qwz6wUeLcMK8nYsv6k/tXJ6R8ATevmBix+7ZLZPdGm0KU/X53SOc5ZQFi+KpVtwLEtJUwihdwsS9FDE8KQcaVFqoJt3iM6zLD4Y9pnRzk3I071IUYJfuKmjbcNdPsHivyeiM4l6XHu9jF12C0LyM8RsbDbWbfXtm5X82s3n4pg91CfhFDaGasxGgVyK9YKgx7GEIWJVWoMd5vuLby7Xr196rtXO107JEge2l2H1JLS3lrsJZi7hsmo3YXQdQ5t6tVswyhhBFP+ndABdQj0YYNXFwFOUAB3DsRZC+0D3YbfDDvNbBm4oL0zhF3YI2OEzcgpTYo7COCNyLRiyy+JrQbvjZkcH/OzBxYurPR/8OGN6BeYsfE8YRUS/0WnRNfEOHguxupo6YjMj0aRIdVi+KLEooEe8IBjiz4QF0jCg/n4GzCKRz7vco4gI88T4YHCHQ/EHvU2WfMT7hBf+IjxXdo1w/OlamFuEBLMRoS3Di+ss/JTl+kWzkU5PMEI8vyS7rviVx21XzQs6m21xg8WKsMOeRPragNfShM7dgO7fsA3Xun0O3uSxmLdfir12tEsbY8J4ARdyD3CcUhrHMO92jRvEdJQOChvEepR20CUwyTj24BTgv0zAbOxIIio2RC9LYOm0wECngw6Xg96cwBRFAYcm9B4RVl8wFYW8S7SxnYMuRNz2oLt6YC0GWej237z48iY9ggU34bhKeoIEOmK88cHGf9i0sRX8pq5sjvd6+Vy2y2S2CmSEI4LVPD6Up6HCLhhzjHgUqBryhXOQWcSYF5ZkD6eyLz8xb+Iht239j9s/R6Q6nbRg3pKMYKo1mrZvZGN+8nRsSoY4250kMyXmDNeHMA7Vh50TBnIaz3UMP4PdrP1P7tclLur9gEmKiCWpllNMskRgjNWo9yTziVwpjqXk4VkYFTS55CzO/0ft1sQVSb7UbuYTypI6zIf/L7Rb/pj+se2uHu3qsf63R/r/SZvP7v6Ybf4QPt34m2P5LP6J4ObD4s/Wd8QpZobWTvIQIf4k8wiA+J7kJouZzD1cKQ1dO5Fz5O8VJz9h6MTZ2D38GWOq8aDpHUdKk8BF/0PIoFxMi14d1utRQG8xKwL4P2A9FFlTTrEnnxvvHk1DhqkYBc3uo4+z96y6kxP2scT313g5VDrmf9rHQdpBxhW0QBOFox+3i/i4j5agiYqAS9V/jC5qPEYmT1zP5o9RUOU+lQnrOoQYh0niYmZTrV294uj2Ym770aPbcWH7UXTQXmsyxyiDqEkWFHTwSDnm6Pan0AFFkCu0lKTRAhbOz7XQkaS0SSYBJFUawUBWsbOh4qh7HEsb57cMbdkyxG85mUe5IQzYxAesHyIdiYPVEpC8jSbcUiyouQJLigIweGzAeMgSOMXY2HyhJK8IOPvbwmZOBAqvhotwXDAbk5xJJ0oBho4APQeaBchuaJ+MAPlAlAUMmCDavObtNXl8ncsgFX8rwRP7pQwaGimog8LbkSPq4JFwJh19OwKpNufJkIumMrhoqu+rgyMFNISH05EjaOipaPTPsRL+yWtyH+6xXA4LovyMKGN6E01AAx0Kqvfbeuf1WtWDQTQFPYOmkJJcBXfFnJGTwWg0SMQ5V5xAU9QTY2RKFCox3sDuqcZcTnP303smcv+4G6lBPqfdPuH/PvPeUOPVc0IB6B3KewVKh8SiDQyld0LjMxF6T04ZlgQIgAQgcMTtwpwD1bl8Eg90ng8gy9G/qR9z6gl1lXpiiXj1eVf69IlUUue78ryrxSUoHw6i5mDWbbO5s8FmFAyn+/ufO6FCv07cd6v+yTt/eb6/ocF//i/vfFK/S1uv4r+gnyLA2HSuh5sHrdJmk4vCXLqySBkL2lT+xUoFG6ovU2BpArrvImzKJZhwJv9Gdmw9vHUQcwFZfUIOyGjdkqPbRxiUk1xvxkqIaZrF7naNMDAkAGL6nDU+iALFQXWYX7tWHV7rWwykOhqEYtoHcaFSTvFHL2mlbD9aI9lkKEYUNSGQdX03m6EUG35VHS5CUdi3FgXW+qCUxZXxZ3fkzdzq8XK20xIaOk2Pp+qeUTrM7VK0u8tuFApIouJiq55K2/dI9HaFSQZBl4V8uYvcabPiXdhuELeUe2f3eW2K8101z1b/kHrs2u1TiVvH2wwG1/SmkOQMdS66at9zm4Zgy/AqsJPjkFos91Mx1wreBr7cy9cVg9lj0+nRG2oe9oumwu696rNuIzZbGi4d3NM+bfng4mUzOmIutsFAklS577tgrluZ1KA80bTSLp45sXQnU7S7+LESjqPdrcyowUzEsXNqMIui448jP/H0edSlHs+V8EYSvh1eV3rwOvWbY6fSgCtTqcJUGogOnYC8HvQFlsGjfgBZaSElvZrTsERhPmeWzhnGZqKso7LwAGMrBZ0OsXzK0s2Z8aPKV/RMPilIr7DcCJb7aU5JAY4KqBBz0gcgRoC0MqeCOHZJQKOpkz4gGtFoxOGHPl56ZWxtVTwAqheUYTwoaHZsnJyVU85kyU8Vr1cpduj5Kkl5vXCtYvKezHlNCn5ZbyiuLuPcgHGvNuqq9EWax5c/STUsUSYrVmo7s078suI9o+aOSZoAiU3eYgdry84Sr6tmgrakKjUv02rWCfSpKLQ2QTdhbTC6o8Wzvt4o7BL2UI0JPRJZt9ga3XjyNXcw6Bba3PjCot/s8AoFr8MMrjA3Rp7QWjrhxxyqwnhVIK4k9c80AEby1T4hN0r1VFNA0TLslus5oxZxDMU0ppzRvKI2du5K19ylHkqst6I0lQ4dfpkOHQwMHT4YOjpy0GETHVMjfpk5YOTgYfLilw36SvllODmjfLc89rqUVjVRjTqhSlVDN3nt4DgyOkD4iEFf3Zgxa2JsW8Y3olJ7db1jaxxXEZtvqEFEgghwUstxirYpsNlAVTNC67GMwhiFPeHlqmnBU8tD7C3+QZODinpPw1Mbz4dOP8QfEf4AGBOnxy5Ncry0H9GNlD9YfBcrinKEzoQXoPwP4Dii8D8tvlt8lzm1IHjQNFqZq6HMS0plniGETgtdBkVpeRUohRUOBeCDtAbmgf9aAppwDOzTu0OOavaEgrKmvuOUg5oOTzIoa4o8aRlOiDGSOwXaZTbup1n/keZhQmG58aI7uVLMmXlQ85lyTFWyRKV2lVtzZhuq9IAmrLVE8zZPIBNYrqeZ3ZumWhEVFWilUjVWxiyzUvy2Hkns6UomehlvE0Z8TBtuUp57TlFWK7Ve6vDWgvPMELR7XNvQox+WvBSCjk86Nm4m40VbC2g4oJWsrW7aSiqzWNU+gbevgXlXN/4WnmvsdrSJVoHr7SPjZSobfHaoWb3st1C13QeEzCGFplswrg3Vsl4d3BzAmMfrjKVaEBAHIhuzklAInMmSBZVTwPmb7eHD48Q/K/Li3FVHVv49b3XvkUw2fTrYkGrrj7f1XsYim4OBho76GpQf1/qhimA5/sKqQ0t/5rFfLJpmeTypYLTF5ds2M0yjlW7F7pzWuqB7PDCM9onSXh3lPsmjoMf43BUgJOO6PEbaj7NbBsvCrIOapDK4qzqIz2j8EARyNBYcaoG97OTuoVKI/Rvj2zsKB61M76eiB9KCYhWeiwVJSYoAUb8fuSsqIj1I48tAfCUt5KuU0YOylbSQD8rgP38FXUhXBB6/nC2nyx8PjA9A10a990Tefpx5H387cg+NHxeAuclyVwLQlMmzlwLGymSGmAQ7pyn9SNrG2AsLIqVdSZSoEyusXEdmMhnE+QcMXsPevfA4YKBvwzj/qx8mlYi+N3Gmir/mw0WTz5Sb1ldh3/WodGhMKkB5UF1Nl/evFOUSeB9EdJO/RNn5oYKUP4U8CoqylCwLzXvyI7bzE5yeszM94VQMsfs6gclUAlBBwzT9mJK2jhBYWbTsHbrqewdWjNTgv9/+FJDRQmDnq+rv1O+qv6MCT7AltKO6V/Hux28rWs9beeAHL+K/rTkwcv8TqFd9Wf0tk670ow5UR130HMydTkMb+mGkSnpDbHY1vlpaY6wxdSzEEKsZqWIORaLRfiqCUNwWieA76X1IfzSq/hoXUjNwPp/uV38Vvjw8AHH7maDCvmh0QXQTJOjX8JG0UCjVp/G22NGLKjwqbaIYRSgUIsVtsVQyBuWjSDGXmjEjhQvqr6H+aCodxXdGcC4Toc3ohwpQpD8NtaMo1A4Zitvohs6lYYz7hRzVoEfljlWwHu3gL3WTIi79UBLVePoVK4p1BIrCd4aymQitLv0hbaFt1XCL9OnnoM58Wfe7PJilblVwr9LYQqW0l2l4wkhRB4oOpPKpARSl49cfwQWI20rHk/J4+iMR9Vcw1gMDdC6i0PfYKM5ZoPBeouWoLLVFgEPMUdI9b8ExDH21B5NymV5TKQU1vP7hT169vickCLLVZpJMVrIr/QT+3jBQWZgjQJWplOxCnKk+c+62oQ3ZWWJIb3XIei+clHVHXrkNHaSYCKTixpynrVpL3K5R7Ly8/JiMWisq4110e9GYbn83qF+5V9EEaaH6e9EALPpriJu61a9Qt8GABu4tSc+id70sfUUgl6aH5POZHC7NAOm9LEMqWpLfM5++S/i7cK3WvsnaMVm7mczbBA2ZpN04N2FD8MEJm12xdSFo+oml9VgB1soKqQAQpaio3uwg092kuiVUeYR50FC8nQQmCmXpS3VhqItoNNQ4PjEt9xQTceULpZLKCqIa7UnppzTTh7HCwRcb1XkTRE1tZyqcgb1w9rmFSnsjGaoJJkqC8P2WWm/Oe2mL+j6DdPX9lkvBX9uCDODUopBBWwSGUpT6PvoDBF8J0Z9UX2Vq1MlPQviVEP/QQ+UYlGSa2a9WYqrPA0qjTGUSnPbyjj9e/54oqRgNABxV0UJwq7Zll7d8/CW7uWB2OOBhx3aDwfKGxWCQHZavWxRhPB5y6q8vWRSH+SWzQ0GX4CtMok4nmooHDVZr+W4L2pXjzJwLqOUFFEuS00Gn7CzhfUl2w+xwhVMMeU4mNJ2xan0wjcJilk/Y6ZzUTKEkXGRILYR9BV9Ybf/Wzd5mmDn8i/Z4s/emb8bRs4BHwfTCdGrY1NfO3737/M3d+Xz3ZupCX7PYv9KOThQK6pT2mtpasuHx+vbF7fBX//gQRcPKMKVpG+5+fvfCp55aCC+7xidjtK+T3V7QhvMi488C6krFMsJJymUWOY0HiKjuAL0xj1GpVE3pk96uYyq008NTYxACIDmfU9/43U5YXh5n7TrHXiR91Yujjhb17V+/Pnz/PusBt621uafO3+SQsY6QngU9Pqxf+eBLV2S/8uUvPRAzxBwNMU+sN2Aj0VT0oqO3Oz2w5jzrlBs3IvGC9cPqN6+4vFVYkBvIubx1vEU0S6GFmQ6Fn2VIpq/9yWPbw3Yr0ccihpjs1q/ds1WzyyJQPqiVakII429YHGzTjbkZg1OAHdwd8/P0Lmn0nuw0N+2cwcFzps3k0er9e1dnNV8f0XxDFcl1Xlm05/xl8+atSQ7mEWpcvvWWz60vh6y7tRRSwiXouPNUvjzIjOREY7Dra/xwUXIBsLO50BjlTIKXo7MQ4Kh0QgbebjF/+K1uTeiq+63Dn0D3oRPovuJzPsdNX/bFfTtXOMjljv1qrPg3Nbbf4diPfokt6Jf7ce6dbRuv/zpVF/769Ru3vfPq3/+Op8d9X77J4fM5VuxUfzIr9Af1beR6KzQr9BZyqX9+i+nUDklUHlvP1XDd3EzuXID8bAtiTbWPb2eEtrPEXYUUVOyCtjiYYBqllMevAC2EXDxjP/NwUoez0VgWEG3cvGjleujL03jvaC/Q7egyde2maQa7aadtyj3/vcrh+CR6GZnPW5Mx2AVv2B8ktsijtyKPDhUcsTmH1G2/WXACXXb9tU/3XvAf0793V29hM+2nquIrR7v5Vwm/WDQdO882B4rtn/GLvfUD9W8jm3yhzaTYFWxQ2+58K4Hen7pnTkNuyede2mP/y4tfvnZL7ksXaHNng/3pPQZPQQpRkbPuSQS5pIqEJ6KXHXzVXS3sSmbjG0ZzaVcyEy4UkTsbTnINnXIkRDi5a07X47AxKRb6QHvQD0yS0ShZ1KzBbCbPnsz39tY1NNRR0d36cLh0Jl0uXE51/mD7tiKlzO2O6RHjfDcjKvJPlYHYNqRHmtstwJIXBqfkBh4fEuS8ZOKJVVT/Sy2mBfOg3oKt+mMjRowM4BbxNxFReQvBxrzFhj85NFAQBlOFgceL8xTLoIiIGY2oxW/KlkE9No4ck2xm04V6lEYEuXU2mzFvFh4bGsjRk+y0dkdxphx0WQL6HO5ajnOXpLgj496o2l9h3pT246p02XFxkXEaIyVyL1hlR8CVRwF1GA2inFpQh8a78TBz5+mTcDREc6tDo2o0kKYSjlhpgdFIlB9InWTa6/l1fbm+dUh7QYhWbyDHsuVyKDAC5aOC9oZQHEABJvFKDQ+MfJ4loRkKVcELTzFjJwI8B+n1wqD2HCjRMbCehWGgYrLc1VSfT2rhq8QUynfY3QiImhYxlsn6+WRQUyNA9kpkEI4CWMKWagkHKrqW7RErqfFDXQtd/mSyf8owU209KYh6tUDvswOb2lenBhJ9qY7azlISqgFdVvWjSU5zbYu6mjyBlrrGmd0rz98xSytjXGA5F1+/9rmp2XmNdYzFMGLx0VJgfSFEJIu7oaU7dv5XWDzVQVS/QbaXE/i7elt6ruhbvWPximSQZR4ToiUfvX+B7ZCipoCQwIoSBdjDorF0NBOlZ6CQpaYRehBVopO499SL/zGn/2X15LQZci1PBGTAJiy1ORs9fuMjz939Hhr46j/Qp0iL+mn1l5/V/cdMiw677Ii38VZiwbq0u71lXvw8JB669d3PbfjsWJo/ybR4nQ6GFZVPMth//CTRQyon21m5+d9RH1fnqY9/R9PaaO1a2tLUsrSrVfNS40OqZoWtZJho1IcL+e+pLz33HOr7nsZiTA1EXTzvooQQ5Q9fMpq0OluJP7yac4pH+ADl5Uakaqsi5Tuqg4w1fAY3+NWnytzdp5S0gt9SlGKtki7zh4fFI+TtMn/4jNs78SDjD5/BDca/gDJoWWkoVNEY00+xQjXcKA9ndIRqWGk2r1pIF+pGY7ReNZ3/ILv1L1/EpbWbOI1aZUY9iA9IfXpXJ3BUh05nlHgMtIQV5ZQuBeWsUW8B52z6IQnnrWrB0eFQCzSsWKBhVN+unAPWOG8QZdGBhtAQoFgyyrtcal72UGEzY8GIDnlkNe92IxaE8qaC3jiaRR2s4h/lBU1/uoPad9GkLfjSm2oMSgK9I64Y62NoHpU01jrEu5nUBbPaQX7IXj8Mek69Y/aQw8yAH9CYNlst/uIPNUa3rcZi4iXEf9EbTTFLH9ofKaicJ0J2dhlsbVSM3WtsrJ8mkCy4zfZ6Z1SKcmN03Rxn3h/VMV5Hfs/aU7m1e/asRfDEQ2v3kKEi85MCfQb2VO7EpZVQjsI1adS+di6XVd2pVBLVkkBSamz50sp69dnmh/tOFRrS9WgxuPhcQ1o9OlJYd7xb/Q8BlSoOwG9efUjdmpzr9deH0H54o46hC+apW0Ve5qsaQ3k5HC6ITLaGY0A0/ip39OIWF2CRjbumrbpm5X+Vouu16haW5yqXrtr4oZzEkYJWV/nuePxN8dh74QkLHL31HXfLW7rVLdlg0ZV1m8yA4TrpnAVlTQMrKCflsg/nYQTgJ3D/4gAYNQ9VnqLyOyNAcZ3Kw453EmjeIke1sU7R1TjKs2jjcuz0ygAeqiGhbkA36SsaA4TUTXEewCvpi/LpgGKJZc7YFLn2GbNqZszuXrvyBuGW355Tt6Y1ffH8OpfZ69w8a+t9Xs/9X9jy7f0bpgFt3HR0+wiTayKF7UfJozX6+MKoue+GlXWKtPXCRPs13agG92+z6PjepWg1WTd3+8NHl9v1UxEezXV0zF1omOqmlC715GQ2RLeKbDrK+OwhZ7JsZSPJD9P8L77if6t11s7ea+948rvfLb5Dg5hIAhSOl/3p/vZ29CP90IHP/qn4ea0ujcQYtYdD8SqqXdbC9ZQovSqsPVOWtgqmg5wtGhBtrgB1kyCAiVStPq8ZXQNakgp52Nvjlr8xmaORQ9T+J58v2fYbeZNqw0E3R76dK94o5vvTJ7l0f39ahCf+ks++ro+e5fF2HRNLGvlmHtWjnjdpZh7mv3Ddvnz+FMsg0Ceb83niQUanzi3JP9FpZuQ27QKdYGZpswXHJHeJgaZJ4qXs4ZJ1yGxZldLPk9yWoS1KY9PiLaU3+dZ6WR9raCaDb/gWNcV9xQufPfbkqy+hxNCTr+5GFw2SlobAetlsEBcvP286eXZoy5bFTY3KltJb5eT1ATgcIHO8aZEPP7b71SeHUOKlV5889qz6yCBphkNOXm8QFy5d3aexEbjTVikvvAczJMO87OKOcaeq5Lq0/kHP5IqrysaP80OM/Hx8Ez9VBn4QkwlikkFUSw42B1oPyx6l4kBUPIiVRdWb3bBXQPlaCdAq+X+SmeQZFJFDcCT0b+rXnmreon/Y6GxolyT3dsVouDYSN5ok9/NGO3I3NF4nmY2GeyVDj81tOmywVJK6dtCkDc3VSXUmmtTUZXUbISnOP2CyJ/mdWDdgcTgclgEd3skn7aYHHjDLSZ7vaS9FJBtFfgeflM0PfNz0JTNGpxkSDgDMp0sO9d6vGxTkCTW2zTQYTJJ/u7RaMV3e6rEaPmlwnifpPlGrN1gWuaZEPUg2VpIa9Sad/zpptd1yecuYpLYBV1uDG8vF4f02a23N1TU8mbvOibFz3VzCg7fWaoOIOjeNwOHA+RA1txHPoXHuOit579/JVZEbYbhwhPGNbCLDhpkpIJjsFGDCPTxjEdB7EFiYEuALfpFCGlVajomhAF2xYYBKWLvURNCL6gv/uWL1jQ+FE8SoYEDasUBEJIRtdU7DjXe/iGajm9Fs3HX3jQZnnS0sIJHqKkIyhykRfujG1SvU//5eh/9xFN96023uWw6RO9U/v7PXtiquB8qTSKLIS4SKbTgjcc+8n2y/8529e4t7d/x4nicecUZFBJG8KErEYkOSPr7KtodfvXzte7ct7J/7egXvZnpzXdwVo5ZmEL0dTWXo/XyFEoIjHHpKSUzoVw+CA4eyyGBFOtjKYD+xGdNBGt1P6aKklBPVOYEEVDRaM0fDH1mUUIcGc4NeT6TRleWjNVPCjTFbIGCO1LW624Sf7r6+IPhD9rTDGmjOT9NHATv93F3h8wdfuGGrSx2m+yeyhzd0TPO4o82x5PLb5rQ9u/GwZq8G55MLO37QuX6d97pPNLtnCYlAOhS2F/OiZNXJeP7TXr9t/oJAYnZNt4zWhs9bEAwvnOl0bVh45+NTm+P9aZxP93t296drrt/TFJmxb9v5Fx3mKvaXmCxpN7UZXbWjxdhcZ8CR0RgmkkXQBkygKn7YTffxaJrqsdIDsbzLMalRal6rcvoA0NAdTHJWRrQyXM0BqyNtD/mF9Svzu38qtLlb6yLmQMAWawxPqYnyWVdjxOOF8USDiUX5wxufbQuFbluejDXEjR6lrXNDWP0LG7OAa2v+pcu27P886iJR/TRe069UudBaJHfXzE4EFsy3+b3nLp2PZZ1VEot5eziUDiSEWe7mT1znXbe+8wcdCxOXHr7o/OtmzZ4RCa5ftsKZWLjbo41afMqUR/cKCze4nDMXhoMLNNvDJMfoccCTzrD0S3LjLfkKwye/c6ap3up1SfVep9MbyhbCqHQ6ig0WAkcm0EPZEo45zn6ymG+eObh2444N8zz2Hrtn3oYdG9cOzmx+Ac/Gs17Mv1W8zz6JbWXyuSU3zm+xJRfO9LlcvpkLk7aW+TcueeaF4mu49cVnqIFl+0Sml0dlVAOwj8QpLhdxuCy4Gs9wlgJKMpod2E8qt2WVZNrtGM5jJFjNKpPQpBalSl7K90DUCrcsGngypBSHqRAiszGOCvTKLDDIB5xesyaUrpiZZ11fMde3DvOSESdSNAskDpRsGwQA0S0Ol/V/NTyX2qACmjGblEOw67ETW7sRoBIUDVIyHXIRcLND2DkeBX33j398H83ZOn/udNQ5D8//44Edd8zHfyTkj5K1a8pWdKIa7dyJv/p6atasVHL27JGn0d0PPbptQ19xP9oTtYemPYKvrcY0Gd+b2UoxUnl6pKESMsMlaAOIhZoAixFG/WSScomwo9SeDDvQMGB38IeBxlSXJbFsQrXCgHq5N/rIRRWTi6mLHsFDiIl1MHtk6heACK0zybXoraj3hu9gTqPxVO47FdqL7qOxiez+1ml2fauF/CvWFye68xsVx8WsAcVcRfaYmUWjQqfPFrdqV394/7OKJqaIB9VCWQiXJSwL4DJDjGQpFWhk+dgNIM1HryJHbUu5KZxOAoP6Sp9SUcBySpoKoWATpoinFuTiJwJBdO3R7VSBncEsYj1Rh0swWwoDLP+hiUERJYu5KsjFBQ1ydRpYV2h9Kvdu5ubTu4Y0UH6uSDrokOBkcjq00wuxS5/yPGj3I2xLpnZESkyldBVFjL6/4DR3jP/WaW7BXcfyy+569eqmdLSue2b/NrtlBKZkW//M7rpouunqV+9a1h5HAWgZZXMG4u34rid+PLjomfcHf/xE3TPH83Pv3XqOkGlsWJjMLFgzW7MsM3vNgkxyYUNjRjhn671z8/F2jX/ZrulrVfQVLJyL88Pam8olubtg/xBjUSq/HnNJIjhiJa+76k1fjpCYTiWpjSsILkkXtFA2WqyHp0dULAqYdrRBaoFxcYtUwdxNx6eB2lNphdXtRxRZhh/pRfSyni2kUeNK+3Qms15nMiX0ep1dr08LOgMhBoNPNOgl+O3krXBq2Lpssk3uwAHeZiMvH90+bJNdhtT0NRfOaDwnMtW3KRY9/+Xzbelr6qZEzmnMXbhmelzvbOub4VY6HQ6nTTQBnttsMJh75s2kBixcruHywv+a3mTUwS9tkkSvILVKgiAJRGiUDEZB1Bu3mUTexQs2IzYbMTHoPASTLzIaUueU/3rhVNGTOWf3udefu+Zqfdzj8XqNgan6q9dAwK2LMx4xDFhrc2MgzhO9xSIIhna3O9pqRjwfvZW43KRC5JZtIxQYf4mt9w+3z8cMaWaydPi0O3QtilosK7HZJrPQ91nnRd2I677IiT7LjPQ1UQFLKl15mqPGy1DBnrGjQn10EiN97fPmtbfjwXh5OcYBGy0oiprzV85T4TTA2jTuYnqeMvVjivOxq16mdg/EE9UqdjKxDUdZ+ZtiKfasA2uGfLS0LKPGR9OkArW0TMsfYAzQ4F0Wo8mgMxh4vbLI0fWnzuZLZ7bvnTG4a1qNy+PyXFgz/c3pz116y8+25/ePPHzj96f/th3C5m9w1YTn51cseuibO7v+2KEMOJYsMGCe12ObHb885c5av2+q173GFbEjfZvb48pMm/9ff70lPtToXjmlzlUfnvpz5LjzKfWFU9kpdXVXzfescscfb7zqZ8e/OqOze1GbYcNy92q3QZYNLjH+yFiZB6rT52A0KNDdDEvj6F7BlwwUMfuxgF34Md1iqJlgqqPtJ5p5LOrEVBNDyDuMzg3r1tYmc/WL9esX5tW/ntMWIn6jXUq2J2pW1loke8gYDVhJnWX6zOkGyYkGvr0XN1hq9fb2RJfDUtfE10yfo8wRCYrXrqxJtCclu9FPQm3nIDm/cL1+cX0uWbt23Qan0UFESDe9hm+qszi6Eu12fa2lAe/99gBySgYo21JHrIGoMWSXyudVxU4sdzYFNH5wVA9k3W9GVUW2HxW48hlD44ZGI7QzWrNTImo2C2WUdSPlQw2W5Ec49PR556GnTZNaLuFORdGhc89VNwmrP9yGySgvbTa91aU6WrDDUesTJV34qpt+6hQAmWEWn4HG4dx+gZnlO5OlhsncdFrwuQz2jnabpJhc5KJ7stgsSo3TGg0OQjzeWrfB2JZumSUIZsmOu9D0T4tt9saasG36QSeg89UoD1ppFHTNvjriMMzok0Qzzt5zEXGZFMncGG62Glw+QZzaMi3Au5wHp9vCNY32NvHT6itd2C6ZBWFWS5pMH89/mwJn+XJB+zgN41hgC+I1ipTeV2uvbuRysztuF+8u2dCifMaMuHzmBWjg4dfVn3xO/e83Q81vPnvZkfqgr7lpy8FZi/oWTbkerXlZd+y2/YNXDEYuO5/fuH62xXerWvzL/7riPn4fvulCwej+4jY+SqbcvWxV/wNfNkTDtx27xDn92l4Da9sFp/PkPwFHYnxuxgkMkhC1KSNrd2rkPx9Z0YUiMVU9fpo7/drnDwr/UP81b94x9RdFPf4niv/q+VdLPMan2bwupWuUg+Pw3z/e4NTkKBctwNtFTv31n2pr/t1zylv7J/XXZaFKnD+lXrVQ8Nh/+u+fOpcQu0dYiO479WNN5GfsXUFkjFXnKB3M5FhbNxSj4QKQOuqF/f/QiUODowb6AbNl9mpIoSyrT+3ZFNrjVRYDv07N2VTsjmt7RU3Jhhc3zq5O0slmk7ILZKZPQDeTbJraIAs6xWG6P2hKqmZFzCtms/IBPAcRl0dQ7rq+UbVUCB4eNiunOMWMB4tDZoWaGstrMiVC+ftD3VUatC6NSUi3Z8YVpBxAgGqXXajEYC48GmdiNtw1hVq8BSv2uttrwtilvvBWTdApe4UhFL76mtuxGTvsvnu8EWT6kvo79aaf14Qcdi9BIvo/z7/wOtK0bNXv+BzOYM1baLYLh2tur7PL5tuvuVp944lahyNU83O0G9V9yYwiNfcAsWF+/YXn1WBJT5Mr3U3Vc40Ue+DG3U+5x3+XJVg2XYwmtPTK21r7Wlv7UCt7PVat8HsqwX/qEd5jGfmbxcPzX9RG2vYdeW2WWLJr5e/Y0IV9Wjb69x4atTaF3kW/NcuyuXhziczM1STwunRfX7r4RILtrbsZLd7CpRg0UMoKflzEAnuLBcHxZ0H0vMxkK5bCAxRoiMwJMi/mKS9iIKVeoG7r6OOjDtE+rTVa99TnWqSpSi0xyDtZncPoy+jV1EBevU7dh64necY3TQ2gNUFl3eZYcEays9Hfkahtct/Sdd3yqzPr+qh9zvxAaiRMnld/0qj+rYnxbXKnOZHeRRkBfmcAApdi+EoDpQlQkJNTLXDgYqeNEQfMuD8dYrqf2LOaRUzKh7HTzYTca+s8N3Dp/OJ1gkN9v231J5//5Oo2vgAdycECU3OpgcTSVd2xP7+ka1/crnvpz7HuVUufDZzbabPNvxS1oSnYkbx8fW/v+suTxXfUE6kBuuoGUk1rD37mb3ceRoJPcdDl51B86qnDd/7tMwfXsjWPAU9ThZsYfeMGsLayJxWJl5jMssTMk9NnL2NB0mc2oz3rmfkh+nS7tCfNDfmFwX1+gyn+YtpUX9f4fJuh0STVO26/3dfUaGh7vrGu3pR+MW4y+PeNS9VYd/vtdY1j0+D8uGzYRbMZG0ezNfnGFt1oMNXfeaffaBiTpvKNL7rO09zG8fxIJpRH1U+k0u0A5bDBvlfNjyzz2MQSQ7KkCVs+wXsEir/x2q1JsMKNFI4sShQL/rD/vLmePo85Pm+uf/bcQGDeS99ZcqzEhUT9AIkPXnaUDzJO5CeOfbqzxIYMGNweZ63Fg2eEzPGG1t7oTU+60HXVzEjH9PSy5pndd05x5pYsqZlezOdy1UzIgfRlh3umaxzI2Z0aK02vyD6rjyzIOpf25EK37ZzVdZirGp8s7BzXAlWYlDVcBjNGIrW3RU897GRfP4Ptg2I0bpFeGDISuAeNo1EYCt+LtJsMDY9PBjWcgMqzuf0iQ3sGA4HQjK54HSYCnhe3eJBidzl1c8+DESsWEosGUqhf407yF65c/vJLaKNGyfSn1eHOT7+06+5nEeomQf7oZQ8e3oiucz15U7S3tSFuDs3AHkut0+M2oEC6P4/znkRTkBARL8m5AOsORt3dM5uXpac7FiZTAxX2pCdw7tJcLloa3SIMVufsh/cLA5e4nNN7Dl926eGuWTtvC+V6ljqzCwgMoqzo+6vt55dgiy+PBDV30IIa2D2rJGu3hzIzf6t9QY79Z8cbY3aLVSdfi1CiCjLa9/cYk8HlZhhVmaw7MmaqU2dAAwZoyNNpL0487ZeOAsdq7fOAXdUwORngrvgIEFoBZ656fFJcF+VvU10vdpHOeCj0v4XXgAgnZUYMpmWKT7pgxVEfrlhugL1JZHcm7K6SqnSWDL4yCaoqTUxKIeVyRTbtemGiSW+ZPjrn+RKVXJrrzAw615kF198+bq7Z+umcjXMAifNKgKvjJwHbkAa1pJsNbXGWBqp+6cNBtQTYY+mMeoYZMZ3GbKakvieJjnqEqIV+GjJOx5HKE6uGY4qyhtreP7TGbl+DNoETHMfQ+1SrciKtx2Oash9ND0nVQ5ALHMc+XA+StY1L0Y8nUX1CaFRF75I10ZXIomy11p4gsLK1xqgGhiW+X2oq2rQGmcc3bUOGtb7UGO9oQyG1OqmuY6ldMU3PEWlN6UUVzVT2cYPwWJ3HM3peqQxZxrfqEtZa+yR9KZ6tXa1suCoClpoypsONWLPG2BGhupgT9NzORuXMdl08OssTwAB3+sN0yYzoF9gzTnfAgqSEZmoQzvgoZVH0IjEac0ipqBgrE7uU8o3CaobEQClJmWgsyaIkoIucLnpC0CgRdjsLttLs8F+iP5q6B6XpVV7IxWTn4dh1ZWIulkJ0Ry2I1tBAi8zQAhkG6KIG6USXROlOSnxFGauSirFIWiHurMsdpRfrQK/F6LFOeSpZl5RhGAptlysLW4rkhrdYYrgg8FBjiYzHks1ohqATfqiIxYYSLo0Tw2zmURIeispqcZTIdWUzaTEGKB9lALO8dJREZwO9yOwhUcbvonKPlD7uQSwUuZigQcgF7cqmollXllUOux5tZw8C5CuVhgzaTWcskW0AfD1Ds0Jt7JVJsQnJhGgAHSP6jpIMEyGPZUq2EyULcVMmHLMOGYUEFp66oCV+hvFRu4rwN14LhMzCVhELAhJtlmiDjN2EeAg2GZGot2CDQUTYihEhgqiTEBHhcCVGYrUZRD2RBGR1EF0K3hIy+3jiJYIkYSQKPDEqvKR3i0K4JiiKkolgokcmiYSsgpnXGxTBQvQmvUBMVp0ByTYd0gs6HfEZlFqpVhSQ0WDGFhGbDVCjIOiIFDDwHlngeUR4C2lpE0XBhht0gkWUoEMS5q0WnU08cJ4k8JgY9CJqVjAxIxsikgStw0Q2m4PQcruJ50067EaIIFJDEOZF7LVSrATrIBcxWBxYtOn0LlEQMTabHESo1RlMsmD1SWEFC0YJC14BEjp0lnq7QDDm9VhEyIEFl0DMME4Y6UVsNCkSotfmDZJZoRfyJh7TxsMwIqlZtEoCFjykRiDQM8GAjTpJh+g/q2QwIIvMO0WJRzDcekkQBL1JEoV6ImHCu7BMiN1ssBGTnsjY6pKPHb+PKMQuIklvI9jAG0WJThVGTqtg0htFAcNiEohVb+HNGOYOK5gnklKLeZsNnaHko34HychgQpJOFHUKdiEACxeymQGkMAy93kMEI7XkKhgMGCEYV4wEkUe8TeT1OizoeVGvENEiSLJZZ+N1ThHzdIwEl7VG0OnNZr2ALFYiuunEWk28VfDAWBqogoIdKtDDCLkB7mqQVWdBJiuMmaSXINDAI5hX3sELNbyeIB5LOhhQGG6rF5qgRxZJsOl5IoomkVhgJBffLSFkgy4YkU/mYc4sMI0oEOORaSohcR3CRr0ohETRp4fNjObBjqYaXnDyBGqTnDYXFmsdBl1YlMyiAcOg89DXBl7RIbPdSES7yAs6DyZ11iDSA9xIdl7nIXoMUAwQALiCzWyCFijEqiME87ommyEo27CVIGoDFKCR6EWjGclCrZ3wBMCXCBZDHFyyUdLp9TpiV/RI0PGKTQ81GYkNmww6nSSJGEZV0CEjj83QA1hpCBtEYeTW8CehHkAWTLS1OphmCmkEKoBlhUUBoLhGhJVrxHrC26AzxJAw18s1Vhcv1eqYhoHztFO8mdFNTqpNWMby9SWtVioD6gcwZ2IHnI1j33JwSILTrX3OQUOt8GeKK6ie56ZoFB+NPYjfcLe+fZemUNOxa4rNpv76G8L9N+itcumu4feQPHI51QTFR9c/iPbHZt72tMZYCvqNDcajw5vJmrkOrvqblpouRC2crp1AvQTTQVT+neVbqOP9PEdRfzXPcyPgohJ5+CNZU2Rm7uFvJFdmfVETEn+YzEPpbwHo7xsEjsl6uqSKqTiqtMu+tZQQbpDrVYVZiDvNKapCP6IkcE38LxvrVKXoZcbhOMWL/oDerWuMjdqSZDNHZRdb2fc+qsYg6CzbbQo5g8yO//grSkwt8HN86dsk9Cqbflx88DSU/QG3rg8Namw8NNi3TuDyRU4NaCyVIdq1IRgCqryR71unGdVeVy27OZfaNqGsAufol3X07AQqM58yVLFGKn8ESLM7ZYWgmDYeNCOLFYj6CLroXuh0+YM796qPqI/cSweo9DGde9FFEKB4TaY4vaNiadBFkIl9iargjTIrWuR3E+fzx8bloka0aC6agtXNUtC6BUWTTeSYnXCZm8ZN52Zwy7g1jFNOCRSbxk3IUsPUE38FusShK38NmplfYDI/TAgX8uJSCrzkiUtvW7rlRrF/R+fMPoEf+9loQ9/i2+64bXGfofTZ6BHNth1ZUZIwJcEtS2+79IklQt/Mzh394o2aACEGKFyyCF3Y1OyO1N1ZtEzyiWkhweTz1PrSl6aLjy1acoOw7c66iLu5CW1ikWVdr3vFLcJ7XJCbyV1WsjgCpLCfZ2QbkGKjxlEyqGw8pRyWLYvYEHeG07TZtX0mVtKjLylgUT6Lm7mEZ32v+eJNfhIwKlJ73FrjNdWToO94bWPcd9BXnOE77ovH6g76fK/VNo5PRXade3DZjuuXHV+2atWKnTuWv7Z8nB/l4lB6gNSbvDXWeLukGMHdFPf9qNZ7wIf/BA5f7QFfDBLV1o9NVHzzvWUHlp37o2U7blixahWUPNZbshOZZ/axOQ0uOGrkhJolpB+U0q45JT+S8m8+dqoA2+XdWzGacuJRhDrnDG461HjLMyj/2Juwh+75dcZnPYGmPHt3z6FN/b3+HwO9cS2sOTPTUQ9Sq+kM6rKadHxJYqWZHgNBFEvLIdkp/LN99qZT+U2z29E/c2XzVFFvTn1HfQ9/V33PkV913q5d55EadE9JsOvqWeoy9Pn6CLpHvTqibTuoJN8ocYu4tdwmbgd3G7d/1Ga+gBiPke1xDDm3lJY6w9mTTLiVyTk2sG+wsOtehm1TQdvSpFMGY4aZsmbkRDJBepjZHSiL+qjFEiiEWUFHEuSKIafEjOGDO0trJRrzDF2OTvmI4M+bbbKluOhKHQ848fple+67Y8Vqo7R+6Z4Dy2bpzTt3mvWzlh3Ys3S9JDQ2n7v3vj3L1kuQUncl/pJFtpnzfoH4Tq1tSSxZe/GCmPZqWZJoiS24eK32QpbBoOUcL7EIgCf9fBAPw445pAecz8J7yWC++K8vYiPWDkmveo0jHLLlAOXb3cejaW0L70ovX7T8hoG708vrzfr58/Xm+uXpuwc6L4+dszx198K2aYjvQ7t1Us4WCjv2Ne1Jdobpo9iZ3NMUZg881GEMO3StXmIDtAj9VwDncuqSqwd1mOdtvFct5NDhfYTX7mK0c6Oea+AiXJJ+mWHMXUzphCxrfDjlTFJCQT0KKvQQKX3iMpWpeMSh8q1QcZh+UQHRTypQ3fxZXXn1Z6i5yJ7fRl0q0+7HXJz8QnPyFbV8FCh9uwEyQxnq1+I/U3+GP6v+TP006qJ6OfSrD4iLD478i89rPsbX5k/vEW4UbmSWlB1lyxSa9YuSkHtJ8wExZlOqyu8cl1648dFtt1888s+r33js0Wvx+YZum9lQfOKcSzYdGCC63qW55b3FF7wNddEa9JChx2YyqJf0XrN0VTeeffGD2x69mOiu/dRjv7m6+ITBZOs24AsWHtp02cDIP3uX55b24tmeaF2gVr0E4noM6KHuVUuvgcLWj5GRo3rOs7VvZDC5OPb9lVHdeDlZZnmN1+Mcr7fmplga/aAOR/J5h0H9o6HNqt3K5WG4CQy3mq/Srs1Xvu3Jht/ji7OP++Qt0wyoxuAoK8ef4jRrC5iruuFRRliswL76qf7JN3h2W3bVV9f84NirZ+2Ojt1taTaDP7Z17LG28iZzV1nA/sNETnbGFyRqy0C7Y4txWYrRlLXA7OWbw3G1c5OEn2mZmd0dan/Ce9W3bSfzEwRWu19j2dC9mpHeoYoxYvK78SHo71WWiumwWpl+5j85P6z4Adi1L+duhO2ArYKstjqkWA/OphvEEPsQFJxHijPImK7anUmsh10QU2ZuMn2mMe9gOpmi2KYoxbJJ+ayDcNMVSzb1TZ82va75Mq9uWlixzbBtQgsvSHZh9ZDY2tfXWlfTEjrXc0HH/ItnLZ2Ndgl/1sbBbtEGSv3iZoR1TXPv2CS8Ux1TPVrLF6/tWzW1zpfTtRtmNtoRTh9eda1pAc49FrYnl6eap7hrajs6k9OXzU0sa8nWdKnf0MbMYlfIdRdd1PhE3CRHBnapl6s3VSLGjSup0iFKcxvYXjpGSDCiKZhkNMOq2kcYqEIKO9gqlwMkWLI4W76R05RCKN6czmqSQO6SvTQqXSUyZd8PmDQg+pbP3XbbJxCf2NZ3lcFoEUzLLYn0qp3XzJrZ1/ez2Rs7Iu+gh6VGd1tk3uL5i2+4Zsn+6VYdpRsvsfqtQmhqc0/n/Fz/wqmtSxpwfvTbdbnQ1AvXPJffpZjC0cU3dNlrgaZ8oH1NZ8eq+TNn9jhafJ7TXCx91YbstFBLm93pjttMOov58jZ/NDIFNyyI6qZHwk5Xrbere9by+XVVfNGL6K2TEm3VjMmyPiWyktspagPicrqVqt5qPW7RhsyKALTcrqy7Mlg0vUtxjY5cTPvumwyDNN42YFtER8y1Xak9DSuWbvW3+xHuynUpZoQs4tRQ96rzNq5sb26Tw7JTsgLNrTQ0X2zBy18d2AG0/tTYfNFKdBbRafVGF/RvvuLA09u2d3W7bHKNsMJuGf0MuRDEeBXiJQI0viWn19dYrjPHxLfUP924qDPY6rMHw772jvmfOmf9wRWdM50hhMkKAzHjqFnymJBRtHqluFFRb//WFQMtMzqmB4Itrf0D2xc/gha+WBM+eWt5buwcZ6jIcYy3y38P95hmdaG67/I4P/q/7B9f3/hvbNLvfFd94r3KPTZG5SaP++gpq92U3GXyCAIVN6vYBUR3V5zqqJNYJgo9a4KqwtCi6i900n249vTDJZsOCtM5bKZWMoDwRWEmN91asQUacdOdohehSd78ERTZrP4aN9lPnrRn7C/b7YJI3yd/sH693w8/dOO3v93VBT/ym1JI8dGSg7zA8v4sQ/NC1gzNa3/5PhbpX6+OsHxd3y6uK4Vgf8nBeA+5Cv5v4zzcwqpbdmpPmZJ4FdUW2WHhoyFNKII9AQHTCD9AZHoINarETEwkRxWm1R+i/KNm/bf0giYijwZ0iiVoihFKlFJKNkdipqBF0QHhjni9Yn5Z6a0dinp5oGQ0mXoMyCLkNxe/wLx8YYSzui16ghCVl6A/hIje4rZSu6C6jKu1tgEK8RY0JfxRHGZBxZYB3YgoaU/VdJihH0J1aLVLiNJXJDWUkn6DLl3SH3UT0U1tHtDbHZHexP34qs2din6qY1P39S9t3P7buy/76q41zYsX+nXYhEU5+eOjDx7du7l7gUUXcWcSPStqLpL542rZAucSxqcNnD+34Yux6XvfO3TNd/8/5t4DPo7i7h/emW3Xy+413UmnK7o71ZOl092p6yzJRbZsy93GTbghywbLDYON7cOYZroB07FooRoInScmuSSQkFDNAyEkkIiE8BBCSyGArVu/M7N7RcU2ed73//+8YN3O7s7uzszOzvzmV77f3Y29uy7p6LvTo/PwEzi7peWMm96796KHvljY4t+2uLi2ffP8rhpp+eT1S8AFfz0qW4FydevOk/sztRNkci2lcmTwPWXl/CNicNMV8+3qSuu65qf/MnnnM/19T+86o2LWDL2V0bCcufaN+2+8/9L+Zlw5W7SmZb5jpcP8bH6c7o5FvsdC9SD0p3l3nN/V0Lvz4va1t3tYjaHSbBdbFx185+4LH/hsYbNv28Limomb5k6tkVauvjUbzJuzbbmIvIa9Nb3WiEEJya+1x3GpTVjQCUSi/iiScawRa2S0hErfyEkH36NdE+bHVl155aqlLX0bbhwcGhq87xWw+Oyzz0H/ASFfhoXbncF9jrqY/+qXr25asxprX97ajrOdAy8eId3i+e8eNcUuU/B0LTCPVNpj54mrtIX0MDrujXptASsWw/zRSDRiZe94VPrxmzdKX724deuLwHQjcL/2y22P7Ty6Y8fRnXOvOKOjmEPrqqd09Kqjbx09+hbc+Kb0o2dxRlAOTC9uTf1k0wXvDL9zQXjSopn+4bY2nOfo0awOEeMc6KhCqpKsBAn1J2+P4WCdEiTq+cKwrhXWojWFWf6CcfiL1Vs3ZkTHEejJzTfMKNdjvWL5jN0Hd88olzewvP/g8ST+7pjkwU+Dzu+IxoHHoLzJXpC6vCdgkYY+vvLaC2bOvOBaeSOVQwpfIJFfOpHj3Akq8foMWt9Q+ky0CcEEQMVgKFFKYMTLhEgIh+gzSFoEKbEug5WAlo0UnZCvlbmyZSd6DOIxTOL2UzhuPwWIr4QoO7zL1yaoJMRR9vosM60CD4BX9rkHMYn8+4gZPuIkTDB5ZZbB+OwAJkiZ5WfhMJZM4YPKc0fGqBRRVMRL/CMDmE9x7Nw6CHvTSZE9O52EvTL1dHa+Y5LHB/Wih+k9nhSZ1/K5PHD/TDEyfptrdKsKo9ppZBsHRzXb7/JaYpw2JM+B1Onf3YgbKdfSlFLG07w7evRzczG5TozokfvubXbG7oZNkNi+AzEMv0XxBqYCEqf9EmLFVaiWZEV5ZQPov7RhyrkRACLnTml4CExtqFjZJV22VDOxoiVmR9NzrKViomaJ9JCv9Zy5M9jUxBV04/DHxMPdWRP896ry6pqa6vKdfwiBBbOujUjHE3x1UYkglBRV84nPHeXXt83sW07e+eNoPNtA4ucqFIwIm+yuiz0KiUZfpni3mr2CqRp4rX4SqgiWSc+AFeCseXDO6rN+sJq5Rnp29oK2+Vat9CwS+0EXtJRPOavt4Tfpa4a99B9BbdfKlV3Tzjxz+IP0y1BYt31SxB1JvwuuAV9NmHCtZ0J98Z9HYtTXkTkRhzSXhII4hD6CtW7Yp4fMHRw/Ss2PQfIYtDTf8br00e2PSL8+mweqyzVGE9/19va+F/bPnr3/hb6VT02+PE8zv3c9EK+/HRS+ThdKL0sfvb7jun2aAtV+NdSs6EPZ30RXTWnfn6e5v3DNxh2vozKWnrByf2N/i3GbvCOAX3GQp5vDQbOscqyVISHFrF3pQmEOR9+ziu7IwJCwDTaE8WMzeKp/C6wnvLU3BitOULsNpQZoZUyMii6kXVqn4NSXFkp9hWq1Teum3UGNyawxcxZoMICl42UFN4+TdTegKrCWan0gGtgQCABsGasA6FkGaOFQJpMmiC7Q2tRqoinTo1tpXeimKnRzK0SPQc8amxWVapysu09QFaguoRwOhuxTjNlPsWVjei4+OSvMibEwwJHgxN8Dc/GWjMqR8YgDJl62+5gzzOkgSViEgVbefLOGc9WG+TXNy02Wnlv3W0yVcCU5k36FbKCS74qrRP+xS/ziVRgRCmwA3V9dDciZ6VChFz4EdjurDC6ntJed0Txjf2nPjObNBjnHK2SzTc6Xko7/oajoA8A9g29y9VfSU5lxQcatsuH5j0KCGpJ9MKw7H5MR3UtipiCTA7TCIfwjEa0I0HK31CfdcfSavQtdjvDNOysaJrW8ClYdPQpm5+FcsUbHGKCrr8Dt4BNwO5O84rPLB16ZVtu7ZHbbhiCnuuIzIHz2yxz4ldU8DvbVoyD08MM5HQSOi2jEkVi5WmTrUBfEb+EUSATg1BgESPyjF0uvS/++o7/3TL+vsDI6c/otQHPHHek7MfbAkdMgFLCN3wuZ4Gom2ffE2jk319fPs4jFGkPfE68+8cnln50GruD4t6dHKth53lE0PoATFH0BGsO8sh1WNkDERVY2TigO8WiUoAM4mGSboE1/pC9iNGYz85LUz6gEvcD+inGYwFTRyT4MrlQxIv1ri+P4zgLIFpro0jVAa3TQDQahwKzSSDUrYT5/xvyR+lC06EHy6Why4XGPEcOtfyQBRQWwehUkPp6qL5VD9nolimhkx93rroPyPgnsK+2FGP2utD4/3C+VyuQeZ6+uO5W5Fh9Nddel6nOySQqtZmdRixW5KOP0jtFnzLFaWcuIl01cxhSEvcnAqF0ymcnx/TEKzxrYJASsQR9Pbkcnb37z5mBdcObqmd5W2ivqtbqaRY2d51XwVkZrFrSMla/Yftl2siuYye55nY2LanRavQiqqBNg/o+vBPqh+7wgTZVXlmPX3xfTR/puvrkPizC1M2fWwk5tUC9qwuFpzZoSzmzmSjTN0/LT4bBG1LPwWWC+rOf6P++H8K2VEK7EQimTtauo0IrYhVcgrFe2pXjHKEu82VjolpHEIkR7TyPJFuvdpSRmOEwTbSZMoTpQoEJ6B1I5Y0t9KYNSViOeC5JYlQ8GgSeLt5o+G+WfnybvfFBW02PTit6I5oPerFxJ+FRMVCm1lNgmSXi2smZCza9ENlhkpulITCYjtmAPtyy+BF4ZkgAp8uYyf9ifPEqWDhAOiU5xQx0uV+2q6YOTNl66/9KNkzo1ZZqk/iN9Em07k2dVNTUz1QUFVfq2sKVneY8l3KavKiioZpqbqs5afN2zP372usU00byGa9HdPN11Uy+YVVU164Kpa2ZpK7W3XHfdLWgza81tm2q6t9QWxgIuV6CuyO4I11bW1VXWhh32ojp8LFZYu6W7ZtNtqx7eNHHipofJ+C/jtzpJHApRU+dsQzIXI3GXMOVhOwZzAd8yJJj+2KCo1+mkn6rVIEHoFnsxoSBBajw2SJBye2UkRtCLaoH+aVA+zFqYwCiLIvRmABeJajkLq5jB2SP8PlESY1uRswBlbFmYZI89hV2ZpQTDELnxECZ07MWEjis0MGNtvvJcbG2+HdBNU1b0Hyzbez/sNQigl9h5BgmL5CCq1grd28QGvff9uFv/Nqh89NrWg/3drcVHx5YxRByXZZyHrB9uREFWOGkZ8WNQK9ylySvsKco4aMA1Qfl1OoMgkTYGvaL0+UkKSeVzjPPUIqo3Z9Fhs74adBx9pSTYXw7uxxGOnjjqAPjrzSCChchwNGI/GKrDPphuJuvYIZt6maDstqENNPZ12honDwwOTGko2Acm7yvoP+ip76n3dPd1k+2kJgAYjaqzrzGglVKKG8fviAl71/n795/fufvgliXGus5XLKtbegYGelpWW15pLe7rK25NHOxfXFSOP+7yosUYdyK317ndp5lYXFcuGpdsObib/q3i0JGN3ZbbYkZO0ouj5Y/ZwnhKMOmHQtNJzD7ki0Dv0hOTffGJTkh+ezgU1yqfIZJEbTZsYUqDDMF87/tBJ6cxN/ux27u3+AhQHSn24rS/2azhnMH378WHGqag1qFlp4NE60qrtO3Qhx8e2mf57bUEmsJdgqQ4QTqHaO8OCGinxA0xx9a1v7XsIwevsK5sRU2j8GXKdlW8mg3IvlFsDmIcrZ0iWVcoBYc8kvGIkgYJMiIzOEwlZRcoSO1bmkAHmSQGXtu3lEbp40jekj2fhoZTS/ex1D7Uprk4scioKLHvHxlGJ75nMNj3Cv6SZcOEItv7yJsmlQVeudOjDlsxirOUSw70JBI9333FUwf7j1P9B/nEh4cS+5ZixEishDlETxgckJLpFHo+o0Z9yoPbCw5hhqscnngV1S5LA3w2ylTuUqTL2GQMk5FpNpvTn89dOqWBgOc3TMmHKcBRLBQ5joaJI/uwqx2bSifRZzH8Nf4IaC36UKAMsdpLnPEGR6e/I7wTEI3etGffEdnuK8eviGg2kHFk5xJWAOtoIztv9mJeUaDM8GYwAqYlGGVHWQFHWwXZI9jPQbG8J0t7C/eB8zQ66Zc6sIq4N1AYuDcD3WIQ4FAmlX9UMDD7CntLjyfxXThihe+ULivSgQbdMYGhsDhwjKJ7M0Yjw2DOuneCyqVxNHUWA36sLekx6ifUG9QfqS+RBGUExaAKtIzlfo6O2mdH7QfG4Xo+1fnA/8+uP13+0fXFqNrmjLflGEwjzM2cFdNymNdULn0iL02f5PiJ/4v54UmOjywzxiDFdSMAU1Q+g/pQtqb/HFvxvGPpf45z8J//BzNK/zxlyY5dj4E7h2QBLs8dGGsgT/HNPEv9nvr6//5X8r/ppVm/jLz+WgAymP3+6EhvoxYQsY7FiI94syuY/yO9+/v2vhN4JYzGQZyWeyE5lVeepHK/TN8ECTRKYi6ZxP9nffQ0PWr4eibpwQO253iS9Cs6JRe0tzfrWCWnq3KfDyBXSENBJHQkslzg2PbaTK0aaX0lMKgZcU4kry/LwODP0DBYs2+zVoF4GmGgDRLrbEy2zWanYaJ2k14ByTsNqp/zkKXIgVeQtE5M3TL+fCaJ+R5TGXst+W6c4i/EhHNQtuIoKjy0woX8z3Wa9GGyT3vG3AcnYRibfzKWW+zTOehMoLsRf/VgBl9Cxn4PUTXoW+ySoyhPW/XvJRWS1dM4VUzL0mKSSD9M6nhqMCctetBBMDh+bb44pRCZwegg2OrYUsHpAe+XRfAKOhox+3l/CFsFo6FoHBsyo/GIHR2NNkHZ1xdE7Cxjt/FJIH0oDQ4lpN9Pws3fO5hIDKZ6PZ5kKpX0eHpTeJ8IQ5NAIIHZG1gngAkP+h+twwxqDxgc8qQ8KkfSoULbITDoUeOVYMLT6KexnJdQ/E841AuJdQKLuVZvNE7aMxT3xr1ITMKY1dOjDJoYkslDHyY8YMhDpzwJHG9xgopOlxKpVOrDQyCRSCZTnuGhEbyjmD0kRzk6yu9RhgghOIJjEHaIH59E5bhfYYZ9NN92m5JtV5hGImPDwgOChL0A6P8a5Zs4qlzfhw91vHJJKblsKflZcqkSo0smE6Im5NKNvAA2jiwYRHL2DPqfTARJcWV4RTuaT5ZXA2a8g3CLplbj1EhhjQa8hRK1Go20HVwO9o97+DBJkSPoR86yXdquGf+wzE2GyvXfmXJROd+WHC8tM95BOBc/XL7v5egJ5KbgLVSu8Q7DGXJZyd7l4HKlxGHN+IdxuWZQVzERZu6I9hrJsSCMd5CJnK7WIw5/Pqao+Png3HEPU3K5DqNybclvr1E8DcJ4B1G5TlrdcQ7Dw2NfLsqBCzbOYTwWof4Ft5D3iEulBqMpi1FHUnKP6Df05+M3FhnfUN+Ac7P3/N6d4GRvm9xzBtAzEXqufM//4AWCs0/2TvA9q9A9t+TK+T0bn646SXMqdmhZbqyWcUfzkXpkW77FnV2R17WCaN4YglWN3xERgUsQ2356yOORicY9njSBSeJwMJeHJjLFMPENnoFd0AKzW/R4DDE09wRz7mh5PiBGErGOx7aRlgY/yMN1w2XFIqAiM0bY2jo0AloiYDDr5NZ+fFDUM+Txx1NYETooQzcN0gMm06DJBCgZhVNGkaV7cwpucXguUVb3olkq6w/OyLKOHc3sWTknMG6r5asMZJyHHygtoKflxsrhzK0lCoQhWaM8jEtAvzbCUY+RC0D0JnbZG/1kT4ekCZrAaBoA8CYBRaJOIKmOInVEvyncBINgQnedRMnah7ruFTJ2EmkCWd9Pz/B4PMMkA4N/8+cfLSoPRSlsr61ANk5mmZJvyBK7HjgwhtqVGcwjfn1hPKwHZU73EgadXH1aYRPIkAVnqbzyKXPGz0BTAz1SsmcAm/jJbJboP1hfOtQzQCdPcgIm8OGBHpjCrgFk6jvYj4RfOfs4x6lxy22AecscJOuReTqf6ufUGWhqTMEGekASl/skJ5hUOjG6xICU+CTHKYLVmjiRIPpCNWUmyGj4+2tSYg1kKJ3abMRgJrrAIqtfc/EG4+eQvfagYXq0rnt6P2yRjetXkA2TJnD7/dOHm5fvW758H/OVYnqXQc327luKmROX7vt5/3ScUfofWVqXDenpq/ENp0+n/44vXZ6+Rz4phyRIm+Ur9430GdHKfpSZXsqNRiVRfBvzOuMIDlhgoTGkggISiv3B2YqR/ldWc8QjotFxD23U8TqT0cyy/taVm265bSUmfpUoEa8h0QcPf3V3FAz+QPoz73OqzRaj2s91xtcMbpsfK9bhmF2SDf9glFTp7EuyWK0U+e5qqEV4JjAAXxjUEaa6vLRdRpbyhWT/SDeNKb9o0cIbGL8vzIQyljFZb47V6kT5C5MFLfNaCvAPvCWbfH7/uWW3Tnlkys0V5+5PrDxwyZwH5lxyYGViqCV46fU/Pbh0ZvL+/Zf1e1svc0U23Lv++rtv2Lfu3vUR12Wgr2deZ+e8kT8XnPeAVau1PnDeooumVxkMVdMvAqo3Lpgx0OxXc2JZ6+qJO9/8/NCcRVvXzprn98yZuXbrwtmDI78rO34LyriHv5pTjr4y4xBaiqcTOfMzJl4dQ0I0BMm5RBZWEH4ympVI5oLcxmIuyBCOkAJ1MpAdamECigtiAW90dMHQwpXNsRfll4tYzO027uvo8VTpEqf0OyHKJEqXFoCgcPwKmsrgF+JCA6ryWrYhLL1XcaDjeCpbbrSyS8XOsBnhMn9FsXSjw+SvLAbrbU8N5qryMGiKTrqntVG6MTopV5mlgzVhT5YDSOH0LqRKqDrC1ENMqEECN+JGY1K8FbjBaGA/yhSGHgM0uSEa+YV8ou9zAr+Wfh1QOZwF1aqCSx+4tEA1odYhaWRfmumyL830tQ9/Lg1//vBatAXM5w9/PJqs/LXzb7jhfHQDdJueVat6nA5TNXijX76afPoSvmxt7jZouB713Y5fNxuB8pPt/djjAn8u/0HdVI7aCUqtqgucDhWuqxT/z+oWKag2ZaqlQrdBVYXq/23dtMR3vwJb+TN+iLiLff8qJYPONFlvwqRTCv5nNZGNguDp/6jwipyHNvIs0/H9NCTMKP+uEhPl94X8nAwB4a2lE4IhJRiSBkGOeMgkYUKpjLKR3n47deD9A6m3pbdB5dt08m2QGnMNTp5FqqN4eL0tLZLeTiZBJXgAYCZwY1Yvgsdi7EeN58q51ApqPbWduohoXu+hniRWfFQnNBygesTz0qG8NMqD3htKo1oETp7ntMdPlmbz0+ZsOor3RcLwNdomYOo1oX9J05AJ/VP2GMo0jARGuteUzp4nGzD+bmYrUcp+botuO4Av+A5Nq9Oj3xH8TIyiCQZIjq/yftNfjTkkjbOjbIC8Uf5JgySfCcefDifxH34QjX8pBUtT1tXZqHJqAZbWMr5BvJnwbRBsADDKbKhYBzPRcdjRlMmiR8SJ22smYgwN7skHL5/TtvqB5Yc//vpI/MxV8XhhZcN5x8/2FxF7V5Ef9S025dfwv7tp0eTCxOSBxrXS1yuMgsnkKfYvvOreroGfDQQjO47Y1MXFxeBvsG+Jpya+J/3gJmOgwGWw0Zv8jebjBmJ/+4e5ERu1t6XZkMAyW/0Gr7twUaNaJQbgx36LtaIl2BoXB3SsSbDg2J9M3VnUg8upWmoytRl/hxxvjYnkF6VDUTRUqlFzWEml7FZUL3QS1dVq+3/VLHTi6Vdee/KRt9+l//q3Gy0iW6+vFcPOSn+lze4U1z69XrSU15x3+MHLq7w3HH/kf9VW0JEyrXm+Fzz+kurcFzZK9c9trRri1HQh5+BFTssw9B8ao2ruiBnyLyxRvVgOvvjfNSTWLSG5hOgPSmRGy1H6A5tldPwp7BpPoaBhqgTDMDGE0njUKhtfiyJV5UXe4T5cdeJ6fi7zOXl+g8LTOVK9ZrOo0YyOicZwID2GjB63mHDdeNo2DZwkXcHYda16PQO2yQl41bgVuHx8TRTjPfY1utjM2PWsVk6k+8avXM43/keUFWPqAGsGngZXCONWEsA6i4FWQBwE7K43KpMVPQGJsgTBRha3i8pC0hZR5PS+imghp7JwdAGsuDHxzl0j84DbjjwIfjEZo6sosjd2BJ8kbcaRADMab9q1q15nBionuPa+KbP0x0flk44V/vSwLKvCE4e53ewQpaFKUR2qUNvTZjtLh9RAJBiuAcIdhJmDYpg4CEngIusGzN0ASLe3uw81gdZmHfhaunEBa7Ob7VKb1IY2NnaBdINHqAL//tBSVGj9EPy7SoAdx+o0zaB9uKX4AbCqHUSlOyWdN6D77DNdwIs5hzxxHlMOlUkNXXw8i7+bJD7GVA6w3uvDgG9Axr5gz08nzaWsxuZKp2x+jWBhKb3JJRh55p7jlB+yfhtMuCpLNTDJi4ayDNYmls0hGk3qCTq+GnhlC2DWzOdVfCnkhW6OyDmOeh/W4xGnlyo4N51Ef4eZZMZUMTw4wnJBz/036i9q9TfEsIOy/g799eZZN+jePAvHN2o1yv3v4cMCpXBdMDIeL2ZZnJ7TowijfMax75HMtVIEiAKMLPfimXHOisc+JBazUeUAwH5TmX/wObK5ua4SDnVempxbWYdWo3WVyia2Oj6xuzxkJrsOcgnzHNlMJb+9dYsLpA/3BCtKWyc5CxbX4YU7OkTX5dKS0VlsLgiUN89SDma4VrAuz0A5qSA1kVpGraO2IUlEecuK6tFmsctOscTJJZgnMLLZIIUQRtdCowL2/o9j0hLAZ9Fy7IAPEm/ENiUSgcm7Bci7NYs1lNmHgmdPUBq9TqtWAwq/vkGZs2goLxqWhTIIjvSE1folMLvmuK4vLJS+EPxW0DMvfdOX0pcKoA4Q0DHpcQUzB8y0wqvzbpP+h3xrcNMJSuvIPhCoT1CkLwCyieQF5A6R/IPnYaAcMMvqF6QvXECG1wHil1b0qAVwuQAEBXJH+uIrKyrSgnPJBdIPretk+iUq75b3jXiYPCb0og9lmOg2m2XfzhHWbzyiGfKPEmd3BR6azKcgLnixA2vKgSQaB/kBzcWhKZWhsjjaM1r3zmyqXdYyscI/VS/o9PfqWdUgmNBz9945wJG5wAGnxpY3Nbts9nkF5uKAWDX3er+rsbo8UVRwhkm1S+PWA01r302Z9TbE37Qbc1Llo1/IdLeZycyKv1t69AyXlPXAQWcikaGURomkzPcig5FloS9AUjGOpVNBZi0xLsnBr5BaiX7cWV6PUQ8RaXlNHaKDShx3/u3dhSCEd0OgEASwdTYAPEP4JP5huDTJSBNQNDxqUazErqd8WN8VsPpxhL8fwwZ5oxGR9ke9BPQgEmuDXqufFoHVSxyKmcwbCsksMSRWJxKlL/z2kENF02qN8TZJSr70/OXAcgW0oiO0quBKAHY99yr8NC3RTN3MM2bWNZVFwgbbOmdg7rpzLquZvqg7Tn9y//3D5Wqd1eI4dj/wA9MDHzFBtU6tK//oAelr6bfw/tddhUKiv6Mt3OoN1oS0rqWBoonbV9Uvb2qsaPb2yP2Nxf5j9F5Up8nfp07syetEf886fZaWGHpknXo2nHPZpFWrpzGnqdJ7r7uqwNgata/raOwM9ZD6ALTe2sPKGHNUAPut27DqhfSAIJm7sLY0CXrSlPQ497VRWzCcDDamqWCbCaVplKZRmmDrMVHf9MJhqrLMh7YM2so6vvfJ+Nkn42IRxGyMIWv18QYoIz5n440xUY4SK1ANfCFf1IxxMbBwi4OWM0HKhGoIE69YscYQ42vIhDpoUbB4VllXVWfgHA+waX17+sIt8/xl/g2z553rDrjDgZ4VB9UBtR5ACIsD9MEVPYEwOn7u/J4NKNe8lsQn1YBlgcNfWWVrqOmpmLMEPDMbn7ogdHOIRaKGJtoQ6KzqKpu1eMmcip6aBltVpd8BGQgBYKhRlyolaYi6Rz1NkcWYJOGBi5Dvj+KtWZZx4nQepPDXSLTtlEdJ41nAQ2YBj41JSu+9R6AHFR0DoN6T3sMqAwKsiBInqCPSt0ewzy2dSH4gPe/YJztU7nOAKR/IQ4SM2UiQcdZK1L4jR/ZB/Is9apEss4X4uHbg2RzdMFscNZA953nU6HmFHFOBEJ+Pc2CzBIAMfA6Ma3BYBrNOuunIvnis98wNz5PyjqnPrnMkNNLP0WiYt8hW2pG+/si+tffBWWvO2ihXIArd0k3JfUfE3ohSEeeIquo7JQ260olvgbfoDriG52Z9o2XeIZ/s24C+S9FsMbCELDKLP84kpMT25X9Lday6fOvuqElXqDNFd2+9fFWH7OQCEzB5/Jq2ac/Rj6epBQ9edMGcLifPcbyza84FFz24QB4IFRmJymJC+PF4aPeavYFRHg9j90dFCSnCXTaFWhRNJsfQ55dz9qTzHD8x0cUxwlSYXN6O2efkDTqCJLYU8BDgDCLT5aVnHidmKRZHDxHWOfm3m7QbTeTcISTrded8ygMKlGMgjMObRjrTxqMYbUD5rHEsWtYp2otOBghEDJS9yekf6FQ6hpYSWsMJauN18mS3a5WnaWBKi4Uxl5r0drOOFesnrqsvWL5vuQGEDVqQohl0FSu/814pZVLzoBcK2rX2x7cMk6mJ9vQ/6N5Y3TTNq/LzulqHxjN94iShvBLXylusFWAv4NW4biUnPJxsi6zKY261YImV5nhWRu1By4tsCpc/HivBBqdBIpwCx01PzN5sgQYpyat12oSenS/9j/QZzRnUCbNuSGMCO3t7joB5gDVYGFlKBcnvpBuf7OmVLjZphhg1fmkWUDAfqBOiBSQN0LJ59o+uFrO8PkflNQagvWIshDoL2nrRH+0lmNbc0XulJ57QF7rqH3xVeuJV6U/49xZmeM0Pm5rL4fE0SyfqPd7hKfTz+A9Mmd3V9ZORvi94wKEC8VgdWlVl8Ok5EoGSb96hr1oritJrICKKa/EqrlEUwS/EOnjJKE3mVfgsiKB8dSK+olHODN89Kaa6/Hz06JACQm9XK4Dv+c+Hr6HHybdDtwUR6TVSEHry6OfjUuGiycV8DeXDV5zu+SAey0S4yLD36lHPZ67Kq42YqyQY3QBAboHRhQXvjsVuH6cNSPOrMw0x+h1UjamX/BJGq5M/J40w+oXB7eO0QYLEi5hJD4ujnoVhaPwiG4kGRG8IeGk2wPSbhq+shqttL72of8wG+hlwVm36AqNUzyaT6R+nf0Y//Fj604+i0SulT1eDVdDzNHjn2Mq77yb9V3ciwf1LwY3zqqHo5Vl0X9Eb9wKR/VD69/D76clTQFkR+AH4uPP41Ebm+eDxqWh4e0X6GmjB6uvvugvMBWU/UdrKxMs8HfPzvlV5HKoGHGql0BjsWTew5y2V8xad1kjGsm1uBfEMQC2dkkeltRYVo9cs2y5tkuqkTduXqQ2MyoJGzF6bSmVc3fH1jbJw3Tj54NsHJzfKOzd+3bHaqFLZQK9BYD4mY9PwoDRoU0H1smvuv/+aZWoon7SIptVLdlngpURav8e3bTL2gJy8zXcPOZA+37JryWqTaBHk75/IDf4x3FrYhxN1GmWhE5WZbhlPjszLo0gGCs1XzgxG8H8ThMfreVxy/HQpNdKGJa/ribSSQ7cNejiTzUOZKOXvZHYQGbYW2JR4J3CmRJT+ROX/yGkMIfBTGab2TND6Ib4ezsteWpnefVprDtGhIJE9SWcwtMasENnT+U8n60tJO6Ww1+f4adqTSY37k/VzATksrzHlMJ9mP78c4/2AXBnAb8dL5vM185SLimJLa9bfBRNXEtsQ4UUARPYIwjAowcwN5LiNEeQTY/kOoewmDB7SS899YrCY9be+rwWCPqm3gD3s2h/+VfrwVoNaI+hfBUuP8uSERguK870h5Sh+3ydgqh5Y0HkBaN+/VW+26G8FxX/94VoWaDTkKH9UuvdVvaBR06+N9pHM2e1co1gvyFBOCHnIWmIMM8IT2K2q2OvxmExm4xi0/PRNwjQBJERBDKSTAVGlRu8ydiLKvcL+mshy6F2q2dxsgQdpWQ0cQ23LhzISMNF+2W0WtFBoTr8ovQjWwX40IGO+kfRBNG73CzH6iuFtgfWB3fUDg/W7AgH6CrSzC+/sDjDN0otpjK+Kr6rDufFVdfh6eM3w1gC6aHAA5VsfoPcH0EVoZ1dg/Yh2kdf6o8OUx/FflZ1k6eS4HquySmGkhyo9gie0ehyNwml8ubBScphoeWgZvS3nxJXM5xGFQ1kdvVRLaEblnPTefEpRNE6iEtHH2D1UIfatrgA5gHLsAe7PUerSx4TSFA60sqpUukG1CSRSpYLZCRJCK3rlLvq+ANaSChZjSguTgUAxSNpsUtJD5jIkB6NnULi3iRl9jeI+iCkEzV4iIcY82OUrVVriklLoplLKaUaPlFIG7aBerWYp0TB81zSPhO4LksXBAExqUwaLOFIWKMmTBUAoJwuM+QwPw7XK7F7134o4gGWitflv8XO4VpEFUB45860ifUn++8yN+xwa2a3KO7Xz2BGdQCqQ9lPTZqAQGBnH+sXdcHNdfS94y2CWPjDrDWbgN0vHoUcaSg/RyaWFhTcX9hQuhYMjWE4fubmutx78lx5fYtDjS9IJ6AHo25SGYO9SdMXNhYVLe0/23Rdgn1rF15LnijMsQXEgKxDG9dT2EEj49KdyQ0DbtYJLpw+N6va9AC0iQmVFOB9pOZRPZM2wfDTXvFyOAI6PVmcGnSLgM7CyiiIeC0FMCizvjUEl+xz0opcy6A6Vbv/ZRWfWezX3a4w8Z6Mr+8MPXFmq0zlhcERzPYnyo5GgF5tIBkNtK3p3rGl++o86Wu0AK7fXVQ+Wm1mYGtFYufEfojcrUG5iQwFmYEaTN1C8DUdQT+HgDRxoI1G0J8+tcIzTIUglk2BW+k8nKLQi/4A4Jsq54YpRU3IOww2jXFUpGB3yR4OaYfRIMbqVmPMFu5QS20UpZRfMpTBZerPi26mnCXxCfhPRy/zFUsLlAqlivz/tGeEIOmr8GlUmebhQBonTl8lcmk6WmgU7miXaRZCwbzt5mcA9fr+/GKRcLilRLP3u+5eJ+CbLNt+YHZy2TAl8f7/8rN/n2z9Hde678prSjNs2/RlNRmJyBf16fpmI/En/E5WpF41IdhtnBAbe76NCWZE6GM8mYxRhv0ZCNzGRshj4QxbCUUE5u5zEimaCK8W0YQMj/aaf1mlZRi86XOgFiJ9Kd7etwA3UDukOXKiVHeDMobVLtWqOrqBteoYxWgpcxYbdL9eCt01qDe1gXZKDpsErRiQhOKCglXZNeGWPUFJcaDUxrF6v+8shnRVTs3AsyzIQsB+I+k16sWGCYNhsEN4ClB09X38Im2QBzdA0TA7odIbNzkCnTmcc0Bq3XU4z6EIAWZ5X1uP0MGqPtpwn7UhNvozsgo1/OGQLc2zJjMaZUGFzRpNDD6Mm7zQIov7MFbimK775yfMH0RLhLLVer2HLe6vm94EaEjz2BrhTMNyNXuQ10nU450HUxfaI+osMwh8f/sMuVYFmjxZANVtYsrz7XcFwkV6ULn5aBjIGVN0Jin4LrR9WyrzlWRETey62YbAn+wQZlhfrW+lQWIWNc1ldE+a8VqqhMEhiOCH6rV8eEgyX6sX2nT2dBazZeBZvMqrhpr2BwOyd7kBPXSxUNbO6vSxcYH7xDlF/qUFoWN/RLHBm3WyV0aCn7fHWheUrzjOXB6aHq6P1vfFJASdYccsHzsdwazymrqyKONCzLtVAqIWrnKoFswprfWV2q0nwuyrLGpqmle1/0/0UhoZ+nPN5y02cYDlgBLSGFvxF9gWdzsqQyy8KFnt1sHXiIuWd7UXvrDUjgxsAb1MYgkNUKOswHM8KMMGMHJ4J/64ANju2zuwVDA/Y337oflBi0KisPzeppdcxvsfAvrts0nyiU7uj4b+vw0Wjyff312rzw2g1WL7WIFz7lOUJ6VaTIOjAxlfV+j16ccEcwYBObBL1F+O8KNkyVyBAhkjUIPzklNevgPcr0CTZ7iaLHLUYVRktX0WSRuNqJNPNrLkOZ+HgkkdQpyBxicAjb38j/USl0gg/EzXvigFNGf8TlfUnZo1aJf3yXdLn/gB88hZVBUwTDGfpxfmCoU8vwnaTySRIC4MLHYvM4F7RZDCnXxD1fQZhvqg/yyBIz+hFhUdeXnfUk7U67viYHyW/ZNnOmPt0sil5VGPEvf04kqsfbEy/LD0CviMKS17U358xS2ds1dD1Mn3WyxdICXCXtPtf5452XkMHbkRl32YQ8jiHVJQOSTsFaLQ9B/UM0S/aLPa6mBj32r2RkB8fQIsg+YC8RqRJj6H9tMwgTWdLmxsP6cx78YojtjaezioceGyfh7MPTQcAbPVL73vAXVf4J4NDM++ejY5s9ErvEszud+7lHYcc/A+O3o+2WjMcfBPX5zHv1Xhz9mJWozFd7mTPAGedyTt2O/iV4OxlrPNyk0bDLtmIs1znexKNGfNBBVo+M5jV65FkMplGS2npHbSDDh1OJj2ol6ZvdjhgH/o1aGAfkbVlzTJYZNTrHNLNoM8h/+r0RukBJQNe39afoJhPUDtGqKkEZ8iGyU4MDG/1R30hq9/sQ59RHElB5kjQb8ZOifbaeDRijWHwUzdN14UZHwEerW3l8A6aGtBOK8dcI9y4bauej8zcumfOrT3ltwpTxZeLN9aqTJxG373x7YT31jmlt87a0ddy1F05pXlR7SyVqjHYWTMxXOMWpxSUNNd2VUzk2SZfe2VTsESgk890Fx68YsqGydU25sRxMEydAM9GwAEAijvvBWD4G/j1MF/cdGb6jpL6kgIdB6VHAc3qTE5fGHzrjXjtGg4A6TU0PagM9uKwjIVB8CSUGEls17ezcpxg3pTMUDYDuNlgSD9QXwo9WVgID1oO/tZgkPoMNk9p/fGhDMqDzOGRvW8p+m6m4ja1e80YSH5kXLbFJp4Gmnv0PnsEPbPUZujML0r9y+PBT4xOMyUGGy5y+sVcaTFOVdqTXZsBw3hJLH/6UJ12cRjZvIRqp+agGkUwHZCfR5MRkLGXMssnedIhqyoWk1vF2gCmLcCeL5i5ACDhw4ozRkXMShDy8xG8FSMic/8Pp+ow/R2T/koj/RR7R0gprIlLEf8V7OrSmX4ObNKpMVGaTvjkPBiXruGMWoPa+u1b0tD06n9WT5c+nPzx3R8zfb+rNjEW4NMdd2eAn0yihSVwG8cGhYv/egY0C2o1Degtf1mc/kIlaCGE2+kL+/uvvba/Hx5M98u2n/x61+F6B3L1Zk9abzCqZvQp2+F71PuOEbUTT9oK2Wr/abxaS8O56jF7xjSBBslf21H/9SlYaXhd1kB1Ydy4wCle8UiNAf0f7sOh8avMePI1C3ipnyQdOUl2JJlcIUV2TlBkB/32jlfrPLj3f5wmKU93mfobc/UfXcvAKV79KA3KafaZERWQPOO3BhwcVecRrZFrJ0+2KpvHawqw+fQNQPo8+7rS5zuwF3CAGPmJ5f7kfT5gwXDeoWAoLsuhcT/mIlQinfAHgEELkIyAHS4wBwnbvqiprrWrs3Zy+s6TVPoLZ33PtkmtYYcQMpoCwXlrTNA6u7L/kmvP3nmvW6q4H0BeJbTOSe38Y1v/tM3dsQXj1Tneuv3sOTUmFb+JZ/TbFtoLr1mz7sALsHrzZvA472BNOr3QuOD59GZqTN3jxAM6V/dTj3Ojqieeqjm+R93fzK/fz0/REIxS+eMPjVf74dHVZCPjtkcGKzKh6GGXZt667LAxWu/HYmRBG28j/GEcj/GYAaHqJWZjAkOIIVihjOJrtWAiMMhj9RIVdLoCAZczOBh0SsTGCzzOIDMYN9Jhs9kYUjcmLi7pNrffvnDGTr8zWFLg6Kvp9ApOtZrXFlpEZ7ir2mtUA1EUaIOKAdaZm4nVBt0TurJBG+h3QVulp7ulvqUhMDCpGxa7nBUABJzwwoIAhJsTC71Cc6A8VNlsEa3FtaXNbkewu9LHOSyGzVSWKz1B4spcCvZi9uWNXsEHbFayGoZ27ARDIIwx4S+UqYuVJsHt0URj3jTyx1tO1hDr4mDTTOlvjMpAC4IFqI3e6q6wU7QUanm12il4O2v6HAUlQad/54yFt7ebu0suTjSqQ0azOUzTmZZI/0VuA9Iej7UsmrnZYHFwgdIZQYe7ubS22CpamitD5YFmwbswsRnCQAG80BkAoMLpKobdkwYCDajhuj0YeT6jy1ATO1IF1YJaYzW1h7qSupN6gvoZ4TLB3vBYSxbBcGoBJDCi/6Ms+lOMeBFFfW9mFR8hlAWLj1jLYLVkmGHQgEgcX4uA32pBuetidZjHCAdm1II6QkXn9RBEUgXw0kP6GRLv+ZCfAGBaI5jclPhqIXFJVtxh8A2zUg6/Uo4xCrybiswmk7noufb29Es902aCH3aEAl411w6AwWIDbbyuzO/t6PCUlOn445DWuaJ1RVZL0VqX9WKfgwPShYkEtIqa9orLpM+kzy+rnKixWDQTKy6HwcsrUDqtP2N6JDpT5eH92mnAay2qibisVlekpsj6dEcHgbDu4LTo7uCbfAXPX++oNQ2ZHvZFIp9MlhaD+yfvlq4rrSo0BYFP+ocDGouBY+OBOmt5WQn4/K7Scusz6iKDTSgNupoubHIFg4WN3RMjTqCzaun62yOR2+vS9A/nVjaxRiPbVLnw8OPzKppxurliHt0ESn/+c/tS+1nxX523t7EoGCxqJBtXM9gs/aXYBB3AJP0+ILiqgGqkDhd9HWi8/AuJkc30jyXUKmoXdTl1G/UYWadjZEL0rlkk9NTVBiIYQ9cc8Y7zWjIvL4p6R5S8vEDUTzpMC4iMebFxzGrjQ7u1hPWW5zyki2CYcNQrPKSHgAiN7o4BkyNipu/J/Qz3vcA4PZR+JWS32ewhMOeMM4Yb10svr1sNPIsXu10CDRardOEJMXBYbY7VVixeXDUhZlaDOUvQsBZ+0hXq6AwVFoUmTUULFZgeXLAAvuE0LGp8Lu18rnGx3onSTc/Cj0l62Ln2/NWG6kBh/xTwTGFgUkewsDDYMSlQCGYtidaG9aolgBZcblDy3x02UGXrDIc7Dy5fnv4l+EK6pNxKe8AG6fwaR6Bl+UtdzvrYe+l1E+Jx11x9RFMyaeFZswKRSGDWYbSJulxq+mdvTZr01uT0wk+3NvVwVivX0zTwBU7zFguP0oxB2iT9HRin7T9rnvTd5Mdmo6uDPY/14JvMkfTx1oAjAvZL13mhrQLskn0oMVfuvykRR/wDTl5Bx8XaUGbBjLXC1oxSBsQAPgjna75xBb+0WjRpAO7SadX2L0ud9K+12vRXoEer0di+LHdIhwUICkJ/t9FrBGla2Ie5CtArNBqrwGqTdfgMkL7FYjZWwXM89NVV1AhOETHLKYL1PdiCYKU5O/bCigNyBNgA2YuFABLD7WOML7utxc8JKl6160W1WmV6vlik47z5R25RWoOW2xbPcwKvUkvD4BbV70coqWnwgU+rM/8WSD8wGPQl9GydPx2CktePFtjgfQD/23TZWJwaSsYzJ/gS1EjzJiixyISZcl/G3B4g15sxCKtboop9Xq/JaDFACrqh0Wjqn/KH4d1/mLLeZDBCZZ/eq+wvmWYGCYsgBNPJoKDSgMTB1Ib7JnatVhUUqFZ3Tbxvw8hdSsav4lLsfmIfxczFxejTZqzAGuKjaN2P/sWtah1adH8hPSTZ2ErJhtbU9uvBAgDAwvRssEASpEfZMJgj2aUHwULwV+lRSaBbpDekP4M26aMN0u8Jj3pgQy8oxCxn0kfMb6U/S28Cg/QP6e/ST0ERvVv6qfQPMAEJ4Fo0tnxN/ES0qL3k8mDcZr8Z/QXiLI+pRPEfDXg19l5j1cfvHmTvHBye46WN3vSiDvhOR/pfa+Hate+BD5KSP/0E7ekFQ+kkTFbecd/t0HlAOnwdfGZn+sROemd6Ty+88Nhdhw5R+fYWq4IfR6HRAjuwYnptNMb4lbmfykqHuVBN2f8vPlpimnOpJfn+3pekTyxX+Z1MVUGJ9NHTyT1PP70nCY6WFj1aVEp+Ht06+/j+2Vu3zmbOnb31HHhZW+fudy4AxlRnW/o8p98Pnvz2sce+fQxef19hWVnhfeiiz3PZt+Z9E0aCizHa1ySSjRTNRHcQaiC5l4JbL3j8ggseh4+TTYb3R+69ww/gY8q//G8PopEf82aLXjaiBpG4d4SbE/Ur6RwYWy5FpejyPqgBx0cjCxyQXh+CT6ZnDIKa8eJ5e9gL2XuQLI6jETuos7AehQvhuJwY+iDC+FtBnwX6REQkbZWwSMLETsdI0hJJ7ACSv2g09rcBJCq4ASdyBKcggA4z+AzmmIiXsNhvgq5WbYuGigqDJV3xjYZfrGybTjPXL12y4yPL1Moa6QPp84pwQnAvjTd/9H5bdOkClVFfWbLgjZfOCk+Zk7AUeDjhjzA+ZOVMTzvns5UV3mHp1m8PGK16lodqv9Wppot89SXuXUfATlB2W7MJwPvauj3mOXPMgq7JvH5zZeH5k5YkVaqb4Q6XX62qruE1PmehX80XFapU/mHBuaajyzKhmjarLL6ov/dFk/qGGzhfPf3c/ZLDXVdo3h10DeiKylx16tqXdz4y1Vnldhu1YSGwMNxtaSW4qfK7UpGRshGtZwkbdJBQ98biJPybhLaLuH2w5IoFdyTNinWxYAgNRkZAOP9ww8Yw/wDL8XJbu2l0nMFyvjBGqOqZU1IBKkLzpqkW7eunYbxq8jXPWDpClbc9WBnssOrDPvcv3vKW1NZrWeNdUt/dOtZprL7juyd9buOlanPFwG+lv+9bHqyIMCpbCQdUnKBf9ySgn3YUFzMTQOkIS9itFWGbZZ1gj7W0n6Nb2lGzyFI8BzRanRxrsXB8gUV08EgoZ/mCNM2HCpj+fk53a/1sV3iVOLEf/jJqi3vbXDqf0TLB3Xnlr0vYOotP22MpXKK3BK1AC2pHjeGA6sQxU6hZfdiWhofrMI2kmCjqTwSRz2v1mi1u1IL04z32xxf3HR6Y6X1g6ubOCRYW8My/wAzpCb2nY8LMNz73twJYv/S88xqh513nwmUbF1axvLRoOH3MXRd1A5hvI5cZV0OcnwvDqNkbxc4QPOrlSJjCz2oFY+yIA62VTSV1BRoATlBHVIAtiK7p3Fux8LZVky4Fd+e33/RnbcBeWmYHV/8MTNZULuhbUHCftLxha/9ECCYw1SPtiPSJBEyjumOUG9v4y2H4tUkv3a3RGzTSHXqV2qLg66EFj0lKajQgaRJFhuj7j2f8MSiYZlP4norPRxZmOK7EVMF09j5Wkx4sx3cHq/SMKB4nzs/MUNAE0M2lpEnhggI0T9Fpcs8ManwGM94ug03wFC7BqELBoZHPWGkgNVC4qWgupdxTtumORJvHLDQpXIRRpYIXoaa406DKrwJqoKwv+ybUnkESJagshbCg6/fRMKpIqljeJaslmVMTZLhIZWI4u8XGbgrNuzBZs2TBxJbZsyM333j9poFHpq7r81WtXDtl+/K6uln+ifulD4vcbbFYoIOePu1xQKNZeOKuXS96PF4f2mH/8dGBa91un29iSaIjsnzTBb9gdrRMn94WE7TcjRvWl9EmmtFlfeEJdrc8K1PAHDAT9iNlCx9KL8B/XHJ4G3aLgkJ623JYBf8nfTaMprcPf7EL3kifM/wxvIPwLRKcVnY38VMsRFLcDLR+oKjaGJmfGGXLyrOY3Lll6EcSgNiCl4pkYR4i9jUcmIg907EXaDF2AcCB1Tz5MpQPo9YGPvDY7R4bOOKx2Tz24ePlzU0LmpuZWYmq6c0Lmvc3V5Q3g2nhBHx0fXJ4VXLDFF6n56eueHvFVF6v48FBfL65vKKZKbLj+8j/3mgul+ZUNDdXgEfLm8X02nDiz3jvz/JvIgxvBTfGX9q27aX4RXqe0+0rL9+n43h9+sbMVRVNTWgexfLOd4Sjwkj5kGRjASWgBkwBXxL8ET+mQKq1c0EeVQoE8bjDc3j8bqWbQRAJv610sA4rHkAIqxjQSSxDkpkuGFNUEXiQR6N+HC2t0WHObvGHUTfGRO4c5gzCqyqeBA/Za20cCfYkUyyNx34aTwlA5gRBs0RQnhHQ9IkDLwxY24FFWSSYkiHRhrPg92AEnCy9kovd0BpDEwwar9DFJO4d34zYPmOEab4Vyeq4PFabvZbn0LIR14iRZ6pQHZryORKkZWkDdXi55zegpQZ6pA3foDYG3BAXBhAgE5pA/aBBMiQ3BL4/bgIiVEdJAdHd3DRv4eyy8yTWWBE9VhCfJBosVOu4PDtGCPQLr+S14YfQ5LaY8h4VULmx0s5uFt6kVTOsyC5ljBqHipZuYxiWpnmeY8wMgBBAen6c4Wka8kANNNP8Du9CrzZUbARatVXQ64HBV2BjGIs2ZGziVJytIFCo0QpIpjAX2EzrBaAuK6CBr9BVBIHazGs4RsubAbA4zBYAbGpVCOhZjcGmcdmq47Dc5WHVWpZW6yxd6kpnQQxNCqaCcnPQ53XZ9BBynJbX04WzYjZruY0G7iK9YJ+lgoBTWT0M5BiWKQmzpYzlAbWJLnaryg3hEKPnAG3RhM+7uNKu1UH0SM5K2yE0Q5uxBHTMTN9Fazk1pDU0raXBPVBt5lg1y0HaUC6otU9pdLSBh9DAqOpZPW1Uq1kaAg1kGJVBBUwGGLfYIO+wB5xBVXBFoXltULBrfO7KBWK3pXJKSaSw6N6EmCipcLAaHwBo+NYYFpjdDmvUE/Gp9QLUsQzw0bTPcqHfsXqivaKCFiya8yd0VmkZNPAJbl4VsAUt5xh0DKzrCU2M9pc0TGKRjLAqvtiIRA2txuWK+QSXoDZAW1AwWURN/RmlTS1d0QnakMfrpQ3AYHSaXMwaIAIOVQUYaa2ek+YAlZllVRoITBpahV83lG4VHMYCl6lI4+Mr2AnnWCxtd28thUzVjnCouVjQgdY57hKbdaJPRbsBqK0DdHuBaOSZBOsutapp1W6jmmb4hnYAGoqNlcWQ1qpBkWhzg/ISxmjQ2YHByarsRi2AZqBTm9UGDpWE5ooZkUHSJ8MY7QDoTKJRzaghyzIczQNDs1OnbS1W03xB24TOIu6BBmGtymEtbissFAE7cY3Ow9gvVRvDpbSxqSbs6FSZVJBV83Um49SgigsXdNiLgLjVY1232CkEPFq63OyEUM0Co+VnKp5maA3HA2iKM0AY0ppVAHAAMC6a/QxyKmgEej3H6FmORs0GmGMv6wrsNpvZohcYcZrLxAvqIhvqxuglFXoKAGjWo26tM2vtC7WmCYEStY7RCD5fl9fC0npjOefQ2bTGToNZzRWoOI+B5irrJobMP66b5lM7TLYizHy9NtZpuaZu4Bdn7KywgiJX+aHOFds3rWt6c2HNlFIIfQHU6CpRV8QGDPPik3dNnMJ6a/wFqFoFWu20KbriiNulNWZiybEcZqA8SIYOU7VUK7UAe+MEgrQfG8sxHxcdDDFePEPbZepcNJKgYcLDBnk8wgEfH2Px3I52GDEYwleRsaQV1LoZe2yE5335SghNsRt2X+Y3PvfpvharR/qVdBAs6qm9fv/OYIARzjrvgv0pDwjT77/1y4VlG28Y/jua0OGs57/tnnXRlkk7pjQbP6IPALWlY/quSQUiVNMlMyZ3Nkcr3Jodo9ZgJfhKzjpj4dUztAfh9TWty3jDBR8uXnzb8k6DHrC/eee+if+46cvm4i8/nv4X+mwArrtXfOht56RYs1XyffIE0BUkGroKo+WcHXUvGq0MWPjyeNiFSvu1Usvx2iNMVwPMMxypddOyzxJm7YU4jrQYEB52HG9KZ+wPrVAmqeIIK6uM1IYlohgmLxQwThtzY6hx0YyaPndhuWC8tqKztKTSWd0w8EhvZ3JjR3DaguYDZ9g8PRMjs2vKa4tqI/96sOuSje1g/YeH9vbN6LpGOv7CRlOPsgNYvAPeq50bq3RoHTxvMjnNMxxenyNRFV8cLm7b2NWypDlgKLEZLKWhiKeqytNctfSiwORt1x76sMe08QXAXtM1o2+vvCMdxztEX1WJ1g2vkBiQNqqTRCpl7AhxguVdSyh9g3nWwVic02BXDOIYCzD5WxZqlI45Af1JgC20puvtxRzw293eL21u2qFniq3S77AWF5wh+D42zmhlOM7mqvVKf9erVdJyW5cu3j2HPm9FwnYn0zqDmfkzu89nOf4kekCv01hk3NtiRdeWFwVcX3RJu6Rfmm3WSptFo5ZcBbza1s3uja/o7x/+1AwawEUj9XCKD3lgjIfjafBAsT2XyMtgSLF0ZvcGg85jxJTBot8UQ+ykwxQh8YbEAkrsoLQhlymY5Q1kKXaIcCXK1psQ7beKNuL/M4LIpC4uRv20wmxGYqaRHJ+JlWGp+tJI0Z+rvlEHnan28GC4PeUMqr+p+nNRpLTeBKius0DyrC5AmaTei/7roov+CwyV1leA+fukNUbBGZS+Cre3h4Ep6BSM4LZ90sMV9aVFDpBcv15KOuhefMFFclkZXNYA8WBVBF3/SbZym2WxzKj6nvpE+9J28ofSAz0w2TMgDZHS0AlJ5pTrHR4gJXlTmoC39LUSwcMDgz0DA+C1XDkyOi8v9ltvxWqBDAMcRCKVzV6Sr9xhwXKTuai6dEGLo6S5qcTRsqAsXGQ2MYtGDTCfgvds03qLnUhaKS0t9AFnce8029XjjBGVaG3xNnsC9aMurBsl5GZoQKhtBQE0rOD4sFCAxCazxJ02EMSuj1jGjAeIby0bJ8TsBO+GJQ6sdhubWnLbO5++c9sSeQM2Mibpfb3RIL3/lMajeUp632DUS++bGFb91FNqljGBEnQSlDyl9qmfAiXoJChRTkJt7jZoEzWyvdLrJo2GW/6tXv/tck6jMYHaXtZo1n37rd6EzoJa+axOJ5+VXkdnTfpvv9Up674fs3soAfVQKoDHNTyscWQEjNSWBDhGGeqEWAkRkzEUBna4JVI480Ws/hnp10/1/erE2oc/33stmjCDy6WLh27HdKxbXgLCLZVmwbtgyYFjN5x7Tlmxgf8rqk3smdR9zdKj7+79/OG1O3/+yj93vA4Kb78F2F/dxcGysuKZb2y54diBiFBsKJVxwLiUYguuUDz/iKLTO8b/fUxMSCIPdQKuzf+C0Zlj5AyHOaN+IEPlUcMEEYNYL8EPcngVBO/Cc2KQ62VTVDv2oqIIFwJvt1lIN0DjIvosfGFYnaEpbAMKQUITMIfw91FM0HQUMB3gxQH4XG/QOdTxpigKMeEXrCXRvnJCMrKmq8lgfNZS6BBF2vzrRhkW47AYrBMP092HxbqgeHjIKU1OJ38END+CZ9QFH95+VKwTRfEl1lTmcWIgNVcopDe8YTUJUcufNw/iigXlC+XbSL+D1MU/+hH6wE+coAC/i5lCXUJ87Th5HWePFEMkDUC00GO5IJodaTTu2y2EMAIrffARtMgiKDNIasGzJP5107XxVoagLpDlFu4raE1jIcgpWEMHsC4PrUuQPALtAbSG4XfZDzvKZurMxeYElhmuqkWLElV58ATlSFgs7p6GiQ5a4xCNgGcYwb9lysFNyxwFGv+GvquaOZoxlgNBZ2NZk8pSZzQVxSpKC/WQE9QaFhp4rqBZL5it0f+aE7W4kHyPZHrObFAJvvLWQHM1g6RyyFk0wBOq5ehvEx97oquLy0qtLagQF53BGoPuAoa16HTWBZOqVYB1+CdVGAs4VqSZsokdDoem9OpBwF1lsrGciORNhtZaa9cXFjUvqilkgaqksa+rtF2v86mhTdQ6IdCx5mJvY93ioLbVV12shoyzYklr3/kaI00D9A+yRrXMrfsQ9w07ndKQUa+amk+to/agLzK7JsYzMkmiBag9g4+JmjUQBiVoLYc/xnisJIDWvWhkxHGpAtrFC0I3dvjCBm306ZLFJXQDBWAzhtaX8qIyQI6RQyG8uJWX6PAebDadabUJnbO3qtR6QxFvdhvcT1f9aeP62dXVR/s3rkCrxEHpxIE/Sr83qAcBOPBHEADBadf+VEpLH0v/emfvFckHweJpE6sYzmDkuCt+E66qgqxBo2tY2rl1XoGoqrCjglkWtTnKGdbpaAbzF0ZC6tqYU1VY0tr6yMLCCbriwp3/GPZNNhqcXt8kj+s2vYtltfpiA6tdvra3xPf8imVLXUVPN/feMNlg//yAvLm685qL+lo7tj+7YQtgkg9eMi1xnUGHugFsamnbojdoUY9qXAdXLN9Zj56OytDWq0dPd5Sx+lm96S0up1DrmvNU56SowBXXV3PO6fnyxWZKTYmYX53wwaK1Nma9t0AekxiXABOPBkuzjRGYsx9+6cWH9//c5/+5dFv61afvByVM9OlX00+Ckvt9y5cv/Pbaa79lWyTXsHTmqneB40dg0m/S5dIn764Ch4bBX9y/kX6kYCNT7A4kq63Huhcai6scxROEDDQeGyA2HwD0ecVwmsVpthjEomEWrfwZA1rmoCEK60YM+FPmcJLd4Vm0vG/V8lnNJvMm6dCbotMpHgYVa0umLl+0csFc7+aXL93cVhB18rYpnSvmLEhUcZP3rFzQEvHaWEanck2przMEI11nN5ewnEVQ8WiNZKiOLVpxYScMtcycP6+7yWy213KO6T3bt14NftiztcVDG9wFGs1H0nfAGSwA7xwxCCp95bTdc6st/pndlRcNAhrS5qL6aVsmF5rFsqa2thqjaUcXZ5k0bWDTVZ0FXT1nLJo7OWY0skucvL0t2lgM7TP3zGlxC+j7oa+/jLc3hYOwBokuViS//I2liBe2hcQmESkLyP7uwOo147+ANcNgxPxty+wGaTj95ewtzG+Ol2f+tsymZ87eAlzt87dL/wT67fPbweQT1AkwFf1c2dExb/v2PFmzAElLNUpszbi0n7aTBEYxSYX4M0NKKRN/PniqICl49Tj8nw+fKlhqhFyslHUke2k+ealw0rJijk9cwBx1KWb+HDxlYYeUIoI2zCQqM5hKJ05Z2jEyvKwzzRUTnC5qiQo6LWY5ZMtswfGnpwjuSmG/JJ0ScqULDv/ie8RS8ejbL87FsAsnQdhXQtbLT4Wzr0SmA88p4fYV//BlSC63UjEcRUlEMiyRxe14dqUiWDC1k9GIlkG34oSME1saRK/ViyOlRPrE2kbpzR/dLn1z29GHzDsOAP753e9sg67GE5TeVGr+Uip1BOheqDIsiLUv7+sMgPuldSbwy1LzR2DZq0/+4Tagvv1pUN56UeyPFz8vfbf3A+fmJO8HH3gdtNbkjLQtb590Ji/9MZn0Sw3j8ODEQkEavT4em61ltSZWjtrluCZsVxCFMZ59Os3D/zO7Mjhfy1zprwjpPe69TetcG1x13dqGWmOzsbP3jj+9f2zE+9z7W04l/VPsbXj/wdivXtDxyxy9jo66J+O/jz8JgsAF9oywoIEsbwReA1sgIy/Fss45bSCan86EMCHRpQjJfqw1kzDHKOUkk3xBOvKTQYPwLs1p1Hr7XzNbwYAOgu1Gp13armyOAIYchamfSEdeEAxwVTvgNKakXTVlWTZ1DK8sn97KWvDe+csyCalADyw/xl6yubhpv4LWbFVCdOTKZAejrFXse8ZSSzILpDRIFsC9cvxG72kjq8fkJ3c6VaS14uOgwriXIeLh0CNb36LyQjgMZBpg7J+OeouXSDCKe0ocTW52HCXr5XgfElCBAVQAOlJL+0UMaQvcTIT1BuGGc+5Mok+ab5wxo5EX9Ynknecwi8svNC3eUVW1Y7HpwnIuGp3d2Xl8Pv3Ne182DLgKpSHn4qreZUV33FG0rDe8yAk8jKG6tqsEvDys3goGE4lqr6MAmh1mWODwVicSvI02RipLKiNG2sYPlwyUuCfcMEH6TbB8gsOBPSrBm2AIvIm9Kxm9t8Dak1C+D4zDMYf49uKPFa8SZSsSWljmkhlCgzZA55IhxQUUrTJzSQUUDjWEGI+BAM2yX7bOXfZIPT+vqXqGMS79Oq6a11zdbYzfUmRtmR2vvH3d7U5b85x45R1R+UQMxGKq+Thz9G6rrXl+c+Ud6+51DA+D2Drp1/Db2S1nepvutzqbFsSq7uu/12HHiXui6p4WdG0UNMRUs/Fdoocc9ub5sarBdYM4S7zyrjg3q6mqyxiTXqxXScfWgab1o/U1ZYSLbZSPCDArxO8NQKF+Dyk9NtOBFawJrraVjQdaQb4TCT1U7PW9FF3Z3r4y/JNqXbmmvpROlNbHy4ZTpfUtgeqnQ3ShoVB0WC1Wh4hSNND620b6mhwfAk/5LbbdJZMmec73qIIqqRuTD6wpa6wvDcwq8Gx2QlFtRisOVoM2InzUPovK2BKJ3z6LevMUajZ1JrWJokQ0gwUhQZOkifEnaJT1Gnj1JGYP+YL+GCa1t8vhkUjaZ0WbncyB6N1CXoxF6ygPg6ZqiAFqgmi6iVGekhjaD2LODLRv29MBNr74BatijSoX0y19Gi4XDaL42vQ9OjNHG3U95z0gfaIc4z2adWDuL64H2nWa+DSG0XEC6s1tEvc5YHZfOLCO3rnizcf+1jR8N9gAur+6+uqvpKekG6SncArMB/8Pbe8BGFWV/QG/e99786b3PpOZTJ/0ZCYzk94JEJIQQg8t9A6hFxGGZseCUlSUqIiKHSuKbsSyrgV1cQv+LbiL7urq2guQuXz33jcJAdm/7vf/PsK8d+sr991yzj3n/E4HqPzkiis+QS+i/ehFEoLJu3b2GqaA5UBqCFU4O1RnGbaM5aEnA8iBDCj1BjWQoqeRlK3pS+1+dl7niITSanBoXEo/P/9Yao2Ez83k2h968R20dxbcf9/8bFh83o2b6cOceuqKT0DlBc/Q7zuJtL+e6GkBHR/0kzHiT5gknMnIWXTAEEgEQzHOwlWhr0+ia/78BzDp+HH0GYh9zj4YSH1346o7gOkN4tIzadyX2n7NT/vsDwRPXLf7UxffhqrR2qUjGzMe8Kzr08+mfpqUTJApJFb7Jl+6C/tiwKOL6gb8zuGu8X3BKNvD9iSznKflzqwkwGtSsu9/uTPrFM4ol+DAzzggYVBSRM84y6Twjc/9RChP4gEu2edbOSkT7b4JvWAw046SMPDmSCLtnypALFZNRsGQ1o/EuWSyjScCfX6wJP/Wcw+gP6N96M8PcHpYZS42c23mM92ckkstzymRVJeVQblM06ORyWFZWa1iLHrMbOY6cTbXCQ+jlwatHIT/g4onBAFq86UI84ZHvbfO9A8dFETD1Qr8Tw0eDQ4aGnzrkjnSfCnoBAB14/dfeDbJ3yjqtAADEVIYggwkMg3MZuktVWyCBIsIGBw7QVWVk1WjCqOzj0wqi+Q0VG97ITtwQ8fqgnispMxZ42uVb4f1qUqFAr44CLwMwldrNIu/xE9W+dmNb45Vq0PTyy7T/Zz2IcN/TNdQBnjIKBP3vPDI8kczLQJ+CkrkYTqLTXhYBv5J+SR6+L3b0Mmja9YcBc7bQO5f3rnkqY3/k0z+z8ax2yc3eiSoGf67vvI4ur+HFABlwHl0zR/+sGrTR+jnjzYVDpnYHhD1ysR5gtiMeplWKpEwE6XLIFVAJ3tsEX8a4Jh4nxcd+iQIKEwwZLAQj9gUERTTU6xESBtJWPCBi0b8sWLMDfoHzBJ4djBzg7XaKvTvKq1WopcUrlldJNGjY8VNsVgT+F2sqRiHzjTO8G96ovpVkhiI2z8wSAY9vtFXHGkMuCXA+vIrwCq4/GDWRcYjWKLVVFVptBJJUZHkXXwx3Jc6AuSaxe1Fjf4OCXDkBYpjTbFIEW9CrwodgcYiX5nGkXHta69dm2nTlD57wQVx6HwMKQ31fkTmU9pO3nQ7kWYK9DWTme8PJWjjBEMJC/l2/6GpREv10C/1ltj7VarYFzGVitfy2UezeS1C+VX5eTV5oF08/6UiJ9u95Jb4/SDPTWQvhabndFzFLYtduTkVmXb+6/sOfC2xuUH0POyGXfii+JoSSXa2ZKc7P5/WTJ8HZ1e4W7nvQpm5+Oo52bwefS9pyazIdkVUNsvaBx9ca7OqisDJi/MlLjz7EPTiRBq4q18thb6gqHKSAfhYWlGlEgghE+lA56lJTutY3r3cGXTsWtY+YpnDaHCAK3eSU0fF8juXgREX8i+HHFXDuxYPR58YHQ7j6rXtS5e0AbyYOg3xj9auNzqchkvszkvali4FD17I1ZA56i4hyU+iz00xhcSHFs3T+52904cWeE9fjiUhZnHBilEVvY8ePAOG4EDq4Ud6XwTXgSFnDj7au/lFnMKWrCTqMak9D/985iCQo9M55eU5cMH9337/wBVld6AfD5459QhQVpahb7PLy7MH8isEK4MJELfcojvRi9DHfE+qBmVO2gx7wIlJm2sGft9ucAL2bJ6EMlM1m7mM8xX2pPhnlzLcp7hHy/B9dNRSPEAxZ8jy4LEBnw7glYI1RWMGguuA/wI6nDYwPOSN1BdgyCXg5jfffLMdmlL/AkPQ0yThFmjEOYPRITD4Eu7T3ix4COctQdfhMoPhIeB64w30t972u9r3iYn9wQHjS0ZxRQuJLx6Gst3EXmJASJsGvRZ0CWIXAWncJ0Z+wYibm2M5Dmd2DP2QDsD1j1xqNFgSY9cdi9Zdes+jlzbVP3MsUXkpazlPibIh2aEBJh0YkZxAzqkioHyebS2bIkltyTpqgHNx1N/7NA6Cn89vXzmTdVYmvInn003MYeY15ijzPvN35h/MZ8yXDNFcirtYzDpY1FDI531Ek9QluIEZR4Oi8UVxogri6YGwqFT3hhOJbbIk4nmfctSWPgobStIIF0RYEiITCLUvsyTUrCWRL4TyYTZxVYLJUhesBiYLJu6k1aLOElFYxVwaSy6In4hSdgmLAEQ451AVjOKhSTINUZwaM2lANeReGXbl9Nm1OZ4JFYMK1+zx51Y4QvnTh8olnEySK7h5PSsBAAhSHevbkhnyQBaWJ/BI9O+qtM3sckpMyOXWWnVq8KlUYTI4eM4i0diFu2Q6m07zJAB3mwuuL0gUyBty+Paq3ES20SS3KiNsOM8HKnmdoJbIBRknaOz6AvX6CdpwQ3XGYKkyM9OsNP+0zpmbZfOqfYocqQCzhvc+ri7J1bE5P4UOxWWODIsNrrmksgadKlw4FNzB+kqjJZxgGl7rRIM6JfI8peGYW57FrgGQ/E1hCxpXTR1SMi9R6UpUawN7Hjy8YyrkeBkfEDKULlvA7LFXZzXjPiHXupvMqtJKE7THJq2/2cjZu8xajYWdpzar5BwPgSpTFzDrNGY2rLU/1V3k97JGq1ZvyB1qz9SyapXfXeO0hcNQofkzb5JqJJiAhywHclwee75jpEyW5wR4BZoyxeQPWfJ0pYZmjSw25u5XcliZXGaIC4reUfYcdzy/hM9TsH7lo4XobQ0QNAqpAHKgSoDLjTqgTK0bqZQUAUCvLPK4ejzG/s1YME02iWD/88H0bgjRnyUb+dRSkao1i6OMqtQJuJNQ3fI4KCbIL0T9jkhkiP4XpUhE3Weq82VMr/WxYtzvaJdNpPkj7jre4FratLGGlyo0ApB650+LZI3NEZS5BqMlVmDNKLKrZToLq5GoZVq1QeHwKaRyXm4BHXJLnsuT3OR3DB0+riuxbB+EzRn1jaU7V67NtLfWDjb6CjKdGbF1b6N/obfRp39Khsrbh7UXGNRNvkqXP1e6sTT3gRyTf3T9yEQoYlCbvUWYwzDKM50sy3kcgnJLgVojV+ZajVLBCFWcnJOwUKPW6CScEhSY8/KcI0eBcFlZGIBbZ3YVG3W1LTUAVA6tAqw3P2v10X3oH79bsOz3wNk9/p51S4bVZMilAWPY6hw/4tZgRqtDZR00ZOX6+8+zo3DhVbKDWY3nAw1Ug1CfLWwiiLlqiyAxYnKimmUtmFDwSoxuViiA+SCRL2Lw4PFvFg0wQ2Q7PWEhBFgBm3ATiYoLsEaJYKZWt0RbVMOGqmEVUarBFbn87l2u2gdHa7uGjl49fpA5v1a5SxEIBOYEXLvueF65WxmY0xTI2N29645droZcR2PH6tHNy5Sj7mdnrx7dtFQ95tkGxS5axrW7G/9l1BSYmmfCWc32/HolzmiaQzPu2J1R//QYxbLW0avBW927XTX5psaONaOHdGnHPFSr3K0IzAkGSEGoJ3dsmkvuiP9c9YfGavCDrZnWZCw4s2P0msmDnbkNtMic9A1dNQ+OVizjLC3LFaOfqk8/bzqrPs8+bNYaUTdJxJsYxIxjJjBTmNnMPOZK5i6ynxMsoK7dQqIyZyito5gIkulQYhQVOfEfNdglypd4LBC5ENXxFHU2WSqh9JFSCSoNS0R4SwgEdDywsCE87VoAr8OfkNyCoqmI+yK0LjF7xoML6Kg4O1Qc0lENl4SOj+TiTJMOXgssRmNujtDA1dePsHJuVtJs2qjWNUDpLGnIBSHg7RarXs4BSUBRVjADyusUMhvHQdbmZG3FNcpLeU71Fisogy6X3aLmAOsxFvoNOvh89dVnfoZPppq447OemPHXWXnHUD6sRKdvj4c3bS/zjBr+TbVULuWcHm7og4OnXD9a4w7IwY7e0+pUvqDiiUK0Zl4OzIeY0S3njOA1VpDKjBl8DM5unaKBHOTGWZ90uK6UAS9USInunZwXBE4n0UEJq9X6oI9j5QAoTTBSykdGOCXFEBSBExqVRaNkLRo7HoacWgm3/z07dfM/Oelnqbgb3uBO/dO9qJYtfxqsO61TddeNtClb8wUZnjr0MFCU4Rd0mJFOnvnDj5LvVABycRmQkAU1+cqi+SY0mdrq9uEWEHu4wcxY3BNWMZczu5h7mKeYnv6dnn5nqvz5cN+EfiC+kEwX2jLpfiX+/3d5gwjK5dGBTLKfmSQH/kRZ4855vd11k0vCsDvc6dztDKcyKUjQfzwA5v+W39kdLkklueTkunPeiO/yrhyUYubtnFwnYcIlYfwYneEzyf5qQH2xIFL/XwuAawFTEu5GDPF+TXToJUxadlPNDMdzwGJmA/W49zDzO+Yt5iNMiZ0FGuAGBaD6Ijt+/U4FxXbX/Zdx9r/8nr+lf1wIgvN/vd7/l8/HU4WVM6KmSs85yP7//ZD8rQXPHSAzwI/Pb64FmP/+ThImaD9F97kk+IgGwLV++2vBg78CH3Tx4Bl1P+gI/C+q9ar/X92N7k/WnNVyPXwn5f4Y2YWKdmCgvpC/T79uH3o/rV2H3neWtDlPgq6TzrYS1C0q2L2P3u99larWJVGSqtaVAD/Od548iUt/ImrW9e2liDi7GVRiNILIvkSeh3iRJwum6GMFpJdPPsLpiTUFnvl8XpxBnK0EBpQmtqiBSNoklXqiZ5XBcZXN6yrwseWSCnRgVEvz5kZ6AFetBPqnvdV1OQ1fVdelmp7quudtMKRyXLDikhZyXAdmtIxq3NxMDly4Yn7rsj1DyfHW1LG2lYv3NLWtWnxbwYvos2X5lRmKjvHbxxx7aOWx1vkVTbcuw8ehe5bNWdXWtGfxyram2xYT26uzDCR+s00iVqHBnDYSFx8ePzvsWTolD/rtPXY/zJuydPTOAztHs1/f8HKg93WqCRYLvHxD8rvbbvvuHBZHn82RGzcm0PGhPKAiH1BEIE1jbNANVEyxJGEylayBz6QaU438ab87VeOsc6Zq3P78IOwx55phTzB/EpgE1322BCEEU4yvQoeSWi1I6ip8LBOuUwNGKj3LqOtEc218f6no/+OcJTLO4gP0OXiQPof64uS5eLLbi+lVMZB+wAA94KekCy8+QOp8pwbchBagBfy7AyK5YvgQGowG86eCHlRjq7GhGh5CPh30BHN84CD+9VjiFtDjywEH/dmdPaBsX9eDDz6Y2tYXWn03kO/reu6551KVqNNfpT2hVp+A+B85a6v8oDtYo30GXI+PPXJ5j7YmiLqe0daI8hQkZXiI31uG2z3I5DO1ZKfW5GEJImiQxdRdFHq8mPFhxB4peIzmgCcSK/Z5Yh7Cp/s8AeKhC+fQDsv6PEIJAuBsb0eXBOzW769eqftgBjr05xTgj1715kyYWrTsTByE3/w9+iOwtU54HvWif8H2sVesqH5g6fKikUuTjanbuAfXoT/O7Xgx9VRNAr0JpH95Gxiu+PBKnWvxmsg9jz8/tOX6vzjr1094oj1z/5phl4wqs6e/Yd9epguP/lz8JoOpf5wLVkID3Xki+wpkk4H1xTCVakyfeFzGE4+dQ8UhkD5sxOLDQw83ykAp2DG0Daxf0X3d/FDTqJZH7lo19dBz66C8YQi4FezYmNx3+2VvVl2lGFq0RIG4xnmgGr1wvgQM3dD75bIlt2cXd5UOz9ahI093TEaPHl8yJ7N5kNy45dEHNl2+73feMFi0tqQOyFv6+CyhDx8+ROzV+9H+6f6rpU/3LESocjAA2SdhZHyAziEFeFxR1RkCAMtI8q977brrXktt2z7H4ZjTUut27242tRszVw6ew7792PoNjz22Yf1jO9EPh9Ew5ZEta56xfQq2Dp+sMhO7fsWzh4GCc5P61515/u3tkmz3ruaWGrfUI60Yyn60/jFc/+DBDc+hH9ELGw/uXj4RPHhbIQS7ngVS9ANzHt8oxe9Tz7Sk/USQrVNG5ASp6XIcP3T83CZYZR/TEYikv5PAkrcP9O0ti21CGMP3lnYvWdKNtMvbSybbivMrVtus0cp2s7Gd7RW/xAPGG6fMuUUOxu88dmznTX+EH8sMw6rQX8QP9NO1r27bNmPmNjare8nS4W1L0Kv7l5UVGo34GhWrrR4eLhQ/5s2DJq6+ZnbvsR07j71zE3oeBFaBd3E66p6xbdur124jKN1nx0i+4s8yKtwv8zCPPIyiDbFCgApeMfNkdmBumdUAlmi3xhMhQKyNAObOWANpASBhAyED0UjkicRJUPNCEKck2ECCKK3xcUzRm9kGDUQT8dhXCBqZF7bmPn5j9dRCN8s9r4OC1Df8GknysLLIoB98k/TTY8KBv5WmQgXvoRcNHxvbwtYiX6G1EO56V68wq8L+Sk+jwvsPULru2vfRpF3e9kEVOh3Y4Y4rFSGwGF1vzmBLA46SJv9EQQnL0NaJQ26YO8pkAjPtFTp99aVjUp+jmzN8LCfw+8BiMO9BrdnMHqxG1zyrBDPcTg4azbm2OHoZ7Qi0+oxes1muZ4eABS9+ORJdbRwz/pZJ9SoVYB0aTaXYR2qkYp8ne7r153yJGDy4tagj+v6UgUajnj7j0T4HHLj9SPewEPUFcGLylsmTt2xifx4PrbIUI7NCnqVJSK/u7Oru6mXwoVOt3zzJOddy5zSWmXanZa5z0mawnhSaDE6AmVKDQZqyiVEGYXI9SdxUJsUjpuWSuPRdkzdsmIwmbRZtaqVkuo0y5ZiHbxnAp/0vDyziE3vSnqQshj6bWXDu3dMpQuakzRd99KSIJpckL3DqtPi4Mwa8N+ehaTC5eRJ5iRry+DXi8dxLiMCt5FVQJm0msElsgN5naRTTA5mYPzlB34/xk4Hq6sPIIxtAxO1YgrxZ/1H0vUsUCMUjfyJoRxEg99tQj80vByhiDxrA9k/o8WVyTBI49aQhaH8ZbMfHT8D2juKgblvQ5vPZgtt0QZx7Y/8haTAgXCGIFtLDeVgfOUwD1YNJgw2Js3zaBDuewKmeAamZNNWAU/10L7G/NEfd2oGBammzXS+grbdkO8x85pbFf7vfoDY4O31foj/cvLPQZxNcazcCyztWtc23ILweHXzkjW6LO8utyNj60F6QN9tkyMh580LY9sZMwzKvLMeYIXXMVji+CJu2ZauiNp/Us07lA7oCy9BhBULA5c6WBhoqlVkTLhAEAdHvK/4mBkIJE39mAitg/jqEQwlDwsMx6B0rsCA+91oXOgYKrOgzcAaHQR73TuoZN5rqQl+5QAEc7AJ7XUDnwmNPh3/XyBhuOaPGKyzx/l7BDGFGMdOY6cwSzI1uw/zobcz9mB89RrxUkV7qJTajZMbGUdyMpG0F1mjpA92PkZ1BbwGx7E1YiBJOLJQoxrM9axGMPpoexQT7uQx3WmkHR3CODBgEI/UoRNwJmxMXxsSIaBNexJJcsgQaiATT0h/D5KrZIBTRGDTE4mk7fAp7TIk6ksBQ+QSrxRSkSi5Tq9VAJTODbIVSJdVKVUCukMjUCpnszBdGI1RDnQ6qx9ntUCqzWGRSYD9ssynk0GSCcsVkiwUqVSaTStmJ42qJzGiUSdRgI/rIZJILWohZJa0gn2wwKKQ4hONSxTScZjTgiEoqU4IrX9FoNJgjUKs1Rs10tVpr1gKlEmjNmj+p9XY9kEiUUC5TSAU15GbtX9H7b5XeObrzReDSxUpX7N/3DVTI1Wp56odv5KriY7BJK+V5qVaSeg78C8gFhUxQgQXJ9TLZ+qSs8a3XZfLX3pLhgfmvH75UKL78Qcn3fq9Sfd+rcn/+o1Ym/Pi5RIbMcCHa8qOg0P8I1ukVw1Hu91KF4XvwrkGRiSTfmkzfgtMylSqlg58j+JVco1Z8BZBCrXYh4xcKrVbxBfhCqdUi6T9Uer1q6Qq4jtXIBF6qT9204m6oV7GbLXIvOtVj3n/OTx/p0ypMMxDkTobJ9CfwVEN25yuB+X+PcRTUWYwWx6EBvAf2rDqKbked6Pajq8CeX4kfAt1g2tG++FGWGTPqgKiLcWBU74EBEZA9IMJl41NSjOHTgL1cA2NnfMxkPHZWMEnmCjwn/XKvziLoPMT1MFW0JuJbQCVlZANXIpjE/XIBUn93xJodENsQE9l/JfYG5TBCje/xa+MDpizUAEgseJJLUL2/YCwYMgosKRsil5HwQR8ZlMX8YWe4H3k4Ge50bgGr5Ur0eyWYTozNUgxEnmh52Y0urRoCSW3hZdUf3H/zeI3KCng5J5s8Wi2DxYkGv1WlUrhNwKLUy4gtvDKBHMWjo0PBRo0KPw+Fp1CCdZfvgGa+OeooccFV1uXNhWqO20L31/rwi8POBnRFhhKUKk/rOYZYtJ1m4Ai7SygyY+4KgGDYYy1HpwUl4OT28Ow8mQbC0V1XrG+/NRLWmAokkOVdlwzahxzWy8Lj2LXZHUKADXMcBaky4xZJzY07MFlcv3DM4hKF1QnAwH4mfqMRv+3bGEwECBi3fixKNtZxmELhsRIN8BG6nPVRws6HW5uNxn61lec27tubFFjIsYBnk3v3NaJ3O6Zj7hDHJfD6pddDHnAcZhand/yGFmOT81PzwSdGu1ZqZb0y5IA75s9HTUa7ycRnyqAn9ZHMLTGZ7Ebw5PxfvP/I3/b+RP3fR0AwiQQYuoGPxFmxEQT65riTFgAaN7C/+v4gD9iGzeblPP7KHOQFdn4z8DX0vFiPPmuazSlZ3Kk4iWJeM/qw4bkjv6EJPp837w7BIOUknCDj7pg3D+iAff78vYKBY/F1lHtxe3yNPunTixn4/iVU//e3tgDmJEU/1pjCIEiIwKcjI5aAE/76O2eCwZOubM6uH95UXdiOrp8I+FWri90lVe7f9oL3aCzJ9hGrHYb5qT8BK1DqPe3j3ZqLvVM2E/mNM47OE0tYACeqSBl/9RW4ZC/TQzY92rq7MC36G54b9KCeHlIl2UWqEKTJvmft248hz5tgmigqecxn4mO+jPTZ9Ovv4CNg3DpALYOp5nPcEIsSp4IwTT7DJFEMJD+24n99u2QSMXDbfOkNH94gNU1PDjd7D1PfaFxywD/wa2+cTOIZ7B10l8M2cuHCkTZHNWhJJu3ITv0Z9uu5DvhWpUwz1WD7TeuDqc/LYr+jg0ScACNqQyKamllLoVZCEeJFMx+QFCNN+fXOiakbKadU7N9MGILN+7Xgcbdh40Zt3GjidTNm6HiT/jmHcexYfTwIDcXFBmgw/paZKV9qTp0grhfvoXvF92hSg617we69JolOFzNdgo5cYoppNTcZJ/VOMkB/zFh6U6kxptddpE9Hf+s4vXBPiO9rNYoeGY38+gpIvfYiemQXkGZRy9BPQCb7TcsXm+yrC/AR4vfvIe8P5B1ALrvI908wwwhm0m96sypiMQqIxjuxK6UmKx6zwFI/P4CotxOTRUzeYgLBIJYlmaFf//idUrsiqmClTz4pZXHALv2bGr+sWv23C9PRSpUGXgXNqur0+Te1CL5CEF/pu+/wFYL4SiDPgP+hYxempyT4iiy5tBwHel/AAczrhM7u4o/j9iJauZgskkDREY4ccztmO6GZEsF+D+V4EBA1pIHbfPzxmVNr/3BnQVu7s3bujGWdYx3AYR+3Zu3w+1Zee+fbjx98vkyw1ZfX6t1lkVjNH++sgi+/YrkCfXuHPa9QF1t63cdAAIveeg/tQl+90nnfl0NA+FDPD8d69m4AnDKUOXvE2I7pE575S1qOL4jzmoSRYy5KjzlSG8EEMABdgE+EZCDQt9GMeTYdH8CUic6YdsJFeBGRdf4rnIAOoideeIGN4tB36GAL0OLF6+urQWvqbu7NF9ATQJW6m416e9805Zp63/R62SgO4ASwGC0Csz/yb9zY+z7Y/vhHlz355JOTPgKz0SL01UYA/Y+D7ejmnNSHWZbUhyoV9FqyoDfLAr2YhP/Q0o9vKmX41bhfdoh9ku7W+Tw5kEo2+oE7iK69HmcCyjQTDYU+fG0XH03v3hGEwbTml88r+qGSLr7yi3s4DXtmMID8gS8WTVTuWzGlZRgIPbYfWO8Cp9+4d92Vs7XVyvqWREtLLHdEbe3QEUtq19xz7yXXTVO7g/K65uK2ptKc4bV1Q9sXV689AHvzf79232dA/o+7Fz0TD+Usu7PslsN3oC/ukljR12uvnW4cqq6tj8cashva2xuyr1u15tqpWn+usqYuWjpITNt2vu2BiLtJLGoS1JfleQYD/kzBQlDJQCJYnAhJtEwmPnpDgj4zTn2y8hY8EQtmI3ztl2r/sAdtuf9I+4H2I2e+OeJ0HumAdWCdmPBa2sUqO+NIR8cRp4S5iJawuoNUwlVJhfvRltTzNAEEPxYrS4/cL16O7tdkSk7wfyEoEOCccpOeKPIzBJ8gs4ps+YdiZk4vOXHlP1AP6kY9/7jyCGg7+gH6IO0Pdhb64IOjoO0ITD5CMq/8B6h55E9g2dfuk3mo+9NNovvXTZ+CzryT7q/RNqIPbsDz2r9xG07HPT6uT0SK8GjkqCIJNV8HxMidbGomiOlGnGoCEcKRZNKAmtrEi6bu+RzmeqLmIpfUok/rlRukf32ZB9JwTYmHHzokMqelSqsNOTUOlVqelZetVs0JtRoNIGQy3tHtCbGcebjTOTu33WBwe40FnvEjBptNFUOtXGZ2UZZapRbk4bzhRQ05hU4DYD9Ei84eQo//ayvceRysxSNFGp21aveO/YMjIa1bp41uXjrDlWEr8tglkmW6RrujcHGm+6kn8pd4PYHBOt0y9ZCMjJJbD9XkuY0enTa2btW6rtkjK3U6FZvhrYu0Nc2as2kwSqEZn970M2gX6R/a15SYzw0zbcwkZgGzhrmSuZn4qQj6iccB/B8zdQI+BrUJi0QgKtfEglGIxROheMISZwVixCUhajsW3AUTwRDR2CbdkuTiYwRfAF8GT5jpYqG4n9Hio6h3iSskSBVai3QFZoAhDCcaxpynAs/OexvdPq8sI7f2pvd1tam/jTQ7SqdNK3UZ2n28tGweuv3tklrd+zfV5q79TK3+p7v+UGlHYfHE4sKO0kP17n+q1Z956g6VjyvMXZBbOK78UB3Kri0hxYO+0nmgk9NOK3WYR/p97QZXqbnUFyQ3Kal9B3QC1eUn0UtoP3rp5OWXnwQVoANUnHzsIgNkVp3krQe8RZHSe3PHKKHOWVHseRzc8rinpMQ5o2sh+qf3gbckdUA5Jvfe0gic0JY9JrttYsud9fpv5PJv9PV3tkykSZOa72zQfy2Xf61vuLMZBuugYkz2fSXZJZ4H3krdj2Y97imucM5e2DXDWVLiCXpwxn3ZYxQQ3xqvoeTJLh/4tHDvxTTzhQE2sVpM/Q1i5jLLiGZjwEikxNEImz6bEzGJr0/l3kRQ88mBwIsQ9oNMx5QTCcUNUbp6+Aidw8dEvPWIORrzkTQCx08m4ajJhyuzVHgkCmLiF7oOhY2T5k+b5W9qafEH97eWRirGrCzPDWYtCTc055zobHUUFbV0yAODr4TwShacduHpXuaTzWWv4Sr8gNViLk7vLgnWoFcLhxRFGovgjIEisZN11TVgx+hRHdHApRkZS8dE5mhYXUPMygZm5dX7tIfra9S825or1SwabnXK0FRHAmzOt1gK0eqIbI2p/WO4ot1odResYAE8HoiXB63wPX8iHvDH4iMvwHeVMA14HjpMcae1dA9zAbOKeMPweYlfApasTCRARgb1QE6RWXiT1uOlaskxwkTE0nJ8SwT4iEZ9KErU7AMmimoV00VjXop0T2DtcU7URFxs6YxprW9xHYQj7779gV3lFeXr1q0CKn+Odvu6cChv8Jgxg/PQjkFrF9U+WV89ZMrz13S2TwNPfshxH3Jw0uDZVR2RDCkUrBJTsFPyd8n9mlL16LGVqa9bS8vahpeXmWfMmclOrGy/4XLw5mtKeU7Whscs0mDInWUxufJGlqK3baXzm+6u4LJGL3Ry1vtGXH2ooPf5vPFw6mSvZ0Lq1vGPvhQKV3SOKwdTOCh5vjnuy1r3PIdu3Mypl48dW1Y+7pf+nGXAx+LJg/UBXfQXth5ZQN51m9WYfetqIMyEfzlPId0IvsNdIXciKEEGdJi96nyfraVnGe73+BtlUKwgERxMgEQCRra9giJuIzFHIdbhFBuGYk4SzV0RWIhsMlPgY6JYgYkRtmnp8IpoVeynPOAw8XiYqE3BxoZw5WDtkm7w7z3ou9tr6k0WnveboqVTDyabm5MHj+BTsVwVzJLXTNrz15W3AxVn7F7iqx+OtiGr2QMdxvXf/e6JTRUdw3zZbUvy8cD+fo+aD+A7c6p0dXyaunSOMWxUGy65dtVf90zcg9dBfXodJCjNaSXZBIEVIVbbEjfRWCfjGJjS1BXBoPQJBFvTIqI1pV2xUCVb3NtEhyxkP53CxBBRhdhIMS1QS80qoFMfuvTqQ1u3FrVXRLxuoxIk9CzXMjbkl5l0JoUWYFKrfKhxZEIKOb7m37FlI2o0UnWNNOvBdl/DylG1Rrei3MjJISxcreI5qX5oFuA41gLfM3iMZVpzlfJqkFNRlzDFy1obp7eV8SPr1cVKwPNg6R8W5CzVGDNNbgi4WwYZA/nZnFUyVW828JADIC/MauzxQDiUAc0AQsgqnqtijVn1nAzE84Ghj+6qwvTmEYoR7sG08lCKH3uOeB8o6oYXTwY4yJH+QAdnSEj4CaIIQZYj2isWEXROSylWM2yIZOXU1eVksbZo2JGX5whHvygSU+ADxSGSEipGP7pD96GTd1l8HnthlaNdlhqCPnwRtLz8CCg9BhdfuSLx+50NpMBdwHnfHcB5Pydvj0TDoSia4szNczjzcsFXFyYc4G5Bp/a0NrGsnNPBDe+9Dtz3AeddWz5LVa/409gnFga2fQtc327b9p2IXSI5i5vGlfbRS3nXACtCJMUw70CQsyiug+SkR3KW4R1qnUKFyr/Vu1Uyg4XtPHMMrQiw0CtJavCK8IM1fJrJ0Er5Q+i4hRM8RjCJ8/VOv1OdFTawPbJzWAln+Z8wR5p53l1B313T9wQGwMvAwPumvkF/1meoZQYzCgdY1idJ+tDrH5yeBdrYKch77u5/QYdM9O4vvaDOChnZHtNpNZ/T+/KVcEPv38+bd4rpnEDoD/zlRJ42ak6r7VNtfvxVzULfTEShgunH5c93BCua7kuYtUfRyT0PoNcWCkB6pVyjFYa+u2rOc1eNGHHVc3OmPd54JXHjjGrswXDItWk+MNy4BziPpk73Ke6doAporBO9SrC5btgit0mvkkH5lDm4+tv4KoPrrnKFwkSPkHi03jhz8dqju1G/Jl9nn+7aOf0VB+Er1FBL6XBtPjjPkmwT6hUpa0qCz7of3HCB4JBncObAQuipX8gGq/C9juB7bcX0ZFr7jM6SeAYhYjoKRmhijRYXm+buBpYI4XYjqMOgz10SHmGUhyMa5yYDEe15yFxkKA7lw4uXoNeVbM99NC/3kVyr3ZtbpvUAoAqkJgVVAAS0NZGwzVpwKD/nQLbF5s6KazwEx4qXqmWainy/1Zp/KD/7vmybzZtTovHhinb4rA1X9OlHRG02fMmcB3JsNl9eGc70aisK/NakIGTZ3C5OLjetApeb5BwnN6Ft15rlEpDhtucKQrbV5eLlcsvqUjaPzXdEvCGrRM45aV6u3eWAErnpatRjUrCswgRqrsYBSzCd6QS83HJV74hVJrkAM1z2XIovZD2b5BBu49w0dgQ1PTmnnO3rDxHFe9FGOJ5FsC5QwBrh7BLWb1tg81/nsy+w+26ctr6uZty4NYtBBHxk8/P1QzNqgMSmiJ1J2vx+G3fkTBU5g6+VBWVrVly7f/XKrICf8hGkTzEDfH0Q7eF6ZjCmdkyeWOAXWsKemMHki5Eze2HehXtmuBxx7wg6UTekbqnSuG7dvd0nTkiYVOaJc4ls8lwY1pw40dtNdkoHgMgFAY5DJpnsxT/uvBzEDIyli4ny7bRPd6JNoZVkkjYkOHt4JsfraIB0zkycjmcnHnNCfJzr2frss+jHZyHaPXE9Dm5dPxHMgQTujQTRbgjBnImQIUWe3ao0Pz6GZI153KwUq+GQFSeeN1apP3m/aP8axyyTOSpuKeOlRuhzG5KgxrCRX/q4v3TcqMpvIPymctS4Sy99ZD38pmokDowbWfUNXP8IuHQgqZR6ZH3Zaq1au7ps/SO4iKBdXXrpI5eWrtYK4y5lTwykm4R+3lGHv3UV08yMY2Zg7oFh8kXHM9RXnehXy0Jw9jQU/eAcIxclmOoRNzDQTeRgMY2Y8dI5MBYX+y6dP0Np1RUqVhdxXYpFWDQjHGQstC3Ynys32lSKbL134ygb+3T+9w0GQ814gpuK/kZgWSmc6pN31BhihoYzcqVKPkEmk9vlHfL3FVZFh1wuc8gmyDL1agp60ql+SO/U4/+7JpCiclzMLpext0SM8tz9C2yFcj48aqNXAR7M/64BX7Dmjiev67sHcBHc1/E1BkMDyE1XxFd2fEWPMpryLL12d/pWev2gvvvjJ0pjEpC25Rgj+fIgwLMeeMEWEIgTE2CDJRiy8IGEREgYiEGwJcEbBHMkETIE4FTgBu6F6Db+l3tA3MIds76uvmznVzH0Mfo49tXOy6u+nrXDBRqvXr7ixxXLrwaN8O2330aPcMmLMLhnhrx+hh1/AtQrjzav27t3XfNRJXruxHj2zOtbwujPg0KhQSA7zFCfb2m/yn32BEOpxxCyw3Anc5A5TGaHPo/PaRfoF8TBr+QH+pSafOD/eCUyFxXzHAV1qOLwCujidBcU0fU73ASid0XRxeK5IKy5aHLqiDMIYdABz/43tUAyhdAmtCmFdNG2bY8BFagCyse3tUV158oEHSjpCJ4453/znFdOtPRiqduDjo0bHcHUf1EFXKWSz4FgplylK24e1lIWCJS1DGsuRmPPlRiFL4kv3C//S2MiGKn2TmkaA6x/XjIQNCMi8OtLoCKFiAX0w7rx/SHYE7QH7QhPyKcEK/wngbcVo3gmv9cq9B4nMEcgk4D99oW4nhTOT9GlAjLsXEuqBvb0JlF6UcCLBGMBiRPnnIWLdC59ZifxRWIUiLYQFwJ4gQrqq4EFEIGkQM6SJ5sCaPHO7rtQ+SG08wkwb13BXd07wfXBeTi963NwQ5DrbJoXRF24SME6WuIQeJkUuSHQNB9X/RxcH8DvYDurlPyD+rozMWXUG9FA9IOL+Id08ZiyiVOHBXFLxAWreDzi9aLVXYKNEal/2k+CgTpdcAFLev436RJxMzt3w8EN+D/4cX3H+A0bxnes/7hm+Jl7R5bnTBg8ITreORo2OCSc3Scs5qstDcHB0aGVTa+sOTNqft2KOa1jOCD1CIAbO3zOitq5I8+ssWWHWC07uZ77rH6yKZTNOkeuWjVy1MqVo9Jn9DO8dezQhompKRavWYNrAqeEtdknEMR8VqLQWtzWHbPR3x9f4sssiC4BjQBKAXpoaaQg07/0ceCYvSNQ7IByFj45ZNasIakmjaOYzIQz8Fq4Jy2rJTgSuFdR9106Q4LY3psSQAc8AhHBGtjkDdB9ww2pM2NA43FMMLeiZ44fR0sXcq2oFRwkv5QUsY4z/zh+nDvQq0Ct+HwZ8Ij9d/xZwB/gU5gLzMEzViszk8xSkDQ1JaBEDpgCd4YkGsBRe8YgjuOFiIi5AFn8QkGWgnKmPTwQrAvq3MZPvqCex1EeT9gSEWeVqtPgYiwPeGUoftan4gDPVewC5Zoim9Wxky1ajb7U+QxKXqrP9qmea8wbZbGxpcJ90YBdfaBAzet8hWDl661SZ6qDLy8rQZdJHVmgpSwsY4PwVjZDg16ptwJLvtrlAk2XRmTOQOFOyfEN6H1VplQ2OVtjUqrlTY81GhQyefBkQhMaB722SPMTDbAlQ++V5aDD8T8b1SY5MLWYIqYcHQjVOQQzHDHLqBsHx/gcOZM0cp8+9cKrIaO8WSOFmBgpCIOZ99dJDDrLB6XUrl+U5STPs3twMD5MsxJfNfjrUQpPR+EdY+f9CP1KNwg9OqNwHpSDJ8YxiEjzU9RKg2cQJpjO/TCBFywOSpKnGQX/OqbnutpOJdu6AEMqncWUHcvQeky/TJ7+emvYHhFEmKs50+NxB7n3zlA9Va4miatmMyrhzxRnwY3ntRGYJkuPWpMx4cWMStqCJkGU/SgAGMW98nmJA19KeuN1haYbMPWCw2k8sHPpnDG8/dL2S+fA5g2bNgxj9bvkrV98+kWrfBdzVqG84p+7R9+/YUYZ1O2UbwGrQRKs3iLfiRSKx9AGVII2PKZQ6HbJn4UctEPuWfku1Y3GzNzcTOO6CP63U6+St4wb1yJX6XcCrXTu9NyqqtydeqV8y/btW+RKnKiR3bZ3720yUvCZN954hhQkGnDUZobuYQ6USFUzw5iRzHRmPnMJHpwX+IJj/sszwYQU0eyoH7z+tIEYd9oB+tcD6VuQHEZ0I8Dr9ITEEztsYOyiieyw5jnN+D/qq99nhsfjI016vbn4NJWe8/gYmyfWJv/B6/SEXh8Yu2hiKgnOSfDhWTGrh0JSi7wGupumscxphpSTkCPxhHeW4b+SEDy9QXQPBHp8BB6PwAZQAyiyKVkOqN8bOoEQRQvRlZPRF8IMIEubKNGnjY4J0q/05rHIm2sL8lwC8iHbGZOVlfn0fhkf3Lx19sNds2JWBWA5bvjN+W0fLrm6o2OGHo4ECnTcnMH+k8/LgGO8GwrnL2HXjlqNGjx2A9qvsXtcppITXR+VBKAlNHfKrsZqCQvY8sfmb/ysPQwB6JSmfpR7zPzvMoJ2Q9Y+MoevwnP4Nsoz5DMV1D7BBSUCZfLJnmrAxfWhxFMHOFB0l4M/skQIhgiyAvUeZ3CxeuLMAIgF4/p4PttXEnYYrPJgjmni9OllXFWo4bKqq8B9CkPcbTQOa4iOjeeWWsMV2dpCl+DOq/ZmFYwEY3UJXb7N5ahfOk0msadkGWU5Ns3woeZx0ZCvPuoqq1HofdkWzptXG8gtGs0+UXnp7d21I3bPGu4H3i3rQt6RL9iy9157/MjHnUPc4avKRr//2JNNmuqtbl0klejetXnZQ88e3NexJpDzGHxBV3vgGfQd/nvi9sKE1n1V/Xog/PXYzg0xSe02rzHaZyMmYn8R301WTJFUiX7jgS9OJJcJC8/icSFwAeqMyBAFbNTg46mFCgGUMImqyYI5aiZq5qLwIO4GAcw6stFE1GyJXjiChKeuUheznJJVnt5UpqhB30OQAJo7dfaVQy5/GPCB/XP2w92D2i7ZA8D2wmBFaEyj2dK0eNNt8Jqi3KL8xrgG9CRrzT8+5HuX19ySbC7+mXZlKT5Cb+BamTxTnlgNQnHV8ImoaXzjqgwE4cbUerhJ61g5edYQi9/kyvQorveC1TPmNdi8JrMH2KS3xlOPd5qb2CNn6MV4Oi60/W0jMHrGzviZImY4s4DZxOxg7mIOMX9iTjLfgQxAfB+IkpV4IBqL53M+L98XL6abtTSH9SUEX0jwGaKWABk8vkQ/5WUpJvIs3GSi2zSBCmrojB7yhooJ+0317ohszBIVfEQGgJld2nPJ/krUYhR8BGCGJom0HKbXguQeOFfAn1E4Z/slnLvthY8RH/AQ5+obyQXI458rSDCKqT8YH1Gx9cUT5yDPEsFQlGimRCUC3aO+UNS2V1Vg1JnBNVWAUGcywQmNykKSUuMyWJ1G2+kJY3NLMgeHOG8sdwQExZwWFABj0JJRXKCWAeDPcAnBjKY9UrPBIdOFx3qtQoY5U6bLGeVa4BQyoIw3SKVSkyEHSllz4mVhMWu3uZwyl2NKItuXdbVKhpnaEky8Rlm15Q2Z0+wOO2wmh9xpzosNLrG/zKm4fGAMWZzRAkxb4JtJgxlDt6kFi05XwhrkxZzGcltJToy1ZLgDiYDbfMkNZ2564sYNuZHcpUvxYcONT9x05gaatjovkj9vXn4kbzVJA1vO66gTMs2uCpbjZZjwb8LhSFbYnR1+EJ3+wx9efRVI7iqR+GcqzfZMeygHsDwHjHIuV8EVsTqpVDBkDQESWCA1CDKpMTSEK9YVuFgtLBAKlLnG9XMtGWazOi6dkhicHbKEYPEs9aZBHpMuUKpO5Li8qnJpZXHj+CV663Bv+vqChF6dtQZhZI56zhQFpuFz0WmDpTAca814jUARL1p+787Zs3feu3yRiDy8aPHNV02ZctXNixdt59QDh4zod52OGTmedcnOXB0zlpnGzGOWMJcyVzG3UA+EBK2VOrI20gBPjNR1fU7P+bSMl/SzRJ8UuM+zToh2KirrTXfFWL8fW50aKCHvObemB6iHdUMiSrRXxR+IUg0pcrvYL6R6oNSfUaHTVTr9kq9rDMbqUyNnDJ8ypSmvwlVbC2qyEhkmhynD6s0qza3w5wekBqe50JKdOzhaA8yBrKLq6vycYDjcNHtWUzb3U+1e9BK6DxkRknjswd4H5+2cN28ngNcP7hg/+Nq3n161bNmqp8HlbXObq0qm1sqApyXxszTR0pIQfk60wJ+iHvv7DreqeObSpknosWB0PGj5ZzjXKNertSZHbiAR9mVpVRKl2ejIDddUZrUEaiOF9cEW48ztM1NPQU143PaN1xQG4UvkpvOkYMyJE+iArKSjpKkUPXaNtrWgGD22FfrPKEtaW0u47/GRrAX6/m8HMdWsxryiE9PMQcwxDmcmMEeZvzGnAA9kwA+qwTSGMURDIBHymYh8PWCJWYpzgCkaCYgnIJ74aIg4K8fznskX8pG5z6CLWhLAqOa8QR9OEzAxbkngaiafjlyI/PqNrHR4AbFEY5ZoApPmiQjZK3HBeF+izmcKkf/E77qJrFE0JvTzoTQD/zwm/LnJT6A2Qrgu7mkmcqQY5gny0EaJ4MIzuY92DfIoESpCo2nFeLmniRayazPgMQm6mtiBCRpdvoj4bKJTd9wFEiZJX56EygvSeS7A6vqaA8/VONUbVHMUlyJBWye2anwerG1qvOvaa0Hl9OfCo0ZmAU92+4gc9Dk5gtfH5/aa6yaXTt5iu9zWuLxz0bzRLXC3Que0hqxZsvVtI88ygGtrf2sh+uD48d033cS/K/atxbaE7T3DEiPMkMuBxVKTNVpmK7H93fvk47ZDllODwg9Yi1LX5OS8Yr6vVeyGq6OuRxMW9JK75B1Lw+fxCLoLjE0UHzOVux+SSjmoK3XfW5HKs5pt+lqrd1DtLYVl6F82k11XCzBjadE31txchHmHv/511003oS/r4E+z1q/3eosi3uLwplV+X1GR7ytrzaWXemyBnIAtFt640l82/KaJa7fYL7MN27i1WsjWuJU6icOfMXHqwulL2TELUpcNH16UiLcuOl7hGRTOqATfZlQEFxSgb97F/yoqgAadBeDpp1PvGl1GlQDBhI4OoBk/vrcEaEpxvdQ7nySGD0/A/ZWV+fkFBdOBeoxFqQSwsrKsDKzNxf/M+N/Uqbm5j4HLSclUhzn9r6wMXVZePl41azonHWu1nrGEZTJvRjzPY5oONC5wrxXHPa6YzKcxy4VpQAMyUsvxXUvwXeF9xE19avmYMptWLgT9oexSm1YGJAH1TF+ZTaUEvCLgIolGTgLr0Levv15RsfWqcghYuS7DEAz/CX9N5vBhMj4V/eNTgTkjHx6XI5lFzFZmL/MQpkb+kPYWld7LwV3aJ1DH9pgaH5hOAUEEVkLwQIi+GZVi8YY4TR5gXY3PuARDi2sAdVBPhfcWMSMBfvOVjGINQ6yYlheMooN7TE+LD2j+BY3wWTSQ4YsEnAFWhxlKHVTozXYrmBL1Z/hJ6ul7W6q6DbAWSCXNRqgHSr3WzI6ZBmJZJEXNOhqGzBxU5qzQc6pBBnBEyrcohHm5vG4YLw3lgXYVjjJnwfqWqr1GepF2JffLi9gHkYvg9YBc5ANVk4IWrTPAU0P5bDyTQIUh7BeWnresrwwUZToDUc/qbBeYr+BM9/kjNH5tecyA5kjkhkVSOQun/g3wErknvGBoeaPVqJRpgUkuk+/ZqZXxcOkWrkuqkoOuknQV1fJfVgFaTBQ9ANQK1Al5mQEYfGZ8Owv46LylmOyD9K/FGibCDMEr8QRMvy5nrmZuFddhvKDGiGK4L05XYbruppddIY2WTRy6BOmym4iDhC+mYaNpM0dR4YqnCzCefHVRgvlooCs4tUINpZEeE+eYbJohSdcPUaFKKPoLvExJpcngsegznKXgyUWSSPTUF3UN/sxgWZ2+vr0lv7C2PuQuzGh364d0jiiMYqakc6M+X1eVGxyaWZCpzAZXalSZBXL55p32Em3Bzp1wUV54cE1MumWnP3NktBLl5tfl59exjxRGJncurk7Mm1muLR2cY7TwP8PzuYk1gwI+2QnXmGmfldfaVGa13dOVGQw1ltVa1Rat26ZfkhXIAr7Fl5uWSmf/zyi/S7FSiLxsu5rNdJWgLBBxo4fBXz5cW1pcUpC6xLZLUVILXiJ3LkD/WlJds2VpsiIRnu02GArU8NHzPhzLqM8ywrcSho5zgnqkt5AGInu2IT5STMcyWWWAmcCIEKS0OPEfVcURFw99G0R48bIQlXiJufLL5mJUs/PdHQAwWm356MzZXFQK5D8/IndIR+HAM4ZI+7jK0OfPS0vaSqTrno+BO3EOfADtebW4ed7OHfMezhxdrtUOnS2pkTtkpw5IobwTF7gj05s98cYD3169G/BOg5HowRsN+o2TwHxcQLRrPPceZkxHtJKdm/6Hj8pA2nWiFvS/XcITZBN6ouX/qy/Gia8yNPUTuzD7ia2Tbu4o5Hr6XnQH/GF/5eJKUD/qV1/0kfTLgX/Bn8etqJ62IIqSqEZ88Y3PAu1UtIe7t/O3vng//jCf7JdDJYhmD/EtSKdQnYjE9Gtx4MFDwyMR+D6/f+IA8fX5Z0iIey1u4oUFMheHUBoYTp0APYWCHL0oF9jFenWn6FyBCgRBrFHTGgY14VZNI4ip9d2QilpStOp/CLP/XiGDULYDh3ubR65ZMZJ9mt7mnkBxceAe/QCc4VyqiUh0BQgkECNCrrAZhHLyVg7UZuoTe8H/pCPCrR+6bE3pm+hLoH3dO3J2e4l2pXbzkGseferahmtkklUSee+v6ZCAowsjrTl43Lz1OtDKHFlD8hZqtY05RU9t3/VyYXajIJOxOb+mZTJQTq4mflTpOxCWnNrO80QZxCvObOntWT1FgqwWPWVazHjFJGVxp9YyHi99VzJHErgLinU4AEqcYd+YP7l67bTK+VM7u0fD4qZLrhkmMQhTCpx88d7Jdzy65W9bx14RhAog41fyUh6u5m2ZzrJxdYVoH3q/T1P95KMKuzRLCqB81pmt1M8e9Z8HxoF74akFaysX7J/atXbr73WLH5gWhSDmidSN+91DtwH5rYNrDCUSpYJXpG6xWkN2IAtVrmzF1P/Evia6XgYVRUqlSjayg1wSlADn0bVoXL9eFZVx+RgimzVrie2OUQOIvJ146+BDBuK1Mi1UJ74oZCAETJKGw5M/niOX/1Ful89N3R2IvX6WqUkG4IS5Ytqcjyb1vgxrelI9EuYw+mnSR3Nw4h/ltGyyBjCvx2hZmjbn48mna2jZnrSeF6Jywqy0/wyBEfqdZ1KnCmbGRzRhia5wooqTDG+cm4ce3zp1zfonJsL15b3PhC4fCTj0w18ueX5ZmdBQUqXJUttqm2bNkTCTGqvHpa6+ZMKhDclRsD5+5sfmBebBf0LfT7rzjZV8JOQN1E0q92vOk1fm4JV4HXMNs0dEj45QfEuyeQqjNAyjNCKmi2EDZhVCIqirQPG1Lh4hbAxRA/P0/4nsjKjqxMXOCf1+GRGYU0xeW9DpymnMyszwt+XntfldJkvI6stxOYNtHTTL56WRPB8tkpff5s8wm8OkyC9r0FxcpauthngrEP9q2rrOMENKYsMMTq/TEOyA/zGSJCIXp8PqMJsdNrszw2YzaNVmHHemE3EI1PTQTKddzLygnN3mMPe0dYEeVNP362K1LSOHxTJyrZnusuBNzf8xIo51KkviCf3tMRHPDJhdxz8p8zODpwHAnEqCHliDg6eTHNObhLjPpXr6/ZX00PVPi1dABpP91BMTns2iBg/xzYG/O6dnGeidhz657R1xnnnnWZZfvWBfinkHzzfwstSHC1b3zT4p5jb0yTx4J8vgie28Z3P3PRtZKsgII8MsREcWMY4jSwV9XoEJadekLscD5DPU2QOHkgB4e41WZwKPqfXiO5xALSYdLdVXSCwT0qd9IAkMN5bpJBQkwRLmRF1eSYh4Pe4HExFtN/CaBUU1ZeKYRETAllCgVSKB9LmgRQiGKAHJK+VyV7E/AAYd21E+t7U5UuoqUmSWj1vd3vnQrD/d9uiIEscoTQbYjM7e+MMVY2/4/dyx188eW1aeXWbvvHLEsmB1+9hxTSUK9uHFraMLgdLs4jbanZamoka2RuLLyHKo5BO+2f5CID6lbcPwy5wj5o4LLz7Y2f3VlOrYbq8f7L4dgO1zX9s1MVg1bcZly7bHX53all2R6bbklc9t1OoW7eNYS7bCkcdPLzIBU915a8BYKk8nOoGh4r5tK58Zk9AhESfESNFo8YJnpoIGnrSRxSTO+Yl+OGE6wIXoRbDjd3/u84dlHCzyx3XAaJgUknsGRdvWQe3UGRnhiAOMLJ/aaCkNDRqeHDnzyXksN+mhhc9MMioqspeOX7Z735yu5flSnznLnyhpzp6/e855vgVOPlgnVwWcUKWA/gKNxj84Ls8wLmsTtJ3jMqQaZ5adL2u8vmDHrFVDirqengEWPLlkkcO6sG3IQyvm3jt/lWlK2YTShpDjavjJ+YYIbFr+KuJ6Ri/wiOsniqweolokeHBUr8WTFzFA0OJe4sHMKpdM65eKJ5Zqq6L1q66+ehXYNOe5q94ha1qK6VvdWBKC1nMV+k4d6Hv0Bvq+Y8RV4J4L6IIB9n4MRbBnrEC8O0w/DeD61e0xy9t/n1n99+YOnndHgNKX7qMdbjjvYei8T9Qv8IlYR1oxVUSkUfg7VxMlbomWjI1QFJP3wCOYLRwFyic2AdRHG6EXMvEUkkn8hiVCZPkk/QanEF6Nuo2N4tEfSocIEFo0Ak+jV8I+6+HaIVsOH96y7JG7ntGXgiUgE2VOn2vi+cNbKiof0sjNGpNP/9Ckw0AKKtApdC06NbyxFu3Ve1629N57CJ0CwqGlM6+kKo8gCR4b/aGosOgxAsWEmYdAsjHzjPsw+vnwDV+Nrr4JJLfM3vESkB62ol5LsVqRAbgpm7YcBvS6+EpTH6yehnLs+94HAlgKhMRTweJgkojNnagrd6Dds0B7Tg7BuWMukPUa+kCiWAmV08Lz/Pv6LsSd0hUTqSQx47IY+mS3nChXzRjC+yy98yw+fggfdHFBV/AfTmMqaXQ6jTBpBA+QwikGH5K22bJHgQOMAY5HZXMtQDFANguVIGnJyLCgpCs/Hy4KO51hZ2pC6u5kbNiwWFI8wgldi8ErrSsrKla2orJZdF24Ave9n/G6kE9s/xlxyNNvh3lnEV8q6iHoTFS93yNaknrMHFEEB4QhEJUbcR8IifNHOaCEpp9g+uC5hH8q4k/V+SMRP3zeD6SW3mwSZq8Zh9578FF07GEL+2eS0Lt8HAg9uOXbh+aAZRH/Zt3m99Fb9/yI5k9/juRuwXFQdO8PYMf0w/4I/HtjNNoYHTNmVMTnj1x378Po3Uf7wrMf/gZs8UVGj74HvfXBZiA/HvHTGCj6YDP68XiE2DsozjLcD+lv68D9fwXF+WYteiJzorbM+fjVCMaRhUDfSVjqNJpY7JF1RUK0tqkTaV0xsRLxixsULi4RobhGIkw4HicmnBwMSXxpd2iYuDOnFx66TXHOkFdU4TaYLVU81eFmifI2FBH2IXto6Yq7g6XoGhcb8CqzfejNvXq3pmLNsEKDcfjsLV61JVMVLK3LMEZvt5Wfuu3vt+7G36kE/WFZQKnMaRg7rj1DK1i1Gs7ZUJlZMz7AclfKpB44It5+n6dY2lKizHg4Iye+dPRk59rKjKy72ls3H5FASX5WfdXwwOD2vZXDg+rJB3p3L+7a8R53GXraBF6sL+ntapNm26AgsFunofFyHkx539f7g3//NXa1tTWzbVpNHN2WVX3DvgP3AZhT2Kwviil4l7fYaeA4aDD4nXazNf+KQe5lLqUSyo9CQR0bumeE11OjnKNTej8cn5i5zt7kqlqrAUfnts1MPauTaDcsumHmkGlDF6BGTdXkSTU7Ue/zi7JLgeqcDz6y/tmZOMVuZ0B04GLmS69+ZKEL/MeceIBsOsFQ0JNJgN3pFyQ+N8ycJ5MAsFcBAyZfWd1b6vs23XnomWtuulf1Ol8ZLa2W2+OhKfDPR9X39qW/wVVFSHosVJQAC915Eo0TjkndlrpuNG/TSfJcrjyJ3iLJBZcDA5w2lrfq+HxXz88M1N7+xD9fPfKvh7prGtesKBxS77/6woTmJ996tVKq1MPqak6jklb8/p23f18pVat5T2Ytp1bLKl5hXz9Npq2+dYXvxO2SwZSLmohp0PLgAC+LdKRTL8Bq0LfY93lbjPdF2BPU32N3F/qaBjCj/vblJ7eC5NaTl6NCEic+IrVd3TTAXo+0tMzXXd1nKNg2j9nxrSfB0N7rcS29mhWZd6a7i+0SbTO4AbYZVVS7hrlQa5UX8aOFPhBpnNaXdbFYINavREPz0hjoF1A0bof1NavTiQ8OZK6NbW1wOhs2xWpNCUy6T7Y6TXGz0zoVE/cJE2ypi6GfY3U46K7+Xaxu/RWdZ97uvOKKTq6w8wr45FJyFXJAp2O1xcW1sdNm86ck7dP+88pbYrW1MTTLZHo8uxbedq72FQP9CUK8NBMNP48DeMif7Bf2fjei9278DCTQYTQEHQYJsAHOO7Cyt2blgQMr2Z6VB8ARGOrdhal/BpTB/efSD5DuYOnHSWxhRjMzmPlMF579LmE2MZdj/u8m5mZmL54L72EOMA8yB5lnmeeZF5iXmKMiBjFLLTXZtPTTIyE/cV5jqSEsK6ITGIpJkiE9t3ni5CfCQhgovi0+4hfzAZwDaCrxc5DQhSQC8FgC+LIEoVPwJVhgAQmDB8T5KGZyLGbWkwAaEI0JZp2R1LPoEjoLKACCLhGSBHy8xSSDgZCOF6LAYiiAuOOwwZAMxliDzwCEakC9xCmAJS5l7P9Pc18eGEWR/d9V3T09930kk2Qyk8nM5Jwck5lJgCRDCEdIgJBwRM5w3xDuUxhuFFDkUkCRFfHEA7/eF0FXxQMWXXBBUaOrru6q67rqQpKp/KqqZ5JJQN3d7/ePH2S6q6urq6uqq169evXe5xnPsInGU6wjIVGLmnRFOrRQZ7WkcaeMiexZY2KS8Q2Q9i6XZrHqwQ5tQAtu0ZO7f7DYhRcMie0esBk9dCt6CMzUZ7WPBfAc5CXwxRdUWvgAWvMyzEJfaXPgY4AL6WzmdnSxHCzX9kUjwRBpexMPRqHtHB4ru0Po7btOHX2AA9KHbQdA5iefcGdOStjl2sieC+hP+KtmRFZvA19mjQSu7zaxwCy9yEtRNQi0Nx/F/7jS/A0Zf4Dsw+uH8HC9KZVDd8pkRnx6TCq1pOmNRqMjQaoEw7hUo0wGpvKpRpwGNAAOpGvAHLk0wWHC/xwJEiU6CBxmlRq9yKW2nwGT0WEtm8zJ5Dy6A7LgDTD2FSkEzadPa9tGSPjKYbOAHJ0JoV3JIIAe5DQ4/QkJD1ZUgL73ffTSCSnrBxBoVSeASoHevAv0+uZjKboy+E2obPk0G72GTgGfZif6/KMcsK0N4qYw4RYDKwCHCtBz4OdP0JftN6EvQNKf/zwAzJJz+FtnRO6sY0V5CcXmJ5h0DB0GnYMCf/A4ZblnNsIvQeMzG9t/3PgMd+7xkBcle0N9c9mGjSfB9NaKTS+/vCn9SfAgwRhHRm8/ke5sxOPuRkZOvW4TeQzHsISBwfwLj9lffIEXm0DPuMQLnmiZBJigRDCz96FXUdpy4xnQeK4OTB0/EK2OvLZgfFkTDKCji6EOTMlQo8sotHwG+4dTj249NA8MfsdU25efvRKloFM3jD4HJp25ue+YhZFTaPWgMWAD7NXWB0yFxmXjZqxAZehDtbGw7wjLGVA9/45Nj0VphJTh/kX1cwlFN4geeOgOSTYwBDC7HfDZieSGjcWzZMGLGRrRcZxAPTdZAhZh2qGNa0+f+mzv3s9OnQ6v4Q+1APj1wYNfA4j+sf7sXWsefq1l//6W1x5eM2vl42PeOn78h+Af997x8eNHFq15d+m7x46/xa1ok5aM3bt3bAl3Zd3s2W33lfRlI0N37hzazmbnOOfOTWO3c7cfqmiv9xVOn8OL/PQxPEeP7bSHGPefy6Gvue4CQI1DRKE0xgb4yzbjeKONHtDnNuM0EsYHdPn6YX7bN/e1pd/3zdpZ8t8tnD40F2S9tK99j3rr8WPwI5PNZoo4SUJoIMfIt+QIHiFHVE/Ds2l4Pz7ed98339y35LXCNM/C3/V75q972vdVFDs+ZIhGI9NRJhFtW0QfaibqRc1B/ajlMgWMnylhSpm+TH+mCtPn4ZhC38CMZybhVf0cZgGzmFmOKfU6ZjNzE7OTuY3Zh6n1MeYCHhFEBOSiR7/DRKzLLD1/QYsQ/yPuguJ/gOB3/cqP3PeZgr9w10L0WUzCdX6uGKdFQWpsMGAmW3gep0BtyP2YfZa4RSx+s8UX9EqI8FrCtF+JSPk7W0/DffBo6+nhrti/cs0sTSr+2eh5pmbYLM2sFfi3Mnpu77sIGBcD02JgXET/ouG2Z12L7+kZ//3QxZ0ZuyLb1j/77PoNzzyDLnn6VPbxNE2ysqn9JqYEi53B2mHBzAxTWpUGc+XpMpvaalamBP0OCdO6Cz0K6vqyh9snow/4jDffRO8vXrw37u/WtDyHOs2bRn4qhzctzevIm+BN85Lf+Lw0L/dueo9/6Piwxd1jFg9L75Yn/nM+s0EsLbgxPVPGA4OpwFeeJTfnpHrzBKAwmhIkZksvoGEVrATKLbkx/P/FePztpHgMWT3Wstcznou6eCUMx8S7Ww4fbmHR4Za7724BLeW5Vy7mlpfngsdyQvCHUA54LLccbCP3DpOETQsPc8WtL+aUl+fwleT4u9/hY5QfzcD06xI+E1wjPgZKJHTtz1NRM8Hx40QvDkw8lFFUc8AvbnLE1M3FBwL8fsDtfe+DwyMPrlo0c8aiFXfUH3z13N1TL47k7clStanPNPTTus2fbgVJZ1dcOHzb5i3HxkzfvH6ibYbOmKr709295pQWSjWmxN6PTziJuBL2uXde233Xu8FxKzZvWjEu+MyBu56vLuVSDCZ1gr9h7pL3t5wB2tHb739g++jV0yaGXTajfqjx7nOuHJdJY0jqV9X2sitFE+VpiW9wou+fzYymrZ4t+otMAVRVrDegICAEKySGNc9FzwbqAYHi/uOPECN1ZSDIxmQrNo4sxzniPJdIL6h/XRqIfCnqeYvq3m/bE9u+AQKfwN5BkrQzVrfZBU+8I4pPtIkaBScA7oTVzXbPhQQi8crfbDNiElzsKiElQa7NJ1h6VrWvkmODOKjSp5pdgrsLd57UW9SZrxd7myam6k69k1mAuTAI/ts684y7yLAHv3YPZjYNgCHQ1Uxkz39da8Nu4CI30Ie7DTjnDsZA8kv7z+su+rkQ+XjiKVNJbcHwLYOMdXgMDhl0uBwsZexd4pY59bxBcAQchefhAnQefA3GRwbc9A5qRS1sBMe81P4KfOgd9B1cAMagFtQKbgBhNdS2h/S99O0hLVSDsN7BhR0sE5kBD7S3sxz1h9H+F3iABkB4OmL0ebp2xmjkGF2eHjLEzhJXUvgWz0VVzO3METxBE/G84KFQ0b9+CIrGq794cMUn0rFk21znIy5ATQSqk/hQYHVdqX/rlcDk4v1kmhEM+COHx9TX6wP6+noc/sUDSfRr9+tbc+NShd7TGW0nwuJmUPiEzah7zxCf06++DoQAMcNBuL+IGRp+6fcrd1eSu3V1BkNdCLhAL2upvBfIJsbb6EIveakVvY4+1OObdb+aCWcVoTFj44+P+VrpxyxjGIcBt6RBA0DUQWNa1E+j6GJRRpxDE+0sFgekouFy59hjgx4fIbQisaWGBoUURAVQwFWz4BNsLAw1NpKGCDcCBkL5qAGThGRh0oBRcuIjBSrwH6vkVQqd3qJK9xrkKoVSoZIbvOkqi16nUPFKVkFTgXt2r2zfv3K3LMU73D/mfTN85T1d/3R7jm1un7m2HHt6f917rwhJ79eV35ClBc3hEDFjCoVhIQelBggNUsjpZawgcA6pVWoUlByX6ExLTExzJnKcUjDiSAcnCKys/ejKm29eWbropvmTrJdDIaUxo7gkq2xXlquszJW1qyyrpDhj+LBPHeuO3BrdP4hgWlaDOdYmYpGihsT6wE03TKgo1BknAHd32mzboMXhIxLRIN1rJ909KpzArLqF7DlhDjboEN2XU7F7BghcI2uXRpSVG16Y8btvtcphwwY2zncldTD9O8XhNTUJq5+iJlvhoVum5KRAZvHIj21unnMnRBzGAYsMSdPIzf9ZvHHXrW9dOb/4cQt63WnU6/bk5Wx68UU+DKQvdpe9gx9nnNxWIyg+P7LgjYFzaj/fkOSJSciTcudjUpdUmGIO59ostuRZiwz4tVb38fIk66VI220LUu2peEVHBPAv9hS7R/0P8WG+BfO4w8hM6DCqod0LRbwLM1GyUXOCjSNeyqlNDDUzZEWZVbzGSadeXnTG4MOrz/yEWn86s7piyYqB1hyOT7X2aizJ0AA2f/KGk+dPbpiczwJNRkljL2sqz+VYB65YUoHCbmtINEPCrVftB2F/dSP1RVU+rTQ1tXRaecGwgFOJs8IZypMSLFpOkeq0GY229FQlp06wJMlxTjg/pTMwjB2GiLOvsLgvQX7+6mrwgOi1Cnb6lEmi2lMOArEnYk16HPj7JwHR14rBYgZ4ziMAshJBgWcEsqvgiGI5QksZSwTpDCjg5RwbuU1fpI/s4rVgodnJD3hZkmY2pUl2F+uhZwa6dYHUachVrP+9xJmTxi9BN8xALWXrF9Smp9cuWF/WgiAjkbFc5AG9Ho6B+iQTSIxMM1qtRvBFkxMcv+3QRzoj5DNRHXzUaE0yofxDt12+kl0VSk8PVWVfITwc7GC4MN+O+RkfkQoxgs4X69WdArtOXFydF0DqGZbTp5M9I/zjwujSpZYuUBcxuP+f65WK7Z9ufghkPdrOiD2O7AGxzR+h53BfiksqqhNx2keB/tCWL3drDLvRX/Xirg55Kn4/lNjrdffXSD0VwzQvpBvBFhAFqvGJZWO0fLPVTV+ANqwde+jCXy8cGotPS9++E6xFbVRoOSNWNHSVx18biWpLErT+zreXiqnJQ2vBWppNa7irLp26KByhzaWifZvehJvQ9CtN6HczVOMMUxyismMjVINSEkESKzRbdtsJ3KgiogJ9rRi8hC6duO1YucSg62+S5jR/05wjTSnVGSTlkXu7KsH9fhD62/2klTfFPUqDmxLAwI/uB6ZBjSe0ScbZGzbMNiZpT7RdjqsS7Q90rqlgBpO956jCe6waBNztN+pHukiAIUTARcZ3rFIcQ2zaY19j7fXqt++fG5RaYH972eUGpmOLWh/ZGvdtcGfBX4d2mS0dh9+8fgVxJ9IdegdkW9QVA5Be3dYY/7Vgp/3nHILu8d/UjXy7oEfohAY2dZO6xyaDYCeicMDevRH4324E/JHXFk2TWeX5ciCbtYDewUTITm5unj0qemNMyWGw+/B/2UqkG7x52L9ADqQ50iT54qYttM/HyjVnQvTGlOK1a69pRSL7gUTfiY8wxUwZU83U0R0aM5Rcj3Q4foGIkB6CZ00zgydJj0TLFlKGxE0nXqAjMjkdKMRhYglG2BIJUq7/5/44ioGYHuRGBzxnzj788NkzwNO+B7MuzYtnHDw4YzGdWeHVm5YvvwmGniO1eI7eYP9+CH33qLYbKbqWIJ0FuQbT4sUmA/pj5K2NYO7GjWgv+rnk2Gct95eITY4Zck4zbJgGtYMobSi5v+WzYyWEbwMdEoH0twFMLTOBmXu9PofZZwkjSNI9XjYoTp2uTj3M7p3TEh1QoIgyKpYy4DKaLbjVmCDZ9cJ0kSGWfLQT24CkW0+rKTenoh+eeQ8d7bf03J5aqezmz7Yu+/AG2n/i0/VOe3o3jUQMd88H+K89/PExFqjf9n+0FTck24wbEEegH3AE1xjf1yZ+F34atVtTPjgpmXH04+Vb/7pPI47BUHyqwRNli3EcOmJ0J7beTw8PtFtSbO+BcteK3ehqu4C5IDEGncIxuA0l0f2NwbgNxzEzf6UNcZ/5twgTdQciNiXte5TVC7q1pPd19jkt7nLhHk1oR/966pPnl26/ZsweunqjJRGonm95fvejb0ZHJRMm5vy4OkunHTw4belzbInY+ehl93GK2+5J1J6Utmao5trBqnsOpN3zAtCkpK2ZREfjX6LdECwg3a/kftB8f0l7Z9dDoftLuukQ9aYI7/FzptCpLCl0nz2DXRqTvziPXtghk3kxEdoxtPt8OvS4GH/8wq/Pq+/vkFtxQtnOYd3n16HHxfjjF35hnoUdHJ1nS6i/RTNjMkKObu/qA0F/10cWRNAlsRqxenZ1CxitDwxfAp5H0fsPbf50u4JQFroJemScWIi38FrwLbE+48QbV7tqw65JQM99dD/6626DZveXWw4B/aNa8bMdGyc+86bB8KaY0bhj9EZbuPs8hFd0QphbG6sLRSsXSx1HLiUM0ecTuS2zxeePbYY6YmBRsW8jzDMY0AeyJFmuXP4c+iBK43+hjMD9nFyeixO3hbqqBOfhCqMPxBvPiVQQz0OPgqzO9hEjnxPf0v7tNfMq/TZEPiTykJ1AbQxZEWCWt5MNIOwiLQl+QfTjR4S41qUMYuROqhM+lcxU0V4SebvHOzGBDXPEfpqArEeZUaazOxNtLwZd7eQjt3b1VnwCcXMm9HfF4xMTh5OWHucLU+cLEt1XX5CqFBIAYJ+uE9jtYWdhoROtfMP2RV7lqvLF246ePh1xkDg+XOhsfchZCOu/2ltcDP4gO7L74a8ij+Abo5yFTPRdPKFvNWQnjKwLODN1Cprm9qglxDgKv1Qf7BK7i7rgHBWaUuBxcffWy1ZvOv76jMNA+5C7btnxGZVbUuTpCps5q9Cllmmyxwj2mbWllQ1jQsEJ5QVJqg8fP41+TExJtJmhxjcs28w+PPfkLTOLNqMjjc8+tH5IqNizJ3tKdl1VIS+/K3XcF2CMre/M+t3Dyypay8rrC0fNXDor75FTKPJGTl1+tix5DKupmzMvJpdehdtuC15PlBFUEUZED4khHODVsegvzEy1EgGtEMUCwhFsPA6tEDTrYzBhBI/OQJWQ2HesD/JQp52fV7J58q6aQYAdmJAsSRAMGqm0sD+fVlk8USnXNK37+oGpUx/4GuHTimE/HMZkHVjeWrHiLfT1gVcfQhO3zV3xFixskPFyR7bHX5a7u2nOaOnYfmZWZTJuE0xVckFaFfLnC2hYNBN8Wvf2sa+HzOSnk0zQWfT1WysmbAH7nvjjAZwz9b8SxQcTMX0MVEbswa2AVyxBh9+hw79OU6W4sL4TC4T6jaE/ourLkJ/EXlxbXFzbmhB3If7dcZUh6tTkF6bAMXfQG5w9FoJiyoidCAwh03Xs3Hek2APZxHKGsbu1BPcPRFnYOG2S2DzgiGmRUOfjppgwiffFVjBEM5V4rpuIXvmUoOfDEGhUGQwqdMSgalYZ0BFyARrpRcReUwSYyhlENCSY7IEB00oNxmG3P3H7MKNh08hPimpgOArAj+6+9mkx30hzUc13hTev9E9bOnVivwxdKf6na6wpiulGC/+i9fMxo+LqR3qiBoioEiJWn7+onA4xgoZKZTrkSPorT1TAUkF8Rc12Wk3KfHXV86mrMtk2mUotu3pVplbhIAn0iImYnnK56k2WbhU+CAYfNBqSU5Ktrs76Rj755Uy6Yp5yBfyuerar8qtW6SRJXkfAFacfK6JKMICySqKqfvQTxrqeo1OjBjASPL93MK2YkFMhEAztP79//3l+1Kd3R0L4kiCVhQAh8xSLDJnJ3f2huz/F4XAX1i2hY2aq7cL6TA7BYXLISF/3OPw+lqq+GPCs1tyMvguCKjQNHcL/p4GqIPquuRkwoB9YBfohZu5FCYNCzeHm9maWnEBzBFcLT1ddfq+Z6FzjJPSZI/QZ8zT0U5WLbq/TffqY509cb47w/W1PXtBqzW0tZq32wpNtmC/7njpbwjljWv/C5vbwhmf5tzQZGZq3+Gc3sOHNL7Q2U99K4ByBYOruD0p8d7Yojbj++2Hc+5nfLMtnok/RUKSFRaLL0RCxQrlusURXrOAVUqxI/EVsr+ZmTIeWUT8pycQ+horbOt1tEyGJ2SKDxL+7x0XmahkQI+HIxASdFuWZUowGtQ10sCFojvyVm5Ocb0EDYWKkIwetApU6p1oJUzhubNucRKf0a3mehVtiTNZ0MOyM9sNADge0fZaYqrrMfsG2nxwIV0FNsgT9ALvhn2t64p87dD0xz1uZHkjn3EOiFlwCM6JDIr2X74jaKecxlcwQph1IgB4kARem833AQDAcTABzwXLwBDgFLoKvQAQq8ecjeDxuCq5j5om0m3hK9rglQRqmICgSMQ1RQAiYgS9NiILQeKLbmUVuvNQSyqANADPmnc1ijpyLOpEm2OpkcRE9FonrW4s/Ou2RvVDMxpGprgwQ8Y+nKOiNPodXfUYbayEgSG6B4iB5OU86gUIK+srYcgooREWqQDARbVRcYpLIVwZs9A5FKXUahYD4ThNB1sMFtASAkRxJzcgiSfRyiJdJaR6zpRDXnhe9GlIfVxbcMAXErow8EcSch19ioe1kI7LboJuJ+jfwF7FuwS8xi/FuHv88folTdDPiklAP1Di9RMAF4CyB9CAeE34TfS0F9fOopU6JR80KaZI0HBDjyHrfzAYI+J9bDSzi16F6u+Q5zCOYKSKUExfJwlEP8hL6jNNU6CK1EgJ+EdGOeGjEWfEBEbrVKJYSfCx16xP9ENQl4ToVCW5Doh/A+iSzuUQ1Oi138Nb8jLzWRapRYtAL3wSZzqS0gLsomW8aVtvU1DLln2uSFty4bDj8QWoQwNhwIL/BHBke+b1ldMGoFwDkDVJJojpJkCmSU2wqS7LTqjcqBH+DQibTDIVp7mRe5VWzUJ4p12gslaBsYbLdJNUOtvRiWcgJfFJBfmHGqrzS6bfdZMwqcpQpYT3wT+4zMh3wAgchYHtZqvR43khe0GdgglqnyJIBTpuj4pPdaXCYWiZVNvjlAjDqrc5ki9phTVLIpckqC/pJVmfjkpKN9qHORFU/m4pni32awTZ1lsJk1tquvmyrkzkMyUkZKZWqRKdL4wtysufVvQ3puV5rIntJqmNZlS4jBySglq/uu++r+wKzZwFBnrI+Vcbx6Acpy8HzkJNIFGlb0B3azBKNnmXlfP9XWNcmYLnvODAdcrCsrkJjLfal8pwghxKZoJRqpQZudgmntGmTIeTA/yTAQF6OUqqT9UoBw1ldpSdzZQPv3BDwjVJZuFdfm3xsksQCU2XKHLkBQNYwEhrhNPRoTa1U2jd07hwA3BEuQW0ArEaTpZalQq3ynf95HTbyDSuy3P11rHyUL7Bhu9YlyBIN5gqe85niwg1JfWUqp8M7j+dHpsWFuQqNNDfJWZhtMQyeNWvvrA/m5fbrUyXJmNd6WZFq0RUvHABhXlZiYmY+ZA/Vm/WpCrnMnJIik6uN6hSpMhl/M00VlPf3u7PLHDqXPFHP61kO8EAhyWAlHHSkpjcVr/VrLSnAqk1Qs2roTeb03l7+KpVUo5Kq2bXoXyNulhtYdYJGrU5O0BWtLWly2h1QDjN5JSAuLHGOCVK3zl6ekekfIIMFCRrci5KVsmStXiWTJ9tMUvaxlET7VNfqFAO3LGtzL5VdrQ5N02rkYPEatnJLwVR7YoqeM6Ss3p6q7rU5S6LRTu2r67tmAYfb8oY5rMe906AXpMaNfSDceGzJ0mPHli5BbtwTk5bhUaVgB/V7nmtowM1uHFHHa+Dp3ssTpRK9dm8K3GBR7Xw9WPDKAZVJBgAUwJgsPCClqgJeKuGJ/0kgM+oMChYCXUm5TOpVqVLScZtENqm1A5cplP45AX8thH0ulxcvLC3aNomTQUzZDRaFSlHfL+2MybSnwGlmWVNynzDIC1S4HWBIDe48CUY9x3PSlyf03hGY41cqlg/Qqgtw2Wspv9BPBviXKFfem/ra7qahAGy4TX2FNg5TJIlQxnvxKd0r8D82bps0aVtk8aRtjY3bImNK5my96dUzwANKLm7/4+2TctmsgXPXDHluWsrE8Y0D3MphB9GJB9Dlyy9tWFxZ6cjLJg9Noo9O4gv63FDty7CoebnFnlc8aPi0uX3vGuNbMnH68No+vlQtC7W2It/g3iOCw2P6BlGfWakUtbOamUE8rTDdvQgRxMVuEMqGQsyGYJ4dz/E+ji4UhU5RAlG8gXZOH7N3NphEfTsRgBpz/LErt13SE6uQy0SPonc+2bTpE1AE6kARCUXmXYvCvEirtWu1YPXsamcKXd6nOIeLVs0xM+n3aPTG5zfS81l0+Szb6La2h2Ng53zzpk/QOz3e9vvrYDZHhmoReVeLNlTtd/bSLSKygkW6Xk4/W93DKBt9J4rSxm/cOF4M7T57tv0WSFELKYxuzKZMJmK+WyhPR9ZhPp2zR1P4KSdl6qlWVWgWwlfDAl6H6dVXqCK8QO3jq/0TKq40V0yYUCGEKib4qzmG8LGRZhAWhfntot37ERT2Vx8hyVia+Eg106NMSZ1lisoiehTBlAiuKSpm6XkGUhuh+FL0KCIuDgObq/09ihBp7F5GYP+/KA+Ll7X/P5UHYm70/6w8sLM8Fjxqmf+kJNJfLwX7b72fyJF4brWI+wyoHw9DzJ0l9Tbijrplt3DzqGuODW/KjQknEvMVJ9Fpg1WpzMhQKpP04FubJwOl4+hqfBv8Ht/jdVl8S5aON4jY0iyR8xH/AXYTQavSGR34aPdIHE6/z+7X4aOuiIYtAXyHDaHmcBiEQiH0fVMT+j4UAqFwGDXjs7apCWhDfLgFNYYjLS3h3bvDLdAeBkdoUGzOmG1DzBNDNkW86E2lpgQThioh6chIxWe/gzdRR8l+nd9pcuGCUG1WXErq8zZqr07O1HzdJMUjFoXbGEQc0IZ5BhAsXSJOkeBfm3hGOLYdp2LDxIFpBPfgDpye+OsVn+IYEPNh20oE/jhC9MdAQhGG9qAwJL2IPBDFzcEVw3VK7ZQP+aL+JUZ3r1X3uumcsRqC+Fo6TT6Xo6uqxMOvA/9wP/M7olnhlbhfRutKaoL/xKKzRGxEtJ1wrSNMuBVH8vjXhm/gKog+I0hE7BGWwgyLz5IfpGcUdeBLj23RpoB06yMi3sHtFn0naYCudaAOr+UYoIsfHfhCYnGQXitwTHsjAT/hQxnF1I0wuFFT+GxhHbCjRjG2OKO9sXhQHY7UMPH2NhLq+5ghDtrKQcAVk3wQ2k2cIXazFlpxJUX5nBL9AOxtuGMXg9MZyc8mN2a0M7FXA+aKHKe4i8UdAtgzitkj+F4jTpQRLUTM31IMOysBf9O+zAhmKrW87AQjDHSGzT4zTx2Z4DFpIsAQdpef4HEX0bUicUXlptbMQWq+5he9YhNfoTrHteZOwt2pFqn8wAG51KKyWVjl9u2sAljaZn1e02/uSv+2zCwwCL41ZdrcVavmTpuSPzM5ed0zk3NyJj+zbhpbNaqiJFRXwep5VAL+Nnhid3iioiIXD3dA/rHCNA6sB1wLKELv9Krq3aTRAuBYWCRIJz8/WSr4mpQaCCUZtY1LGmszJNwtgf48K+3nDVawAMEqNtANe4jvbCeCd2BlvEwZ6QFqzH+k40rqAgz1SualbjXtHKDG3NRKVc/h2pbBayynxszetAlO3jR7Nhh7F/rh7uWX7hp/F/7GZUANkxc8+8+N6I+Po0uPPQqyHgW56396dgFoiK8l8MCnMl/660v4LzMyOBO8i15BP+AcLi2/G6jvugvVbP/pvsZ70PvPP4w+fGjag9+wku4YWGw3Xg3zlnwP2n4NvrPJ2WXEZqaYfV24VGGDqq2ZSDa5kMoQnlDRRkk9h6cDPHZi944ciUU2kmTRaG5IV+IJoOzIkdidcDQu6otVSmg30WP1M6XMSGYekcMQCR3Bedd1yn47Jb547d15QeFDYkm4mDxL3G2hSoWBQouN43tGSJox7WSuEgrKgKfU5RmQcmGtdHaDjRnlamSiM9jfTJPXTDaBv9Gtw/KKvLyKPG7X+Fv2bNpzy/gBi6bO5PQ1em7m1EUD2pjrxXIh4hkhEmLDOMvWn7qgiXgFfikNlQwcWEID2jySffukqiUVDkfFkirFjneffl5wOITnn353h+K6sfHyzVxmCO61WiiY9TF1hy73WFp90A11cRv49DYoY/0OPKYtNmJ1p2ZNDty1PV6chA9fOHLkgtgmtMiNnde8aFN585Bdiwe0MwMW7xpisFgM5IqLXfFh1IYWzJ6NFqC2OGQmHtyGR8RtgI9DaOqTsu6JHzZt+uGJdSmCI8MhdL+Ml6vm0vnoP6thNnAYLQ5iPg09Tly/36xWSzsjY7+TVS7cUfNlzY6Flf9+TSrKSlv7bfj7iXWpqetO/H1Dd5kwKXvv/67sLO7tTjwO/p2ij2RHjSwJPDPjyxnPBP79kp994ol29c43s7Le3Nm9Pw383/UnieBw/3ed6aY58MU5N/3vOpLvttt8YheK+w4apoR4m+N7kJRgmTTolXocaqlgk1oMPe7yLV0ln8xa03oV1BbdkJOdnXNDUW1BrzQry7VfL3Zy11MhvZpaJ+NDKDhzVEOoOrevLTnZ1je3OtQwambwenFETyb2UJzeBINn8dn4u9Cd3qjbc51HDOBSW8geEaXxuOhBQyAKNiam9cQHPYXUWzc94AcpQJc4KQCx2oUW0YSPxYsjeyjfW0EPThDwuK0QL4vlc+U0ttCjluFT30JeOqJvSUXvmWlJ9qk7VPMkTbWR8Ii56J2anVMUvGT7xCLvIC5c7Q+Pz+9X4UX1tuPk3JLnRBc95WTZm5iZDp5Mz/yZRNtvzOgrhRXe8CrfEB6EC9MCBcKtU3/2laCahLzapqUjQEbV9JYpO8HEDab+Xfs8jfgbFzAEjIs0i1O0A0kEMQBGQFsGN4s/aiHijDt3tkWALJEEVmTJPCBq8SduUQTYw+Mq7BXjKg66Q/5qooYbgo+nBYQavkKMtz+5bXGqwTJl56zbpTXqG4dHavvMS0dh3/7ZQwt3TrEYUvlwhTfSBLXENDTyfQdzxlftz05DjC8nDeyzJ4EfqM3o97EEcJf3lYGl3M4pOsmOWUidkY3mDpsZzINM5ajZ+9PAE1N2cqWd+Ht0n9eNZ9HBzGTiY5gn6ytRzBJ0iOrinSjTfFRVSeAlLOE/RQgjshlDu4zAU3xeElUGWFcMkpo3RXFHgmRrkqV3RTt/IepbohT4qFkkEfTwXMGJo+WWsioetc3ev3/2wpzBY/fP9ubCJXgA7587Cj0y7tZDR23pFV6rEdQVlIMQCaGPk/XZWm15oVEPGm3pX0WWJZj91bkuqI7QFSm0fO1dMLeuCtRnB/AS9J1t6aTdS4r6e93orfDOAj9vW9rfLd9/fr8ueWPt7P26v++fHZnasN000gLfGDhYHXR4K+QH5bWFHQwObFJJrSaXuTAkO6IOsror0mp/RoX6dKh6dvXs18uzp7czhpGK/jnwTn/1WkcBuugtG+A9d25AjnS4P2uQbmdn36PrwXSKjYd7Euh0sFcKXJ3MCvkIHjEMdEW4a1GWi+DLEmBDkyOKnORzUI2K6KqADGvSby08QWaOCr/Wlc5Ph32WNdWicG0T+izycW3Tg8vBvVmRuql7pH2baiXN4yOvekLtfa1uVquT+1LZUHszDksH5cLw2IxiPiQvTEX9KybgsVygVYHShBSiUG51S5jigvZ/3n0a3UU8spy4tanWvvzB8NYpw2bYa5uuNoMpd61jVUVuq93pNaa67W5rjjqnV3GGRtOc4ppQYbe6hcMqb9JrVIAl4uER3q4vs4TSLFw9g5ONYUSZrbhCrh5jswyQ8SkCl7DOuCB+DDioEZOorM5ZWLfoLZeQsSQQBYwjRrmElpEBzObnl7P7rUtkpZ68EMcOCqEzadlF1cWgLS0LPu0okk6VcsIStiLPXSabYt3EhvLdpbLb1t0rK4UTI4NHViK+sGT/rMSCtHxzUL5aWDFOvfmG+g3GGfXGDfWjN+rGrxGW8KpphpV8uDJfrY7sAp+58yvzFHoVuoh+5P78pbWqqF822mzNtIPbbEuSwcdKtbfC50IzoVOtzqvId0fugw+586+GfWCNu6ls1l6FwqbNFiDjTBh/s3z04hnD0QgwbviMuSPl28bbkpDTnIsp4ILqibE9X9K2PopEMoUicl2f2pWKTsCd/ri5QAzgkeuhJM9HZ4OuyeBa4meIeoIiPyK/uz2zomiwSADPmp38uITi2mJxmhgcwBPG4MCcfWb5lMF5RQsHJqVM2JA8TjuzIlIoEsN9swb23v9XO7CTPx7PCYhB4bcCNUWUECaZQFPj5EuZfYozSslcEBoTHFbtb4S9gsPCh+Zchv1No4WtEy4tmYd2hYaLpHDW7U7onL2/NWqHJv7i9sVd1MvsJGYDGZ2W+Cr6dWxUhSkViFirBNDXLKRJNBSMkHZAS5qajSJYitNHkRtPtQYT0Y8PxqYQsVuDaIuzFP3FI66tA3RxpQFk+cVL++TttIw0bW+ITJ29/++6/bNrNybrMLFKMvVf+rwjqB48MFhYi+lTxWNml8kqVW2SV3hx9BFZqK2v9Mr07PLXMWWqDp1WV2T4q7nknP6KkYadukFZ/uHSnAHnznkHlHnRxQLH2mo/u9JSfvTEhHHokVFz92N+CS7J9c7eP3ZwzkJCjFEbXxVMtx09VF4A6oxWb8VWrTZbn4w+JuF0G2jUGwvLwQxzQmRZ/wXer6GF0N5IGKpdudWtfwtkg/qqurHoLbe3f1EJmfnSt6F3/NWdeDDCkxzDJFIe0nR9zZ1CM28wCzTWoyD4Xmn4RJ3veNx+gwgcaqCb0gYRG+YGgwq9r1dtVRnQn1QGvZpNVBk49RAgk6u2KPXA+5LUtMIoezEX6JVbVXLZUHy+xSi7LJezKu4jmXGnSs+2LFXp28/Th3P0qqVqvUHeXq5SyHVKWINGGwzg4cgTSp1crmZPKXWGyJWEJMEpg1KDLqbDIK6rZUwW00u0Q/CIbhwClmhdPKyzO+SNqEwmmGGPjRImbpOEbJpw+j6OEavvqRhUdEYqkxruMEpfOaRXi3rQ7nDZyMkjqyS56Dz6/rWlS18DWpADtDT0wXV2Iti+DQ49+svgS2i7Tq3VgXnoHpIPgcNJSL1z+rg96XI2sPQ19H2P/FB1j4xwKL7euZjWUG9UoDAYyCNGfniS4jthjlKJu6RyzCESdzBkuDj+vWTXNE2PPSQ4/sBMtSJXotcqOE5jTLK5DDWTGwe7+mu1Co1W6ldpWG2Ovy537+9fYZU4qTxXqvuNpHtee8VzbWNG7r12AwnkzdTr61QcVLGcUq1RClOH1ExJVqsVACqHGg2cNjXReGrX7pMklZr9rVRcwXWaHZiu8w3JOAp1tAjNvJ3qlDAyziJ4ZCAoYz1BiwwI+D9sIYQu0giPPNA4CNlByyn0CTwCj0Qa8TVoQfZTwNGIwrCFCDrJDZqMRKeSRNFk5LFPG0GY6SY7Iu/0YNKJ32QRZMAS9Mj4oCcoAx6hZ9eFZ4AGfd3Q3Ii+BpaM0etQLzYHvI56oX8AC44FFvR1xmi25jqVfJoYozScxEnIg2H8SAV4HT/6D5zdSZwdfrABXL1OpyTy6ssyhk/H5TQwyVEvmP2ZetxDw929AsR2VvmoelmAOvmlvlJoKkL106Mhn6hmrwYUiA0QiK5CGzQVlcGYJq/Boabq6UQiSFQ68PKcwhdDP1WbcVDn5HB70O0JBj3uILchODQYHNruWXhkIf7j1i+sHbZo4ZH2/kcXLzl675dHuQ1Hlyw+ii/aP0H/OHnj+TVrzt94kn0YoffQKbT0/IGxo/edhcPRD2gDcakA1nJgXU6ZbP5BdOXQ5q9q8+oUI+21X28+hK4cnC8rywHz9oE7P2sBN8Mk8fVBSN4emEDeuXAhoGVopi8+CvDvy6MoA6wFmjUXWi+s4RQL5o89eH7p4nfvmBARSDT+DPi1HOdb57v9+TvRlQNNU4pXm1e6piw8AKR3Pn87jp+6sAn3mekdDHeQ0kUD0RemoI34YDJ2KecAGyAewwVLVPkdr0CjyuVBonXkZUU9JBuHaSlRLLIBtg/ahn4GcrACyNH+ZzdufHYjyFFxqoxcz+LTVUBhsylTR6X2O41+Sh2Fg6lAMejtRZ7cDJxEnp4fcvDGikFNJWPvc7kdofx0uBTIX3gR5/Tziy+AQxvHj9u4cdz4yP1JuemZjsQq0yCai8pmqzyNfrThwCiSn6kq0ZGZnptktKn1Vk7ttJp9iYlWvdoWhyMmMAGmjGqrxnbuvUAiqGGaO4+GiOaRhWgJGTHdwzMqvsTHQFEeJLwr1LrtEq3Zfo0I+e7xm8aP3wR88vTeqXL3mg3LkpJSe6fLzRn96m/13VJgNsvMpeaTi4bgo8xsPlm0c0S/jIEvox9ffhko4ap4yFMWkZzGR342JvCJ0oSMdL0+kU8w5vbO8auLbsmPZrC4Rszy5SK1P6c30APlyyQ38FV3nFNRDvEsrree6vDRRSTVhMbkIOpcPAhErh1TjU5WVJLSd8y2L9Cpxx5Hp77cNi4ET+U5wV5X/wK8/n8JveT0FvRPB/scfHhs38jVx1Hzl1u3fglCj0MhNK7tooMALRb0d6C3QMDRv8CXhtY4ojrqd2AaMIP0OR4QUxu3380QTOgit99hUkOLmbEQJXWIe5ufN4kaXFS9LlDkL8QrBhwlsGa9hfjB8/PkMzEC/z66lIh+6gv8dejYKNPYJTkADvQML9JawY25qR+YDe+nuI9C0KefyTHXPr88oXIiCF3YYyhb5Lig+kIAz6kH9raCdwDYXhb5wTEDPlMQ6dgMADjFGt8qXDyKd0sLYXIvZ+/2XVNLwaEsD/jc3x8Wgjzo9Q74e+X7+4IFUEiXAFAAywrRAEcE6dir7gI1wFQlh9vZFqqOw9OWMwnMIszV7o6jeGT1qeYEUMa5jAKBx8btj2tJVwWpdMuVAOJQ1GxMr4LkU2kInx8k2IT4Io96wCOcbh5dF1BXbkQXkTrHKMcDU9TyiJ+xu80G7FOORKs7rRBnO0G2dMv2iSw6KqzYtGMCvHkmm5zIqXoP/mijFjMEEqAdNPiNR0CCQYUHCVx4OLW/XMFXqudBRxKnSjQah7Rs0kAVTqcZWP7OYx6lwrXgQGqxXMGVqEeuex8vsp5HF99ft+59kAEGgIz3P7nOBAM3Wt2kOI562F86b82GsZLIi8L81RvH9nnzIajXqORpTXfZ++EsKzWzoMvGqVIy2OpPN2lYJXntoH5nHwFmrVJiUCqbDtpwOr5CNa9YpgpVf7xBCUkVVIP+Ql++Lr5AcP0v8VEgOreamTSCjgPI7prLjT9XIF0GzFyQdeOZROsy6yGmGC4QgJ50gk+CCQt74/d//GpFxHoE/ehD34TB/MhHYPggYD745Xl03xuS3/dip5699Uv0I9jXoJiGiltPnGg9IWHgqi3feWT37wYP3P0ImhuZdeveFFTquArWXQaK4H50En0Uqd+shgs2gvJlkhPkITKuIOlf/Jt0R8HOeNzQCoJsGRFTBMkYYqnOJxQsHomNGAIRrA01h+dBjw0QsyAvCVhw2TnGYIZqwLFb0Reo/9xe+gF3zFAoFqmyvl0S2CgkVvtGSjWKRN4yplizXW/y1Wb6JlS5SktkePlkzrT2efDGwSeO7JuTlC3tlzt6apLmtpsAJikcHHnPRfR1BwNyr2wEI0B/kD0e/UXN6oYvgrl/6CPFjB/ghzsFS778pX7ZQ4qTBJnPA7le6VDQq6TsxOGK0uzUqun+sW8/6nbXD3wIjFkwBM1Br63rYC4fn9IDxz+IWwCPHI6quBL1Tzw/Banhh5sQPAI/2xt/N2CEFEohoPcXQQ/1FqjnLxx75RD6Znr1DRx3Q/V0YDz0yrGV6MyDKerH0O8/30L6xtPsA6AA3Htw28xlNy07+MbrB5dvXT5n6+188vzd68a37sza2Tp+3e75c1cA6d7vQOWJp0lPAsvbrzSjh9eWjygGkz//M5hcUt/3RnQ8uj7R4u/2PZPN+JlyZgD1d+MQV62YbSGlxoUk+hZBvUvC6hm8OiFAZgQGx8xSkk2+G6ByP6LhChx0UYuJYtv6D/dOeaQQ3F/8BTr7wAsPfn7ft7m6cW8A47P/LAfPgUSbhul4IjRzZH71tAGzR8zdvfLt/r6rr08atfj2Vc94J4Mr8CJ/8dZdf4Kji/N3vzZ+xN0/bq5fAoTFR/o8CGb+PAx9iyeciWCpNTi5YslDT4PH6ycPyHtwwda2NaPG1w/6eMsZOPiWl1+OydrCguhnhOACXHdn03TNnqE/fnOaMaiu0l1LibijGbEDuhnRTjcjQGPETjYtJaGKCcDO0oTtZE+TPdMu6sDE9hzCUb0XsVxmPC/+FZfLQnaPDT6ynyYqQeP/0bdndpo7Blie6PV56Hab6J4ajyqX++bXBhSne9Vsgt7AQZ+tZCL6Pr+ykvsKFOFT/hPntSgbGrOGBFfX2LNK05wmud44sk/ukBKfUwfOV/Lh0MjiZZvn3DXxBoPsu7EPz6zM5xPIg61f5Ve+B6ZMyx08oEBprUiqfPno0dND3ZkhlVJhySuwT32s03cNv5LKSwYwDzOv4VlVECFCRF1ookBOlLijZlF0EUeCeIVgFq61XglGTVcsZt5IoYrTaCZ+J83H4tNFLa5EVXYcmQpi8MeiLyZdFL1NvMRrSNJa0c9oJJZvUZwYUgbWbOwsKklNNdvpQMQ1Wrj74NFjd+xdsLAsS8kV+XigTy6cPjm8adetm8OTJHKN0pSOTBXlpmSdRi4rq+DlGi3USysqtDa9SiL07au3JYE3vLnDa9//4f3aumwNkBUVyl19ADtl1t49597d3SuQrNHi1Z5LOXPXoIEz5wwMzd/U+MSWqp073ji9w58ApXKH2ZRq0rHzbLb2CyBjjXfeqpXv1w7P9abKFAqrSibMnhbeu3l9kh6TPtWGB++94yaFZFFpKFTe1LR7xqhkqTQZsGP6r5k+OVBcHMQl5liDC9bREstLK3gt1KgFed8KbYqer+irsyUNXjZ/1vDaceNq62bapUk6bfKUSlAPtzXOOLt7zzmtotAnZVnJrTOmDRhYO6gBTelXteXxia/v3LHDnwYVMrmUt2jgAxrLfJSSNcLgHVc7fFYTOCc1alVWYWxWcYE8L1Gl5UpCvUifSelgJJ9KCPZYGbOESNhcAbMRTwfONC9LfQ6bqW58wEXQZjCHhjs75vbV0Klms6AIcBMwE8y+VMKQEGmBmqVb9XxQ/PJ4oLioAaKNNQEjNUYIlAI1K9FozBpV2foDnyxb/t2Tx6amSTmJXMU3zwWbwcGXwR0KnTHNp9PLTHk63uSw5hiygUQtlfESlgVAMrvQuwZtSnK51ao/Zww1GBRq9/JtuzbOLCtuuHHFjimFprTRElOfoj569EHOmLUnpk+9Z1LfxEjjgIqqETZ175nz+vaRSFIM2uDwfgVlY5eOz5RpZDzglhY8PirjPe2cgvpMtdyQe8AsyFhIFMrJPwi1+RJBCR5MrSjMUihaXEOMRoW59+gMSX79rWNH7BhflZksg+v62v3Q7KoLJvVZNreuoLBq/LC0yOFReTnmxMm5xfdAY95EJl7+68R0kGhpzYmzCY2hK3fZ5naGXFFMS38U45LvcS3qmP6KtXrUWIu60Y4678aEkBBL8dQR74ApLsyFW8Mscw0gi6gNwdQUdemwNBLy2xg9irboolZhXLhVT0wPYahnTjTYrX001NuBj2qxmeLnhEIz0bn7bSzQ32hQ3FYcnhQiouoI8Q2FV4VEEt1VdTbeP1X4uq2GY8CRWBp95D2Oab6mzmJ46PUbqqZ7n/BgzoX2CVcXxJmbUuVO30NRO3SL2fh/1g6jiZX5iy+KNuYvvSRanceuX3xR1m7/75rm9utn13mNWv537WXE66gMpphgxcpE0KRoK0Wt9f+vGoi3IEZulaMWseiXgViXtsb/rllgH8TIZMAuNgjOjWYb6fVfNAbo5HlTonQE0Kk5doqTToBmqxsm6Cyxo9t6lerKSxi3tX0zeETttiLx1CbG46MoV+RI/krc2tR+PdgpJzfH0A9cdKukU2YUgExFGbX7LL0NPABy0HnUgM5DhlRn91l9sv5B0KyJLCQvgbdquJB4H+SAB2rwzbO7SbrlD+J3u/B3/pDOUS6qh0NFUF3ilq6PRZCaYsXqoqZR4AbCRpok78rlO5MzWqm9KQyJVqlMRnL7i0A0UWUpTlprc0byTpoS4rbl/oS/+s5kAghJkcDc1lBy22Wq529lm0WAMJycpGluFuXtUoZvo7rFZCwz4n6yACQeFx/Tmg4EMffFuwK8jte58H+Az8LnyWZ9JJyQELkjcodcbdDhS4gv4Uw4096WAENtjdDOtURa+J+Mjtaw0S50MArFzz/zCqODJ5eAXqoOtsm/5H5WtckvcT+3RrifL7XJ42XDOlwqf2y+EYBE1BfE5XFcJya2GU6GFSk2ZFQGHbILUnwCLQL3VbfLtgekEsjoDSqpBOGTBDPrrSGjFHceA57bjVJAAj1j2A5GbmjFTDoLcIDHPHtsv8YukGFObGwsTPG1nlViZ1HD0yPhJdQUM1gmBMk+M1H3hKIDFfB299P3aOqP86c9glqL0pRGlkvgXWqHxqrW8Lvv/x7cCb4Cd8LqOFhP8Q940b3o0sP6R4rlLFArNGbeoXZZ8/P7ecZEbn0UeB5+mOnyl9ZZbi9FdO1hHxQ7k70TPFxSCZ4b5scJX54e0LqBsbNCRE7tdwfcxLUEH6S+qYhzGBu4bs2+RjPRXe/eumF0UoL3jtXZJf1L3wFT3n0XDCcVHlD9Omot6MtrEjiWB3KohEK+KTPBprjrqS5RB3zq2nqHt39zU9Pbgwsbxw4vn+uWSLd/A/TfoO2P4saQPtZPLcV0htNyGswWSv2WYu+gjBuAZP+Gb49Pm3b8W/odZRzD/wv3QAkjZ1SESuvwH0gE9EzMeBH+D+kPD7gbgCdyAl1kl0dOgAzuMAnDYegSiaVyw7qOZskjfIjSIQlgnGmsm4XEe2tZ1OpVL65vggEcqefNkkfk6GX0P1/cMjmnYdBI/bwhCQ947xw5cYklxxzs65sxTapaVRJaAerb2NZv0CQ0HAhHQAWQ1Ew23Z5xs1S2fjv6dNTV3/1u5HYruEkhZbrh4LBkL4NaALAGB+7AEqaV4Uo/+iiy5aOPQCmeGBhwDC4HmehPkZvQOaabDws8TTAhZkT0eYFibgc9QQ9xtM3jlW6QqCpHQUGIHRZeQ5kcfrzqJFo7vqAzjegGlEHgp3p6fp0DL+SiyUgx2B3K6tTEOXMSU6uVE/12P9pvTwSPOisGFWze1FhjlKuqQPM+CQ8BOOn+i0TKKpPgsoDAQ/Stpd6iVA8gheeaHfWLEktKEhfVOxobj9rzTMFql3rxjYPCUrRBrQRCwyg1ABwn58HGsJKtTUpKUbS/Ogqvg1ilBEqnmQUjukUtg7JRtN5TKf0hez3DiYdRomdIN2Ps0Q2YKDy7y1AGLDxVCSHjxO9iOarcAMjEQqcYEMCLi7ToohSvF42i30F3DALaKDC9C5UX0C5Ui267oPCVLakf2ecDkLmETVCDhfpB2WUNDWtGoydmgpwPe42sX9J6z+g1DQ1lpQ0sZu3lNkXmkSNHMhU2uUKRffuEhgm3m9eMbigta4BP9JqY6C08hK4cOACkh/LyEif1qltafoccylRadrgrF+cyumwwypDdXroU/YW+pAE1KmwKuTwrIyNLLpenKrILZbLCK+Rlo9fQ/ty/A0pewO2STyQPZSzZgiJaDg4bizu0TqLEbB8BJAqqgeAIeLk8vHrqD7Qjb3sZgL1/AfMXzGw7BGY98Mc/vVk1Dn2L7tn50k+Q/fyP+X20cLXUXjasrtJs3nr19YPwi7V/eXvfqD++/kLHiwuO1tmt/Xxoa3AwDFSBxt//AEZM7rNxwpC1Q4qtGgD4YRtuj/VVqlsvItEnMQzuZlF2gnRGYkTSySj5ZMyEiiuYuSFGHMRMRYL5k3/hODtsjBAVc5BGTVgwB9TSUjGhU7fzUbr35GQq6ZxEFy5OHcBzPOPodCxayKVCYo4OOFDIBF2dXgntnMVFXCupOaONk6iCpZUl2xJBNccvRENQx9MxMe7TP4Jjy6HUdqFEgjwgjBa2ggfno08HoR8P347Q/v0AAi+A1SBhCZr+3fI/n7ynqby86Z6Tf2ZvKJkfOAFuiTyhkH+Jvu8ik1fe57SaOaks+tczkRFA9un6HfdGM9m/Z+Ot536gT39HM6LtaMf1bIli7UaxCoIO4NGBVEwDoQPweyIHx7GjW596lrvbuCfyDRiHlO0Pgqlsb7Dh9vaPl7BjIomNE9vvA8PguvaPYe9Y24Wje71k/Ui9lXe6tekM88RShWq54DO+xrxs7OyPO+s6vRWbHDjO6HRgqtMjDaZC4hmGtY1a/AeZ2DkSbjrSFCHRXT+t3V3ktgOtVou+12rj70Fti7brL6IFIaKwhpohTtcEm/BB/IGbDOmEzUo3yHDCcCxaG9nVpGWivh1p/5wtIl6J7FUpcJgtNp7y8TFQN3Hl6Ezz8sQ7l4Mq+IjenYiUKlgm6Q2iBIfMuKRDERVo4vZRisuEmqVSmaBtv8/l1epSLal2XSPmzCmPj/DSsdHeK8eb7NEbLMk5uQnoDvPNDURJp+Fm88yE3Jxki0HvSfbm9LLPMU0uIxUtm2yao7PjfHRar4sbY9fCD6VuaTPPyfXhXnNc6WX2dG1jLHO9utGYFHDXeDL9JVVpI+buP79/7oi0qhJ/pqfGHUgylgzELT+wRJtuL0t3zekV1hsV3XUBBDxyHZQHocoujJbY/fhoqIcSy9phxZFIMYDPbETDnoxsgFuvp51S1jQUqNC/APdsexiowKzrbJYQunEJfxcP5n57MUOYSdTnsEcSw2si+1aibNpsISTeI27pU423Lm8dom84G7CIbt/JY1qPm4qk0rWdUUTMRGd9ybxKv6AVMhOUytRkuWXVe6u3fBaYW2vOCVmqZ5HPwZmHLTjw5i1tf33w+9P7ykDZq38DYy1LDrROsmQmGKxK/cCBemVRuX4SYLZYMi0Gq0o/d65eZbWW6cHTvSeacvMSkll5iW3goNXvrtq9MnmoJZRjrt53ft+Cobec/vuDBz43P/s5evUviS+sfGyXQ6Urt84EcKa1LF1lvaUSJbyRptKXWe995dV7rOU6vTIJ8xDpHQx/mdK++ZhtpDMdGYEiDiPxeMATkxciOCMquamA+iLlPGS73R8TqVFML2cW8HLUyot6M7WxFpuUv7z2yXXrnlz79eJDjt1fz3t29eSAUylLzq2fXZeTJLUkz/VkLN6vzw1MGF+VrFlyy4zMzLFb3li14vT6MW5bdiBHByUGa1G6N9moaXC5Kqdkyd2Va0fX3Di+Kj/NIIeqG9atu2HMunUnNY8tGxwamtVv1Ig6n9qQ19eX7szr7VGn5SXZIJheZ83NcRfmpqmE4JhFN00YumvjpJKiutmzfN6q7BS5XO8OjA5oDQCUDXUluAP5vVMSSwKh4IBAlS/e9k60Wb9mt8DV4zre8TZs1qs76EoT4CPofhXu6WO7EdKR3CUEioZBRw9P2lwc3oyFSmmIBX2nBTxjLwNaL16wA63ZFe8jLV62EL2Ged3t2MFhkNG6e3cruoiP4DtShuauQtED37PgbY/ubu18ami3oseFu/GrxJPhNS3ZzWV5KD4H0PxrbXVN+7A92ucXWycYb5/5W60xv6s+/0ET9NSHcjGlDOMyUCNmCqcOMMNONbdFxffOc6GZCINED3i0jcRwwG6WfORkDYaUq+EUg4F1SsaPujpiFJueCBi6SCIHJjEdbcSTHqbR+Ejgt8LojWSzyWROBiXswParrJDgiPe06fhdByP6miAUKha++9NPo7Z15GSiiES9mSpiWxflkGI6vlGPF3ju8rBeoAYWgw34XLGSm8VR0hk2BIhOCyshk14AsE6qpxn9DFRflujBZsdQ/Ql9pqXULJYO8rYx3kHSxRpyDaZZndAOM4vI0ZUIjhBHF0VuEI6eG+3QWZSJ7zmtfKKrbe34TdMMO8bcL+qo3z9mh2HapvGK/rn3E5gvHJHbnyUtGJnt7dPHC/fjYHsLzLSCI1Ynl2lFjYlpIRwm0AqNtHm6wiYczuSc5CITpnEfoKnguYYF5PaCBjQQ3JlTTMLFuP87cL/8hK65hhGPWE6WbHY5WEehxUyFSSzV/sS9wtkZIr2Eyo3iQhRc2yywvs4QyYH9JIRCLCoWEtBzIRDUyOVcMW9Fzw0XElq0chk7FOHQpxoaepOccEowMETCNCUYOFxIbNFEU0ZDJB8ZET91MOBKS0IHo1SrWxLQs3h604Li2BkfWhKAeA8MInHodOysVIrrzTl4ntkXtdHUUSt7i6CzCKyM1bFENxDg8U8tLPEgpaiabNXeffv2bgTn0FlQiPI7xoMQah7PdMA/hBY8dOrnUw8tCMUC4M9797E79u1tnwTOgUL8/1zkLqZjPDqJTuIHQBMeq2+8uaagYM2boASP1xIxLI7NjA6GvdhZLsYV9OiCHgORDBBFSXyCIx7B/+xgauQL9Ke5YAnaMRdkwqSFx4+D+cePR/6B7ox8Dt9AF+eCpWDpXHQRvhH5XLSliep2EflLJlPAMJ2Sok6JkYSi9xmItIvKC4m0ixBnLnqHZ2pm1tTMjNTQE1fzqYjMt17V1mKw4x6o4uz0HGmM3nmHpKthafIalBoD8ms26ltxJ7ca9Tw+vRCNZpj/B/E+mQF42mNgZGBgYGFkm5DVEhDPb/OVgZudAQQuldqthNH///9n4GRkA3E5GJhAFAA1zwr/AAAAeNpjYGRgYGP4d5eBgZPhPxBwMjIARZABUx0Ak74GcwB42o1Uy2oVQRDteXT3jPHGiyGiBiFKxCjJxhe6kVnEpRsxCwOiiLgRJeBCzKrxM/wPwaUfJeIunpqpmqmuTIgDh+qprq4+9eoquUOHr9x3rvg1ILp5VEAoJllCFglwAxydvwe5P0ja0+eL3718Fei82qM1wZMu5XvAV+g/iU2QM26wh+5q4H+cvSs2c6Bz9eC7I7uK/8e7Jz+kO+eFp7Kp1f3xLDCX2k1Sxxtz3ZHX3NV+KF0BLt+Bg9Nim0HHfh4Q4qRf+DTm7kjnxud5X3pTC7Y76JFUHEMuO7JpTL4lD+p+VyWVh6kmY9xaClc/7e8gJ6+Dqo1P2X0Ud6k5n4rk1jlub2q/ZPkZ+oJt6nAytgsZ7+Q2ouSd0bLPmmtZJteVnDfR1YYr1tvZ3KWBg+2ZqOJXtet0Tvw0V12c4hs5wtcusEANnhHAbRcY/+WOmucl5P3bBdvTpl/UbMpex/O3wP8uny3BsZScsHxDeQLe4rwnwL4IzAX2C5lPrCvIrbl6c17Oy+yLrkhZvh+KHvdWhLPmS9XufvUNsnK1lzly7pHqsRsE6HsEgXrPgA3qQdPDKzYOvncvDG9xReB8yjyL3XgWXHZYju9QZB3XYTOm42P9psJ2fWZWxlklm8a8xzL77WD/MdieZlt5H+Ifd9vOE/OUt7mPq9VnJrlsJv2m1KP9/7eRcEs4M/9NYE3dscd8HmN9Udlpzk+wfznMvXk5rgDvsP+Sed9hPy3kl5a5W8BuleDTvP/GSMmvqkO/BseVxsTfmHVj11xf/l8Lyif3eCl9pd7bkmYU9oH3Sqz7ufAmf175agwH2xPNX/ei5f+5PElvN6YHZD+e0RvR8Bh74Ee2N/Yj7nvfn/05+R/jz2tyCXarkNfm+oLf8ZvNvP654fe0zXvVxrY1Fxf7vo7/D/C7LfqT3z/eSHeWeNqdwm1QkgcAAGAyMjIzcoSEpGiGyJkZmZFnzMgMzQidESIxYkZoSmRmhh/zyMiIzJjziMiZI0ZmxIxzzsyIPDNHZEbUERGZM7I3ZoZmRN7u+r1fu+cBgUDw/yUMRAXJQJY5pDmCOVo/kF/y3Ki5IjAZbAZ75yXPU8/z+ef4983nzvdBciAyiHMBeYFmwWxAdkBDgG1h7EJFYGpgeeDgosRFzEWqoNQgzWL44szFaigdKoGOLMEtaQ3GBtd8g4f5wViw7qWwpXw4Ai6B+0LiQypDDCFuBBLBQdiW0ZcZkTgkA9mCHEICoehQYig/VB86ioKjUlCFqE7U+PLU5eLlE2HksIHwuHBReF+4D52A5qM1aCAiOUIaYYxwRCZGiiKBFawVmhWzUeIo68rYlWMYEcYYjYmmRgujXdgUbD62DeuMgcekxahj7LgUnCYWElu9CrZKu8oSFxsnibOtjlxds9oRn7YGsaYS748X4tvxwFruWv3apwm0hIaE4XWJ6xTrJhKpif3raes9hNoN6A38Dd1J/kk5GzkbO4hQYhKxljj9bWUKNIWYUr6JtqmHhCKJSSqSa3P25tlU2ZakNHhaeZprK22rkRxMZpK7yFayJz04PT6dk96Urk8fzsBllGT0bWNvc2SmZFq2B22vpvhRmBTHjrgdNTssVAZ1IAucRckSZ41ms7/z7kzcaaBhaUKamja5i7hLsstKj6Tz6XK6kQ7kwnNZue254ww8I59hyEPlSfPa8tzMIqZ2N+Ir8W4PK5ul/76JDWN3sWf2sPcYOVBOEqee4/vBlB+Vz81X7AXvLdqr5GK4ZVzXPvS+2n2TPBJPwNPxJgrwBSUFrQUDhaRCYaF9P3o/Z/9QkX8Rs6i+yFoMKSYUlxWb+FA+h6/iuw8QDogEAQKOYPRg8sHmg0BJw6HAQ4RDraVhpfLDiMPyMnhZ4xHkkeZy7VH1UUCYJmwS2iuQFWUVbRX2ypoqbBWrSl01VOWtjqqmVKurzT/miCJFxmOpx3THvLXU2sZay/GM44rjDjH5RNAJZx2yTlc3djL5pOykQ4KSlEkGTuFOSaX+0jqp57T+9Hh9Qr2s3nQGckbZgGsQN5jPgs5mntXJZn/qbRT8XNokkIPlJHmX3HkOfU6p8FOUKGznKecBJVVpuAC9ILmgb/b8QmvBtmguYi/KLrpaea2+X3kqkCpH1XkJf0l+yaLm/cbTIDRdmvHL9MvutvK2jjbPFc4VeXtGu7Tde5VwVaxN0Mqvya4Buihdr27yd2UHqEN4PeF6ix6vN3Qy/iD8CelGd/tusG/Ye1g9ppusm+qb473GXuct6K2MW2YD06A1jN0uvw0YuXcod2x98X26vtF+Yn9Rv/Eu+m7rgPNe5D3FIHywcdD1l9VUeR99X2kGm2lm1YPAB8KhsKGOhzkPJ4bpw72PMI/Yj+q/6rPEWjSW2cf8x4AVa2VaFVbgCeEJ01ZqMz0TPxuyI+xsu8bueo58nv28x5Hs4DnUL5JetL6YccpfQl5yXxpGcCPSV6hXylHG6NjfjWOYsZHXlNeDLrHL8Ab2xjaeMz70Fv5WBvAB4zvSu2Y31M109/7zdKLxfdT75snEyZ5J4APug+iD2YPxiKYCpvBTpVOy6aBpxbTrI+Kj9GPnDGGm/xP4U5MX4xV4TZ9Bn8mf1b5M3+AX+BfSl6b/8i+TDl6HAAAAeNpjYGRgYGpnkmRQZwABJiBmBEIGBgcwnwEAFtQBEQB42o1RPUsDQRB9d4maKAQFCWJ1hVhYJLn4gQSbYIidiIKChXBJLh8kuYt3MWJraWlt5S8Qf4XGzkKw8YdY+XZvk1zkBFl25+3OzJs3swCW8I4YtHgSwAV3gDWkeQuwjhT6CseQwa3CcazjSeEZrOFD4Vnmfis8h0dtUeEEVrRnhZNY1oYKL2BD+1I4hT09ofAL0npJ4Vfk9HOFh0jodwq/YV6/D/BnDKv6A/bhoocbeGihgSaVGyjBwgA20QGRgxr9BvLIwcQ2OzJQRIfLCGX58mbT2rQiu8bIMtkdeou4lj4XXdpj7gauyGAxNqjuo0CG6PjCuHr+jwjjF+epVOFTnYg2sEUtYpuhPqKZjshgk8OXrKKjuuQyGOnKsyk9UXMTOVWiUdU6rRfKqauK4sVjjRpfu1Jvm28WX/uSr8I+JiwOrbhVpcpgpp5kmVYe9WtNydnjBLNco/rWVF5GVvp/ZJYTCtQ4suMsznhWQt2ZjMxRp+jFwCHfB2ruwrfDGiZ2eW5yTf6jTRabClyZJ7jKY8YTXHImLXrEj3R+AFcTjTsAAAB42n1XBZgbR9LdqhattLuGMDPTrqQercJOHIeZURlJLWmskWY8sOBjzF04uRwzMzMzc46ZGXLMVG9mZK+///t+f+vu6p5+DfVeV7WmeOr//ce3SUFTPKWIp+6eumPq9qm7pu6duo8U5ShPBSpSiaapTBWaoVmao3VTd07dP3UPracNtJF2o91pD9qT9qK9aR/al/aj/ekAOpAOooPpEDqUDqPD6Qg6ko6io+kYOpaOo+PpBDqRTqJ5WqAq1ahOmixq0CI16WQ6hU6l0+h0OoPOpE10Fp1Nm+kc2kLn0nl0Pl1AF9JFdDFdQpfSZXQ5XUFX0lV0NV1D19J1dD3dQDfSTXQz3UItupVsalOHumSoR30akENbaUgujWhMHvm0bWpu6qGpWQoopIhiWqJlWqFV2k4Po4fTI+iR9Ch6ND2GHkuPo8fTE+iJdBs9iZ5Mt9MddCfdRXfTPXQv3Uf301PoAXoqPY2eTs+gZ9Kz6Nn0HHouPY+eTy+gF9KL6MX0EnopvYxeTq+gV9Kr6NX0GnotvY5eT2+gN9Kb6M30FnorvY3eTu+gd9K76N30HnovvY/eTx+gD9KH6MP0EfoofYw+Tp+gT9Kn6NP0GfosfY4+T1+gL9KD9CX6Mn2Fvkpfo6/TN+ib9C36Nn2Hvkvfo+/TD+iH9CP6Mf2Efko/o5/TL+iX9Cv6Nf2GfksP0e/o9/QH+iP9if5Mf6G/0t/o7/QP+if9i/5N/6H/8hQTMyvOcZ4LXOQST3OZKzzDszzH63g9b+CNvBvvznvwnrzX1KG8N+/D+/J+vD8fwAfyQXwwH8KH8mF8OB/BR/JRfDQfw8fycXw8n8An8kk8zwtc5RrXWbPFDV7kJp/Mp/CpfBqfzmfwmbyJz+KzeTOfw1v4XD6Pz+cL+EK+iC/mS/hSvowv5yv4Sr6Kr+Zr+Fq+jq/nG/hGvolv5lu4xbeyze2pB7nDXTbc4z4P2OGtPGSXRzxmj33exgGHHHHMS7zMK7zK2/lh/HB+BD+SH8WP5sfwY/lx/Hh+Aj+Rb+Mn8ZP5dr6D7+S7+G6+h+/l+/h+fgo/wE/lp/HT+Rn8TH4WP5ufw8/l5/Hz+QX8Qn4Rv5hfwi/ll/HL+RX8Sn4Vv5pfw6/l1/Hr+Q38Rn4Tv5nfwm/lt/Hb+R38Tn4Xv5vfw+/l9/H7+QP8Qf4Qf5g/wh/lj/HH+RP8Sf4Uf5o/w5/lz/Hn+Qv8RX6Qv8Rf5q/wV/lr/HX+Bn+Tv8Xf5u/wd/l7/H3+Af+Qf8Q/5p/wT/ln/HP+Bf+Sf8W/5t/wb/kh/h3/nv/Af+Q/8Z/5L/xX/hv/nf/B/+R/8b/5P/xfJaFBsVIqp/KqoIqqpKZVWVXUjJpVc2qdWq82qI1qN7W72kPtqfZSe6t91L5qP7W/OkAdqA5SB6tD1KHqMHW4OkIdqY5SR6tj1LHqOHW8OkGdqE5S82pBVVVN1ZVWlmqoRdVUJ6tT1KnqNHW6OkOdqTaps9TZarM6R21R56rz1PnqAnWhukhdrC5Rl6rL1OXqCnWlukpdra5R16rr1PXqBnWjukndrG5RLXWrslVbdVRXGdVTfTVQjtqqhspVIzVWnvLVNhWoUEUqnnqgGI+d+flN86ir8/OTeiGrq1ldy+p6VuustrK6kdWLWd3M6k1pXd2S1jqt9Zaz833XDsP8KA6dTiE0dtAZlMx4ybieb/IDaUe5MLKDMoqWGfnRai4OTZDrOe6oFA1arh30DUeDImwnjNgbFgIz8pZMcbvnjVrOuJTUXhwpr9crhE5/bLuq4/XzUWCHg9zAG5mSzGZathvlImdkcoFnd2e63vLYFQPdpUmjEPuo8s647a1UfNdebXWcoOMaWdM3dlQMTC8w4aCErSQTul5nmOu5dr8sh+n6A29swvKS58Yj05L9VDITC0xnduwXtgUdr2uKbTupVWT3c/I/zLU9b1hCMbKDYd4PnHFU6NgjE9i5njeO5LvbLTiR7TqdSmRWotbAOP1BVE7sZacbDcryrT9uuaYXzaRmx4wjE1TSRoDhs6m9NQ4jp7eaw1kqzrgr41JcZidj53p2x8BrrSWna7yi73SiODAF34w7jlse2X4LezVBwe5iQvGw7NN0nSgfDuzA5DsDIx4CYbNhZPxW2+4Ml+2gO9uzxYWTVmli5OD0vG+LCEQYnl/seQH6Z5Lhk0YyU9bIm62mE83IOkuBl558dtJIjjDtu3HYgjDKI2ecmZVURIld9IZJPbstNuISwaE17Yx7XgoLO4Ex43DgRbMZLFXFtABTq9y2xxPTDgJvOdlHJTWTXZRSO/az74kiEhdBR7Kd0NluWr3YdWcyOxzZrrverHRce2Tv2Fau7/REdsbuyR0JTMmsitCEjWkYHdcLzYx4ZeyM+8nwvPhzbEod2zXjrh0UAnvc9UbFjjcaCceFkd0fm6g88Vfs7/Aj9idyj5aNiWbl6L6PKTtyYWd6okITpItVsga2sC7b+JIJIkdW3JC1B17gbBf52u60KL7VGWCSaNmJRJep4yEyyD5pzaSKb8nigaeGZjUntzksZVsOZ6NBPGqHslc4bl3WwnbRnk4CycB2e5UkuqQxpYh5JUTMus54KOJMXVn043Agx5qV22MCCRstfE5CiDMuyOL+YLXSd2SFdqqDNDpgmbwrOhDn4r5XEomnC81NLm/aLCcD0sWyA5cmZy2kMxfiMWJIRSQmlwYO7qogDNWgK5dC1CDOG+faxnUrHbi1J46NTHkgNGbqTkyorZhYsZ/2wCEbUkW2dipy4y49yQTrdumK/V1BmEZiuNc2heVA7vwgH9nhMCxIRJXDTLcDx/Q6dmjKUG56T/L9wIv9HHyZF43E3ULb2BIhVCeOhEpfvGL7iX4cPxfaS6YM/7TaItShKM4LRE8cu+y5EjECZ2iigUzYH0zHEpcCmdbIHtquyYt4nY6E+bgznBYaZT9yfed2WInb1/c9ry+n2REDKms68sKhWS2Lz02UnLSUmnJJUyO5xKmZ+ErujYTwcZgLvUCkJkV6TxJLLs8ksyVJZaK1nOzbE8H0Rf9dSUltTziuZHLGyJmJtJOMIjE+Er1GRmJrSbQdCPe2RESJeWUXm2iJLNoliQvCc9/MJS5uTTLYTNpMlVpEKm2NuhXBRgMvFOebUhg7ERgrQVRYsdCRRGWMZBhPojIyZZJOcIR27Lhygn5JwD7yzrQ9ktXtcccURqY7dKJKD1uSVbYa2bqRPDBIw1Rvvmc2dL24DSmN4fFEf7v0pPrbpUv0t0sb5yrvxFfWAEsTRHnn0GLXhENJGwXX9lElQolmRl4b50pu40ym70Rv5W2xF2VTp2bKs5x2PJbDpGPzkv3d1XIWCsQx69eGwCQMrQmDaJfNio9bmLIrBPrpuHw4ko3ke3K1xmpkBsW+xDrf7pYkzCW6KOEtgZFziZGEFlFztyQ+luxluzm8GKaTDckwd92OeJcFIAkmabJI7m+uI1FsGhCkyyGCjagy16o2mpU1maUSxnIj5fo6vsg6bqeWDFuszfjx9u3wnWM6RhIoJoQb53aareThNXCM252bJJp0NxuQolqiJtFQ7IQD8Wggwc4g8ax0uhKgsmwTTh4tG3fpyQLU2i4EqLXtJEANopGrc50wrBVEmxIyy2lUzUQskUmy426id8cPnXBNQtqwo2+StHKt2nxtOnn6Yf6CdMp+53a+HJJ0nYb8pLPkGrn0kGFqJIpNvyfPiCSsJ1eiVVuoltOUn2QEufZyrZHZUoHsVIpIF6MbysSB6rd9FYdd5YwDtdVfVUHcVsNgWbWjDp7JZnrHnV2fxKE2hOEP7LbcyFat2ty4ozeScNqOIxPu+X+7cKzZSXcSgzfs0kpiU6tWq6PQM6uSTeN2dpCskVsRmqdXJk+PHWPgzGJXxCKPagnp8tKbBC95Y0m7H9ijQk/etMNA2V0JHQuNhbm2E7VjuD6jQSKhG1TSKula53qy0M4sNbumHftrv0JX69e00yu+LM9cbzksyjUNPKebl4sRr8g2nTZySzhc9SWpeXEQbouFMXkOiFS8Qk/CsmtyKJDAI8dXYQxqLauIHzfOklHtuM9Lw/yycdqe/HAYy58MaFTnkrO3JodHX32PdEuTnOumOQefrLmuF635gL7FmSV5isurNNmT9CzOz6aZLeloeeiqoqihAFeLGoWFooFiEUXys23LwqZ58bW9ID1NgJo1NAFqAtQEqAlQE6BmM9eqzyeINqwqihqKejrbWQtoWCgaKBZRALQwjwJfFwBaAGihjkKjAGIBiAUgFrK9nT2f1cBVgasCVwWuClwVuCpwVeCqWKmGlWpA1ICoAVHLtrc5m3DzQlYnIwCtZUtu1lltZTUmr2OOOlatY9U6Vq0nHwCtZ9BzsLDGwhrTaoA0QBogDZAGSAOksVULCAsICwgLCCvb6pbkG0BWQ/zdS74B1MCHBkANgBr40MAyDSzTsDC4AwvLNIBYBGIRCOiiDl3UoYs6dFGHLurQRR26qC8C0QSiCQREUW8C0aznetWERhGFWMkHICAKLaKQYgFFFUUNRR2FRmGhaKBYRNHMLxkJm2JCEhpzaUhCQxIaktCQhIYkNCShF7BIFYtUgYAYNMSgIQYNMWiIQUMMGmLQEIOGGDTEoCEGDTFohC9dA6IGRA0IaEDXgKgDUQeiDgSo16Beg3oN6jWo16Be14HQQIB3Dd41eNfgXYN3Dd41eNfgXYN3Dd41eNfgXYN3bQFhAQHStQWEBYSQ3qsKQgoghHSxgADpGqTrBhANIEC6BukapGuQrkG6BukapGuQrkG6BukapGuQrkG6BukapGuQrptAIBJoRAKNSKCF9F61YRKZVhfns1pwFqi3QL2VxYPqos5qC50NFIsoZD0LWrLAvwX+LfBvgX8L/Fvg3wL/Fvi3wL8F/i3wb4F/C/xb4N8C/xb4t8C/Bf6tavN/jalaPAAAAAFWT44pAAA=') format('woff');\n" + +" src: url('data:application/font-woff;base64,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') format('woff');\n" + " font-weight: 400;\n" + " font-style: normal;\n" + "}\n" + -".fa::before {\n" + -" font-family: FontAwesome;\n" + -" font-weight: 400;\n" + -" font-style: normal;\n" + -" -webkit-font-smoothing: antialiased;\n" + -" text-decoration: inherit;\n" + -" speak: none;\n" + -" display: inline-block;\n" + -" font-size: 13px;\n" + -" visibility: visible;\n" + -"}\n" + -":root:not(.shortcut-icons) #shortcuts .fa::before {\n" + -" display: none;\n" + -"}\n" + -":root.shortcut-icons #shortcuts .fa::before {\n" + -" font-size: 15px !important;\n" + -" margin-top: -3px !important;\n" + -" position: relative;\n" + -" top: 1px;\n" + -"}\n" + -":root.shortcut-icons #shortcuts .fa, .menu-button .fa {\n" + -" font-size: 0;\n" + -" visibility: hidden;\n" + -"}\n" + -":root.shortcut-icons .shortcut.brackets-wrap::after,\n" + -":root.shortcut-icons .shortcut.brackets-wrap::before {\n" + -" display: none;\n" + -"}\n" + -":root.shortcut-icons #shortcuts a .fa,\n" + -".menu-button .fa,\n" + -".hide-reply-button .fa,\n" + -".hide-thread-button .fa {\n" + -" display: inline;\n" + -"}\n" + ".fa-glass:before {content: \"\\f000\";}\n" + ".fa-music:before {content: \"\\f001\";}\n" + ".fa-search:before {content: \"\\f002\";}\n" + @@ -19237,6 +1099,63 @@ ".fa-bluetooth:before {content: \"\\f293\";}\n" + ".fa-bluetooth-b:before {content: \"\\f294\";}\n" + ".fa-percent:before {content: \"\\f295\";}\n" + +".fa-gitlab:before {content: \"\\f296\";}\n" + +".fa-wpbeginner:before {content: \"\\f297\";}\n" + +".fa-wpforms:before {content: \"\\f298\";}\n" + +".fa-envira:before {content: \"\\f299\";}\n" + +".fa-universal-access:before {content: \"\\f29a\";}\n" + +".fa-wheelchair-alt:before {content: \"\\f29b\";}\n" + +".fa-question-circle-o:before {content: \"\\f29c\";}\n" + +".fa-blind:before {content: \"\\f29d\";}\n" + +".fa-audio-description:before {content: \"\\f29e\";}\n" + +".fa-volume-control-phone:before {content: \"\\f2a0\";}\n" + +".fa-braille:before {content: \"\\f2a1\";}\n" + +".fa-assistive-listening-systems:before {content: \"\\f2a2\";}\n" + +".fa-asl-interpreting:before, .fa-american-sign-language-interpreting:before {content: \"\\f2a3\";}\n" + +".fa-deafness:before, .fa-hard-of-hearing:before, .fa-deaf:before {content: \"\\f2a4\";}\n" + +".fa-glide:before {content: \"\\f2a5\";}\n" + +".fa-glide-g:before {content: \"\\f2a6\";}\n" + +".fa-signing:before, .fa-sign-language:before {content: \"\\f2a7\";}\n" + +".fa-low-vision:before {content: \"\\f2a8\";}\n" + +".fa-viadeo:before {content: \"\\f2a9\";}\n" + +".fa-viadeo-square:before {content: \"\\f2aa\";}\n" + +".fa-snapchat:before {content: \"\\f2ab\";}\n" + +".fa-snapchat-ghost:before {content: \"\\f2ac\";}\n" + +".fa-snapchat-square:before {content: \"\\f2ad\";}\n" + +".fa::before {\n" + +" font-family: FontAwesome;\n" + +" font-weight: 400;\n" + +" font-style: normal;\n" + +" -webkit-font-smoothing: antialiased;\n" + +" text-decoration: inherit;\n" + +" speak: none;\n" + +" display: inline-block;\n" + +" font-size: 13px;\n" + +" visibility: visible;\n" + +"}\n" + +":root:not(.shortcut-icons) #shortcuts .fa::before {\n" + +" display: none;\n" + +"}\n" + +":root.shortcut-icons #shortcuts .fa::before {\n" + +" font-size: 15px !important;\n" + +" margin-top: -3px !important;\n" + +" position: relative;\n" + +" top: 1px;\n" + +"}\n" + +":root.shortcut-icons #shortcuts .fa, .menu-button .fa {\n" + +" font-size: 0;\n" + +" visibility: hidden;\n" + +"}\n" + +":root.shortcut-icons .shortcut.brackets-wrap::after,\n" + +":root.shortcut-icons .shortcut.brackets-wrap::before {\n" + +" display: none;\n" + +"}\n" + +":root.shortcut-icons #shortcuts a .fa,\n" + +".menu-button .fa,\n" + +".hide-reply-button .fa,\n" + +".hide-thread-button .fa {\n" + +" display: inline;\n" + +"}\n" + ".fa-spin::before {\n" + " -webkit-animation:spin 2s infinite linear;\n" + " -moz-animation:spin 2s infinite linear;\n" + @@ -20093,7 +2012,7 @@ ":root.float #updater {\n" + " padding: 0px 3px;\n" + "}\n" + -":root:not(.float) #updater {\n" + +":root:not(.float).shortcut-icons #updater {\n" + " display: inline-block;\n" + " min-width: 12pt;\n" + " text-align: right;\n" + @@ -21046,75 +2965,6 @@ ".boardSubtitle[contenteditable=\"true\"] {\n" + " cursor: text !important;\n" + "}\n" + -"/* Link Title Favicons */\n" + -".linkify.audio {\n" + -" 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;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.clyp {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAwUExURTSY22ey5E2l4KbS75rM7Y3F64C/6f///8zl9nS45r/f9PL5/UGe3bPY8Vqr4v///wNjrzUAAAABYktHRA8YugDZAAAAB3RJTUUH4AINEi85AIH95AAAAE9JREFUCNdjYMAGGBWgDGYHCM2a3hkAZmi0dzSBaKaO9o5moCqmLiCjYzNQyw4QowIodQzI6E0AKcpo72gE6+Jyb1kAMehUA9RktgdYbQYAjGIVNGGXBJkAAAAASUVORK5CYII=') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.dailymotion {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAnUExURQBk3ff6/trp+kKO5wZt3xx54q7P9Ozz/IS17zOG5WKh653E8sbc9/GbbcoAAABZSURBVAjXY2BAASyhDhAGc9oECMOjyAAiESEEYrBYpLWBGcwHxcvBjDDxHelghpF0yDQwY3kVgweEUeEQDWbMEepqAjO8FMsLIeYsU8o+BrbCdWboTAe4AwALXxWGjW41FwAAAABJRU5ErkJggg==') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.gfycat {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAjVBMVEWn3gCo3gSr3w2t4BSu4Bav4Ri35C+45DK45DO55DXA50rA50vB50zC6E/D6FTF6VjG6VvL62vN7G/P7XbQ7XfW74vY8JDa8ZTe8qDe8qLf86Pi9Kzj9K7k9LHp9sDp98Lq98Ps+Mr0++L5/O75/fD6/fH6/fL6/fP7/fT7/fb8/ff8/vj8/vn+/v7///91X4cfAAAAcklEQVR42o3M2xKBUACF4aVQckrIuRJK6H//x2sme4/MuPDfre9i6c/Cc3U5Dj87BuAxsXvGu6JvIIXEHRWwNHCHQNrCzkAFkbSBg4EM8i+Yw7PXBa3zRfuxVyf/Bis7nKwGKAcWxgC8prI5Sc315OlnDfzpDar2S9/oAAAAAElFTkSuQmCC') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.gist {\n" + -" 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;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.image {\n" + -" 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;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.installgentoo {\n" + -" 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;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.liveleak {\n" + -" 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;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.pastebin {\n" + -" 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;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.soundcloud {\n" + -" 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;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.twitchtv {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAYUExURf///2RBpWRBpWRBpWRBpWRBpWRBpf///+zQyUYAAAAGdFJOUwFdZX0lTzs4r5oAAAABYktHRAcWYYjrAAAAB3RJTUUH4AINEi42iSXRNAAAAD1JREFUCNdjYEiDAAZGGIMtjQEEUBlMCWoEGci6mGEMsxQgIy0BiB3AjLS0FAYQIw0kwABipoI1AhkBQBIAFCIXxiHgq80AAAAASUVORK5CYII=') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.twitter {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAEsUExURf///1Cf21Gg3FGi31Gh3VKj4FGh3lKj4VKk4lKl41Ol5FOn51Sp6VSo6FOn5lCf21Gg3FGh3VGi31Gi31Gh3lGg3FGg3FGg3FGg3FGh3lGg3FGi31Kk4lKj4FGh3lGi31Kk4lGh3lGg3FGh3lOm5FOm5VGi31Kj4VSo6FGi31Gh3VGg3FKj4FOn51Gi31So6FWr7VOl5FGi31On51Sq6lKk4lOo51Sp6VOm5FSq61Ws7VOn51Oo51Sq61Ol5FOm5FSq61Wr7VOo51On51Sr7FWs7VSp6lGg3FGh3VOm5FWr7VSp6lKj4VOm5FSo6FSr7FWs7VWs7VWr7VSq6lOo51Om5FOo51So6FOm5VOl5FSq61Ws7VSr7FSp6lSp6VWs7lWr7VKk4lSq6v///6E3MNsAAABVdFJOUwAAAAAAAAAAAAAAAAAAAB0Ii+3xnBVTJhfsMKb+qTEp9GwBF/7lLAbo0m4pLkUTdvk2Ev3+EZnOBo/3Z8ffCRzH/D0OqPxiLnvx3UI8m9n1++GwXQZNS29BAAAAAWJLR0QAiAUdSAAAAAd0SU1FB+ACDRIwBwy67tEAAADKSURBVBjTY2BAB4xogIGRH8IQEBQSFhEVE2eQkJQC8ZmkQ8PCI2Rk5RjkIxUUlRgZlVWioqNjYlXVGNQ14iI1tbR14qLj4+MTdJkZ9PQNosJCE0OjgPz4KEMWBiPjhPiEmKQokIJ4E1MmBmazhHg4MGdlYmCzsLSC8ROsmRkZmFht4Eps7ViADmOzd4DyHZ2YmYACTOzOLmATXd04mIBOd/eQ9owFCXh5c7KB/MLi4+vnHxAYFBzCwcYEEmBi5uLm4eHl42RmAnsSAMZBLgZiFUQ5AAAAAElFTkSuQmCC') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.video {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QAxgDGAP8nNqN7AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gMZBjQQLEEqGwAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAA5SURBVDjLY2AYaMDIwMDwn1JD/lPCZhpwL+B1wf///ykzgBhDiAoDfIYQZQAjIyP5BuDTPJqQqAQAvW0ZAMk8+EEAAAAASUVORK5CYII=') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.vimeo {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAYFBMVEUAAAAIdZUKh6sLlLkLmr4LmsAMp88NrdYVW3MZj7Acstkrt9s1e5E7vN5EfI9JvdtKwuBijp5kpbl30eiDt8aG1uqRr7qTyNehxM+k4PCy3enB3OTg6Ovv9PXw+fz////L9U5WAAAAAXRSTlMAQObYZgAAAIFJREFUeNplz90OwiAMBWAQpAoyxclkP3je/y0H2AQXz0WT8100rRD6kNI9/cRroemQL3hXhoujZYj4OHoAmBvYGcBISwbWBvfXCrytnIDUQMkbsBpagMA7zhtQdyTFQAmIG7IkYniiZuh3XGsPqoOZkMOJOpAcLqUzNFGGu/57fwc1hgtp0mVSyQAAAABJRU5ErkJggg==') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.vine {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAHCUExURQAAAAC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+j////54tRLAAAACUdFJOUwAAAEK+9/e+QQIDAwEqzskfUZmUNHz2mrT++V1w+f5tCanNFUDwfEjtjAyyvg027Hki27QMBJzaHE/1+FkNsN0iZvv6bxyAlB589lQeyud0KB8PQO+ZBUrc+eXgcRG/3CoATe316Wxw/P6BAgBt+fp4IAwh0d4zM9q7Fm76qi605EMSrvfX/PRtAivF9IAJNMLxhA2KYlJ9AAAAAWJLR0SVCGB6gwAAAAd0SU1FB+ACDRI2MOJd7FgAAADrSURBVBjTLY9VWwJgGEPfiYWBha2YYHcHditgd3d3odjdivvBfgK727nYsyPiCrw03j6+fv6AaAMCgyAI1lElJBQSFh6hBxDJqOiY2Lh4SEKiIQlITmFqWrqRJkhGJrOA7Bzm5uUXsBBSVMySUpSVs6KyqrqmFmKuY30D0NjU3NLa1t6h9jvZ1Q30WGi19fb1KzAwyKFhYGSUY+MTkwpMTXNmFpibX+Di0rICWFldW9/A5tb2zu7ePtTrg0MeHePklPYzuDRw7uDF5RWvbwC32O0d7x8en55f4DHF6xv5/vHp6f/k6/vH+evuf1LAObptvSvrAAAAAElFTkSuQmCC') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.vocaroo {\n" + -" 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;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.youtube {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAYAAABr5z2BAAABIklEQVQoz53LvUrDUBjG8bOoOammSf1IoBSvoCB4JeIqOHgBLt6AIMRBBQelWurQ2kERnMRBsBUcIp5FJSBI5oQsJVkkUHh8W0o5nhaFHvjBgef/Mq+Q46RJBMkI/vE+aOus956tnEswIZe1LV0QyJ5sE2GzgZfVMtRNIdiDpccEssdlB1mW4bvTwdvWJtRdErM7U+8S/FJykCRJX5qm+KpVce8UMNLRLbulz4iSjTAMh6Iowsd5BeNadp3nUF0VlxAEwZBotXC0Usa4ll3meZdA1iguwvf9vpvDA2wvmKgYGtSud8suDB4TyGr2PF49D/vra9jRZ1BVdknMzgwuCGSnZEObwu6sBnVTCHZiaC7BhFx2PKdxUidiAH/4lLo9Mv0DELVs9qsOHXwAAAAASUVORK5CYII=') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + "/* Embedding */\n" + "#embedding {\n" + " padding: 1px 4px 1px 4px;\n" + @@ -21874,6 +3724,75 @@ "{\n" + " background-image: url(\"data:image/svg+xml,\");\n" + "}\n" + +"/* Link Title Favicons */\n" + +".linkify.audio {\n" + +" 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;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.clyp {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAwUExURTSY22ey5E2l4KbS75rM7Y3F64C/6f///8zl9nS45r/f9PL5/UGe3bPY8Vqr4v///wNjrzUAAAABYktHRA8YugDZAAAAB3RJTUUH4AINEi85AIH95AAAAE9JREFUCNdjYMAGGBWgDGYHCM2a3hkAZmi0dzSBaKaO9o5moCqmLiCjYzNQyw4QowIodQzI6E0AKcpo72gE6+Jyb1kAMehUA9RktgdYbQYAjGIVNGGXBJkAAAAASUVORK5CYII=') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.dailymotion {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAnUExURQBk3ff6/trp+kKO5wZt3xx54q7P9Ozz/IS17zOG5WKh653E8sbc9/GbbcoAAABZSURBVAjXY2BAASyhDhAGc9oECMOjyAAiESEEYrBYpLWBGcwHxcvBjDDxHelghpF0yDQwY3kVgweEUeEQDWbMEepqAjO8FMsLIeYsU8o+BrbCdWboTAe4AwALXxWGjW41FwAAAABJRU5ErkJggg==') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.gfycat {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAjVBMVEWn3gCo3gSr3w2t4BSu4Bav4Ri35C+45DK45DO55DXA50rA50vB50zC6E/D6FTF6VjG6VvL62vN7G/P7XbQ7XfW74vY8JDa8ZTe8qDe8qLf86Pi9Kzj9K7k9LHp9sDp98Lq98Ps+Mr0++L5/O75/fD6/fH6/fL6/fP7/fT7/fb8/ff8/vj8/vn+/v7///91X4cfAAAAcklEQVR42o3M2xKBUACF4aVQckrIuRJK6H//x2sme4/MuPDfre9i6c/Cc3U5Dj87BuAxsXvGu6JvIIXEHRWwNHCHQNrCzkAFkbSBg4EM8i+Yw7PXBa3zRfuxVyf/Bis7nKwGKAcWxgC8prI5Sc315OlnDfzpDar2S9/oAAAAAElFTkSuQmCC') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.gist {\n" + +" 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;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.image {\n" + +" 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;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.installgentoo {\n" + +" 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;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.liveleak {\n" + +" 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;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.pastebin {\n" + +" 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;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.soundcloud {\n" + +" 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;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.twitchtv {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAYUExURf///2RBpWRBpWRBpWRBpWRBpWRBpf///+zQyUYAAAAGdFJOUwFdZX0lTzs4r5oAAAABYktHRAcWYYjrAAAAB3RJTUUH4AINEi42iSXRNAAAAD1JREFUCNdjYEiDAAZGGIMtjQEEUBlMCWoEGci6mGEMsxQgIy0BiB3AjLS0FAYQIw0kwABipoI1AhkBQBIAFCIXxiHgq80AAAAASUVORK5CYII=') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.twitter {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAEsUExURf///1Cf21Gg3FGi31Gh3VKj4FGh3lKj4VKk4lKl41Ol5FOn51Sp6VSo6FOn5lCf21Gg3FGh3VGi31Gi31Gh3lGg3FGg3FGg3FGg3FGh3lGg3FGi31Kk4lKj4FGh3lGi31Kk4lGh3lGg3FGh3lOm5FOm5VGi31Kj4VSo6FGi31Gh3VGg3FKj4FOn51Gi31So6FWr7VOl5FGi31On51Sq6lKk4lOo51Sp6VOm5FSq61Ws7VOn51Oo51Sq61Ol5FOm5FSq61Wr7VOo51On51Sr7FWs7VSp6lGg3FGh3VOm5FWr7VSp6lKj4VOm5FSo6FSr7FWs7VWs7VWr7VSq6lOo51Om5FOo51So6FOm5VOl5FSq61Ws7VSr7FSp6lSp6VWs7lWr7VKk4lSq6v///6E3MNsAAABVdFJOUwAAAAAAAAAAAAAAAAAAAB0Ii+3xnBVTJhfsMKb+qTEp9GwBF/7lLAbo0m4pLkUTdvk2Ev3+EZnOBo/3Z8ffCRzH/D0OqPxiLnvx3UI8m9n1++GwXQZNS29BAAAAAWJLR0QAiAUdSAAAAAd0SU1FB+ACDRIwBwy67tEAAADKSURBVBjTY2BAB4xogIGRH8IQEBQSFhEVE2eQkJQC8ZmkQ8PCI2Rk5RjkIxUUlRgZlVWioqNjYlXVGNQ14iI1tbR14qLj4+MTdJkZ9PQNosJCE0OjgPz4KEMWBiPjhPiEmKQokIJ4E1MmBmazhHg4MGdlYmCzsLSC8ROsmRkZmFht4Eps7ViADmOzd4DyHZ2YmYACTOzOLmATXd04mIBOd/eQ9owFCXh5c7KB/MLi4+vnHxAYFBzCwcYEEmBi5uLm4eHl42RmAnsSAMZBLgZiFUQ5AAAAAElFTkSuQmCC') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.video {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QAxgDGAP8nNqN7AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gMZBjQQLEEqGwAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAA5SURBVDjLY2AYaMDIwMDwn1JD/lPCZhpwL+B1wf///ykzgBhDiAoDfIYQZQAjIyP5BuDTPJqQqAQAvW0ZAMk8+EEAAAAASUVORK5CYII=') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.vimeo {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAYFBMVEUAAAAIdZUKh6sLlLkLmr4LmsAMp88NrdYVW3MZj7Acstkrt9s1e5E7vN5EfI9JvdtKwuBijp5kpbl30eiDt8aG1uqRr7qTyNehxM+k4PCy3enB3OTg6Ovv9PXw+fz////L9U5WAAAAAXRSTlMAQObYZgAAAIFJREFUeNplz90OwiAMBWAQpAoyxclkP3je/y0H2AQXz0WT8100rRD6kNI9/cRroemQL3hXhoujZYj4OHoAmBvYGcBISwbWBvfXCrytnIDUQMkbsBpagMA7zhtQdyTFQAmIG7IkYniiZuh3XGsPqoOZkMOJOpAcLqUzNFGGu/57fwc1hgtp0mVSyQAAAABJRU5ErkJggg==') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.vine {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAHCUExURQAAAAC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+j////54tRLAAAACUdFJOUwAAAEK+9/e+QQIDAwEqzskfUZmUNHz2mrT++V1w+f5tCanNFUDwfEjtjAyyvg027Hki27QMBJzaHE/1+FkNsN0iZvv6bxyAlB589lQeyud0KB8PQO+ZBUrc+eXgcRG/3CoATe316Wxw/P6BAgBt+fp4IAwh0d4zM9q7Fm76qi605EMSrvfX/PRtAivF9IAJNMLxhA2KYlJ9AAAAAWJLR0SVCGB6gwAAAAd0SU1FB+ACDRI2MOJd7FgAAADrSURBVBjTLY9VWwJgGEPfiYWBha2YYHcHditgd3d3odjdivvBfgK727nYsyPiCrw03j6+fv6AaAMCgyAI1lElJBQSFh6hBxDJqOiY2Lh4SEKiIQlITmFqWrqRJkhGJrOA7Bzm5uUXsBBSVMySUpSVs6KyqrqmFmKuY30D0NjU3NLa1t6h9jvZ1Q30WGi19fb1KzAwyKFhYGSUY+MTkwpMTXNmFpibX+Di0rICWFldW9/A5tb2zu7ePtTrg0MeHePklPYzuDRw7uDF5RWvbwC32O0d7x8en55f4DHF6xv5/vHp6f/k6/vH+evuf1LAObptvSvrAAAAAElFTkSuQmCC') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.vocaroo {\n" + +" 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;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.youtube {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAYAAABr5z2BAAABIklEQVQoz53LvUrDUBjG8bOoOammSf1IoBSvoCB4JeIqOHgBLt6AIMRBBQelWurQ2kERnMRBsBUcIp5FJSBI5oQsJVkkUHh8W0o5nhaFHvjBgef/Mq+Q46RJBMkI/vE+aOus956tnEswIZe1LV0QyJ5sE2GzgZfVMtRNIdiDpccEssdlB1mW4bvTwdvWJtRdErM7U+8S/FJykCRJX5qm+KpVce8UMNLRLbulz4iSjTAMh6Iowsd5BeNadp3nUF0VlxAEwZBotXC0Usa4ll3meZdA1iguwvf9vpvDA2wvmKgYGtSud8suDB4TyGr2PF49D/vra9jRZ1BVdknMzgwuCGSnZEObwu6sBnVTCHZiaC7BhFx2PKdxUidiAH/4lLo9Mv0DELVs9qsOHXwAAAAASUVORK5CYII=') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + "/* XXX Moved to end of stylesheet to avoid breaking whole stylesheet in Maxthon. */\n" + "@supports (text-decoration-style: dashed) or (-moz-text-decoration-style: dashed) {\n" + " .quotelink.forwardlink,\n" + @@ -21883,13 +3802,18839 @@ " text-decoration-style: dashed;\n" + " border-bottom: none;\n" + " }\n" + -"}", - cssWWW: "#captcha-cnt {\n" + +"}\n", + +report: +"#g-recaptcha,\n" + +":root:not(.js-enabled) #captchaContainerAlt {\n" + " height: auto;\n" + -"}", - features: [['Polyfill', Polyfill], ['Normalize URL', NormalizeURL], ['Captcha Configuration', Captcha.replace], ['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], ['Thread Links', ThreadLinks], ['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], ['Cooldown', QR.cooldown], ['Pass Link', PassLink], ['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], ['Edit Link', QR.oekaki.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], ['Flash Features', Flash], ['Reply Pruning', ReplyPruning]] +"}\n" + +"#captchaContainerAlt td:nth-child(2) {\n" + +" display: table-cell !important;\n" + +"}\n", + +www: +"#captcha-cnt {\n" + +" height: auto;\n" + +"}\n" + +}; + +$ = (function() { + var $, + 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; }; + + $ = function(selector, root) { + if (root == null) { + root = d.body; + } + return root.querySelector(selector); }; - Main.init(); + $.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: "4chan X was blocked from loading the following URL:

        [More info]" + }); + $('span', message).textContent = (/^\/\//.test(url) ? location.protocol : '') + url; + return new Notice('warning', message, 30, function() { + return delete blockedURLs[url]; + }); + }; + return function(url, options, extra) { + var err, event, form, i, len, r, ref, ref1, type, upCallbacks, whenModified; + if (options == null) { + options = {}; + } + if (extra == null) { + extra = {}; + } + type = extra.type, whenModified = extra.whenModified, upCallbacks = extra.upCallbacks, form = extra.form; + url = url.replace(/^((?:https?:)?\/\/(?:\w+\.)?4c(?:ha|d)n\.org)\/adv\//, '$1//adv/'); + r = new XMLHttpRequest(); + type || (type = form && 'post' || 'get'); + try { + r.open(type, url, true); + } catch (_error) { + err = _error; + blockedError(url); + ref = ['error', 'loadend']; + for (i = 0, len = ref.length; i < len; i++) { + event = ref[i]; + r["on" + event] = options["on" + event]; + $.queueTask($.event, event, null, r); + } + return; + } + if (whenModified) { + if (((ref1 = lastModified[whenModified]) != null ? ref1[url] : void 0) != null) { + r.setRequestHeader('If-Modified-Since', lastModified[whenModified][url]); + } + $.on(r, 'load', function() { + return (lastModified[whenModified] || (lastModified[whenModified] = {}))[url] = r.getResponseHeader('Last-Modified'); + }); + } + if (/\.json$/.test(url)) { + if (options.responseType == null) { + options.responseType = 'json'; + } + } + $.extend(r, options); + if (options.responseType === 'json' && r.responseType !== 'json' && delete r.response) { + Object.defineProperty(r, 'response', { + configurable: true, + enumerable: true, + get: function() { + return JSON.parse(r.responseText); + } + }); + } + $.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, true); + }); + } 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 fn1, i, len, ref; + this.evt = e; + ref = this.callbacks; + fn1 = (function(_this) { + return function(cb) { + return $.queueTask(function() { + return cb.call(_this, e, false); + }); + }; + })(this); + for (i = 0, len = ref.length; i < len; i++) { + cb = ref[i]; + fn1(cb); + } + 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, cb) { + var el, observer; + if (el = $(selector, root)) { + return cb(el); + } + if ($.engine === 'edge' && d.readyState === 'loading') { + $.asap((function() { + return d.readyState !== 'loading' || $(selector, root); + }), function() { + return $.onExists(root, selector, cb); + }); + return; + } + observer = new MutationObserver(function() { + if (el = $(selector, root)) { + observer.disconnect(); + return cb(el); + } + }); + return observer.observe(root, { + childList: true, + subtree: true + }); + }; + + $.addStyle = function(css, id, test) { + var style; + if (test == null) { + test = 'head'; + } + style = $.el('style', { + textContent: css + }); + if (id != null) { + style.id = id; + } + $.onExists(doc, 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 != null ? el.remove() : void 0; + }; + + $.rmAll = function(root) { + return root.textContent = null; + }; + + $.tn = function(s) { + return d.createTextNode(s); + }; + + $.frag = function() { + return d.createDocumentFragment(); + }; + + $.nodes = function(nodes) { + var frag, i, len, node; + 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, properties2) { + var el; + el = d.createElement(tag); + if (properties) { + $.extend(el, properties); + } + if (properties2) { + $.extend(el, properties2); + } + 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 + })); + }; + + (function() { + var clone, err, ref, unsafeConstructors; + if (!(/PaleMoon\//.test(navigator.userAgent) && +(typeof GM_info !== "undefined" && GM_info !== null ? (ref = GM_info.version) != null ? ref.split('.')[0] : void 0 : void 0) >= 2 && typeof cloneInto === 'undefined')) { + return; + } + try { + return new CustomEvent('x', { + detail: {} + }); + } catch (_error) { + err = _error; + unsafeConstructors = { + Object: unsafeWindow.Object, + Array: unsafeWindow.Array + }; + clone = function(obj) { + var constructor, key, obj2, val; + if ((obj != null) && typeof obj === 'object' && (constructor = unsafeConstructors[obj.constructor.name])) { + obj2 = new constructor(); + for (key in obj) { + val = obj[key]; + obj2[key] = clone(val); + } + return obj2; + } else { + return obj; + } + }; + return $.event = function(event, detail, root) { + if (root == null) { + root = d; + } + return root.dispatchEvent(new CustomEvent(event, { + bubbles: true, + detail: clone(detail) + })); + }; + } + })(); + + $.open = typeof GM_openInTab !== "undefined" && GM_openInTab !== null ? GM_openInTab : function(url) { + return window.open(url, '_blank'); + }; + + $.debounce = function(wait, fn) { + var args, exec, lastCall, that, timeout; + lastCall = 0; + timeout = null; + that = null; + args = null; + exec = function() { + lastCall = Date.now(); + return fn.apply(that, args); + }; + return function() { + args = arguments; + that = this; + if (lastCall < Date.now() - wait) { + return exec(); + } + clearTimeout(timeout); + return timeout = setTimeout(exec, wait); + }; + }; + + $.queueTask = (function() { + var execTask, taskChannel, taskQueue; + taskQueue = []; + execTask = function() { + var args, func, task; + task = taskQueue.shift(); + func = task[0]; + args = Array.prototype.slice.call(task, 1); + return func.apply(func, args); + }; + if (window.MessageChannel) { + taskChannel = new MessageChannel(); + taskChannel.port1.onmessage = execTask; + return function() { + taskQueue.push(arguments); + return taskChannel.port2.postMessage(null); + }; + } else { + return function() { + taskQueue.push(arguments); + return setTimeout(execTask, 0); + }; + } + })(); + + $.globalEval = function(code) { + var script; + script = $.el('script', { + textContent: code + }); + $.add(d.head || doc, script); + return $.rm(script); + }; + + $.global = function(fn) { + if (doc) { + return $.globalEval("(" + fn + ")();"); + } else { + return fn(); + } + }; + + $.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; + }; + + $.engine = (function() { + if (/Edge\//.test(navigator.userAgent)) { + return 'edge'; + } + if (/Chrome\//.test(navigator.userAgent)) { + return 'blink'; + } + if (/WebKit\//.test(navigator.userAgent)) { + return 'webkit'; + } + if (/Gecko\/|Goanna/.test(navigator.userAgent)) { + return 'gecko'; + } + })(); + + $.platform = 'userscript'; + + try { + localStorage.getItem('x'); + $.hasStorage = true; + } catch (_error) { + $.hasStorage = false; + } + + $.item = function(key, val) { + var item; + item = {}; + item[key] = val; + return item; + }; + + $.syncing = {}; + + if (typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null) { + $.getValue = GM_getValue; + $.listValues = function() { + return GM_listValues(); + }; + } else if ($.hasStorage) { + $.getValue = function(key) { + return localStorage[key]; + }; + $.listValues = function() { + var key, results; + results = []; + for (key in localStorage) { + if (key.slice(0, g.NAMESPACE.length) === g.NAMESPACE) { + results.push(key); + } + } + return results; + }; + } else { + $.getValue = function() {}; + $.listValues = function() { + return []; + }; + } + + if (typeof GM_addValueChangeListener !== "undefined" && GM_addValueChangeListener !== null) { + $.setValue = GM_setValue; + $.deleteValue = GM_deleteValue; + } else if (typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null) { + $.oldValue = {}; + $.setValue = function(key, val) { + GM_setValue(key, val); + if (key in $.syncing) { + $.oldValue[key] = val; + if ($.hasStorage) { + return localStorage[key] = val; + } + } + }; + $.deleteValue = function(key) { + GM_deleteValue(key); + if (key in $.syncing) { + delete $.oldValue[key]; + if ($.hasStorage) { + return localStorage.removeItem(key); + } + } + }; + if (!$.hasStorage) { + $.cantSync = true; + } + } else if ($.hasStorage) { + $.oldValue = {}; + $.setValue = function(key, val) { + if (key in $.syncing) { + $.oldValue[key] = val; + } + return localStorage[key] = val; + }; + $.deleteValue = function(key) { + if (key in $.syncing) { + delete $.oldValue[key]; + } + return localStorage.removeItem(key); + }; + } else { + $.setValue = function() {}; + $.deleteValue = function() {}; + $.cantSync = $.cantSet = true; + } + + if (typeof GM_addValueChangeListener !== "undefined" && GM_addValueChangeListener !== null) { + $.sync = function(key, cb) { + return $.syncing[key] = GM_addValueChangeListener(g.NAMESPACE + key, function(key2, oldValue, newValue, remote) { + if (remote) { + if (newValue !== void 0) { + newValue = JSON.parse(newValue); + } + return cb(newValue, key); + } + }); + }; + $.forceSync = function() {}; + } else if ((typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null) || $.hasStorage) { + $.sync = function(key, cb) { + key = g.NAMESPACE + key; + $.syncing[key] = cb; + return $.oldValue[key] = $.getValue(key); + }; + (function() { + var onChange; + onChange = function(arg) { + var cb, key, newValue; + key = arg.key, newValue = arg.newValue; + if (!(cb = $.syncing[key])) { + return; + } + if (newValue != null) { + if (newValue === $.oldValue[key]) { + return; + } + $.oldValue[key] = newValue; + return cb(JSON.parse(newValue), key.slice(g.NAMESPACE.length)); + } else { + if ($.oldValue[key] == null) { + return; + } + delete $.oldValue[key]; + return cb(void 0, key.slice(g.NAMESPACE.length)); + } + }; + $.on(window, 'storage', onChange); + return $.forceSync = function(key) { + key = g.NAMESPACE + key; + return onChange({ + key: key, + newValue: $.getValue(key) + }); + }; + })(); + } else { + $.sync = function() {}; + $.forceSync = function() {}; + } + + $["delete"] = function(keys) { + var i, key, len; + if (!(keys instanceof Array)) { + keys = [keys]; + } + for (i = 0, len = keys.length; i < len; i++) { + key = keys[i]; + $.deleteValue(g.NAMESPACE + 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 = $.getValue(g.NAMESPACE + key)) { + items[key] = JSON.parse(val); + } + } + return cb(items); + }); + }; + + $.set = function(keys, val, cb) { + var key, value; + if (typeof keys === 'string') { + $.setValue(g.NAMESPACE + keys, JSON.stringify(val)); + } else { + for (key in keys) { + value = keys[key]; + $.setValue(g.NAMESPACE + key, JSON.stringify(value)); + } + cb = val; + } + return typeof cb === "function" ? cb() : void 0; + }; + + $.clear = function(cb) { + var id; + $["delete"](Object.keys(Conf)); + $["delete"](['previousversion', 'AutoWatch', '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; + })()); + try { + $["delete"]($.listValues().map(function(key) { + return key.replace(g.NAMESPACE, ''); + })); + } catch (_error) {} + return typeof cb === "function" ? cb() : void 0; + }; + + return $; + +}).call(this); + +$$ = (function() { + var slice = [].slice; + + return function(selector, root) { + if (root == null) { + root = d.body; + } + return slice.call(root.querySelectorAll(selector)); + }; + +}).call(this); + +CrossOrigin = (function() { + var CrossOrigin; + + CrossOrigin = { + binary: function(url, cb, headers) { + var options, ref, workaround; + if (headers == null) { + headers = {}; + } + url = url.replace(/^((?:https?:)?\/\/(?:\w+\.)?4c(?:ha|d)n\.org)\/adv\//, '$1//adv/'); + workaround = $.engine === 'gecko' && (typeof GM_info !== "undefined" && GM_info !== null) && /^[0-2]\.|^3\.[01](?!\d)/.test(GM_info.version); + workaround || (workaround = /PaleMoon\//.test(navigator.userAgent)); + workaround || (workaround = (typeof GM_info !== "undefined" && GM_info !== null ? (ref = GM_info.script) != null ? ref.includeJSB : void 0 : void 0) != null); + options = { + method: "GET", + url: url, + headers: headers, + onload: function(xhr) { + var contentDisposition, contentType, data, i, r, ref1, ref2; + if (workaround) { + r = xhr.responseText; + data = new Uint8Array(r.length); + i = 0; + while (i < r.length) { + data[i] = r.charCodeAt(i); + i++; + } + } else { + data = new Uint8Array(xhr.response); + } + if (typeof xhr.responseHeaders === 'object') { + contentType = xhr.responseHeaders['Content-Type']; + contentDisposition = xhr.responseHeaders['Content-Disposition']; + } else { + contentType = (ref1 = xhr.responseHeaders.match(/Content-Type:\s*(.*)/i)) != null ? ref1[1] : void 0; + contentDisposition = (ref2 = xhr.responseHeaders.match(/Content-Disposition:\s*(.*)/i)) != null ? ref2[1] : void 0; + } + return cb(data, contentType, contentDisposition); + }, + onerror: function() { + return cb(null); + }, + onabort: function() { + return cb(null); + } + }; + if (workaround) { + options.overrideMimeType = options.mimeType = 'text/plain; charset=x-user-defined'; + } else { + options.responseType = 'arraybuffer'; + } + return GM_xmlhttpRequest(options); + }, + file: function(url, cb) { + return CrossOrigin.binary(url, function(data, contentType, contentDisposition) { + var blob, match, mime, name, ref, ref1, ref2, ref3; + 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, '"'); + } + if ((typeof GM_info !== "undefined" && GM_info !== null ? (ref3 = GM_info.script) != null ? ref3.includeJSB : void 0 : void 0) != null) { + mime = QR.typeFromExtension[name.match(/[^.]*$/)[0].toLowerCase()] || 'application/octet-stream'; + } + 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 j, len, ref, response; + response = JSON.parse(xhr.responseText); + ref = callbacks[url]; + for (j = 0, len = ref.length; j < len; j++) { + cb = ref[j]; + cb(response); + } + delete callbacks[url]; + return responses[url] = response; + }, + onerror: function() { + return delete callbacks[url]; + }, + onabort: function() { + return delete callbacks[url]; + } + }); + }; + })() + }; + + return CrossOrigin; + +}).call(this); + +Board = (function() { + var Board; + + 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; + + })(); + + return Board; + +}).call(this); + +Callbacks = (function() { + var Callbacks; + + Callbacks = (function() { + Callbacks.Post = new Callbacks('Post'); + + Callbacks.Thread = new Callbacks('Thread'); + + Callbacks.CatalogThread = new Callbacks('Catalog Thread'); + + 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, keys) { + var err, errors, i, len, name, ref; + if (keys == null) { + keys = this.keys; + } + for (i = 0, len = keys.length; i < len; i++) { + name = keys[i]; + try { + if ((ref = this[name]) != null) { + ref.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; + + })(); + + return Callbacks; + +}).call(this); + +CatalogThread = (function() { + var CatalogThread; + + CatalogThread = (function() { + 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; + + })(); + + return CatalogThread; + +}).call(this); + +Connection = (function() { + var Connection, + bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + + Connection = (function() { + function Connection(target, origin, cb) { + this.target = target; + this.origin = origin; + this.cb = cb != null ? cb : {}; + this.onMessage = bind(this.onMessage, this); + this.send = bind(this.send, this); + $.on(window, 'message', this.onMessage); + } + + Connection.prototype.targetWindow = function() { + if (this.target instanceof window.HTMLIFrameElement) { + return this.target.contentWindow; + } else { + return this.target; + } + }; + + Connection.prototype.send = function(data) { + return this.targetWindow().postMessage("" + g.NAMESPACE + (JSON.stringify(data)), this.origin); + }; + + Connection.prototype.onMessage = function(e) { + var base, data, type, value; + if (!(e.source === this.targetWindow() && 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; + + })(); + + return Connection; + +}).call(this); + +DataBoard = (function() { + var DataBoard, + bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + + 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[this.key]; + $.sync(this.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(cb) { + return $.set(this.key, this.data, cb); + }; + + DataBoard.prototype["delete"] = function(arg) { + var boardID, postID, ref, threadID; + 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, cb) { + var base, base1, base2, boardID, postID, threadID, val; + 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(cb); + }; + + DataBoard.prototype.get = function(arg) { + var ID, board, boardID, defaultValue, i, len, postID, thread, threadID, val; + boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, defaultValue = arg.defaultValue; + if (board = this.data.boards[boardID]) { + if (threadID == null) { + if (postID != null) { + 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 != null ? thread[postID] : thread; + } + } + return val || defaultValue; + }; + + DataBoard.prototype.forceSync = function() { + return $.forceSync(this.key); + }; + + DataBoard.prototype.clean = function() { + var boardID, now, ref, val; + $.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) { + this.ajaxClean(boardID); + } + } + }; + + DataBoard.prototype.ajaxClean = function(boardID) { + return $.cache("//a.4cdn.org/" + boardID + "/threads.json", (function(_this) { + return function(e1) { + var ref; + if ((ref = e1.target.status) !== 200 && ref !== 404) { + return; + } + return $.cache("//a.4cdn.org/" + boardID + "/archive.json", function(e2) { + var ref1; + if ((ref1 = e2.target.status) !== 200 && ref1 !== 404) { + return; + } + return _this.ajaxCleanParse(boardID, e1.target.response, e2.target.response); + }); + }; + })(this)); + }; + + DataBoard.prototype.ajaxCleanParse = function(boardID, response1, response2) { + var ID, board, i, j, k, len, len1, len2, page, ref, thread, threads; + if (!(board = this.data.boards[boardID])) { + return; + } + threads = {}; + if (response1) { + for (i = 0, len = response1.length; i < len; i++) { + page = response1[i]; + ref = page.threads; + for (j = 0, len1 = ref.length; j < len1; j++) { + thread = ref[j]; + ID = thread.no; + if (ID in board) { + threads[ID] = board[ID]; + } + } + } + } + if (response2) { + for (k = 0, len2 = response2.length; k < len2; k++) { + ID = response2[k]; + if (ID in board) { + threads[ID] = board[ID]; + } + } + } + this.data.boards[boardID] = threads; + this.deleteIfEmpty({ + boardID: boardID + }); + return this.save(); + }; + + DataBoard.prototype.onSync = function(data) { + this.data = data || { + boards: {} + }; + return typeof this.sync === "function" ? this.sync() : void 0; + }; + + return DataBoard; + + })(); + + return DataBoard; + +}).call(this); + +Fetcher = (function() { + var Fetcher, + slice = [].slice; + + Fetcher = (function() { + function Fetcher(boardID1, threadID, postID1, root, quoter) { + var post; + this.boardID = boardID1; + this.threadID = threadID; + this.postID = postID1; + this.root = root; + this.quoter = quoter; + 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(_this) { + return function(e, isCached) { + return _this.fetchedPost(e.target, isCached); + }; + })(this)); + } else { + this.archivedPost(); + } + } + + Fetcher.prototype.insert = function(post) { + var boardID, clone, k, len, nodes, postID, quote, ref, ref1; + if (!this.root.parentNode) { + return; + } + clone = post.addClone(this.quoter.context, $.hasClass(this.root, 'dialog')); + Main.callbackNodes('Post', [clone]); + nodes = clone.nodes; + $.rmAll(nodes.root); + $.add(nodes.root, nodes.post); + ref = clone.nodes.quotelinks.concat(slice.call(clone.nodes.backlinks)); + for (k = 0, len = ref.length; k < len; k++) { + quote = ref[k]; + ref1 = Get.postDataFromLink(quote), boardID = ref1.boardID, postID = ref1.postID; + if (postID === this.quoter.ID && boardID === this.quoter.board.ID) { + $.addClass(quote, 'forwardlink'); + } + } + $.rmAll(this.root); + $.add(this.root, nodes.root); + return $.event('PostsInserted'); + }; + + Fetcher.prototype.fetchedPost = function(req, isCached) { + var api, board, k, len, post, posts, status, thread; + 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 (k = 0, len = posts.length; k < len; k++) { + post = posts[k]; + if (post.no === this.postID) { + break; + } + } + if (post.no !== this.postID) { + if (isCached) { + api = "//a.4cdn.org/" + this.boardID + "/thread/" + this.threadID + ".json"; + $.cleanCache(function(url) { + return url === api; + }); + $.cache(api, (function(_this) { + return function(e) { + return _this.fetchedPost(e.target, false); + }; + })(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 archive, url; + if (!Conf['Resurrect Quotes']) { + return false; + } + if (!(url = Redirect.to('post', { + boardID: this.boardID, + postID: this.postID + }))) { + return false; + } + archive = Redirect.data.post[this.boardID]; + if (/^https:\/\//.test(url) || location.protocol === 'http:') { + $.cache(url, (function(_this) { + return function(e) { + return _this.parseArchivedPost(e.target.response, url, archive); + }; + })(this), { + responseType: 'json', + withCredentials: archive.withCredentials + }); + return true; + } else if (Conf['Exempt 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 (!((ref = media[key]) != null ? ref.match(/^http:\/\//) : void 0)) { + delete media[key]; + } + } + } + } + return _this.parseArchivedPost(response, url, archive); + }; + })(this)); + return true; + } + return false; + }; + + Fetcher.prototype.parseArchivedPost = function(data, url, archive) { + var board, comment, greentext, i, j, key, o, post, ref, ref1, text, text2, thread, val; + if (post = g.posts[this.boardID + "." + this.postID]) { + this.insert(post); + return; + } + if (data == null) { + $.addClass(this.root, 'warning'); + this.root.textContent = "Error fetching Post No." + this.postID + " from " + archive.name + "."; + 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 k, len, results; + results = []; + for (i = k = 0, len = comment.length; k < len; i = ++k) { + text = comment[i]; + if (i % 2 === 1) { + results.push(this.archiveTags[text]); + } else { + greentext = text[0] === '>'; + text = text.replace(/(\[\/?[a-z]+):lit(\])/g, '$1$2'); + text = (function() { + var l, len1, ref, results1; + ref = text.split(/(>>(?:>\/[a-z\d]+\/)?\d+)/g); + results1 = []; + for (j = l = 0, len1 = ref.length; l < len1; j = ++l) { + text2 = ref[j]; + results1.push({ + innerHTML: ((j % 2) ? "" + E(text2) + "" : E(text2)) + }); + } + return results1; + })(); + text = { + innerHTML: ((greentext) ? "" + E.cat(text) + "" : E.cat(text)) + }; + results.push(text); + } + } + return results; + }).call(this); + comment = { + innerHTML: E.cat(comment) + }; + this.threadID = +data.thread_num; + o = { + postID: this.postID, + threadID: this.threadID, + boardID: this.boardID, + isReply: this.postID !== this.threadID + }; + o.info = { + subject: data.title, + email: data.email, + name: data.name || '', + tripcode: data.trip, + capcode: (function() { + switch (data.capcode) { + case 'M': + return 'Mod'; + case 'A': + return 'Admin'; + case 'D': + return 'Developer'; + } + })(), + uniqueID: data.poster_hash, + flagCode: data.poster_country, + flag: data.poster_country_name, + dateUTC: data.timestamp, + dateText: data.fourchan_date, + commentHTML: comment + }; + if (o.info.capcode) { + delete o.info.uniqueID; + } + if ((ref = data.media) != null ? ref.media_filename : void 0) { + ref1 = data.media; + for (key in ref1) { + val = ref1[key]; + if (/_link$/.test(key) && (val != null ? val[0] : void 0) === '/') { + data.media[key] = url.split('/', 3).join('/') + val; + } + } + o.file = { + name: data.media.media_filename, + url: data.media.media_link || data.media.remote_media_link || (location.protocol + "//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: $.bytesToString(data.media.media_size), + thumbURL: data.media.thumb_link || (location.protocol + "//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 (!/\.pdf$/.test(o.file.url)) { + o.file.dimensions = o.file.width + "x" + o.file.height; + } + if (this.boardID === 'f' && data.media.exif) { + 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); + post.kill(); + if (post.file) { + post.file.thumbURL = o.file.thumbURL; + } + post.isFetchedQuote = true; + Main.callbackNodes('Post', [post]); + return this.insert(post); + }; + + Fetcher.prototype.archiveTags = { + '\n': { + innerHTML: "
        " + }, + '[b]': { + innerHTML: "" + }, + '[/b]': { + innerHTML: "" + }, + '[spoiler]': { + innerHTML: "" + }, + '[/spoiler]': { + innerHTML: "" + }, + '[code]': { + innerHTML: "
        "
        +      },
        +      '[/code]': {
        +        innerHTML: "
        " + }, + '[moot]': { + innerHTML: "
        " + }, + '[/moot]': { + innerHTML: "
        " + }, + '[banned]': { + innerHTML: "" + }, + '[/banned]': { + innerHTML: "" + } + }; + + return Fetcher; + + })(); + + return Fetcher; + +}).call(this); + +Notice = (function() { + var Notice, + bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + + 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: "
        " + }); + 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 (this.closed) { + return; + } + 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() { + this.closed = true; + $.off(d, 'visibilitychange', this.add); + $.rm(this.el); + return typeof this.onclose === "function" ? this.onclose() : void 0; + }; + + return Notice; + + })(); + + return Notice; + +}).call(this); + +Post = (function() { + var Post, + 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; }; + + Post = (function() { + Post.prototype.toString = function() { + return this.ID; + }; + + function Post(root, thread, board) { + var capcode, clone, date, email, flag, info, j, len, name, post, ref, subject, tripcode, uniqueID; + this.thread = thread; + this.board = board; + this.ID = +root.id.slice(2); + this.fullID = this.board + "." + this.ID; + this.context = this; + root.dataset.fullID = this.fullID; + 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: [] + }; + if ($.engine === 'edge') { + Object.defineProperty(this.nodes, 'backlinks', { + configurable: true, + enumerable: true, + get: function() { + return info.getElementsByClassName('backlink'); + } + }); + } else { + this.nodes.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 || void 0; + } + 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(); + 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 (j = 0, len = ref.length; j < len; j++) { + clone = ref[j]; + clone.origin = this; + } + } + this.board.posts.push(this.ID, this); + this.thread.posts.push(this.ID, this); + g.posts.push(this.fullID, this); + } + + Post.prototype.parseComment = function() { + var abbr, bq, commentDisplay, j, k, len, len1, node, ref, spoilers; + this.nodes.comment.normalize(); + bq = this.nodes.comment.cloneNode(true); + ref = $$('.abbr + br, .exif, b, .fortune', bq); + for (j = 0, len = ref.length; j < len; j++) { + node = ref[j]; + $.rm(node); + } + if (abbr = $('.abbr', bq)) { + $.rm(abbr); + } + this.info.comment = this.nodesToText(bq); + if (abbr) { + this.info.comment = this.info.comment.replace(/\n\n$/, ''); + } + commentDisplay = this.info.comment; + if (!(Conf['Remove Spoilers'] || Conf['Reveal Spoilers'])) { + spoilers = $$('s', bq); + if (spoilers.length) { + for (k = 0, len1 = spoilers.length; k < len1; k++) { + node = spoilers[k]; + $.replace(node, $.tn('[spoiler]')); + } + commentDisplay = this.nodesToText(bq); + } + } + return this.info.commentDisplay = commentDisplay.trim().replace(/\s+$/gm, ''); + }; + + 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; + }; + + Post.prototype.parseQuotes = function() { + var j, len, quotelink, ref; + this.quotes = []; + ref = $$(':not(pre) > .quotelink', this.nodes.comment); + for (j = 0, len = ref.length; j < len; j++) { + quotelink = ref[j]; + this.parseQuote(quotelink); + } + }; + + Post.prototype.parseQuote = function(quotelink) { + var fullID, match; + match = quotelink.href.match(/^https?:\/\/boards\.4chan\.org\/+([^\/]+)\/+(?:res|thread)\/+\d+(?:\/[^#]*)?#p(\d+)$/); + if (!(match || (this.isClone && quotelink.dataset.postID))) { + 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() { + var fileEl, fileText, info, link, m, ref, ref1, ref2, size, thumb, unit; + if (!(fileEl = $('.file', this.nodes.post))) { + return; + } + if (!(link = $('.fileText > a, .fileText-original > a', fileEl))) { + return; + } + if (!(info = (ref = link.nextSibling) != null ? ref.textContent.match(/\(([\d.]+ [KMG]?B).*\)/) : void 0)) { + return; + } + fileText = fileEl.firstElementChild; + this.file = { + text: fileText, + link: link, + url: link.href, + name: fileText.title || link.title || link.textContent, + size: info[1], + isImage: /(jpg|png|gif)$/i.test(link.href), + isVideo: /webm$/i.test(link.href), + dimensions: (ref1 = info[0].match(/\d+x\d+/)) != null ? ref1[0] : void 0, + tag: (ref2 = info[0].match(/,[^,]*, ([a-z]+)\)/i)) != null ? ref2[1] : void 0 + }; + 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; + if ((thumb = $('.fileThumb > [data-md5]', fileEl))) { + return $.extend(this.file, { + thumb: thumb, + thumbURL: (m = link.href.match(/\d+(?=\.\w+$)/)) ? location.protocol + "//i.4cdn.org/" + this.board + "/" + m[0] + "s.jpg" : void 0, + MD5: thumb.dataset.md5, + isSpoiler: $.hasClass(thumb.parentNode, 'imgspoiler') + }); + } + }; + + Post.prototype.kill = function(file) { + var clone, j, k, len, len1, quotelink, ref, ref1, strong; + if (file) { + if (this.isDead || this.file.isDead) { + return; + } + this.file.isDead = true; + $.addClass(this.nodes.root, 'deleted-file'); + } else { + if (this.isDead) { + return; + } + this.isDead = true; + $.rmClass(this.nodes.root, 'deleted-file'); + $.addClass(this.nodes.root, 'deleted-post'); + } + if (!(strong = $('strong.warning', this.nodes.info))) { + strong = $.el('strong', { + className: 'warning' + }); + $.after($('input', this.nodes.info), strong); + } + strong.textContent = file ? '[File deleted]' : '[Deleted]'; + if (this.isClone) { + return; + } + ref = this.clones; + for (j = 0, len = ref.length; j < len; j++) { + clone = ref[j]; + clone.kill(file); + } + if (file) { + return; + } + ref1 = Get.allQuotelinksLinkingTo(this); + for (k = 0, len1 = ref1.length; k < len1; k++) { + quotelink = ref1[k]; + if (!(!$.hasClass(quotelink, 'deadlink'))) { + continue; + } + quotelink.textContent = quotelink.textContent + '\u00A0(Dead)'; + $.addClass(quotelink, 'deadlink'); + } + }; + + Post.prototype.resurrect = function() { + var clone, j, k, len, len1, quotelink, ref, ref1, strong; + this.isDead = false; + $.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 (j = 0, len = ref.length; j < len; j++) { + clone = ref[j]; + clone.resurrect(); + } + ref1 = Get.allQuotelinksLinkingTo(this); + for (k = 0, len1 = ref1.length; k < len1; k++) { + quotelink = ref1[k]; + if (!($.hasClass(quotelink, 'deadlink'))) { + continue; + } + quotelink.textContent = quotelink.textContent.replace('\u00A0(Dead)', ''); + $.rmClass(quotelink, 'deadlink'); + } + }; + + Post.prototype.collect = function() { + g.posts.rm(this.fullID); + this.thread.posts.rm(this); + return this.board.posts.rm(this); + }; + + Post.prototype.addClone = function(context, contractThumb) { + return new Post.Clone(this, context, contractThumb); + }; + + Post.prototype.rmClone = function(index) { + var clone, j, len, ref; + this.clones.splice(index, 1); + ref = this.clones.slice(index); + for (j = 0, len = ref.length; j < len; j++) { + clone = ref[j]; + clone.nodes.root.dataset.clone = index++; + } + }; + + return Post; + + })(); + + return Post; + +}).call(this); + +(function() { + var extend = 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; }, + hasProp = {}.hasOwnProperty, + slice = [].slice; + + Post.Clone = (function(superClass) { + extend(_Class, superClass); + + _Class.prototype.isClone = true; + + function _Class(origin, context, contractThumb) { + var base, file, i, info, inline, inlined, j, k, key, l, len, len1, len2, len3, node, nodes, post, ref, ref1, ref2, ref3, ref4, ref5, root, val; + 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] = this.origin[key]; + } + nodes = this.origin.nodes; + root = contractThumb ? this.cloneWithoutVideo(nodes.root) : nodes.root.cloneNode(true); + (base = Post.Clone).prefix || (base.prefix = 0); + ref1 = [root].concat(slice.call($$('[id]', root))); + for (j = 0, len1 = ref1.length; j < len1; j++) { + node = ref1[j]; + node.id = Post.Clone.prefix + node.id; + } + Post.Clone.prefix++; + 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: [] + }; + if ($.engine === 'edge') { + Object.defineProperty(this.nodes, 'backlinks', { + configurable: true, + enumerable: true, + get: function() { + return info.getElementsByClassName('backlink'); + } + }); + } else { + this.nodes.backlinks = info.getElementsByClassName('backlink'); + } + ref2 = $$('.inline', post); + for (k = 0, len2 = ref2.length; k < len2; k++) { + inline = ref2[k]; + $.rm(inline); + } + ref3 = $$('.inlined', post); + for (l = 0, len3 = ref3.length; l < len3; l++) { + inlined = ref3[l]; + $.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(); + this.quotes = slice.call(this.origin.quotes); + if (this.origin.file) { + this.file = {}; + ref4 = this.origin.file; + for (key in ref4) { + val = ref4[key]; + this.file[key] = val; + } + file = $('.file', post); + this.file.text = file.firstElementChild; + this.file.link = $('.fileText > a, .fileText-original', file); + 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 ((ref5 = this.file.thumb) != null ? ref5.dataset.src : void 0) { + this.file.thumb.src = this.file.thumb.dataset.src; + this.file.thumb.removeAttribute('data-src'); + } + if (this.file.thumb && contractThumb) { + ImageExpand.contract(this); + } + } + if (this.origin.isDead) { + this.isDead = true; + } + root.dataset.clone = this.origin.clones.push(this) - 1; + } + + _Class.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 _Class; + + })(Post); + +}).call(this); + +RandomAccessList = (function() { + var RandomAccessList; + + RandomAccessList = (function() { + function RandomAccessList(items) { + var i, item, 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; + + })(); + + return RandomAccessList; + +}).call(this); + +ShimSet = (function() { + var ShimSet; + + 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; + } + + return ShimSet; + +}).call(this); + +SimpleDict = (function() { + var SimpleDict, + slice = [].slice; + + 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 j, key, len, ref; + ref = slice.call(this.keys); + for (j = 0, len = ref.length; j < len; j++) { + key = ref[j]; + fn(this[key]); + } + }; + + return SimpleDict; + + })(); + + return SimpleDict; + +}).call(this); + +Thread = (function() { + var Thread; + + Thread = (function() { + 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; + this.board.threads.push(this.ID, this); + g.threads.push(this.fullID, 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; + + })(); + + return Thread; + +}).call(this); + +Redirect = (function() { + var Redirect, + 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; }; + + Redirect = { + init: function() { + var archive, archives, boardID, boards, data, files, i, id, j, len, len1, name, o, record, ref, ref1, software, type, uid, withCredentials; + o = { + thread: {}, + post: {}, + file: {}, + report: {} + }; + archives = {}; + ref = Redirect.archives; + for (i = 0, len = ref.length; i < len; i++) { + data = ref[i]; + uid = data.uid, name = data.name, boards = data.boards, files = data.files, software = data.software, withCredentials = data.withCredentials; + archives[JSON.stringify(uid != null ? uid : name)] = data; + for (j = 0, len1 = boards.length; j < len1; j++) { + boardID = boards[j]; + if (!withCredentials) { + 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; + } + } + if (name === 'fgts') { + o.report[boardID] = data; + } + } + } + ref1 = Conf['selectedArchives']; + for (boardID in ref1) { + record = ref1[boardID]; + for (type in record) { + id = record[type]; + if (id === null) { + delete o[type][boardID]; + } else if (archive = archives[JSON.stringify(id)]) { + boards = type === 'file' ? archive.files : archive.boards; + if (indexOf.call(boards, boardID) >= 0) { + o[type][boardID] = archive; + } + } + } + } + return Redirect.data = o; + }, + archives: [ + { "uid": 3, "name": "4plebs", "domain": "archive.4plebs.org", "http": true, "https": true, "software": "foolfuuka", "boards": [ "adv", "f", "hr", "o", "pol", "s4s", "sp", "tg", "trv", "tv", "x" ], "files": [ "adv", "f", "hr", "o", "pol", "s4s", "sp", "tg", "trv", "tv", "x" ] }, + { "uid": 4, "name": "Nyafuu Archive", "domain": "archive.nyafuu.org", "http": true, "https": true, "software": "foolfuuka", "boards": [ "c", "e", "news", "w", "wg", "wsr" ], "files": [ "c", "e", "news", "w", "wg", "wsr" ] }, + { "uid": 8, "name": "Rebecca Black Tech", "domain": "rbt.asia", "http": false, "https": true, "software": "fuuka", "boards": [ "cgl", "g", "mu" ], "files": [ "cgl", "g", "mu" ] }, + { "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", "b", "cm", "gd", "h", "hc", "hm", "n", "out", "p", "po", "qa", "r", "s", "soc", "toy", "vp", "y" ], "files": [ "asp", "b", "cm", "gd", "h", "hc", "hm", "n", "out", "p", "po", "qa", "r", "s", "soc", "toy", "vp", "y" ] }, + { "uid": 23, "name": "Desustorage", "domain": "desustorage.org", "http": true, "https": true, "software": "foolfuuka", "boards": [ "a", "aco", "an", "c", "co", "d", "fit", "gif", "his", "int", "k", "m", "mlp", "qa", "r9k", "tg", "trash", "vr", "wsg" ], "files": [ "a", "aco", "an", "c", "co", "d", "fit", "gif", "his", "int", "k", "m", "mlp", "qa", "r9k", "tg", "trash", "vr", "wsg" ] }, + { "uid": 24, "name": "fireden.net", "domain": "boards.fireden.net", "http": false, "https": true, "software": "foolfuuka", "boards": [ "a", "cm", "ic", "sci", "tg", "v", "vg", "y" ], "files": [ "a", "cm", "ic", "sci", "tg", "v", "vg", "y" ] }, + { "uid": 25, "name": "arch.b4k.co", "domain": "arch.b4k.co", "http": true, "https": true, "software": "foolfuuka", "boards": [ "g", "jp", "mlp", "v" ], "files": [] }, + { "uid": 5, "name": "Love is Over", "domain": "deploy.loveisover.me", "http": true, "https": false, "software": "foolfuuka", "boards": [ "c", "d", "e", "i", "lgbt", "t", "u" ], "files": [ "c", "d", "e", "i", "lgbt", "t", "u" ], "search": [] }, + { "uid": 28, "name": "bstats", "domain": "archive.b-stats.org", "http": true, "https": true, "software": "foolfuuka", "boards": [ "f", "cm", "hm", "lgbt", "news", "trash", "y" ], "files": [] } + ], + 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 boardID, postID, protocol, url; + boardID = arg.boardID, postID = arg.postID; + protocol = Redirect.protocol(archive); + url = "" + protocol + archive.domain + "/_/api/chan/post/?board=" + boardID + "&num=" + postID; + if (!Redirect.securityCheck(url)) { + return ''; + } + 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 === 'MD5' ? 'image' : type; + if (type === 'capcode') { + value = { + 'Developer': 'dev' + }[value] || value.toLowerCase(); + } else if (type === 'image') { + value = value.replace(/[+\/=]/g, function(c) { + return { + '+': '-', + '/': '_', + '=': '' + }[c]; + }); + } + value = encodeURIComponent(value); + path = archive.software === 'foolfuuka' ? boardID + "/search/" + type + "/" + value + "/" : type === 'image' ? boardID + "/image/" + value : boardID + "/?task=search2&search_" + type + "=" + value; + return "" + (Redirect.protocol(archive)) + archive.domain + "/" + path; + }, + report: function(archive, arg) { + var boardID, postID; + boardID = arg.boardID, postID = arg.postID; + return "https://so.fgts.jp/report/?board=" + boardID + "&no=" + postID; + }, + securityCheck: function(url) { + return /^https:\/\//.test(url) || location.protocol === 'http:' || Conf['Exempt Archives from Encryption']; + }, + navigate: function(dest, data, alternative) { + var url; + if (!Redirect.data) { + Redirect.init(); + } + url = Redirect.to(dest, data); + 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); + } + } + }; + + return Redirect; + +}).call(this); + +Anonymize = (function() { + var Anonymize; + + 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 Callbacks.Post.push({ + name: 'Anonymize', + cb: this.node + }); + }, + node: function() { + var email, name, ref, tripcode; + 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 i, j, len, len1, name, ref, ref1, trip; + 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); + } + }); + } + }; + + return Anonymize; + +}).call(this); + +Filter = (function() { + var Filter, + 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; }; + + Filter = { + filters: {}, + init: function() { + var boards, err, excludes, filter, hl, i, key, len, line, op, ref, ref1, ref2, ref3, ref4, ref5, ref6, regexp, stub, top; + 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'; + boards = boards === 'global' ? null : boards.split(','); + if (boards === null) { + excludes = ((ref3 = filter.match(/exclude:([^;]+)/)) != null ? ref3[1].toLowerCase().split(',') : void 0) || null; + } + 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, boards, excludes, op, stub, hl, top)); + } + if (!this.filters[key].length) { + delete this.filters[key]; + } + } + if (!Object.keys(this.filters).length) { + return; + } + return Callbacks.Post.push({ + name: 'Filter', + cb: this.node + }); + }, + createFilter: function(regexp, boards, excludes, 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, boardID, isReply) { + if (boards && indexOf.call(boards, boardID) < 0) { + return false; + } + if (excludes && indexOf.call(excludes, boardID) >= 0) { + return false; + } + if (isReply && op === 'only' || !isReply && op === 'no') { + return false; + } + if (!test(value)) { + return false; + } + return settings; + }; + }, + node: function() { + var filter, i, key, len, ref, ref1, result, value; + if (this.isClone) { + return; + } + for (key in Filter.filters) { + if ((value = Filter[key](this)) != null) { + ref = Filter.filters[key]; + for (i = 0, len = ref.length; i < len; i++) { + filter = ref[i]; + if (!(result = filter(value, this.board.ID, this.isReply))) { + continue; + } + if (result.hide && !this.isFetchedQuote) { + 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; + } + } + } + } + }, + isHidden: function(post) { + var filter, i, key, len, ref, result, value; + for (key in Filter.filters) { + if ((value = Filter[key](post)) != null) { + ref = Filter.filters[key]; + for (i = 0, len = ref.length; i < len; i++) { + filter = ref[i]; + if (result = filter(value, post.boardID, post.isReply)) { + if (result.hide) { + return true; + } + } + } + } + } + return false; + }, + postID: function(post) { + var ref; + return "" + ((ref = post.ID) != null ? ref : post.postID); + }, + name: function(post) { + return post.info.name; + }, + uniqueID: function(post) { + return post.info.uniqueID; + }, + tripcode: function(post) { + return post.info.tripcode; + }, + capcode: function(post) { + return post.info.capcode; + }, + subject: function(post) { + return post.info.subject; + }, + comment: function(post) { + var base; + return (base = post.info).comment != null ? base.comment : base.comment = Build.parseComment(post.info.commentHTML.innerHTML); + }, + flag: function(post) { + return post.info.flag; + }, + filename: function(post) { + var ref; + return (ref = post.file) != null ? ref.name : void 0; + }, + dimensions: function(post) { + var ref; + return (ref = post.file) != null ? ref.dimensions : void 0; + }, + filesize: function(post) { + var ref; + return (ref = post.file) != null ? ref.size : void 0; + }, + MD5: function(post) { + var ref; + return (ref = post.file) != null ? ref.MD5 : void 0; + }, + menu: { + init: function() { + var div, entry, i, len, ref, ref1, type; + 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 != null; + } + }; + }, + 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(); + }); + } + } + }; + + return Filter; + +}).call(this); + +PostHiding = (function() { + var PostHiding; + + 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 Callbacks.Post.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, ref, replies, thisPost; + if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Menu'] || !Conf['Reply Hiding Link']) { + return; + } + div = $.el('div', { + className: 'hide-reply-link', + textContent: 'Hide' + }); + 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' + }); + 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, i, len, quotelink, 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 i, len, quotelink, 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'); + } + } + }; + + return PostHiding; + +}).call(this); + +Recursive = (function() { + var Recursive, + 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; }; + + Recursive = { + recursives: {}, + init: function() { + var ref; + if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { + return; + } + return Callbacks.Post.push({ + name: 'Recursive', + cb: this.node + }); + }, + node: function() { + var i, j, k, len, len1, obj, quote, recursive, ref, ref1; + if (this.isClone || this.isFetchedQuote) { + return; + } + ref = this.quotes; + for (j = 0, len = ref.length; j < len; j++) { + quote = ref[j]; + if (obj = Recursive.recursives[quote]) { + ref1 = obj.recursives; + for (i = k = 0, len1 = ref1.length; k < len1; i = ++k) { + recursive = ref1[i]; + recursive.apply(null, [this].concat(slice.call(obj.args[i]))); + } + } + } + }, + add: function() { + var args, base, name, obj, post, recursive; + 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, j, len, obj, rec, ref; + if (!(obj = Recursive.recursives[post.fullID])) { + return; + } + ref = obj.recursives; + for (i = j = 0, len = ref.length; j < len; i = ++j) { + 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))); + } + }); + } + }; + + return Recursive; + +}).call(this); + +ThreadHiding = (function() { + var ThreadHiding; + + ThreadHiding = { + init: function() { + var ref; + if (((ref = g.VIEW) !== 'index' && ref !== 'catalog') || !Conf['Thread Hiding Buttons'] && !(Conf['Menu'] && Conf['Thread Hiding Link']) && !Conf['JSON Index']) { + return; + } + this.db = new DataBoard('hiddenThreads'); + if (g.VIEW === 'catalog') { + return this.catalogWatch(); + } + this.catalogSet(g.BOARD); + return Callbacks.Post.push({ + name: 'Thread Hiding', + cb: this.node + }); + }, + catalogSet: function(board) { + var hiddenThreads, threadID; + if (!$.hasStorage) { + return; + } + 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() { + if (!$.hasStorage) { + return; + } + this.hiddenThreads = JSON.parse(localStorage.getItem("4chan-hide-t-" + g.BOARD)) || {}; + return Main.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 (this.isReply || this.isClone || this.isFetchedQuote) { + return; + } + if (data = ThreadHiding.db.get({ + boardID: this.board.ID, + threadID: this.ID + })) { + ThreadHiding.hide(this.thread, data.makeStub); + } + if (!Conf['Thread Hiding Buttons']) { + return; + } + return $.prepend(this.nodes.root, ThreadHiding.makeButton(this.thread, 'hide')); + }, + onIndexBuild: function(nodes) { + var i, len, root, thread; + 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' + }); + 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 Index'] && 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', + 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 Index'] && 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 Index'] && 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: "" + }); + 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 Index']) { + 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 Index']) { + return Index.updateHideLabel(); + } + } + }; + + return ThreadHiding; + +}).call(this); + +Build = (function() { + var Build, + slice = [].slice; + + 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|#44);/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; + } + }, + spoilerThumb: function(boardID) { + var spoilerRange; + if (spoilerRange = Build.spoilerRange[boardID]) { + return Build.staticPath + "spoiler-" + boardID + (Math.floor(1 + spoilerRange * Math.random())) + ".png"; + } else { + return Build.staticPath + "spoiler.png"; + } + }, + 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; + } + }, + parseJSON: function(data, boardID) { + var o; + o = { + postID: data.no, + threadID: data.resto || data.no, + boardID: boardID, + isReply: !!data.resto, + isSticky: !!data.sticky, + isClosed: !!data.closed, + isArchived: !!data.archived, + fileDeleted: !!data.filedeleted + }; + o.info = { + subject: Build.unescape(data.sub), + email: Build.unescape(data.email), + name: Build.unescape(data.name) || '', + tripcode: data.trip, + uniqueID: data.id, + flagCode: data.country, + flag: Build.unescape(data.country_name), + dateUTC: data.time, + dateText: data.now, + commentHTML: { + innerHTML: data.com || '' + } + }; + if (data.capcode) { + o.info.capcode = data.capcode.replace(/_highlight$/, '').replace(/_/g, ' ').replace(/\b\w/g, function(c) { + return c.toUpperCase(); + }); + o.capcodeHighlight = /_highlight$/.test(data.capcode); + delete o.info.uniqueID; + } + if (data.ext) { + o.file = { + name: (Build.unescape(data.filename)) + data.ext, + url: boardID === 'f' ? location.protocol + "//i.4cdn.org/" + boardID + "/" + (encodeURIComponent(data.filename)) + data.ext : location.protocol + "//i.4cdn.org/" + boardID + "/" + data.tim + data.ext, + height: data.h, + width: data.w, + MD5: data.md5, + size: $.bytesToString(data.fsize), + thumbURL: location.protocol + "//i.4cdn.org/" + boardID + "/" + data.tim + "s.jpg", + theight: data.tn_h, + twidth: data.tn_w, + isSpoiler: !!data.spoiler, + tag: data.tag + }; + if (!/\.pdf$/.test(o.file.url)) { + o.file.dimensions = o.file.width + "x" + o.file.height; + } + } + return o; + }, + parseComment: function(html) { + html = html.replace(//gi, '\n').replace(/\n\nRolled [^<]*<\/b>/i, '').replace(/]*>/g, ''); + return Build.unescape(html); + }, + postFromObject: function(data, boardID, suppressThumb) { + var o; + o = Build.parseJSON(data, boardID); + return Build.post(o, suppressThumb); + }, + post: function(o, suppressThumb) { + var boardID, capcode, capcodeDescription, capcodeLC, capcodeLong, capcodePlural, commentHTML, container, dateText, dateUTC, email, file, fileBlock, fileThumb, fileURL, flag, flagCode, gifIcon, href, i, len, match, name, postClass, postID, postInfo, postLink, protocol, quote, quoteLink, ref, ref1, shortFilename, staticPath, subject, threadID, tripcode, uniqueID, wholePost; + postID = o.postID, threadID = o.threadID, boardID = o.boardID, file = o.file; + ref = o.info, subject = ref.subject, email = ref.email, name = ref.name, tripcode = ref.tripcode, capcode = ref.capcode, uniqueID = ref.uniqueID, flagCode = ref.flagCode, flag = ref.flag, dateUTC = ref.dateUTC, dateText = ref.dateText, commentHTML = ref.commentHTML; + staticPath = Build.staticPath, gifIcon = Build.gifIcon; + + /* Post Info */ + if (capcode) { + capcodeLC = capcode.toLowerCase(); + if (capcode === 'Founder') { + capcodePlural = 'the Founder'; + capcodeDescription = "4chan's Founder"; + } else { + capcodeLong = { + 'Admin': 'Administrator', + 'Mod': 'Moderator' + }[capcode] || capcode; + capcodePlural = capcodeLong + "s"; + capcodeDescription = "a 4chan " + capcodeLong; + } + } + postLink = Build.postURL(boardID, threadID, postID); + quoteLink = Build.sameThread(boardID, threadID) ? "javascript:quote('" + (+postID) + "');" : "/" + boardID + "/thread/" + threadID + "#q" + postID; + postInfo = { + innerHTML: "
        " + ((!o.isReply || boardID === "f" || subject) ? "" + E(subject || "") + " " : "") + "" + ((email) ? "" : "") + "" + E(name) + "" + ((tripcode) ? " " + E(tripcode) + "" : "") + ((capcode) ? " ## " + E(capcode) + "" : "") + ((email) ? "" : "") + ((boardID === "f" && !o.isReply || capcode) ? "" : " ") + ((capcode) ? " \""" : "") + ((uniqueID && !capcode) ? " (ID: " + E(uniqueID) + ")" : "") + ((flagCode) ? " " : "") + " " + E(dateText) + " No." + E(postID) + "" + ((o.isSticky) ? " \"Sticky\"" : "") + ((o.isClosed && !o.isArchived) ? " \"Closed\"" : "") + ((o.isArchived) ? " \"Archived\"" : "") + ((!o.isReply && g.VIEW === "index") ? "   [Reply]" : "") + "
        " + }; + + /* File Info */ + if (file) { + protocol = /^https?:(?=\/\/i\.4cdn\.org\/)/; + fileURL = file.url.replace(protocol, ''); + shortFilename = Build.shortFilename(file.name); + fileThumb = file.isSpoiler ? Build.spoilerThumb(boardID) : file.thumbURL.replace(protocol, ''); + } + fileBlock = { + innerHTML: ((file) ? "
        " + ((boardID === "f") ? "
        File: " + E(file.name) + "-(" + E(file.size) + ", " + E(file.dimensions) + ((file.tag) ? ", " + E(file.tag) : "") + ")
        " : "
        File: " + ((file.isSpoiler) ? "Spoiler Image" : E(shortFilename)) + " (" + E(file.size) + ", " + E(file.dimensions || "PDF") + ")
        ") + "
        " : ((o.fileDeleted) ? "
        \"File
        " : "")) + }; + + /* Whole Post */ + postClass = o.isReply ? 'reply' : 'op'; + wholePost = { + innerHTML: ((o.isReply) ? "
        >>
        " : "") + "
        " + ((o.isReply) ? (postInfo).innerHTML + (fileBlock).innerHTML : (fileBlock).innerHTML + (postInfo).innerHTML) + "
        " + (commentHTML).innerHTML + "
        " + }; + container = $.el('div', { + className: "postContainer " + postClass + "Container", + id: "pc" + postID + }); + $.extend(container, wholePost); + ref1 = $$('.quotelink', container); + for (i = 0, len = ref1.length; i < len; i++) { + quote = ref1[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] || '#'; + } else if (/^\d+(#|$)/.test(href) && !(g.VIEW === 'thread' && g.BOARD.ID === boardID)) { + quote.href = "/" + boardID + "/thread/" + href; + } + } + return container; + }, + summaryText: function(status, posts, files) { + var text; + text = ''; + if (status) { + text += status + " "; + } + text += posts + " post" + (posts > 1 ? 's' : ''); + if (+files) { + text += " and " + files + " image repl" + (files > 1 ? 'ies' : 'y'); + } + return text += " " + (status === '-' ? 'shown' : 'omitted') + "."; + }, + summary: function(boardID, threadID, posts, files) { + return $.el('a', { + className: 'summary', + textContent: Build.summaryText('', posts, files), + href: "/" + boardID + "/thread/" + threadID + }); + }, + thread: function(board, data, full) { + var OP, root; + Build.spoilerRange[board] = data.custom_spoiler; + if (OP = board.posts[data.no]) { + if (OP.isFetchedQuote) { + OP = null; + } + } + if (OP && (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, true)]; + 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, i, imgClass, j, k, l, len, len1, len2, len3, pageCount, postCount, pp, quote, ref, ref1, ref2, ref3, ref4, root, spoilerRange, src, staticPath; + 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'; + } + postCount = data.replies + 1; + fileCount = data.images + !!data.ext; + pageCount = Math.floor(Index.liveThreadIDs.indexOf(thread.ID) / Index.threadsNumPerPage) + 1; + comment = { + innerHTML: data.com || '' + }; + root = $.el('div', { + className: 'catalog-thread' + }); + $.extend(root, { + innerHTML: "
        " + E(postCount) + " / " + E(fileCount) + " / " + E(pageCount) + "
        " + ((thread.OP.info.subject) ? "
        " + E(thread.OP.info.subject) + "
        " : "") + "
        " + (comment).innerHTML + "
        " + }); + 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; + } + }; + + return Build; + +}).call(this); + +(function() { + + +}).call(this); + +Get = (function() { + var Get, + 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; }; + + 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.commentDisplay.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 index, post; + if (root == null) { + return null; + } + post = g.posts[root.dataset.fullID]; + index = root.dataset.clone; + 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)); + }, + postDataFromLink: function(link) { + var boardID, path, postID, ref, threadID; + 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, i, len, posts, qPost, quote, quotelinks, 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 i, len, ref, script; + 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 ''; + } + }; + + return Get; + +}).call(this); + +Header = (function() { + var Header; + + 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: "" + }); + 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 popstate', 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 absbot, oldFooter; + if ((oldFooter = $.id('boardNavDesktopFoot'))) { + return $.replace($('.boardList', oldFooter), Header.bottomBoardList); + } else if ((absbot = $.id('absbot'))) { + $.before(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, i, j, len, len1, node, nodes, ref, ref1, spacer, span; + Header.boardList = boardList = $.el('span', { + id: 'board-list' + }); + $.extend(boardList, { + innerHTML: "" + }); + 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|(mode|sort|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, indexOptions, 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 ''; + }); + indexOptions = []; + t = t.replace(/-(?:mode|sort):"([^"]+)"/g, function(m0, m1) { + indexOptions.push(m1.toLowerCase().replace(/\ /g, '-')); + return ''; + }); + indexOptions = indexOptions.join('/'); + 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)/)) { + if (!(boardID === 'f' && m[1] === 'catalog')) { + a.dataset.only = m[1]; + a.href = CatalogLinks[m[1]](boardID); + if (m[1] === 'catalog') { + $.addClass(a, 'catalog'); + } + } else { + return a.firstChild; + } + } + if (Conf['JSON Index'] && indexOptions) { + a.dataset.indexOptions = indexOptions; + if (a.hostname === 'boards.4chan.org' && a.pathname.split('/')[2] === '') { + a.href += (a.hash ? '/' : '#') + indexOptions; + } + } + 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' && boardID !== 'trash') { + 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() { + 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(e) { + var el, hash; + if (e) { + if (e.state) { + return; + } + if (!history.state) { + history.replaceState({}, ''); + } + } + if ((hash = location.hash.slice(1))) { + ReplyPruning.showIfHidden(hash); + if ((el = $.id(hash))) { + return $.queueTask(function() { + return Header.scrollTo(el); + }); + } + } + }, + scrollTo: function(root, down, needed) { + var height, x; + if (!root.offsetParent) { + return; + } + if (down) { + x = Header.getBottomOf(root); + if (Conf['Fixed Header'] && 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['Fixed Header'] && 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['Fixed Header'] && 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, ref, type; + 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: "4chan X needs your permission to show desktop notifications. [FAQ]
        or " + }); + 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); + } + }; + + return Header; + +}).call(this); + +Index = (function() { + var Index, + 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; }; + + Index = { + showHiddenThreads: false, + changed: {}, + init: function() { + var anchorEntry, input, j, k, label, len, len1, name, pinEntry, ref, ref1, ref2, ref3, ref4, ref5, ref6, refNavEntry, repliesEntry, select, sortEntry; + if (g.BOARD.ID === 'f' || !Conf['JSON Index'] || g.VIEW !== 'index') { + return; + } + Callbacks.CatalogThread.push({ + name: 'Catalog Features', + cb: this.catalogNode + }); + this.search = ((ref = history.state) != null ? ref.searched : void 0) || ''; + if ((ref1 = history.state) != null ? ref1.mode : void 0) { + Conf['Index Mode'] = (ref2 = history.state) != null ? ref2.mode : void 0; + } + this.currentSort = (ref3 = history.state) != null ? ref3.sort : void 0; + this.currentSort || (this.currentSort = typeof Conf['Index Sort'] === 'object' ? Conf['Index Sort'][g.BOARD.ID] || 'bump' : Conf['Index Sort']); + this.currentPage = this.getCurrentPage(); + this.processHash(); + $.addClass(doc, 'index-loading', (Conf['Index Mode'].replace(/\ /g, '-')) + "-mode"); + $.on(window, 'popstate', this.cb.popstate); + $.on(d, 'scroll', Index.scroll); + 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') + }; + sortEntry = { + el: UI.checkbox('Per-Board Sort Type', 'Per-board sort type', typeof Conf['Index Sort'] === 'object') + }; + 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') + }; + sortEntry.el.title = 'Set the sorting order of each board independently.'; + 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 (j = 0, len = ref4.length; j < len; j++) { + label = ref4[j]; + 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.resort); + } + } + $.on(sortEntry.el.firstChild, 'change', this.cb.perBoardSort); + Header.menu.addEntry({ + el: $.el('span', { + textContent: 'Index Navigation' + }), + order: 100, + subEntries: [repliesEntry, sortEntry, pinEntry, anchorEntry, refNavEntry] + }); + this.navLinks = $.el('div', { + className: 'navLinks json-index' + }); + $.extend(this.navLinks, { + innerHTML: "Index Catalog Archive Bottom ×" + }); + $('.cataloglink a', this.navLinks).href = CatalogLinks.catalog(); + if ((ref5 = g.BOARD.ID) === 'b' || ref5 === 'trash') { + $('.archlistlink', this.navLinks).hidden = true; + } + $.on($('#index-last-refresh a', this.navLinks), 'click', this.cb.refreshFront); + this.searchInput = $('#index-search', this.navLinks); + this.setupSearch(); + $.on(this.searchInput, 'input', this.onSearchInput); + $.on($('#index-search-clear', this.navLinks), 'click', this.clearSearch); + this.hideLabel = $('#hidden-label', this.navLinks); + $.on($('#hidden-toggle a', this.navLinks), 'click', this.cb.toggleHiddenThreads); + this.selectMode = $('#index-mode', this.navLinks); + this.selectSort = $('#index-sort', this.navLinks); + this.selectSize = $('#index-size', this.navLinks); + $.on(this.selectMode, 'change', this.cb.mode); + $.on(this.selectSort, 'change', this.cb.sort); + $.on(this.selectSize, 'change', $.cb.value); + $.on(this.selectSize, 'change', this.cb.size); + ref6 = [this.selectMode, this.selectSize]; + for (k = 0, len1 = ref6.length; k < len1; k++) { + select = ref6[k]; + select.value = Conf[select.name]; + } + this.selectSort.value = Index.currentSort; + this.root = $.el('div', { + className: 'board json-index' + }); + this.cb.size(); + this.pagelist = $.el('div', { + className: 'pagelist json-index' + }); + $.extend(this.pagelist, { + innerHTML: "
        " + }); + $('.cataloglink a', this.pagelist).href = CatalogLinks.catalog(); + $.on(this.pagelist, 'click', this.cb.pageNav); + this.update(true); + $.onExists(doc, 'title + *', function() { + return d.title = d.title.replace(/\ -\ Page\ \d+/, ''); + }); + $.onExists(doc, '.board > .thread > .postContainer, .board + *', function() { + var board, el, l, len2, len3, m, ref7, ref8, threadRoot, topNavPos; + Index.hat = $('.board > .thread > img:first-child'); + if (Index.hat) { + if (Index.nodes) { + ref7 = Index.nodes; + for (l = 0, len2 = ref7.length; l < len2; l++) { + threadRoot = ref7[l]; + $.prepend(threadRoot, Index.hat.cloneNode(false)); + } + } + $.addClass(doc, 'hats-enabled'); + $.addStyle(".catalog-thread::after {background-image: url(" + Index.hat.src + ");}"); + } + board = $('.board'); + $.replace(board, Index.root); + $.event('PostsInserted'); + try { + d.implementation.createDocument(null, null, null).appendChild(board); + } catch (_error) {} + ref8 = $$('.navLinks'); + for (m = 0, len3 = ref8.length; m < len3; m++) { + el = ref8[m]; + $.rm(el); + } + $.rm($.id('ctrl-top')); + topNavPos = $.id('delform').previousElementSibling; + $.before(topNavPos, $.el('hr')); + return $.before(topNavPos, Index.navLinks); + }); + return Main.ready(function() { + var pagelist; + if ((pagelist = $('.pagelist'))) { + $.replace(pagelist, Index.pagelist); + } + return $.rmClass(doc, 'index-loading'); + }); + }, + scroll: function() { + var nodes, pageNum; + if (Index.req || !Index.liveThreadData || Conf['Index Mode'] !== 'infinite' || (window.scrollY <= doc.scrollHeight - (300 + window.innerHeight))) { + return; + } + if (Index.pageNum == null) { + Index.pageNum = Index.currentPage; + } + 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 Index'] || !Conf['Menu'] || !Conf['Thread Hiding Link'] || g.BOARD.ID === 'f') { + return; + } + return Menu.menu.addEntry({ + el: $.el('a', { + href: 'javascript:;', + className: 'has-shortcut-text' + }, { + innerHTML: "Shift+click" + }), + order: 20, + open: function(arg) { + var thread; + thread = arg.thread; + if (Conf['Index Mode'] !== 'catalog') { + return false; + } + this.el.firstElementChild.textContent = thread.isHidden ? 'Unhide' : 'Hide'; + 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, j, len, type, types; + types = slice.call(Index.selectSort.options).filter(function(option) { + return !option.disabled; + }); + for (i = j = 0, len = types.length; j < len; i = ++j) { + 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() { + Index.pushState({ + mode: this.value + }); + return Index.pageLoad(false); + }, + sort: function() { + Index.pushState({ + sort: this.value + }); + return Index.pageLoad(false); + }, + resort: function() { + Index.sort(); + return Index.buildIndex(); + }, + perBoardSort: function() { + Conf['Index Sort'] = this.checked ? {} : ''; + return Index.saveSort(); + }, + 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, nCommands, page, ref, searched, sort; + if (e != null ? e.state : void 0) { + ref = e.state, searched = ref.searched, mode = ref.mode, sort = ref.sort; + page = Index.getCurrentPage(); + Index.setState({ + search: searched, + mode: mode, + sort: sort, + page: page + }); + return Index.pageLoad(false); + } else { + nCommands = Index.processHash(); + if (Conf['Refreshed Navigation'] && nCommands) { + return Index.update(); + } else { + return Index.pageLoad(); + } + } + }, + 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); + }, + refreshFront: function() { + Index.pushState({ + page: 1 + }); + return Index.update(); + } + }, + scrollToIndex: function() { + return Header.scrollToIfNeeded((Index.navLinks.getBoundingClientRect().height ? Index.navLinks : Index.root)); + }, + getCurrentPage: function() { + return +window.location.pathname.split(/\/+/)[2] || 1; + }, + userPageNav: function(page) { + Index.pushState({ + page: page + }); + if (Conf['Refreshed Navigation']) { + return Index.update(); + } else { + return Index.pageLoad(); + } + }, + hashCommands: { + mode: { + 'paged': 'paged', + 'infinite-scrolling': 'infinite', + 'infinite': 'infinite', + 'all-threads': 'all pages', + 'all-pages': 'all pages', + 'catalog': 'catalog' + }, + sort: { + 'bump-order': 'bump', + 'last-reply': 'lastreply', + 'last-long-reply': 'lastlong', + 'creation-date': 'birth', + 'reply-count': 'replycount', + 'file-count': 'filecount' + } + }, + processHash: function() { + var command, commands, hash, j, leftover, len, mode, ref, sort, state; + hash = ((ref = location.href.match(/#.*/)) != null ? ref[0] : void 0) || ''; + state = { + replace: true + }; + commands = hash.slice(1).split('/'); + leftover = []; + for (j = 0, len = commands.length; j < len; j++) { + command = commands[j]; + if ((mode = Index.hashCommands.mode[command])) { + state.mode = mode; + } else if (command === 'index') { + state.mode = Conf['Previous Index Mode']; + state.page = 1; + } else if ((sort = Index.hashCommands.sort[command])) { + state.sort = sort; + } else if (/^s=/.test(command)) { + state.search = decodeURIComponent(command.slice(2)).replace(/\+/g, ' ').trim(); + } else { + leftover.push(command); + } + } + hash = leftover.join('/'); + if (hash) { + state.hash = "#" + hash; + } + Index.pushState(state); + return commands.length - leftover.length; + }, + pushState: function(state) { + var hash, pageBeforeSearch, pathname, ref, replace, search; + search = state.search, hash = state.hash, replace = state.replace; + pageBeforeSearch = (ref = history.state) != null ? ref.oldpage : void 0; + if ((search != null) && search !== Index.search) { + state.page = search ? 1 : pageBeforeSearch || 1; + if (!search) { + pageBeforeSearch = void 0; + } else if (!Index.search) { + pageBeforeSearch = Index.currentPage; + } + } + Index.setState(state); + pathname = Index.currentPage === 1 ? "/" + g.BOARD + "/" : "/" + g.BOARD + "/" + Index.currentPage; + hash || (hash = ''); + return history[replace ? 'replaceState' : 'pushState']({ + mode: Conf['Index Mode'], + sort: Index.currentSort, + searched: Index.search, + oldpage: pageBeforeSearch + }, '', location.protocol + "//" + location.host + pathname + hash); + }, + setState: function(arg) { + var hash, mode, page, ref, search, sort; + search = arg.search, mode = arg.mode, sort = arg.sort, page = arg.page, hash = arg.hash; + if ((search != null) && search !== Index.search) { + Index.changed.search = true; + Index.search = search; + } + if ((mode != null) && mode !== Conf['Index Mode']) { + Index.changed.mode = true; + Conf['Index Mode'] = mode; + $.set('Index Mode', mode); + if (!(mode === 'catalog' || Conf['Previous Index Mode'] === mode)) { + Conf['Previous Index Mode'] = mode; + $.set('Previous Index Mode', mode); + } + } + if ((sort != null) && sort !== Index.currentSort) { + Index.changed.sort = true; + Index.currentSort = sort; + Index.saveSort(); + } + if ((ref = Conf['Index Mode']) === 'all pages' || ref === 'catalog') { + page = 1; + } + if ((page != null) && page !== Index.currentPage) { + Index.changed.page = true; + Index.currentPage = page; + } + if (hash != null) { + return Index.changed.hash = true; + } + }, + saveSort: function() { + if (typeof Conf['Index Sort'] === 'object') { + Conf['Index Sort'][g.BOARD.ID] = Index.currentSort; + } else { + Conf['Index Sort'] = Index.currentSort; + } + return $.set('Index Sort', Conf['Index Sort']); + }, + pageLoad: function(scroll) { + var hash, mode, page, ref, search, sort, threads; + if (scroll == null) { + scroll = true; + } + if (!Index.liveThreadData) { + return; + } + ref = Index.changed, threads = ref.threads, search = ref.search, mode = ref.mode, sort = ref.sort, page = ref.page, hash = ref.hash; + if (threads || search || sort) { + Index.sort(); + } + if (threads || search) { + Index.buildPagelist(); + } + if (search) { + Index.setupSearch(); + } + if (mode) { + Index.setupMode(); + } + if (sort) { + Index.setupSort(); + } + if (threads || search || mode || page || sort) { + Index.buildIndex(); + } + if (threads || search || mode || page) { + Index.setPage(); + } + if (scroll && !hash) { + Index.scrollToIndex(); + } + if (hash) { + Header.hashScroll(); + } + return Index.changed = {}; + }, + setupMode: function() { + var j, len, mode, ref; + ref = ['paged', 'infinite', 'all pages', 'catalog']; + for (j = 0, len = ref.length; j < len; j++) { + mode = ref[j]; + $[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'; + }, + setupSort: function() { + return Index.selectSort.value = Index.currentSort; + }, + 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, j, maxPageNum, nodes, pagesRoot, ref; + pagesRoot = $('.pages', Index.pagelist); + maxPageNum = Index.getMaxPageNum(); + if (pagesRoot.childElementCount !== maxPageNum) { + nodes = []; + for (i = j = 1, ref = maxPageNum; j <= ref; i = j += 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.currentPage; + 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, ref, ref1, thread, threadID; + 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(firstTime) { + var now, ref, ref1; + if ((ref = Index.req) != null) { + ref.abort(); + } + if ((ref1 = Index.notice) != null) { + ref1.close(); + } + if (Conf['Index Refresh Notifications'] && d.readyState !== 'loading') { + Index.notice = new Notice('info', 'Refreshing index...'); + } else { + now = Date.now(); + $.ready(function() { + return Index.nTimeout = setTimeout((function() { + if (Index.req && !Index.notice) { + return Index.notice = new Notice('info', 'Refreshing index...'); + } + }), 3 * $.SECOND - (Date.now() - now)); + }); + } + if (!firstTime && d.readyState !== 'loading' && !$('.board + *')) { + location.reload(); + return; + } + Index.req = $.ajax("//a.4cdn.org/" + g.BOARD + "/catalog.json", { + onabort: Index.load, + onloadend: Index.load + }, { + whenModified: 'Index' + }); + return $.addClass(Index.button, 'fa-spin'); + }, + load: function(e) { + var err, nTimeout, notice, ref, req, timeEl; + $.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; + if (notice != 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); + } else if (req.status === 304) { + Index.pageLoad(); + } + } 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; + } + if (notice) { + if (Conf['Index Refresh Notifications']) { + notice.setType('success'); + notice.el.lastElementChild.textContent = 'Index refreshed!'; + setTimeout(notice.close, $.SECOND); + } else { + notice.close(); + } + } + timeEl = $('#index-last-refresh time', Index.navLinks); + timeEl.dataset.utc = Date.parse(req.getResponseHeader('Last-Modified')); + return RelativeDates.update(timeEl); + }, + parse: function(pages) { + $.cleanCache(function(url) { + return /^\/\/a\.4cdn\.org\//.test(url); + }); + Index.parseThreadList(pages); + Index.buildThreads(); + Index.changed.threads = true; + return Index.pageLoad(); + }, + parseThreadList: function(pages) { + var ref; + Index.pagesNum = pages.length; + Index.threadsNumPerPage = ((ref = pages[0]) != null ? ref.threads.length : void 0) || 1; + 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 ref1; + if (ref1 = thread.ID, indexOf.call(Index.liveThreadIDs, ref1) < 0) { + return thread.collect(); + } + }); + }, + buildThreads: function() { + var err, errors, i, j, len, posts, ref, thread, threadData, threadRoot, threads; + if (!Index.liveThreadData) { + return; + } + Index.nodes = []; + threads = []; + posts = []; + ref = Index.liveThreadData; + for (i = j = 0, len = ref.length; j < len; i = ++j) { + 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.OP && !thread.OP.isFetchedQuote)) { + 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, j, k, lastReplies, len, len1, node, nodes, post, posts, thread, threadRoot; + posts = []; + for (j = 0, len = threadRoots.length; j < len; j++) { + threadRoot = threadRoots[j]; + thread = Get.threadFromRoot(threadRoot); + i = Index.liveThreadIDs.indexOf(thread.ID); + if (!(lastReplies = Index.liveThreadData[i].last_replies)) { + continue; + } + nodes = []; + for (k = 0, len1 = lastReplies.length; k < len1; k++) { + data = lastReplies[k]; + if ((post = thread.posts[data.no]) && !post.isFetchedQuote) { + 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, j, len, thread, threads; + threads = Index.sortedNodes.map(function(threadRoot) { + return Get.threadFromRoot(threadRoot); + }).filter(function(thread) { + return !thread.isHidden !== Index.showHiddenThreads; + }); + catalogThreads = []; + for (j = 0, len = threads.length; j < len; j++) { + thread = threads[j]; + 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, j, len, node, ratio, ref, size, thumb, width; + size = Conf['Index Size'] === 'small' ? 150 : 250; + for (j = 0, len = nodes.length; j < len; j++) { + node = nodes[j]; + 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 j, lastlong, len, liveThreadData, liveThreadIDs, nodes, sortedNodes, sortedThreadIDs, threadID; + liveThreadIDs = Index.liveThreadIDs, liveThreadData = Index.liveThreadData; + if (!liveThreadData) { + return; + } + sortedThreadIDs = (function() { + switch (Index.currentSort) { + case 'lastreply': + return 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; + }); + case 'lastlong': + lastlong = function(thread) { + var i, j, r, ref; + ref = thread.last_replies || []; + for (i = j = ref.length - 1; j >= 0; i = j += -1) { + r = ref[i]; + if (r.com && Build.parseComment(r.com).replace(/[^a-z]/ig, '').length >= 100) { + return r; + } + } + return thread; + }; + return slice.call(liveThreadData).sort(function(a, b) { + return lastlong(b).no - lastlong(a).no; + }).map(function(post) { + return post.no; + }); + case 'bump': + return liveThreadIDs; + case 'birth': + return slice.call(liveThreadIDs).sort(function(a, b) { + return b - a; + }); + case 'replycount': + return slice.call(liveThreadData).sort(function(a, b) { + return b.replies - a.replies; + }).map(function(post) { + return post.no; + }); + case 'filecount': + return slice.call(liveThreadData).sort(function(a, b) { + return b.images - a.images; + }).map(function(post) { + return post.no; + }); + } + })(); + Index.sortedNodes = sortedNodes = []; + nodes = Index.nodes; + for (j = 0, len = sortedThreadIDs.length; j < len; j++) { + threadID = sortedThreadIDs[j]; + 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, j, len, ref, threadRoot, topNodes; + topNodes = []; + bottomNodes = []; + ref = Index.sortedNodes; + for (j = 0, len = ref.length; j < len; j++) { + threadRoot = ref[j]; + (match(Get.threadFromRoot(threadRoot)) ? topNodes : bottomNodes).push(threadRoot); + } + return Index.sortedNodes = topNodes.concat(bottomNodes); + }, + buildIndex: function() { + var i, nodes, page, post; + if (!Index.liveThreadData) { + return; + } + 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.currentPage) { + Index.currentPage = page; + Index.pushState({ + page: page + }); + Index.setPage(); + } + } + nodes = Index.buildSinglePage(Index.currentPage); + } + delete Index.pageNum; + $.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 j, len, node, thumb; + for (j = 0, len = nodes.length; j < len; j++) { + node = nodes[j]; + if (thumb = $('img[data-src]', node)) { + thumb.src = thumb.dataset.src; + thumb.removeAttribute('data-src'); + } + $.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() { + 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; + } + Index.pushState({ + search: search, + replace: !!search === !!Index.search + }); + return Index.pageLoad(false); + }, + 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, j, k, key, keyword, len, len1, ref, ref1, text; + ref = thread.OP, info = ref.info, file = ref.file; + text = []; + ref1 = ['comment', 'subject', 'name', 'tripcode', 'email']; + for (j = 0, len = ref1.length; j < len; j++) { + key = ref1[j]; + if (key in info) { + text.push(info[key]); + } + } + if (file) { + text.push(file.name); + } + text = text.join(' ').toLowerCase(); + for (k = 0, len1 = keywords.length; k < len1; k++) { + keyword = keywords[k]; + if (-1 === text.indexOf(keyword)) { + return false; + } + } + return true; + } + }; + + return Index; + +}).call(this); + +Polyfill = (function() { + var Polyfill; + + Polyfill = { + init: function() { + return this.toBlob(); + }, + toBlob: function() { + if (HTMLCanvasElement.prototype.toBlob) { + return; + } + HTMLCanvasElement.prototype.toBlob = function(cb, type, encoderOptions) { + var data, i, j, l, ref, ui8a, url; + if (type == null) { + type = 'image/png'; + } + url = this.toDataURL(type, encoderOptions); + data = atob(url.slice(url.indexOf(',') + 1)); + l = data.length; + ui8a = new Uint8Array(l); + for (i = j = 0, ref = l; j < ref; i = j += 1) { + ui8a[i] = data.charCodeAt(i); + } + return cb(new Blob([ui8a], { + type: type + })); + }; + return $.globalEval("HTMLCanvasElement.prototype.toBlob = (" + HTMLCanvasElement.prototype.toBlob + ");"); + } + }; + + return Polyfill; + +}).call(this); + +Settings = (function() { + var Settings, + 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; }; + + 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']) { + if ($.hasStorage) { + settings = JSON.parse(localStorage.getItem('4chan-settings')) || {}; + if (settings.disableAll) { + return; + } + settings.disableAll = true; + return localStorage.setItem('4chan-settings', JSON.stringify(settings)); + } else { + return $.onExists(doc, 'body', function() { + return $.global(function() { + return window.Config.disableAll = true; + }); + }); + } + } + }, + open: function(openSection) { + var dialog, j, len, link, links, overlay, ref, section, sectionToOpen; + if (Settings.overlay) { + return; + } + $.event('CloseMenu'); + Settings.dialog = dialog = $.el('div', { + id: 'fourchanx-settings', + className: 'dialog' + }); + $.extend(dialog, { + innerHTML: "
        " + }); + 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 (j = 0, len = ref.length; j < len; j++) { + section = ref[j]; + 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); + }, + warnings: { + localStorage: function(cb) { + var why; + if ($.cantSync) { + why = $.cantSet ? 'save your settings' : 'synchronize settings between tabs'; + return cb($.el('li', { + textContent: "4chan X needs local storage to " + why + ".\nEnable it on boards.4chan.org in your browser's privacy settings (may be listed as part of \"local data\" or \"cookies\")." + })); + } + }, + ads: function(cb) { + return $.onExists(doc, '.ad-cnt', function(ad) { + return $.onExists(ad, 'img', function() { + return cb($.el('li', { + innerHTML: "To protect yourself from malicious ads, you should block ads on 4chan." + })); + }); + }); + } + }, + main: function(section) { + var addWarning, arr, button, container, containers, description, div, fs, input, inputs, items, key, level, obj, ref, ref1, warning, warnings; + warnings = $.el('fieldset', { + hidden: true + }, { + innerHTML: "Warnings
          " + }); + addWarning = function(item) { + $.add($('ul', warnings), item); + return warnings.hidden = false; + }; + ref = Settings.warnings; + for (key in ref) { + warning = ref[key]; + warning(addWarning); + } + $.add(section, warnings); + items = {}; + inputs = {}; + ref1 = Config.main; + for (key in ref1) { + obj = ref1[key]; + fs = $.el('fieldset', { + innerHTML: "" + E(key) + "" + }); + containers = [fs]; + for (key in obj) { + arr = obj[key]; + description = arr[1]; + div = $.el('div', { + innerHTML: ": " + E(description) + "" + }); + if ($.engine !== 'gecko' && key === 'Remember QR Size') { + div.hidden = true; + } + 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: ": 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, ref2, ref3, thread; + hiddenThreads = arg.hiddenThreads, hiddenPosts = arg.hiddenPosts; + hiddenNum = 0; + ref2 = hiddenThreads.boards; + for (ID in ref2) { + board = ref2[ID]; + hiddenNum += Object.keys(board).length; + } + ref3 = hiddenPosts.boards; + for (ID in ref3) { + board = ref3[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; + if ($.hasStorage) { + 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) { + 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; + } + this.value = null; + 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 { + return Settings.loadSettings(JSON.parse(e.target.result), function(err) { + if (err) { + return output.textContent = 'Import failed due to an error.'; + } else 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); + }, + convertFrom: { + loadletter: function(data) { + var base, boardID, convertSettings, key, ref, ref1, threadData, threadID, threads, val; + 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': 'Disable Native Extension', + 'Comment Auto-Expansion': '', + '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', + 'Current Page': 'Page Count in Stats', + 'Current Page Position': '', + 'Alternative captcha': 'Use Recaptcha v1', + 'Auto Submit': 'Post on Captcha Completion', + '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()); + }); + } + } + if (data.WatchedThreads) { + data.Conf['watchedThreads'] = { + boards: {} + }; + ref1 = data.WatchedThreads; + for (boardID in ref1) { + threads = ref1[boardID]; + for (threadID in threads) { + threadData = threads[threadID]; + ((base = data.Conf['watchedThreads'].boards)[boardID] || (base[boardID] = {}))[threadID] = { + excerpt: threadData.textContent + }; + } + } + } + return data; + } + }, + upgrade: function(data, version) { + var boardID, changes, compareString, j, key, len, name, record, ref, ref1, ref2, ref3, ref4, ref5, rice, set, type, uids, value; + changes = {}; + set = function(key, value) { + return data[key] = changes[key] = value; + }; + compareString = version.replace(/\d+/g, function(x) { + return ('0000' + x).slice(-5); + }); + if (compareString < '00001.00011.00008.00000') { + if (data['Fixed Thread Watcher'] == null) { + set('Fixed Thread Watcher', (ref = data['Toggleable Thread Watcher']) != null ? ref : true); + } + if (data['Exempt Archives from Encryption'] == null) { + set('Exempt Archives from Encryption', (ref1 = data['Except Archives from Encryption']) != null ? ref1 : false); + } + } + if (compareString < '00001.00011.00010.00001') { + if (data['selectedArchives'] != null) { + uids = { + "Moe": 0, + "4plebs Archive": 3, + "Nyafuu Archive": 4, + "Love is Over": 5, + "Rebecca Black Tech": 8, + "warosu": 10, + "fgts": 15, + "not4plebs": 22, + "DesuStorage": 23, + "fireden.net": 24, + "disabled": null + }; + ref2 = data['selectedArchives']; + for (boardID in ref2) { + record = ref2[boardID]; + for (type in record) { + name = record[type]; + if (name in uids) { + record[type] = uids[name]; + } + } + } + set('selectedArchives', data['selectedArchives']); + } + } + if (compareString < '00001.00011.00016.00000') { + if ((rice = Config['usercss'].match(/\/\* Board title rice \*\/(?:\n.+)*/)[0])) { + if ((data['usercss'] != null) && data['usercss'].indexOf(rice) < 0) { + set('usercss', rice + '\n\n' + data['usercss']); + } + } + } + if (compareString < '00001.00011.00017.00000') { + ref3 = ['Persistent QR', 'Color User IDs', 'Fappe Tyme', 'Werk Tyme', 'Highlight Posts Quoting You', 'Highlight Own Posts']; + for (j = 0, len = ref3.length; j < len; j++) { + key = ref3[j]; + if (data[key] == null) { + set(key, key === 'Persistent QR'); + } + } + } + if (compareString < '00001.00011.00017.00006') { + if (data['sauces'] != null) { + set('sauces', data['sauces'].replace(/^(#?\s*)http:\/\/iqdb\.org\//mg, '$1//iqdb.org/')); + } + } + if (compareString < '00001.00011.00019.00003' && !Settings.overlay) { + $.queueTask(function() { + return Settings.warnings.ads(function(item) { + return new Notice('warning', slice.call(item.childNodes)); + }); + }); + } + if (compareString < '00001.00011.00020.00003') { + ref4 = { + 'Inline Cross-thread Quotes Only': false, + 'Pass Link': true + }; + for (key in ref4) { + value = ref4[key]; + if (data[key] == null) { + set(key, value); + } + } + } + if (compareString < '00001.00011.00021.00003') { + if (data['Remember Your Posts'] == null) { + set('Remember Your Posts', (ref5 = data['Mark Quotes of You']) != null ? ref5 : true); + } + } + if (compareString < '00001.00011.00022.00000') { + if (data['sauces'] != null) { + set('sauces', data['sauces'].replace(/^(#?\s*https:\/\/www\.google\.com\/searchbyimage\?image_url=%(?:IMG|URL))%3Fs\.jpg/mg, '$1')); + set('sauces', data['sauces'].replace(/^#?\s*https:\/\/www\.google\.com\/searchbyimage\?image_url=%(?:IMG|T?URL)(?=$|;)/mg, '$&&safe=off')); + } + } + if (compareString < '00001.00011.00022.00002') { + if ((data['Use Recaptcha v1 in Reports'] == null) && data['Use Recaptcha v1'] && !data['Use Recaptcha v2 in Reports']) { + set('Use Recaptcha v1 in Reports', true); + } + } + if (compareString < '00001.00011.00024.00000') { + if ((data['JSON Navigation'] != null) && (data['JSON Index'] == null)) { + set('JSON Index', data['JSON Navigation']); + } + } + if (compareString < '00001.00011.00026.00000') { + if ((data['Oekaki Links'] != null) && (data['Edit Link'] == null)) { + set('Edit Link', data['Oekaki Links']); + } + if (data['Inline Cross-thread Quotes Only'] == null) { + set('Inline Cross-thread Quotes Only', true); + } + } + if (compareString < '00001.00011.00030.00000') { + if (data['Quote Threading'] && (data['Thread Quotes'] == null)) { + set('Thread Quotes', true); + } + } + return changes; + }, + loadSettings: function(data, cb) { + if (data.version.split('.')[0] === '2') { + data = Settings.convertFrom.loadletter(data); + } else if (data.version !== g.VERSION) { + Settings.upgrade(data.Conf, data.version); + } + return $.clear(function(err) { + if (err) { + return cb(err); + } + return $.set(data.Conf, cb); + }); + }, + reset: function() { + if (confirm('Your current settings will be entirely wiped, are you sure?')) { + return $.clear(function(err) { + if (err) { + return $('.imp-exp-result').textContent = 'Import failed due to an error.'; + } else if (confirm('Reset successful. Reload now?')) { + return window.location.reload(); + } + }); + } + }, + filter: function(section) { + var select; + $.extend(section, { + innerHTML: "
          " + }); + select = $('select', section); + $.on(select, 'change', Settings.selectFilter); + return Settings.selectFilter.call(select); + }, + selectFilter: function() { + var div, name, ta; + div = this.nextElementSibling; + if ((name = this.value) !== 'guide') { + $.rmAll(div); + ta = $.el('textarea', { + name: name, + className: 'field', + spellcheck: false + }); + $.get(name, Conf[name], function(item) { + return ta.value = item[name]; + }); + $.on(ta, 'change', $.cb.value); + $.add(div, ta); + return; + } + $.extend(div, { + innerHTML: "
          Filter is disabled.

          Use regular expressions, one per line.
          Lines starting with a # will be ignored.
          For example, /weeaboo/i will filter posts containing the string \`weeaboo\`, case-insensitive.
          MD5 filtering uses exact string matching, not regular expressions.

            You can use these settings with each regular expression, separate them with semicolons:
          • Per boards, separate them with commas. It is global if not specified.
            For example: boards:a,jp;.
          • In case of a global rule, select boards to be excluded from the filter.
            For example: exclude:vg,v;.
          • Filter OPs only along with their threads (\`only\`), replies only (\`no\`), or both (\`yes\`, this is default).
            For example: op:only;, op:no; or op:yes;.
          • Overrule the \`Show Stubs\` setting if specified: create a stub (\`yes\`) or not (\`no\`).
            For example: stub:yes; or stub:no;.
          • Highlight instead of hiding. You can specify a class name to use with a userstyle.
            For example: highlight; or highlight:wallpaper;.
          • Highlighted OPs will have their threads put on top of the board index by default.
            For example: top:yes; or top:no;.

          Note: If you're using the native catalog rather than 4chan X's catalog, 4chan X's filters do not apply there.
          The native catalog has its own separate filter list.

          " + }); + return $('.warning', div).hidden = Conf['Filter']; + }, + sauce: function(section) { + var ta; + $.extend(section, { + innerHTML: "
          Sauce is disabled.
          Lines starting with a # will be ignored.
          You can specify a display text by appending ;text:[text] to the URL.
          You can specify the applicable boards by appending ;boards:[board1],[board2].
          You can specify the applicable file types by appending ;types:[extension1],[extension2].
          You can open links with scripts and popups disabled by appending ;sandbox.
            These parameters will be replaced by their corresponding values:
          • %TURL: Thumbnail URL.
          • %URL: Full image URL.
          • %IMG: Full image URL for GIF, JPG, and PNG; thumbnail URL for other types.
          • %MD5: MD5 hash in base64.
          • %sMD5: MD5 hash in base64 using - and _.
          • %hMD5: MD5 hash in hexadecimal.
          • %name: Original file name.
          • %board: Current board.
          • %%, %semi: Literal % and ;.
          " + }); + $('.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, archive, boardID, boardOptions, boardSelect, boards, customCSS, files, i, input, inputs, interval, item, items, j, k, l, len, len1, len2, len3, len4, len5, len6, m, n, name, o, q, r, ref, ref1, ref2, ref3, ref4, ref5, ref6, row, rows, software, ta, table, uid, warning, withCredentials; + $.extend(section, { + innerHTML: "
          Archiver
          404 Redirect is disabled.
          Thread redirectionPost fetchingFile redirection
          Captcha Language
          Choose from list of language codes. Leave blank to autoselect.
          Custom Board Navigation
          New lines will be converted into spaces.

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

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

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

            You can use these settings with each item, separate them with semicolons:
          • Possible items are: name, options (or equivalently email), subject and password.
          • Wrap values of items with quotes, like this: options:"sage".
          • Force values as defaults with the always keyword, for example: options:"sage";always.
          • Select specific boards for an item, separated with commas, for example: options:"sage";boards:jp;always.
          Unread Favicon is disabled.
          Thread Updater is disabled.
          Interval: seconds
          Custom Cooldown Time
          Seconds:
          " + }); + ref = $$('.warning', section); + for (j = 0, len = ref.length; j < len; j++) { + warning = ref[j]; + warning.hidden = Conf[warning.dataset.feature]; + } + items = {}; + inputs = {}; + ref1 = ['captchaLanguage', 'boardnav', 'time', 'backlink', 'fileInfo', 'favicon', 'usercss', 'customCooldown']; + for (k = 0, len1 = ref1.length; k < len1; k++) { + name = ref1[k]; + 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); + if (name in Settings) { + $.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 in Settings && key !== 'usercss') { + 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 (l = 0, len2 = ref2.length; l < len2; l++) { + ref3 = ref2[l], uid = ref3.uid, name = ref3.name, boards = ref3.boards, files = ref3.files, software = ref3.software, withCredentials = ref3.withCredentials; + for (m = 0, len3 = boards.length; m < len3; m++) { + boardID = boards[m]; + o = archBoards[boardID] || (archBoards[boardID] = { + thread: [[], []], + post: [[], []], + file: [[], []] + }); + i = +(!!withCredentials); + archive = [uid != null ? uid : name, name]; + o.thread[i].push(archive); + if (software === 'foolfuuka') { + o.post[i].push(archive); + } + if (indexOf.call(files, boardID) >= 0) { + o.file[i].push(archive); + } + } + } + for (boardID in archBoards) { + o = archBoards[boardID]; + ref4 = ['thread', 'post', 'file']; + for (n = 0, len4 = ref4.length; n < len4; n++) { + item = ref4[n]; + i = o[item][0].length ? 1 : 0; + o[item][i].push([null, 'disabled']); + o[item] = o[item][0].concat(o[item][1]); + } + } + rows = []; + boardOptions = []; + ref5 = Object.keys(archBoards).sort(); + for (q = 0, len5 = ref5.length; q < len5; q++) { + boardID = ref5[q]; + 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 (r = 0, len6 = ref6.length; r < len6; r++) { + item = ref6[r]; + $.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, id, select, selectedArchives, type; + selectedArchives = arg.selectedArchives; + for (boardID in selectedArchives) { + data = selectedArchives[boardID]; + for (type in data) { + id = data[type]; + if (select = $("select[data-boardid='" + boardID + "'][data-type='" + type + "']", section)) { + select.value = JSON.stringify(id); + } + } + } + }); + }, + 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', { + value: JSON.stringify(archive[0]), + textContent: archive[1] + })); + } + $.extend(td, { + innerHTML: "" + }); + select = td.firstElementChild; + if (!(select.disabled = length === 1)) { + select.setAttribute('data-boardid', boardID); + select.setAttribute('data-type', type); + $.on(select, 'change', Settings.saveSelectedArchive); + } + $.add(select, options); + return td; + }, + saveSelectedArchive: function() { + return $.get('selectedArchives', Conf['selectedArchives'], (function(_this) { + return function(arg) { + var name1, selectedArchives; + selectedArchives = arg.selectedArchives; + (selectedArchives[name1 = _this.dataset.boardid] || (selectedArchives[name1] = {}))[_this.dataset.type] = JSON.parse(_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, + isVideo: false, + isSpoiler: true, + tag: 'Loop' + } + }; + 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, ref, tbody, tr; + $.extend(section, { + innerHTML: "
          Keybinds are disabled.
          Allowed keys: a-z, 0-9, Ctrl, Shift, Alt, Meta, Enter, Esc, Up, Down, Right, Left.
          Press Backspace to disable a keybind.
          ActionsKeybinds
          " + }); + $('.warning', section).hidden = Conf['Keybinds']; + tbody = $('tbody', section); + items = {}; + inputs = {}; + ref = Config.hotkeys; + for (key in ref) { + arr = ref[key]; + tr = $.el('tr', { + innerHTML: "" + E(arr[1]) + "" + }); + input = $('input', tr); + input.name = key; + input.spellcheck = false; + items[key] = Conf[key]; + inputs[key] = input; + $.on(input, 'keydown', Settings.keybind); + $.add(tbody, tr); + } + return $.get(items, function(items) { + var val; + for (key in items) { + val = items[key]; + inputs[key].value = val; + } + }); + }, + keybind: function(e) { + var key; + if (e.keyCode === 9) { + return; + } + e.preventDefault(); + e.stopPropagation(); + if ((key = Keybinds.keyCode(e)) == null) { + return; + } + this.value = key; + return $.cb.value.call(this); + } + }; + + return Settings; + +}).call(this); + +UI = (function() { + var Menu, checkbox, dialog, drag, dragend, dragstart, hover, hoverend, hoverstart, touchend, touchmove, + bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, + slice = [].slice; + + dialog = function(id, position, properties) { + var child, el, i, len, move, 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); + this.setPosition = bind(this.setPosition, 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 entry, i, len, menu, ref; + 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 CloseMenu', this.close); + $.on(d, 'scroll', this.setPosition); + $.on(window, 'resize', this.setPosition); + $.add(button, menu); + this.setPosition(); + entry = $('.entry', menu); + this.focus(entry); + return menu.focus(); + }; + + Menu.prototype.setPosition = function() { + var bLeft, bRect, bTop, bottom, cHeight, cWidth, left, mRect, ref, ref1, right, top; + mRect = this.menu.getBoundingClientRect(); + bRect = lastToggledButton.getBoundingClientRect(); + bTop = window.scrollY + bRect.top; + bLeft = window.scrollX + bRect.left; + cHeight = doc.clientHeight; + cWidth = doc.clientWidth; + ref = bRect.top + bRect.height + mRect.height < cHeight ? [bRect.bottom + "px", ''] : ['', (cHeight - bRect.top) + "px"], top = ref[0], bottom = ref[1]; + ref1 = bRect.left + mRect.width < cWidth ? [bRect.left + "px", ''] : ['', (cWidth - bRect.right) + "px"], left = ref1[0], right = ref1[1]; + $.extend(this.menu.style, { + top: top, + right: right, + bottom: bottom, + left: left + }); + return this.menu.classList.toggle('left', right); + }; + + Menu.prototype.insertEntry = function(entry, parent, data) { + var err, i, len, ref, subEntry, submenu; + if (typeof entry.open === 'function') { + try { + if (!entry.open(data)) { + return; + } + } catch (_error) { + err = _error; + Main.handleErrors({ + message: "Error in building the " + this.type + " menu.", + error: err + }); + 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; + $.off(d, 'click scroll CloseMenu', this.close); + $.off(d, 'scroll', this.setPosition); + return $.off(window, 'resize', this.setPosition); + }; + + 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, i, left, len, ref, ref1, ref2, right, sRect, style, submenu, top; + 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, i, len, subEntries, subEntry; + 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, ref, screenHeight, screenWidth; + 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 i, len, ref, touch; + 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 i, len, ref, touch; + 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 cb, el, endEvents, height, latestEvent, noRemove, o, ref, root; + root = arg.root, el = arg.el, latestEvent = arg.latestEvent, endEvents = arg.endEvents, 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); + o.hover(o.latestEvent); + new MutationObserver(function() { + if (el.parentNode) { + return o.hover(o.latestEvent); + } + }).observe(el, { + childList: true + }); + $.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); + }; + + hoverstart.padding = 25; + + hover = function(e) { + var clientX, clientY, height, left, ref, right, style, threshold, top; + this.latestEvent = e; + height = (this.height || this.el.offsetHeight) + hoverstart.padding; + 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 + }; + +}).call(this); + +FappeTyme = (function() { + var FappeTyme; + + FappeTyme = { + init: function() { + var el, i, lc, len, ref, ref1, type; + if (!((Conf['Fappe Tyme'] || Conf['Werk Tyme']) && ((ref = g.VIEW) === 'index' || ref === 'thread'))) { + 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')); + } + Callbacks.Post.push({ + name: 'Fappe Tyme', + cb: this.node + }); + return Callbacks.CatalogThread.push({ + name: 'Werk Tyme', + cb: this.catalogNode + }); + }, + node: function() { + return this.nodes.root.classList.toggle('noFile', !this.file); + }, + 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]); + } + } + }; + + return FappeTyme; + +}).call(this); + +Gallery = (function() { + var Gallery; + + 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 Callbacks.Post.push({ + name: 'Gallery', + cb: this.node + }); + }, + node: function() { + var ref; + if (!((ref = this.file) != null ? ref.thumb : void 0)) { + 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, i, j, key, len, len1, menuButton, nodes, post, ref, ref1, ref2, ref3, thumb, value; + cb = Gallery.cb; + 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: "
          " + }); + 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'); + $.on(nodes.frame, 'click', cb.blank); + if (Conf['Mouse Wheel Volume']) { + $.on(nodes.frame, 'wheel', Volume.wheel); + } + $.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); + } + $.on(window, 'resize', Gallery.cb.setHeight); + ref2 = $$('.post .file'); + for (j = 0, len1 = ref2.length; j < len1; j++) { + file = ref2[j]; + post = Get.postFromNode(file); + if (!((ref3 = post.file) != null ? ref3.thumb : void 0)) { + 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.thumb && (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); + }, + load: function(thumb, errorCB) { + var elType, ext, file; + ext = thumb.href.match(/\w*$/); + elType = { + 'webm': 'video', + 'pdf': 'iframe' + }[ext] || 'img'; + file = $.el(elType, { + title: thumb.title + }); + $.extend(file.dataset, thumb.dataset); + $.on(file, 'error', errorCB); + file.src = thumb.href; + return file; + }, + open: function(thumb) { + var el, file, newID, nodes, oldID, post, ref; + nodes = Gallery.nodes; + oldID = +nodes.current.dataset.id; + newID = +thumb.dataset.id; + if (el = Gallery.images[oldID]) { + $.rmClass(el, 'gal-highlight'); + } + $.addClass(thumb, 'gal-highlight'); + nodes.thumbs.scrollTop = thumb.offsetTop + thumb.offsetHeight / 2 - nodes.thumbs.clientHeight / 2; + if (((ref = Gallery.cache) != null ? ref.dataset.id : void 0) === '' + newID) { + file = Gallery.cache; + $.off(file, 'error', Gallery.cacheError); + $.on(file, 'error', Gallery.error); + } else { + file = Gallery.load(thumb, Gallery.error); + } + $.off(nodes.current, 'error', Gallery.error); + ImageCommon.pause(nodes.current); + $.replace(nodes.current, file); + nodes.current = file; + if (file.nodeName === 'VIDEO') { + file.loop = true; + Volume.setup(file); + if (Conf['Autoplay']) { + file.play(); + } + if (Conf['Show Controls']) { + ImageCommon.addControls(file); + } + } + doc.classList.toggle('gal-pdf', file.nodeName === 'IFRAME'); + Gallery.cb.setHeight(); + nodes.count.textContent = +thumb.dataset.id + 1; + nodes.name.download = nodes.name.textContent = thumb.title; + nodes.name.href = thumb.href; + nodes.frame.scrollTop = 0; + nodes.next.focus(); + if (Gallery.slideshow && (newID > oldID || (oldID === Gallery.images.length - 1 && newID === 0))) { + Gallery.setupTimer(); + } else { + Gallery.cb.stop(); + } + if (Conf['Scroll to Post'] && (post = g.posts[file.dataset.post])) { + Header.scrollTo(post.nodes.root); + } + if (isNaN(oldID) || newID === (oldID + 1) % Gallery.images.length) { + return Gallery.cache = Gallery.load(Gallery.images[(newID + 1) % Gallery.images.length], Gallery.cacheError); + } + }, + 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)); + }, + cacheError: function() { + return delete Gallery.cache; + }, + 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 (!Conf['Autoplay'] && 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); + } + $.off(window, 'resize', Gallery.cb.setHeight); + return clearTimeout(Gallery.timeoutID); + }, + setFitness: function() { + return (this.checked ? $.addClass : $.rmClass)(doc, "gal-" + (this.name.toLowerCase().replace(/\s+/g, '-'))); + }, + setHeight: $.debounce(100, function() { + var current, dim, frame, height, minHeight, ref, ref1, ref2, style, width; + ref = Gallery.nodes, current = ref.current, frame = ref.frame; + style = current.style; + if (Conf['Stretch to Fit'] && (dim = (ref1 = g.posts[current.dataset.post]) != null ? ref1.file.dimensions : void 0)) { + ref2 = dim.split('x'), width = ref2[0], height = ref2[1]; + minHeight = Math.min(doc.clientHeight - 25, height / width * frame.clientWidth); + style.minHeight = minHeight + 'px'; + return style.minWidth = (width / height * minHeight) + 'px'; + } else { + return style.minHeight = style.minWidth = null; + } + }), + 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 === 'Hide Thumbnails' || name === 'Fit Width' || name === 'Fit Height') { + $.on(input, 'change', Gallery.cb.setFitness); + } + $.event('change', null, input); + $.on(input, 'change', $.cb.checked); + if (name === 'Hide Thumbnails' || name === 'Fit Width' || name === 'Fit Height' || name === 'Stretch to Fit') { + $.on(input, 'change', Gallery.cb.setHeight); + } + return { + el: label + }; + }, + createSubEntries: function() { + var delayInput, delayLabel, item, subEntries; + subEntries = (function() { + var i, len, ref, results; + ref = ['Hide Thumbnails', 'Fit Width', 'Fit Height', 'Stretch to Fit', '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: " + }); + delayInput = delayLabel.firstElementChild; + delayInput.value = Gallery.delay; + $.on(delayInput, 'change', Gallery.cb.setDelay); + $.on(delayInput, 'change', $.cb.value); + subEntries.push({ + el: delayLabel + }); + return subEntries; + } + } + }; + + return Gallery; + +}).call(this); + +ImageCommon = (function() { + var ImageCommon; + + 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 i, len, postObj, ref; + if (this.status === 404) { + post.kill(!post.isClone); + } + 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 $.engine !== 'gecko' || (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)); + } + }; + + return ImageCommon; + +}).call(this); + +ImageExpand = (function() { + var ImageExpand, + slice = [].slice; + + 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: " contract" + }); + return Callbacks.Post.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 (!Conf['Autoplay'] && ((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() { + return g.posts.forEach(function(post) { + var file, i, len, ref, video, visible; + 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, i, len, oldHeight, ref, ref1, scrollY, top, x; + 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'); + $.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, ref, thumb; + 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 = Math.min(doc.clientHeight - file.fullImage.getBoundingClientRect().bottom - 25, Header.getBottomOf(file.fullImage)); + 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, ref, subEntries; + 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 + }; + } + } + }; + + return ImageExpand; + +}).call(this); + +ImageHover = (function() { + var ImageHover; + + ImageHover = { + init: function() { + var ref; + if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { + return; + } + if (Conf['Image Hover']) { + Callbacks.Post.push({ + name: 'Image Hover', + cb: this.node + }); + } + if (Conf['Image Hover in Catalog']) { + return Callbacks.CatalogThread.push({ + name: 'Image Hover', + cb: this.catalogNode + }); + } + }, + node: function() { + if (!(this.file && (this.file.isImage || this.file.isVideo))) { + return; + } + return $.on(this.file.thumb, 'mouseover', ImageHover.mouseover(this)); + }, + catalogNode: function() { + var file; + file = this.thread.OP.file; + if (!(file && (file.isImage || file.isVideo))) { + return; + } + return $.on(this.nodes.thumb, 'mouseover', ImageHover.mouseover(this.thread.OP)); + }, + mouseover: function(post) { + return function(e) { + var el, error, file, height, isVideo, left, maxHeight, maxWidth, ref, ref1, ref2, right, scale, width, x; + 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; + maxWidth = Math.max(left, doc.clientWidth - right); + maxHeight = doc.clientHeight - UI.hover.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', + height: scale * height, + 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)); + }; + } + }; + + return ImageHover; + +}).call(this); + +ImageLoader = (function() { + var ImageLoader, + slice = [].slice; + + 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; + } + Callbacks.Post.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: " Prefetch Images" + }); + this.el = prefetch.firstElementChild; + $.on(this.el, 'change', this.toggle); + return Header.menu.addEntry({ + el: prefetch, + order: 98 + }); + }, + 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, i, len, ref, thumb, video; + file = post.file; + thumb = file.thumb; + video = $.el('video', { + preload: 'none', + loop: true, + muted: true, + poster: thumb.src || thumb.dataset.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 clone, el, file, i, isImage, isVideo, len, match, ref, replace, thumb, type, url; + 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 || thumb.dataset.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 ($.engine === 'gecko') { + $.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; + } + thumb.src = url; + return thumb.removeAttribute('data-src'); + }); + } + 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 i, len, ref1, ref2, thumb; + 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(); + } + } + }); + } + }; + + return ImageLoader; + +}).call(this); + +Metadata = (function() { + var Metadata; + + Metadata = { + init: function() { + var ref; + if (!(Conf['WEBM Metadata'] && ((ref = g.VIEW) === 'index' || ref === 'thread') && g.BOARD.ID !== 'f')) { + return; + } + return Callbacks.Post.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: "" + }); + $.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; + } + }; + + return Metadata; + +}).call(this); + +RevealSpoilers = (function() { + var RevealSpoilers; + + RevealSpoilers = { + init: function() { + var ref; + if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Reveal Spoiler Thumbnails'])) { + return; + } + return Callbacks.Post.push({ + name: 'Reveal Spoiler Thumbnails', + cb: this.node + }); + }, + node: function() { + var thumb; + if (!(!this.isClone && this.file && this.file.thumb && this.file.isSpoiler)) { + return; + } + thumb = this.file.thumb; + thumb.removeAttribute('style'); + thumb.style.maxHeight = thumb.style.maxWidth = this.isReply ? '125px' : '250px'; + if (thumb.src) { + return thumb.src = this.file.thumbURL; + } else { + return thumb.dataset.src = this.file.thumbURL; + } + } + }; + + return RevealSpoilers; + +}).call(this); + +Sauce = (function() { + var Sauce, + 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; }; + + Sauce = { + init: function() { + var err, j, len, link, links, ref, ref1; + if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Sauce'])) { + return; + } + links = []; + ref1 = Conf['sauces'].split('\n'); + for (j = 0, len = ref1.length; j < len; j++) { + link = ref1[j]; + 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', + className: 'sauce' + }); + return Callbacks.Post.push({ + name: 'Sauce', + cb: this.node + }); + }, + sandbox: function(url) { + return E.url({ + innerHTML: "[sb] " + E(url) + "" + }); + }, + rmOrigin: function(e) { + if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) { + return; + } + $.open(this.href); + return e.preventDefault(); + }, + createSauceLink: function(link, post) { + var a, ext, i, j, key, len, m, part, parts, ref, ref1, ref2, skip, url; + if (!(link = link.trim())) { + return null; + } + parts = {}; + ref = link.split(/;(?=(?:text|boards|types|sandbox):?)/); + for (i = j = 0, len = ref.length; j < len; i = ++j) { + 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) || '?'); + ext = post.file.url.match(/[^.]*$/)[0]; + skip = false; + for (key in parts) { + parts[key] = parts[key].replace(/%(T?URL|IMG|[sh]?MD5|board|name|%|semi)/g, function(_, parameter) { + var type; + type = Sauce.formatters[parameter](post, ext); + if (type == null) { + skip = true; + return ''; + } + if (key === 'url' && (parameter !== '%' && parameter !== 'semi')) { + if (/^javascript:/i.test(parts['url'])) { + type = JSON.stringify(type); + } + type = encodeURIComponent(type); + } + return type; + }); + } + if (skip) { + return null; + } + if (!(!parts['boards'] || (ref2 = post.board.ID, indexOf.call(parts['boards'].split(','), ref2) >= 0))) { + return null; + } + if (!(!parts['types'] || indexOf.call(parts['types'].split(','), ext) >= 0)) { + return null; + } + url = parts['url']; + if (parts['sandbox'] != null) { + url = Sauce.sandbox(url); + } + a = Sauce.link.cloneNode(true); + a.href = url; + a.textContent = parts['text']; + if (/^javascript:/i.test(parts['url'])) { + a.removeAttribute('target'); + } + if (parts['sandbox'] != null) { + $.on(a, 'click', Sauce.rmOrigin); + } + return a; + }, + node: function() { + var j, len, link, node, nodes, ref; + if (this.isClone || !this.file) { + return; + } + nodes = []; + ref = Sauce.links; + for (j = 0, len = ref.length; j < len; j++) { + link = ref[j]; + if (node = Sauce.createSauceLink(link, this)) { + nodes.push($.tn('\u00A0'), node); + } + } + return $.add(this.file.text, nodes); + }, + formatters: { + TURL: function(post) { + return post.file.thumbURL; + }, + URL: function(post) { + return post.file.url; + }, + IMG: function(post, ext) { + if (ext === 'gif' || ext === 'jpg' || ext === 'png') { + return post.file.url; + } else { + return post.file.thumbURL; + } + }, + MD5: function(post) { + return post.file.MD5; + }, + sMD5: function(post) { + var ref; + return (ref = post.file.MD5) != null ? ref.replace(/[+\/=]/g, function(c) { + return { + '+': '-', + '/': '_', + '=': '' + }[c]; + }) : void 0; + }, + hMD5: function(post) { + var c; + if (post.file.MD5) { + return ((function() { + var j, len, ref, results; + ref = atob(post.file.MD5); + results = []; + for (j = 0, len = ref.length; j < len; j++) { + c = ref[j]; + results.push(("0" + (c.charCodeAt(0).toString(16))).slice(-2)); + } + return results; + })()).join(''); + } + }, + board: function(post) { + return post.board.ID; + }, + name: function(post) { + return post.file.name; + }, + '%': function() { + return '%'; + }, + semi: function() { + return ';'; + } + } + }; + + return Sauce; + +}).call(this); + +Volume = (function() { + var Volume; + + Volume = { + init: function() { + var ref, ref1, unmuteEntry, volumeEntry; + 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 (Conf['Mouse Wheel Volume']) { + Callbacks.Post.push({ + name: 'Mouse Wheel Volume', + cb: this.node + }); + } + if ((ref1 = g.BOARD.ID) !== 'gif' && ref1 !== 'wsg') { + return; + } + if (Conf['Mouse Wheel Volume']) { + Callbacks.CatalogThread.push({ + name: 'Mouse Wheel Volume', + cb: this.catalogNode + }); + } + 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: " 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, key, muted, val, volume; + muted = this.muted, volume = this.volume; + items = { + 'Allow Sound': !muted, + 'Default Volume': volume + }; + for (key in items) { + val = items[key]; + if (Conf[key] === val) { + delete items[key]; + } + } + $.set(items); + $.extend(Conf, items); + if (Volume.inputs) { + Volume.inputs.unmute.checked = !muted; + return Volume.inputs.volume.value = volume; + } + }, + node: function() { + var ref, ref1; + if (!(((ref = this.board.ID) === 'gif' || ref === 'wsg') && ((ref1 = this.file) != null ? ref1.isVideo : void 0))) { + return; + } + $.on(this.file.thumb, 'wheel', Volume.wheel.bind(Header.hover)); + return $.on($('a', this.file.text), 'wheel', Volume.wheel.bind(this.file.thumb.parentNode)); + }, + catalogNode: function() { + var file; + file = this.thread.OP.file; + if (!(file != null ? file.isVideo : void 0)) { + return; + } + return $.on(this.nodes.thumb, 'wheel', Volume.wheel.bind(Header.hover)); + }, + wheel: function(e) { + var el, volume; + if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) { + return; + } + if (!(el = $('video:not([data-md5])', this))) { + 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(); + } + }; + + return Volume; + +}).call(this); + +Embedding = (function() { + var Embedding; + + Embedding = { + init: function() { + var j, len, ref, type; + if (!(Conf['Embedding'] || Conf['Link Title'])) { + return; + } + this.types = {}; + ref = this.ordered_types; + for (j = 0, len = ref.length; j < len; j++) { + type = ref[j]; + this.types[type.key] = type; + } + if (Conf['Floating Embeds']) { + this.dialog = UI.dialog('embedding', 'top: 50px; right: 0px;', { + innerHTML: "
          " + }); + this.media = $('#media-embed', this.dialog); + $.one(d, '4chanXInitFinished', this.ready); + } + if (Conf['Link Title']) { + return $.on(d, '4chanXInitFinished PostsInserted', function() { + var key, ref1, ref2, service; + 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, j, len, match, ref, type; + href = link.href; + ref = Embedding.ordered_types; + for (j = 0, len = ref.length; j < len; j++) { + type = ref[j]; + if (!(match = type.regExp.exec(href))) { + continue; + } + if (type.dummy) { + return; + } + return { + key: type.key, + uid: match[1], + options: match[2], + link: link + }; + } + }, + embed: function(data) { + var embed, href, key, link, name, options, post, ref, uid, value; + key = data.key, uid = data.uid, options = data.options, link = data.link, post = data.post; + href = link.href; + if (Embedding.types[key].httpOnly && location.protocol !== 'http:') { + return; + } + $.addClass(link, key.toLowerCase()); + embed = $.el('a', { + className: 'embedder', + href: 'javascript:;', + textContent: '(embed)' + }); + ref = { + key: key, + uid: uid, + options: options, + href: href + }; + for (name in ref) { + value = ref[name]; + embed.dataset[name] = value; + } + $.on(embed, 'click', Embedding.cb.toggle); + $.after(link, [$.tn(' '), embed]); + if (Conf['Auto-embed'] && !Conf['Floating Embeds'] && !post.isFetchedQuote && key !== 'TwitchTV') { + 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; + } + $.addClass(link, key.toLowerCase()); + 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) + "] Title Link Blocked (are you using NoScript?)" + }); + } + } + }, + flushTitles: function(service) { + var cb, data, j, len, queue; + queue = service.queue; + if (!(queue != null ? queue.length : void 0)) { + return; + } + service.queue = []; + cb = function() { + var data, j, len; + for (j = 0, len = queue.length; j < len; j++) { + data = queue[j]; + Embedding.cb.title(this, data); + } + }; + if (!$.cache(service.api((function() { + var j, len, results; + results = []; + for (j = 0, len = queue.length; j < len; j++) { + data = queue[j]; + results.push(data.uid); + } + return results; + })()), cb, { + responseType: 'json' + })) { + for (j = 0, len = queue.length; j < len; j++) { + data = queue[j]; + $.extend(data.link, { + innerHTML: "[" + E(data.key) + "] Title Link Blocked (are you using NoScript?)" + }); + } + } + }, + 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: none; width: 640px; height: 360px;'; + return container; + }, + title: function(req, data) { + var base1, j, k, key, len, len1, link, link2, options, post, post2, ref, ref1, service, status, text, uid; + 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 (j = 0, len = ref.length; j < len; j++) { + post2 = ref[j]; + ref1 = $$('a.linkify', post2.nodes.comment); + for (k = 0, len1 = ref1.length; k < len1; k++) { + link2 = ref1[k]; + if (!(link2.href === link.href)) { + continue; + } + if ((base1 = link2.dataset).original == null) { + base1.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.dataset.href + }); + } + }, { + key: 'Dailymotion', + regExp: /^\w+:\/\/(?:(?:www\.)?dailymotion\.com\/(?:embed\/)?video|dai\.ly)\/([A-Za-z0-9]+)[^?]*(.*)/, + el: function(a) { + var el, options, start; + options = (start = a.dataset.options.match(/[?&](start=\d+)/)) ? "?" + start[1] : ''; + el = $.el('iframe', { + src: "//www.dailymotion.com/embed/video/" + a.dataset.uid + options + }); + el.setAttribute("allowfullscreen", "true"); + return el; + }, + title: { + api: function(uid) { + return "https://api.dailymotion.com/video/" + uid; + }, + text: function(_) { + return _.title; + } + } + }, { + 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: "" + E(a.dataset.uid) + "" + }; + el.src = E.url(content); + 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: "" + }); + } + }, { + 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', { + src: "http://www.liveleak.com/ll_embed?i=" + a.dataset.uid + }); + el.setAttribute("allowfullscreen", "true"); + 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)?)/, + style: 'border: 0; width: 600px; height: 406px;', + el: function(a) { + return $.el('iframe', { + src: "//strawpoll.me/embed_1/" + a.dataset.uid + }); + } + }, { + key: 'TwitchTV', + regExp: /^\w+:\/\/(?:www\.)?twitch\.tv\/(\w[^#\&\?]*)/, + style: "border: none; width: 620px; height: 378px;", + el: function(a) { + var _, channel, flashvars, id, idprefix, j, len, obj, part, ref, result, seconds, start, type; + if (result = /(\w+)\/([bcv])\/(\d+)/i.exec(a.dataset.uid)) { + _ = result[0], channel = result[1], type = result[2], id = result[3]; + idprefix = type === 'b' ? 'a' : type; + flashvars = "channel=" + channel + "&start_volume=25&auto_play=false&videoId=" + idprefix + id; + if (start = a.dataset.href.match(/\bt=(\w+)/)) { + seconds = 0; + ref = start[1].match(/\d+[hms]/g); + for (j = 0, len = ref.length; j < len; j++) { + part = ref[j]; + seconds += +part.slice(0, -1) * { + 'h': 3600, + 'm': 60, + 's': 1 + }[part.slice(-1)]; + } + flashvars += "&initial_time=" + seconds; + } + } else { + channel = (/(\w+)/.exec(a.dataset.uid))[0]; + flashvars = "channel=" + channel + "&start_volume=25&auto_play=false"; + } + obj = $.el('object', { + data: '//www-cdn.jtvnw.net/swflibs/TwitchPlayer.swf' + }); + $.extend(obj, { + innerHTML: "" + }); + obj.children[1].value = flashvars; + return obj; + } + }, { + key: 'Vocaroo', + regExp: /^\w+:\/\/(?:www\.)?vocaroo\.com\/i\/(\w+)/, + style: '', + el: function(a) { + var el, type; + el = $.el('audio', { + controls: true, + preload: 'auto' + }); + type = el.canPlayType('audio/webm') ? 'webm' : 'mp3'; + el.src = "http://vocaroo.com/media_command.php?media=" + a.dataset.uid + "&command=download_" + type; + return el; + } + }, { + 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=https://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=|\bembed\/|\bv\/))([\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, j, len, ref; + ref = data.items; + for (j = 0, len = ref.length; j < len; j++) { + item = ref[j]; + if (item.id === uid) { + return item.snippet.title; + } + } + return 'Not Found'; + } + } + }, { + key: 'Loopvid', + regExp: /^\w+:\/\/(?:www\.)?loopvid.appspot.com\/#?((?:pf|kd|lv|gd|gh|db|dx|nn|cp|wu|ig|ky|mf|pc|gc)\/[\w\-\/]+(,[\w\-\/]+)*|fc\/\w+\/\d+)/, + style: 'max-width: 80vw; max-height: 80vh;', + el: function(a) { + var _, base, el, host, j, k, len, len1, name, names, ref, ref1, type, types, url; + el = $.el('video', { + controls: true, + preload: 'auto', + loop: true + }); + ref = a.dataset.uid.match(/(\w+)\/(.*)/), _ = ref[0], host = ref[1], names = ref[2]; + types = (function() { + switch (host) { + case 'gd': + case 'wu': + case 'fc': + return ['']; + case 'gc': + return ['giant', 'fat', 'zippy']; + default: + return ['.webm', '.mp4']; + } + })(); + ref1 = names.split(','); + for (j = 0, len = ref1.length; j < len; j++) { + name = ref1[j]; + for (k = 0, len1 = types.length; k < len1; k++) { + type = types[k]; + base = "" + name + type; + url = (function() { + switch (host) { + case 'pf': + return "https://web.archive.org/web/2/http://a.pomf.se/" + base; + case 'kd': + return "http://kastden.org/loopvid/" + base; + case 'lv': + return "http://kastden.org/_loopvid_media/lv/" + 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://dl.dropboxusercontent.com/u/" + base; + case 'dx': + return "https://dl.dropboxusercontent.com/" + base; + case 'nn': + return "http://naenara.eu/loopvids/" + base; + case 'cp': + return "https://copy.com/" + base; + case 'wu': + return "http://webmup.com/" + base + "/vid.webm"; + case 'ig': + return "https://i.imgur.com/" + base; + case 'ky': + return "https://kiyo.me/" + base; + case 'mf': + return "https://d.maxfile.ro/" + base; + case 'pc': + return "http://a.pomf.cat/" + base; + case 'fc': + return "//i.4cdn.org/" + base + ".webm"; + case 'gc': + return "https://" + type + ".gfycat.com/" + name + ".webm"; + } + })(); + $.add(el, $.el('source', { + src: url + })); + } + } + return el; + } + }, { + key: 'Clyp', + regExp: /^\w+:\/\/(?:www\.)?clyp\.it\/(\w+)/, + style: '', + el: function(a) { + var el, type; + el = $.el('audio', { + controls: true, + preload: 'auto' + }); + type = el.canPlayType('audio/ogg') ? 'ogg' : 'mp3'; + el.src = "https://clyp.it/" + a.dataset.uid + "." + type; + return el; + } + }, { + 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.dataset.href, + loop: /^https?:\/\/i\.4cdn\.org\//.test(a.dataset.href) + }); + } + } + ] + }; + + return Embedding; + +}).call(this); + +Linkify = (function() { + var Linkify; + + Linkify = { + init: function() { + var ref; + if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Linkify']) { + return; + } + if (Conf['Comment Expansion']) { + ExpandComment.callbacks.push(this.node); + } + Callbacks.Post.push({ + name: 'Linkify', + cb: this.node + }); + Callbacks.CatalogThread.push({ + name: 'Linkify', + cb: this.catalogNode + }); + return Embedding.init(); + }, + node: function() { + var j, k, len, len1, link, links, ref; + if (this.isClone) { + return Embedding.events(this); + } + if (!Linkify.regString.test(this.info.comment)) { + return; + } + ref = $$('a[href^="http://i.4cdn.org/"], a[href^="https://i.4cdn.org/"]', this.nodes.comment); + for (j = 0, len = ref.length; j < len; j++) { + link = ref[j]; + $.addClass(link, 'linkify'); + Embedding.process(link, this); + } + links = Linkify.process(this.nodes.comment); + for (k = 0, len1 = links.length; k < len1; k++) { + link = links[k]; + 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, part1, part2, ref, ref1, 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') { + if ((part1 = word.match(/(https?:\/\/)?([a-z\d-]+\.)*[a-z\d-]+$/i)) && (part2 = (ref = snapshot.snapshotItem(i)) != null ? (ref1 = ref.data) != null ? ref1.match(/^(\.[a-z\d-]+)*\//i) : void 0 : void 0) && (part1[0] + part2[0]).search(Linkify.regString) === 0) { + continue; + } else { + 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|xyz|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, encodedDomain, 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; + } + if (encodedDomain = text.match(/^(https?:\/\/[^\/]*%[0-9a-f]{2})(.*)$/i)) { + text = encodedDomain[1].replace(/%([0-9a-f]{2})/ig, function(x, y) { + if (y === '25') { + return x; + } else { + return String.fromCharCode(parseInt(y, 16)); + } + }) + encodedDomain[2]; + } + a = $.el('a', { + className: 'linkify', + rel: 'nofollow noreferrer', + target: '_blank', + href: text + }); + $.add(a, range.extractContents()); + range.insertNode(a); + return a; + } + }; + + return Linkify; + +}).call(this); + +ArchiveLink = (function() { + var ArchiveLink; + + ArchiveLink = { + init: function() { + var div, entry, i, len, ref, ref1, type; + 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'], ['Capcode', 'capcode'], ['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 + }; + } + }; + + return ArchiveLink; + +}).call(this); + +DeleteLink = (function() { + var DeleteLink; + + DeleteLink = { + auto: [{}, {}], + 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:;' + }); + this.nodes = { + menu: div.firstChild, + links: [postEl, fileEl] + }; + postEntry = { + el: postEl, + open: function() { + postEl.textContent = DeleteLink.linkText(false); + $.on(postEl, 'click', DeleteLink.toggle); + return true; + } + }; + fileEntry = { + el: fileEl, + open: function(arg) { + var file; + file = arg.file; + if (!file || file.isDead) { + return false; + } + fileEl.textContent = DeleteLink.linkText(true); + $.on(fileEl, 'click', DeleteLink.toggle); + return true; + } + }; + return Menu.menu.addEntry({ + el: div, + order: 40, + open: function(post) { + if (post.isDead) { + return false; + } + DeleteLink.post = post; + DeleteLink.nodes.menu.textContent = DeleteLink.menuText(); + DeleteLink.cooldown.start(post); + return true; + }, + subEntries: [postEntry, fileEntry] + }); + }, + menuText: function() { + var seconds; + if (seconds = DeleteLink.cooldown.seconds[DeleteLink.post.fullID]) { + return "Delete (" + seconds + ")"; + } else { + return 'Delete'; + } + }, + linkText: function(fileOnly) { + var text; + text = fileOnly ? 'File' : 'Post'; + if (DeleteLink.auto[+fileOnly][DeleteLink.post.fullID]) { + text = "Deleting " + (text.toLowerCase()) + "..."; + } + return text; + }, + toggle: function() { + var auto, fileOnly, post; + post = DeleteLink.post; + fileOnly = $.hasClass(this, 'delete-file'); + auto = DeleteLink.auto[+fileOnly]; + if (auto[post.fullID]) { + delete auto[post.fullID]; + } else { + auto[post.fullID] = true; + } + this.textContent = DeleteLink.linkText(fileOnly); + if (!DeleteLink.cooldown.seconds[post.fullID]) { + return DeleteLink["delete"](post, fileOnly); + } + }, + "delete": function(post, fileOnly) { + var form, link; + link = DeleteLink.nodes.links[+fileOnly]; + delete DeleteLink.auto[+fileOnly][post.fullID]; + if (post.fullID === DeleteLink.post.fullID) { + $.off(link, 'click', DeleteLink.toggle); + } + form = { + mode: 'usrdel', + onlyimgdel: fileOnly, + pwd: QR.persona.getPassword() + }; + form[post.ID] = 'delete'; + 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, post); + } + }, { + form: $.formData(form) + }); + }, + load: function(link, post, fileOnly, resDoc) { + var el, msg; + link.textContent = DeleteLink.linkText(fileOnly); + if (resDoc.title === '4chan - Banned') { + el = $.el('span', { + innerHTML: "You can't delete posts because you are banned." + }); + return new Notice('warning', el, 20); + } else if (msg = resDoc.getElementById('errmsg')) { + new Notice('warning', msg.textContent, 20); + if (post.fullID === DeleteLink.post.fullID) { + $.on(link, 'click', DeleteLink.toggle); + } + if (QR.cooldown.data && Conf['Cooldown'] && /\bwait\b/i.test(msg.textContent)) { + DeleteLink.cooldown.start(post, 5); + DeleteLink.auto[+fileOnly][post.fullID] = true; + return DeleteLink.nodes.links[+fileOnly].textContent = DeleteLink.linkText(fileOnly); + } + } else { + if (!fileOnly) { + QR.cooldown["delete"](post); + } + if (resDoc.title === 'Updating index...') { + (post.origin || post).kill(fileOnly); + } + if (post.fullID === DeleteLink.post.fullID) { + return link.textContent = 'Deleted'; + } + } + }, + error: function(link, post) { + new Notice('warning', 'Connection error, please retry.', 20); + if (post.fullID === DeleteLink.post.fullID) { + return $.on(link, 'click', DeleteLink.toggle); + } + }, + cooldown: { + seconds: {}, + start: function(post, seconds) { + if (DeleteLink.cooldown.seconds[post.fullID] != null) { + return; + } + if (seconds == null) { + seconds = QR.cooldown.secondsDeletion(post); + } + if (seconds > 0) { + DeleteLink.cooldown.seconds[post.fullID] = seconds; + return DeleteLink.cooldown.count(post); + } + }, + count: function(post) { + var fileOnly, i, len, ref; + if (post.fullID === DeleteLink.post.fullID) { + DeleteLink.nodes.menu.textContent = DeleteLink.menuText(); + } + if (DeleteLink.cooldown.seconds[post.fullID] > 0 && Conf['Cooldown']) { + DeleteLink.cooldown.seconds[post.fullID]--; + setTimeout(DeleteLink.cooldown.count, 1000, post); + } else { + delete DeleteLink.cooldown.seconds[post.fullID]; + ref = [false, true]; + for (i = 0, len = ref.length; i < len; i++) { + fileOnly = ref[i]; + if (DeleteLink.auto[+fileOnly][post.fullID]) { + DeleteLink["delete"](post, fileOnly); + } + } + } + } + } + }; + + return DeleteLink; + +}).call(this); + +DownloadLink = (function() { + var DownloadLink; + + 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; + } + }); + } + }; + + return DownloadLink; + +}).call(this); + +Menu = (function() { + var Menu; + + 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: "" + }); + this.menu = new UI.Menu('post'); + Callbacks.Post.push({ + name: 'Menu', + cb: this.node + }); + return Callbacks.CatalogThread.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; + } + }; + + return Menu; + +}).call(this); + +ReportLink = (function() { + var ReportLink; + + 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:;' + }); + $.on(a, 'click', ReportLink.report); + return Menu.menu.addEntry({ + el: a, + order: 10, + open: function(post) { + if (!(post.isDead || (post.thread.isDead && !post.thread.isArchived))) { + a.textContent = 'Report'; + ReportLink.url = "//sys.4chan.org/" + post.board + "/imgboard.php?mode=report&no=" + post; + if ((Conf['Use Recaptcha v1 in Reports'] && Main.jsEnabled) || d.cookie.indexOf('pass_enabled=1') >= 0) { + ReportLink.url += '&altc=1'; + ReportLink.dims = 'width=350,height=275'; + } else { + ReportLink.dims = 'width=400,height=550'; + } + } else if (Conf['Archive Report']) { + a.textContent = 'Report to archive'; + ReportLink.url = Redirect.to('report', { + boardID: post.board.ID, + postID: post.ID + }); + ReportLink.dims = 'width=700,height=475'; + } else { + ReportLink.url = ''; + } + return !!ReportLink.url; + } + }); + }, + report: function() { + var dims, id, set, url; + url = ReportLink.url, dims = ReportLink.dims; + id = Date.now(); + set = "toolbar=0,scrollbars=1,location=0,status=1,menubar=0,resizable=1," + dims; + return window.open(url, id, set); + } + }; + + return ReportLink; + +}).call(this); + +AntiAutoplay = (function() { + var AntiAutoplay; + + 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); + Callbacks.Post.push({ + name: 'Disable Autoplaying Sounds', + cb: this.node + }); + Callbacks.CatalogThread.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 i, iframe, j, len, len1, object, 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', ''); + $.addClass(iframe, 'autoplay-removed'); + } + 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', ''); + $.addClass(object, 'autoplay-removed'); + } + } + }; + + return AntiAutoplay; + +}).call(this); + +Banner = (function() { + var Banner, + slice = [].slice; + + 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","79.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","256.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","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 base, br, j, 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 (j = 0, len = ref.length; j < len; j++) { + br = ref[j]; + $.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, j, len, ref; + ref = $$('br', this); + for (j = 0, len = ref.length; j < len; j++) { + br = ref[j]; + $.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, j, len, ref, string, string2; + className = child.className; + child.title = "Ctrl/\u2318+click to edit board " + (className.slice(5).toLowerCase()); + child.spellcheck = false; + ref = ['click', 'keydown', 'blur']; + for (j = 0, len = ref.length; j < len; j++) { + event = ref[j]; + $.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 + }); + } + } + } + }; + + return Banner; + +}).call(this); + +CatalogLinks = (function() { + var CatalogLinks; + + CatalogLinks = { + init: function() { + var el, input, selector; + if ((Conf['External Catalog'] || Conf['JSON Index']) && !(Conf['JSON Index'] && 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, i, len, link, ref; + ref = $$(selector); + for (i = 0, len = ref.length; i < len; i++) { + link = ref[i]; + switch (link.pathname.replace(/\/+/g, '/')) { + case "/" + g.BOARD + "/": + if (Conf['JSON Index']) { + link.textContent = 'Index'; + } + link.href = CatalogLinks.index(); + break; + case "/" + g.BOARD + "/catalog": + link.href = CatalogLinks.catalog(); + } + if (g.VIEW === 'catalog' && Conf['JSON Index'] && 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 Index'] && Conf['Use 4chan X Catalog']) { + Callbacks.Post.push({ + name: 'Catalog Link Rewrite', + cb: this.node + }); + Callbacks.CatalogThread.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, i, len, m, 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 (!CatalogLinks.el) { + 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') || !(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 + "/"; + if (a.dataset.indexOptions && a.hostname === 'boards.4chan.org' && a.pathname.split('/')[2] === '') { + a.href += (a.hash ? '/' : '#') + a.dataset.indexOptions; + } + } + 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 Index'] && 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 Index'] && board !== 'f') { + if (g.BOARD.ID === board && g.VIEW === 'index') { + return '#index'; + } else { + return "/" + board + "/#index"; + } + } else { + return "/" + board + "/"; + } + } + }; + + return CatalogLinks; + +}).call(this); + +CustomCSS = (function() { + var CustomCSS; + + CustomCSS = { + init: function() { + if (!Conf['Custom CSS']) { + return; + } + return this.addStyle(); + }, + addStyle: function() { + return this.style = $.addStyle(Conf['usercss'], 'custom-css', '#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']; + } + }; + + return CustomCSS; + +}).call(this); + +ExpandComment = (function() { + var ExpandComment; + + ExpandComment = { + init: function() { + if (g.VIEW !== 'index' || !Conf['Comment Expansion'] || Conf['JSON Index']) { + return; + } + if (g.BOARD.ID === 'g') { + this.callbacks.push(Fourchan.code); + } + if (g.BOARD.ID === 'sci') { + this.callbacks.push(Fourchan.math); + } + return Callbacks.Post.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, i, j, k, len, len1, len2, postObj, posts, quote, ref, ref1, spoilerRange, status; + 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); + } + } + }; + + return ExpandComment; + +}).call(this); + +ExpandThread = (function() { + var ExpandThread, + slice = [].slice; + + ExpandThread = { + statuses: {}, + init: function() { + if (g.VIEW === 'thread' || !Conf['Thread Expansion']) { + return; + } + if (Conf['JSON Index']) { + return $.on(d, 'IndexRefresh', this.onIndexRefresh); + } else { + return Callbacks.Thread.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 = Build.summaryText.apply(Build, ['+'].concat(slice.call(a.textContent.match(/\d+/g)))); + a.style.cursor = 'pointer'; + return $.on(a, 'click', ExpandThread.cbToggle); + }, + disconnect: function(refresh) { + var ref, ref1, status, threadID; + 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); + }); + }, + 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); + } + }, + expand: function(thread, a) { + var status; + ExpandThread.statuses[thread] = status = {}; + a.textContent = Build.summaryText.apply(Build, ['...'].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, i, inlined, len, num, postsCount, replies, reply, status; + status = ExpandThread.statuses[thread]; + delete ExpandThread.statuses[thread]; + if (status.req) { + status.req.abort(); + if (a) { + a.textContent = Build.summaryText.apply(Build, ['+'].concat(slice.call(a.textContent.match(/\d+/g)))); + } + return; + } + replies = $$('.thread > .replyContainer', threadRoot); + if (!Conf['JSON Index'] || 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 = Build.summaryText('+', postsCount, filesCount); + }, + parse: function(req, thread, a) { + var filesCount, i, len, post, postData, posts, postsCount, postsRoot, ref, ref1, root; + 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 = Build.summaryText('-', postsCount, filesCount); + } + }; + + return ExpandThread; + +}).call(this); + +FileInfo = (function() { + var FileInfo; + + FileInfo = { + init: function() { + var ref; + if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['File Info Formatting']) { + return; + } + return Callbacks.Post.push({ + name: 'File Info Formatting', + cb: this.node + }); + }, + node: function() { + var info, oldInfo; + if (!this.file || this.isClone) { + return; + } + oldInfo = $.el('span', { + className: 'fileText-original' + }); + $.prepend(this.file.link.parentNode, oldInfo); + $.add(oldInfo, [this.file.link.previousSibling, this.file.link, this.file.link.nextSibling]); + info = $.el('span', { + className: 'file-info' + }); + FileInfo.format(Conf['fileInfo'], this, info); + return $.prepend(this.file.text, info); + }, + 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: E.cat(output) + }); + }, + formatters: { + t: function() { + return { + innerHTML: E(this.file.url.match(/[^/]*$/)[0]) + }; + }, + T: function() { + return { + innerHTML: "" + (FileInfo.formatters.t.call(this)).innerHTML + "" + }; + }, + l: function() { + return { + innerHTML: "" + (FileInfo.formatters.n.call(this)).innerHTML + "" + }; + }, + L: function() { + return { + innerHTML: "" + (FileInfo.formatters.N.call(this)).innerHTML + "" + }; + }, + 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: "" + E(shortname) + "" + E(fullname) + "" + }; + } + }, + N: function() { + return { + innerHTML: E(this.file.name) + }; + }, + p: function() { + return { + innerHTML: ((this.file.isSpoiler) ? "Spoiler, " : "") + }; + }, + 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") + }; + }, + g: function() { + return { + innerHTML: ((this.file.tag) ? ", " + E(this.file.tag) : "") + }; + }, + '%': function() { + return { + innerHTML: "%" + }; + } + } + }; + + return FileInfo; + +}).call(this); + +Flash = (function() { + var Flash; + + Flash = { + init: function() { + if (g.BOARD.ID === 'f' && Conf['Enable Native Flash Embedding']) { + return $.ready(Flash.initReady); + } + }, + initReady: function() { + if ($.hasStorage) { + return $.global(function() { + if (JSON.parse(localStorage['4chan-settings'] || '{}').disableAll) { + return window.SWFEmbed.init(); + } + }); + } else { + if (g.VIEW === 'thread') { + $.global(function() { + return window.Main.tid = location.pathname.split(/\/+/)[3]; + }); + } + return $.global(function() { + return window.SWFEmbed.init(); + }); + } + } + }; + + return Flash; + +}).call(this); + +Fourchan = (function() { + var Fourchan; + + Fourchan = { + init: function() { + var ref; + if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { + return; + } + if (g.BOARD.ID === 'g') { + $.on(window, 'prettyprint:cb', function(e) { + var post, pre; + if (!(post = g.posts[e.detail.ID])) { + return; + } + if (!(pre = $$('.prettyprint', post.nodes.comment)[e.detail.i])) { + return; + } + if (!$.hasClass(pre, 'prettyprinted')) { + pre.innerHTML = e.detail.html; + return $.addClass(pre, 'prettyprinted'); + } + }); + $.globalEval('window.addEventListener(\'prettyprint\', function(e) {\n window.dispatchEvent(new CustomEvent(\'prettyprint:cb\', {\n detail: {\n ID: e.detail.ID,\n i: e.detail.i,\n html: prettyPrintOne(e.detail.html)\n }\n }));\n}, false);'); + Callbacks.Post.push({ + name: 'Parse /g/ code', + cb: this.code + }); + } + if (g.BOARD.ID === 'sci') { + $.global(function() { + return window.addEventListener('mathjax', function(e) { + if (window.MathJax) { + return window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub, e.target]); + } else { + if (!document.querySelector('script[src^="//cdn.mathjax.org/"]')) { + window.loadMathJax(); + window.loadMathJax = function() {}; + } + if (!e.target.classList.contains('postMessage')) { + return document.querySelector('script[src^="//cdn.mathjax.org/"]').addEventListener('load', function() { + return window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub, e.target]); + }, false); + } + } + }, false); + }); + Callbacks.Post.push({ + name: 'Parse /sci/ math', + cb: this.math + }); + Callbacks.CatalogThread.push({ + name: 'Parse /sci/ math', + cb: this.math + }); + } + return Main.ready(function() { + return $.global(function() { + var j, len, node, ref1; + window.clickable_ids = false; + ref1 = document.querySelectorAll('.posteruid, .capcode'); + for (j = 0, len = ref1.length; j < len; j++) { + node = ref1[j]; + node.removeEventListener('click', window.idClick, false); + } + }); + }); + }, + code: function() { + if (this.isClone) { + return; + } + return $.ready((function(_this) { + return function() { + var i, j, len, pre, ref; + ref = $$('.prettyprint', _this.nodes.comment); + for (i = j = 0, len = ref.length; j < len; i = ++j) { + pre = ref[i]; + if (!$.hasClass(pre, 'prettyprinted')) { + $.event('prettyprint', { + ID: _this.fullID, + i: i, + html: pre.innerHTML + }, window); + } + } + }; + })(this)); + }, + math: function() { + var cb, j, len, wbr, wbrs; + if (!/\[(math|eqn)\]/.test(this.nodes.comment.textContent)) { + return; + } + if ((wbrs = $$('wbr', this.nodes.comment)).length) { + for (j = 0, len = wbrs.length; j < len; j++) { + wbr = wbrs[j]; + $.rm(wbr); + } + this.nodes.comment.normalize(); + } + cb = (function(_this) { + return function() { + if (!doc.contains(_this.nodes.comment)) { + return; + } + $.off(d, 'PostsInserted', cb); + return $.event('mathjax', null, _this.nodes.comment); + }; + })(this); + $.on(d, 'PostsInserted', cb); + return cb(); + } + }; + + return Fourchan; + +}).call(this); + +IDColor = (function() { + var IDColor; + + 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 Callbacks.Post.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; + } + }; + + return IDColor; + +}).call(this); + +IDHighlight = (function() { + var IDHighlight; + + IDHighlight = { + init: function() { + var ref; + if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { + return; + } + return Callbacks.Post.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); + }; + } + }; + + return IDHighlight; + +}).call(this); + +Keybinds = (function() { + var Keybinds; + + Keybinds = { + init: function() { + var hotkey, init; + if (!Conf['Keybinds']) { + return; + } + for (hotkey in Config.hotkeys) { + $.sync(hotkey, Keybinds.sync); + } + init = function() { + var i, len, node, 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, i, key, len, notification, notifications, op, ref, ref1, ref2, ref3, ref4, ref5, searchInput, target, thread, threadRoot; + 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) && !/^Alt\+(\d|Up|Down|Left|Right)$/.test(key))) { + return; + } + } + if (!(((ref1 = g.VIEW) !== 'index' && ref1 !== 'thread') || g.VIEW === 'index' && Conf['JSON Index'] && Conf['Index Mode'] === 'catalog' || g.VIEW === 'index' && g.BOARD.ID === 'f')) { + 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['SJIS tags']: + if (target.nodeName !== 'TEXTAREA') { + return; + } + Keybinds.tags('sjis', 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 Index'] && g.BOARD.ID !== 'f')) { + return; + } + Index.update(); + break; + default: + return; + } + break; + case Conf['Watch']: + if (!(ThreadWatcher.enabled && thread)) { + return; + } + ThreadWatcher.toggle(thread); + break; + case Conf['Update thread watcher']: + if (!ThreadWatcher.enabled) { + return; + } + ThreadWatcher.buttonFetchAll(); + 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'))) { + return; + } + FappeTyme.toggle('fappe'); + break; + case Conf['werkTyme']: + if (!(Conf['Werk Tyme'] && ((ref3 = g.VIEW) === 'index' || ref3 === 'thread'))) { + return; + } + FappeTyme.toggle('werk'); + break; + case Conf['Front page']: + if (Conf['JSON Index'] && g.VIEW === 'index' && g.BOARD.ID !== 'f') { + 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' && g.BOARD.ID !== 'f')) { + return; + } + if (Conf['JSON Index']) { + 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' && g.BOARD.ID !== 'f')) { + return; + } + if (Conf['JSON Index']) { + 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' && g.BOARD.ID !== 'f')) { + return; + } + searchInput = Conf['JSON Index'] ? Index.searchInput : $.id('search-box'); + Header.scrollToIfNeeded(searchInput); + searchInput.focus(); + break; + case Conf['Paged mode']: + if (!(Conf['JSON Index'] && g.BOARD.ID !== 'f')) { + return; + } + window.location = g.VIEW === 'index' ? '#paged' : "/" + g.BOARD + "/#paged"; + break; + case Conf['Infinite scrolling mode']: + if (!(Conf['JSON Index'] && g.BOARD.ID !== 'f')) { + return; + } + window.location = g.VIEW === 'index' ? '#infinite' : "/" + g.BOARD + "/#infinite"; + break; + case Conf['All pages mode']: + if (!(Conf['JSON Index'] && g.BOARD.ID !== 'f')) { + return; + } + window.location = g.VIEW === 'index' ? '#all-pages' : "/" + g.BOARD + "/#all-pages"; + break; + case Conf['Open catalog']: + if (g.BOARD.ID === 'f') { + return; + } + window.location = CatalogLinks.catalog(); + break; + case Conf['Cycle sort type']: + if (!(Conf['JSON Index'] && g.VIEW === 'index' && g.BOARD.ID !== '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 && QuoteYou.db)) { + return; + } + QuoteYou.cb.seek('preceding'); + break; + case Conf['Next Post Quoting You']: + if (!(threadRoot && QuoteYou.db)) { + 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 32: + return 'Space'; + case 37: + return 'Left'; + case 38: + return 'Up'; + case 39: + return 'Right'; + case 40: + return 'Down'; + case 188: + return 'Comma'; + case 190: + return 'Period'; + case 191: + return 'Slash'; + case 59: + case 186: + return 'Semicolon'; + default: + if ((48 <= kc && kc <= 57) || (65 <= kc && kc <= 90)) { + return String.fromCharCode(kc).toLowerCase(); + } else if ((96 <= kc && kc <= 105)) { + return String.fromCharCode(kc - 48).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'; + case 'sjis': + return g.BOARD.ID === 'jp'; + } + })(); + 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, i, len, next, postEl, replies, reply, root; + 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'); + } + }; + + return Keybinds; + +}).call(this); + +Nav = (function() { + var Nav; + + 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 i, len, ref, thread, threadRoot; + 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, ref, thread, top; + 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); + } + } + }; + + return Nav; + +}).call(this); + +NormalizeURL = (function() { + var NormalizeURL; + + NormalizeURL = { + init: function() { + var pathname; + if (!Conf['Normalize URL']) { + return; + } + pathname = location.pathname.split(/\/+/); + switch (g.VIEW) { + case 'thread': + pathname[2] = 'thread'; + pathname = pathname.slice(0, 4); + break; + case 'index': + pathname = pathname.slice(0, 3); + } + pathname = pathname.join('/'); + if (location.pathname !== pathname) { + return history.replaceState(history.state, '', location.protocol + "//" + location.host + pathname + location.hash); + } + } + }; + + return NormalizeURL; + +}).call(this); + +PSAHiding = (function() { + var PSAHiding; + + 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: "[Dismiss]" + }); + $.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() { + 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; + } + } + }; + + return PSAHiding; + +}).call(this); + +RelativeDates = (function() { + var RelativeDates, + 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; }; + + 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 Index'] && g.BOARD.ID !== 'f') { + this.flush(); + $.on(d, 'visibilitychange ThreadUpdate', this.flush); + } + if (Conf['Relative Post Dates']) { + return Callbacks.Post.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, i, len, now, 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, i, isPost, len, ref, relative, singlePost; + 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); + } + }; + + return RelativeDates; + +}).call(this); + +RemoveSpoilers = (function() { + var RemoveSpoilers, + slice = [].slice; + + RemoveSpoilers = { + init: function() { + if (Conf['Reveal Spoilers']) { + $.addClass(doc, 'reveal-spoilers'); + } + if (!Conf['Remove Spoilers']) { + return; + } + Callbacks.Post.push({ + name: 'Reveal Spoilers', + cb: this.node + }); + Callbacks.CatalogThread.push({ + name: 'Reveal Spoilers', + cb: this.node + }); + if (g.VIEW === 'archive') { + return $.ready(function() { + return RemoveSpoilers.unspoiler($.id('arc-list')); + }); + } + }, + node: function() { + return RemoveSpoilers.unspoiler(this.nodes.comment); + }, + unspoiler: function(el) { + var i, len, span, spoiler, spoilers; + 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)); + } + } + }; + + return RemoveSpoilers; + +}).call(this); + +Report = (function() { + var Report; + + Report = { + init: function() { + var match; + if (!(match = location.search.match(/\bno=(\d+)/))) { + return; + } + Captcha.replace.init(); + this.postID = +match[1]; + return $.ready(this.ready); + }, + ready: function() { + var passAd, prev, ref; + $.addStyle(CSS.report); + if (Conf['Archive Report']) { + Report.archive(); + } + if ((passAd = $('a[href="https://www.4chan.org/pass"]'))) { + $.extend(passAd, { + textContent: 'Complain', + href: 'https://www.4chan-x.net/captchas.html', + tabIndex: -1 + }); + passAd.parentNode.normalize(); + if (((ref = (prev = passAd.previousSibling)) != null ? ref.nodeType : void 0) === Node.TEXT_NODE) { + prev.nodeValue = prev.nodeValue.replace(/4chan Pass[^\.]*\./i, 'reCAPTCHA malfunctioning?'); + } + $.after(passAd, [ + $.tn('] ['), $.el('a', { + href: 'mailto:4chanpass@4chan.org?subject=4chan%20Pass%20-%20Purchase%20Support', + textContent: 'Email 4chan', + target: '_blank', + tabIndex: -1 + }) + ]); + } + if (!Conf['Use Recaptcha v1 in Reports'] && !Conf['Force Noscript Captcha'] && Main.jsEnabled) { + return new MutationObserver(function() { + Report.fit('iframe[src^="https://www.google.com/recaptcha/api2/frame"]'); + return Report.fit('body'); + }).observe(d.body, { + childList: true, + attributes: true, + subtree: true + }); + } else { + return Report.fit('body'); + } + }, + fit: function(selector) { + var dy, el; + if (!((el = $(selector, doc)) && getComputedStyle(el).visibility !== 'hidden')) { + return; + } + dy = el.getBoundingClientRect().bottom - doc.clientHeight + 8; + if (dy > 0) { + return window.resizeBy(0, dy); + } + }, + archive: function() { + var link, message, types, url; + Redirect.init(); + if (!(url = Redirect.to('report', { + boardID: g.BOARD.ID, + postID: Report.postID + }))) { + return; + } + if ((message = $('h3')) && /Report submitted!/.test(message.textContent)) { + if (location.hash === '#redirect') { + $.globalEval('self.close = function(){};'); + window.resizeTo(700, 475); + location.replace(url); + } + return; + } + link = $.el('a', { + href: url, + textContent: 'Report to archive' + }); + $.on(link, 'click', function(e) { + if (!(e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0)) { + return window.resizeTo(700, 475); + } + }); + $.add(d.body, [$.tn(' ['), link, $.tn(']')]); + if (types = $.id('reportTypes')) { + return $.on(types, 'change', function(e) { + return $('form').action = e.target.value === 'illegal' ? '#redirect' : ''; + }); + } + } + }; + + return Report; + +}).call(this); + +ThreadLinks = (function() { + var ThreadLinks; + + ThreadLinks = { + init: function() { + if (!(g.VIEW === 'index' && Conf['Open Threads in New Tab'])) { + return; + } + Callbacks.Post.push({ + name: 'Thread Links', + cb: this.node + }); + return Callbacks.CatalogThread.push({ + name: 'Thread Links', + cb: this.catalogNode + }); + }, + node: function() { + if (this.isReply || this.isClone) { + return; + } + return ThreadLinks.process($('.replylink', this.nodes.info)); + }, + catalogNode: function() { + return ThreadLinks.process(this.nodes.thumb.parentNode); + }, + process: function(link) { + return link.target = '_blank'; + } + }; + + return ThreadLinks; + +}).call(this); + +Time = (function() { + var Time; + + Time = { + init: function() { + var ref; + if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Time Formatting'])) { + return; + } + return Callbacks.Post.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 '%'; + } + } + }; + + return Time; + +}).call(this); + +Favicon = (function() { + var Favicon; + + 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==' + }; + + return Favicon; + +}).call(this); + +MarkNewIPs = (function() { + var MarkNewIPs; + + MarkNewIPs = { + init: function() { + if (g.VIEW !== 'thread' || !Conf['Mark New IPs']) { + return; + } + return Callbacks.Thread.push({ + name: 'Mark New IPs', + cb: this.node + }); + }, + node: function() { + MarkNewIPs.ipCount = this.ipCount; + MarkNewIPs.postCount = this.posts.keys.length; + return $.on(d, 'ThreadUpdate', MarkNewIPs.onUpdate); + }, + onUpdate: function(e) { + var deletedPosts, fullID, i, ipCount, j, k, len, len1, newPosts, postCount, ref; + ref = e.detail, ipCount = ref.ipCount, postCount = ref.postCount, newPosts = ref.newPosts, deletedPosts = ref.deletedPosts; + if (ipCount == null) { + return; + } + switch (ipCount - MarkNewIPs.ipCount) { + case postCount - MarkNewIPs.postCount + deletedPosts.length: + i = MarkNewIPs.ipCount; + for (j = 0, len = newPosts.length; j < len; j++) { + fullID = newPosts[j]; + MarkNewIPs.markNew(g.posts[fullID], ++i); + } + break; + case -deletedPosts.length: + for (k = 0, len1 = newPosts.length; k < len1; k++) { + fullID = newPosts[k]; + MarkNewIPs.markOld(g.posts[fullID]); + } + } + MarkNewIPs.ipCount = ipCount; + return MarkNewIPs.postCount = postCount; + }, + 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'); + } + }; + + return MarkNewIPs; + +}).call(this); + +ReplyPruning = (function() { + var ReplyPruning; + + ReplyPruning = { + init: function() { + var el, label; + if (!(g.VIEW === 'thread' && Conf['Reply Pruning'])) { + return; + } + this.active = !(Conf['Quote Threading'] && Conf['Thread Quotes']); + this.container = $.frag(); + this.summary = $.el('span', { + hidden: true, + className: 'summary' + }); + this.summary.style.cursor = 'pointer'; + $.on(this.summary, 'click', (function(_this) { + return function() { + _this.inputs.enabled.checked = !_this.inputs.enabled.checked; + return $.event('change', null, _this.inputs.enabled); + }; + })(this)); + label = UI.checkbox('Prune Replies', 'Show Last', this.active); + el = $.el('span', { + title: 'Maximum number of replies to show.' + }, { + innerHTML: " " + }); + $.prepend(el, label); + this.inputs = { + enabled: label.firstElementChild, + replies: el.lastElementChild + }; + $.on(this.inputs.enabled, 'change', this.setEnabled); + $.on(this.inputs.replies, 'change', $.cb.value); + Header.menu.addEntry({ + el: el, + order: 190 + }); + return Callbacks.Thread.push({ + name: 'Reply Pruning', + cb: this.node + }); + }, + position: 0, + hidden: 0, + hiddenFiles: 0, + total: 0, + totalFiles: 0, + setEnabled: function() { + var other; + other = QuoteThreading.input; + if (this.checked && (other != null ? other.checked : void 0)) { + other.checked = false; + $.event('change', null, other); + } + return ReplyPruning.active = this.checked; + }, + showIfHidden: function(id) { + var ref; + if ((ref = ReplyPruning.container) != null ? ref.getElementById(id) : void 0) { + ReplyPruning.inputs.enabled.checked = false; + return $.event('change', null, ReplyPruning.inputs.enabled); + } + }, + node: function() { + var ref; + ReplyPruning.thread = this; + this.posts.forEach(function(post) { + if (post.isReply) { + ReplyPruning.total++; + if (post.file) { + return ReplyPruning.totalFiles++; + } + } + }); + if (ReplyPruning.active && /^#p\d+$/.test(location.hash) && (0 <= (ref = this.posts.keys.indexOf(location.hash.slice(2))) && ref < 1 + Math.max(ReplyPruning.total - +Conf["Max Replies"], 0))) { + ReplyPruning.active = ReplyPruning.inputs.enabled.checked = false; + } + $.after(this.OP.nodes.root, ReplyPruning.summary); + $.on(ReplyPruning.inputs.enabled, 'change', ReplyPruning.update); + $.on(ReplyPruning.inputs.replies, 'change', ReplyPruning.update); + $.on(d, 'ThreadUpdate', ReplyPruning.updateCount); + $.on(d, 'ThreadUpdate', ReplyPruning.update); + return ReplyPruning.update(); + }, + updateCount: function(e) { + var fullID, i, len, ref; + if (e.detail[404]) { + return; + } + ref = e.detail.newPosts; + for (i = 0, len = ref.length; i < len; i++) { + fullID = ref[i]; + ReplyPruning.total++; + if (g.posts[fullID].file) { + ReplyPruning.totalFiles++; + } + } + }, + update: function() { + var boardTop, frag, hidden2, oldPos, post, posts; + hidden2 = ReplyPruning.active ? Math.max(ReplyPruning.total - +Conf["Max Replies"], 0) : 0; + oldPos = d.body.clientHeight - window.scrollY; + posts = ReplyPruning.thread.posts; + if (ReplyPruning.hidden < hidden2) { + while (ReplyPruning.hidden < hidden2 && ReplyPruning.position < posts.keys.length) { + post = posts[posts.keys[ReplyPruning.position++]]; + if (post.isReply && !post.isFetchedQuote) { + $.add(ReplyPruning.container, post.nodes.root); + ReplyPruning.hidden++; + if (post.file) { + ReplyPruning.hiddenFiles++; + } + } + } + } else if (ReplyPruning.hidden > hidden2) { + frag = $.frag(); + while (ReplyPruning.hidden > hidden2 && ReplyPruning.position > 0) { + post = posts[posts.keys[--ReplyPruning.position]]; + if (post.isReply && !post.isFetchedQuote) { + $.prepend(frag, post.nodes.root); + ReplyPruning.hidden--; + if (post.file) { + ReplyPruning.hiddenFiles--; + } + } + } + $.after(ReplyPruning.summary, frag); + $.event('PostsInserted'); + } + ReplyPruning.summary.textContent = ReplyPruning.active ? Build.summaryText('+', ReplyPruning.hidden, ReplyPruning.hiddenFiles) : Build.summaryText('-', ReplyPruning.total, ReplyPruning.totalFiles); + ReplyPruning.summary.hidden = ReplyPruning.total <= +Conf["Max Replies"]; + if ((boardTop = Header.getTopOf($('.board'))) < 0) { + return window.scroll(window.scrollX, Math.max(d.body.clientHeight - oldPos, window.scrollY + boardTop)); + } + } + }; + + return ReplyPruning; + +}).call(this); + +ThreadExcerpt = (function() { + var ThreadExcerpt; + + ThreadExcerpt = { + init: function() { + if (g.BOARD.ID !== 'f' || g.VIEW !== 'thread' || !Conf['Thread Excerpt']) { + return; + } + return Callbacks.Thread.push({ + name: 'Thread Excerpt', + cb: this.node + }); + }, + node: function() { + return d.title = Get.threadExcerpt(this); + } + }; + + return ThreadExcerpt; + +}).call(this); + +ThreadStats = (function() { + var ThreadStats; + + ThreadStats = { + init: function() { + var sc, statsHTML, statsTitle; + if (g.VIEW !== 'thread' || !Conf['Thread Stats']) { + return; + } + statsHTML = { + innerHTML: "? / ?" + ((Conf["IP Count in Stats"]) ? " / ?" : "") + ((Conf["Page Count in Stats"]) ? " / ?" : "") + }; + statsTitle = 'Posts / Files'; + if (Conf['IP Count in Stats']) { + statsTitle += ' / IPs'; + } + if (Conf['Page Count in Stats']) { + statsTitle += (g.BOARD.ID === 'f' ? ' / Purge Position' : ' / 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: "
          " + (statsHTML).innerHTML + "
          " + }); + $.addClass(doc, 'float'); + $.ready(function() { + return $.add(d.body, sc); + }); + } + this.postCountEl = $('#post-count', sc); + this.fileCountEl = $('#file-count', sc); + this.ipCountEl = $('#ip-count', sc); + this.pageCountEl = $('#page-count', sc); + if (this.pageCountEl) { + $.on(this.pageCountEl, 'click', ThreadStats.fetchPage); + } + return Callbacks.Thread.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 (ThreadStats.pageCountEl) { + 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 (!ThreadStats.pageCountEl) { + return; + } + if (newPosts.length) { + ThreadStats.lastPost = g.posts[newPosts[newPosts.length - 1]].info.date; + } + if (g.BOARD.ID !== 'f' && ((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) && ipCountEl) { + ipCountEl.textContent = ipCount; + } + (thread.postLimit && !thread.isSticky ? $.addClass : $.rmClass)(postCountEl, 'warning'); + return (thread.fileLimit && !thread.isSticky ? $.addClass : $.rmClass)(fileCountEl, 'warning'); + }, + fetchPage: function() { + if (!ThreadStats.pageCountEl) { + 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: 'ThreadStats' + }); + }, + onThreadsLoad: function() { + var i, j, k, len, len1, len2, page, purgePos, ref, ref1, ref2, thread; + if (this.status === 200) { + ref = this.response; + for (i = 0, len = ref.length; i < len; i++) { + page = ref[i]; + if (g.BOARD.ID === 'f') { + purgePos = 1; + ref1 = page.threads; + for (j = 0, len1 = ref1.length; j < len1; j++) { + thread = ref1[j]; + if (thread.no < ThreadStats.thread.ID) { + purgePos++; + } + } + ThreadStats.pageCountEl.textContent = purgePos; + } else { + ref2 = page.threads; + for (k = 0, len2 = ref2.length; k < len2; k++) { + thread = ref2[k]; + 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); + ThreadStats.retry(); + return; + } + } + } + } else if (this.status === 304) { + return ThreadStats.retry(); + } + }, + retry: function() { + var ref; + if (g.BOARD.ID !== 'f' && ThreadStats.lastPost > ThreadStats.lastPageUpdate && ((ref = ThreadStats.pageCountEl) != null ? ref.textContent : void 0) !== '1') { + clearTimeout(ThreadStats.timeout); + return ThreadStats.timeout = setTimeout(ThreadStats.fetchPage, 5 * $.SECOND); + } + } + }; + + return ThreadStats; + +}).call(this); + +ThreadUpdater = (function() { + var ThreadUpdater, + 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; }; + + ThreadUpdater = { + init: function() { + var conf, el, input, name, ref, sc, subEntries, updateLink; + if (g.VIEW !== 'thread' || !Conf['Thread Updater']) { + return; + } + this.audio = $.el('audio', { + src: ThreadUpdater.beep + }); + if (Conf['Updater and Stats in Header']) { + this.dialog = sc = $.el('span', { + id: 'updater' + }); + $.extend(sc, { + innerHTML: "" + }); + $.ready(function() { + return Header.addShortcut(sc); + }); + } else { + this.dialog = sc = UI.dialog('updater', 'bottom: 0px; left: 0px;', { + innerHTML: "
          " + }); + $.addClass(doc, 'float'); + $.ready(function() { + return $.add(d.body, sc); + }); + } + this.checkPostCount = 0; + this.timer = $('#update-timer', sc); + this.status = $('#update-status', sc); + $.on(this.timer, 'click', this.update); + $.on(this.status, 'click', this.update); + updateLink = $.el('span', { + className: 'brackets-wrap updatelink' + }); + $.extend(updateLink, { + innerHTML: "Update" + }); + Main.ready(function() { + var navLinksBot; + if ((navLinksBot = $('.navLinksBot'))) { + 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.setInterval); + } + subEntries.push({ + el: el + }); + } + this.settings = $.el('span', { + innerHTML: "Interval" + }); + $.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 Callbacks.Thread.push({ + name: 'Thread Updater', + cb: this.node + }); + }, + node: function() { + ThreadUpdater.thread = this; + ThreadUpdater.root = this.OP.nodes.root.parentNode; + ThreadUpdater.outdateCount = 0; + ThreadUpdater.postIDs = []; + ThreadUpdater.fileIDs = []; + this.posts.forEach(function(post) { + ThreadUpdater.postIDs.push(post.ID); + if (post.file) { + return ThreadUpdater.fileIDs.push(post.ID); + } + }); + ThreadUpdater.cb.interval.call($.el('input', { + value: Conf['Interval'] + })); + $.on(d, 'QRPostSuccessful', ThreadUpdater.cb.checkpost); + $.on(d, 'visibilitychange', ThreadUpdater.cb.visibility); + return ThreadUpdater.setInterval(); + }, + + /* + 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', + playBeep: function() { + var audio; + audio = ThreadUpdater.audio; + if (audio.paused) { + return audio.play(); + } else { + return $.one(audio, 'ended', ThreadUpdater.playBeep); + } + }, + cb: { + checkpost: function(e) { + if (e.detail.threadID !== ThreadUpdater.thread.ID) { + return; + } + ThreadUpdater.postID = e.detail.postID; + ThreadUpdater.checkPostCount = 0; + ThreadUpdater.outdateCount = 0; + return ThreadUpdater.setInterval(); + }, + 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; + }; + }, + 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() { + var req; + req = ThreadUpdater.req; + switch (req.status) { + case 200: + ThreadUpdater.parse(req); + if (ThreadUpdater.thread.isArchived) { + return ThreadUpdater.kill(); + } else { + return ThreadUpdater.setInterval(); + } + break; + case 404: + return $.ajax("//a.4cdn.org/" + ThreadUpdater.thread.board + "/catalog.json", { + onloadend: function() { + var confirmed, i, k, len, len1, page, ref, ref1, thread; + 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 (k = 0, len1 = ref1.length; k < len1; k++) { + thread = ref1[k]; + if (thread.no === ThreadUpdater.thread.ID) { + confirmed = false; + break; + } + } + } + } else { + confirmed = false; + } + if (confirmed) { + return ThreadUpdater.kill(); + } else { + return ThreadUpdater.error(req); + } + } + }); + default: + return ThreadUpdater.error(req); + } + } + }, + kill: function() { + ThreadUpdater.thread.kill(); + ThreadUpdater.setInterval(); + return $.event('ThreadUpdate', { + 404: true, + threadID: ThreadUpdater.thread.fullID + }); + }, + error: function(req) { + if (req.status === 304) { + ThreadUpdater.set('status', ''); + } + ThreadUpdater.setInterval(); + if (!req.status) { + return ThreadUpdater.set('status', 'Connection Failed', 'warning'); + } else if (req.status !== 304) { + return ThreadUpdater.set('status', req.statusText + " (" + req.status + ")", 'warning'); + } + }, + setInterval: function() { + var cur, interval, j, limit; + clearTimeout(ThreadUpdater.timeoutID); + if (ThreadUpdater.thread.isDead) { + ThreadUpdater.set('status', (ThreadUpdater.thread.isArchived ? 'Archived' : '404'), 'warning'); + ThreadUpdater.set('timer', ''); + return; + } + if (ThreadUpdater.postID && ThreadUpdater.checkPostCount < 5) { + ThreadUpdater.set('timer', '...', 'loading'); + ThreadUpdater.timeoutID = setTimeout(ThreadUpdater.update, ++ThreadUpdater.checkPostCount * $.SECOND); + return; + } + if (!Conf['Auto Update']) { + ThreadUpdater.set('timer', 'Update'); + return; + } + interval = ThreadUpdater.interval; + if (Conf['Optional Increase']) { + limit = d.hidden ? 10 : 5; + j = Math.min(ThreadUpdater.outdateCount, limit); + cur = (Math.floor(interval * 0.1) || 1) * j * j; + ThreadUpdater.seconds = $.minmax(cur, interval, 300); + } else { + ThreadUpdater.seconds = interval; + } + return ThreadUpdater.timeout(); + }, + 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; + } + return el.className = klass != null ? klass : (text === '' ? 'empty' : ''); + }, + timeout: function() { + if (ThreadUpdater.seconds) { + ThreadUpdater.set('timer', ThreadUpdater.seconds); + ThreadUpdater.timeoutID = setTimeout(ThreadUpdater.timeout, 1000); + } else { + ThreadUpdater.outdateCount++; + ThreadUpdater.update(); + } + return ThreadUpdater.seconds--; + }, + update: function() { + var ref; + clearTimeout(ThreadUpdater.timeoutID); + ThreadUpdater.set('timer', '...', 'loading'); + 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: 'ThreadUpdater' + }); + }, + 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(req) { + var ID, OP, board, deletedFiles, deletedPosts, files, firstPost, i, index, ipCountEl, k, l, lastPost, len, len1, len2, len3, m, newPosts, node, post, postObject, postObjects, posts, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, scroll, thread, unreadCount, unreadQYCount; + postObjects = req.response.posts; + OP = postObjects[0]; + thread = ThreadUpdater.thread; + board = thread.board; + ref = ThreadUpdater.postIDs, lastPost = ref[ref.length - 1]; + if (postObjects[postObjects.length - 1].no < lastPost && new Date(req.getResponseHeader('Last-Modified')) - thread.posts[lastPost].info.date < 30 * $.SECOND) { + return; + } + Build.spoilerRange[board] = OP.custom_spoiler; + thread.setStatus('Archived', !!OP.archived); + ThreadUpdater.updateThreadStatus('Sticky', !!OP.sticky); + ThreadUpdater.updateThreadStatus('Closed', !!OP.closed); + thread.postLimit = !!OP.bumplimit; + thread.fileLimit = !!OP.imagelimit; + if (OP.unique_ips != null) { + thread.ipCount = OP.unique_ips; + } + posts = []; + index = []; + files = []; + newPosts = []; + for (i = 0, len = postObjects.length; i < len; i++) { + postObject = postObjects[i]; + ID = postObject.no; + index.push(ID); + if (postObject.fsize) { + files.push(ID); + } + if (ID <= lastPost) { + continue; + } + if ((post = thread.posts[ID]) && !post.isFetchedQuote) { + post.resurrect(); + continue; + } + newPosts.push(board + "." + ID); + node = Build.postFromObject(postObject, board.ID); + posts.push(new Post(node, thread, board)); + if (ThreadUpdater.postID === ID) { + delete ThreadUpdater.postID; + } + } + deletedPosts = []; + ref1 = ThreadUpdater.postIDs; + for (k = 0, len1 = ref1.length; k < len1; k++) { + ID = ref1[k]; + if (!(indexOf.call(index, ID) < 0)) { + continue; + } + thread.posts[ID].kill(); + deletedPosts.push(board + "." + ID); + } + ThreadUpdater.postIDs = index; + deletedFiles = []; + ref2 = ThreadUpdater.fileIDs; + for (l = 0, len2 = ref2.length; l < len2; l++) { + ID = ref2[l]; + if (!(!(indexOf.call(files, ID) >= 0 || (ref3 = board + "." + ID, indexOf.call(deletedPosts, ref3) >= 0)))) { + continue; + } + thread.posts[ID].kill(true); + deletedFiles.push(board + "." + ID); + } + ThreadUpdater.fileIDs = files; + if (!posts.length) { + ThreadUpdater.set('status', ''); + } else { + ThreadUpdater.set('status', "+" + posts.length, 'new'); + ThreadUpdater.outdateCount = 0; + unreadCount = (ref4 = Unread.posts) != null ? ref4.size : void 0; + unreadQYCount = (ref5 = Unread.postsQuotingYou) != null ? ref5.size : void 0; + Main.callbackNodes('Post', posts); + if (d.hidden || !d.hasFocus()) { + if (Conf['Beep Quoting You'] && ((ref6 = Unread.postsQuotingYou) != null ? ref6.size : void 0) > unreadQYCount) { + ThreadUpdater.playBeep(); + if (Conf['Beep']) { + ThreadUpdater.playBeep(); + } + } else if (Conf['Beep'] && ((ref7 = Unread.posts) != null ? ref7.size : void 0) > 0 && unreadCount === 0) { + ThreadUpdater.playBeep(); + } + } + scroll = Conf['Auto Scroll'] && ThreadUpdater.scrollBG() && ThreadUpdater.root.getBoundingClientRect().bottom - doc.clientHeight < 25; + firstPost = null; + for (m = 0, len3 = posts.length; m < len3; m++) { + post = posts[m]; + if (!QuoteThreading.insert(post)) { + firstPost || (firstPost = post.nodes.root); + $.add(ThreadUpdater.root, post.nodes.root); + } + } + $.event('PostsInserted'); + if (scroll) { + if (Conf['Bottom Scroll']) { + window.scrollTo(0, d.body.clientHeight); + } else { + if (firstPost) { + Header.scrollTo(firstPost); + } + } + } + } + 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'); + } + return $.event('ThreadUpdate', { + 404: false, + threadID: thread.fullID, + newPosts: newPosts, + deletedPosts: deletedPosts, + deletedFiles: deletedFiles, + postCount: OP.replies + 1, + fileCount: OP.images + !!OP.fsize, + ipCount: OP.unique_ips + }); + } + }; + + return ThreadUpdater; + +}).call(this); + +ThreadWatcher = (function() { + var ThreadWatcher, + slice = [].slice; + + ThreadWatcher = { + init: function() { + var sc; + if (!(this.enabled = 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: "
          Thread Watcher ×
          " + }); + this.status = $('#watcher-status', this.dialog); + this.list = this.dialog.lastElementChild; + this.refreshButton = $('.refresh', this.dialog); + this.closeButton = $('.move > .close', this.dialog); + this.unreaddb = Unread.db || new DataBoard('lastReadPosts'); + this.unreadEnabled = Conf['Remember Last Read Post']; + $.on(d, 'QRPostSuccessful', this.cb.post); + $.on(sc, 'click', this.toggleWatcher); + $.on(this.refreshButton, 'click', this.buttonFetchAll); + $.on(this.closeButton, '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['Fixed Thread Watcher']) { + $.addClass(doc, 'fixed-watcher'); + } + if (Conf['Toggleable Thread Watcher']) { + this.dialog.hidden = true; + Header.addShortcut(sc); + $.addClass(doc, 'toggleable-watcher'); + } + ThreadWatcher.fetchAuto(); + if (g.VIEW === 'index' && Conf['JSON Index'] && Conf['Menu'] && g.BOARD.ID !== 'f') { + Menu.menu.addEntry({ + el: $.el('a', { + href: 'javascript:;', + className: 'has-shortcut-text' + }, { + innerHTML: "Alt+click" + }), + order: 6, + open: function(arg) { + var thread; + thread = arg.thread; + if (Conf['Index Mode'] !== 'catalog') { + return false; + } + this.el.firstElementChild.textContent = ThreadWatcher.isWatched(thread) ? 'Unwatch' : 'Watch'; + 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; + } + }); + } + Callbacks.Post.push({ + name: 'Thread Watcher', + cb: this.node + }); + return Callbacks.CatalogThread.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('a', { + href: 'javascript:;', + 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'); + } + $.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)); + return $.on(this.nodes.thumb.parentNode, 'mousedown', function(e) { + if (e.button === 0 && e.altKey) { + return e.preventDefault(); + } + }); + }, + ready: function() { + $.off(d, '4chanXInitFinished', ThreadWatcher.ready); + if (!Main.isThisPageLegit()) { + return; + } + ThreadWatcher.refresh(); + $.add(d.body, ThreadWatcher.dialog); + 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, i, len, ref, ref1, threadID; + if ($.hasClass(this, 'disabled')) { + return; + } + ThreadWatcher.db.forceSync(); + 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, ref, threadID; + ref = this.parentNode.dataset.fullID.split('.'), boardID = ref[0], threadID = ref[1]; + return ThreadWatcher.rm(boardID, +threadID); + }, + post: function(e) { + var boardID, postID, ref, threadID; + 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, ref, threadID; + db = ThreadWatcher.db; + boardID = g.BOARD.ID; + db.forceSync(); + ref = db.data.boards[boardID]; + for (threadID in ref) { + data = ref[threadID]; + if (!(data != null ? data.isDead : void 0) && !(threadID in g.BOARD.threads)) { + if (Conf['Auto Prune'] || !(data && typeof data === 'object')) { + db["delete"]({ + boardID: boardID, + threadID: threadID + }); + } else { + if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { + ThreadWatcher.fetchStatus({ + boardID: boardID, + threadID: threadID, + data: data + }); + } + data.isDead = true; + 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); + } + }, + requests: [], + fetched: 0, + clearRequests: function() { + ThreadWatcher.requests = []; + ThreadWatcher.fetched = 0; + ThreadWatcher.status.textContent = ''; + return $.rmClass(ThreadWatcher.refreshButton, 'fa-spin'); + }, + abort: function() { + var i, len, ref, req; + ref = ThreadWatcher.requests; + for (i = 0, len = ref.length; i < len; i++) { + req = ref[i]; + if (req.readyState !== 4) { + req.abort(); + } + } + return ThreadWatcher.clearRequests(); + }, + fetchAuto: function() { + var db, interval, now; + clearTimeout(ThreadWatcher.timeout); + if (!Conf['Auto Update Thread Watcher']) { + return; + } + db = ThreadWatcher.db; + interval = ThreadWatcher.unreadEnabled && 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); + }, + buttonFetchAll: function() { + if (ThreadWatcher.requests.length) { + return ThreadWatcher.abort(); + } else { + return ThreadWatcher.fetchAllStatus(); + } + }, + fetchAllStatus: function() { + var i, len, ref, thread, threads; + ThreadWatcher.db.forceSync(); + ThreadWatcher.unreaddb.forceSync(); + if ((ref = QuoteYou.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, req, threadID; + boardID = thread.boardID, threadID = thread.threadID, data = thread.data; + if (data.isDead && !force) { + return; + } + if (ThreadWatcher.requests.length === 0) { + ThreadWatcher.status.textContent = '...'; + $.addClass(ThreadWatcher.refreshButton, 'fa-spin'); + } + req = $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", { + onloadend: function() { + return ThreadWatcher.parseStatus.call(this, thread); + }, + timeout: $.MINUTE + }, { + whenModified: force ? false : 'ThreadWatcher' + }); + return ThreadWatcher.requests.push(req); + }, + parseStatus: function(arg) { + var boardID, data, i, isDead, lastReadPost, len, match, postObj, quotesYou, quotingYou, ref, ref1, regexp, threadID, unread; + boardID = arg.boardID, threadID = arg.threadID, data = arg.data; + ThreadWatcher.fetched++; + if (ThreadWatcher.fetched === ThreadWatcher.requests.length) { + ThreadWatcher.clearRequests(); + } else { + ThreadWatcher.status.textContent = (Math.round(ThreadWatcher.fetched / ThreadWatcher.requests.length * 100)) + "%"; + } + 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 = QuoteYou.db) != null ? ref1.get({ + boardID: boardID, + threadID: threadID, + postID: postObj.no + }) : void 0) { + continue; + } + unread++; + if (!(QuoteYou.db && postObj.com)) { + continue; + } + quotesYou = false; + regexp = /]*\bhref="(?:\/([^\/]+)\/thread\/)?(\d+)?(?:#p(\d+))?"/g; + while (match = regexp.exec(postObj.com)) { + if (QuoteYou.db.get({ + boardID: match[1] || boardID, + threadID: match[2] || threadID, + postID: match[3] || match[2] || threadID + })) { + quotesYou = true; + break; + } + } + if (quotesYou && !Filter.isHidden(Build.parseJSON(postObj, boardID))) { + quotingYou++; + } + } + 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, ref, threadID, threads; + 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]; + if (data && typeof data === 'object') { + 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 (ThreadWatcher.unreadEnabled && 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 (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { + if (data.unread === 0) { + $.addClass(div, 'replies-read'); + } + 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, i, j, len, len1, list, nodes, ref, ref1, ref2, refresher, threadID; + 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, j, len1, post, ref2, toggler; + 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, ref, val; + 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(); + } + }, + set404: function(boardID, threadID, cb) { + var data, ref; + if (!(data = (ref = ThreadWatcher.db) != null ? ref.get({ + boardID: boardID, + threadID: threadID + }) : void 0)) { + return cb(); + } + if (Conf['Auto Prune']) { + ThreadWatcher.db["delete"]({ + boardID: boardID, + threadID: threadID + }); + return cb(); + } + if (data.isDead && !((data.unread != null) || (data.quotingYou != null))) { + return cb(); + } + data.isDead = true; + delete data.unread; + delete data.quotingYou; + return ThreadWatcher.db.set({ + boardID: boardID, + threadID: threadID, + val: data + }, cb); + }, + 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 (ThreadWatcher.unreadEnabled && 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(); + }, + 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, ref, rmClass, text; + 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, i, len, name, ref, ref1, refresh, subEntries; + 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; + if (name === 'Show Unread Count' && !ThreadWatcher.unreadEnabled) { + input.disabled = true; + $.addClass(entry.el, 'disabled'); + entry.el.title += '\n[Remember Last Read Post is disabled.]'; + } + $.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; + } + } + }; + + return ThreadWatcher; + +}).call(this); + +Unread = (function() { + var Unread; + + Unread = { + init: function() { + if (!(g.VIEW === 'thread' && (Conf['Unread Count'] || Conf['Unread Favicon'] || Conf['Unread Line'] || Conf['Remember Last Read Post'] || Conf['Desktop Notifications'] || Conf['Quote Threading']))) { + return; + } + if (Conf['Remember Last Read Post']) { + $.sync('Remember Last Read Post', function(enabled) { + return Conf['Remember Last Read Post'] = enabled; + }); + 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; + Callbacks.Thread.push({ + name: 'Unread', + cb: this.node + }); + return Callbacks.Post.push({ + name: 'Unread', + cb: this.addPost + }); + }, + node: function() { + var ID, j, len, ref, ref1; + Unread.thread = this; + Unread.title = d.title; + Unread.lastReadPost = ((ref = Unread.db) != null ? ref.get({ + boardID: this.board.ID, + threadID: this.ID + }) : void 0) || 0; + Unread.readCount = 0; + ref1 = this.posts.keys; + for (j = 0, len = ref1.length; j < len; j++) { + ID = ref1[j]; + if (+ID <= Unread.lastReadPost) { + Unread.readCount++; + } + } + $.one(d, '4chanXInitFinished', Unread.ready); + return $.on(d, 'ThreadUpdate', Unread.onUpdate); + }, + ready: function() { + if (Conf['Remember Last Read Post'] && Conf['Scroll to Last Read Post']) { + Unread.scroll(); + } + Unread.setLine(true); + Unread.read(); + Unread.update(); + $.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, ref, root; + if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) { + return; + } + ReplyPruning.showIfHidden((ref = Unread.position) != null ? ref.data.nodes.root.id : void 0); + 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, j, lastReadPost, postIDs, 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 = j = ref = Unread.readCount, ref1 = postIDs.length; j < ref1; i = j += 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 = QuoteYou.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 j, len, quotelink, ref, ref1; + ref = post.nodes.quotelinks; + for (j = 0, len = ref.length; j < len; j++) { + quotelink = ref[j]; + if (!((ref1 = QuoteYou.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; + } + try { + notif = new Notification(post.info.nameBlock + " replied to you", { + body: post.info.commentDisplay, + icon: Favicon.logo + }); + notif.onclick = function() { + Header.scrollToIfNeeded(post.nodes.root, true); + return $.global(function() { + return window.focus(); + }); + }; + return notif.onshow = function() { + return setTimeout(function() { + return notif.close(); + }, 7 * $.SECOND); + }; + } catch (_error) {} + }, + 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, ref, ref1, root; + if (!Unread.posts.size && Unread.readCount !== Unread.thread.posts.keys.length) { + Unread.saveLastReadPost(); + } + if (d.hidden || !Unread.posts.size) { + return; + } + 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 ((ref1 = QuoteYou.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, j, postIDs, ref, ref1; + $.forceSync('Remember Last Read Post'); + if (!(Conf['Remember Last Read Post'] && Unread.db)) { + return; + } + postIDs = Unread.thread.posts.keys; + for (i = j = ref = Unread.readCount, ref1 = postIDs.length; j < ref1; i = j += 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 (Unread.hr.hidden || 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, isDead, 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; + } + $.forceSync('Remember Last Read Post'); + if (Conf['Remember Last Read Post'] && (!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']) { + isDead = Unread.thread.isDead; + Favicon.el.href = countQuotingYou ? Favicon[isDead ? 'unreadDeadY' : 'unreadY'] : count ? Favicon[isDead ? 'unreadDead' : 'unread'] : Favicon[isDead ? 'dead' : 'default']; + return $.add(d.head, Favicon.el); + } + } + }; + + return Unread; + +}).call(this); + +Captcha = {}; + +(function() { + Captcha.fixes = { + imageKeys: '789456123uiojklm'.split('').concat(['Comma', 'Period']), + imageKeys16: '7890uiopjkl'.split('').concat(['Semicolon', 'm', 'Comma', 'Period', 'Slash']), + css: '.rc-imageselect-target > div:focus, .rc-image-tile-target:focus {\n outline: 2px solid #4a90e2;\n}\n.rc-imageselect-target td:focus {\n box-shadow: inset 0 0 0 2px #4a90e2;\n outline: none;\n}\n.rc-button-default:focus {\n box-shadow: inset 0 0 0 2px #0063d6;\n}', + cssNoscript: '.fbc-payload-imageselect {\n position: relative;\n}\n.fbc-payload-imageselect > label {\n position: absolute;\n display: block;\n height: 93.3px;\n width: 93.3px;\n}\nlabel[data-row="0"] {top: 0px;}\nlabel[data-row="1"] {top: 93.3px;}\nlabel[data-row="2"] {top: 186.6px;}\nlabel[data-col="0"] {left: 0px;}\nlabel[data-col="1"] {left: 93.3px;}\nlabel[data-col="2"] {left: 186.6px;}\n.fbc-payload-imageselect > input:focus + label {\n outline: 2px solid #4a90e2;\n}\n.fbc-button-verify input:focus {\n box-shadow: inset 0 0 0 2px #0063d6;\n}\nbody.focus .fbc {\n box-shadow: inset 0 0 0 2px #4a90e2;\n}', + init: function() { + switch (location.pathname.split('/')[3]) { + case 'anchor': + return this.initMain(); + case 'frame': + return this.initPopup(); + case 'fallback': + return this.initNoscript(); + } + }, + initMain: function() { + var a, j, len, ref; + $.onExists(d.body, '#recaptcha-anchor', function(checkbox) { + var focus; + focus = function() { + var ref; + if (d.hasFocus() && ((ref = d.activeElement) === d.documentElement || ref === d.body)) { + return checkbox.focus(); + } + }; + focus(); + return $.on(window, 'focus', function() { + return $.queueTask(focus); + }); + }); + ref = $$('.rc-anchor-pt a'); + for (j = 0, len = ref.length; j < len; j++) { + a = ref[j]; + a.tabIndex = -1; + } + }, + initPopup: function() { + $.addStyle(this.css); + this.fixImages(); + new MutationObserver((function(_this) { + return function() { + return _this.fixImages(); + }; + })(this)).observe(d.body, { + childList: true, + subtree: true + }); + return $.on(d, 'keydown', this.keybinds.bind(this)); + }, + initNoscript: function() { + var data, ref, token; + this.noscript = true; + data = (token = (ref = $('.fbc-verification-token > textarea')) != null ? ref.value : void 0) ? { + token: token + } : { + working: true + }; + new Connection(window.parent, '*').send(data); + d.body.classList.toggle('focus', d.hasFocus()); + $.on(window, 'focus blur', function() { + return d.body.classList.toggle('focus', d.hasFocus()); + }); + this.images = $$('.fbc-payload-imageselect > input'); + this.width = 3; + if (this.images.length !== 9) { + return; + } + $.addStyle(this.cssNoscript); + this.addLabels(); + $.on(d, 'keydown', this.keybinds.bind(this)); + return $.on($('.fbc-imageselect-challenge > form'), 'submit', this.checkForm.bind(this)); + }, + fixImages: function() { + var img, j, len, ref; + this.images = $$('.rc-image-tile-target'); + if (!this.images.length) { + this.images = $$('.rc-imageselect-target > div, .rc-imageselect-target td'); + } + this.width = $$('.rc-imageselect-target tr:first-of-type td').length || Math.round(Math.sqrt(this.images.length)); + ref = this.images; + for (j = 0, len = ref.length; j < len; j++) { + img = ref[j]; + img.tabIndex = 0; + } + if (this.images.length === 9) { + this.addTooltips(this.images); + } else { + this.addTooltips16(this.images); + } + return this.complaintLinks(); + }, + complaintLinks: function() { + var errmsg, j, len, link, ref; + ref = $$('.rc-imageselect-incorrect-response, .rc-imageselect-error-select-one, .rc-imageselect-error-select-more, .rc-imageselect-error-dynamic-more'); + for (j = 0, len = ref.length; j < len; j++) { + errmsg = ref[j]; + if (!$('a', errmsg)) { + link = $.el('a', { + href: 'https://www.4chan-x.net/captchas.html', + target: '_blank', + textContent: '[complain]' + }); + $.add(errmsg, [$.tn(' '), link]); + } + } + }, + addLabels: function() { + var checkbox, i, imageSelect, label, labels; + imageSelect = $('.fbc-payload-imageselect'); + labels = (function() { + var j, len, ref, results; + ref = this.images; + results = []; + for (i = j = 0, len = ref.length; j < len; i = ++j) { + checkbox = ref[i]; + checkbox.id = "checkbox-" + i; + label = $.el('label', { + htmlFor: checkbox.id + }); + label.dataset.row = Math.floor(i / 3); + label.dataset.col = i % 3; + $.after(checkbox, label); + results.push(label); + } + return results; + }).call(this); + return this.addTooltips(labels); + }, + addTooltips: function(nodes) { + var i, j, len, node; + for (i = j = 0, len = nodes.length; j < len; i = ++j) { + node = nodes[i]; + node.title = this.imageKeys[i] + " or " + (this.imageKeys[i + 9][0].toUpperCase()) + this.imageKeys[i + 9].slice(1); + } + }, + addTooltips16: function(nodes) { + var i, j, key, len, node, ref; + ref = this.imageKeys16; + for (i = j = 0, len = ref.length; j < len; i = ++j) { + key = ref[i]; + if (i % 4 < this.width && (node = nodes[nodes.length - (4 - Math.floor(i / 4)) * this.width + (i % 4)])) { + node.title = "" + (key[0].toUpperCase()) + key.slice(1); + } + } + }, + checkForm: function(e) { + var checkbox, j, len, n, ref; + n = 0; + ref = this.images; + for (j = 0, len = ref.length; j < len; j++) { + checkbox = ref[j]; + if (checkbox.checked) { + n++; + } + } + if (n === 0) { + return e.preventDefault(); + } + }, + keybinds: function(e) { + var dx, i, img, key, last, n, reload, verify, w, x; + if (!(this.images && doc.contains(this.images[0]))) { + return; + } + n = this.images.length; + w = this.width; + last = n + w - 1; + reload = $('#recaptcha-reload-button, .fbc-button-reload'); + verify = $('#recaptcha-verify-button, .fbc-button-verify > input'); + x = this.images.indexOf(d.activeElement); + if (x < 0) { + x = d.activeElement === verify ? last : n; + } + key = Keybinds.keyCode(e); + if (!this.noscript && key === 'Space' && x < n) { + this.images[x].click(); + } else if (n === 9 && (i = this.imageKeys.indexOf(key)) >= 0) { + this.images[i % 9].click(); + verify.focus(); + } else if (n !== 9 && (i = this.imageKeys16.indexOf(key)) >= 0 && i % 4 < w && (img = this.images[n - (4 - Math.floor(i / 4)) * w + (i % 4)])) { + img.click(); + verify.focus(); + } else if (dx = { + 'Up': n, + 'Down': w, + 'Left': last, + 'Right': 1 + }[key]) { + x = (x + dx) % (n + w); + if ((n < x && x < last)) { + x = dx === last ? n : last; + } + (this.images[x] || (x === n ? reload : void 0) || (x === last ? verify : void 0)).focus(); + } else { + return; + } + e.preventDefault(); + return e.stopPropagation(); + } + }; + +}).call(this); + +(function() { + Captcha.replace = { + init: function() { + if (!(d.cookie.indexOf('pass_enabled=1') < 0)) { + return; + } + if (location.hostname === 'sys.4chan.org' && /[?&]altc\b/.test(location.search) && Main.jsEnabled) { + $.onExists(doc, 'script[src="//www.google.com/recaptcha/api/js/recaptcha_ajax.js"]', function() { + $.global(function() { + return window.el.onload = null; + }); + return Captcha.v1.create(); + }); + return; + } + if (((Conf['Use Recaptcha v1'] && location.hostname === 'boards.4chan.org') || (Conf['Use Recaptcha v1 in Reports'] && location.hostname === 'sys.4chan.org')) && Main.jsEnabled) { + $.ready(Captcha.replace.v1); + return; + } + if (Conf['Force Noscript Captcha'] && Main.jsEnabled) { + $.ready(Captcha.replace.noscript); + return; + } + if (Conf['captchaLanguage'].trim() || Conf['Captcha Fixes']) { + if (location.hostname === 'boards.4chan.org') { + return $.onExists(doc, '#captchaFormPart', function(node) { + return $.onExists(node, 'iframe', Captcha.replace.iframe); + }); + } else { + return $.onExists(doc, 'iframe', Captcha.replace.iframe); + } + } + }, + noscript: function() { + var insert, noscript, original, span, toggle; + if (!((original = $('#g-recaptcha, #captchaContainerAlt')) && (noscript = $('noscript')))) { + return; + } + span = $.el('span', { + id: 'captcha-forced-noscript' + }); + $.replace(noscript, span); + $.rm(original); + insert = function() { + span.innerHTML = noscript.textContent; + return Captcha.replace.iframe($('iframe', span)); + }; + if ((toggle = $('#togglePostFormLink a, #form-link'))) { + return $.on(toggle, 'click', insert); + } else { + return insert(); + } + }, + v1: function() { + var form, link; + if (!$.id('g-recaptcha')) { + return; + } + Captcha.v1.replace(); + if ((link = $.id('form-link'))) { + return $.on(link, 'click', function() { + return Captcha.v1.create(); + }); + } else if (location.hostname === 'boards.4chan.org') { + form = $.id('postForm'); + return form.addEventListener('focus', (function() { + return Captcha.v1.create(); + }), true); + } else { + return Captcha.v1.create(); + } + }, + iframe: function(iframe) { + var lang, src; + if ((lang = Conf['captchaLanguage'].trim())) { + src = /[?&]hl=/.test(iframe.src) ? iframe.src.replace(/([?&]hl=)[^&]*/, '$1' + encodeURIComponent(lang)) : iframe.src + ("&hl=" + (encodeURIComponent(lang))); + if (iframe.src !== src) { + iframe.src = src; + } + } + return Captcha.replace.autocopy(iframe); + }, + autocopy: function(iframe) { + if (!(Conf['Captcha Fixes'] && /^https:\/\/www\.google\.com\/recaptcha\/api\/fallback\?/.test(iframe.src))) { + return; + } + return new Connection(iframe, 'https://www.google.com', { + working: function() { + var ref, ref1; + if ((ref = $.id('qr')) != null ? ref.contains(iframe) : void 0) { + return (ref1 = $('#qr .captcha-container textarea')) != null ? ref1.parentNode.hidden = true : void 0; + } + }, + token: function(token) { + var node, textarea; + node = iframe; + while ((node = node.parentNode)) { + if ((textarea = $('textarea', node))) { + break; + } + } + textarea.value = token; + return $.event('input', null, textarea); + } + }); + } + }; + +}).call(this); + +(function() { + Captcha.v1 = { + blank: "data:image/svg+xml,", + init: function() { + var imgContainer, input; + if (d.cookie.indexOf('pass_enabled=1') >= 0) { + return; + } + if (!(this.isEnabled = !!$('#g-recaptcha, #captchaContainerAlt'))) { + return; + } + imgContainer = $.el('div', { + className: 'captcha-img', + title: 'Reload reCAPTCHA' + }); + $.extend(imgContainer, { + innerHTML: "" + }); + input = $.el('input', { + className: 'captcha-input field', + title: 'Verification', + autocomplete: 'off', + spellcheck: false + }); + this.nodes = { + img: imgContainer.firstChild, + input: input + }; + $.on(input, 'blur', QR.focusout); + $.on(input, 'focus', QR.focusin); + $.on(input, 'keydown', QR.captcha.keydown.bind(QR.captcha)); + $.on(this.nodes.img.parentNode, 'click', QR.captcha.reload.bind(QR.captcha)); + $.addClass(QR.nodes.el, 'has-captcha', 'captcha-v1'); + $.after(QR.nodes.com.parentNode, [imgContainer, 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.replace(); + this.beforeSetup(); + if (Conf['Auto-load captcha']) { + this.setup(); + } + new MutationObserver(this.afterSetup).observe($.id('captchaContainerAlt'), { + childList: true + }); + return this.afterSetup(); + }, + replace: function() { + var container, old; + if (this.script) { + return; + } + if (!(this.script = $('script[src="//www.google.com/recaptcha/api/js/recaptcha_ajax.js"]', d.head))) { + this.script = $.el('script', { + src: '//www.google.com/recaptcha/api/js/recaptcha_ajax.js' + }); + $.add(d.head, this.script); + } + if (old = $.id('g-recaptcha')) { + container = $.el('div', { + id: 'captchaContainerAlt' + }); + return $.replace(old, container); + } + }, + create: function() { + var cont, lang; + cont = $.id('captchaContainerAlt'); + if (this.occupied) { + return; + } + this.occupied = true; + if ((lang = Conf['captchaLanguage'].trim())) { + cont.dataset.lang = lang; + } + $.onExists(cont, '#recaptcha_image', function(image) { + return $.on(image, 'click', function() { + if ($.id('recaptcha_challenge_image')) { + return $.global(function() { + return window.Recaptcha.reload(); + }); + } + }); + }); + $.onExists(cont, '#recaptcha_response_field', function(field) { + $.on(field, 'keydown', function(e) { + if (e.keyCode === 8 && !field.value) { + return $.global(function() { + return window.Recaptcha.reload(); + }); + } + }); + if (location.hostname === 'sys.4chan.org') { + return field.focus(); + } + }); + return $.global(function() { + var container, options, script; + container = document.getElementById('captchaContainerAlt'); + options = { + theme: 'clean', + tabindex: { + "boards.4chan.org": 5 + }[location.hostname], + lang: container.dataset.lang + }; + if (window.Recaptcha) { + return window.Recaptcha.create('6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc', container, options); + } else { + script = document.head.querySelector('script[src="//www.google.com/recaptcha/api/js/recaptcha_ajax.js"]'); + return script.addEventListener('load', function() { + return window.Recaptcha.create('6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc', container, options); + }, false); + } + }); + }, + cb: { + focus: function() { + return QR.captcha.setup(false, true); + } + }, + beforeSetup: function() { + var img, input, ref; + ref = this.nodes, img = ref.img, input = ref.input; + img.parentNode.hidden = true; + img.src = this.blank; + 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 && (force || this.needed()))) { + return; + } + this.create(); + if (focus) { + $.addClass(QR.nodes.el, 'focus'); + return this.nodes.input.focus(); + } + }, + afterSetup: function() { + var challenge, img, input, ref, setLifetime; + if (!(challenge = $.id('recaptcha_challenge_field_holder'))) { + return; + } + if (challenge === QR.captcha.nodes.challenge) { + return; + } + setLifetime = function(e) { + return QR.captcha.lifetime = e.detail; + }; + $.on(window, 'captcha:timeout', setLifetime); + $.global(function() { + return window.dispatchEvent(new CustomEvent('captcha:timeout', { + detail: window.RecaptchaState.timeout + })); + }); + $.off(window, 'captcha:timeout', setLifetime); + ref = QR.captcha.nodes, img = ref.img, input = ref.input; + img.parentNode.hidden = false; + input.placeholder = 'Verification'; + QR.captcha.count(); + $.off(input, 'focus click', QR.captcha.cb.focus); + QR.captcha.nodes.challenge = challenge; + new MutationObserver(QR.captcha.load.bind(QR.captcha)).observe(challenge, { + childList: true, + subtree: true, + attributes: true + }); + QR.captcha.load(); + if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) { + QR.nodes.el.style.top = null; + return QR.nodes.el.style.bottom = '0px'; + } + }, + destroy: function() { + if (!this.script) { + return; + } + $.global(function() { + return window.Recaptcha.destroy(); + }); + delete this.occupied; + if (this.nodes) { + return this.beforeSetup(); + } + }, + sync: function(captchas) { + if (captchas == null) { + captchas = []; + } + QR.captcha.captchas = captchas; + return QR.captcha.count(); + }, + getOne: function() { + var captcha, challenge, response, timeout; + this.clear(); + if (captcha = this.captchas.shift()) { + this.count(); + $.set('captchas', this.captchas); + return captcha; + } else { + challenge = this.nodes.img.alt; + timeout = this.timeout; + if (/\S/.test(response = this.nodes.input.value)) { + this.destroy(); + return { + challenge: challenge, + response: response, + timeout: timeout + }; + } else { + return null; + } + } + }, + save: function() { + var response; + if (!/\S/.test(response = this.nodes.input.value)) { + return; + } + this.nodes.input.value = ''; + this.captchas.push({ + challenge: this.nodes.img.alt, + response: response, + timeout: this.timeout + }); + this.captchas.sort(function(a, b) { + return a.timeout - b.timeout; + }); + this.count(); + this.destroy(); + this.setup(false, true); + return $.set('captchas', this.captchas); + }, + clear: function() { + var captcha, i, j, len, now, ref; + if (!this.captchas.length) { + return; + } + $.forceSync('captchas'); + now = Date.now(); + ref = this.captchas; + for (i = j = 0, len = ref.length; j < len; i = ++j) { + captcha = ref[i]; + if (captcha.timeout > now) { + break; + } + } + if (!i) { + return; + } + this.captchas = this.captchas.slice(i); + this.count(); + return $.set('captchas', this.captchas); + }, + load: function() { + var challenge, challenge_image; + if ($('#captchaContainerAlt[class~="recaptcha_is_showing_audio"]')) { + this.nodes.img.src = this.blank; + return; + } + if (!this.nodes.challenge.firstChild) { + return; + } + if (!(challenge_image = $.id('recaptcha_challenge_image'))) { + return; + } + this.timeout = Date.now() + this.lifetime * $.SECOND - $.MINUTE; + challenge = this.nodes.challenge.firstChild.value; + this.nodes.img.alt = challenge; + this.nodes.img.src = challenge_image.src; + this.nodes.input.value = ''; + return this.clear(); + }, + 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.timer); + if (count) { + return this.timer = setTimeout(this.clear.bind(this), this.captchas[0].timeout - Date.now()); + } + }, + reload: function(focus) { + $.global(function() { + if (window.Recaptcha.type === 'image') { + window.Recaptcha.reload(); + } else { + window.Recaptcha.switch_type('image'); + } + return window.Recaptcha.should_focus = false; + }); + if (focus) { + return this.nodes.input.focus(); + } + }, + keydown: function(e) { + if (e.keyCode === 8 && !this.nodes.input.value) { + this.reload(); + } else if (e.keyCode === 13 && e.shiftKey) { + this.save(); + } else { + return; + } + return e.preventDefault(); + } + }; + +}).call(this); + +(function() { + Captcha.v2 = { + lifetime: 2 * $.MINUTE, + init: function() { + var counter, root; + if (d.cookie.indexOf('pass_enabled=1') >= 0) { + return; + } + if (!(this.isEnabled = !!$('#g-recaptcha, #captchaContainerAlt, #captcha-forced-noscript'))) { + return; + } + if ((this.noscript = Conf['Force Noscript Captcha'] || !Main.jsEnabled)) { + $.addClass(QR.nodes.el, 'noscript-captcha'); + } + 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: "
          " + }); + counter = $('.captcha-counter > a', root); + this.nodes = { + root: root, + counter: counter + }; + this.count(); + $.addClass(QR.nodes.el, 'has-captcha', 'captcha-v2'); + $.after(QR.nodes.com.parentNode, root); + $.on(counter, 'click', this.toggle.bind(this)); + $.on(counter, 'keydown', (function(_this) { + return function(e) { + if (Keybinds.keyCode(e) !== 'Space') { + return; + } + _this.toggle(); + e.preventDefault(); + return e.stopPropagation(); + }; + })(this)); + return $.on(window, 'captcha:success', (function(_this) { + return function() { + return $.queueTask(function() { + return _this.save(false); + }); + }; + })(this)); + }, + timeouts: {}, + postsCount: 0, + noscriptURL: function() { + var lang, url; + url = 'https://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc'; + if ((lang = Conf['captchaLanguage'].trim())) { + url += "&hl=" + (encodeURIComponent(lang)); + } + return url; + }, + 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) { + if (!(this.isEnabled && (this.needed() || force))) { + return; + } + if (focus) { + $.addClass(QR.nodes.el, 'focus'); + this.nodes.counter.focus(); + } + if (this.timeouts.destroy) { + clearTimeout(this.timeouts.destroy); + delete this.timeouts.destroy; + return this.reload(); + } + if (this.nodes.container) { + $.queueTask((function(_this) { + return function() { + var iframe; + if (_this.nodes.container && d.activeElement === _this.nodes.counter && (iframe = $('iframe', _this.nodes.container))) { + iframe.focus(); + return QR.focus(); + } + }; + })(this)); + 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 + }); + if (this.noscript) { + return this.setupNoscript(); + } else { + return this.setupJS(); + } + }, + setupNoscript: function() { + var div, iframe, textarea; + iframe = $.el('iframe', { + id: 'qr-captcha-iframe', + src: this.noscriptURL() + }); + div = $.el('div'); + textarea = $.el('textarea'); + $.add(div, textarea); + return $.add(this.nodes.container, [iframe, div]); + }, + setupJS: function() { + return $.global(function() { + var cbNative, render; + render = function() { + var classList, container; + classList = document.documentElement.classList; + container = document.querySelector('#qr .captcha-container'); + return container.dataset.widgetID = window.grecaptcha.render(container, { + sitekey: '6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc', + theme: classList.contains('tomorrow') || classList.contains('dark-captcha') ? 'dark' : 'light', + callback: function(response) { + return window.dispatchEvent(new CustomEvent('captcha:success', { + detail: response + })); + } + }); + }; + if (window.grecaptcha) { + return render(); + } else { + cbNative = window.onRecaptchaLoaded; + return window.onRecaptchaLoaded = function() { + render(); + return cbNative(); + }; + } + }); + }, + afterSetup: function(mutations) { + var iframe, j, k, len, len1, mutation, node, ref, textarea; + for (j = 0, len = mutations.length; j < len; j++) { + mutation = mutations[j]; + ref = mutation.addedNodes; + for (k = 0, len1 = ref.length; k < len1; k++) { + node = ref[k]; + 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) { + if (!doc.contains(iframe)) { + return; + } + Captcha.replace.iframe(iframe); + $.addClass(QR.nodes.el, 'captcha-open'); + this.fixQRPosition(); + $.on(iframe, 'load', this.fixQRPosition); + if (d.activeElement === this.nodes.counter) { + iframe.focus(); + } + return $.global(function() { + var f; + f = document.querySelector('#qr iframe'); + return f.focus = f.blur = function() {}; + }); + }, + fixQRPosition: function() { + if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) { + QR.nodes.el.style.top = null; + return QR.nodes.el.style.bottom = '0px'; + } + }, + setupTextArea: function(textarea) { + return $.one(textarea, 'input', (function(_this) { + return function() { + return _this.save(true); + }; + })(this)); + }, + destroy: function() { + var garbage, i, ins, node, ref; + if (!this.isEnabled) { + return; + } + delete this.timeouts.destroy; + $.rmClass(QR.nodes.el, 'captcha-open'); + if (this.nodes.container) { + $.rm(this.nodes.container); + } + delete this.nodes.container; + garbage = $.X('//iframe[starts-with(@src, "https://www.google.com/recaptcha/api2/frame")]/ancestor-or-self::*[parent::body]'); + i = 0; + while (node = garbage.snapshotItem(i++)) { + if (((ref = (ins = node.nextSibling)) != null ? ref.nodeName : void 0) === 'INS') { + $.rm(ins); + } + $.rm(node); + } + }, + 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; + } else { + return null; + } + }, + save: function(pasted, token) { + var base, focus, ref; + $.forceSync('captchas'); + this.captchas.push({ + response: token || $('textarea', this.nodes.container).value, + timeout: Date.now() + this.lifetime + }); + this.captchas.sort(function(a, b) { + return a.timeout - b.timeout; + }); + $.set('captchas', this.captchas); + this.count(); + focus = ((ref = d.activeElement) != null ? ref.nodeName : void 0) === 'IFRAME' && /https?:\/\/www\.google\.com\/recaptcha\//.test(d.activeElement.src); + if (this.needed()) { + if (focus) { + if (QR.cooldown.auto || Conf['Post on Captcha Completion']) { + this.nodes.counter.focus(); + } 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); + } + } + if (focus) { + QR.nodes.status.focus(); + } + } + if (Conf['Post on Captcha Completion'] && !QR.cooldown.auto) { + return QR.submit(); + } + }, + clear: function() { + var captcha, i, j, len, now, ref; + if (!this.captchas.length) { + return; + } + $.forceSync('captchas'); + now = Date.now(); + ref = this.captchas; + for (i = j = 0, len = ref.length; j < len; i = ++j) { + 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(d.activeElement === QR.nodes.status); + }, + 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() { + if ($('iframe[src^="https://www.google.com/recaptcha/api/fallback?"]', this.nodes.container)) { + this.destroy(); + return this.setup(false, true); + } else { + return $.global(function() { + var container; + container = document.querySelector('#qr .captcha-container'); + return window.grecaptcha.reset(container.dataset.widgetID); + }); + } + } + }; + +}).call(this); + +PassLink = (function() { + var PassLink; + + PassLink = { + init: function() { + if (!Conf['Pass Link']) { + return; + } + return Main.ready(this.ready); + }, + ready: function() { + var passLink, styleSelector; + if (!(styleSelector = $.id('styleSelector'))) { + return; + } + passLink = $.el('span', { + className: 'brackets-wrap pass-link-container' + }); + $.extend(passLink, { + innerHTML: "4chan Pass" + }); + $.on(passLink.firstElementChild, 'click', function() { + return window.open('//sys.4chan.org/auth', Date.now(), 'width=500,height=280,toolbar=0'); + }); + return $.before(styleSelector.previousSibling, [passLink, $.tn('\u00A0\u00A0')]); + } + }; + + return PassLink; + +}).call(this); + +PostSuccessful = (function() { + var PostSuccessful; + + PostSuccessful = { + init: function() { + if (!Conf['Remember Your Posts']) { + return; + } + return $.ready(this.ready); + }, + ready: function() { + var _, db, postID, ref, threadID; + if (d.title !== 'Post successful!') { + return; + } + ref = $('h1').nextSibling.textContent.match(/thread:(\d+),no:(\d+)/), _ = ref[0], threadID = ref[1], postID = ref[2]; + postID = +postID; + threadID = +threadID || postID; + db = new DataBoard('yourPosts'); + return db.set({ + boardID: g.BOARD.ID, + threadID: threadID, + postID: postID, + val: true + }); + } + }; + + return PostSuccessful; + +}).call(this); + +QR = (function() { + var QR, + indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, + slice = [].slice; + + QR = { + mimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'application/pdf', 'application/vnd.adobe.flash.movie', 'application/x-shockwave-flash', 'video/webm'], + validExtension: /\.(jpe?g|png|gif|pdf|swf|webm)$/i, + typeFromExtension: { + 'jpg': 'image/jpeg', + 'jpeg': 'image/jpeg', + 'png': 'image/png', + 'gif': 'image/gif', + 'pdf': 'application/pdf', + 'swf': 'application/vnd.adobe.flash.movie', + 'webm': 'video/webm' + }, + extensionFromType: { + 'image/jpeg': 'jpg', + 'image/png': 'png', + 'image/gif': 'gif', + 'application/pdf': 'pdf', + 'application/vnd.adobe.flash.movie': 'swf', + 'application/x-shockwave-flash': 'swf', + 'video/webm': 'webm' + }, + init: function() { + var sc, version; + if (!Conf['Quick Reply']) { + return; + } + this.posts = []; + if (g.VIEW === 'archive') { + return; + } + version = Conf['Use Recaptcha v1'] && Main.jsEnabled ? 'v1' : 'v2'; + this.captcha = Captcha[version]; + $.on(d, '4chanXInitFinished', this.initReady); + Callbacks.Post.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(); + } + }); + return Header.addShortcut(sc); + } + }, + initReady: function() { + var link, linkBot, navLinksBot, origToggle; + $.off(d, '4chanXInitFinished', this.initReady); + QR.postingIsEnabled = !!$.id('postForm'); + if (!QR.postingIsEnabled) { + return; + } + link = $.el('h1', { + className: "qr-link-container" + }); + $.extend(link, { + innerHTML: "" + ((g.VIEW === "thread") ? "Reply to Thread" : "Start a Thread") + "" + }); + 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: "Reply to Thread" + }); + $.on(linkBot.firstElementChild, 'click', function() { + QR.open(); + return QR.nodes.com.focus(); + }); + if ((navLinksBot = $('.navLinksBot'))) { + $.prepend(navLinksBot, linkBot); + } + } + origToggle = $.id('togglePostFormLink'); + $.before(origToggle, link); + origToggle.firstElementChild.textContent = 'Original Form'; + $.on(d, 'QRGetFile', QR.getFile); + $.on(d, 'QRSetFile', QR.setFile); + $.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 j, len, post, 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 (j = 0, len = ref.length; j < len; j++) { + post = ref[j]; + post["delete"](); + } + QR.cooldown.auto = false; + QR.status(); + return QR.captcha.destroy(); + }, + focus: function() { + return $.queueTask(function() { + if (!QR.inBubble()) { + QR.hasFocus = d.activeElement && QR.nodes.el.contains(d.activeElement); + return QR.nodes.el.classList.toggle('focus', QR.hasFocus); + } + }); + }, + inBubble: function() { + var bubbles, ref; + bubbles = $$('iframe[src^="https://www.google.com/recaptcha/api2/frame"]'); + return (ref = d.activeElement, indexOf.call(bubbles, ref) >= 0) || bubbles.some(function(el) { + return getComputedStyle(el).visibility !== 'hidden' && el.getBoundingClientRect().bottom > 0; + }); + }, + 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(); + } + }, + toggleSJIS: function(e) { + e.preventDefault(); + Conf['sjisPreview'] = !Conf['sjisPreview']; + $.set('sjisPreview', Conf['sjisPreview']); + return QR.nodes.el.classList.toggle('sjis-preview', Conf['sjisPreview']); + }, + texPreviewShow: function() { + if ($.hasClass(QR.nodes.el, 'tex-preview')) { + return QR.texPreviewHide(); + } + $.addClass(QR.nodes.el, 'tex-preview'); + QR.nodes.texPreview.textContent = QR.nodes.com.value; + return $.event('mathjax', null, QR.nodes.texPreview); + }, + texPreviewHide: function() { + return $.rmClass(QR.nodes.el, 'tex-preview'); + }, + setCustomCooldown: function(enabled) { + Conf['customCooldownEnabled'] = enabled; + QR.cooldown.customCooldown = enabled; + return QR.nodes.customCooldown.classList.toggle('disabled', !enabled); + }, + toggleCustomCooldown: function() { + var enabled; + enabled = $.hasClass(this, 'disabled'); + QR.setCustomCooldown(enabled); + return $.set('customCooldownEnabled', enabled); + }, + error: function(err, focusOverride) { + var el, notice, notif; + QR.open(); + if (typeof err === 'string') { + el = $.tn(err); + } else { + el = err; + el.removeAttribute('style'); + } + notice = new Notice('warning', el); + QR.notifications.push(notice); + if (!Header.areNotificationsEnabled) { + if (d.hidden && !QR.cooldown.auto) { + return alert(el.textContent); + } + } else if (d.hidden || !(focusOverride || d.hasFocus())) { + try { + notif = new Notification(el.textContent, { + body: el.textContent, + icon: Favicon.logo + }); + notif.onclick = function() { + return $.global(function() { + return window.focus(); + }); + }; + if ($.engine !== 'gecko') { + notif.onclose = function() { + return notice.close(); + }; + return notif.onshow = function() { + return setTimeout(function() { + notif.onclose = null; + return notif.close(); + }, 7 * $.SECOND); + }; + } + } catch (_error) {} + } + }, + notifications: [], + cleanNotifications: function() { + var j, len, notification, ref; + ref = QR.notifications; + for (j = 0, len = ref.length; j < len; j++) { + notification = ref[j]; + 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; + }, + openPost: function() { + var index; + 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'); + return QR.cooldown.auto = true; + } + }, + quote: function(e) { + var ancestor, caretPos, com, frag, insideCode, j, k, l, len, len1, len2, len3, len4, len5, n, node, o, post, q, range, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, sel, text, thread; + 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 (j = 0, len = ref.length; j < len; j++) { + node = ref[j]; + $.replace(node, $.tn('\n')); + } + ref1 = $$('br', frag); + for (k = 0, len1 = ref1.length; k < len1; k++) { + node = ref1[k]; + if (node !== frag.lastChild) { + $.replace(node, $.tn('\n>')); + } + } + ref2 = $$('s, .removed-spoiler', frag); + for (l = 0, len2 = ref2.length; l < len2; l++) { + node = ref2[l]; + $.replace(node, [$.tn('[spoiler]')].concat(slice.call(node.childNodes), [$.tn('[/spoiler]')])); + } + ref3 = $$('.prettyprint', frag); + for (n = 0, len3 = ref3.length; n < len3; n++) { + node = ref3[n]; + $.replace(node, [$.tn('[code]')].concat(slice.call(node.childNodes), [$.tn('[/code]')])); + } + ref4 = $$('.linkify[data-original]', frag); + for (o = 0, len4 = ref4.length; o < len4; o++) { + node = ref4[o]; + $.replace(node, $.tn(node.dataset.original)); + } + ref5 = $$('.embedder', frag); + for (q = 0, len5 = ref5.length; q < len5; q++) { + node = ref5[q]; + if (((ref6 = node.previousSibling) != null ? ref6.nodeValue : void 0) === ' ') { + $.rm(node.previousSibling); + } + $.rm(node); + } + text += ">" + (frag.textContent.trim()) + "\n"; + } + QR.openPost(); + 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.value.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '_').length; + counter.textContent = count; + counter.hidden = count < QR.max_comment / 2; + return (count > QR.max_comment ? $.addClass : $.rmClass)(counter, 'warning'); + }, + getFile: function() { + var ref; + return $.event('QRFile', (ref = QR.selected) != null ? ref.file : void 0); + }, + setFile: function(e) { + var file, name, ref, source; + ref = e.detail, file = ref.file, name = ref.name, source = ref.source; + if (name != null) { + file.name = name; + } + if (source != null) { + file.source = source; + } + QR.open(); + return QR.handleFiles([file]); + }, + 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, j, len, ref; + if (!e.clipboardData.items) { + return; + } + files = []; + ref = e.clipboardData.items; + for (j = 0, len = ref.length; j < len; j++) { + item = ref[j]; + 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'); + }, + pasteFF: function() { + var arr, blob, bstr, i, images, img, j, k, len, m, pasteArea, ref, src; + pasteArea = QR.nodes.pasteArea; + if (!pasteArea.childNodes.length) { + return; + } + images = $$('img', pasteArea); + $.rmAll(pasteArea); + for (j = 0, len = images.length; j < len; j++) { + img = images[j]; + src = img.src; + if (m = src.match(/data:(image\/(\w+));base64,(.+)/)) { + bstr = atob(m[3]); + arr = new Uint8Array(bstr.length); + for (i = k = 0, ref = bstr.length; 0 <= ref ? k < ref : k > ref; i = 0 <= ref ? ++k : --k) { + arr[i] = bstr.charCodeAt(i); + } + blob = new Blob([arr], { + type: m[1] + }); + blob.name = "file." + m[2]; + QR.handleFiles([blob]); + } else if (/^https?:\/\//.test(src)) { + QR.handleUrl(src); + } + } + }, + handleUrl: function(urlDefault) { + var url; + url = prompt('Enter a URL:', urlDefault); + if (url === null) { + return; + } + QR.nodes.fileButton.focus(); + return CrossOrigin.file(url, function(blob) { + if (blob && !/^text\//.test(blob.type)) { + return QR.handleFiles([blob]); + } else { + return QR.error("Can't load file."); + } + }); + }, + handleFiles: function(files) { + var file, j, len; + if (this !== QR) { + files = slice.call(this.files); + this.value = null; + } + if (!files.length) { + return; + } + QR.cleanNotifications(); + for (j = 0, len = files.length; j < len; j++) { + file = files[j]; + QR.handleFile(file, files.length); + } + if (files.length !== 1) { + $.addClass(QR.nodes.el, 'dump'); + } + if (d.activeElement === QR.nodes.fileButton && $.hasClass(QR.nodes.fileSubmit, 'has-file')) { + return QR.nodes.filename.focus(); + } + }, + handleFile: function(file, nfiles) { + var isText, post; + isText = /^text\//.test(file.type); + if (nfiles === 1) { + post = QR.selected; + } else { + post = QR.posts[QR.posts.length - 1]; + if ((isText ? post.com || post.pasting : post.file)) { + post = new QR.post(); + } + } + return post[isText ? 'pasteText' : 'setFile'](file); + }, + openFileInput: function() { + if (QR.nodes.fileButton.disabled) { + return; + } + QR.nodes.fileInput.click(); + return QR.nodes.fileButton.focus(); + }, + generatePostableThreadsList: function() { + var j, len, list, options, ref, thread, val; + if (!QR.nodes) { + return; + } + list = QR.nodes.thread; + options = [list.firstElementChild]; + ref = g.BOARD.threads.keys; + for (j = 0, len = ref.length; j < len; j++) { + thread = ref[j]; + options.push($.el('option', { + value: thread, + textContent: "Thread " + 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, ref, rules, save, scriptData, setNode; + QR.nodes = nodes = { + el: dialog = UI.dialog('qr', 'top: 50px; right: 0px;', { + innerHTML: "
          ×
          No selected file
          " + }) + }; + setNode = function(name, query) { + return nodes[name] = $(query, dialog); + }; + setNode('move', '.move'); + setNode('autohide', '#autohide'); + setNode('close', '.close'); + setNode('thread', 'select'); + setNode('form', 'form'); + setNode('sjisToggle', '#sjis-toggle'); + setNode('texButton', '#tex-preview-button'); + setNode('name', '[data-name=name]'); + setNode('email', '[data-name=email]'); + setNode('sub', '[data-name=sub]'); + setNode('com', '[data-name=com]'); + setNode('charCount', '#char-count'); + setNode('texPreview', '#tex-preview'); + setNode('dumpList', '#dump-list'); + setNode('addPost', '#add-post'); + setNode('oekaki', '.oekaki'); + setNode('drawButton', '#qr-draw-button'); + setNode('fileSubmit', '#file-n-submit'); + setNode('fileButton', '#qr-file-button'); + setNode('noFile', '#qr-no-file'); + setNode('filename', '#qr-filename'); + setNode('spoiler', '#qr-file-spoiler'); + setNode('oekakiButton', '#qr-oekaki-button'); + setNode('fileRM', '#qr-filerm'); + setNode('urlButton', '#url-button'); + setNode('pasteArea', '#paste-area'); + setNode('customCooldown', '#custom-cooldown-button'); + setNode('dumpButton', '#dump-button'); + setNode('status', '[type=submit]'); + setNode('flashTag', '[name=filetag]'); + 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; + scriptData = Get.scriptData(); + QR.max_size = (m = scriptData.match(/\bmaxFilesize *= *(\d+)\b/)) ? +m[1] : 4194304; + QR.max_size_video = (m = scriptData.match(/\bmaxWebmFilesize *= *(\d+)\b/)) ? +m[1] : QR.max_size; + QR.max_comment = (m = scriptData.match(/\bcomlen *= *(\d+)\b/)) ? +m[1] : 2000; + 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'); + } + if (g.BOARD.ID === 'jp' && Conf['sjisPreview']) { + $.addClass(QR.nodes.el, 'sjis-preview'); + } + if (parseInt(Conf['customCooldown'], 10) > 0) { + $.addClass(QR.nodes.fileSubmit, 'custom-cooldown'); + $.get('customCooldownEnabled', Conf['customCooldownEnabled'], function(arg) { + var customCooldownEnabled; + customCooldownEnabled = arg.customCooldownEnabled; + QR.setCustomCooldown(customCooldownEnabled); + return $.sync('customCooldownEnabled', QR.setCustomCooldown); + }); + } + $.on(nodes.autohide, 'change', QR.toggleHide); + $.on(nodes.close, 'click', QR.close); + $.on(nodes.form, 'submit', QR.submit); + $.on(nodes.sjisToggle, 'click', QR.toggleSJIS); + $.on(nodes.texButton, 'mousedown', QR.texPreviewShow); + $.on(nodes.texButton, 'mouseup', QR.texPreviewHide); + $.on(nodes.addPost, 'click', function() { + return new QR.post(true); + }); + $.on(nodes.drawButton, 'click', QR.oekaki.draw); + $.on(nodes.fileButton, 'click', QR.openFileInput); + $.on(nodes.noFile, 'click', QR.openFileInput); + $.on(nodes.filename, 'focus', function() { + return $.addClass(this.parentNode, 'focus'); + }); + $.on(nodes.filename, 'blur', function() { + return $.rmClass(this.parentNode, 'focus'); + }); + $.on(nodes.spoiler, 'change', function() { + return QR.selected.nodes.spoiler.click(); + }); + $.on(nodes.oekakiButton, 'click', QR.oekaki.button); + $.on(nodes.fileRM, 'click', function() { + return QR.selected.rmFile(); + }); + $.on(nodes.urlButton, 'click', function() { + return QR.handleUrl(''); + }); + $.on(nodes.customCooldown, 'click', QR.toggleCustomCooldown); + $.on(nodes.dumpButton, 'click', function() { + return nodes.el.classList.toggle('dump'); + }); + $.on(nodes.fileInput, 'change', QR.handleFiles); + window.addEventListener('focus', QR.focus, true); + window.addEventListener('blur', QR.focus, true); + $.on(d, 'click', QR.focus); + if ($.engine === 'gecko') { + nodes.pasteArea.hidden = false; + new MutationObserver(QR.pasteFF).observe(nodes.pasteArea, { + childList: true + }); + } + 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 ($.engine === 'gecko' && 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.load(); + new QR.post(true); + QR.status(); + QR.cooldown.setup(); + QR.captcha.init(); + $.add(d.body, dialog); + QR.captcha.setup(); + QR.oekaki.setup(); + return $.event('QRDialogCreation', null, dialog); + }, + submit: function(e) { + var captcha, cb, err, extra, filetag, formData, options, post, ref, 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(); + threadID = post.thread; + thread = g.BOARD.threads[threadID]; + if (g.BOARD.ID === 'f' && threadID === 'new') { + filetag = QR.nodes.flashTag.value; + } + if (threadID === 'new') { + threadID = null; + if (g.BOARD.ID === 'vg' && !post.sub) { + err = 'New threads require a subject.'; + } else if (!($.hasClass(d.body, 'text_only') || 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 comment or file.'; + } else if (post.file && thread.fileLimit) { + err = 'Max limit of image replies has been reached.'; + } + if (g.BOARD.ID === 'r9k' && !((ref = post.com) != null ? ref.match(/[a-z-]/i) : void 0)) { + err || (err = 'Original comment required.'); + } + if (QR.captcha.isEnabled && !err) { + captcha = QR.captcha.getOne(); + if (!captcha) { + err = 'No valid captcha.'; + QR.captcha.setup(!QR.cooldown.auto || d.activeElement === QR.nodes.status); + } + } + 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.getPassword() + }; + 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: "Connection error while posting. [More info]" + })); + } + }; + extra = { + form: $.formData(formData), + upCallbacks: { + onload: function() { + QR.req.isUploadFinished = true; + 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) { + if (response.challenge != null) { + extra.form.append('recaptcha_challenge_field', response.challenge); + extra.form.append('recaptcha_response_field', response.response); + } else { + extra.form.append('g-recaptcha-response', 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, err, h1, isReply, lastPostToThread, m, open, post, postID, postsCount, ref, ref1, ref2, req, resDoc, seconds, threadID; + 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 + "! ;_;
          Click here to see the reason." + } : { + innerHTML: "You were issued a warning on " + ($(".board", resDoc)).innerHTML + " as " + ($(".nameBlock", resDoc)).innerHTML + ".
          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 = $.el('span', { + innerHTML: "You mistyped the CAPTCHA, or the CAPTCHA malfunctioned [complain here]." + }); + } else if (/expired/i.test(err.textContent)) { + err = 'This CAPTCHA is no longer valid because it has expired.'; + } + QR.cooldown.auto = QR.captcha.isEnabled || err === 'Connection error with sys.4chan.org.'; + QR.cooldown.addDelay(post, 2); + } else if (err.textContent && (m = err.textContent.match(/(?:(\d+)\s+minutes?\s+)?(\d+)\s+second/i)) && !/duplicate|hour/i.test(err.textContent)) { + QR.cooldown.auto = !/have\s+been\s+muted/i.test(err.textContent); + seconds = 60 * (+(m[1] || 0)) + (+m[2]); + if (/muted/i.test(err.textContent)) { + QR.cooldown.addMute(seconds); + } else { + QR.cooldown.addDelay(post, seconds); + } + } else { + QR.cooldown.auto = false; + } + QR.captcha.setup(QR.cooldown.auto && ((ref1 = d.activeElement) === QR.nodes.status || ref1 === d.body)); + if (QR.captcha.isEnabled && !QR.captcha.captchas.length) { + 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)); + } + ref2 = h1.nextSibling.textContent.match(/thread:(\d+),no:(\d+)/), _ = ref2[0], threadID = ref2[1], postID = ref2[2]; + postID = +postID; + threadID = +threadID || postID; + isReply = threadID !== 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; + lastPostToThread = !((function() { + var j, len, p, ref3; + ref3 = QR.posts.slice(1); + for (j = 0, len = ref3.length; j < len; j++) { + p = ref3[j]; + if (p.thread === post.thread) { + return true; + } + } + })()); + if (!(Conf['Persistent QR'] || postsCount)) { + QR.close(); + } else { + post.rm(); + QR.captcha.setup(d.activeElement === QR.nodes.status); + } + QR.cooldown.add(threadID, postID); + URL = threadID === postID ? window.location.origin + "/" + g.BOARD + "/thread/" + threadID : g.VIEW === 'index' && lastPostToThread && Conf['Open Post in New Tab'] ? window.location.origin + "/" + g.BOARD + "/thread/" + threadID + "#p" + postID : void 0; + if (URL) { + open = Conf['Open Post in New Tab'] || postsCount ? function() { + return $.open(URL); + } : function() { + return window.location = URL; + }; + if (threadID === postID) { + QR.waitForThread(URL, open); + } else { + open(); + } + } + return QR.status(); + }, + waitForThread: function(url, cb) { + var attempts, check; + attempts = 0; + check = function() { + return $.ajax(url, { + onloadend: function() { + attempts++; + if (attempts >= 6 || this.status === 200) { + return cb(); + } else { + return setTimeout(check, attempts * $.SECOND); + } + } + }, { + type: 'HEAD' + }); + }; + return check(); + }, + 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(); + } + }; + + return QR; + +}).call(this); + +(function() { + QR.cooldown = { + seconds: 0, + delays: { + thread: 0, + reply: 0, + image: 0, + reply_intra: 0, + image_intra: 0, + deletion: 60, + thread_global: 300 + }, + init: function() { + if (!Conf['Quick Reply']) { + return; + } + this.data = Conf['cooldowns']; + return $.sync('cooldowns', this.sync); + }, + setup: function() { + var delay, m, ref, type; + if (m = Get.scriptData().match(/\bcooldowns *= *({[^}]+})/)) { + $.extend(QR.cooldown.delays, JSON.parse(m[1])); + } + QR.cooldown.maxDelay = 0; + ref = QR.cooldown.delays; + for (type in ref) { + delay = ref[type]; + if (type !== 'thread' && type !== 'thread_global') { + QR.cooldown.maxDelay = Math.max(QR.cooldown.maxDelay, delay); + } + } + QR.cooldown.isSetup = true; + return QR.cooldown.start(); + }, + start: function() { + var data; + data = QR.cooldown.data; + if (!(Conf['Cooldown'] && QR.cooldown.isSetup && !QR.cooldown.isCounting && Object.keys(data[g.BOARD.ID] || {}).length + Object.keys(data.global || {}).length > 0)) { + return; + } + QR.cooldown.isCounting = true; + return QR.cooldown.count(); + }, + sync: function(data) { + QR.cooldown.data = data || {}; + return QR.cooldown.start(); + }, + add: function(threadID, postID) { + var boardID, start; + if (!Conf['Cooldown']) { + return; + } + start = Date.now(); + boardID = g.BOARD.ID; + QR.cooldown.set(boardID, 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(g.BOARD.ID, Date.now(), cooldown); + return QR.cooldown.start(); + }, + addMute: function(delay) { + if (!Conf['Cooldown']) { + return; + } + QR.cooldown.set(g.BOARD.ID, Date.now(), { + type: 'mute', + delay: delay + }); + return QR.cooldown.start(); + }, + "delete": function(post) { + var base, cooldown, cooldowns, id, name; + if (!QR.cooldown.data) { + return; + } + $.forceSync('cooldowns'); + cooldowns = ((base = QR.cooldown.data)[name = post.board.ID] || (base[name] = {})); + for (id in cooldowns) { + cooldown = cooldowns[id]; + if ((cooldown.delay == null) && cooldown.threadID === post.thread.ID && cooldown.postID === post.ID) { + delete cooldowns[id]; + } + } + return QR.cooldown.save([post.board.ID]); + }, + secondsDeletion: function(post) { + var cooldown, cooldowns, seconds, start; + if (!(QR.cooldown.data && Conf['Cooldown'])) { + return 0; + } + cooldowns = QR.cooldown.data[post.board.ID] || {}; + for (start in cooldowns) { + cooldown = cooldowns[start]; + if ((cooldown.delay == null) && cooldown.threadID === post.thread.ID && cooldown.postID === post.ID) { + seconds = QR.cooldown.delays.deletion - Math.floor((Date.now() - start) / $.SECOND); + return Math.max(seconds, 0); + } + } + return 0; + }, + 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) { + var base, cooldowns; + $.forceSync('cooldowns'); + cooldowns = ((base = QR.cooldown.data)[scope] || (base[scope] = {})); + cooldowns[id] = value; + return $.set('cooldowns', QR.cooldown.data); + }, + save: function(scopes) { + var data, i, len, scope; + data = QR.cooldown.data; + for (i = 0, len = scopes.length; i < len; i++) { + scope = scopes[i]; + if (scope in data && !Object.keys(data[scope]).length) { + delete data[scope]; + } + } + return $.set('cooldowns', data); + }, + count: function() { + var base, cooldown, cooldowns, elapsed, i, len, maxDelay, nCooldowns, now, ref, ref1, save, scope, seconds, start, suffix, threadID, type, update; + $.forceSync('cooldowns'); + save = []; + nCooldowns = 0; + now = Date.now(); + ref = QR.cooldown.categorize(QR.posts[0]), type = ref.type, threadID = ref.threadID; + seconds = 0; + if (Conf['Cooldown']) { + ref1 = [g.BOARD.ID, 'global']; + for (i = 0, len = ref1.length; i < len; i++) { + scope = ref1[i]; + cooldowns = ((base = QR.cooldown.data)[scope] || (base[scope] = {})); + for (start in cooldowns) { + cooldown = cooldowns[start]; + start = +start; + elapsed = Math.floor((now - start) / $.SECOND); + if (elapsed < 0) { + delete cooldowns[start]; + save.push(scope); + continue; + } + if (cooldown.delay != null) { + if (cooldown.delay <= elapsed) { + delete cooldowns[start]; + save.push(scope); + } else if ((cooldown.type === type && cooldown.threadID === threadID) || cooldown.type === 'mute') { + 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 (QR.cooldown.customCooldown) { + maxDelay = Math.max(maxDelay, parseInt(Conf['customCooldown'], 10)); + } + if (maxDelay <= elapsed) { + delete cooldowns[start]; + save.push(scope); + 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 (QR.cooldown.customCooldown) { + seconds = Math.max(seconds, parseInt(Conf['customCooldown'], 10) - elapsed); + } + } + nCooldowns += Object.keys(cooldowns).length; + } + } + if (save.length) { + QR.cooldown.save(save); + } + if (nCooldowns) { + 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(); + } + } + }; + +}).call(this); + +(function() { + QR.oekaki = { + menu: { + init: function() { + var a, ref; + if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Menu'] && Conf['Edit Link'] && Conf['Quick Reply'])) { + return; + } + a = $.el('a', { + className: 'edit-link', + href: 'javascript:;', + textContent: 'Edit image' + }); + $.on(a, 'click', this.editFile); + return Menu.menu.addEntry({ + el: a, + order: 95, + open: function(post) { + var file; + QR.oekaki.menu.post = post; + file = post.file; + return QR.postingIsEnabled && !!file && (file.isImage || file.isVideo); + } + }); + }, + editFile: function() { + var currentTime, isVideo, post, ref; + post = QR.oekaki.menu.post; + QR.quote.call(post.nodes.post); + isVideo = post.file.isVideo; + currentTime = ((ref = post.file.fullImage) != null ? ref.currentTime : void 0) || 0; + return CrossOrigin.file(post.file.url, function(blob) { + var video; + if (!blob) { + return QR.error("Can't load file."); + } else if (isVideo) { + video = $.el('video'); + $.on(video, 'loadedmetadata', function() { + $.on(video, 'seeked', function() { + var canvas; + canvas = $.el('canvas', { + width: video.videoWidth, + height: video.videoHeight + }); + canvas.getContext('2d').drawImage(video, 0, 0); + return canvas.toBlob(function(snapshot) { + snapshot.name = post.file.name.replace(/\.\w+$/, '') + '.png'; + QR.handleFiles([snapshot]); + return QR.oekaki.edit(); + }); + }); + return video.currentTime = currentTime; + }); + return video.src = URL.createObjectURL(blob); + } else { + blob.name = post.file.name; + QR.handleFiles([blob]); + return QR.oekaki.edit(); + } + }); + } + }, + setup: function() { + return $.global(function() { + var FCX; + FCX = window.FCX; + FCX.oekakiCB = function() { + return window.Tegaki.flatten().toBlob(function(file) { + var source; + source = "oekaki-" + (Date.now()); + FCX.oekakiLatest = source; + return document.dispatchEvent(new CustomEvent('QRSetFile', { + bubbles: true, + detail: { + file: file, + name: FCX.oekakiName, + source: source + } + })); + }); + }; + if (window.Tegaki) { + return document.querySelector('#qr .oekaki').hidden = false; + } + }); + }, + load: function(cb) { + var n, onload, script, style; + if ($('script[src^="//s.4cdn.org/js/painter"]', d.head)) { + return cb(); + } else { + style = $.el('link', { + rel: 'stylesheet', + href: "//s.4cdn.org/css/painter." + (Date.now()) + ".css" + }); + script = $.el('script', { + src: "//s.4cdn.org/js/painter.min." + (Date.now()) + ".js" + }); + n = 0; + onload = function() { + if (++n === 2) { + return cb(); + } + }; + $.on(style, 'load', onload); + $.on(script, 'load', onload); + return $.add(d.head, [style, script]); + } + }, + draw: function() { + return $.global(function() { + var FCX, Tegaki; + Tegaki = window.Tegaki, FCX = window.FCX; + if (Tegaki.bg) { + Tegaki.destroy(); + } + FCX.oekakiName = 'tegaki.png'; + return Tegaki.open({ + onDone: FCX.oekakiCB, + onCancel: function() { + return Tegaki.bgColor = '#ffffff'; + }, + width: +document.querySelector('#qr [name=oekaki-width]').value, + height: +document.querySelector('#qr [name=oekaki-height]').value, + bgColor: document.querySelector('#qr [name=oekaki-bg]').checked ? document.querySelector('#qr [name=oekaki-bgcolor]').value : 'transparent' + }); + }); + }, + button: function() { + if (QR.selected.file) { + return QR.oekaki.edit(); + } else { + return QR.oekaki.toggle(); + } + }, + edit: function() { + return QR.oekaki.load(function() { + return $.global(function() { + var FCX, Tegaki, cb, error, name, source; + Tegaki = window.Tegaki, FCX = window.FCX; + name = document.getElementById('qr-filename').value.replace(/\.\w+$/, '') + '.png'; + source = document.getElementById('file-n-submit').dataset.source; + error = function(content) { + return document.dispatchEvent(new CustomEvent('CreateNotification', { + bubbles: true, + detail: { + type: 'warning', + content: content, + lifetime: 20 + } + })); + }; + cb = function(e) { + var file, isVideo; + document.removeEventListener('QRFile', cb, false); + if (!e.detail) { + return error('No file to edit.'); + } + if (!/^(image|video)\//.test(e.detail.type)) { + return error('Not an image.'); + } + isVideo = /^video\//.test(e.detail.type); + file = document.createElement(isVideo ? 'video' : 'img'); + file.addEventListener('error', function() { + return error('Could not open file.', false); + }); + file.addEventListener((isVideo ? 'loadeddata' : 'load'), function() { + if (Tegaki.bg) { + Tegaki.destroy(); + } + FCX.oekakiName = name; + Tegaki.open({ + onDone: FCX.oekakiCB, + onCancel: function() { + return Tegaki.bgColor = '#ffffff'; + }, + width: file.naturalWidth || file.videoWidth, + height: file.naturalHeight || file.videoHeight, + bgColor: 'transparent' + }); + return Tegaki.activeCtx.drawImage(file, 0, 0); + }, false); + return file.src = URL.createObjectURL(e.detail); + }; + if (Tegaki.bg && Tegaki.onDoneCb === FCX.oekakiCB && source === FCX.oekakiLatest) { + FCX.oekakiName = name; + return Tegaki.resume(); + } else { + document.addEventListener('QRFile', cb, false); + return document.dispatchEvent(new CustomEvent('QRGetFile', { + bubbles: true + })); + } + }); + }); + }, + toggle: function() { + return QR.oekaki.load(function() { + return QR.nodes.oekaki.hidden = !QR.nodes.oekaki.hidden; + }); + } + }; + +}).call(this); + +(function() { + var 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; }; + + QR.persona = { + always: {}, + types: { + name: [], + email: [], + sub: [] + }, + init: function() { + var i, item, len, ref; + if (!(Conf['Quick Reply'] || (Conf['Menu'] && Conf['Delete Link']))) { + return; + } + ref = Conf['QR.personas'].split('\n'); + for (i = 0, len = ref.length; i < len; i++) { + item = ref[i]; + QR.persona.parseItem(item.trim()); + } + }, + parseItem: function(item) { + var boards, match, ref, ref1, ref2, type, val; + 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(QR.persona.types[type], val) < 0) { + return QR.persona.types[type].push(val); + } + }, + load: function() { + var arr, i, len, list, ref, type, val; + ref = QR.persona.types; + for (type in ref) { + arr = ref[type]; + 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 m; + if (QR.persona.pwd != null) { + return QR.persona.pwd; + } else if ((m = d.cookie.match(/4chan_pass=([^;]+)/))) { + return decodeURIComponent(m[1]); + } else { + return ''; + } + }, + 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 + }; + return $.set('QR.persona', persona); + }); + } + }; + +}).call(this); + +(function() { + var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, + indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, + slice = [].slice; + + QR.post = (function() { + function _Class(select) { + this.select = bind(this.select, this); + var el, event, i, j, label, len, len1, prev, ref, ref1; + el = $.el('a', { + className: 'qr-preview', + draggable: true, + href: 'javascript:;' + }); + $.extend(el, { + innerHTML: "" + }); + this.nodes = { + el: el, + rm: el.firstChild, + spoiler: $('.qr-preview-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.spoiler, 'change', (function(_this) { + return function(e) { + _this.spoiler = e.target.checked; + if (_this === QR.selected) { + return QR.nodes.spoiler.checked = _this.spoiler; + } + }; + })(this)); + ref = $$('label', el); + for (i = 0, len = ref.length; i < len; i++) { + label = ref[i]; + $.on(label, 'click', function(e) { + return e.stopPropagation(); + }); + } + $.add(QR.nodes.dumpList, el); + ref1 = ['dragStart', 'dragEnter', 'dragLeave', 'dragOver', 'dragEnd', 'drop']; + for (j = 0, len1 = ref1.length; j < len1; j++) { + event = ref1[j]; + $.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 : ''; + _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); + URL.revokeObjectURL(this.URL); + return this.dismissErrors(); + }; + + _Class.prototype.lock = function(lock) { + var i, len, name, node, 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' : ''; + 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.removeAttribute('id'); + 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 i, len, name, node, 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"] || ''; + } + (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.updateComment(); + 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.saveFilename(); + return this.updateFilename(); + case 'name': + return QR.persona.set(this); + } + }; + + _Class.prototype.forceSave = function() { + var i, len, name, node, 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.setComment = function(com) { + this.com = com || null; + if (this === QR.selected) { + QR.nodes.com.value = this.com; + } + return this.updateComment(); + }; + + _Class.prototype.updateComment = function() { + if (this === QR.selected) { + QR.characterCount(); + } + this.nodes.span.textContent = this.com; + return $.queueTask(function() { + return QR.captcha.onPostChange(); + }); + }; + + _Class.rmErrored = function(e) { + var error, errors, i, j, len, post, ref; + e.stopPropagation(); + ref = QR.posts; + for (i = ref.length - 1; i >= 0; i += -1) { + post = ref[i]; + if (errors = post.errors) { + for (j = 0, len = errors.length; j < len; j++) { + error = errors[j]; + if (!(doc.contains(error))) { + continue; + } + post.rm(); + break; + } + } + } + }; + + _Class.prototype.error = function(className, message) { + var div, ref, rm, rmAll; + div = $.el('div', { + className: className + }); + $.extend(div, { + innerHTML: E(message) + "
          [delete] [delete all]" + }); + (this.errors || (this.errors = [])).push(div); + ref = $$('a', div), rm = ref[0], rmAll = ref[1]; + $.on(div, 'click', (function(_this) { + return function() { + if (indexOf.call(QR.posts, _this) >= 0) { + return _this.select(); + } + }; + })(this)); + $.on(rm, 'click', (function(_this) { + return function(e) { + e.stopPropagation(); + if (indexOf.call(QR.posts, _this) >= 0) { + return _this.rm(); + } + }; + })(this)); + $.on(rmAll, 'click', QR.post.rmErrored); + return QR.error(div, true); + }; + + _Class.prototype.fileError = function(message) { + return this.error('file-error', this.filename + ": " + message); + }; + + _Class.prototype.dismissErrors = function(test) { + var error, i, len, ref; + if (test == null) { + test = function() { + return true; + }; + } + if (this.errors) { + ref = this.errors; + for (i = 0, len = ref.length; i < len; i++) { + error = ref[i]; + if (doc.contains(error) && test(error)) { + error.parentNode.previousElementSibling.click(); + } + } + } + }; + + _Class.prototype.setFile = function(file1) { + var ext, ref; + this.file = file1; + if (Conf['Randomize Filename'] && g.BOARD.ID !== 'f') { + this.filename = "" + (Date.now() - Math.floor(Math.random() * 365 * $.DAY)); + if (ext = this.file.name.match(QR.validExtension)) { + this.filename += ext[0]; + } + } else { + this.filename = this.file.name; + } + this.filesize = $.bytesToString(this.file.size); + this.checkSize(); + $.addClass(this.nodes.el, 'has-file'); + $.queueTask(function() { + return QR.captcha.onPostChange(); + }); + URL.revokeObjectURL(this.URL); + this.saveFilename(); + if (this === QR.selected) { + this.showFileData(); + } else { + this.updateFilename(); + } + this.nodes.el.style.backgroundImage = null; + if (ref = this.file.type, indexOf.call(QR.mimeTypes, ref) < 0) { + return this.fileError('Unsupported file type.'); + } else if (/^(image|video)\//.test(this.file.type)) { + return this.readFile(); + } + }; + + _Class.prototype.checkSize = function() { + var max; + max = QR.max_size; + if (/^video\//.test(this.file.type)) { + max = Math.min(max, QR.max_size_video); + } + if (this.file.size > max) { + return this.fileError("File too large (file: " + this.filesize + ", max: " + ($.bytesToString(max)) + ")."); + } + }; + + _Class.prototype.readFile = function() { + var el, event, isVideo, onerror, onload; + isVideo = /^video\//.test(this.file.type); + el = $.el(isVideo ? 'video' : 'img'); + if (isVideo && !el.canPlayType(this.file.type)) { + return; + } + event = isVideo ? 'loadeddata' : 'load'; + onload = (function(_this) { + return function() { + $.off(el, event, onload); + $.off(el, 'error', onerror); + _this.checkDimensions(el); + return _this.setThumbnail(el); + }; + })(this); + onerror = (function(_this) { + return function() { + $.off(el, event, onload); + $.off(el, 'error', onerror); + _this.fileError((isVideo ? 'Video' : 'Image') + " appears corrupt"); + return URL.revokeObjectURL(el.src); + }; + })(this); + $.on(el, event, onload); + $.on(el, 'error', onerror); + return el.src = URL.createObjectURL(this.file); + }; + + _Class.prototype.checkDimensions = function(el) { + var duration, height, max_height, max_width, ref, videoHeight, videoWidth, width; + if (el.tagName === 'IMG') { + height = el.height, width = el.width; + if (height > QR.max_height || width > QR.max_width) { + this.fileError("Image too large (image: " + height + "x" + width + "px, max: " + QR.max_height + "x" + QR.max_width + "px)"); + } + if (height < QR.min_height || width < QR.min_width) { + return this.fileError("Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); + } + } else { + videoHeight = el.videoHeight, videoWidth = el.videoWidth, duration = el.duration; + max_height = Math.min(QR.max_height, QR.max_height_video); + max_width = Math.min(QR.max_width, QR.max_width_video); + if (videoHeight > max_height || videoWidth > max_width) { + this.fileError("Video too large (video: " + videoHeight + "x" + videoWidth + "px, max: " + max_height + "x" + max_width + "px)"); + } + if (videoHeight < QR.min_height || videoWidth < QR.min_width) { + this.fileError("Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); + } + if (!isFinite(duration)) { + this.fileError('Video lacks duration metadata (try remuxing)'); + } else if (duration > QR.max_duration_video) { + this.fileError("Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)"); + } + if (((ref = g.BOARD.ID) !== 'gif' && ref !== 'wsg') && $.hasAudio(el)) { + return this.fileError('Audio not allowed'); + } + } + }; + + _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.removeAttribute('title'); + QR.nodes.filename.removeAttribute('title'); + this.nodes.el.style.backgroundImage = null; + $.rmClass(this.nodes.el, 'has-file'); + this.showFileData(); + URL.revokeObjectURL(this.URL); + return this.dismissErrors(function(error) { + return $.hasClass(error, 'file-error'); + }); + }; + + _Class.prototype.saveFilename = function() { + this.file.newName = (this.filename || '').replace(/[\/\\]/g, '-'); + if (!QR.validExtension.test(this.filename)) { + return this.file.newName += "." + (QR.extensionFromType[this.file.type] || 'jpg'); + } + }; + + _Class.prototype.updateFilename = function() { + var long; + long = this.filename + " (" + this.filesize + ")"; + this.nodes.el.title = long; + if (this !== QR.selected) { + return; + } + return QR.nodes.filename.title = long; + }; + + _Class.prototype.showFileData = function() { + var ref; + if (this.file) { + this.updateFilename(); + QR.nodes.filename.value = this.filename; + $.addClass(QR.nodes.oekaki, 'has-file'); + $.addClass(QR.nodes.fileSubmit, 'has-file'); + } else { + $.rmClass(QR.nodes.oekaki, 'has-file'); + $.rmClass(QR.nodes.fileSubmit, 'has-file'); + } + if (((ref = this.file) != null ? ref.source : void 0) != null) { + QR.nodes.fileSubmit.dataset.source = this.file.source; + } else { + QR.nodes.fileSubmit.removeAttribute('data-source'); + } + return QR.nodes.spoiler.checked = this.spoiler; + }; + + _Class.prototype.pasteText = function(file) { + var reader; + this.pasting = true; + reader = new FileReader(); + reader.onload = (function(_this) { + return function(e) { + var result; + result = e.target.result; + _this.setComment((_this.com ? _this.com + "\n" + result : result)); + return delete _this.pasting; + }; + })(this); + return reader.readAsText(file); + }; + + _Class.prototype.dragStart = function(e) { + var left, ref, top; + ref = this.getBoundingClientRect(), left = ref.left, top = ref.top; + e.dataTransfer.setDragImage(this, e.clientX - left, e.clientY - top); + 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; + + })(); + +}).call(this); + +QuoteBacklink = (function() { + var QuoteBacklink; + + QuoteBacklink = { + containers: {}, + init: function() { + var ref; + if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Quote Backlinks']) { + return; + } + Callbacks.Post.push({ + name: 'Quote Backlinking Part 1', + cb: this.firstNode + }); + return Callbacks.Post.push({ + name: 'Quote Backlinking Part 2', + cb: this.secondNode + }); + }, + firstNode: function() { + var a, clone, container, containers, hash, i, j, k, len, len1, len2, link, markYours, nodes, post, quote, ref, ref1, ref2; + if (this.isClone || !this.quotes.length || this.isRebuilt) { + return; + } + markYours = Conf['Mark Quotes of You'] && ((ref = QuoteYou.db) != null ? ref.get({ + boardID: this.board.ID, + threadID: this.thread.ID, + postID: this.ID + }) : void 0); + 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)' : '') + }); + ref1 = this.quotes; + for (i = 0, len = ref1.length; i < len; i++) { + quote = ref1[i]; + containers = [QuoteBacklink.getContainer(quote)]; + if ((post = g.posts[quote]) && post.nodes.backlinkContainer) { + ref2 = post.clones; + for (j = 0, len1 = ref2.length; j < len1; j++) { + clone = ref2[j]; + containers.push(clone.nodes.backlinkContainer); + } + } + for (k = 0, len2 = containers.length; k < len2; k++) { + container = containers[k]; + link = a.cloneNode(true); + nodes = container.firstChild ? [$.tn(' '), link] : [link]; + 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' + })); + } + }; + + return QuoteBacklink; + +}).call(this); + +QuoteCT = (function() { + var QuoteCT; + + 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 Callbacks.Post.push({ + name: 'Mark Cross-thread Quotes', + cb: this.node + }); + }, + node: function() { + var board, boardID, i, len, quotelink, ref, ref1, ref2, thread, threadID; + if (this.isClone && this.thread === this.context.thread) { + return; + } + ref = this.context, 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)); + } + } + } + }; + + return QuoteCT; + +}).call(this); + +QuoteInline = (function() { + var QuoteInline; + + QuoteInline = { + init: function() { + var ref; + if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Quote Inlining']) { + return; + } + if (Conf['Comment Expansion']) { + ExpandComment.callbacks.push(this.node); + } + return Callbacks.Post.push({ + name: 'Quote Inlining', + cb: this.node + }); + }, + node: function() { + var i, isClone, j, len, len1, link, process, 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); + } + }, + process: function(link, clone) { + if (Conf['Quote Hash Navigation']) { + if (!clone) { + $.after(link, QuoteInline.qiQuote(link, $.hasClass(link, 'filtered'))); + } + } + return $.on(link, 'click', QuoteInline.toggle); + }, + 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, quoter, ref, ref1, threadID; + if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) { + return; + } + ref = Get.postDataFromLink(this), boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; + if (Conf['Inline Cross-thread Quotes Only'] && g.VIEW === 'thread' && ((ref1 = g.posts[boardID + "." + postID]) != null ? ref1.nodes.root.offsetParent : void 0)) { + return; + } + e.preventDefault(); + quoter = Get.postFromNode(this); + context = quoter.context; + if ($.hasClass(this, 'inlined')) { + QuoteInline.rm(this, boardID, threadID, postID, context); + } else { + if ($.x("ancestor::div[@data-full-i-d='" + boardID + "." + postID + "']", this)) { + return; + } + QuoteInline.add(this, boardID, threadID, postID, context, quoter); + } + 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, quoter) { + var inline, isBacklink, post, qroot, root; + isBacklink = $.hasClass(quotelink, 'backlink'); + inline = $.el('div', { + className: 'inline' + }); + inline.dataset.fullID = boardID + "." + postID; + 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, quoter); + 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, ref, root; + isBacklink = $.hasClass(quotelink, 'backlink'); + root = QuoteInline.findRoot(quotelink, isBacklink); + root = $.x("following-sibling::div[@data-full-i-d='" + boardID + "." + 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'); + } + } + }; + + return QuoteInline; + +}).call(this); + +QuoteOP = (function() { + var QuoteOP, + 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; }; + + 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 Callbacks.Post.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.context.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)); + } + } + } + }; + + return QuoteOP; + +}).call(this); + +QuotePreview = (function() { + var QuotePreview, + slice = [].slice; + + 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 Callbacks.Post.push({ + name: 'Quote Previewing', + cb: this.node + }); + }, + node: function() { + var i, len, link, 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, i, len, origin, post, postID, posts, qp, ref, threadID; + if ($.hasClass(this, 'inlined') || !d.contains(this)) { + 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.postFromNode(this)); + UI.hover({ + root: this, + el: qp, + latestEvent: e, + endEvents: 'mouseout click', + cb: QuotePreview.mouseout + }); + if (Conf['Quote Highlighting'] && (origin = g.posts[boardID + "." + postID])) { + posts = [origin].concat(origin.clones); + posts.pop(); + for (i = 0, len = posts.length; i < len; i++) { + post = posts[i]; + $.addClass(post.nodes.post, 'qphl'); + } + } + }, + mouseout: function() { + var clone, i, len, post, ref, root; + 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'); + } + } + }; + + return QuotePreview; + +}).call(this); + +QuoteStrikeThrough = (function() { + var QuoteStrikeThrough; + + 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 Callbacks.Post.push({ + name: 'Strike-through Quotes', + cb: this.node + }); + }, + node: function() { + var boardID, i, len, postID, quotelink, 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'); + } + } + } + }; + + return QuoteStrikeThrough; + +}).call(this); + +QuoteThreading = +/* + <3 aeosynth + */ + +(function() { + var QuoteThreading; + + QuoteThreading = { + init: function() { + if (!(Conf['Quote Threading'] && g.VIEW === 'thread')) { + return; + } + this.controls = $.el('label', { + innerHTML: " Threading" + }); + this.threadNewLink = $.el('span', { + className: 'brackets-wrap threadnewlink', + hidden: true + }); + $.extend(this.threadNewLink, { + innerHTML: "Thread New Posts" + }); + this.input = $('input', this.controls); + this.input.checked = Conf['Thread Quotes']; + $.on(this.input, 'change', this.setEnabled); + $.on(this.input, 'change', this.rethread); + $.on(this.threadNewLink.firstElementChild, 'click', this.rethread); + $.on(d, '4chanXInitFinished', (function(_this) { + return function() { + return _this.ready = true; + }; + })(this)); + Header.menu.addEntry(this.entry = { + el: this.controls, + order: 99 + }); + Callbacks.Thread.push({ + name: 'Quote Threading', + cb: this.setThread + }); + return Callbacks.Post.push({ + name: 'Quote Threading', + cb: this.node + }); + }, + parent: {}, + children: {}, + inserted: {}, + setEnabled: function() { + var other, ref; + other = (ref = ReplyPruning.inputs) != null ? ref.enabled : void 0; + if (this.checked && (other != null ? other.checked : void 0)) { + other.checked = false; + $.event('change', null, other); + } + return $.cb.checked.call(this); + }, + setThread: function() { + QuoteThreading.thread = this; + return $.asap((function() { + return !Conf['Thread Updater'] || $('.navLinksBot > .updatelink'); + }), function() { + var navLinksBot; + if ((navLinksBot = $('.navLinksBot'))) { + return $.add(navLinksBot, [$.tn(' '), QuoteThreading.threadNewLink]); + } + }); + }, + node: function() { + var ancestor, j, lastParent, len, parent, parents, quote, ref; + if (this.isFetchedQuote || this.isClone || !this.isReply) { + return; + } + parents = new Set(); + lastParent = null; + ref = this.quotes; + for (j = 0, len = ref.length; j < len; j++) { + quote = ref[j]; + 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, j, len, posts; + posts = [post]; + if (children = QuoteThreading.children[post.fullID]) { + for (j = 0, len = children.length; j < len; j++) { + child = children[j]; + posts = posts.concat(QuoteThreading.descendants(child)); + } + } + return posts; + }, + insert: function(post) { + var base, child, children, descendants, i, j, k, l, len, name, next, nodes, order, parent, prev, prev2, threadContainer, x; + if (!(Conf['Thread Quotes'] && (parent = QuoteThreading.parent[post.fullID]) && !QuoteThreading.inserted[post.fullID])) { + return false; + } + descendants = QuoteThreading.descendants(post); + if (!Unread.posts.has(parent.ID)) { + if ((function() { + var j, len, x; + for (j = 0, len = descendants.length; j < len; j++) { + x = descendants[j]; + 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 (j = children.length - 1; j >= 0; j += -1) { + child = children[j]; + if (child.ID >= post.ID) { + i--; + } + } + if (i !== children.length) { + next = children[i]; + for (k = 0, len = descendants.length; k < len; k++) { + x = descendants[k]; + 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 (l = descendants.length - 1; l >= 0; l += -1) { + x = descendants[l]; + 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; + if (!QuoteThreading.ready) { + return; + } + thread = QuoteThreading.thread; + posts = thread.posts; + QuoteThreading.threadNewLink.hidden = true; + if (Conf['Thread Quotes']) { + 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(); + } + }; + + return QuoteThreading; + +}).call(this); + +QuoteYou = (function() { + var QuoteYou; + + QuoteYou = { + init: function() { + var ref; + if (!Conf['Remember Your Posts']) { + return; + } + this.db = new DataBoard('yourPosts'); + $.sync('Remember Your Posts', function(enabled) { + return Conf['Remember Your Posts'] = enabled; + }); + $.on(d, 'QRPostSuccessful', function(e) { + var boardID, postID, ref, threadID; + $.forceSync('Remember Your Posts'); + if (Conf['Remember Your Posts']) { + ref = e.detail, boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; + return QuoteYou.db.set({ + boardID: boardID, + threadID: threadID, + postID: postID, + val: true + }); + } + }); + if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { + 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 Callbacks.Post.push({ + name: 'Mark Quotes of You', + cb: this.node + }); + }, + node: function() { + var i, len, quotelink, ref; + if (this.isClone) { + return; + } + if (QuoteYou.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 (!(QuoteYou.db.get(Get.postDataFromLink(quotelink)))) { + continue; + } + if (Conf['Mark Quotes of You']) { + $.add(quotelink, $.tn(QuoteYou.text)); + } + $.addClass(quotelink, 'you'); + $.addClass(this.nodes.root, 'quotesYou'); + } + }, + cb: { + seek: function(type) { + var highlight, post, posts, result, str; + if (highlight = $('.highlight')) { + $.rmClass(highlight, 'highlight'); + } + if (!(QuoteYou.lastRead && doc.contains(QuoteYou.lastRead) && $.hasClass(QuoteYou.lastRead, 'quotesYou'))) { + 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(root) { + var post; + post = $('.post', root); + if (!post.getBoundingClientRect().height) { + return false; + } else { + QuoteYou.lastRead = root; + window.location = "#" + post.id; + Header.scrollTo(post); + $.addClass(post, 'highlight'); + return true; + } + } + } + }; + + return QuoteYou; + +}).call(this); + +Quotify = (function() { + var Quotify, + indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, + slice = [].slice; + + 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 Callbacks.Post.push({ + name: 'Resurrect Quotes', + cb: this.node + }); + }, + node: function() { + var deadlink, i, len, ref; + if (this.isClone) { + return; + } + ref = $$('.deadlink', this.nodes.comment); + for (i = 0, len = ref.length; i < len; i++) { + deadlink = ref[i]; + 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', + 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', + 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)); + } + }; + + return Quotify; + +}).call(this); + +Main = (function() { + var Main; + + Main = { + init: function() { + var db, flatten, items, j, key, len, ref; + if (d.body && !$('title', d.head)) { + return; + } + if (window['4chan X antidup']) { + return; + } + window['4chan X antidup'] = true; + if (location.hostname === 'www.google.com') { + $.get('Captcha Fixes', true, function(arg) { + var enabled; + enabled = arg['Captcha Fixes']; + if (enabled) { + return $.ready(function() { + return Captcha.fixes.init(); + }); + } + }); + return; + } + $.global(function() { + var j, len, nuke, prop, ref; + nuke = function(obj, prop) { + try { + return Object.defineProperty(obj, prop, { + configurable: false, + get: function() { + throw new Error(); + }, + set: function() { + throw new Error(); + } + }); + } catch (_error) {} + }; + ref = ['atOptions', 'adsterra_key', 'EpmadsConfig', 'epmads_key', 'EpomConfig', 'epom_key', 'exoDocumentProtocol']; + for (j = 0, len = ref.length; j < len; j++) { + prop = ref[j]; + nuke(window, prop); + } + }); + $.on(window, 'beforescriptexecute', function(e) { + var host, ref, ref1; + host = (ref = e.target.src.split('/')[2]) != null ? (ref1 = ref.match(/[^.]+\.[^.]+$/)) != null ? ref1[0] : void 0 : void 0; + if (host === 'bnhtml.com' || host === 'ecpmrocks.com' || host === 'advertisation.com' || host === 'exoclick.com') { + return e.preventDefault(); + } + }); + $.on(d, '4chanXInitFinished', function() { + if (Main.expectInitFinished) { + return delete Main.expectInitFinished; + } else { + new Notice('error', 'Error: Multiple copies of 4chan X are enabled.'); + return $.addClass(doc, 'tainted'); + } + }); + 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); + ref = DataBoard.keys; + for (j = 0, len = ref.length; j < len; j++) { + db = ref[j]; + Conf[db] = { + boards: {} + }; + } + Conf['selectedArchives'] = {}; + Conf['cooldowns'] = {}; + Conf['Index Sort'] = {}; + Conf['Except Archives from Encryption'] = false; + Conf['JSON Navigation'] = true; + Conf['Oekaki Links'] = true; + items = {}; + for (key in Conf) { + items[key] = void 0; + } + items['previousversion'] = void 0; + return $.get(items, function(items) { + return $.asap((function() { + var doc; + return doc = d.documentElement; + }), function() { + var ref1, val; + if ($.cantSet) { + + } else if (items.previousversion == null) { + Main.ready(function() { + $.set('previousversion', g.VERSION); + return Settings.open(); + }); + } else if (items.previousversion !== g.VERSION) { + Main.upgrade(items); + } + for (key in Conf) { + val = Conf[key]; + Conf[key] = (ref1 = items[key]) != null ? ref1 : val; + } + return Main.initFeatures(); + }); + }); + }, + upgrade: function(items) { + var changes, previousversion; + previousversion = items.previousversion; + changes = Settings.upgrade(items, previousversion); + items.previousversion = changes.previousversion = g.VERSION; + return $.set(changes, function() { + var el, ref; + if ((ref = items['Show Updated Notifications']) != null ? ref : true) { + el = $.el('span', { + innerHTML: "4chan X has been updated to version " + E(g.VERSION) + "." + }); + return new Notice('info', el, 15); + } + }); + }, + initFeatures: function() { + var err, feature, hostname, j, len, match, name, pathname, ref, ref1, ref2, ref3, search; + hostname = location.hostname, search = location.search; + pathname = location.pathname.split(/\/+/); + if (hostname !== 'www.4chan.org') { + g.BOARD = new Board(pathname[1]); + } + if (hostname === 'boards.4chan.org' || hostname === 'sys.4chan.org' || hostname === 'www.4chan.org') { + $.global(function() { + document.documentElement.classList.add('js-enabled'); + return window.FCX = {}; + }); + Main.jsEnabled = $.hasClass(doc, 'js-enabled'); + } + switch (hostname) { + case 'www.4chan.org': + $.onExists(doc, 'body', function() { + return $.addStyle(CSS.www); + }); + Captcha.replace.init(); + return; + case 'sys.4chan.org': + if (pathname[2] === 'imgboard.php') { + if (/\bmode=report\b/.test(search)) { + Report.init(); + } else if ((match = search.match(/\bres=(\d+)/))) { + $.ready(function() { + var ref; + if (Conf['404 Redirect'] && ((ref = $.id('errmsg')) != null ? ref.textContent : void 0) === 'Error: Specified thread does not exist.') { + return Redirect.navigate('thread', { + boardID: g.BOARD.ID, + postID: +match[1] + }); + } + }); + } + } else if (pathname[2] === 'post') { + PostSuccessful.init(); + } + return; + case 'i.4cdn.org': + if (!(pathname[2] && !/s\.jpg$/.test(pathname[2]))) { + return; + } + $.asap((function() { + return d.readyState !== 'loading'; + }), function() { + var ref, video; + if (Conf['404 Redirect'] && ((ref = d.title) === '4chan - Temporarily Offline' || ref === '4chan - 404 Not Found')) { + return Redirect.navigate('file', { + boardID: g.BOARD.ID, + filename: pathname[pathname.length - 1] + }); + } 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 ((ref = pathname[2]) === 'thread' || ref === 'res') { + g.VIEW = 'thread'; + g.THREADID = +pathname[3]; + } else if ((ref1 = pathname[2]) === 'catalog' || ref1 === 'archive') { + g.VIEW = pathname[2]; + } else if (pathname[2].match(/^\d*$/)) { + g.VIEW = 'index'; + } else { + return; + } + g.threads = new SimpleDict(); + g.posts = new SimpleDict(); + $.onExists(doc, 'body', Main.initStyle); + ref2 = Main.features; + for (j = 0, len = ref2.length; j < len; j++) { + ref3 = ref2[j], name = ref3[0], feature = ref3[1]; + try { + feature.init(); + } catch (_error) { + err = _error; + Main.handleErrors({ + message: "\"" + name + "\" initialization crashed.", + error: err + }); + } + } + return $.ready(Main.initReady); + }, + initStyle: function() { + var keyboard, ref; + if (!Main.isThisPageLegit()) { + 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); + if ($.engine) { + $.addClass(doc, $.engine); + } + $.onExists(doc, '.ad-cnt', function(ad) { + return $.onExists(ad, 'img', function() { + return $.addClass(doc, 'ads-loaded'); + }); + }); + if (Conf['Autohiding Scrollbar']) { + $.addClass(doc, 'autohiding-scrollbar'); + } + $.ready(function() { + if (d.body.clientHeight > doc.clientHeight && (window.innerWidth === doc.clientWidth) !== Conf['Autohiding Scrollbar']) { + Conf['Autohiding Scrollbar'] = !Conf['Autohiding Scrollbar']; + $.set('Autohiding Scrollbar', Conf['Autohiding Scrollbar']); + return $.toggleClass(doc, 'autohiding-scrollbar'); + } + }); + $.addStyle(CSS.boards, 'fourchanx-css'); + Main.bgColorStyle = $.el('style', { + id: 'fourchanx-bgcolor-css' + }); + keyboard = false; + $.on(d, 'mousedown', function() { + return keyboard = false; + }); + $.on(d, 'keydown', function(e) { + if (e.keyCode === 9) { + return keyboard = true; + } + }); + window.addEventListener('focus', (function() { + return doc.classList.toggle('keyboard-focus', keyboard); + }), true); + 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 bgColor, div, j, len, styleSheet; + $.rmClass(doc, style); + style = null; + for (j = 0, len = styleSheets.length; j < len; j++) { + styleSheet = styleSheets[j]; + if (styleSheet.href === (mainStyleSheet != null ? mainStyleSheet.href : void 0)) { + style = styleSheet.title.toLowerCase().replace('new', '').trim().replace(/\s+/g, '-'); + break; + } + } + if (style) { + $.addClass(doc, style); + return $.rm(Main.bgColorStyle); + } else { + div = $.el('div', { + className: 'reply' + }); + div.style.cssText = 'position: absolute; visibility: hidden;'; + $.add(d.body, div); + bgColor = window.getComputedStyle(div).backgroundColor; + $.rm(div); + Main.bgColorStyle.textContent = ".dialog, .suboption-list > div:last-of-type {\n background-color: " + bgColor + ";\n}"; + return $.after($.id('fourchanx-css'), Main.bgColorStyle); + } + }; + setStyle(); + if (!mainStyleSheet) { + return; + } + return new MutationObserver(setStyle).observe(mainStyleSheet, { + attributes: true, + attributeFilter: ['href'] + }); + }, + initReady: function() { + var msg, ref, ref1, ref2; + if (g.VIEW === 'thread' && (((ref = d.title) === '4chan - Temporarily Offline' || ref === '4chan - 404 Not Found') || ($('.board') && !$('.opContainer')))) { + ThreadWatcher.set404(g.BOARD.ID, g.THREADID, function() { + if (Conf['404 Redirect']) { + return Redirect.navigate('thread', { + boardID: g.BOARD.ID, + threadID: g.THREADID, + postID: +location.hash.match(/\d+/) + }, "/" + g.BOARD + "/"); + } + }); + return; + } + if ((ref1 = d.title) === '4chan - Temporarily Offline' || ref1 === '4chan - 404 Not Found') { + return; + } + if (((ref2 = g.VIEW) === 'index' || ref2 === 'thread') && !$('.board + *')) { + msg = $.el('div', { + innerHTML: "The page didn't load completely.
          Some features may not work unless you reload." + }); + $.on($('a', msg), 'click', function() { + return location.reload(); + }); + new Notice('warning', msg); + } + if (!(Conf['JSON Index'] && g.VIEW === 'index')) { + return Main.initThread(); + } else { + Main.expectInitFinished = true; + return $.event('4chanXInitFinished'); + } + }, + initThread: function() { + var board, err, errors, j, k, len, len1, m, postRoot, posts, ref, ref1, scriptData, thread, threadRoot, threads; + if ((board = $('.board'))) { + threads = []; + posts = []; + ref = $$('.board > .thread', board); + for (j = 0, len = ref.length; j < len; j++) { + threadRoot = ref[j]; + thread = new Thread(+threadRoot.id.slice(1), g.BOARD); + threads.push(thread); + ref1 = $$('.thread > .postContainer', threadRoot); + for (k = 0, len1 = ref1.length; k < len1; k++) { + postRoot = ref1[k]; + if ($('.postMessage', postRoot)) { + 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 l, len2, post; + for (l = 0, len2 = posts.length; l < len2; l++) { + post = posts[l]; + QuoteThreading.insert(post); + } + Main.expectInitFinished = true; + return $.event('4chanXInitFinished'); + }); + } else { + Main.expectInitFinished = true; + return $.event('4chanXInitFinished'); + } + }, + callbackNodes: function(klass, nodes) { + var cb, i, node; + i = 0; + cb = Callbacks[klass]; + while (node = nodes[i++]) { + cb.execute(node); + } + }, + callbackNodesDB: function(klass, nodes, cb) { + var cbs, fn, i, softTask; + i = 0; + cbs = Callbacks[klass]; + 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, j, len, logs; + if (!(errors instanceof Array)) { + error = errors; + } else if (errors.length === 1) { + error = errors[0]; + } + if (error) { + new Notice('error', Main.parseError(error, Main.reportLink([error])), 15); + return; + } + div = $.el('div', { + innerHTML: E(errors.length) + " errors occurred." + (Main.reportLink(errors)).innerHTML + " [show]" + }); + $.on(div.lastElementChild, 'click', function() { + var ref; + return ref = this.textContent === 'show' ? ['hide', false] : ['show', true], this.textContent = ref[0], logs.hidden = ref[1], ref; + }); + logs = $.el('div', { + hidden: true + }); + for (j = 0, len = errors.length; j < len; j++) { + error = errors[j]; + $.add(logs, Main.parseError(error)); + } + return new Notice('error', [div, logs], 30); + }, + parseError: function(data, reportLink) { + var context, error, lines, message, ref, ref1; + c.error(data.message, data.error.stack); + message = $.el('div', { + innerHTML: E(data.message) + ((reportLink) ? (reportLink).innerHTML : "") + }); + error = $.el('div', { + textContent: (data.error.name || 'Error') + ": " + (data.error.message || 'see console for details') + }); + lines = ((ref = data.error.stack) != null ? (ref1 = ref.match(/\d+(?=:\d+\)?$)/mg)) != null ? ref1.join().replace(/^/, ' at ') : void 0 : void 0) || ''; + context = $.el('div', { + textContent: "(4chan X ccd0 v" + g.VERSION + " " + $.platform + " on " + $.engine + lines + ")" + }); + return [message, error, context]; + }, + reportLink: function(errors) { + var data, details, ref, title, url; + data = errors[0]; + title = data.message; + if (errors.length > 1) { + title += " (+" + (errors.length - 1) + " other errors)"; + } + details = "[Please describe the steps needed to reproduce this error.]\n\nScript: 4chan X ccd0 v" + g.VERSION + " " + $.platform + "\nUser agent: " + navigator.userAgent + "\nURL: " + location.href + "\n\n" + data.error + "\n" + (((ref = data.error.stack) != null ? ref.replace(data.error.toString(), '').trim() : void 0) || ''); + details = details.replace(/file:\/{3}.+\//g, ''); + url = "https://gitreports.com/issue/ccd0/4chan-x?issue_title=" + (encodeURIComponent(title)) + "&details=" + (encodeURIComponent(details)); + return { + innerHTML: " [report]" + }; + }, + 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(); + } + }); + }, + features: [['Polyfill', Polyfill], ['Normalize URL', NormalizeURL], ['Captcha Configuration', Captcha.replace], ['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], ['Thread Links', ThreadLinks], ['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 Personas', QR.persona], ['Quick Reply', QR], ['Cooldown', QR.cooldown], ['Pass Link', PassLink], ['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], ['Edit Link', QR.oekaki.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], ['Flash Features', Flash], ['Reply Pruning', ReplyPruning]] + }; + + return Main; + +}).call(this); + +Main.init(); }).call(this); diff --git a/builds/4chan-X.crx b/builds/4chan-X.crx index 7c4320766..8e7b1865d 100644 Binary files a/builds/4chan-X.crx and b/builds/4chan-X.crx differ diff --git a/builds/4chan-X.meta.js b/builds/4chan-X.meta.js index 171427df9..d2724fc43 100644 --- a/builds/4chan-X.meta.js +++ b/builds/4chan-X.meta.js @@ -1,6 +1,6 @@ // ==UserScript== // @name 4chan X -// @version 1.11.30.3 +// @version 1.11.31.0 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index 7c43b962e..ec07ab623 100644 --- a/builds/4chan-X.user.js +++ b/builds/4chan-X.user.js @@ -1,7 +1,6 @@ -// Generated by CoffeeScript // ==UserScript== // @name 4chan X -// @version 1.11.30.3 +// @version 1.11.31.0 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X @@ -107,7 +106,7 @@ /* * Contains data from external sources: * -* audio/beep.wav from http://freesound.org/people/pierrecartoons1979/sounds/90112/ +* src/Monitoring/ThreadUpdater/beep.wav from http://freesound.org/people/pierrecartoons1979/sounds/90112/ * cc-by-nc-3.0 * * Font Awesome by Dave Gandy (http://fontawesome.io) @@ -119,12 +118,56 @@ '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, Flash, Fourchan, Gallery, Get, Header, IDColor, IDHighlight, ImageCommon, ImageExpand, ImageHover, ImageLoader, Index, Keybinds, Linkify, Main, MarkNewIPs, Menu, Metadata, Nav, NormalizeURL, Notice, PSAHiding, PassLink, Polyfill, Post, PostHiding, PostSuccessful, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, RandomAccessList, Recursive, Redirect, RelativeDates, RemoveSpoilers, ReplyPruning, Report, ReportLink, RevealSpoilers, Sauce, Settings, ShimSet, SimpleDict, Thread, ThreadExcerpt, ThreadHiding, ThreadLinks, 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; }, - extend = 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; }, - hasProp = {}.hasOwnProperty, - bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + +var $, $$, Anonymize, AntiAutoplay, ArchiveLink, Banner, Board, Build, CSS, Callbacks, Captcha, CatalogLinks, CatalogThread, Config, Connection, CrossOrigin, CustomCSS, DataBoard, DeleteLink, DownloadLink, Embedding, ExpandComment, ExpandThread, FappeTyme, Favicon, Fetcher, FileInfo, Filter, Flash, Fourchan, Gallery, Get, Header, IDColor, IDHighlight, ImageCommon, ImageExpand, ImageHover, ImageLoader, Index, Keybinds, Linkify, Main, MarkNewIPs, Menu, Metadata, Nav, NormalizeURL, Notice, PSAHiding, PassLink, Polyfill, Post, PostHiding, PostSuccessful, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, RandomAccessList, Recursive, Redirect, RelativeDates, RemoveSpoilers, ReplyPruning, Report, ReportLink, RevealSpoilers, Sauce, Settings, ShimSet, SimpleDict, Thread, ThreadExcerpt, ThreadHiding, ThreadLinks, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, Volume; + +var Conf, E, c, d, doc, g; + +Conf = {}; +c = console; +d = document; +doc = d.documentElement; + +g = { + VERSION: '1.11.31.0', + NAMESPACE: '4chan X.', + 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); + }; +})(); + +E.cat = function(templates) { + var html, i, len; + html = ''; + for (i = 0, len = templates.length; i < len; i++) { + html += templates[i].innerHTML; + } + return html; +}; + +E.url = function(content) { + return "data:text/html;charset=utf-8," + encodeURIComponent(content.innerHTML); +}; + +Config = (function() { + var Config; Config = { main: { @@ -368,7 +411,7 @@ ":root.tomorrow div.boardTitle {\n" + " font-family: sans-serif !important;\n" + " text-shadow: 1px 1px 1px rgba(167,170,168,0.6);\n" + -"}", +"}\n", hotkeys: { 'Toggle board list': ['Ctrl+b', 'Toggle the full board list.'], 'Toggle header': ['Shift+h', 'Toggle the auto-hide option of the header.'], @@ -434,18204 +477,23 @@ 'Autohiding Scrollbar': false }; - Conf = {}; + return Config; - c = console; +}).call(this); - d = document; +CSS = { - doc = d.documentElement; - - g = { - VERSION: '1.11.30.3', - NAMESPACE: '4chan X.', - 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); - }; - })(); - - E.cat = function(templates) { - var html, k, len1, x; - html = ''; - for (k = 0, len1 = templates.length; k < len1; k++) { - x = templates[k]; - html += x.innerHTML; - } - return html; - }; - - E.url = function(content) { - return "data:text/html;charset=utf-8," + (encodeURIComponent(content.innerHTML)); - }; - - $ = 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: "4chan X was blocked from loading the following URL:

          [More info]" - }); - $('span', message).textContent = (/^\/\//.test(url) ? location.protocol : '') + url; - return new Notice('warning', message, 30, function() { - return delete blockedURLs[url]; - }); - }; - return function(url, options, extra) { - var err, event, form, k, len1, r, ref, ref1, type, upCallbacks, whenModified; - if (options == null) { - options = {}; - } - if (extra == null) { - extra = {}; - } - type = extra.type, whenModified = extra.whenModified, upCallbacks = extra.upCallbacks, form = extra.form; - url = url.replace(/^((?:https?:)?\/\/(?:\w+\.)?4c(?:ha|d)n\.org)\/adv\//, '$1//adv/'); - r = new XMLHttpRequest(); - type || (type = form && 'post' || 'get'); - try { - r.open(type, url, true); - } catch (_error) { - err = _error; - blockedError(url); - ref = ['error', 'loadend']; - for (k = 0, len1 = ref.length; k < len1; k++) { - event = ref[k]; - r["on" + event] = options["on" + event]; - $.queueTask($.event, event, null, r); - } - return; - } - if (whenModified) { - if (((ref1 = lastModified[whenModified]) != null ? ref1[url] : void 0) != null) { - r.setRequestHeader('If-Modified-Since', lastModified[whenModified][url]); - } - $.on(r, 'load', function() { - return (lastModified[whenModified] || (lastModified[whenModified] = {}))[url] = r.getResponseHeader('Last-Modified'); - }); - } - if (/\.json$/.test(url)) { - if (options.responseType == null) { - options.responseType = 'json'; - } - } - $.extend(r, options); - if (options.responseType === 'json' && r.responseType !== 'json' && delete r.response) { - Object.defineProperty(r, 'response', { - configurable: true, - enumerable: true, - get: function() { - return JSON.parse(r.responseText); - } - }); - } - $.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, true); - }); - } 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 fn1, k, len1, ref; - this.evt = e; - ref = this.callbacks; - fn1 = (function(_this) { - return function(cb) { - return $.queueTask(function() { - return cb.call(_this, e, false); - }); - }; - })(this); - for (k = 0, len1 = ref.length; k < len1; k++) { - cb = ref[k]; - fn1(cb); - } - 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, cb) { - var el, observer; - if (el = $(selector, root)) { - return cb(el); - } - if ($.engine === 'edge' && d.readyState === 'loading') { - $.asap((function() { - return d.readyState !== 'loading' || $(selector, root); - }), function() { - return $.onExists(root, selector, cb); - }); - return; - } - observer = new MutationObserver(function() { - if (el = $(selector, root)) { - observer.disconnect(); - return cb(el); - } - }); - return observer.observe(root, { - childList: true, - subtree: true - }); - }; - - $.addStyle = function(css, id, test) { - var style; - if (test == null) { - test = 'head'; - } - style = $.el('style', { - textContent: css - }); - if (id != null) { - style.id = id; - } - $.onExists(doc, 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, k, len1; - el = arguments[0], classNames = 2 <= arguments.length ? slice.call(arguments, 1) : []; - for (k = 0, len1 = classNames.length; k < len1; k++) { - className = classNames[k]; - el.classList.add(className); - } - }; - - $.rmClass = function() { - var className, classNames, el, k, len1; - el = arguments[0], classNames = 2 <= arguments.length ? slice.call(arguments, 1) : []; - for (k = 0, len1 = classNames.length; k < len1; k++) { - className = classNames[k]; - 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 != null ? el.remove() : void 0; - }; - - $.rmAll = function(root) { - return root.textContent = null; - }; - - $.tn = function(s) { - return d.createTextNode(s); - }; - - $.frag = function() { - return d.createDocumentFragment(); - }; - - $.nodes = function(nodes) { - var frag, k, len1, node; - if (!(nodes instanceof Array)) { - return nodes; - } - frag = $.frag(); - for (k = 0, len1 = nodes.length; k < len1; k++) { - node = nodes[k]; - 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, properties2) { - var el; - el = d.createElement(tag); - if (properties) { - $.extend(el, properties); - } - if (properties2) { - $.extend(el, properties2); - } - return el; - }; - - $.on = function(el, events, handler) { - var event, k, len1, ref; - ref = events.split(' '); - for (k = 0, len1 = ref.length; k < len1; k++) { - event = ref[k]; - el.addEventListener(event, handler, false); - } - }; - - $.off = function(el, events, handler) { - var event, k, len1, ref; - ref = events.split(' '); - for (k = 0, len1 = ref.length; k < len1; k++) { - event = ref[k]; - 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 - })); - }; - - (function() { - var clone, err, ref, unsafeConstructors; - if (!(/PaleMoon\//.test(navigator.userAgent) && +(typeof GM_info !== "undefined" && GM_info !== null ? (ref = GM_info.version) != null ? ref.split('.')[0] : void 0 : void 0) >= 2 && typeof cloneInto === 'undefined')) { - return; - } - try { - return new CustomEvent('x', { - detail: {} - }); - } catch (_error) { - err = _error; - unsafeConstructors = { - Object: unsafeWindow.Object, - Array: unsafeWindow.Array - }; - clone = function(obj) { - var constructor, key, obj2, val; - if ((obj != null) && typeof obj === 'object' && (constructor = unsafeConstructors[obj.constructor.name])) { - obj2 = new constructor(); - for (key in obj) { - val = obj[key]; - obj2[key] = clone(val); - } - return obj2; - } else { - return obj; - } - }; - return $.event = function(event, detail, root) { - if (root == null) { - root = d; - } - return root.dispatchEvent(new CustomEvent(event, { - bubbles: true, - detail: clone(detail) - })); - }; - } - })(); - - $.open = typeof GM_openInTab !== "undefined" && GM_openInTab !== null ? GM_openInTab : function(url) { - return window.open(url, '_blank'); - }; - - $.debounce = function(wait, fn) { - var args, exec, lastCall, that, timeout; - lastCall = 0; - timeout = null; - that = null; - args = null; - exec = function() { - lastCall = Date.now(); - return fn.apply(that, args); - }; - return function() { - args = arguments; - that = this; - if (lastCall < Date.now() - wait) { - return exec(); - } - clearTimeout(timeout); - return timeout = setTimeout(exec, wait); - }; - }; - - $.queueTask = (function() { - var execTask, taskChannel, taskQueue; - taskQueue = []; - execTask = function() { - var args, func, task; - task = taskQueue.shift(); - func = task[0]; - args = Array.prototype.slice.call(task, 1); - return func.apply(func, args); - }; - if (window.MessageChannel) { - taskChannel = new MessageChannel(); - taskChannel.port1.onmessage = execTask; - return function() { - taskQueue.push(arguments); - return taskChannel.port2.postMessage(null); - }; - } else { - return function() { - taskQueue.push(arguments); - return setTimeout(execTask, 0); - }; - } - })(); - - $.globalEval = function(code) { - var script; - script = $.el('script', { - textContent: code - }); - $.add(d.head || doc, script); - return $.rm(script); - }; - - $.global = function(fn) { - if (doc) { - return $.globalEval("(" + fn + ")();"); - } else { - return fn(); - } - }; - - $.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; - }; - - $.engine = (function() { - if (/Edge\//.test(navigator.userAgent)) { - return 'edge'; - } - if (/Chrome\//.test(navigator.userAgent)) { - return 'blink'; - } - if (/WebKit\//.test(navigator.userAgent)) { - return 'webkit'; - } - if (/Gecko\/|Goanna/.test(navigator.userAgent)) { - return 'gecko'; - } - })(); - - try { - localStorage.getItem('x'); - $.hasStorage = true; - } catch (_error) { - $.hasStorage = false; - } - - $.item = function(key, val) { - var item; - item = {}; - item[key] = val; - return item; - }; - - $.syncing = {}; - - if (typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null) { - $.getValue = GM_getValue; - $.listValues = function() { - return GM_listValues(); - }; - } else if ($.hasStorage) { - $.getValue = function(key) { - return localStorage[key]; - }; - $.listValues = function() { - var key, results; - results = []; - for (key in localStorage) { - if (key.slice(0, g.NAMESPACE.length) === g.NAMESPACE) { - results.push(key); - } - } - return results; - }; - } else { - $.getValue = function() {}; - $.listValues = function() { - return []; - }; - } - - if (typeof GM_addValueChangeListener !== "undefined" && GM_addValueChangeListener !== null) { - $.setValue = GM_setValue; - $.deleteValue = GM_deleteValue; - } else if (typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null) { - $.oldValue = {}; - $.setValue = function(key, val) { - GM_setValue(key, val); - if (key in $.syncing) { - $.oldValue[key] = val; - if ($.hasStorage) { - return localStorage[key] = val; - } - } - }; - $.deleteValue = function(key) { - GM_deleteValue(key); - if (key in $.syncing) { - delete $.oldValue[key]; - if ($.hasStorage) { - return localStorage.removeItem(key); - } - } - }; - if (!$.hasStorage) { - $.cantSync = true; - } - } else if ($.hasStorage) { - $.oldValue = {}; - $.setValue = function(key, val) { - if (key in $.syncing) { - $.oldValue[key] = val; - } - return localStorage[key] = val; - }; - $.deleteValue = function(key) { - if (key in $.syncing) { - delete $.oldValue[key]; - } - return localStorage.removeItem(key); - }; - } else { - $.setValue = function() {}; - $.deleteValue = function() {}; - $.cantSync = $.cantSet = true; - } - - if (typeof GM_addValueChangeListener !== "undefined" && GM_addValueChangeListener !== null) { - $.sync = function(key, cb) { - return $.syncing[key] = GM_addValueChangeListener(g.NAMESPACE + key, function(key2, oldValue, newValue, remote) { - if (remote) { - if (newValue !== void 0) { - newValue = JSON.parse(newValue); - } - return cb(newValue, key); - } - }); - }; - $.forceSync = function() {}; - } else if ((typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null) || $.hasStorage) { - $.sync = function(key, cb) { - key = g.NAMESPACE + key; - $.syncing[key] = cb; - return $.oldValue[key] = $.getValue(key); - }; - (function() { - var onChange; - onChange = function(arg) { - var cb, key, newValue; - key = arg.key, newValue = arg.newValue; - if (!(cb = $.syncing[key])) { - return; - } - if (newValue != null) { - if (newValue === $.oldValue[key]) { - return; - } - $.oldValue[key] = newValue; - return cb(JSON.parse(newValue), key.slice(g.NAMESPACE.length)); - } else { - if ($.oldValue[key] == null) { - return; - } - delete $.oldValue[key]; - return cb(void 0, key.slice(g.NAMESPACE.length)); - } - }; - $.on(window, 'storage', onChange); - return $.forceSync = function(key) { - key = g.NAMESPACE + key; - return onChange({ - key: key, - newValue: $.getValue(key) - }); - }; - })(); - } else { - $.sync = function() {}; - $.forceSync = function() {}; - } - - $["delete"] = function(keys) { - var k, key, len1; - if (!(keys instanceof Array)) { - keys = [keys]; - } - for (k = 0, len1 = keys.length; k < len1; k++) { - key = keys[k]; - $.deleteValue(g.NAMESPACE + 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 = $.getValue(g.NAMESPACE + key)) { - items[key] = JSON.parse(val); - } - } - return cb(items); - }); - }; - - $.set = function(keys, val, cb) { - var key, value; - if (typeof keys === 'string') { - $.setValue(g.NAMESPACE + keys, JSON.stringify(val)); - } else { - for (key in keys) { - value = keys[key]; - $.setValue(g.NAMESPACE + key, JSON.stringify(value)); - } - cb = val; - } - return typeof cb === "function" ? cb() : void 0; - }; - - $.clear = function(cb) { - var id; - $["delete"](Object.keys(Conf)); - $["delete"](['previousversion', 'AutoWatch', 'QR Size', 'captchas', 'QR.persona', 'hiddenPSA']); - $["delete"]((function() { - var k, len1, ref, results; - ref = ['embedding', 'updater', 'thread-stats', 'thread-watcher', 'qr']; - results = []; - for (k = 0, len1 = ref.length; k < len1; k++) { - id = ref[k]; - results.push(id + ".position"); - } - return results; - })()); - try { - $["delete"]($.listValues().map(function(key) { - return key.replace(g.NAMESPACE, ''); - })); - } catch (_error) {} - 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(type1) { - this.type = type1; - 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, keys) { - var err, errors, k, len1, name, ref; - if (keys == null) { - keys = this.keys; - } - for (k = 0, len1 = keys.length; k < len1; k++) { - name = keys[k]; - try { - if ((ref = this[name]) != null) { - ref.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(ID1) { - this.ID = ID1; - 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(ID1, board1) { - this.ID = ID1; - this.board = board1; - 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; - this.board.threads.push(this.ID, this); - g.threads.push(this.fullID, 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, thread1) { - this.thread = thread1; - 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, thread1, board1) { - var capcode, clone, date, email, flag, info, k, len1, name, post, ref, subject, tripcode, uniqueID; - this.thread = thread1; - this.board = board1; - this.ID = +root.id.slice(2); - this.fullID = this.board + "." + this.ID; - this.context = this; - root.dataset.fullID = this.fullID; - 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: [] - }; - if ($.engine === 'edge') { - Object.defineProperty(this.nodes, 'backlinks', { - configurable: true, - enumerable: true, - get: function() { - return info.getElementsByClassName('backlink'); - } - }); - } else { - this.nodes.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 || void 0; - } - 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(); - 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 (k = 0, len1 = ref.length; k < len1; k++) { - clone = ref[k]; - clone.origin = this; - } - } - this.board.posts.push(this.ID, this); - this.thread.posts.push(this.ID, this); - g.posts.push(this.fullID, this); - } - - Post.prototype.parseComment = function() { - var abbr, bq, commentDisplay, k, len1, len2, node, q, ref, spoilers; - this.nodes.comment.normalize(); - bq = this.nodes.comment.cloneNode(true); - ref = $$('.abbr + br, .exif, b, .fortune', bq); - for (k = 0, len1 = ref.length; k < len1; k++) { - node = ref[k]; - $.rm(node); - } - if (abbr = $('.abbr', bq)) { - $.rm(abbr); - } - this.info.comment = this.nodesToText(bq); - if (abbr) { - this.info.comment = this.info.comment.replace(/\n\n$/, ''); - } - commentDisplay = this.info.comment; - if (!(Conf['Remove Spoilers'] || Conf['Reveal Spoilers'])) { - spoilers = $$('s', bq); - if (spoilers.length) { - for (q = 0, len2 = spoilers.length; q < len2; q++) { - node = spoilers[q]; - $.replace(node, $.tn('[spoiler]')); - } - commentDisplay = this.nodesToText(bq); - } - } - return this.info.commentDisplay = commentDisplay.trim().replace(/\s+$/gm, ''); - }; - - 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; - }; - - Post.prototype.parseQuotes = function() { - var k, len1, quotelink, ref; - this.quotes = []; - ref = $$(':not(pre) > .quotelink', this.nodes.comment); - for (k = 0, len1 = ref.length; k < len1; k++) { - quotelink = ref[k]; - this.parseQuote(quotelink); - } - }; - - Post.prototype.parseQuote = function(quotelink) { - var fullID, match; - match = quotelink.href.match(/^https?:\/\/boards\.4chan\.org\/+([^\/]+)\/+(?:res|thread)\/+\d+(?:\/[^#]*)?#p(\d+)$/); - if (!(match || (this.isClone && quotelink.dataset.postID))) { - 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() { - var fileEl, fileText, info, link, m, ref, ref1, ref2, size, thumb, unit; - if (!(fileEl = $('.file', this.nodes.post))) { - return; - } - if (!(link = $('.fileText > a, .fileText-original > a', fileEl))) { - return; - } - if (!(info = (ref = link.nextSibling) != null ? ref.textContent.match(/\(([\d.]+ [KMG]?B).*\)/) : void 0)) { - return; - } - fileText = fileEl.firstElementChild; - this.file = { - text: fileText, - link: link, - url: link.href, - name: fileText.title || link.title || link.textContent, - size: info[1], - isImage: /(jpg|png|gif)$/i.test(link.href), - isVideo: /webm$/i.test(link.href), - dimensions: (ref1 = info[0].match(/\d+x\d+/)) != null ? ref1[0] : void 0, - tag: (ref2 = info[0].match(/,[^,]*, ([a-z]+)\)/i)) != null ? ref2[1] : void 0 - }; - 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; - if ((thumb = $('.fileThumb > [data-md5]', fileEl))) { - return $.extend(this.file, { - thumb: thumb, - thumbURL: (m = link.href.match(/\d+(?=\.\w+$)/)) ? location.protocol + "//i.4cdn.org/" + this.board + "/" + m[0] + "s.jpg" : void 0, - MD5: thumb.dataset.md5, - isSpoiler: $.hasClass(thumb.parentNode, 'imgspoiler') - }); - } - }; - - Post.prototype.kill = function(file) { - var clone, k, len1, len2, q, quotelink, ref, ref1, strong; - 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 (k = 0, len1 = ref.length; k < len1; k++) { - clone = ref[k]; - clone.kill(file); - } - if (file) { - return; - } - ref1 = Get.allQuotelinksLinkingTo(this); - for (q = 0, len2 = ref1.length; q < len2; q++) { - quotelink = ref1[q]; - if (!(!$.hasClass(quotelink, 'deadlink'))) { - continue; - } - quotelink.textContent = quotelink.textContent + '\u00A0(Dead)'; - $.addClass(quotelink, 'deadlink'); - } - }; - - Post.prototype.resurrect = function() { - var clone, k, len1, len2, q, quotelink, ref, ref1, strong; - this.isDead = false; - $.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 (k = 0, len1 = ref.length; k < len1; k++) { - clone = ref[k]; - clone.resurrect(); - } - ref1 = Get.allQuotelinksLinkingTo(this); - for (q = 0, len2 = ref1.length; q < len2; q++) { - quotelink = ref1[q]; - if (!($.hasClass(quotelink, 'deadlink'))) { - continue; - } - quotelink.textContent = quotelink.textContent.replace('\u00A0(Dead)', ''); - $.rmClass(quotelink, 'deadlink'); - } - }; - - Post.prototype.collect = function() { - 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, k, len1, ref; - this.clones.splice(index, 1); - ref = this.clones.slice(index); - for (k = 0, len1 = ref.length; k < len1; k++) { - clone = ref[k]; - clone.nodes.root.dataset.clone = index++; - } - }; - - return Post; - - })(); - - Clone = (function(superClass) { - extend(Clone, superClass); - - Clone.prototype.isClone = true; - - function Clone(origin1, context1, contractThumb) { - var file, info, inline, inlined, k, key, len1, len2, len3, len4, node, nodes, post, q, ref, ref1, ref2, ref3, ref4, ref5, root, u, v, val; - this.origin = origin1; - this.context = context1; - ref = ['ID', 'fullID', 'board', 'thread', 'info', 'quotes', 'isReply']; - for (k = 0, len1 = ref.length; k < len1; k++) { - key = ref[k]; - this[key] = this.origin[key]; - } - nodes = this.origin.nodes; - root = contractThumb ? this.cloneWithoutVideo(nodes.root) : nodes.root.cloneNode(true); - Clone.prefix || (Clone.prefix = 0); - ref1 = [root].concat(slice.call($$('[id]', root))); - for (q = 0, len2 = ref1.length; q < len2; q++) { - node = ref1[q]; - node.id = Clone.prefix + node.id; - } - Clone.prefix++; - 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: [] - }; - if ($.engine === 'edge') { - Object.defineProperty(this.nodes, 'backlinks', { - configurable: true, - enumerable: true, - get: function() { - return info.getElementsByClassName('backlink'); - } - }); - } else { - this.nodes.backlinks = info.getElementsByClassName('backlink'); - } - ref2 = $$('.inline', post); - for (u = 0, len3 = ref2.length; u < len3; u++) { - inline = ref2[u]; - $.rm(inline); - } - ref3 = $$('.inlined', post); - for (v = 0, len4 = ref3.length; v < len4; v++) { - inlined = ref3[v]; - $.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(); - this.quotes = slice.call(this.origin.quotes); - if (this.origin.file) { - this.file = {}; - ref4 = this.origin.file; - for (key in ref4) { - val = ref4[key]; - this.file[key] = val; - } - file = $('.file', post); - this.file.text = file.firstElementChild; - this.file.link = $('.fileText > a, .fileText-original', file); - 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 ((ref5 = this.file.thumb) != null ? ref5.dataset.src : void 0) { - this.file.thumb.src = this.file.thumb.dataset.src; - this.file.thumb.removeAttribute('data-src'); - } - if (this.file.thumb && contractThumb) { - ImageExpand.contract(this); - } - } - if (this.origin.isDead) { - this.isDead = true; - } - root.dataset.clone = this.origin.clones.push(this) - 1; - } - - Clone.prototype.cloneWithoutVideo = function(node) { - var child, clone, k, len1, 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 (k = 0, len1 = ref.length; k < len1; k++) { - child = ref[k]; - $.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(key1, sync, dontClean) { - var init; - this.key = key1; - this.onSync = bind(this.onSync, this); - this.data = Conf[this.key]; - $.sync(this.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(cb) { - return $.set(this.key, this.data, cb); - }; - - DataBoard.prototype["delete"] = function(arg) { - var boardID, postID, ref, threadID; - 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, cb) { - var base1, base2, base3, boardID, postID, threadID, val; - boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, val = arg.val; - $.forceSync(this.key); - if (postID !== void 0) { - ((base1 = ((base2 = this.data.boards)[boardID] || (base2[boardID] = {})))[threadID] || (base1[threadID] = {}))[postID] = val; - } else if (threadID !== void 0) { - ((base3 = this.data.boards)[boardID] || (base3[boardID] = {}))[threadID] = val; - } else { - this.data.boards[boardID] = val; - } - return this.save(cb); - }; - - DataBoard.prototype.get = function(arg) { - var ID, board, boardID, defaultValue, k, len1, postID, thread, threadID, val; - boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, defaultValue = arg.defaultValue; - if (board = this.data.boards[boardID]) { - if (threadID == null) { - if (postID != null) { - for (thread = k = 0, len1 = board.length; k < len1; thread = ++k) { - ID = board[thread]; - if (postID in thread) { - val = thread[postID]; - break; - } - } - } else { - val = board; - } - } else if (thread = board[threadID]) { - val = postID != null ? thread[postID] : thread; - } - } - return val || defaultValue; - }; - - DataBoard.prototype.forceSync = function() { - return $.forceSync(this.key); - }; - - DataBoard.prototype.clean = function() { - var boardID, now, ref, val; - $.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) { - this.ajaxClean(boardID); - } - } - }; - - DataBoard.prototype.ajaxClean = function(boardID) { - return $.cache("//a.4cdn.org/" + boardID + "/threads.json", (function(_this) { - return function(e1) { - var ref; - if ((ref = e1.target.status) !== 200 && ref !== 404) { - return; - } - return $.cache("//a.4cdn.org/" + boardID + "/archive.json", function(e2) { - var ref1; - if ((ref1 = e2.target.status) !== 200 && ref1 !== 404) { - return; - } - return _this.ajaxCleanParse(boardID, e1.target.response, e2.target.response); - }); - }; - })(this)); - }; - - DataBoard.prototype.ajaxCleanParse = function(boardID, response1, response2) { - var ID, board, k, len1, len2, len3, page, q, ref, thread, threads, u; - if (!(board = this.data.boards[boardID])) { - return; - } - threads = {}; - if (response1) { - for (k = 0, len1 = response1.length; k < len1; k++) { - page = response1[k]; - ref = page.threads; - for (q = 0, len2 = ref.length; q < len2; q++) { - thread = ref[q]; - ID = thread.no; - if (ID in board) { - threads[ID] = board[ID]; - } - } - } - } - if (response2) { - for (u = 0, len3 = response2.length; u < len3; u++) { - ID = response2[u]; - if (ID in board) { - threads[ID] = board[ID]; - } - } - } - this.data.boards[boardID] = threads; - this.deleteIfEmpty({ - boardID: boardID - }); - return this.save(); - }; - - 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, timeout1, onclose) { - this.timeout = timeout1; - this.onclose = onclose; - this.close = bind(this.close, this); - this.add = bind(this.add, this); - this.el = $.el('div', { - innerHTML: "
          " - }); - this.el.style.opacity = 0; - this.setType(type); - $.on(this.el.firstElementChild, 'click', this.close); - if (typeof content === 'string') { - content = $.tn(content); - } - $.add(this.el.lastElementChild, content); - $.ready(this.add); - } - - 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, k, len1; - this.length = 0; - if (items) { - for (k = 0, len1 = items.length; k < len1; k++) { - item = items[k]; - 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 k, key, len1, ref; - ref = slice.call(this.keys); - for (k = 0, len1 = ref.length; k < len1; k++) { - key = ref[k]; - 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(target1, origin1, cb1) { - this.target = target1; - this.origin = origin1; - this.cb = cb1 != null ? cb1 : {}; - this.onMessage = bind(this.onMessage, this); - this.send = bind(this.send, this); - $.on(window, 'message', this.onMessage); - } - - Connection.prototype.targetWindow = function() { - if (this.target instanceof window.HTMLIFrameElement) { - return this.target.contentWindow; - } else { - return this.target; - } - }; - - Connection.prototype.send = function(data) { - return this.targetWindow().postMessage("" + g.NAMESPACE + (JSON.stringify(data)), this.origin); - }; - - Connection.prototype.onMessage = function(e) { - var base1, data, type, value; - if (!(e.source === this.targetWindow() && 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 (base1 = this.cb)[type] === "function") { - base1[type](value); - } - } - }; - - return Connection; - - })(); - - Fetcher = (function() { - function Fetcher(boardID1, threadID1, postID1, root1, quoter1) { - var post; - this.boardID = boardID1; - this.threadID = threadID1; - this.postID = postID1; - this.root = root1; - this.quoter = quoter1; - 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(_this) { - return function(e, isCached) { - return _this.fetchedPost(e.target, isCached); - }; - })(this)); - } else { - this.archivedPost(); - } - } - - Fetcher.prototype.insert = function(post) { - var boardID, clone, k, len1, nodes, postID, quote, ref, ref1; - if (!this.root.parentNode) { - return; - } - clone = post.addClone(this.quoter.context, $.hasClass(this.root, 'dialog')); - Main.callbackNodes(Clone, [clone]); - nodes = clone.nodes; - $.rmAll(nodes.root); - $.add(nodes.root, nodes.post); - ref = clone.nodes.quotelinks.concat(slice.call(clone.nodes.backlinks)); - for (k = 0, len1 = ref.length; k < len1; k++) { - quote = ref[k]; - ref1 = Get.postDataFromLink(quote), boardID = ref1.boardID, postID = ref1.postID; - if (postID === this.quoter.ID && boardID === this.quoter.board.ID) { - $.addClass(quote, 'forwardlink'); - } - } - $.rmAll(this.root); - $.add(this.root, nodes.root); - return $.event('PostsInserted'); - }; - - Fetcher.prototype.fetchedPost = function(req, isCached) { - var api, board, k, len1, post, posts, status, thread; - 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 (k = 0, len1 = posts.length; k < len1; k++) { - post = posts[k]; - if (post.no === this.postID) { - break; - } - } - if (post.no !== this.postID) { - if (isCached) { - api = "//a.4cdn.org/" + this.boardID + "/thread/" + this.threadID + ".json"; - $.cleanCache(function(url) { - return url === api; - }); - $.cache(api, (function(_this) { - return function(e) { - return _this.fetchedPost(e.target, false); - }; - })(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 archive, url; - if (!Conf['Resurrect Quotes']) { - return false; - } - if (!(url = Redirect.to('post', { - boardID: this.boardID, - postID: this.postID - }))) { - return false; - } - archive = Redirect.data.post[this.boardID]; - if (/^https:\/\//.test(url) || location.protocol === 'http:') { - $.cache(url, (function(_this) { - return function(e) { - return _this.parseArchivedPost(e.target.response, url, archive); - }; - })(this), { - responseType: 'json', - withCredentials: archive.withCredentials - }); - return true; - } else if (Conf['Exempt 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 (!((ref = media[key]) != null ? ref.match(/^http:\/\//) : void 0)) { - delete media[key]; - } - } - } - } - return _this.parseArchivedPost(response, url, archive); - }; - })(this)); - return true; - } - return false; - }; - - Fetcher.prototype.parseArchivedPost = function(data, url, archive) { - var board, comment, greentext, i, j, key, o, post, ref, ref1, text, text2, thread, val; - if (post = g.posts[this.boardID + "." + this.postID]) { - this.insert(post); - return; - } - if (data == null) { - $.addClass(this.root, 'warning'); - this.root.textContent = "Error fetching Post No." + this.postID + " from " + archive.name + "."; - 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 k, len1, results; - results = []; - for (i = k = 0, len1 = comment.length; k < len1; i = ++k) { - text = comment[i]; - if (i % 2 === 1) { - results.push(this.archiveTags[text]); - } else { - greentext = text[0] === '>'; - text = text.replace(/(\[\/?[a-z]+):lit(\])/g, '$1$2'); - text = (function() { - var len2, q, ref, results1; - ref = text.split(/(>>(?:>\/[a-z\d]+\/)?\d+)/g); - results1 = []; - for (j = q = 0, len2 = ref.length; q < len2; j = ++q) { - text2 = ref[j]; - results1.push({ - innerHTML: (j % 2 ? "" + E(text2) + "" : E(text2)) - }); - } - return results1; - })(); - text = { - innerHTML: (greentext ? "" + E.cat(text) + "" : E.cat(text)) - }; - results.push(text); - } - } - return results; - }).call(this); - comment = { - innerHTML: E.cat(comment) - }; - this.threadID = +data.thread_num; - o = { - postID: this.postID, - threadID: this.threadID, - boardID: this.boardID, - isReply: this.postID !== this.threadID - }; - o.info = { - subject: data.title, - email: data.email, - name: data.name || '', - tripcode: data.trip, - capcode: (function() { - switch (data.capcode) { - case 'M': - return 'Mod'; - case 'A': - return 'Admin'; - case 'D': - return 'Developer'; - } - })(), - uniqueID: data.poster_hash, - flagCode: data.poster_country, - flag: data.poster_country_name, - dateUTC: data.timestamp, - dateText: data.fourchan_date, - commentHTML: comment - }; - if (o.info.capcode) { - delete o.info.uniqueID; - } - if ((ref = data.media) != null ? ref.media_filename : void 0) { - ref1 = data.media; - for (key in ref1) { - val = ref1[key]; - if (/_link$/.test(key) && (val != null ? val[0] : void 0) === '/') { - data.media[key] = url.split('/', 3).join('/') + val; - } - } - o.file = { - name: data.media.media_filename, - url: data.media.media_link || data.media.remote_media_link || (location.protocol + "//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: $.bytesToString(data.media.media_size), - thumbURL: data.media.thumb_link || (location.protocol + "//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 (!/\.pdf$/.test(o.file.url)) { - o.file.dimensions = o.file.width + "x" + o.file.height; - } - if (this.boardID === 'f' && data.media.exif) { - 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); - post.kill(); - if (post.file) { - post.file.thumbURL = o.file.thumbURL; - } - post.isFetchedQuote = true; - Main.callbackNodes(Post, [post]); - return this.insert(post); - }; - - Fetcher.prototype.archiveTags = { - '\n': { - innerHTML: "
          " - }, - '[b]': { - innerHTML: "" - }, - '[/b]': { - innerHTML: "" - }, - '[spoiler]': { - innerHTML: "" - }, - '[/spoiler]': { - innerHTML: "" - }, - '[code]': { - innerHTML: "
          "
          -      },
          -      '[/code]': {
          -        innerHTML: "
          " - }, - '[moot]': { - innerHTML: "
          " - }, - '[/moot]': { - innerHTML: "
          " - }, - '[banned]': { - innerHTML: "" - }, - '[/banned]': { - innerHTML: "" - } - }; - - return Fetcher; - - })(); - - Polyfill = { - init: function() { - return this.toBlob(); - }, - toBlob: function() { - if (HTMLCanvasElement.prototype.toBlob) { - return; - } - HTMLCanvasElement.prototype.toBlob = function(cb, type, encoderOptions) { - var data, i, k, l, ref, ui8a, url; - if (type == null) { - type = 'image/png'; - } - url = this.toDataURL(type, encoderOptions); - data = atob(url.slice(url.indexOf(',') + 1)); - l = data.length; - ui8a = new Uint8Array(l); - for (i = k = 0, ref = l; k < ref; i = k += 1) { - ui8a[i] = data.charCodeAt(i); - } - return cb(new Blob([ui8a], { - type: type - })); - }; - return $.globalEval("HTMLCanvasElement.prototype.toBlob = (" + HTMLCanvasElement.prototype.toBlob + ");"); - } - }; - - 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: "" - }); - 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 popstate', 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 absbot, oldFooter; - if ((oldFooter = $.id('boardNavDesktopFoot'))) { - return $.replace($('.boardList', oldFooter), Header.bottomBoardList); - } else if ((absbot = $.id('absbot'))) { - $.before(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, k, len1, len2, node, nodes, q, ref, ref1, spacer, span; - Header.boardList = boardList = $.el('span', { - id: 'board-list' - }); - $.extend(boardList, { - innerHTML: "" - }); - btn = $('.hide-board-list-button', boardList); - $.on(btn, 'click', Header.toggleBoardList); - nodes = []; - spacer = function() { - return $.el('span', { - className: 'spacer' - }); - }; - ref = $('#boardNavDesktop > .boardList').childNodes; - for (k = 0, len1 = ref.length; k < len1; k++) { - node = ref[k]; - switch (node.nodeName) { - case '#text': - ref1 = node.nodeValue; - for (q = 0, len2 = ref1.length; q < len2; q++) { - chr = ref1[q]; - 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|(mode|sort|text):"[^"]+"(,"[^"]+")?))*|[^\w@]+/g; - nodes = (function() { - var k, len1, ref, results; - ref = boardnav.match(re); - results = []; - for (k = 0, len1 = ref.length; k < len1; k++) { - t = ref[k]; - results.push(Header.mapCustomNavigation(t, as)); - } - return results; - })(); - $.add(list, nodes); - return $.ready(CatalogLinks.initBoardList); - }, - mapCustomNavigation: function(t, as) { - var a, boardID, href, indexOptions, 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 ''; - }); - indexOptions = []; - t = t.replace(/-(?:mode|sort):"([^"]+)"/g, function(m0, m1) { - indexOptions.push(m1.toLowerCase().replace(/\ /g, '-')); - return ''; - }); - indexOptions = indexOptions.join('/'); - 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 k, len1, ref; - if (boardID === '@') { - return $.el('a', { - href: 'https://twitter.com/4chan', - title: '4chan Twitter', - textContent: '@' - }); - } - for (k = 0, len1 = as.length; k < len1; k++) { - a = as[k]; - 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)/)) { - if (!(boardID === 'f' && m[1] === 'catalog')) { - a.dataset.only = m[1]; - a.href = CatalogLinks[m[1]](boardID); - if (m[1] === 'catalog') { - $.addClass(a, 'catalog'); - } - } else { - return a.firstChild; - } - } - if (Conf['JSON Index'] && indexOptions) { - a.dataset.indexOptions = indexOptions; - if (a.hostname === 'boards.4chan.org' && a.pathname.split('/')[2] === '') { - a.href += (a.hash ? '/' : '#') + indexOptions; - } - } - 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' && boardID !== 'trash') { - 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() { - 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(e) { - var el, hash; - if (e) { - if (e.state) { - return; - } - if (!history.state) { - history.replaceState({}, ''); - } - } - if ((hash = location.hash.slice(1))) { - ReplyPruning.showIfHidden(hash); - if ((el = $.id(hash))) { - return $.queueTask(function() { - return Header.scrollTo(el); - }); - } - } - }, - scrollTo: function(root, down, needed) { - var height, x; - if (!root.offsetParent) { - return; - } - if (down) { - x = Header.getBottomOf(root); - if (Conf['Fixed Header'] && 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['Fixed Header'] && 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['Fixed Header'] && 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, ref, type; - 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: "4chan X needs your permission to show desktop notifications. [FAQ]
          or " - }); - 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, - changed: {}, - init: function() { - var anchorEntry, input, k, label, len1, len2, name, pinEntry, q, ref, ref1, ref2, ref3, ref4, ref5, ref6, refNavEntry, repliesEntry, select, sortEntry; - if (g.BOARD.ID === 'f' || !Conf['JSON Index'] || g.VIEW !== 'index') { - return; - } - CatalogThread.callbacks.push({ - name: 'Catalog Features', - cb: this.catalogNode - }); - this.search = ((ref = history.state) != null ? ref.searched : void 0) || ''; - if ((ref1 = history.state) != null ? ref1.mode : void 0) { - Conf['Index Mode'] = (ref2 = history.state) != null ? ref2.mode : void 0; - } - this.currentSort = (ref3 = history.state) != null ? ref3.sort : void 0; - this.currentSort || (this.currentSort = typeof Conf['Index Sort'] === 'object' ? Conf['Index Sort'][g.BOARD.ID] || 'bump' : Conf['Index Sort']); - this.currentPage = this.getCurrentPage(); - this.processHash(); - $.addClass(doc, 'index-loading', (Conf['Index Mode'].replace(/\ /g, '-')) + "-mode"); - $.on(window, 'popstate', this.cb.popstate); - $.on(d, 'scroll', Index.scroll); - 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') - }; - sortEntry = { - el: UI.checkbox('Per-Board Sort Type', 'Per-board sort type', typeof Conf['Index Sort'] === 'object') - }; - 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') - }; - sortEntry.el.title = 'Set the sorting order of each board independently.'; - 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 (k = 0, len1 = ref4.length; k < len1; k++) { - label = ref4[k]; - 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.resort); - } - } - $.on(sortEntry.el.firstChild, 'change', this.cb.perBoardSort); - Header.menu.addEntry({ - el: $.el('span', { - textContent: 'Index Navigation' - }), - order: 100, - subEntries: [repliesEntry, sortEntry, pinEntry, anchorEntry, refNavEntry] - }); - this.navLinks = $.el('div', { - className: 'navLinks json-index' - }); - $.extend(this.navLinks, { - innerHTML: "Index Catalog Archive Bottom ×" - }); - $('.cataloglink a', this.navLinks).href = CatalogLinks.catalog(); - if ((ref5 = g.BOARD.ID) === 'b' || ref5 === 'trash') { - $('.archlistlink', this.navLinks).hidden = true; - } - $.on($('#index-last-refresh a', this.navLinks), 'click', this.cb.refreshFront); - this.searchInput = $('#index-search', this.navLinks); - this.setupSearch(); - $.on(this.searchInput, 'input', this.onSearchInput); - $.on($('#index-search-clear', this.navLinks), 'click', this.clearSearch); - this.hideLabel = $('#hidden-label', this.navLinks); - $.on($('#hidden-toggle a', this.navLinks), 'click', this.cb.toggleHiddenThreads); - this.selectMode = $('#index-mode', this.navLinks); - this.selectSort = $('#index-sort', this.navLinks); - this.selectSize = $('#index-size', this.navLinks); - $.on(this.selectMode, 'change', this.cb.mode); - $.on(this.selectSort, 'change', this.cb.sort); - $.on(this.selectSize, 'change', $.cb.value); - $.on(this.selectSize, 'change', this.cb.size); - ref6 = [this.selectMode, this.selectSize]; - for (q = 0, len2 = ref6.length; q < len2; q++) { - select = ref6[q]; - select.value = Conf[select.name]; - } - this.selectSort.value = Index.currentSort; - this.root = $.el('div', { - className: 'board json-index' - }); - this.cb.size(); - this.pagelist = $.el('div', { - className: 'pagelist json-index' - }); - $.extend(this.pagelist, { - innerHTML: "
          " - }); - $('.cataloglink a', this.pagelist).href = CatalogLinks.catalog(); - $.on(this.pagelist, 'click', this.cb.pageNav); - this.update(true); - $.onExists(doc, 'title + *', function() { - return d.title = d.title.replace(/\ -\ Page\ \d+/, ''); - }); - $.onExists(doc, '.board > .thread > .postContainer, .board + *', function() { - var board, el, len3, len4, ref7, ref8, threadRoot, topNavPos, u, v; - Index.hat = $('.board > .thread > img:first-child'); - if (Index.hat) { - if (Index.nodes) { - ref7 = Index.nodes; - for (u = 0, len3 = ref7.length; u < len3; u++) { - threadRoot = ref7[u]; - $.prepend(threadRoot, Index.hat.cloneNode(false)); - } - } - $.addClass(doc, 'hats-enabled'); - $.addStyle(".catalog-thread::after {background-image: url(" + Index.hat.src + ");}"); - } - board = $('.board'); - $.replace(board, Index.root); - $.event('PostsInserted'); - try { - d.implementation.createDocument(null, null, null).appendChild(board); - } catch (_error) {} - ref8 = $$('.navLinks'); - for (v = 0, len4 = ref8.length; v < len4; v++) { - el = ref8[v]; - $.rm(el); - } - $.rm($.id('ctrl-top')); - topNavPos = $.id('delform').previousElementSibling; - $.before(topNavPos, $.el('hr')); - return $.before(topNavPos, Index.navLinks); - }); - return Main.ready(function() { - var pagelist; - if ((pagelist = $('.pagelist'))) { - $.replace(pagelist, Index.pagelist); - } - return $.rmClass(doc, 'index-loading'); - }); - }, - scroll: function() { - var nodes, pageNum; - if (Index.req || !Index.liveThreadData || Conf['Index Mode'] !== 'infinite' || (window.scrollY <= doc.scrollHeight - (300 + window.innerHeight))) { - return; - } - if (Index.pageNum == null) { - Index.pageNum = Index.currentPage; - } - 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 Index'] || !Conf['Menu'] || !Conf['Thread Hiding Link'] || g.BOARD.ID === 'f') { - return; - } - return Menu.menu.addEntry({ - el: $.el('a', { - href: 'javascript:;', - className: 'has-shortcut-text' - }, { - innerHTML: "Shift+click" - }), - order: 20, - open: function(arg) { - var thread; - thread = arg.thread; - if (Conf['Index Mode'] !== 'catalog') { - return false; - } - this.el.firstElementChild.textContent = thread.isHidden ? 'Unhide' : 'Hide'; - 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, k, len1, type, types; - types = slice.call(Index.selectSort.options).filter(function(option) { - return !option.disabled; - }); - for (i = k = 0, len1 = types.length; k < len1; i = ++k) { - 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() { - Index.pushState({ - mode: this.value - }); - return Index.pageLoad(false); - }, - sort: function() { - Index.pushState({ - sort: this.value - }); - return Index.pageLoad(false); - }, - resort: function() { - Index.sort(); - return Index.buildIndex(); - }, - perBoardSort: function() { - Conf['Index Sort'] = this.checked ? {} : ''; - return Index.saveSort(); - }, - 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, nCommands, page, ref, searched, sort; - if (e != null ? e.state : void 0) { - ref = e.state, searched = ref.searched, mode = ref.mode, sort = ref.sort; - page = Index.getCurrentPage(); - Index.setState({ - search: searched, - mode: mode, - sort: sort, - page: page - }); - return Index.pageLoad(false); - } else { - nCommands = Index.processHash(); - if (Conf['Refreshed Navigation'] && nCommands) { - return Index.update(); - } else { - return Index.pageLoad(); - } - } - }, - 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); - }, - refreshFront: function() { - Index.pushState({ - page: 1 - }); - return Index.update(); - } - }, - scrollToIndex: function() { - return Header.scrollToIfNeeded((Index.navLinks.getBoundingClientRect().height ? Index.navLinks : Index.root)); - }, - getCurrentPage: function() { - return +window.location.pathname.split(/\/+/)[2] || 1; - }, - userPageNav: function(page) { - Index.pushState({ - page: page - }); - if (Conf['Refreshed Navigation']) { - return Index.update(); - } else { - return Index.pageLoad(); - } - }, - hashCommands: { - mode: { - 'paged': 'paged', - 'infinite-scrolling': 'infinite', - 'infinite': 'infinite', - 'all-threads': 'all pages', - 'all-pages': 'all pages', - 'catalog': 'catalog' - }, - sort: { - 'bump-order': 'bump', - 'last-reply': 'lastreply', - 'last-long-reply': 'lastlong', - 'creation-date': 'birth', - 'reply-count': 'replycount', - 'file-count': 'filecount' - } - }, - processHash: function() { - var command, commands, hash, k, leftover, len1, mode, ref, sort, state; - hash = ((ref = location.href.match(/#.*/)) != null ? ref[0] : void 0) || ''; - state = { - replace: true - }; - commands = hash.slice(1).split('/'); - leftover = []; - for (k = 0, len1 = commands.length; k < len1; k++) { - command = commands[k]; - if ((mode = Index.hashCommands.mode[command])) { - state.mode = mode; - } else if (command === 'index') { - state.mode = Conf['Previous Index Mode']; - state.page = 1; - } else if ((sort = Index.hashCommands.sort[command])) { - state.sort = sort; - } else if (/^s=/.test(command)) { - state.search = decodeURIComponent(command.slice(2)).replace(/\+/g, ' ').trim(); - } else { - leftover.push(command); - } - } - hash = leftover.join('/'); - if (hash) { - state.hash = "#" + hash; - } - Index.pushState(state); - return commands.length - leftover.length; - }, - pushState: function(state) { - var hash, pageBeforeSearch, pathname, ref, replace, search; - search = state.search, hash = state.hash, replace = state.replace; - pageBeforeSearch = (ref = history.state) != null ? ref.oldpage : void 0; - if ((search != null) && search !== Index.search) { - state.page = search ? 1 : pageBeforeSearch || 1; - if (!search) { - pageBeforeSearch = void 0; - } else if (!Index.search) { - pageBeforeSearch = Index.currentPage; - } - } - Index.setState(state); - pathname = Index.currentPage === 1 ? "/" + g.BOARD + "/" : "/" + g.BOARD + "/" + Index.currentPage; - hash || (hash = ''); - return history[replace ? 'replaceState' : 'pushState']({ - mode: Conf['Index Mode'], - sort: Index.currentSort, - searched: Index.search, - oldpage: pageBeforeSearch - }, '', location.protocol + "//" + location.host + pathname + hash); - }, - setState: function(arg) { - var hash, mode, page, ref, search, sort; - search = arg.search, mode = arg.mode, sort = arg.sort, page = arg.page, hash = arg.hash; - if ((search != null) && search !== Index.search) { - Index.changed.search = true; - Index.search = search; - } - if ((mode != null) && mode !== Conf['Index Mode']) { - Index.changed.mode = true; - Conf['Index Mode'] = mode; - $.set('Index Mode', mode); - if (!(mode === 'catalog' || Conf['Previous Index Mode'] === mode)) { - Conf['Previous Index Mode'] = mode; - $.set('Previous Index Mode', mode); - } - } - if ((sort != null) && sort !== Index.currentSort) { - Index.changed.sort = true; - Index.currentSort = sort; - Index.saveSort(); - } - if ((ref = Conf['Index Mode']) === 'all pages' || ref === 'catalog') { - page = 1; - } - if ((page != null) && page !== Index.currentPage) { - Index.changed.page = true; - Index.currentPage = page; - } - if (hash != null) { - return Index.changed.hash = true; - } - }, - saveSort: function() { - if (typeof Conf['Index Sort'] === 'object') { - Conf['Index Sort'][g.BOARD.ID] = Index.currentSort; - } else { - Conf['Index Sort'] = Index.currentSort; - } - return $.set('Index Sort', Conf['Index Sort']); - }, - pageLoad: function(scroll) { - var hash, mode, page, ref, search, sort, threads; - if (scroll == null) { - scroll = true; - } - if (!Index.liveThreadData) { - return; - } - ref = Index.changed, threads = ref.threads, search = ref.search, mode = ref.mode, sort = ref.sort, page = ref.page, hash = ref.hash; - if (threads || search || sort) { - Index.sort(); - } - if (threads || search) { - Index.buildPagelist(); - } - if (search) { - Index.setupSearch(); - } - if (mode) { - Index.setupMode(); - } - if (sort) { - Index.setupSort(); - } - if (threads || search || mode || page || sort) { - Index.buildIndex(); - } - if (threads || search || mode || page) { - Index.setPage(); - } - if (scroll && !hash) { - Index.scrollToIndex(); - } - if (hash) { - Header.hashScroll(); - } - return Index.changed = {}; - }, - setupMode: function() { - var k, len1, mode, ref; - ref = ['paged', 'infinite', 'all pages', 'catalog']; - for (k = 0, len1 = ref.length; k < len1; k++) { - mode = ref[k]; - $[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'; - }, - setupSort: function() { - return Index.selectSort.value = Index.currentSort; - }, - 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, k, maxPageNum, nodes, pagesRoot, ref; - pagesRoot = $('.pages', Index.pagelist); - maxPageNum = Index.getMaxPageNum(); - if (pagesRoot.childElementCount !== maxPageNum) { - nodes = []; - for (i = k = 1, ref = maxPageNum; k <= ref; i = k += 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.currentPage; - 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, ref, ref1, thread, threadID; - 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(firstTime) { - var now, ref, ref1; - if ((ref = Index.req) != null) { - ref.abort(); - } - if ((ref1 = Index.notice) != null) { - ref1.close(); - } - if (Conf['Index Refresh Notifications'] && d.readyState !== 'loading') { - Index.notice = new Notice('info', 'Refreshing index...'); - } else { - now = Date.now(); - $.ready(function() { - return Index.nTimeout = setTimeout((function() { - if (Index.req && !Index.notice) { - return Index.notice = new Notice('info', 'Refreshing index...'); - } - }), 3 * $.SECOND - (Date.now() - now)); - }); - } - if (!firstTime && d.readyState !== 'loading' && !$('.board + *')) { - location.reload(); - return; - } - Index.req = $.ajax("//a.4cdn.org/" + g.BOARD + "/catalog.json", { - onabort: Index.load, - onloadend: Index.load - }, { - whenModified: 'Index' - }); - return $.addClass(Index.button, 'fa-spin'); - }, - load: function(e) { - var err, nTimeout, notice, ref, req, timeEl; - $.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; - if (notice != 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); - } else if (req.status === 304) { - Index.pageLoad(); - } - } 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; - } - if (notice) { - if (Conf['Index Refresh Notifications']) { - notice.setType('success'); - notice.el.lastElementChild.textContent = 'Index refreshed!'; - setTimeout(notice.close, $.SECOND); - } else { - notice.close(); - } - } - timeEl = $('#index-last-refresh time', Index.navLinks); - timeEl.dataset.utc = Date.parse(req.getResponseHeader('Last-Modified')); - return RelativeDates.update(timeEl); - }, - parse: function(pages) { - $.cleanCache(function(url) { - return /^\/\/a\.4cdn\.org\//.test(url); - }); - Index.parseThreadList(pages); - Index.buildThreads(); - Index.changed.threads = true; - return Index.pageLoad(); - }, - parseThreadList: function(pages) { - var ref; - Index.pagesNum = pages.length; - Index.threadsNumPerPage = ((ref = pages[0]) != null ? ref.threads.length : void 0) || 1; - 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 ref1; - if (ref1 = thread.ID, indexOf.call(Index.liveThreadIDs, ref1) < 0) { - return thread.collect(); - } - }); - }, - buildThreads: function() { - var err, errors, i, k, len1, posts, ref, thread, threadData, threadRoot, threads; - if (!Index.liveThreadData) { - return; - } - Index.nodes = []; - threads = []; - posts = []; - ref = Index.liveThreadData; - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - 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.OP && !thread.OP.isFetchedQuote)) { - 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, k, lastReplies, len1, len2, node, nodes, post, posts, q, thread, threadRoot; - posts = []; - for (k = 0, len1 = threadRoots.length; k < len1; k++) { - threadRoot = threadRoots[k]; - thread = Get.threadFromRoot(threadRoot); - i = Index.liveThreadIDs.indexOf(thread.ID); - if (!(lastReplies = Index.liveThreadData[i].last_replies)) { - continue; - } - nodes = []; - for (q = 0, len2 = lastReplies.length; q < len2; q++) { - data = lastReplies[q]; - if ((post = thread.posts[data.no]) && !post.isFetchedQuote) { - 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, k, len1, thread, threads; - threads = Index.sortedNodes.map(function(threadRoot) { - return Get.threadFromRoot(threadRoot); - }).filter(function(thread) { - return !thread.isHidden !== Index.showHiddenThreads; - }); - catalogThreads = []; - for (k = 0, len1 = threads.length; k < len1; k++) { - thread = threads[k]; - 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, k, len1, node, ratio, ref, size, thumb, width; - size = Conf['Index Size'] === 'small' ? 150 : 250; - for (k = 0, len1 = nodes.length; k < len1; k++) { - node = nodes[k]; - 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 k, lastlong, len1, liveThreadData, liveThreadIDs, nodes, sortedNodes, sortedThreadIDs, threadID; - liveThreadIDs = Index.liveThreadIDs, liveThreadData = Index.liveThreadData; - if (!liveThreadData) { - return; - } - sortedThreadIDs = (function() { - switch (Index.currentSort) { - case 'lastreply': - return 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; - }); - case 'lastlong': - lastlong = function(thread) { - var i, k, r, ref; - ref = thread.last_replies || []; - for (i = k = ref.length - 1; k >= 0; i = k += -1) { - r = ref[i]; - if (r.com && Build.parseComment(r.com).replace(/[^a-z]/ig, '').length >= 100) { - return r; - } - } - return thread; - }; - return slice.call(liveThreadData).sort(function(a, b) { - return lastlong(b).no - lastlong(a).no; - }).map(function(post) { - return post.no; - }); - case 'bump': - return liveThreadIDs; - case 'birth': - return slice.call(liveThreadIDs).sort(function(a, b) { - return b - a; - }); - case 'replycount': - return slice.call(liveThreadData).sort(function(a, b) { - return b.replies - a.replies; - }).map(function(post) { - return post.no; - }); - case 'filecount': - return slice.call(liveThreadData).sort(function(a, b) { - return b.images - a.images; - }).map(function(post) { - return post.no; - }); - } - })(); - Index.sortedNodes = sortedNodes = []; - nodes = Index.nodes; - for (k = 0, len1 = sortedThreadIDs.length; k < len1; k++) { - threadID = sortedThreadIDs[k]; - 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, k, len1, ref, threadRoot, topNodes; - topNodes = []; - bottomNodes = []; - ref = Index.sortedNodes; - for (k = 0, len1 = ref.length; k < len1; k++) { - threadRoot = ref[k]; - (match(Get.threadFromRoot(threadRoot)) ? topNodes : bottomNodes).push(threadRoot); - } - return Index.sortedNodes = topNodes.concat(bottomNodes); - }, - buildIndex: function() { - var i, nodes, page, post; - if (!Index.liveThreadData) { - return; - } - 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.currentPage) { - Index.currentPage = page; - Index.pushState({ - page: page - }); - Index.setPage(); - } - } - nodes = Index.buildSinglePage(Index.currentPage); - } - delete Index.pageNum; - $.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 k, len1, node, thumb; - for (k = 0, len1 = nodes.length; k < len1; k++) { - node = nodes[k]; - if (thumb = $('img[data-src]', node)) { - thumb.src = thumb.dataset.src; - thumb.removeAttribute('data-src'); - } - $.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() { - 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; - } - Index.pushState({ - search: search, - replace: !!search === !!Index.search - }); - return Index.pageLoad(false); - }, - 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, k, key, keyword, len1, len2, q, ref, ref1, text; - ref = thread.OP, info = ref.info, file = ref.file; - text = []; - ref1 = ['comment', 'subject', 'name', 'tripcode', 'email']; - for (k = 0, len1 = ref1.length; k < len1; k++) { - key = ref1[k]; - if (key in info) { - text.push(info[key]); - } - } - if (file) { - text.push(file.name); - } - text = text.join(' ').toLowerCase(); - for (q = 0, len2 = keywords.length; q < len2; q++) { - keyword = keywords[q]; - 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|#44);/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; - } - }, - spoilerThumb: function(boardID) { - var spoilerRange; - if (spoilerRange = Build.spoilerRange[boardID]) { - return Build.staticPath + "spoiler-" + boardID + (Math.floor(1 + spoilerRange * Math.random())) + ".png"; - } else { - return Build.staticPath + "spoiler.png"; - } - }, - 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; - } - }, - parseJSON: function(data, boardID) { - var o; - o = { - postID: data.no, - threadID: data.resto || data.no, - boardID: boardID, - isReply: !!data.resto, - isSticky: !!data.sticky, - isClosed: !!data.closed, - isArchived: !!data.archived, - fileDeleted: !!data.filedeleted - }; - o.info = { - subject: Build.unescape(data.sub), - email: Build.unescape(data.email), - name: Build.unescape(data.name) || '', - tripcode: data.trip, - uniqueID: data.id, - flagCode: data.country, - flag: Build.unescape(data.country_name), - dateUTC: data.time, - dateText: data.now, - commentHTML: { - innerHTML: data.com || '' - } - }; - if (data.capcode) { - o.info.capcode = data.capcode.replace(/_highlight$/, '').replace(/_/g, ' ').replace(/\b\w/g, function(c) { - return c.toUpperCase(); - }); - o.capcodeHighlight = /_highlight$/.test(data.capcode); - delete o.info.uniqueID; - } - if (data.ext) { - o.file = { - name: (Build.unescape(data.filename)) + data.ext, - url: boardID === 'f' ? location.protocol + "//i.4cdn.org/" + boardID + "/" + (encodeURIComponent(data.filename)) + data.ext : location.protocol + "//i.4cdn.org/" + boardID + "/" + data.tim + data.ext, - height: data.h, - width: data.w, - MD5: data.md5, - size: $.bytesToString(data.fsize), - thumbURL: location.protocol + "//i.4cdn.org/" + boardID + "/" + data.tim + "s.jpg", - theight: data.tn_h, - twidth: data.tn_w, - isSpoiler: !!data.spoiler, - tag: data.tag - }; - if (!/\.pdf$/.test(o.file.url)) { - o.file.dimensions = o.file.width + "x" + o.file.height; - } - } - return o; - }, - parseComment: function(html) { - html = html.replace(//gi, '\n').replace(/\n\nRolled [^<]*<\/b>/i, '').replace(/]*>/g, ''); - return Build.unescape(html); - }, - postFromObject: function(data, boardID, suppressThumb) { - var o; - o = Build.parseJSON(data, boardID); - return Build.post(o, suppressThumb); - }, - post: function(o, suppressThumb) { - var boardID, capcode, capcodeDescription, capcodeLC, capcodeLong, capcodePlural, commentHTML, container, dateText, dateUTC, email, file, fileBlock, fileThumb, fileURL, flag, flagCode, gifIcon, href, k, len1, match, name, postClass, postID, postInfo, postLink, protocol, quote, quoteLink, ref, ref1, shortFilename, staticPath, subject, threadID, tripcode, uniqueID, wholePost; - postID = o.postID, threadID = o.threadID, boardID = o.boardID, file = o.file; - ref = o.info, subject = ref.subject, email = ref.email, name = ref.name, tripcode = ref.tripcode, capcode = ref.capcode, uniqueID = ref.uniqueID, flagCode = ref.flagCode, flag = ref.flag, dateUTC = ref.dateUTC, dateText = ref.dateText, commentHTML = ref.commentHTML; - staticPath = Build.staticPath, gifIcon = Build.gifIcon; - - /* Post Info */ - if (capcode) { - capcodeLC = capcode.toLowerCase(); - if (capcode === 'Founder') { - capcodePlural = 'the Founder'; - capcodeDescription = "4chan's Founder"; - } else { - capcodeLong = { - 'Admin': 'Administrator', - 'Mod': 'Moderator' - }[capcode] || capcode; - capcodePlural = capcodeLong + "s"; - capcodeDescription = "a 4chan " + capcodeLong; - } - } - postLink = Build.postURL(boardID, threadID, postID); - quoteLink = Build.sameThread(boardID, threadID) ? "javascript:quote('" + (+postID) + "');" : "/" + boardID + "/thread/" + threadID + "#q" + postID; - postInfo = { - innerHTML: "
          " + (!o.isReply || boardID === "f" || subject ? "" + E(subject || "") + " " : "") + "" + (email ? "" : "") + "" + E(name) + "" + (tripcode ? " " + E(tripcode) + "" : "") + (capcode ? " ## " + E(capcode) + "" : "") + (email ? "" : "") + (boardID === "f" && !o.isReply || capcode ? "" : " ") + (capcode ? " \""" : "") + (uniqueID && !capcode ? " (ID: " + E(uniqueID) + ")" : "") + (flagCode ? " " : "") + " " + E(dateText) + " No." + E(postID) + "" + (o.isSticky ? " \"Sticky\"" : "") + (o.isClosed && !o.isArchived ? " \"Closed\"" : "") + (o.isArchived ? " \"Archived\"" : "") + (!o.isReply && g.VIEW === "index" ? "   [Reply]" : "") + "
          " - }; - - /* File Info */ - if (file) { - protocol = /^https?:(?=\/\/i\.4cdn\.org\/)/; - fileURL = file.url.replace(protocol, ''); - shortFilename = Build.shortFilename(file.name); - fileThumb = file.isSpoiler ? Build.spoilerThumb(boardID) : file.thumbURL.replace(protocol, ''); - } - fileBlock = { - innerHTML: (file ? "
          " + (boardID === "f" ? "
          File: " + E(file.name) + "-(" + E(file.size) + ", " + E(file.dimensions) + (file.tag ? ", " + E(file.tag) : "") + ")
          " : "
          File: " + (file.isSpoiler ? "Spoiler Image" : E(shortFilename)) + " (" + E(file.size) + ", " + E(file.dimensions || "PDF") + ")
          ") + "
          " : (o.fileDeleted ? "
          \"File
          " : "")) - }; - - /* Whole Post */ - postClass = o.isReply ? 'reply' : 'op'; - wholePost = { - innerHTML: (o.isReply ? "
          >>
          " : "") + "
          " + (o.isReply ? postInfo.innerHTML + fileBlock.innerHTML : fileBlock.innerHTML + postInfo.innerHTML) + "
          " + commentHTML.innerHTML + "
          " - }; - container = $.el('div', { - className: "postContainer " + postClass + "Container", - id: "pc" + postID - }); - $.extend(container, wholePost); - ref1 = $$('.quotelink', container); - for (k = 0, len1 = ref1.length; k < len1; k++) { - quote = ref1[k]; - 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] || '#'; - } else if (/^\d+(#|$)/.test(href) && !(g.VIEW === 'thread' && g.BOARD.ID === boardID)) { - quote.href = "/" + boardID + "/thread/" + href; - } - } - return container; - }, - summaryText: function(status, posts, files) { - var text; - text = ''; - if (status) { - text += status + " "; - } - text += posts + " post" + (posts > 1 ? 's' : ''); - if (+files) { - text += " and " + files + " image repl" + (files > 1 ? 'ies' : 'y'); - } - return text += " " + (status === '-' ? 'shown' : 'omitted') + "."; - }, - summary: function(boardID, threadID, posts, files) { - return $.el('a', { - className: 'summary', - textContent: Build.summaryText('', posts, files), - href: "/" + boardID + "/thread/" + threadID - }); - }, - thread: function(board, data, full) { - var OP, root; - Build.spoilerRange[board] = data.custom_spoiler; - if (OP = board.posts[data.no]) { - if (OP.isFetchedQuote) { - OP = null; - } - } - if (OP && (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, true)]; - 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, k, len1, len2, len3, len4, pageCount, postCount, pp, q, quote, ref, ref1, ref2, ref3, ref4, root, spoilerRange, src, staticPath, u, v; - 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'; - } - postCount = data.replies + 1; - fileCount = data.images + !!data.ext; - pageCount = Math.floor(Index.liveThreadIDs.indexOf(thread.ID) / Index.threadsNumPerPage) + 1; - comment = { - innerHTML: data.com || '' - }; - root = $.el('div', { - className: 'catalog-thread' - }); - $.extend(root, { - innerHTML: "
          " + E(postCount) + " / " + E(fileCount) + " / " + E(pageCount) + "
          " + (thread.OP.info.subject ? "
          " + E(thread.OP.info.subject) + "
          " : "") + "
          " + comment.innerHTML + "
          " - }); - root.dataset.fullID = thread.fullID; - if (thread.OP.highlights) { - $.addClass.apply($, [root].concat(slice.call(thread.OP.highlights))); - } - ref = $$('.quotelink', root.lastElementChild); - for (k = 0, len1 = ref.length; k < len1; k++) { - quote = ref[k]; - href = quote.getAttribute('href'); - if (href[0] === '#') { - quote.href = ("/" + thread.board + "/thread/" + thread.ID) + href; - } - } - ref1 = $$('.abbr, .exif', root.lastElementChild); - for (q = 0, len2 = ref1.length; q < len2; q++) { - exif = ref1[q]; - $.rm(exif); - } - ref2 = $$('.prettyprint', root.lastElementChild); - for (u = 0, len3 = ref2.length; u < len3; u++) { - pp = ref2[u]; - cc = $.el('span', { - className: 'catalog-code' - }); - $.add(cc, slice.call(pp.childNodes)); - $.replace(pp, cc); - } - ref3 = $$('br', root.lastElementChild); - for (v = 0, len4 = ref3.length; v < len4; v++) { - br = ref3[v]; - 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.commentDisplay.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 index, post; - if (root == null) { - return null; - } - post = g.posts[root.dataset.fullID]; - index = root.dataset.clone; - 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)); - }, - postDataFromLink: function(link) { - var boardID, path, postID, ref, threadID; - 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, k, len1, posts, qPost, quote, quotelinks, ref; - quotelinks = []; - posts = g.posts; - fullID = post.fullID; - handleQuotes = function(qPost, type) { - var clone, k, len1, ref; - quotelinks.push.apply(quotelinks, qPost.nodes[type]); - ref = qPost.clones; - for (k = 0, len1 = ref.length; k < len1; k++) { - clone = ref[k]; - 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 (k = 0, len1 = ref.length; k < len1; k++) { - quote = ref[k]; - 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 k, len1, ref, script; - ref = $$('script:not([src])', d.head); - for (k = 0, len1 = ref.length; k < len1; k++) { - script = ref[k]; - 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, k, len1, move, 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 (k = 0, len1 = ref.length; k < len1; k++) { - child = ref[k]; - 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(type1) { - this.type = type1; - 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, k, left, len1, mRect, menu, ref, ref1, ref2, right, style, top; - menu = this.menu = this.makeMenu(); - currentMenu = this; - lastToggledButton = button; - this.entries.sort(function(first, second) { - return first.order - second.order; - }); - ref = this.entries; - for (k = 0, len1 = ref.length; k < len1; k++) { - entry = ref[k]; - this.insertEntry(entry, menu, data); - } - $.addClass(lastToggledButton, 'active'); - $.on(d, 'click CloseMenu', this.close); - if (this.type !== 'gallery') { - $.on(d, 'scroll', 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 err, k, len1, ref, subEntry, submenu; - if (typeof entry.open === 'function') { - try { - if (!entry.open(data)) { - return; - } - } catch (_error) { - err = _error; - Main.handleErrors({ - message: "Error in building the " + this.type + " menu.", - error: err - }); - 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 (k = 0, len1 = ref.length; k < len1; k++) { - subEntry = ref[k]; - 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, k, left, len1, ref, ref1, ref2, right, sRect, style, submenu, top; - while (focused = $.x('parent::*/child::*[contains(@class,"focused")]', entry)) { - $.rmClass(focused, 'focused'); - } - ref = $$('.focused', entry); - for (k = 0, len1 = ref.length; k < len1; k++) { - focused = ref[k]; - $.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, k, len1, subEntries, subEntry; - 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 (k = 0, len1 = subEntries.length; k < len1; k++) { - subEntry = subEntries[k]; - this.parseEntry(subEntry); - } - }; - - return Menu; - - })(); - dragstart = function(e) { - var el, isTouching, o, rect, ref, screenHeight, screenWidth; - 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 k, len1, ref, touch; - ref = e.changedTouches; - for (k = 0, len1 = ref.length; k < len1; k++) { - touch = ref[k]; - 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 k, len1, ref, touch; - ref = e.changedTouches; - for (k = 0, len1 = ref.length; k < len1; k++) { - touch = ref[k]; - 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 cb, el, endEvents, height, latestEvent, noRemove, o, ref, root; - root = arg.root, el = arg.el, latestEvent = arg.latestEvent, endEvents = arg.endEvents, 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); - o.hover(o.latestEvent); - new MutationObserver(function() { - if (el.parentNode) { - return o.hover(o.latestEvent); - } - }).observe(el, { - childList: true - }); - $.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); - }; - hoverstart.padding = 25; - hover = function(e) { - var clientX, clientY, height, left, ref, right, style, threshold, top; - this.latestEvent = e; - height = (this.height || this.el.offsetHeight) + hoverstart.padding; - 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) { - var options, ref, workaround; - if (headers == null) { - headers = {}; - } - url = url.replace(/^((?:https?:)?\/\/(?:\w+\.)?4c(?:ha|d)n\.org)\/adv\//, '$1//adv/'); - workaround = $.engine === 'gecko' && (typeof GM_info !== "undefined" && GM_info !== null) && /^[0-2]\.|^3\.[01](?!\d)/.test(GM_info.version); - workaround || (workaround = /PaleMoon\//.test(navigator.userAgent)); - workaround || (workaround = (typeof GM_info !== "undefined" && GM_info !== null ? (ref = GM_info.script) != null ? ref.includeJSB : void 0 : void 0) != null); - options = { - method: "GET", - url: url, - headers: headers, - onload: function(xhr) { - var contentDisposition, contentType, data, i, r, ref1, ref2; - if (workaround) { - r = xhr.responseText; - data = new Uint8Array(r.length); - i = 0; - while (i < r.length) { - data[i] = r.charCodeAt(i); - i++; - } - } else { - data = new Uint8Array(xhr.response); - } - if (typeof xhr.responseHeaders === 'object') { - contentType = xhr.responseHeaders['Content-Type']; - contentDisposition = xhr.responseHeaders['Content-Disposition']; - } else { - contentType = (ref1 = xhr.responseHeaders.match(/Content-Type:\s*(.*)/i)) != null ? ref1[1] : void 0; - contentDisposition = (ref2 = xhr.responseHeaders.match(/Content-Disposition:\s*(.*)/i)) != null ? ref2[1] : void 0; - } - return cb(data, contentType, contentDisposition); - }, - onerror: function() { - return cb(null); - }, - onabort: function() { - return cb(null); - } - }; - if (workaround) { - options.overrideMimeType = options.mimeType = 'text/plain; charset=x-user-defined'; - } else { - options.responseType = 'arraybuffer'; - } - return GM_xmlhttpRequest(options); - }, - file: function(url, cb) { - return CrossOrigin.binary(url, function(data, contentType, contentDisposition) { - var blob, match, mime, name, ref, ref1, ref2, ref3; - 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, '"'); - } - if ((typeof GM_info !== "undefined" && GM_info !== null ? (ref3 = GM_info.script) != null ? ref3.includeJSB : void 0 : void 0) != null) { - mime = QR.typeFromExtension[name.match(/[^.]*$/)[0].toLowerCase()] || 'application/octet-stream'; - } - 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 k, len1, ref, response; - response = JSON.parse(xhr.responseText); - ref = callbacks[url]; - for (k = 0, len1 = ref.length; k < len1; k++) { - cb = ref[k]; - 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, ref, tripcode; - 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 k, len1, len2, name, q, ref, ref1, trip; - ref = $$('.name'); - for (k = 0, len1 = ref.length; k < len1; k++) { - name = ref[k]; - name.textContent = 'Anonymous'; - } - ref1 = $$('.postertrip'); - for (q = 0, len2 = ref1.length; q < len2; q++) { - trip = ref1[q]; - $.rm(trip); - } - }); - } - }; - - Filter = { - filters: {}, - init: function() { - var boards, err, excludes, filter, hl, k, key, len1, line, op, ref, ref1, ref2, ref3, ref4, ref5, ref6, regexp, stub, top; - 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 (k = 0, len1 = ref1.length; k < len1; k++) { - line = ref1[k]; - 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'; - boards = boards === 'global' ? null : boards.split(','); - if (boards === null) { - excludes = ((ref3 = filter.match(/exclude:([^;]+)/)) != null ? ref3[1].toLowerCase().split(',') : void 0) || null; - } - 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, boards, excludes, 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, boards, excludes, 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, boardID, isReply) { - if (boards && indexOf.call(boards, boardID) < 0) { - return false; - } - if (excludes && indexOf.call(excludes, boardID) >= 0) { - return false; - } - if (isReply && op === 'only' || !isReply && op === 'no') { - return false; - } - if (!test(value)) { - return false; - } - return settings; - }; - }, - node: function() { - var filter, k, key, len1, ref, ref1, result, value; - if (this.isClone) { - return; - } - for (key in Filter.filters) { - if ((value = Filter[key](this)) != null) { - ref = Filter.filters[key]; - for (k = 0, len1 = ref.length; k < len1; k++) { - filter = ref[k]; - if (!(result = filter(value, this.board.ID, this.isReply))) { - continue; - } - if (result.hide && !this.isFetchedQuote) { - 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; - } - } - } - } - }, - isHidden: function(post) { - var filter, k, key, len1, ref, result, value; - for (key in Filter.filters) { - if ((value = Filter[key](post)) != null) { - ref = Filter.filters[key]; - for (k = 0, len1 = ref.length; k < len1; k++) { - filter = ref[k]; - if (result = filter(value, post.boardID, post.isReply)) { - if (result.hide) { - return true; - } - } - } - } - } - return false; - }, - postID: function(post) { - var ref; - return "" + ((ref = post.ID) != null ? ref : post.postID); - }, - name: function(post) { - return post.info.name; - }, - uniqueID: function(post) { - return post.info.uniqueID; - }, - tripcode: function(post) { - return post.info.tripcode; - }, - capcode: function(post) { - return post.info.capcode; - }, - subject: function(post) { - return post.info.subject; - }, - comment: function(post) { - var base1; - return (base1 = post.info).comment != null ? base1.comment : base1.comment = Build.parseComment(post.info.commentHTML.innerHTML); - }, - flag: function(post) { - return post.info.flag; - }, - filename: function(post) { - var ref; - return (ref = post.file) != null ? ref.name : void 0; - }, - dimensions: function(post) { - var ref; - return (ref = post.file) != null ? ref.dimensions : void 0; - }, - filesize: function(post) { - var ref; - return (ref = post.file) != null ? ref.size : void 0; - }, - MD5: function(post) { - var ref; - return (ref = post.file) != null ? ref.MD5 : void 0; - }, - menu: { - init: function() { - var div, entry, k, len1, ref, ref1, type; - 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 (k = 0, len1 = ref1.length; k < len1; k++) { - type = ref1[k]; - 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 != null; - } - }; - }, - 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, ref, replies, thisPost; - if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Menu'] || !Conf['Reply Hiding Link']) { - return; - } - div = $.el('div', { - className: 'hide-reply-link', - textContent: 'Hide' - }); - 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' - }); - 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, k, len1, quotelink, 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 (k = 0, len1 = ref.length; k < len1; k++) { - quotelink = ref[k]; - $.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 k, len1, quotelink, 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 (k = 0, len1 = ref.length; k < len1; k++) { - quotelink = ref[k]; - $.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, k, len1, len2, obj, q, quote, recursive, ref, ref1; - if (this.isClone || this.isFetchedQuote) { - return; - } - ref = this.quotes; - for (k = 0, len1 = ref.length; k < len1; k++) { - quote = ref[k]; - if (obj = Recursive.recursives[quote]) { - ref1 = obj.recursives; - for (i = q = 0, len2 = ref1.length; q < len2; i = ++q) { - recursive = ref1[i]; - recursive.apply(null, [this].concat(slice.call(obj.args[i]))); - } - } - } - }, - add: function() { - var args, base1, name1, obj, post, recursive; - recursive = arguments[0], post = arguments[1], args = 3 <= arguments.length ? slice.call(arguments, 2) : []; - obj = (base1 = Recursive.recursives)[name1 = post.fullID] || (base1[name1] = { - recursives: [], - args: [] - }); - obj.recursives.push(recursive); - return obj.args.push(args); - }, - rm: function(recursive, post) { - var i, k, len1, obj, rec, ref; - if (!(obj = Recursive.recursives[post.fullID])) { - return; - } - ref = obj.recursives; - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - 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 Index']) { - return; - } - this.db = new DataBoard('hiddenThreads'); - if (g.VIEW === 'catalog') { - return this.catalogWatch(); - } - this.catalogSet(g.BOARD); - return Post.callbacks.push({ - name: 'Thread Hiding', - cb: this.node - }); - }, - catalogSet: function(board) { - var hiddenThreads, threadID; - if (!$.hasStorage) { - return; - } - 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() { - if (!$.hasStorage) { - return; - } - this.hiddenThreads = JSON.parse(localStorage.getItem("4chan-hide-t-" + g.BOARD)) || {}; - return Main.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 (this.isReply || this.isClone || this.isFetchedQuote) { - return; - } - if (data = ThreadHiding.db.get({ - boardID: this.board.ID, - threadID: this.ID - })) { - ThreadHiding.hide(this.thread, data.makeStub); - } - if (!Conf['Thread Hiding Buttons']) { - return; - } - return $.prepend(this.nodes.root, ThreadHiding.makeButton(this.thread, 'hide')); - }, - onIndexBuild: function(nodes) { - var k, len1, root, thread; - for (k = 0, len1 = nodes.length; k < len1; k++) { - root = nodes[k]; - 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' - }); - 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 Index'] && 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', - 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 Index'] && 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 Index'] && 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: "" - }); - 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 Index']) { - 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 Index']) { - 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, k, len1, len2, len3, link, markYours, nodes, post, q, quote, ref, ref1, ref2, u; - if (this.isClone || !this.quotes.length || this.isRebuilt) { - return; - } - markYours = Conf['Mark Quotes of You'] && ((ref = QuoteYou.db) != null ? ref.get({ - boardID: this.board.ID, - threadID: this.thread.ID, - postID: this.ID - }) : void 0); - 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)' : '') - }); - ref1 = this.quotes; - for (k = 0, len1 = ref1.length; k < len1; k++) { - quote = ref1[k]; - containers = [QuoteBacklink.getContainer(quote)]; - if ((post = g.posts[quote]) && post.nodes.backlinkContainer) { - ref2 = post.clones; - for (q = 0, len2 = ref2.length; q < len2; q++) { - clone = ref2[q]; - containers.push(clone.nodes.backlinkContainer); - } - } - for (u = 0, len3 = containers.length; u < len3; u++) { - container = containers[u]; - link = a.cloneNode(true); - nodes = container.firstChild ? [$.tn(' '), link] : [link]; - 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 base1; - return (base1 = this.containers)[id] || (base1[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, k, len1, quotelink, ref, ref1, ref2, thread, threadID; - if (this.isClone && this.thread === this.context.thread) { - return; - } - ref = this.context, board = ref.board, thread = ref.thread; - ref1 = this.nodes.quotelinks; - for (k = 0, len1 = ref1.length; k < len1; k++) { - quotelink = ref1[k]; - 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; - } - if (Conf['Comment Expansion']) { - ExpandComment.callbacks.push(this.node); - } - return Post.callbacks.push({ - name: 'Quote Inlining', - cb: this.node - }); - }, - node: function() { - var isClone, k, len1, len2, link, process, q, ref, ref1; - process = QuoteInline.process; - isClone = this.isClone; - ref = this.nodes.quotelinks; - for (k = 0, len1 = ref.length; k < len1; k++) { - link = ref[k]; - process(link, isClone); - } - ref1 = this.nodes.backlinks; - for (q = 0, len2 = ref1.length; q < len2; q++) { - link = ref1[q]; - process(link, isClone); - } - }, - process: function(link, clone) { - if (Conf['Quote Hash Navigation']) { - if (!clone) { - $.after(link, QuoteInline.qiQuote(link, $.hasClass(link, 'filtered'))); - } - } - return $.on(link, 'click', QuoteInline.toggle); - }, - 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, quoter, ref, ref1, threadID; - if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) { - return; - } - ref = Get.postDataFromLink(this), boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; - if (Conf['Inline Cross-thread Quotes Only'] && g.VIEW === 'thread' && ((ref1 = g.posts[boardID + "." + postID]) != null ? ref1.nodes.root.offsetParent : void 0)) { - return; - } - e.preventDefault(); - quoter = Get.postFromNode(this); - context = quoter.context; - if ($.hasClass(this, 'inlined')) { - QuoteInline.rm(this, boardID, threadID, postID, context); - } else { - if ($.x("ancestor::div[@data-full-i-d='" + boardID + "." + postID + "']", this)) { - return; - } - QuoteInline.add(this, boardID, threadID, postID, context, quoter); - } - 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, quoter) { - var inline, isBacklink, post, qroot, root; - isBacklink = $.hasClass(quotelink, 'backlink'); - inline = $.el('div', { - className: 'inline' - }); - inline.dataset.fullID = boardID + "." + postID; - 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, quoter); - 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, ref, root; - isBacklink = $.hasClass(quotelink, 'backlink'); - root = QuoteInline.findRoot(quotelink, isBacklink); - root = $.x("following-sibling::div[@data-full-i-d='" + boardID + "." + 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.context.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 k, len1, link, ref; - ref = this.nodes.quotelinks.concat(slice.call(this.nodes.backlinks)); - for (k = 0, len1 = ref.length; k < len1; k++) { - link = ref[k]; - $.on(link, 'mouseover', QuotePreview.mouseover); - } - }, - mouseover: function(e) { - var boardID, k, len1, origin, post, postID, posts, qp, ref, threadID; - if ($.hasClass(this, 'inlined') || !d.contains(this)) { - 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.postFromNode(this)); - UI.hover({ - root: this, - el: qp, - latestEvent: e, - endEvents: 'mouseout click', - cb: QuotePreview.mouseout - }); - if (Conf['Quote Highlighting'] && (origin = g.posts[boardID + "." + postID])) { - posts = [origin].concat(origin.clones); - posts.pop(); - for (k = 0, len1 = posts.length; k < len1; k++) { - post = posts[k]; - $.addClass(post.nodes.post, 'qphl'); - } - } - }, - mouseout: function() { - var clone, k, len1, post, ref, root; - 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 (k = 0, len1 = ref.length; k < len1; k++) { - post = ref[k]; - $.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, k, len1, postID, quotelink, ref, ref1, ref2; - if (this.isClone) { - return; - } - ref = this.nodes.quotelinks; - for (k = 0, len1 = ref.length; k < len1; k++) { - quotelink = ref[k]; - 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.controls = $.el('label', { - innerHTML: " Threading" - }); - this.threadNewLink = $.el('span', { - className: 'brackets-wrap threadnewlink', - hidden: true - }); - $.extend(this.threadNewLink, { - innerHTML: "Thread New Posts" - }); - this.input = $('input', this.controls); - this.input.checked = Conf['Thread Quotes']; - $.on(this.input, 'change', this.setEnabled); - $.on(this.input, 'change', this.rethread); - $.on(this.threadNewLink.firstElementChild, 'click', this.rethread); - $.on(d, '4chanXInitFinished', (function(_this) { - return function() { - return _this.ready = true; - }; - })(this)); - Header.menu.addEntry(this.entry = { - el: this.controls, - order: 99 - }); - Thread.callbacks.push({ - name: 'Quote Threading', - cb: this.setThread - }); - return Post.callbacks.push({ - name: 'Quote Threading', - cb: this.node - }); - }, - parent: {}, - children: {}, - inserted: {}, - setEnabled: function() { - var other, ref; - other = (ref = ReplyPruning.inputs) != null ? ref.enabled : void 0; - if (this.checked && (other != null ? other.checked : void 0)) { - other.checked = false; - $.event('change', null, other); - } - return $.cb.checked.call(this); - }, - setThread: function() { - QuoteThreading.thread = this; - return $.asap((function() { - return !Conf['Thread Updater'] || $('.navLinksBot > .updatelink'); - }), function() { - var navLinksBot; - if ((navLinksBot = $('.navLinksBot'))) { - return $.add(navLinksBot, [$.tn(' '), QuoteThreading.threadNewLink]); - } - }); - }, - node: function() { - var ancestor, k, lastParent, len1, parent, parents, quote, ref; - if (this.isFetchedQuote || this.isClone || !this.isReply) { - return; - } - parents = new Set(); - lastParent = null; - ref = this.quotes; - for (k = 0, len1 = ref.length; k < len1; k++) { - quote = ref[k]; - 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, k, len1, posts; - posts = [post]; - if (children = QuoteThreading.children[post.fullID]) { - for (k = 0, len1 = children.length; k < len1; k++) { - child = children[k]; - posts = posts.concat(QuoteThreading.descendants(child)); - } - } - return posts; - }, - insert: function(post) { - var base1, child, children, descendants, i, k, len1, name1, next, nodes, order, parent, prev, prev2, q, threadContainer, u, x; - if (!(Conf['Thread Quotes'] && (parent = QuoteThreading.parent[post.fullID]) && !QuoteThreading.inserted[post.fullID])) { - return false; - } - descendants = QuoteThreading.descendants(post); - if (!Unread.posts.has(parent.ID)) { - if ((function() { - var k, len1, x; - for (k = 0, len1 = descendants.length; k < len1; k++) { - x = descendants[k]; - if (Unread.posts.has(x.ID)) { - return true; - } - } - })()) { - QuoteThreading.threadNewLink.hidden = false; - return false; - } - } - order = Unread.order; - children = ((base1 = QuoteThreading.children)[name1 = parent.fullID] || (base1[name1] = [])); - 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 (k = children.length - 1; k >= 0; k += -1) { - child = children[k]; - if (child.ID >= post.ID) { - i--; - } - } - if (i !== children.length) { - next = children[i]; - for (q = 0, len1 = descendants.length; q < len1; q++) { - x = descendants[q]; - 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 (u = descendants.length - 1; u >= 0; u += -1) { - x = descendants[u]; - 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; - if (!QuoteThreading.ready) { - return; - } - thread = QuoteThreading.thread; - posts = thread.posts; - QuoteThreading.threadNewLink.hidden = true; - if (Conf['Thread Quotes']) { - 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 (!Conf['Remember Your Posts']) { - return; - } - this.db = new DataBoard('yourPosts'); - $.sync('Remember Your Posts', function(enabled) { - return Conf['Remember Your Posts'] = enabled; - }); - $.on(d, 'QRPostSuccessful', function(e) { - var boardID, postID, ref, threadID; - $.forceSync('Remember Your Posts'); - if (Conf['Remember Your Posts']) { - ref = e.detail, boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; - return QuoteYou.db.set({ - boardID: boardID, - threadID: threadID, - postID: postID, - val: true - }); - } - }); - if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { - 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 k, len1, quotelink, ref; - if (this.isClone) { - return; - } - if (QuoteYou.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 (k = 0, len1 = ref.length; k < len1; k++) { - quotelink = ref[k]; - if (!(QuoteYou.db.get(Get.postDataFromLink(quotelink)))) { - continue; - } - if (Conf['Mark Quotes of You']) { - $.add(quotelink, $.tn(QuoteYou.text)); - } - $.addClass(quotelink, 'you'); - $.addClass(this.nodes.root, 'quotesYou'); - } - }, - cb: { - seek: function(type) { - var highlight, post, posts, result, str; - if (highlight = $('.highlight')) { - $.rmClass(highlight, 'highlight'); - } - if (!(QuoteYou.lastRead && doc.contains(QuoteYou.lastRead) && $.hasClass(QuoteYou.lastRead, 'quotesYou'))) { - 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(root) { - var post; - post = $('.post', root); - if (!post.getBoundingClientRect().height) { - return false; - } else { - QuoteYou.lastRead = root; - window.location = "#" + post.id; - Header.scrollTo(post); - $.addClass(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, k, len1, ref; - if (this.isClone) { - return; - } - ref = $$('.deadlink', this.nodes.comment); - for (k = 0, len1 = ref.length; k < len1; k++) { - deadlink = ref[k]; - 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', - 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', - 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'], - validExtension: /\.(jpe?g|png|gif|pdf|swf|webm)$/i, - typeFromExtension: { - 'jpg': 'image/jpeg', - 'jpeg': 'image/jpeg', - 'png': 'image/png', - 'gif': 'image/gif', - 'pdf': 'application/pdf', - 'swf': 'application/vnd.adobe.flash.movie', - 'webm': 'video/webm' - }, - extensionFromType: { - 'image/jpeg': 'jpg', - 'image/png': 'png', - 'image/gif': 'gif', - 'application/pdf': 'pdf', - 'application/vnd.adobe.flash.movie': 'swf', - 'application/x-shockwave-flash': 'swf', - 'video/webm': 'webm' - }, - init: function() { - var sc, version; - if (!Conf['Quick Reply']) { - return; - } - this.posts = []; - if (g.VIEW === 'archive') { - return; - } - version = Conf['Use Recaptcha v1'] && Main.jsEnabled ? 'v1' : 'v2'; - this.captcha = Captcha[version]; - $.on(d, '4chanXInitFinished', this.initReady); - 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(); - } - }); - return Header.addShortcut(sc); - } - }, - initReady: function() { - var link, linkBot, navLinksBot, origToggle; - $.off(d, '4chanXInitFinished', this.initReady); - QR.postingIsEnabled = !!$.id('postForm'); - if (!QR.postingIsEnabled) { - return; - } - link = $.el('h1', { - className: "qr-link-container" - }); - $.extend(link, { - innerHTML: "" + (g.VIEW === "thread" ? "Reply to Thread" : "Start a Thread") + "" - }); - 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: "Reply to Thread" - }); - $.on(linkBot.firstElementChild, 'click', function() { - QR.open(); - return QR.nodes.com.focus(); - }); - if ((navLinksBot = $('.navLinksBot'))) { - $.prepend(navLinksBot, linkBot); - } - } - origToggle = $.id('togglePostFormLink'); - $.before(origToggle, link); - origToggle.firstElementChild.textContent = 'Original Form'; - $.on(d, 'QRGetFile', QR.getFile); - $.on(d, 'QRSetFile', QR.setFile); - $.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 k, len1, post, 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 (k = 0, len1 = ref.length; k < len1; k++) { - post = ref[k]; - post["delete"](); - } - QR.cooldown.auto = false; - QR.status(); - return QR.captcha.destroy(); - }, - focus: function() { - return $.queueTask(function() { - if (!QR.inBubble()) { - QR.hasFocus = d.activeElement && QR.nodes.el.contains(d.activeElement); - return QR.nodes.el.classList.toggle('focus', QR.hasFocus); - } - }); - }, - inBubble: function() { - var bubbles, ref; - bubbles = $$('iframe[src^="https://www.google.com/recaptcha/api2/frame"]'); - return (ref = d.activeElement, indexOf.call(bubbles, ref) >= 0) || bubbles.some(function(el) { - return getComputedStyle(el).visibility !== 'hidden' && el.getBoundingClientRect().bottom > 0; - }); - }, - 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(); - } - }, - toggleSJIS: function(e) { - e.preventDefault(); - Conf['sjisPreview'] = !Conf['sjisPreview']; - $.set('sjisPreview', Conf['sjisPreview']); - return QR.nodes.el.classList.toggle('sjis-preview', Conf['sjisPreview']); - }, - texPreviewShow: function() { - if ($.hasClass(QR.nodes.el, 'tex-preview')) { - return QR.texPreviewHide(); - } - $.addClass(QR.nodes.el, 'tex-preview'); - QR.nodes.texPreview.textContent = QR.nodes.com.value; - return $.event('mathjax', null, QR.nodes.texPreview); - }, - texPreviewHide: function() { - return $.rmClass(QR.nodes.el, 'tex-preview'); - }, - setCustomCooldown: function(enabled) { - Conf['customCooldownEnabled'] = enabled; - QR.cooldown.customCooldown = enabled; - return QR.nodes.customCooldown.classList.toggle('disabled', !enabled); - }, - toggleCustomCooldown: function() { - var enabled; - enabled = $.hasClass(this, 'disabled'); - QR.setCustomCooldown(enabled); - return $.set('customCooldownEnabled', enabled); - }, - error: function(err, focusOverride) { - var el, notice, notif; - QR.open(); - if (typeof err === 'string') { - el = $.tn(err); - } else { - el = err; - el.removeAttribute('style'); - } - notice = new Notice('warning', el); - QR.notifications.push(notice); - if (!Header.areNotificationsEnabled) { - if (d.hidden && !QR.cooldown.auto) { - return alert(el.textContent); - } - } else if (d.hidden || !(focusOverride || d.hasFocus())) { - try { - notif = new Notification(el.textContent, { - body: el.textContent, - icon: Favicon.logo - }); - notif.onclick = function() { - return $.global(function() { - return window.focus(); - }); - }; - if ($.engine !== 'gecko') { - notif.onclose = function() { - return notice.close(); - }; - return notif.onshow = function() { - return setTimeout(function() { - notif.onclose = null; - return notif.close(); - }, 7 * $.SECOND); - }; - } - } catch (_error) {} - } - }, - notifications: [], - cleanNotifications: function() { - var k, len1, notification, ref; - ref = QR.notifications; - for (k = 0, len1 = ref.length; k < len1; k++) { - notification = ref[k]; - 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; - }, - openPost: function() { - var index; - 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'); - return QR.cooldown.auto = true; - } - }, - quote: function(e) { - var aa, ancestor, caretPos, com, frag, insideCode, k, len1, len2, len3, len4, len5, len6, node, post, q, range, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, sel, text, thread, u, v, z; - 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 (k = 0, len1 = ref.length; k < len1; k++) { - node = ref[k]; - $.replace(node, $.tn('\n')); - } - ref1 = $$('br', frag); - for (q = 0, len2 = ref1.length; q < len2; q++) { - node = ref1[q]; - if (node !== frag.lastChild) { - $.replace(node, $.tn('\n>')); - } - } - ref2 = $$('s, .removed-spoiler', frag); - for (u = 0, len3 = ref2.length; u < len3; u++) { - node = ref2[u]; - $.replace(node, [$.tn('[spoiler]')].concat(slice.call(node.childNodes), [$.tn('[/spoiler]')])); - } - ref3 = $$('.prettyprint', frag); - for (v = 0, len4 = ref3.length; v < len4; v++) { - node = ref3[v]; - $.replace(node, [$.tn('[code]')].concat(slice.call(node.childNodes), [$.tn('[/code]')])); - } - ref4 = $$('.linkify[data-original]', frag); - for (z = 0, len5 = ref4.length; z < len5; z++) { - node = ref4[z]; - $.replace(node, $.tn(node.dataset.original)); - } - ref5 = $$('.embedder', frag); - for (aa = 0, len6 = ref5.length; aa < len6; aa++) { - node = ref5[aa]; - if (((ref6 = node.previousSibling) != null ? ref6.nodeValue : void 0) === ' ') { - $.rm(node.previousSibling); - } - $.rm(node); - } - text += ">" + (frag.textContent.trim()) + "\n"; - } - QR.openPost(); - 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.value.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '_').length; - counter.textContent = count; - counter.hidden = count < QR.max_comment / 2; - return (count > QR.max_comment ? $.addClass : $.rmClass)(counter, 'warning'); - }, - getFile: function() { - var ref; - return $.event('QRFile', (ref = QR.selected) != null ? ref.file : void 0); - }, - setFile: function(e) { - var file, name, ref, source; - ref = e.detail, file = ref.file, name = ref.name, source = ref.source; - if (name != null) { - file.name = name; - } - if (source != null) { - file.source = source; - } - QR.open(); - return QR.handleFiles([file]); - }, - 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, k, len1, ref; - if (!e.clipboardData.items) { - return; - } - files = []; - ref = e.clipboardData.items; - for (k = 0, len1 = ref.length; k < len1; k++) { - item = ref[k]; - 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'); - }, - pasteFF: function() { - var arr, blob, bstr, i, images, img, k, len1, m, pasteArea, q, ref, src; - pasteArea = QR.nodes.pasteArea; - if (!pasteArea.childNodes.length) { - return; - } - images = $$('img', pasteArea); - $.rmAll(pasteArea); - for (k = 0, len1 = images.length; k < len1; k++) { - img = images[k]; - src = img.src; - if (m = src.match(/data:(image\/(\w+));base64,(.+)/)) { - bstr = atob(m[3]); - arr = new Uint8Array(bstr.length); - for (i = q = 0, ref = bstr.length; 0 <= ref ? q < ref : q > ref; i = 0 <= ref ? ++q : --q) { - arr[i] = bstr.charCodeAt(i); - } - blob = new Blob([arr], { - type: m[1] - }); - blob.name = "file." + m[2]; - QR.handleFiles([blob]); - } else if (/^https?:\/\//.test(src)) { - QR.handleUrl(src); - } - } - }, - handleUrl: function(urlDefault) { - var url; - url = prompt('Enter a URL:', urlDefault); - if (url === null) { - return; - } - QR.nodes.fileButton.focus(); - return CrossOrigin.file(url, function(blob) { - if (blob && !/^text\//.test(blob.type)) { - return QR.handleFiles([blob]); - } else { - return QR.error("Can't load file."); - } - }); - }, - handleFiles: function(files) { - var file, k, len1; - if (this !== QR) { - files = slice.call(this.files); - this.value = null; - } - if (!files.length) { - return; - } - QR.cleanNotifications(); - for (k = 0, len1 = files.length; k < len1; k++) { - file = files[k]; - QR.handleFile(file, files.length); - } - if (files.length !== 1) { - $.addClass(QR.nodes.el, 'dump'); - } - if (d.activeElement === QR.nodes.fileButton && $.hasClass(QR.nodes.fileSubmit, 'has-file')) { - return QR.nodes.filename.focus(); - } - }, - handleFile: function(file, nfiles) { - var isText, post; - isText = /^text\//.test(file.type); - if (nfiles === 1) { - post = QR.selected; - } else { - post = QR.posts[QR.posts.length - 1]; - if ((isText ? post.com || post.pasting : post.file)) { - post = new QR.post(); - } - } - return post[isText ? 'pasteText' : 'setFile'](file); - }, - openFileInput: function() { - if (QR.nodes.fileButton.disabled) { - return; - } - QR.nodes.fileInput.click(); - return QR.nodes.fileButton.focus(); - }, - generatePostableThreadsList: function() { - var k, len1, list, options, ref, thread, val; - if (!QR.nodes) { - return; - } - list = QR.nodes.thread; - options = [list.firstElementChild]; - ref = g.BOARD.threads.keys; - for (k = 0, len1 = ref.length; k < len1; k++) { - thread = ref[k]; - options.push($.el('option', { - value: thread, - textContent: "Thread " + 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, ref, rules, save, scriptData, setNode; - QR.nodes = nodes = { - el: dialog = UI.dialog('qr', 'top: 50px; right: 0px;', { - innerHTML: "
          ×
          No selected file
          " - }) - }; - setNode = function(name, query) { - return nodes[name] = $(query, dialog); - }; - setNode('move', '.move'); - setNode('autohide', '#autohide'); - setNode('close', '.close'); - setNode('thread', 'select'); - setNode('form', 'form'); - setNode('sjisToggle', '#sjis-toggle'); - setNode('texButton', '#tex-preview-button'); - setNode('name', '[data-name=name]'); - setNode('email', '[data-name=email]'); - setNode('sub', '[data-name=sub]'); - setNode('com', '[data-name=com]'); - setNode('charCount', '#char-count'); - setNode('texPreview', '#tex-preview'); - setNode('dumpList', '#dump-list'); - setNode('addPost', '#add-post'); - setNode('oekaki', '.oekaki'); - setNode('drawButton', '#qr-draw-button'); - setNode('fileSubmit', '#file-n-submit'); - setNode('fileButton', '#qr-file-button'); - setNode('noFile', '#qr-no-file'); - setNode('filename', '#qr-filename'); - setNode('spoiler', '#qr-file-spoiler'); - setNode('oekakiButton', '#qr-oekaki-button'); - setNode('fileRM', '#qr-filerm'); - setNode('urlButton', '#url-button'); - setNode('pasteArea', '#paste-area'); - setNode('customCooldown', '#custom-cooldown-button'); - setNode('dumpButton', '#dump-button'); - setNode('status', '[type=submit]'); - setNode('flashTag', '[name=filetag]'); - 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; - scriptData = Get.scriptData(); - QR.max_size = (m = scriptData.match(/\bmaxFilesize *= *(\d+)\b/)) ? +m[1] : 4194304; - QR.max_size_video = (m = scriptData.match(/\bmaxWebmFilesize *= *(\d+)\b/)) ? +m[1] : QR.max_size; - QR.max_comment = (m = scriptData.match(/\bcomlen *= *(\d+)\b/)) ? +m[1] : 2000; - 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'); - } - if (g.BOARD.ID === 'jp' && Conf['sjisPreview']) { - $.addClass(QR.nodes.el, 'sjis-preview'); - } - if (parseInt(Conf['customCooldown'], 10) > 0) { - $.addClass(QR.nodes.fileSubmit, 'custom-cooldown'); - $.get('customCooldownEnabled', Conf['customCooldownEnabled'], function(arg) { - var customCooldownEnabled; - customCooldownEnabled = arg.customCooldownEnabled; - QR.setCustomCooldown(customCooldownEnabled); - return $.sync('customCooldownEnabled', QR.setCustomCooldown); - }); - } - $.on(nodes.autohide, 'change', QR.toggleHide); - $.on(nodes.close, 'click', QR.close); - $.on(nodes.form, 'submit', QR.submit); - $.on(nodes.sjisToggle, 'click', QR.toggleSJIS); - $.on(nodes.texButton, 'mousedown', QR.texPreviewShow); - $.on(nodes.texButton, 'mouseup', QR.texPreviewHide); - $.on(nodes.addPost, 'click', function() { - return new QR.post(true); - }); - $.on(nodes.drawButton, 'click', QR.oekaki.draw); - $.on(nodes.fileButton, 'click', QR.openFileInput); - $.on(nodes.noFile, 'click', QR.openFileInput); - $.on(nodes.filename, 'focus', function() { - return $.addClass(this.parentNode, 'focus'); - }); - $.on(nodes.filename, 'blur', function() { - return $.rmClass(this.parentNode, 'focus'); - }); - $.on(nodes.spoiler, 'change', function() { - return QR.selected.nodes.spoiler.click(); - }); - $.on(nodes.oekakiButton, 'click', QR.oekaki.button); - $.on(nodes.fileRM, 'click', function() { - return QR.selected.rmFile(); - }); - $.on(nodes.urlButton, 'click', function() { - return QR.handleUrl(''); - }); - $.on(nodes.customCooldown, 'click', QR.toggleCustomCooldown); - $.on(nodes.dumpButton, 'click', function() { - return nodes.el.classList.toggle('dump'); - }); - $.on(nodes.fileInput, 'change', QR.handleFiles); - window.addEventListener('focus', QR.focus, true); - window.addEventListener('blur', QR.focus, true); - $.on(d, 'click', QR.focus); - if ($.engine === 'gecko') { - nodes.pasteArea.hidden = false; - new MutationObserver(QR.pasteFF).observe(nodes.pasteArea, { - childList: true - }); - } - 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 ($.engine === 'gecko' && 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.setup(); - QR.captcha.init(); - $.add(d.body, dialog); - QR.captcha.setup(); - QR.oekaki.setup(); - return $.event('QRDialogCreation', null, dialog); - }, - submit: function(e) { - var captcha, cb, err, extra, filetag, formData, options, post, ref, 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(); - threadID = post.thread; - thread = g.BOARD.threads[threadID]; - if (g.BOARD.ID === 'f' && threadID === 'new') { - filetag = QR.nodes.flashTag.value; - } - if (threadID === 'new') { - threadID = null; - if (g.BOARD.ID === 'vg' && !post.sub) { - err = 'New threads require a subject.'; - } else if (!($.hasClass(d.body, 'text_only') || 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 comment or file.'; - } else if (post.file && thread.fileLimit) { - err = 'Max limit of image replies has been reached.'; - } - if (g.BOARD.ID === 'r9k' && !((ref = post.com) != null ? ref.match(/[a-z-]/i) : void 0)) { - err || (err = 'Original comment required.'); - } - if (QR.captcha.isEnabled && !err) { - captcha = QR.captcha.getOne(); - if (!captcha) { - err = 'No valid captcha.'; - QR.captcha.setup(!QR.cooldown.auto || d.activeElement === QR.nodes.status); - } - } - 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. [Banned?] [More info]" - })); - } - }; - extra = { - form: $.formData(formData), - upCallbacks: { - onload: function() { - QR.req.isUploadFinished = true; - 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) { - if (response.challenge != null) { - extra.form.append('recaptcha_challenge_field', response.challenge); - extra.form.append('recaptcha_response_field', response.response); - } else { - extra.form.append('g-recaptcha-response', 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, err, h1, isReply, lastPostToThread, m, open, post, postID, postsCount, ref, ref1, ref2, req, resDoc, seconds, threadID; - 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 + "! ;_;
          Click here to see the reason." - } : { - innerHTML: "You were issued a warning on " + $(".board", resDoc).innerHTML + " as " + $(".nameBlock", resDoc).innerHTML + ".
          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 = $.el('span', { - innerHTML: "You mistyped the CAPTCHA, or the CAPTCHA malfunctioned [complain here]." - }); - } else if (/expired/i.test(err.textContent)) { - err = 'This CAPTCHA is no longer valid because it has expired.'; - } - QR.cooldown.auto = QR.captcha.isEnabled || err === 'Connection error with sys.4chan.org.'; - QR.cooldown.addDelay(post, 2); - } else if (err.textContent && (m = err.textContent.match(/(?:(\d+)\s+minutes?\s+)?(\d+)\s+second/i)) && !/duplicate|hour/i.test(err.textContent)) { - QR.cooldown.auto = !/have\s+been\s+muted/i.test(err.textContent); - seconds = 60 * (+(m[1] || 0)) + (+m[2]); - if (/muted/i.test(err.textContent)) { - QR.cooldown.addMute(seconds); - } else { - QR.cooldown.addDelay(post, seconds); - } - } else { - QR.cooldown.auto = false; - } - QR.captcha.setup(QR.cooldown.auto && ((ref1 = d.activeElement) === QR.nodes.status || ref1 === d.body)); - if (QR.captcha.isEnabled && !QR.captcha.captchas.length) { - 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)); - } - ref2 = h1.nextSibling.textContent.match(/thread:(\d+),no:(\d+)/), _ = ref2[0], threadID = ref2[1], postID = ref2[2]; - postID = +postID; - threadID = +threadID || postID; - isReply = threadID !== 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; - lastPostToThread = !((function() { - var k, len1, p, ref3; - ref3 = QR.posts.slice(1); - for (k = 0, len1 = ref3.length; k < len1; k++) { - p = ref3[k]; - if (p.thread === post.thread) { - return true; - } - } - })()); - if (!(Conf['Persistent QR'] || postsCount)) { - QR.close(); - } else { - post.rm(); - QR.captcha.setup(d.activeElement === QR.nodes.status); - } - QR.cooldown.add(threadID, postID); - URL = threadID === postID ? window.location.origin + "/" + g.BOARD + "/thread/" + threadID : g.VIEW === 'index' && lastPostToThread && Conf['Open Post in New Tab'] ? window.location.origin + "/" + g.BOARD + "/thread/" + threadID + "#p" + postID : void 0; - if (URL) { - open = Conf['Open Post in New Tab'] || postsCount ? function() { - return $.open(URL); - } : function() { - return window.location = URL; - }; - if (threadID === postID) { - QR.waitForThread(URL, open); - } else { - open(); - } - } - return QR.status(); - }, - waitForThread: function(url, cb) { - var attempts, check; - attempts = 0; - check = function() { - return $.ajax(url, { - onloadend: function() { - attempts++; - if (attempts >= 6 || this.status === 200) { - return cb(); - } else { - return setTimeout(check, attempts * $.SECOND); - } - } - }, { - type: 'HEAD' - }); - }; - return check(); - }, - 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.fixes = { - imageKeys: '789456123uiojklm'.split('').concat(['Comma', 'Period']), - imageKeys16: '7890uiopjkl'.split('').concat(['Semicolon', 'm', 'Comma', 'Period', 'Slash']), - css: '.rc-imageselect-target > div:focus, .rc-image-tile-target:focus {\n outline: 2px solid #4a90e2;\n}\n.rc-imageselect-target td:focus {\n box-shadow: inset 0 0 0 2px #4a90e2;\n outline: none;\n}\n.rc-button-default:focus {\n box-shadow: inset 0 0 0 2px #0063d6;\n}', - cssNoscript: '.fbc-payload-imageselect {\n position: relative;\n}\n.fbc-payload-imageselect > label {\n position: absolute;\n display: block;\n height: 93.3px;\n width: 93.3px;\n}\nlabel[data-row="0"] {top: 0px;}\nlabel[data-row="1"] {top: 93.3px;}\nlabel[data-row="2"] {top: 186.6px;}\nlabel[data-col="0"] {left: 0px;}\nlabel[data-col="1"] {left: 93.3px;}\nlabel[data-col="2"] {left: 186.6px;}\n.fbc-payload-imageselect > input:focus + label {\n outline: 2px solid #4a90e2;\n}\n.fbc-button-verify input:focus {\n box-shadow: inset 0 0 0 2px #0063d6;\n}\nbody.focus .fbc {\n box-shadow: inset 0 0 0 2px #4a90e2;\n}', - init: function() { - switch (location.pathname.split('/')[3]) { - case 'anchor': - return this.initMain(); - case 'frame': - return this.initPopup(); - case 'fallback': - return this.initNoscript(); - } - }, - initMain: function() { - var a, k, len1, ref; - $.onExists(d.body, '#recaptcha-anchor', function(checkbox) { - var focus; - focus = function() { - var ref; - if (d.hasFocus() && ((ref = d.activeElement) === d.documentElement || ref === d.body)) { - return checkbox.focus(); - } - }; - focus(); - return $.on(window, 'focus', function() { - return $.queueTask(focus); - }); - }); - ref = $$('.rc-anchor-pt a'); - for (k = 0, len1 = ref.length; k < len1; k++) { - a = ref[k]; - a.tabIndex = -1; - } - }, - initPopup: function() { - $.addStyle(this.css); - this.fixImages(); - new MutationObserver((function(_this) { - return function() { - return _this.fixImages(); - }; - })(this)).observe(d.body, { - childList: true, - subtree: true - }); - return $.on(d, 'keydown', this.keybinds.bind(this)); - }, - initNoscript: function() { - var data, ref, token; - this.noscript = true; - data = (token = (ref = $('.fbc-verification-token > textarea')) != null ? ref.value : void 0) ? { - token: token - } : { - working: true - }; - new Connection(window.parent, '*').send(data); - d.body.classList.toggle('focus', d.hasFocus()); - $.on(window, 'focus blur', function() { - return d.body.classList.toggle('focus', d.hasFocus()); - }); - this.images = $$('.fbc-payload-imageselect > input'); - this.width = 3; - if (this.images.length !== 9) { - return; - } - $.addStyle(this.cssNoscript); - this.addLabels(); - $.on(d, 'keydown', this.keybinds.bind(this)); - return $.on($('.fbc-imageselect-challenge > form'), 'submit', this.checkForm.bind(this)); - }, - fixImages: function() { - var img, k, len1, ref; - this.images = $$('.rc-image-tile-target'); - if (!this.images.length) { - this.images = $$('.rc-imageselect-target > div, .rc-imageselect-target td'); - } - this.width = $$('.rc-imageselect-target tr:first-of-type td').length || Math.round(Math.sqrt(this.images.length)); - ref = this.images; - for (k = 0, len1 = ref.length; k < len1; k++) { - img = ref[k]; - img.tabIndex = 0; - } - if (this.images.length === 9) { - this.addTooltips(this.images); - } else { - this.addTooltips16(this.images); - } - return this.complaintLinks(); - }, - complaintLinks: function() { - var errmsg, k, len1, link, ref; - ref = $$('.rc-imageselect-incorrect-response, .rc-imageselect-error-select-one, .rc-imageselect-error-select-more, .rc-imageselect-error-dynamic-more'); - for (k = 0, len1 = ref.length; k < len1; k++) { - errmsg = ref[k]; - if (!$('a', errmsg)) { - link = $.el('a', { - href: 'https://www.4chan-x.net/captchas.html', - target: '_blank', - textContent: '[complain]' - }); - $.add(errmsg, [$.tn(' '), link]); - } - } - }, - addLabels: function() { - var checkbox, i, imageSelect, label, labels; - imageSelect = $('.fbc-payload-imageselect'); - labels = (function() { - var k, len1, ref, results; - ref = this.images; - results = []; - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - checkbox = ref[i]; - checkbox.id = "checkbox-" + i; - label = $.el('label', { - htmlFor: checkbox.id - }); - label.dataset.row = Math.floor(i / 3); - label.dataset.col = i % 3; - $.after(checkbox, label); - results.push(label); - } - return results; - }).call(this); - return this.addTooltips(labels); - }, - addTooltips: function(nodes) { - var i, k, len1, node; - for (i = k = 0, len1 = nodes.length; k < len1; i = ++k) { - node = nodes[i]; - node.title = this.imageKeys[i] + " or " + (this.imageKeys[i + 9][0].toUpperCase()) + this.imageKeys[i + 9].slice(1); - } - }, - addTooltips16: function(nodes) { - var i, k, key, len1, node, ref; - ref = this.imageKeys16; - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - key = ref[i]; - if (i % 4 < this.width && (node = nodes[nodes.length - (4 - Math.floor(i / 4)) * this.width + (i % 4)])) { - node.title = "" + (key[0].toUpperCase()) + key.slice(1); - } - } - }, - checkForm: function(e) { - var checkbox, k, len1, n, ref; - n = 0; - ref = this.images; - for (k = 0, len1 = ref.length; k < len1; k++) { - checkbox = ref[k]; - if (checkbox.checked) { - n++; - } - } - if (n === 0) { - return e.preventDefault(); - } - }, - keybinds: function(e) { - var dx, i, img, key, last, n, reload, verify, w, x; - if (!(this.images && doc.contains(this.images[0]))) { - return; - } - n = this.images.length; - w = this.width; - last = n + w - 1; - reload = $('#recaptcha-reload-button, .fbc-button-reload'); - verify = $('#recaptcha-verify-button, .fbc-button-verify > input'); - x = this.images.indexOf(d.activeElement); - if (x < 0) { - x = d.activeElement === verify ? last : n; - } - key = Keybinds.keyCode(e); - if (!this.noscript && key === 'Space' && x < n) { - this.images[x].click(); - } else if (n === 9 && (i = this.imageKeys.indexOf(key)) >= 0) { - this.images[i % 9].click(); - verify.focus(); - } else if (n !== 9 && (i = this.imageKeys16.indexOf(key)) >= 0 && i % 4 < w && (img = this.images[n - (4 - Math.floor(i / 4)) * w + (i % 4)])) { - img.click(); - verify.focus(); - } else if (dx = { - 'Up': n, - 'Down': w, - 'Left': last, - 'Right': 1 - }[key]) { - x = (x + dx) % (n + w); - if ((n < x && x < last)) { - x = dx === last ? n : last; - } - (this.images[x] || (x === n ? reload : void 0) || (x === last ? verify : void 0)).focus(); - } else { - return; - } - e.preventDefault(); - return e.stopPropagation(); - } - }; - - Captcha.replace = { - init: function() { - if (!(d.cookie.indexOf('pass_enabled=1') < 0)) { - return; - } - if (location.hostname === 'sys.4chan.org' && /[?&]altc\b/.test(location.search) && Main.jsEnabled) { - $.onExists(doc, 'script[src="//www.google.com/recaptcha/api/js/recaptcha_ajax.js"]', function() { - $.global(function() { - return window.el.onload = null; - }); - return Captcha.v1.create(); - }); - return; - } - if (((Conf['Use Recaptcha v1'] && location.hostname === 'boards.4chan.org') || (Conf['Use Recaptcha v1 in Reports'] && location.hostname === 'sys.4chan.org')) && Main.jsEnabled) { - $.ready(Captcha.replace.v1); - return; - } - if (Conf['Force Noscript Captcha'] && Main.jsEnabled) { - $.ready(Captcha.replace.noscript); - return; - } - if (Conf['captchaLanguage'].trim() || Conf['Captcha Fixes']) { - if (location.hostname === 'boards.4chan.org') { - return $.onExists(doc, '#captchaFormPart', function(node) { - return $.onExists(node, 'iframe', Captcha.replace.iframe); - }); - } else { - return $.onExists(doc, 'iframe', Captcha.replace.iframe); - } - } - }, - noscript: function() { - var insert, noscript, original, span, toggle; - if (!((original = $('#g-recaptcha, #captchaContainerAlt')) && (noscript = $('noscript')))) { - return; - } - span = $.el('span', { - id: 'captcha-forced-noscript' - }); - $.replace(noscript, span); - $.rm(original); - insert = function() { - span.innerHTML = noscript.textContent; - return Captcha.replace.iframe($('iframe', span)); - }; - if ((toggle = $('#togglePostFormLink a, #form-link'))) { - return $.on(toggle, 'click', insert); - } else { - return insert(); - } - }, - v1: function() { - var form, link; - if (!$.id('g-recaptcha')) { - return; - } - Captcha.v1.replace(); - if ((link = $.id('form-link'))) { - return $.on(link, 'click', function() { - return Captcha.v1.create(); - }); - } else if (location.hostname === 'boards.4chan.org') { - form = $.id('postForm'); - return form.addEventListener('focus', (function() { - return Captcha.v1.create(); - }), true); - } else { - return Captcha.v1.create(); - } - }, - iframe: function(iframe) { - var lang, src; - if ((lang = Conf['captchaLanguage'].trim())) { - src = /[?&]hl=/.test(iframe.src) ? iframe.src.replace(/([?&]hl=)[^&]*/, '$1' + encodeURIComponent(lang)) : iframe.src + ("&hl=" + (encodeURIComponent(lang))); - if (iframe.src !== src) { - iframe.src = src; - } - } - return Captcha.replace.autocopy(iframe); - }, - autocopy: function(iframe) { - if (!(Conf['Captcha Fixes'] && /^https:\/\/www\.google\.com\/recaptcha\/api\/fallback\?/.test(iframe.src))) { - return; - } - return new Connection(iframe, 'https://www.google.com', { - working: function() { - var ref, ref1; - if ((ref = $.id('qr')) != null ? ref.contains(iframe) : void 0) { - return (ref1 = $('#qr .captcha-container textarea')) != null ? ref1.parentNode.hidden = true : void 0; - } - }, - token: function(token) { - var node, textarea; - node = iframe; - while ((node = node.parentNode)) { - if ((textarea = $('textarea', node))) { - break; - } - } - textarea.value = token; - return $.event('input', null, textarea); - } - }); - } - }; - - Captcha.v1 = { - blank: "data:image/svg+xml,", - init: function() { - var imgContainer, input; - if (d.cookie.indexOf('pass_enabled=1') >= 0) { - return; - } - if (!(this.isEnabled = !!$('#g-recaptcha, #captchaContainerAlt'))) { - return; - } - imgContainer = $.el('div', { - className: 'captcha-img', - title: 'Reload reCAPTCHA' - }); - $.extend(imgContainer, { - innerHTML: "" - }); - input = $.el('input', { - className: 'captcha-input field', - title: 'Verification', - autocomplete: 'off', - spellcheck: false - }); - this.nodes = { - img: imgContainer.firstChild, - input: input - }; - $.on(input, 'blur', QR.focusout); - $.on(input, 'focus', QR.focusin); - $.on(input, 'keydown', QR.captcha.keydown.bind(QR.captcha)); - $.on(this.nodes.img.parentNode, 'click', QR.captcha.reload.bind(QR.captcha)); - $.addClass(QR.nodes.el, 'has-captcha', 'captcha-v1'); - $.after(QR.nodes.com.parentNode, [imgContainer, 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.replace(); - this.beforeSetup(); - if (Conf['Auto-load captcha']) { - this.setup(); - } - new MutationObserver(this.afterSetup).observe($.id('captchaContainerAlt'), { - childList: true - }); - return this.afterSetup(); - }, - replace: function() { - var container, old; - if (this.script) { - return; - } - if (!(this.script = $('script[src="//www.google.com/recaptcha/api/js/recaptcha_ajax.js"]', d.head))) { - this.script = $.el('script', { - src: '//www.google.com/recaptcha/api/js/recaptcha_ajax.js' - }); - $.add(d.head, this.script); - } - if (old = $.id('g-recaptcha')) { - container = $.el('div', { - id: 'captchaContainerAlt' - }); - return $.replace(old, container); - } - }, - create: function() { - var cont, lang; - cont = $.id('captchaContainerAlt'); - if (this.occupied) { - return; - } - this.occupied = true; - if ((lang = Conf['captchaLanguage'].trim())) { - cont.dataset.lang = lang; - } - $.onExists(cont, '#recaptcha_image', function(image) { - return $.on(image, 'click', function() { - if ($.id('recaptcha_challenge_image')) { - return $.global(function() { - return window.Recaptcha.reload(); - }); - } - }); - }); - $.onExists(cont, '#recaptcha_response_field', function(field) { - $.on(field, 'keydown', function(e) { - if (e.keyCode === 8 && !field.value) { - return $.global(function() { - return window.Recaptcha.reload(); - }); - } - }); - if (location.hostname === 'sys.4chan.org') { - return field.focus(); - } - }); - return $.global(function() { - var container, options, script; - container = document.getElementById('captchaContainerAlt'); - options = { - theme: 'clean', - tabindex: { - "boards.4chan.org": 5 - }[location.hostname], - lang: container.dataset.lang - }; - if (window.Recaptcha) { - return window.Recaptcha.create('6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc', container, options); - } else { - script = document.head.querySelector('script[src="//www.google.com/recaptcha/api/js/recaptcha_ajax.js"]'); - return script.addEventListener('load', function() { - return window.Recaptcha.create('6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc', container, options); - }, false); - } - }); - }, - cb: { - focus: function() { - return QR.captcha.setup(false, true); - } - }, - beforeSetup: function() { - var img, input, ref; - ref = this.nodes, img = ref.img, input = ref.input; - img.parentNode.hidden = true; - img.src = this.blank; - 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 && (force || this.needed()))) { - return; - } - this.create(); - if (focus) { - $.addClass(QR.nodes.el, 'focus'); - return this.nodes.input.focus(); - } - }, - afterSetup: function() { - var challenge, img, input, ref, setLifetime; - if (!(challenge = $.id('recaptcha_challenge_field_holder'))) { - return; - } - if (challenge === QR.captcha.nodes.challenge) { - return; - } - setLifetime = function(e) { - return QR.captcha.lifetime = e.detail; - }; - $.on(window, 'captcha:timeout', setLifetime); - $.global(function() { - return window.dispatchEvent(new CustomEvent('captcha:timeout', { - detail: window.RecaptchaState.timeout - })); - }); - $.off(window, 'captcha:timeout', setLifetime); - ref = QR.captcha.nodes, img = ref.img, input = ref.input; - img.parentNode.hidden = false; - input.placeholder = 'Verification'; - QR.captcha.count(); - $.off(input, 'focus click', QR.captcha.cb.focus); - QR.captcha.nodes.challenge = challenge; - new MutationObserver(QR.captcha.load.bind(QR.captcha)).observe(challenge, { - childList: true, - subtree: true, - attributes: true - }); - QR.captcha.load(); - if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) { - QR.nodes.el.style.top = null; - return QR.nodes.el.style.bottom = '0px'; - } - }, - destroy: function() { - if (!this.script) { - return; - } - $.global(function() { - return window.Recaptcha.destroy(); - }); - delete this.occupied; - if (this.nodes) { - return this.beforeSetup(); - } - }, - sync: function(captchas) { - if (captchas == null) { - captchas = []; - } - QR.captcha.captchas = captchas; - return QR.captcha.count(); - }, - getOne: function() { - var captcha, challenge, response, timeout; - this.clear(); - if (captcha = this.captchas.shift()) { - this.count(); - $.set('captchas', this.captchas); - return captcha; - } else { - challenge = this.nodes.img.alt; - timeout = this.timeout; - if (/\S/.test(response = this.nodes.input.value)) { - this.destroy(); - return { - challenge: challenge, - response: response, - timeout: timeout - }; - } else { - return null; - } - } - }, - save: function() { - var response; - if (!/\S/.test(response = this.nodes.input.value)) { - return; - } - this.nodes.input.value = ''; - this.captchas.push({ - challenge: this.nodes.img.alt, - response: response, - timeout: this.timeout - }); - this.captchas.sort(function(a, b) { - return a.timeout - b.timeout; - }); - this.count(); - this.destroy(); - this.setup(false, true); - return $.set('captchas', this.captchas); - }, - clear: function() { - var captcha, i, k, len1, now, ref; - if (!this.captchas.length) { - return; - } - $.forceSync('captchas'); - now = Date.now(); - ref = this.captchas; - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - captcha = ref[i]; - if (captcha.timeout > now) { - break; - } - } - if (!i) { - return; - } - this.captchas = this.captchas.slice(i); - this.count(); - return $.set('captchas', this.captchas); - }, - load: function() { - var challenge, challenge_image; - if ($('#captchaContainerAlt[class~="recaptcha_is_showing_audio"]')) { - this.nodes.img.src = this.blank; - return; - } - if (!this.nodes.challenge.firstChild) { - return; - } - if (!(challenge_image = $.id('recaptcha_challenge_image'))) { - return; - } - this.timeout = Date.now() + this.lifetime * $.SECOND - $.MINUTE; - challenge = this.nodes.challenge.firstChild.value; - this.nodes.img.alt = challenge; - this.nodes.img.src = challenge_image.src; - this.nodes.input.value = ''; - return this.clear(); - }, - 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.timer); - if (count) { - return this.timer = setTimeout(this.clear.bind(this), this.captchas[0].timeout - Date.now()); - } - }, - reload: function(focus) { - $.global(function() { - if (window.Recaptcha.type === 'image') { - window.Recaptcha.reload(); - } else { - window.Recaptcha.switch_type('image'); - } - return window.Recaptcha.should_focus = false; - }); - if (focus) { - return this.nodes.input.focus(); - } - }, - keydown: function(e) { - if (e.keyCode === 8 && !this.nodes.input.value) { - this.reload(); - } else if (e.keyCode === 13 && e.shiftKey) { - this.save(); - } else { - return; - } - return e.preventDefault(); - } - }; - - Captcha.v2 = { - lifetime: 2 * $.MINUTE, - init: function() { - var counter, root; - if (d.cookie.indexOf('pass_enabled=1') >= 0) { - return; - } - if (!(this.isEnabled = !!$('#g-recaptcha, #captchaContainerAlt, #captcha-forced-noscript'))) { - return; - } - if ((this.noscript = Conf['Force Noscript Captcha'] || !Main.jsEnabled)) { - $.addClass(QR.nodes.el, 'noscript-captcha'); - } - 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: "
          " - }); - counter = $('.captcha-counter > a', root); - this.nodes = { - root: root, - counter: counter - }; - this.count(); - $.addClass(QR.nodes.el, 'has-captcha', 'captcha-v2'); - $.after(QR.nodes.com.parentNode, root); - $.on(counter, 'click', this.toggle.bind(this)); - $.on(counter, 'keydown', (function(_this) { - return function(e) { - if (Keybinds.keyCode(e) !== 'Space') { - return; - } - _this.toggle(); - e.preventDefault(); - return e.stopPropagation(); - }; - })(this)); - return $.on(window, 'captcha:success', (function(_this) { - return function() { - return $.queueTask(function() { - return _this.save(false); - }); - }; - })(this)); - }, - timeouts: {}, - postsCount: 0, - noscriptURL: function() { - var lang, url; - url = 'https://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc'; - if ((lang = Conf['captchaLanguage'].trim())) { - url += "&hl=" + (encodeURIComponent(lang)); - } - return url; - }, - 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) { - if (!(this.isEnabled && (this.needed() || force))) { - return; - } - if (focus) { - $.addClass(QR.nodes.el, 'focus'); - this.nodes.counter.focus(); - } - if (this.timeouts.destroy) { - clearTimeout(this.timeouts.destroy); - delete this.timeouts.destroy; - return this.reload(); - } - if (this.nodes.container) { - $.queueTask((function(_this) { - return function() { - var iframe; - if (_this.nodes.container && d.activeElement === _this.nodes.counter && (iframe = $('iframe', _this.nodes.container))) { - iframe.focus(); - return QR.focus(); - } - }; - })(this)); - 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 - }); - if (this.noscript) { - return this.setupNoscript(); - } else { - return this.setupJS(); - } - }, - setupNoscript: function() { - var div, iframe, textarea; - iframe = $.el('iframe', { - id: 'qr-captcha-iframe', - src: this.noscriptURL() - }); - div = $.el('div'); - textarea = $.el('textarea'); - $.add(div, textarea); - return $.add(this.nodes.container, [iframe, div]); - }, - setupJS: function() { - return $.global(function() { - var cbNative, render; - render = function() { - var classList, container; - classList = document.documentElement.classList; - container = document.querySelector('#qr .captcha-container'); - return container.dataset.widgetID = window.grecaptcha.render(container, { - sitekey: '6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc', - theme: classList.contains('tomorrow') || classList.contains('dark-captcha') ? 'dark' : 'light', - callback: function(response) { - return window.dispatchEvent(new CustomEvent('captcha:success', { - detail: response - })); - } - }); - }; - if (window.grecaptcha) { - return render(); - } else { - cbNative = window.onRecaptchaLoaded; - return window.onRecaptchaLoaded = function() { - render(); - return cbNative(); - }; - } - }); - }, - afterSetup: function(mutations) { - var iframe, k, len1, len2, mutation, node, q, ref, textarea; - for (k = 0, len1 = mutations.length; k < len1; k++) { - mutation = mutations[k]; - ref = mutation.addedNodes; - for (q = 0, len2 = ref.length; q < len2; q++) { - node = ref[q]; - 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) { - if (!doc.contains(iframe)) { - return; - } - Captcha.replace.iframe(iframe); - $.addClass(QR.nodes.el, 'captcha-open'); - this.fixQRPosition(); - $.on(iframe, 'load', this.fixQRPosition); - if (d.activeElement === this.nodes.counter) { - iframe.focus(); - } - return $.global(function() { - var f; - f = document.querySelector('#qr iframe'); - return f.focus = f.blur = function() {}; - }); - }, - fixQRPosition: function() { - if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) { - QR.nodes.el.style.top = null; - return QR.nodes.el.style.bottom = '0px'; - } - }, - setupTextArea: function(textarea) { - return $.one(textarea, 'input', (function(_this) { - return function() { - return _this.save(true); - }; - })(this)); - }, - destroy: function() { - var garbage, i, ins, node, ref; - if (!this.isEnabled) { - return; - } - delete this.timeouts.destroy; - $.rmClass(QR.nodes.el, 'captcha-open'); - if (this.nodes.container) { - $.rm(this.nodes.container); - } - delete this.nodes.container; - garbage = $.X('//iframe[starts-with(@src, "https://www.google.com/recaptcha/api2/frame")]/ancestor-or-self::*[parent::body]'); - i = 0; - while (node = garbage.snapshotItem(i++)) { - if (((ref = (ins = node.nextSibling)) != null ? ref.nodeName : void 0) === 'INS') { - $.rm(ins); - } - $.rm(node); - } - }, - 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; - } else { - return null; - } - }, - save: function(pasted, token) { - var base1, focus, ref; - $.forceSync('captchas'); - this.captchas.push({ - response: token || $('textarea', this.nodes.container).value, - timeout: Date.now() + this.lifetime - }); - this.captchas.sort(function(a, b) { - return a.timeout - b.timeout; - }); - $.set('captchas', this.captchas); - this.count(); - focus = ((ref = d.activeElement) != null ? ref.nodeName : void 0) === 'IFRAME' && /https?:\/\/www\.google\.com\/recaptcha\//.test(d.activeElement.src); - if (this.needed()) { - if (focus) { - if (QR.cooldown.auto || Conf['Post on Captcha Completion']) { - this.nodes.counter.focus(); - } else { - QR.nodes.status.focus(); - } - } - this.reload(); - } else { - if (pasted) { - this.destroy(); - } else { - if ((base1 = this.timeouts).destroy == null) { - base1.destroy = setTimeout(this.destroy.bind(this), 3 * $.SECOND); - } - } - if (focus) { - QR.nodes.status.focus(); - } - } - if (Conf['Post on Captcha Completion'] && !QR.cooldown.auto) { - return QR.submit(); - } - }, - clear: function() { - var captcha, i, k, len1, now, ref; - if (!this.captchas.length) { - return; - } - $.forceSync('captchas'); - now = Date.now(); - ref = this.captchas; - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - 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(d.activeElement === QR.nodes.status); - }, - 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() { - if ($('iframe[src^="https://www.google.com/recaptcha/api/fallback?"]', this.nodes.container)) { - this.destroy(); - return this.setup(false, true); - } else { - return $.global(function() { - var container; - container = document.querySelector('#qr .captcha-container'); - return window.grecaptcha.reset(container.dataset.widgetID); - }); - } - } - }; - - PassLink = { - init: function() { - if (!Conf['Pass Link']) { - return; - } - return Main.ready(this.ready); - }, - ready: function() { - var passLink, styleSelector; - if (!(styleSelector = $.id('styleSelector'))) { - return; - } - passLink = $.el('span', { - className: 'brackets-wrap pass-link-container' - }); - $.extend(passLink, { - innerHTML: "4chan Pass" - }); - $.on(passLink.firstElementChild, 'click', function() { - return window.open('//sys.4chan.org/auth', Date.now(), 'width=500,height=280,toolbar=0'); - }); - return $.before(styleSelector.previousSibling, [passLink, $.tn('\u00A0\u00A0')]); - } - }; - - PostSuccessful = { - init: function() { - if (!Conf['Remember Your Posts']) { - return; - } - return $.ready(this.ready); - }, - ready: function() { - var _, db, postID, ref, threadID; - if (d.title !== 'Post successful!') { - return; - } - ref = $('h1').nextSibling.textContent.match(/thread:(\d+),no:(\d+)/), _ = ref[0], threadID = ref[1], postID = ref[2]; - postID = +postID; - threadID = +threadID || postID; - db = new DataBoard('yourPosts'); - return db.set({ - boardID: g.BOARD.ID, - threadID: threadID, - postID: postID, - val: true - }); - } - }; - - QR.cooldown = { - seconds: 0, - delays: { - thread: 0, - reply: 0, - image: 0, - reply_intra: 0, - image_intra: 0, - deletion: 60, - thread_global: 300 - }, - init: function() { - if (!Conf['Quick Reply']) { - return; - } - this.data = Conf['cooldowns']; - return $.sync('cooldowns', this.sync); - }, - setup: function() { - var delay, m, ref, type; - if (m = Get.scriptData().match(/\bcooldowns *= *({[^}]+})/)) { - $.extend(QR.cooldown.delays, JSON.parse(m[1])); - } - QR.cooldown.maxDelay = 0; - ref = QR.cooldown.delays; - for (type in ref) { - delay = ref[type]; - if (type !== 'thread' && type !== 'thread_global') { - QR.cooldown.maxDelay = Math.max(QR.cooldown.maxDelay, delay); - } - } - QR.cooldown.isSetup = true; - return QR.cooldown.start(); - }, - start: function() { - var data; - data = QR.cooldown.data; - if (!(Conf['Cooldown'] && QR.cooldown.isSetup && !QR.cooldown.isCounting && Object.keys(data[g.BOARD.ID] || {}).length + Object.keys(data.global || {}).length > 0)) { - return; - } - QR.cooldown.isCounting = true; - return QR.cooldown.count(); - }, - sync: function(data) { - QR.cooldown.data = data || {}; - return QR.cooldown.start(); - }, - add: function(threadID, postID) { - var boardID, start; - if (!Conf['Cooldown']) { - return; - } - start = Date.now(); - boardID = g.BOARD.ID; - QR.cooldown.set(boardID, 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(g.BOARD.ID, Date.now(), cooldown); - return QR.cooldown.start(); - }, - addMute: function(delay) { - if (!Conf['Cooldown']) { - return; - } - QR.cooldown.set(g.BOARD.ID, Date.now(), { - type: 'mute', - delay: delay - }); - return QR.cooldown.start(); - }, - "delete": function(post) { - var base1, cooldown, cooldowns, id, name1; - if (!QR.cooldown.data) { - return; - } - $.forceSync('cooldowns'); - cooldowns = ((base1 = QR.cooldown.data)[name1 = post.board.ID] || (base1[name1] = {})); - for (id in cooldowns) { - cooldown = cooldowns[id]; - if ((cooldown.delay == null) && cooldown.threadID === post.thread.ID && cooldown.postID === post.ID) { - delete cooldowns[id]; - } - } - return QR.cooldown.save([post.board.ID]); - }, - secondsDeletion: function(post) { - var cooldown, cooldowns, seconds, start; - if (!(QR.cooldown.data && Conf['Cooldown'])) { - return 0; - } - cooldowns = QR.cooldown.data[post.board.ID] || {}; - for (start in cooldowns) { - cooldown = cooldowns[start]; - if ((cooldown.delay == null) && cooldown.threadID === post.thread.ID && cooldown.postID === post.ID) { - seconds = QR.cooldown.delays.deletion - Math.floor((Date.now() - start) / $.SECOND); - return Math.max(seconds, 0); - } - } - return 0; - }, - 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) { - var base1, cooldowns; - $.forceSync('cooldowns'); - cooldowns = ((base1 = QR.cooldown.data)[scope] || (base1[scope] = {})); - cooldowns[id] = value; - return $.set('cooldowns', QR.cooldown.data); - }, - save: function(scopes) { - var data, k, len1, scope; - data = QR.cooldown.data; - for (k = 0, len1 = scopes.length; k < len1; k++) { - scope = scopes[k]; - if (scope in data && !Object.keys(data[scope]).length) { - delete data[scope]; - } - } - return $.set('cooldowns', data); - }, - count: function() { - var base1, cooldown, cooldowns, elapsed, k, len1, maxDelay, nCooldowns, now, ref, ref1, save, scope, seconds, start, suffix, threadID, type, update; - $.forceSync('cooldowns'); - save = []; - nCooldowns = 0; - now = Date.now(); - ref = QR.cooldown.categorize(QR.posts[0]), type = ref.type, threadID = ref.threadID; - seconds = 0; - if (Conf['Cooldown']) { - ref1 = [g.BOARD.ID, 'global']; - for (k = 0, len1 = ref1.length; k < len1; k++) { - scope = ref1[k]; - cooldowns = ((base1 = QR.cooldown.data)[scope] || (base1[scope] = {})); - for (start in cooldowns) { - cooldown = cooldowns[start]; - start = +start; - elapsed = Math.floor((now - start) / $.SECOND); - if (elapsed < 0) { - delete cooldowns[start]; - save.push(scope); - continue; - } - if (cooldown.delay != null) { - if (cooldown.delay <= elapsed) { - delete cooldowns[start]; - save.push(scope); - } else if ((cooldown.type === type && cooldown.threadID === threadID) || cooldown.type === 'mute') { - 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 (QR.cooldown.customCooldown) { - maxDelay = Math.max(maxDelay, parseInt(Conf['customCooldown'], 10)); - } - if (maxDelay <= elapsed) { - delete cooldowns[start]; - save.push(scope); - 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 (QR.cooldown.customCooldown) { - seconds = Math.max(seconds, parseInt(Conf['customCooldown'], 10) - elapsed); - } - } - nCooldowns += Object.keys(cooldowns).length; - } - } - if (save.length) { - QR.cooldown.save(save); - } - if (nCooldowns) { - 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.oekaki = { - menu: { - init: function() { - var a, ref; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Menu'] && Conf['Edit Link'] && Conf['Quick Reply'])) { - return; - } - a = $.el('a', { - className: 'edit-link', - href: 'javascript:;', - textContent: 'Edit image' - }); - $.on(a, 'click', this.editFile); - return Menu.menu.addEntry({ - el: a, - order: 95, - open: function(post) { - var file; - QR.oekaki.menu.post = post; - file = post.file; - return QR.postingIsEnabled && !!file && (file.isImage || file.isVideo); - } - }); - }, - editFile: function() { - var currentTime, isVideo, post, ref; - post = QR.oekaki.menu.post; - QR.quote.call(post.nodes.post); - isVideo = post.file.isVideo; - currentTime = ((ref = post.file.fullImage) != null ? ref.currentTime : void 0) || 0; - return CrossOrigin.file(post.file.url, function(blob) { - var video; - if (!blob) { - return QR.error("Can't load file."); - } else if (isVideo) { - video = $.el('video'); - $.on(video, 'loadedmetadata', function() { - $.on(video, 'seeked', function() { - var canvas; - canvas = $.el('canvas', { - width: video.videoWidth, - height: video.videoHeight - }); - canvas.getContext('2d').drawImage(video, 0, 0); - return canvas.toBlob(function(snapshot) { - snapshot.name = post.file.name.replace(/\.\w+$/, '') + '.png'; - QR.handleFiles([snapshot]); - return QR.oekaki.edit(); - }); - }); - return video.currentTime = currentTime; - }); - return video.src = URL.createObjectURL(blob); - } else { - blob.name = post.file.name; - QR.handleFiles([blob]); - return QR.oekaki.edit(); - } - }); - } - }, - setup: function() { - return $.global(function() { - var FCX; - FCX = window.FCX; - FCX.oekakiCB = function() { - return window.Tegaki.flatten().toBlob(function(file) { - var source; - source = "oekaki-" + (Date.now()); - FCX.oekakiLatest = source; - return document.dispatchEvent(new CustomEvent('QRSetFile', { - bubbles: true, - detail: { - file: file, - name: FCX.oekakiName, - source: source - } - })); - }); - }; - if (window.Tegaki) { - return document.querySelector('#qr .oekaki').hidden = false; - } - }); - }, - load: function(cb) { - var n, onload, script, style; - if ($('script[src^="//s.4cdn.org/js/painter"]', d.head)) { - return cb(); - } else { - style = $.el('link', { - rel: 'stylesheet', - href: "//s.4cdn.org/css/painter." + (Date.now()) + ".css" - }); - script = $.el('script', { - src: "//s.4cdn.org/js/painter.min." + (Date.now()) + ".js" - }); - n = 0; - onload = function() { - if (++n === 2) { - return cb(); - } - }; - $.on(style, 'load', onload); - $.on(script, 'load', onload); - return $.add(d.head, [style, script]); - } - }, - draw: function() { - return $.global(function() { - var FCX, Tegaki; - Tegaki = window.Tegaki, FCX = window.FCX; - if (Tegaki.bg) { - Tegaki.destroy(); - } - FCX.oekakiName = 'tegaki.png'; - return Tegaki.open({ - onDone: FCX.oekakiCB, - onCancel: function() { - return Tegaki.bgColor = '#ffffff'; - }, - width: +document.querySelector('#qr [name=oekaki-width]').value, - height: +document.querySelector('#qr [name=oekaki-height]').value, - bgColor: document.querySelector('#qr [name=oekaki-bg]').checked ? document.querySelector('#qr [name=oekaki-bgcolor]').value : 'transparent' - }); - }); - }, - button: function() { - if (QR.selected.file) { - return QR.oekaki.edit(); - } else { - return QR.oekaki.toggle(); - } - }, - edit: function() { - return QR.oekaki.load(function() { - return $.global(function() { - var FCX, Tegaki, cb, error, name, source; - Tegaki = window.Tegaki, FCX = window.FCX; - name = document.getElementById('qr-filename').value.replace(/\.\w+$/, '') + '.png'; - source = document.getElementById('file-n-submit').dataset.source; - error = function(content) { - return document.dispatchEvent(new CustomEvent('CreateNotification', { - bubbles: true, - detail: { - type: 'warning', - content: content, - lifetime: 20 - } - })); - }; - cb = function(e) { - var file, isVideo; - document.removeEventListener('QRFile', cb, false); - if (!e.detail) { - return error('No file to edit.'); - } - if (!/^(image|video)\//.test(e.detail.type)) { - return error('Not an image.'); - } - isVideo = /^video\//.test(e.detail.type); - file = document.createElement(isVideo ? 'video' : 'img'); - file.addEventListener('error', function() { - return error('Could not open file.', false); - }); - file.addEventListener((isVideo ? 'loadeddata' : 'load'), function() { - if (Tegaki.bg) { - Tegaki.destroy(); - } - FCX.oekakiName = name; - Tegaki.open({ - onDone: FCX.oekakiCB, - onCancel: function() { - return Tegaki.bgColor = '#ffffff'; - }, - width: file.naturalWidth || file.videoWidth, - height: file.naturalHeight || file.videoHeight, - bgColor: 'transparent' - }); - return Tegaki.activeCtx.drawImage(file, 0, 0); - }, false); - return file.src = URL.createObjectURL(e.detail); - }; - if (Tegaki.bg && Tegaki.onDoneCb === FCX.oekakiCB && source === FCX.oekakiLatest) { - FCX.oekakiName = name; - return Tegaki.resume(); - } else { - document.addEventListener('QRFile', cb, false); - return document.dispatchEvent(new CustomEvent('QRGetFile', { - bubbles: true - })); - } - }); - }); - }, - toggle: function() { - return QR.oekaki.load(function() { - return QR.nodes.oekaki.hidden = !QR.nodes.oekaki.hidden; - }); - } - }; - - QR.persona = { - pwd: '', - always: {}, - init: function() { - QR.persona.getPassword(); - return $.get('QR.personas', Conf['QR.personas'], function(arg) { - var arr, item, k, len1, personas, ref, type, types; - personas = arg['QR.personas']; - types = { - name: [], - email: [], - sub: [] - }; - ref = personas.split('\n'); - for (k = 0, len1 = ref.length; k < len1; k++) { - item = ref[k]; - 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, ref, ref1, ref2, type, val; - 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 k, len1, list, val; - list = $("#list-" + type, QR.nodes.el); - for (k = 0, len1 = arr.length; k < len1; k++) { - val = arr[k]; - 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 - }; - return $.set('QR.persona', persona); - }); - } - }; - - QR.post = (function() { - function _Class(select) { - this.select = bind(this.select, this); - var el, event, k, label, len1, len2, prev, q, ref, ref1; - el = $.el('a', { - className: 'qr-preview', - draggable: true, - href: 'javascript:;' - }); - $.extend(el, { - innerHTML: "" - }); - this.nodes = { - el: el, - rm: el.firstChild, - spoiler: $('.qr-preview-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.spoiler, 'change', (function(_this) { - return function(e) { - _this.spoiler = e.target.checked; - if (_this === QR.selected) { - return QR.nodes.spoiler.checked = _this.spoiler; - } - }; - })(this)); - ref = $$('label', el); - for (k = 0, len1 = ref.length; k < len1; k++) { - label = ref[k]; - $.on(label, 'click', function(e) { - return e.stopPropagation(); - }); - } - $.add(QR.nodes.dumpList, el); - ref1 = ['dragStart', 'dragEnter', 'dragLeave', 'dragOver', 'dragEnd', 'drop']; - for (q = 0, len2 = ref1.length; q < len2; q++) { - event = ref1[q]; - $.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 : ''; - _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); - URL.revokeObjectURL(this.URL); - return this.dismissErrors(); - }; - - _Class.prototype.lock = function(lock) { - var k, len1, name, node, ref; - if (lock == null) { - lock = true; - } - this.isLocked = lock; - if (this !== QR.selected) { - return; - } - ref = ['thread', 'name', 'email', 'sub', 'com', 'fileButton', 'filename', 'spoiler']; - for (k = 0, len1 = ref.length; k < len1; k++) { - name = ref[k]; - if (node = QR.nodes[name]) { - node.disabled = lock; - } - } - this.nodes.rm.style.visibility = lock ? 'hidden' : ''; - 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.removeAttribute('id'); - 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 k, len1, name, node, ref; - ref = ['thread', 'name', 'email', 'sub', 'com', 'filename']; - for (k = 0, len1 = ref.length; k < len1; k++) { - name = ref[k]; - if (!(node = QR.nodes[name])) { - continue; - } - node.value = this[name] || node.dataset["default"] || ''; - } - (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.updateComment(); - 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.saveFilename(); - return this.updateFilename(); - case 'name': - return QR.persona.set(this); - } - }; - - _Class.prototype.forceSave = function() { - var k, len1, name, node, ref; - if (this !== QR.selected) { - return; - } - ref = ['thread', 'name', 'email', 'sub', 'com', 'filename', 'spoiler']; - for (k = 0, len1 = ref.length; k < len1; k++) { - name = ref[k]; - if (!(node = QR.nodes[name])) { - continue; - } - this.save(node); - } - }; - - _Class.prototype.setComment = function(com) { - this.com = com || null; - if (this === QR.selected) { - QR.nodes.com.value = this.com; - } - return this.updateComment(); - }; - - _Class.prototype.updateComment = function() { - if (this === QR.selected) { - QR.characterCount(); - } - this.nodes.span.textContent = this.com; - return $.queueTask(function() { - return QR.captcha.onPostChange(); - }); - }; - - _Class.rmErrored = function(e) { - var error, errors, k, len1, post, q, ref; - e.stopPropagation(); - ref = QR.posts; - for (k = ref.length - 1; k >= 0; k += -1) { - post = ref[k]; - if (errors = post.errors) { - for (q = 0, len1 = errors.length; q < len1; q++) { - error = errors[q]; - if (!(doc.contains(error))) { - continue; - } - post.rm(); - break; - } - } - } - }; - - _Class.prototype.error = function(className, message) { - var div, ref, rm, rmAll; - div = $.el('div', { - className: className - }); - $.extend(div, { - innerHTML: E(message) + "
          [delete] [delete all]" - }); - (this.errors || (this.errors = [])).push(div); - ref = $$('a', div), rm = ref[0], rmAll = ref[1]; - $.on(div, 'click', (function(_this) { - return function() { - if (indexOf.call(QR.posts, _this) >= 0) { - return _this.select(); - } - }; - })(this)); - $.on(rm, 'click', (function(_this) { - return function(e) { - e.stopPropagation(); - if (indexOf.call(QR.posts, _this) >= 0) { - return _this.rm(); - } - }; - })(this)); - $.on(rmAll, 'click', QR.post.rmErrored); - return QR.error(div, true); - }; - - _Class.prototype.fileError = function(message) { - return this.error('file-error', this.filename + ": " + message); - }; - - _Class.prototype.dismissErrors = function(test) { - var error, k, len1, ref; - if (test == null) { - test = function() { - return true; - }; - } - if (this.errors) { - ref = this.errors; - for (k = 0, len1 = ref.length; k < len1; k++) { - error = ref[k]; - if (doc.contains(error) && test(error)) { - error.parentNode.previousElementSibling.click(); - } - } - } - }; - - _Class.prototype.setFile = function(file1) { - var ext, ref; - this.file = file1; - if (Conf['Randomize Filename'] && g.BOARD.ID !== 'f') { - this.filename = "" + (Date.now() - Math.floor(Math.random() * 365 * $.DAY)); - if (ext = this.file.name.match(QR.validExtension)) { - this.filename += ext[0]; - } - } else { - this.filename = this.file.name; - } - this.filesize = $.bytesToString(this.file.size); - this.checkSize(); - $.addClass(this.nodes.el, 'has-file'); - $.queueTask(function() { - return QR.captcha.onPostChange(); - }); - URL.revokeObjectURL(this.URL); - this.saveFilename(); - if (this === QR.selected) { - this.showFileData(); - } else { - this.updateFilename(); - } - this.nodes.el.style.backgroundImage = null; - if (ref = this.file.type, indexOf.call(QR.mimeTypes, ref) < 0) { - return this.fileError('Unsupported file type.'); - } else if (/^(image|video)\//.test(this.file.type)) { - return this.readFile(); - } - }; - - _Class.prototype.checkSize = function() { - var max; - max = QR.max_size; - if (/^video\//.test(this.file.type)) { - max = Math.min(max, QR.max_size_video); - } - if (this.file.size > max) { - return this.fileError("File too large (file: " + this.filesize + ", max: " + ($.bytesToString(max)) + ")."); - } - }; - - _Class.prototype.readFile = function() { - var el, event, isVideo, onerror, onload; - isVideo = /^video\//.test(this.file.type); - el = $.el(isVideo ? 'video' : 'img'); - if (isVideo && !el.canPlayType(this.file.type)) { - return; - } - event = isVideo ? 'loadeddata' : 'load'; - onload = (function(_this) { - return function() { - $.off(el, event, onload); - $.off(el, 'error', onerror); - _this.checkDimensions(el); - return _this.setThumbnail(el); - }; - })(this); - onerror = (function(_this) { - return function() { - $.off(el, event, onload); - $.off(el, 'error', onerror); - _this.fileError((isVideo ? 'Video' : 'Image') + " appears corrupt"); - return URL.revokeObjectURL(el.src); - }; - })(this); - $.on(el, event, onload); - $.on(el, 'error', onerror); - return el.src = URL.createObjectURL(this.file); - }; - - _Class.prototype.checkDimensions = function(el) { - var duration, height, max_height, max_width, ref, videoHeight, videoWidth, width; - if (el.tagName === 'IMG') { - height = el.height, width = el.width; - if (height > QR.max_height || width > QR.max_width) { - this.fileError("Image too large (image: " + height + "x" + width + "px, max: " + QR.max_height + "x" + QR.max_width + "px)"); - } - if (height < QR.min_height || width < QR.min_width) { - return this.fileError("Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); - } - } else { - videoHeight = el.videoHeight, videoWidth = el.videoWidth, duration = el.duration; - max_height = Math.min(QR.max_height, QR.max_height_video); - max_width = Math.min(QR.max_width, QR.max_width_video); - if (videoHeight > max_height || videoWidth > max_width) { - this.fileError("Video too large (video: " + videoHeight + "x" + videoWidth + "px, max: " + max_height + "x" + max_width + "px)"); - } - if (videoHeight < QR.min_height || videoWidth < QR.min_width) { - this.fileError("Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); - } - if (!isFinite(duration)) { - this.fileError('Video lacks duration metadata (try remuxing)'); - } else if (duration > QR.max_duration_video) { - this.fileError("Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)"); - } - if (((ref = g.BOARD.ID) !== 'gif' && ref !== 'wsg') && $.hasAudio(el)) { - return this.fileError('Audio not allowed'); - } - } - }; - - _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.removeAttribute('title'); - QR.nodes.filename.removeAttribute('title'); - this.nodes.el.style.backgroundImage = null; - $.rmClass(this.nodes.el, 'has-file'); - this.showFileData(); - URL.revokeObjectURL(this.URL); - return this.dismissErrors(function(error) { - return $.hasClass(error, 'file-error'); - }); - }; - - _Class.prototype.saveFilename = function() { - this.file.newName = (this.filename || '').replace(/[\/\\]/g, '-'); - if (!QR.validExtension.test(this.filename)) { - return this.file.newName += "." + (QR.extensionFromType[this.file.type] || 'jpg'); - } - }; - - _Class.prototype.updateFilename = function() { - var long; - long = this.filename + " (" + this.filesize + ")"; - this.nodes.el.title = long; - if (this !== QR.selected) { - return; - } - return QR.nodes.filename.title = long; - }; - - _Class.prototype.showFileData = function() { - var ref; - if (this.file) { - this.updateFilename(); - QR.nodes.filename.value = this.filename; - $.addClass(QR.nodes.oekaki, 'has-file'); - $.addClass(QR.nodes.fileSubmit, 'has-file'); - } else { - $.rmClass(QR.nodes.oekaki, 'has-file'); - $.rmClass(QR.nodes.fileSubmit, 'has-file'); - } - if (((ref = this.file) != null ? ref.source : void 0) != null) { - QR.nodes.fileSubmit.dataset.source = this.file.source; - } else { - QR.nodes.fileSubmit.removeAttribute('data-source'); - } - return QR.nodes.spoiler.checked = this.spoiler; - }; - - _Class.prototype.pasteText = function(file) { - var reader; - this.pasting = true; - reader = new FileReader(); - reader.onload = (function(_this) { - return function(e) { - var result; - result = e.target.result; - _this.setComment((_this.com ? _this.com + "\n" + result : result)); - return delete _this.pasting; - }; - })(this); - return reader.readAsText(file); - }; - - _Class.prototype.dragStart = function(e) { - var left, ref, top; - ref = this.getBoundingClientRect(), left = ref.left, top = ref.top; - e.dataTransfer.setDragImage(this, e.clientX - left, e.clientY - top); - 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, k, lc, len1, ref, ref1, type; - if (!((Conf['Fappe Tyme'] || Conf['Werk Tyme']) && ((ref = g.VIEW) === 'index' || ref === 'thread'))) { - return; - } - this.nodes = {}; - this.enabled = { - fappe: false, - werk: Conf['werk'] - }; - ref1 = ["Fappe", "Werk"]; - for (k = 0, len1 = ref1.length; k < len1; k++) { - type = ref1[k]; - 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() { - return this.nodes.root.classList.toggle('noFile', !this.file); - }, - 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() { - var ref; - if (!((ref = this.file) != null ? ref.thumb : void 0)) { - 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, k, key, len1, len2, menuButton, nodes, post, q, ref, ref1, ref2, ref3, thumb, value; - cb = Gallery.cb; - 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: "
          " - }); - 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'); - $.on(nodes.frame, 'click', cb.blank); - if (Conf['Mouse Wheel Volume']) { - $.on(nodes.frame, 'wheel', Volume.wheel); - } - $.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 (k = 0, len1 = ref1.length; k < len1; k++) { - entry = ref1[k]; - entry.order = 0; - nodes.menu.addEntry(entry); - } - $.on(d, 'keydown', cb.keybinds); - if (Conf['Keybinds']) { - $.off(d, 'keydown', Keybinds.keydown); - } - $.on(window, 'resize', Gallery.cb.setHeight); - ref2 = $$('.post .file'); - for (q = 0, len2 = ref2.length; q < len2; q++) { - file = ref2[q]; - post = Get.postFromNode(file); - if (!((ref3 = post.file) != null ? ref3.thumb : void 0)) { - 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.thumb && (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); - }, - load: function(thumb, errorCB) { - var elType, ext, file; - ext = thumb.href.match(/\w*$/); - elType = { - 'webm': 'video', - 'pdf': 'iframe' - }[ext] || 'img'; - file = $.el(elType, { - title: thumb.title - }); - $.extend(file.dataset, thumb.dataset); - $.on(file, 'error', errorCB); - file.src = thumb.href; - return file; - }, - open: function(thumb) { - var el, file, newID, nodes, oldID, post, ref; - nodes = Gallery.nodes; - oldID = +nodes.current.dataset.id; - newID = +thumb.dataset.id; - if (el = Gallery.images[oldID]) { - $.rmClass(el, 'gal-highlight'); - } - $.addClass(thumb, 'gal-highlight'); - nodes.thumbs.scrollTop = thumb.offsetTop + thumb.offsetHeight / 2 - nodes.thumbs.clientHeight / 2; - if (((ref = Gallery.cache) != null ? ref.dataset.id : void 0) === '' + newID) { - file = Gallery.cache; - $.off(file, 'error', Gallery.cacheError); - $.on(file, 'error', Gallery.error); - } else { - file = Gallery.load(thumb, Gallery.error); - } - $.off(nodes.current, 'error', Gallery.error); - ImageCommon.pause(nodes.current); - $.replace(nodes.current, file); - nodes.current = file; - if (file.nodeName === 'VIDEO') { - file.loop = true; - Volume.setup(file); - if (Conf['Autoplay']) { - file.play(); - } - if (Conf['Show Controls']) { - ImageCommon.addControls(file); - } - } - doc.classList.toggle('gal-pdf', file.nodeName === 'IFRAME'); - Gallery.cb.setHeight(); - nodes.count.textContent = +thumb.dataset.id + 1; - nodes.name.download = nodes.name.textContent = thumb.title; - nodes.name.href = thumb.href; - nodes.frame.scrollTop = 0; - nodes.next.focus(); - if (Gallery.slideshow && (newID > oldID || (oldID === Gallery.images.length - 1 && newID === 0))) { - Gallery.setupTimer(); - } else { - Gallery.cb.stop(); - } - if (Conf['Scroll to Post'] && (post = g.posts[file.dataset.post])) { - Header.scrollTo(post.nodes.root); - } - if (isNaN(oldID) || newID === (oldID + 1) % Gallery.images.length) { - return Gallery.cache = Gallery.load(Gallery.images[(newID + 1) % Gallery.images.length], Gallery.cacheError); - } - }, - 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)); - }, - cacheError: function() { - return delete Gallery.cache; - }, - 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 (!Conf['Autoplay'] && 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); - } - $.off(window, 'resize', Gallery.cb.setHeight); - return clearTimeout(Gallery.timeoutID); - }, - setFitness: function() { - return (this.checked ? $.addClass : $.rmClass)(doc, "gal-" + (this.name.toLowerCase().replace(/\s+/g, '-'))); - }, - setHeight: $.debounce(100, function() { - var current, dim, frame, height, minHeight, ref, ref1, ref2, style, width; - ref = Gallery.nodes, current = ref.current, frame = ref.frame; - style = current.style; - if (Conf['Stretch to Fit'] && (dim = (ref1 = g.posts[current.dataset.post]) != null ? ref1.file.dimensions : void 0)) { - ref2 = dim.split('x'), width = ref2[0], height = ref2[1]; - minHeight = Math.min(doc.clientHeight - 25, height / width * frame.clientWidth); - style.minHeight = minHeight + 'px'; - return style.minWidth = (width / height * minHeight) + 'px'; - } else { - return style.minHeight = style.minWidth = null; - } - }), - 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 === 'Hide Thumbnails' || name === 'Fit Width' || name === 'Fit Height') { - $.on(input, 'change', Gallery.cb.setFitness); - } - $.event('change', null, input); - $.on(input, 'change', $.cb.checked); - if (name === 'Hide Thumbnails' || name === 'Fit Width' || name === 'Fit Height' || name === 'Stretch to Fit') { - $.on(input, 'change', Gallery.cb.setHeight); - } - return { - el: label - }; - }, - createSubEntries: function() { - var delayInput, delayLabel, item, subEntries; - subEntries = (function() { - var k, len1, ref, results; - ref = ['Hide Thumbnails', 'Fit Width', 'Fit Height', 'Stretch to Fit', 'Scroll to Post']; - results = []; - for (k = 0, len1 = ref.length; k < len1; k++) { - item = ref[k]; - results.push(Gallery.menu.createSubEntry(item)); - } - return results; - })(); - delayLabel = $.el('label', { - innerHTML: "Slide Delay: " - }); - 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 k, len1, postObj, ref; - if (this.status === 404) { - post.kill(); - } - if (this.status !== 200) { - return redirect(); - } - ref = this.response.posts; - for (k = 0, len1 = ref.length; k < len1; k++) { - postObj = ref[k]; - 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 $.engine !== 'gecko' || (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: " contract" - }); - 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 (!Conf['Autoplay'] && ((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 k, len1, ref; - ref = [post].concat(slice.call(post.clones)); - for (k = 0, len1 = ref.length; k < len1; k++) { - post = ref[k]; - toggle(post); - } - }); - }, - playVideos: function() { - return g.posts.forEach(function(post) { - var file, k, len1, ref, video, visible; - ref = [post].concat(slice.call(post.clones)); - for (k = 0, len1 = ref.length; k < len1; k++) { - post = ref[k]; - 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, k, len1, oldHeight, ref, ref1, scrollY, top, x; - 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'); - $.rm(file.videoControls); - file.thumb.parentNode.href = file.url; - file.thumb.parentNode.target = '_blank'; - ref = ['isExpanding', 'isExpanded', 'videoControls', 'wasPlaying', 'scrollIntoView']; - for (k = 0, len1 = ref.length; k < len1; k++) { - x = ref[k]; - 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, ref, thumb; - 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 = Math.min(doc.clientHeight - file.fullImage.getBoundingClientRect().bottom - 25, Header.getBottomOf(file.fullImage)); - 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, ref, subEntries; - 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; - } - return $.on(this.file.thumb, 'mouseover', ImageHover.mouseover(this)); - }, - catalogNode: function() { - var file; - file = this.thread.OP.file; - if (!(file && (file.isImage || file.isVideo))) { - return; - } - return $.on(this.nodes.thumb, 'mouseover', ImageHover.mouseover(this.thread.OP)); - }, - mouseover: function(post) { - return function(e) { - var el, error, file, height, isVideo, left, maxHeight, maxWidth, ref, ref1, ref2, right, scale, width, x; - 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 k, len1, ref1, results; - ref1 = file.dimensions.split('x'); - results = []; - for (k = 0, len1 = ref1.length; k < len1; k++) { - x = ref1[k]; - results.push(+x); - } - return results; - })(), width = ref1[0], height = ref1[1]; - ref2 = this.getBoundingClientRect(), left = ref2.left, right = ref2.right; - maxWidth = Math.max(left, doc.clientWidth - right); - maxHeight = doc.clientHeight - UI.hover.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', - height: scale * height, - 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)); - }; - } - }; - - 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: " Prefetch Images" - }); - this.el = prefetch.firstElementChild; - $.on(this.el, 'change', this.toggle); - return Header.menu.addEntry({ - el: prefetch, - order: 98 - }); - }, - 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, k, len1, ref, thumb, video; - file = post.file; - thumb = file.thumb; - video = $.el('video', { - preload: 'none', - loop: true, - muted: true, - poster: thumb.src || thumb.dataset.src, - textContent: thumb.alt, - className: thumb.className - }); - video.setAttribute('muted', 'muted'); - video.dataset.md5 = thumb.dataset.md5; - ref = ['height', 'width', 'maxHeight', 'maxWidth']; - for (k = 0, len1 = ref.length; k < len1; k++) { - attr = ref[k]; - video.style[attr] = thumb.style[attr]; - } - video.src = file.url; - $.replace(thumb, video); - file.thumb = video; - return file.videoThumb = true; - }, - prefetch: function(post) { - var clone, el, file, isImage, isVideo, k, len1, match, ref, replace, thumb, type, url; - 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 || thumb.dataset.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 (k = 0, len1 = ref.length; k < len1; k++) { - clone = ref[k]; - clone.file.thumb.preload = 'auto'; - } - thumb.preload = 'auto'; - if ($.engine === 'gecko') { - $.on(thumb, 'loadeddata', function() { - return this.removeAttribute('poster'); - }); - } - return; - } - el = $.el(isImage ? 'img' : 'video'); - if (replace && isImage) { - $.on(el, 'load', function() { - var len2, q, ref1; - ref1 = post.clones; - for (q = 0, len2 = ref1.length; q < len2; q++) { - clone = ref1[q]; - clone.file.thumb.src = url; - } - thumb.src = url; - return thumb.removeAttribute('data-src'); - }); - } - 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 k, len1, ref1, ref2, thumb; - ref1 = [post].concat(slice.call(post.clones)); - for (k = 0, len1 = ref1.length; k < len1; k++) { - post = ref1[k]; - 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: "" - }); - $.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; - if (!(!this.isClone && this.file && this.file.thumb && this.file.isSpoiler)) { - return; - } - thumb = this.file.thumb; - thumb.removeAttribute('style'); - thumb.style.maxHeight = thumb.style.maxWidth = this.isReply ? '125px' : '250px'; - if (thumb.src) { - return thumb.src = this.file.thumbURL; - } else { - return thumb.dataset.src = this.file.thumbURL; - } - } - }; - - Sauce = { - init: function() { - var err, k, len1, link, links, ref, ref1; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Sauce'])) { - return; - } - links = []; - ref1 = Conf['sauces'].split('\n'); - for (k = 0, len1 = ref1.length; k < len1; k++) { - link = ref1[k]; - 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', - className: 'sauce' - }); - return Post.callbacks.push({ - name: 'Sauce', - cb: this.node - }); - }, - sandbox: function(url) { - return E.url({ - innerHTML: "[sb] " + E(url) + "" - }); - }, - rmOrigin: function(e) { - if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) { - return; - } - $.open(this.href); - return e.preventDefault(); - }, - createSauceLink: function(link, post) { - var a, ext, i, k, key, len1, m, part, parts, ref, ref1, ref2, skip, url; - if (!(link = link.trim())) { - return null; - } - parts = {}; - ref = link.split(/;(?=(?:text|boards|types|sandbox):?)/); - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - 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) || '?'); - ext = post.file.url.match(/[^.]*$/)[0]; - skip = false; - for (key in parts) { - parts[key] = parts[key].replace(/%(T?URL|IMG|[sh]?MD5|board|name|%|semi)/g, function(_, parameter) { - var type; - type = Sauce.formatters[parameter](post, ext); - if (type == null) { - skip = true; - return ''; - } - if (key === 'url' && (parameter !== '%' && parameter !== 'semi')) { - if (/^javascript:/i.test(parts['url'])) { - type = JSON.stringify(type); - } - type = encodeURIComponent(type); - } - return type; - }); - } - if (skip) { - return null; - } - if (!(!parts['boards'] || (ref2 = post.board.ID, indexOf.call(parts['boards'].split(','), ref2) >= 0))) { - return null; - } - if (!(!parts['types'] || indexOf.call(parts['types'].split(','), ext) >= 0)) { - return null; - } - url = parts['url']; - if (parts['sandbox'] != null) { - url = Sauce.sandbox(url); - } - a = Sauce.link.cloneNode(true); - a.href = url; - a.textContent = parts['text']; - if (/^javascript:/i.test(parts['url'])) { - a.removeAttribute('target'); - } - if (parts['sandbox'] != null) { - $.on(a, 'click', Sauce.rmOrigin); - } - return a; - }, - node: function() { - var k, len1, link, node, nodes, ref; - if (this.isClone || !this.file) { - return; - } - nodes = []; - ref = Sauce.links; - for (k = 0, len1 = ref.length; k < len1; k++) { - link = ref[k]; - if (node = Sauce.createSauceLink(link, this)) { - nodes.push($.tn('\u00A0'), node); - } - } - return $.add(this.file.text, nodes); - }, - formatters: { - TURL: function(post) { - return post.file.thumbURL; - }, - URL: function(post) { - return post.file.url; - }, - IMG: function(post, ext) { - if (ext === 'gif' || ext === 'jpg' || ext === 'png') { - return post.file.url; - } else { - return post.file.thumbURL; - } - }, - MD5: function(post) { - return post.file.MD5; - }, - sMD5: function(post) { - var ref; - return (ref = post.file.MD5) != null ? ref.replace(/[+\/=]/g, function(c) { - return { - '+': '-', - '/': '_', - '=': '' - }[c]; - }) : void 0; - }, - hMD5: function(post) { - if (post.file.MD5) { - return ((function() { - var k, len1, ref, results; - ref = atob(post.file.MD5); - results = []; - for (k = 0, len1 = ref.length; k < len1; k++) { - c = ref[k]; - results.push(("0" + (c.charCodeAt(0).toString(16))).slice(-2)); - } - return results; - })()).join(''); - } - }, - board: function(post) { - return post.board.ID; - }, - name: function(post) { - return post.file.name; - }, - '%': function() { - return '%'; - }, - semi: function() { - return ';'; - } - } - }; - - Volume = { - init: function() { - var ref, ref1, unmuteEntry, volumeEntry; - 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 (Conf['Mouse Wheel Volume']) { - Post.callbacks.push({ - name: 'Mouse Wheel Volume', - cb: this.node - }); - } - if ((ref1 = g.BOARD.ID) !== 'gif' && ref1 !== 'wsg') { - return; - } - if (Conf['Mouse Wheel Volume']) { - CatalogThread.callbacks.push({ - name: 'Mouse Wheel Volume', - cb: this.catalogNode - }); - } - 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: " 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, key, muted, val, volume; - muted = this.muted, volume = this.volume; - items = { - 'Allow Sound': !muted, - 'Default Volume': volume - }; - for (key in items) { - val = items[key]; - if (Conf[key] === val) { - delete items[key]; - } - } - $.set(items); - $.extend(Conf, items); - if (Volume.inputs) { - Volume.inputs.unmute.checked = !muted; - return Volume.inputs.volume.value = volume; - } - }, - node: function() { - var ref, ref1; - if (!(((ref = this.board.ID) === 'gif' || ref === 'wsg') && ((ref1 = this.file) != null ? ref1.isVideo : void 0))) { - return; - } - $.on(this.file.thumb, 'wheel', Volume.wheel.bind(Header.hover)); - return $.on($('a', this.file.text), 'wheel', Volume.wheel.bind(this.file.thumb.parentNode)); - }, - catalogNode: function() { - var file; - file = this.thread.OP.file; - if (!(file != null ? file.isVideo : void 0)) { - return; - } - return $.on(this.nodes.thumb, 'wheel', Volume.wheel.bind(Header.hover)); - }, - wheel: function(e) { - var el, volume; - if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) { - return; - } - if (!(el = $('video:not([data-md5])', this))) { - 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(); - } - }; - - Embedding = { - init: function() { - var k, len1, ref, type; - if (!(Conf['Embedding'] || Conf['Link Title'])) { - return; - } - this.types = {}; - ref = this.ordered_types; - for (k = 0, len1 = ref.length; k < len1; k++) { - type = ref[k]; - this.types[type.key] = type; - } - if (Conf['Floating Embeds']) { - this.dialog = UI.dialog('embedding', 'top: 50px; right: 0px;', { - innerHTML: "
          " - }); - this.media = $('#media-embed', this.dialog); - $.one(d, '4chanXInitFinished', this.ready); - } - if (Conf['Link Title']) { - return $.on(d, '4chanXInitFinished PostsInserted', function() { - var key, ref1, ref2, service; - 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, k, len1, match, ref, type; - href = link.href; - ref = Embedding.ordered_types; - for (k = 0, len1 = ref.length; k < len1; k++) { - type = ref[k]; - if (!(match = type.regExp.exec(href))) { - continue; - } - if (type.dummy) { - return; - } - return { - key: type.key, - uid: match[1], - options: match[2], - link: link - }; - } - }, - embed: function(data) { - var embed, href, key, link, name, options, post, ref, uid, value; - key = data.key, uid = data.uid, options = data.options, link = data.link, post = data.post; - href = link.href; - if (Embedding.types[key].httpOnly && location.protocol !== 'http:') { - return; - } - $.addClass(link, key.toLowerCase()); - embed = $.el('a', { - className: 'embedder', - href: 'javascript:;', - textContent: '(embed)' - }); - ref = { - key: key, - uid: uid, - options: options, - href: href - }; - for (name in ref) { - value = ref[name]; - embed.dataset[name] = value; - } - $.on(embed, 'click', Embedding.cb.toggle); - $.after(link, [$.tn(' '), embed]); - if (Conf['Auto-embed'] && !Conf['Floating Embeds'] && !post.isFetchedQuote && key !== 'TwitchTV') { - 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; - } - $.addClass(link, key.toLowerCase()); - 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) + "] Title Link Blocked (are you using NoScript?)" - }); - } - } - }, - flushTitles: function(service) { - var cb, data, k, len1, queue; - queue = service.queue; - if (!(queue != null ? queue.length : void 0)) { - return; - } - service.queue = []; - cb = function() { - var data, k, len1; - for (k = 0, len1 = queue.length; k < len1; k++) { - data = queue[k]; - Embedding.cb.title(this, data); - } - }; - if (!$.cache(service.api((function() { - var k, len1, results; - results = []; - for (k = 0, len1 = queue.length; k < len1; k++) { - data = queue[k]; - results.push(data.uid); - } - return results; - })()), cb, { - responseType: 'json' - })) { - for (k = 0, len1 = queue.length; k < len1; k++) { - data = queue[k]; - $.extend(data.link, { - innerHTML: "[" + E(data.key) + "] Title Link Blocked (are you using NoScript?)" - }); - } - } - }, - 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: none; width: 640px; height: 360px;'; - return container; - }, - title: function(req, data) { - var base1, k, key, len1, len2, link, link2, options, post, post2, q, ref, ref1, service, status, text, uid; - 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 (k = 0, len1 = ref.length; k < len1; k++) { - post2 = ref[k]; - ref1 = $$('a.linkify', post2.nodes.comment); - for (q = 0, len2 = ref1.length; q < len2; q++) { - link2 = ref1[q]; - if (!(link2.href === link.href)) { - continue; - } - if ((base1 = link2.dataset).original == null) { - base1.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.dataset.href - }); - } - }, { - key: 'Dailymotion', - regExp: /^\w+:\/\/(?:(?:www\.)?dailymotion\.com\/(?:embed\/)?video|dai\.ly)\/([A-Za-z0-9]+)[^?]*(.*)/, - el: function(a) { - var el, options, start; - options = (start = a.dataset.options.match(/[?&](start=\d+)/)) ? "?" + start[1] : ''; - el = $.el('iframe', { - src: "//www.dailymotion.com/embed/video/" + a.dataset.uid + options - }); - el.setAttribute("allowfullscreen", "true"); - return el; - }, - title: { - api: function(uid) { - return "https://api.dailymotion.com/video/" + uid; - }, - text: function(_) { - return _.title; - } - } - }, { - 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: "" + E(a.dataset.uid) + "" - }; - el.src = E.url(content); - 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: "" - }); - } - }, { - 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', { - src: "http://www.liveleak.com/ll_embed?i=" + a.dataset.uid - }); - el.setAttribute("allowfullscreen", "true"); - 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)?)/, - style: 'border: 0; width: 600px; height: 406px;', - el: function(a) { - return $.el('iframe', { - src: "//strawpoll.me/embed_1/" + a.dataset.uid - }); - } - }, { - key: 'TwitchTV', - regExp: /^\w+:\/\/(?:www\.)?twitch\.tv\/(\w[^#\&\?]*)/, - style: "border: none; width: 620px; height: 378px;", - el: function(a) { - var _, channel, flashvars, id, idprefix, k, len1, obj, part, ref, result, seconds, start, type; - if (result = /(\w+)\/([bcv])\/(\d+)/i.exec(a.dataset.uid)) { - _ = result[0], channel = result[1], type = result[2], id = result[3]; - idprefix = type === 'b' ? 'a' : type; - flashvars = "channel=" + channel + "&start_volume=25&auto_play=false&videoId=" + idprefix + id; - if (start = a.dataset.href.match(/\bt=(\w+)/)) { - seconds = 0; - ref = start[1].match(/\d+[hms]/g); - for (k = 0, len1 = ref.length; k < len1; k++) { - part = ref[k]; - seconds += +part.slice(0, -1) * { - 'h': 3600, - 'm': 60, - 's': 1 - }[part.slice(-1)]; - } - flashvars += "&initial_time=" + seconds; - } - } else { - channel = (/(\w+)/.exec(a.dataset.uid))[0]; - flashvars = "channel=" + channel + "&start_volume=25&auto_play=false"; - } - obj = $.el('object', { - data: '//www-cdn.jtvnw.net/swflibs/TwitchPlayer.swf' - }); - $.extend(obj, { - innerHTML: "" - }); - obj.children[1].value = flashvars; - return obj; - } - }, { - key: 'Vocaroo', - regExp: /^\w+:\/\/(?:www\.)?vocaroo\.com\/i\/(\w+)/, - style: '', - el: function(a) { - var el, type; - el = $.el('audio', { - controls: true, - preload: 'auto' - }); - type = el.canPlayType('audio/webm') ? 'webm' : 'mp3'; - el.src = "http://vocaroo.com/media_command.php?media=" + a.dataset.uid + "&command=download_" + type; - return el; - } - }, { - 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=https://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=|\bembed\/|\bv\/))([\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, k, len1, ref; - ref = data.items; - for (k = 0, len1 = ref.length; k < len1; k++) { - item = ref[k]; - if (item.id === uid) { - return item.snippet.title; - } - } - return 'Not Found'; - } - } - }, { - key: 'Loopvid', - regExp: /^\w+:\/\/(?:www\.)?loopvid.appspot.com\/#?((?:pf|kd|lv|gd|gh|db|dx|nn|cp|wu|ig|ky|mf|pc|gc)\/[\w\-\/]+(,[\w\-\/]+)*|fc\/\w+\/\d+)/, - style: 'max-width: 80vw; max-height: 80vh;', - el: function(a) { - var _, base, el, host, k, len1, len2, name, names, q, ref, ref1, type, types, url; - el = $.el('video', { - controls: true, - preload: 'auto', - loop: true - }); - ref = a.dataset.uid.match(/(\w+)\/(.*)/), _ = ref[0], host = ref[1], names = ref[2]; - types = (function() { - switch (host) { - case 'gd': - case 'wu': - case 'fc': - return ['']; - case 'gc': - return ['giant', 'fat', 'zippy']; - default: - return ['.webm', '.mp4']; - } - })(); - ref1 = names.split(','); - for (k = 0, len1 = ref1.length; k < len1; k++) { - name = ref1[k]; - for (q = 0, len2 = types.length; q < len2; q++) { - type = types[q]; - base = "" + name + type; - url = (function() { - switch (host) { - case 'pf': - return "https://web.archive.org/web/2/http://a.pomf.se/" + base; - case 'kd': - return "http://kastden.org/loopvid/" + base; - case 'lv': - return "http://kastden.org/_loopvid_media/lv/" + 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://dl.dropboxusercontent.com/u/" + base; - case 'dx': - return "https://dl.dropboxusercontent.com/" + base; - case 'nn': - return "http://naenara.eu/loopvids/" + base; - case 'cp': - return "https://copy.com/" + base; - case 'wu': - return "http://webmup.com/" + base + "/vid.webm"; - case 'ig': - return "https://i.imgur.com/" + base; - case 'ky': - return "https://kiyo.me/" + base; - case 'mf': - return "https://d.maxfile.ro/" + base; - case 'pc': - return "http://a.pomf.cat/" + base; - case 'fc': - return "//i.4cdn.org/" + base + ".webm"; - case 'gc': - return "https://" + type + ".gfycat.com/" + name + ".webm"; - } - })(); - $.add(el, $.el('source', { - src: url - })); - } - } - return el; - } - }, { - key: 'Clyp', - regExp: /^\w+:\/\/(?:www\.)?clyp\.it\/(\w+)/, - style: '', - el: function(a) { - var el, type; - el = $.el('audio', { - controls: true, - preload: 'auto' - }); - type = el.canPlayType('audio/ogg') ? 'ogg' : 'mp3'; - el.src = "https://clyp.it/" + a.dataset.uid + "." + type; - return el; - } - }, { - 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.dataset.href, - loop: /^https?:\/\/i\.4cdn\.org\//.test(a.dataset.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 k, len1, len2, link, links, q, ref; - if (this.isClone) { - return Embedding.events(this); - } - if (!Linkify.regString.test(this.info.comment)) { - return; - } - ref = $$('a[href^="http://i.4cdn.org/"], a[href^="https://i.4cdn.org/"]', this.nodes.comment); - for (k = 0, len1 = ref.length; k < len1; k++) { - link = ref[k]; - $.addClass(link, 'linkify'); - Embedding.process(link, this); - } - links = Linkify.process(this.nodes.comment); - for (q = 0, len2 = links.length; q < len2; q++) { - link = links[q]; - 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, part1, part2, ref, ref1, 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') { - if ((part1 = word.match(/(https?:\/\/)?([a-z\d-]+\.)*[a-z\d-]+$/i)) && (part2 = (ref = snapshot.snapshotItem(i)) != null ? (ref1 = ref.data) != null ? ref1.match(/^(\.[a-z\d-]+)*\//i) : void 0 : void 0) && (part1[0] + part2[0]).search(Linkify.regString) === 0) { - continue; - } else { - 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|xyz|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, encodedDomain, 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; - } - if (encodedDomain = text.match(/^(https?:\/\/[^\/]*%[0-9a-f]{2})(.*)$/i)) { - text = encodedDomain[1].replace(/%([0-9a-f]{2})/ig, function(x, y) { - if (y === '25') { - return x; - } else { - return String.fromCharCode(parseInt(y, 16)); - } - }) + encodedDomain[2]; - } - a = $.el('a', { - className: 'linkify', - rel: 'nofollow noreferrer', - target: '_blank', - href: text - }); - $.add(a, range.extractContents()); - range.insertNode(a); - return a; - } - }; - - ArchiveLink = { - init: function() { - var div, entry, k, len1, ref, ref1, type; - 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'], ['Capcode', 'capcode'], ['Subject', 'subject'], ['Filename', 'filename'], ['Image MD5', 'MD5']]; - for (k = 0, len1 = ref1.length; k < len1; k++) { - type = ref1[k]; - 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 = { - auto: [{}, {}], - 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:;' - }); - this.nodes = { - menu: div.firstChild, - links: [postEl, fileEl] - }; - postEntry = { - el: postEl, - open: function() { - postEl.textContent = DeleteLink.linkText(false); - $.on(postEl, 'click', DeleteLink.toggle); - return true; - } - }; - fileEntry = { - el: fileEl, - open: function(arg) { - var file; - file = arg.file; - if (!file || file.isDead) { - return false; - } - fileEl.textContent = DeleteLink.linkText(true); - $.on(fileEl, 'click', DeleteLink.toggle); - return true; - } - }; - return Menu.menu.addEntry({ - el: div, - order: 40, - open: function(post) { - if (post.isDead) { - return false; - } - DeleteLink.post = post; - DeleteLink.nodes.menu.textContent = DeleteLink.menuText(); - DeleteLink.cooldown.start(post); - return true; - }, - subEntries: [postEntry, fileEntry] - }); - }, - menuText: function() { - var seconds; - if (seconds = DeleteLink.cooldown.seconds[DeleteLink.post.fullID]) { - return "Delete (" + seconds + ")"; - } else { - return 'Delete'; - } - }, - linkText: function(fileOnly) { - var text; - text = fileOnly ? 'File' : 'Post'; - if (DeleteLink.auto[+fileOnly][DeleteLink.post.fullID]) { - text = "Deleting " + (text.toLowerCase()) + "..."; - } - return text; - }, - toggle: function() { - var auto, fileOnly, post; - post = DeleteLink.post; - fileOnly = $.hasClass(this, 'delete-file'); - auto = DeleteLink.auto[+fileOnly]; - if (auto[post.fullID]) { - delete auto[post.fullID]; - } else { - auto[post.fullID] = true; - } - this.textContent = DeleteLink.linkText(fileOnly); - if (!DeleteLink.cooldown.seconds[post.fullID]) { - return DeleteLink["delete"](post, fileOnly); - } - }, - "delete": function(post, fileOnly) { - var form, link; - link = DeleteLink.nodes.links[+fileOnly]; - delete DeleteLink.auto[+fileOnly][post.fullID]; - if (post.fullID === DeleteLink.post.fullID) { - $.off(link, 'click', DeleteLink.toggle); - } - form = { - mode: 'usrdel', - onlyimgdel: fileOnly, - pwd: QR.persona.getPassword() - }; - form[post.ID] = 'delete'; - 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, post); - } - }, { - form: $.formData(form) - }); - }, - load: function(link, post, fileOnly, resDoc) { - var el, msg; - link.textContent = DeleteLink.linkText(fileOnly); - if (resDoc.title === '4chan - Banned') { - el = $.el('span', { - innerHTML: "You can't delete posts because you are banned." - }); - return new Notice('warning', el, 20); - } else if (msg = resDoc.getElementById('errmsg')) { - new Notice('warning', msg.textContent, 20); - if (post.fullID === DeleteLink.post.fullID) { - $.on(link, 'click', DeleteLink.toggle); - } - if (QR.cooldown.data && Conf['Cooldown'] && /\bwait\b/i.test(msg.textContent)) { - DeleteLink.cooldown.start(post, 5); - DeleteLink.auto[+fileOnly][post.fullID] = true; - return DeleteLink.nodes.links[+fileOnly].textContent = DeleteLink.linkText(fileOnly); - } - } else { - if (!fileOnly) { - QR.cooldown["delete"](post); - } - if (resDoc.title === 'Updating index...') { - (post.origin || post).kill(fileOnly); - } - if (post.fullID === DeleteLink.post.fullID) { - return link.textContent = 'Deleted'; - } - } - }, - error: function(link, post) { - new Notice('warning', 'Connection error, please retry.', 20); - if (post.fullID === DeleteLink.post.fullID) { - return $.on(link, 'click', DeleteLink.toggle); - } - }, - cooldown: { - seconds: {}, - start: function(post, seconds) { - if (DeleteLink.cooldown.seconds[post.fullID] != null) { - return; - } - if (seconds == null) { - seconds = QR.cooldown.secondsDeletion(post); - } - if (seconds > 0) { - DeleteLink.cooldown.seconds[post.fullID] = seconds; - return DeleteLink.cooldown.count(post); - } - }, - count: function(post) { - var fileOnly, k, len1, ref; - if (post.fullID === DeleteLink.post.fullID) { - DeleteLink.nodes.menu.textContent = DeleteLink.menuText(); - } - if (DeleteLink.cooldown.seconds[post.fullID] > 0 && Conf['Cooldown']) { - DeleteLink.cooldown.seconds[post.fullID]--; - setTimeout(DeleteLink.cooldown.count, 1000, post); - } else { - delete DeleteLink.cooldown.seconds[post.fullID]; - ref = [false, true]; - for (k = 0, len1 = ref.length; k < len1; k++) { - fileOnly = ref[k]; - if (DeleteLink.auto[+fileOnly][post.fullID]) { - DeleteLink["delete"](post, fileOnly); - } - } - } - } - } - }; - - 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: "" - }); - 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:;' - }); - $.on(a, 'click', ReportLink.report); - return Menu.menu.addEntry({ - el: a, - order: 10, - open: function(post) { - if (!(post.isDead || (post.thread.isDead && !post.thread.isArchived))) { - a.textContent = 'Report'; - ReportLink.url = "//sys.4chan.org/" + post.board + "/imgboard.php?mode=report&no=" + post; - if ((Conf['Use Recaptcha v1 in Reports'] && Main.jsEnabled) || d.cookie.indexOf('pass_enabled=1') >= 0) { - ReportLink.url += '&altc=1'; - ReportLink.dims = 'width=350,height=275'; - } else { - ReportLink.dims = 'width=400,height=550'; - } - } else if (Conf['Archive Report']) { - a.textContent = 'Report to archive'; - ReportLink.url = Redirect.to('report', { - boardID: post.board.ID, - postID: post.ID - }); - ReportLink.dims = 'width=700,height=475'; - } else { - ReportLink.url = ''; - } - return !!ReportLink.url; - } - }); - }, - report: function() { - var dims, id, set, url; - url = ReportLink.url, dims = ReportLink.dims; - id = Date.now(); - set = "toolbar=0,scrollbars=1,location=0,status=1,menubar=0,resizable=1," + dims; - 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() { - MarkNewIPs.ipCount = this.ipCount; - MarkNewIPs.postCount = this.posts.keys.length; - return $.on(d, 'ThreadUpdate', MarkNewIPs.onUpdate); - }, - onUpdate: function(e) { - var deletedPosts, fullID, i, ipCount, k, len1, len2, newPosts, postCount, q, ref; - ref = e.detail, ipCount = ref.ipCount, postCount = ref.postCount, newPosts = ref.newPosts, deletedPosts = ref.deletedPosts; - if (ipCount == null) { - return; - } - switch (ipCount - MarkNewIPs.ipCount) { - case postCount - MarkNewIPs.postCount + deletedPosts.length: - i = MarkNewIPs.ipCount; - for (k = 0, len1 = newPosts.length; k < len1; k++) { - fullID = newPosts[k]; - MarkNewIPs.markNew(g.posts[fullID], ++i); - } - break; - case -deletedPosts.length: - for (q = 0, len2 = newPosts.length; q < len2; q++) { - fullID = newPosts[q]; - MarkNewIPs.markOld(g.posts[fullID]); - } - } - MarkNewIPs.ipCount = ipCount; - return MarkNewIPs.postCount = postCount; - }, - 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'); - } - }; - - ReplyPruning = { - init: function() { - var el, label; - if (!(g.VIEW === 'thread' && Conf['Reply Pruning'])) { - return; - } - this.active = !(Conf['Quote Threading'] && Conf['Thread Quotes']); - this.container = $.frag(); - this.summary = $.el('span', { - hidden: true, - className: 'summary' - }); - this.summary.style.cursor = 'pointer'; - $.on(this.summary, 'click', (function(_this) { - return function() { - _this.inputs.enabled.checked = !_this.inputs.enabled.checked; - return $.event('change', null, _this.inputs.enabled); - }; - })(this)); - label = UI.checkbox('Prune Replies', 'Show Last', this.active); - el = $.el('span', { - title: 'Maximum number of replies to show.' - }, { - innerHTML: " " - }); - $.prepend(el, label); - this.inputs = { - enabled: label.firstElementChild, - replies: el.lastElementChild - }; - $.on(this.inputs.enabled, 'change', this.setEnabled); - $.on(this.inputs.replies, 'change', $.cb.value); - Header.menu.addEntry({ - el: el, - order: 190 - }); - return Thread.callbacks.push({ - name: 'Reply Pruning', - cb: this.node - }); - }, - position: 0, - hidden: 0, - hiddenFiles: 0, - total: 0, - totalFiles: 0, - setEnabled: function() { - var other; - other = QuoteThreading.input; - if (this.checked && (other != null ? other.checked : void 0)) { - other.checked = false; - $.event('change', null, other); - } - return ReplyPruning.active = this.checked; - }, - showIfHidden: function(id) { - var ref; - if ((ref = ReplyPruning.container) != null ? ref.getElementById(id) : void 0) { - ReplyPruning.inputs.enabled.checked = false; - return $.event('change', null, ReplyPruning.inputs.enabled); - } - }, - node: function() { - var ref; - ReplyPruning.thread = this; - this.posts.forEach(function(post) { - if (post.isReply) { - ReplyPruning.total++; - if (post.file) { - return ReplyPruning.totalFiles++; - } - } - }); - if (ReplyPruning.active && /^#p\d+$/.test(location.hash) && (0 <= (ref = this.posts.keys.indexOf(location.hash.slice(2))) && ref < 1 + Math.max(ReplyPruning.total - +Conf["Max Replies"], 0))) { - ReplyPruning.active = ReplyPruning.inputs.enabled.checked = false; - } - $.after(this.OP.nodes.root, ReplyPruning.summary); - $.on(ReplyPruning.inputs.enabled, 'change', ReplyPruning.update); - $.on(ReplyPruning.inputs.replies, 'change', ReplyPruning.update); - $.on(d, 'ThreadUpdate', ReplyPruning.updateCount); - $.on(d, 'ThreadUpdate', ReplyPruning.update); - return ReplyPruning.update(); - }, - updateCount: function(e) { - var fullID, k, len1, ref; - if (e.detail[404]) { - return; - } - ref = e.detail.newPosts; - for (k = 0, len1 = ref.length; k < len1; k++) { - fullID = ref[k]; - ReplyPruning.total++; - if (g.posts[fullID].file) { - ReplyPruning.totalFiles++; - } - } - }, - update: function() { - var frag, hidden2, post, posts; - hidden2 = ReplyPruning.active ? Math.max(ReplyPruning.total - +Conf["Max Replies"], 0) : 0; - posts = ReplyPruning.thread.posts; - if (ReplyPruning.hidden < hidden2) { - while (ReplyPruning.hidden < hidden2 && ReplyPruning.position < posts.keys.length) { - post = posts[posts.keys[ReplyPruning.position++]]; - if (post.isReply && !post.isFetchedQuote) { - $.add(ReplyPruning.container, post.nodes.root); - ReplyPruning.hidden++; - if (post.file) { - ReplyPruning.hiddenFiles++; - } - } - } - } else if (ReplyPruning.hidden > hidden2) { - frag = $.frag(); - while (ReplyPruning.hidden > hidden2 && ReplyPruning.position > 0) { - post = posts[posts.keys[--ReplyPruning.position]]; - if (post.isReply && !post.isFetchedQuote) { - $.prepend(frag, post.nodes.root); - ReplyPruning.hidden--; - if (post.file) { - ReplyPruning.hiddenFiles--; - } - } - } - $.after(ReplyPruning.summary, frag); - $.event('PostsInserted'); - } - ReplyPruning.summary.textContent = ReplyPruning.active ? Build.summaryText('+', ReplyPruning.hidden, ReplyPruning.hiddenFiles) : Build.summaryText('-', ReplyPruning.total, ReplyPruning.totalFiles); - return ReplyPruning.summary.hidden = ReplyPruning.total <= +Conf["Max Replies"]; - } - }; - - 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: "? / ?" + (Conf["IP Count in Stats"] ? " / ?" : "") + (Conf["Page Count in Stats"] ? " / ?" : "") - }; - statsTitle = 'Posts / Files'; - if (Conf['IP Count in Stats']) { - statsTitle += ' / IPs'; - } - if (Conf['Page Count in Stats']) { - statsTitle += (g.BOARD.ID === 'f' ? ' / Purge Position' : ' / 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: "
          " + statsHTML.innerHTML + "
          " - }); - $.addClass(doc, 'float'); - $.ready(function() { - return $.add(d.body, sc); - }); - } - this.postCountEl = $('#post-count', sc); - this.fileCountEl = $('#file-count', sc); - this.ipCountEl = $('#ip-count', sc); - this.pageCountEl = $('#page-count', sc); - if (this.pageCountEl) { - $.on(this.pageCountEl, 'click', ThreadStats.fetchPage); - } - 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 (ThreadStats.pageCountEl) { - 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 (!ThreadStats.pageCountEl) { - return; - } - if (newPosts.length) { - ThreadStats.lastPost = g.posts[newPosts[newPosts.length - 1]].info.date; - } - if (g.BOARD.ID !== 'f' && ((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) && ipCountEl) { - ipCountEl.textContent = ipCount; - } - (thread.postLimit && !thread.isSticky ? $.addClass : $.rmClass)(postCountEl, 'warning'); - return (thread.fileLimit && !thread.isSticky ? $.addClass : $.rmClass)(fileCountEl, 'warning'); - }, - fetchPage: function() { - if (!ThreadStats.pageCountEl) { - 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: 'ThreadStats' - }); - }, - onThreadsLoad: function() { - var k, len1, len2, len3, page, purgePos, q, ref, ref1, ref2, thread, u; - if (this.status === 200) { - ref = this.response; - for (k = 0, len1 = ref.length; k < len1; k++) { - page = ref[k]; - if (g.BOARD.ID === 'f') { - purgePos = 1; - ref1 = page.threads; - for (q = 0, len2 = ref1.length; q < len2; q++) { - thread = ref1[q]; - if (thread.no < ThreadStats.thread.ID) { - purgePos++; - } - } - ThreadStats.pageCountEl.textContent = purgePos; - } else { - ref2 = page.threads; - for (u = 0, len3 = ref2.length; u < len3; u++) { - thread = ref2[u]; - 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); - ThreadStats.retry(); - return; - } - } - } - } else if (this.status === 304) { - return ThreadStats.retry(); - } - }, - retry: function() { - var ref; - if (g.BOARD.ID !== 'f' && ThreadStats.lastPost > ThreadStats.lastPageUpdate && ((ref = ThreadStats.pageCountEl) != null ? ref.textContent : void 0) !== '1') { - clearTimeout(ThreadStats.timeout); - return ThreadStats.timeout = setTimeout(ThreadStats.fetchPage, 5 * $.SECOND); - } - } - }; - - ThreadUpdater = { - init: function() { - var conf, el, input, name, ref, sc, subEntries, updateLink; - if (g.VIEW !== 'thread' || !Conf['Thread Updater']) { - return; - } - this.audio = $.el('audio', { - src: ThreadUpdater.beep - }); - if (Conf['Updater and Stats in Header']) { - this.dialog = sc = $.el('span', { - id: 'updater' - }); - $.extend(sc, { - innerHTML: "" - }); - $.ready(function() { - return Header.addShortcut(sc); - }); - } else { - this.dialog = sc = UI.dialog('updater', 'bottom: 0px; left: 0px;', { - innerHTML: "
          " - }); - $.addClass(doc, 'float'); - $.ready(function() { - return $.add(d.body, sc); - }); - } - this.checkPostCount = 0; - this.timer = $('#update-timer', sc); - this.status = $('#update-status', sc); - $.on(this.timer, 'click', this.update); - $.on(this.status, 'click', this.update); - updateLink = $.el('span', { - className: 'brackets-wrap updatelink' - }); - $.extend(updateLink, { - innerHTML: "Update" - }); - Main.ready(function() { - var navLinksBot; - if ((navLinksBot = $('.navLinksBot'))) { - 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.setInterval); - } - subEntries.push({ - el: el - }); - } - this.settings = $.el('span', { - innerHTML: "Interval" - }); - $.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.outdateCount = 0; - ThreadUpdater.postIDs = []; - ThreadUpdater.fileIDs = []; - this.posts.forEach(function(post) { - ThreadUpdater.postIDs.push(post.ID); - if (post.file) { - return ThreadUpdater.fileIDs.push(post.ID); - } - }); - ThreadUpdater.cb.interval.call($.el('input', { - value: Conf['Interval'] - })); - $.on(d, 'QRPostSuccessful', ThreadUpdater.cb.checkpost); - $.on(d, 'visibilitychange', ThreadUpdater.cb.visibility); - return ThreadUpdater.setInterval(); - }, - - /* - 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', - playBeep: function() { - var audio; - audio = ThreadUpdater.audio; - if (audio.paused) { - return audio.play(); - } else { - return $.one(audio, 'ended', ThreadUpdater.playBeep); - } - }, - cb: { - checkpost: function(e) { - if (e.detail.threadID !== ThreadUpdater.thread.ID) { - return; - } - ThreadUpdater.postID = e.detail.postID; - ThreadUpdater.checkPostCount = 0; - ThreadUpdater.outdateCount = 0; - return ThreadUpdater.setInterval(); - }, - 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; - }; - }, - 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() { - var req; - req = ThreadUpdater.req; - switch (req.status) { - case 200: - ThreadUpdater.parse(req); - if (ThreadUpdater.thread.isArchived) { - return ThreadUpdater.kill(); - } else { - return ThreadUpdater.setInterval(); - } - break; - case 404: - return $.ajax("//a.4cdn.org/" + ThreadUpdater.thread.board + "/catalog.json", { - onloadend: function() { - var confirmed, k, len1, len2, page, q, ref, ref1, thread; - if (this.status === 200) { - confirmed = true; - ref = this.response; - for (k = 0, len1 = ref.length; k < len1; k++) { - page = ref[k]; - ref1 = page.threads; - for (q = 0, len2 = ref1.length; q < len2; q++) { - thread = ref1[q]; - if (thread.no === ThreadUpdater.thread.ID) { - confirmed = false; - break; - } - } - } - } else { - confirmed = false; - } - if (confirmed) { - return ThreadUpdater.kill(); - } else { - return ThreadUpdater.error(req); - } - } - }); - default: - return ThreadUpdater.error(req); - } - } - }, - kill: function() { - ThreadUpdater.thread.kill(); - ThreadUpdater.setInterval(); - return $.event('ThreadUpdate', { - 404: true, - threadID: ThreadUpdater.thread.fullID - }); - }, - error: function(req) { - if (req.status === 304) { - ThreadUpdater.set('status', ''); - } - ThreadUpdater.setInterval(); - if (!req.status) { - return ThreadUpdater.set('status', 'Connection Failed', 'warning'); - } else if (req.status !== 304) { - return ThreadUpdater.set('status', req.statusText + " (" + req.status + ")", 'warning'); - } - }, - setInterval: function() { - var cur, interval, j, limit; - clearTimeout(ThreadUpdater.timeoutID); - if (ThreadUpdater.thread.isDead) { - ThreadUpdater.set('status', (ThreadUpdater.thread.isArchived ? 'Archived' : '404'), 'warning'); - ThreadUpdater.set('timer', ''); - return; - } - if (ThreadUpdater.postID && ThreadUpdater.checkPostCount < 5) { - ThreadUpdater.set('timer', '...', 'loading'); - ThreadUpdater.timeoutID = setTimeout(ThreadUpdater.update, ++ThreadUpdater.checkPostCount * $.SECOND); - return; - } - if (!Conf['Auto Update']) { - ThreadUpdater.set('timer', 'Update'); - return; - } - interval = ThreadUpdater.interval; - if (Conf['Optional Increase']) { - limit = d.hidden ? 10 : 5; - j = Math.min(ThreadUpdater.outdateCount, limit); - cur = (Math.floor(interval * 0.1) || 1) * j * j; - ThreadUpdater.seconds = $.minmax(cur, interval, 300); - } else { - ThreadUpdater.seconds = interval; - } - return ThreadUpdater.timeout(); - }, - 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; - } - return el.className = klass != null ? klass : (text === '' ? 'empty' : ''); - }, - timeout: function() { - if (ThreadUpdater.seconds) { - ThreadUpdater.set('timer', ThreadUpdater.seconds); - ThreadUpdater.timeoutID = setTimeout(ThreadUpdater.timeout, 1000); - } else { - ThreadUpdater.outdateCount++; - ThreadUpdater.update(); - } - return ThreadUpdater.seconds--; - }, - update: function() { - var ref; - clearTimeout(ThreadUpdater.timeoutID); - ThreadUpdater.set('timer', '...', 'loading'); - 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: 'ThreadUpdater' - }); - }, - 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(req) { - var ID, OP, board, deletedFiles, deletedPosts, files, firstPost, index, ipCountEl, k, lastPost, len1, len2, len3, len4, newPosts, node, post, postObject, postObjects, posts, q, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, scroll, thread, u, unreadCount, unreadQYCount, v; - postObjects = req.response.posts; - OP = postObjects[0]; - thread = ThreadUpdater.thread; - board = thread.board; - ref = ThreadUpdater.postIDs, lastPost = ref[ref.length - 1]; - if (postObjects[postObjects.length - 1].no < lastPost && new Date(req.getResponseHeader('Last-Modified')) - thread.posts[lastPost].info.date < 30 * $.SECOND) { - return; - } - Build.spoilerRange[board] = OP.custom_spoiler; - thread.setStatus('Archived', !!OP.archived); - ThreadUpdater.updateThreadStatus('Sticky', !!OP.sticky); - ThreadUpdater.updateThreadStatus('Closed', !!OP.closed); - thread.postLimit = !!OP.bumplimit; - thread.fileLimit = !!OP.imagelimit; - if (OP.unique_ips != null) { - thread.ipCount = OP.unique_ips; - } - posts = []; - index = []; - files = []; - newPosts = []; - for (k = 0, len1 = postObjects.length; k < len1; k++) { - postObject = postObjects[k]; - ID = postObject.no; - index.push(ID); - if (postObject.fsize) { - files.push(ID); - } - if (ID <= lastPost) { - continue; - } - if ((post = thread.posts[ID]) && !post.isFetchedQuote) { - post.resurrect(); - continue; - } - newPosts.push(board + "." + ID); - node = Build.postFromObject(postObject, board.ID); - posts.push(new Post(node, thread, board)); - if (ThreadUpdater.postID === ID) { - delete ThreadUpdater.postID; - } - } - deletedPosts = []; - ref1 = ThreadUpdater.postIDs; - for (q = 0, len2 = ref1.length; q < len2; q++) { - ID = ref1[q]; - if (!(indexOf.call(index, ID) < 0)) { - continue; - } - thread.posts[ID].kill(); - deletedPosts.push(board + "." + ID); - } - ThreadUpdater.postIDs = index; - deletedFiles = []; - ref2 = ThreadUpdater.fileIDs; - for (u = 0, len3 = ref2.length; u < len3; u++) { - ID = ref2[u]; - if (!(!(indexOf.call(files, ID) >= 0 || (ref3 = board + "." + ID, indexOf.call(deletedPosts, ref3) >= 0)))) { - continue; - } - thread.posts[ID].kill(true); - deletedFiles.push(board + "." + ID); - } - ThreadUpdater.fileIDs = files; - if (!posts.length) { - ThreadUpdater.set('status', ''); - } else { - ThreadUpdater.set('status', "+" + posts.length, 'new'); - ThreadUpdater.outdateCount = 0; - unreadCount = (ref4 = Unread.posts) != null ? ref4.size : void 0; - unreadQYCount = (ref5 = Unread.postsQuotingYou) != null ? ref5.size : void 0; - Main.callbackNodes(Post, posts); - if (d.hidden || !d.hasFocus()) { - if (Conf['Beep Quoting You'] && ((ref6 = Unread.postsQuotingYou) != null ? ref6.size : void 0) > unreadQYCount) { - ThreadUpdater.playBeep(); - if (Conf['Beep']) { - ThreadUpdater.playBeep(); - } - } else if (Conf['Beep'] && ((ref7 = Unread.posts) != null ? ref7.size : void 0) > 0 && unreadCount === 0) { - ThreadUpdater.playBeep(); - } - } - scroll = Conf['Auto Scroll'] && ThreadUpdater.scrollBG() && ThreadUpdater.root.getBoundingClientRect().bottom - doc.clientHeight < 25; - firstPost = null; - for (v = 0, len4 = posts.length; v < len4; v++) { - post = posts[v]; - if (!QuoteThreading.insert(post)) { - firstPost || (firstPost = post.nodes.root); - $.add(ThreadUpdater.root, post.nodes.root); - } - } - $.event('PostsInserted'); - if (scroll) { - if (Conf['Bottom Scroll']) { - window.scrollTo(0, d.body.clientHeight); - } else { - if (firstPost) { - Header.scrollTo(firstPost); - } - } - } - } - 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'); - } - return $.event('ThreadUpdate', { - 404: false, - threadID: thread.fullID, - newPosts: newPosts, - deletedPosts: deletedPosts, - deletedFiles: deletedFiles, - postCount: OP.replies + 1, - fileCount: OP.images + !!OP.fsize, - ipCount: OP.unique_ips - }); - } - }; - - ThreadWatcher = { - init: function() { - var sc; - if (!(this.enabled = 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: "
          Thread Watcher ×
          " - }); - this.status = $('#watcher-status', this.dialog); - this.list = this.dialog.lastElementChild; - this.refreshButton = $('.refresh', this.dialog); - this.closeButton = $('.move > .close', this.dialog); - this.unreaddb = Unread.db || new DataBoard('lastReadPosts'); - this.unreadEnabled = Conf['Remember Last Read Post']; - $.on(d, 'QRPostSuccessful', this.cb.post); - $.on(sc, 'click', this.toggleWatcher); - $.on(this.refreshButton, 'click', this.buttonFetchAll); - $.on(this.closeButton, '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['Fixed Thread Watcher']) { - $.addClass(doc, 'fixed-watcher'); - } - if (Conf['Toggleable Thread Watcher']) { - this.dialog.hidden = true; - Header.addShortcut(sc); - $.addClass(doc, 'toggleable-watcher'); - } - ThreadWatcher.fetchAuto(); - if (g.VIEW === 'index' && Conf['JSON Index'] && Conf['Menu'] && g.BOARD.ID !== 'f') { - Menu.menu.addEntry({ - el: $.el('a', { - href: 'javascript:;', - className: 'has-shortcut-text' - }, { - innerHTML: "Alt+click" - }), - order: 6, - open: function(arg) { - var thread; - thread = arg.thread; - if (Conf['Index Mode'] !== 'catalog') { - return false; - } - this.el.firstElementChild.textContent = ThreadWatcher.isWatched(thread) ? 'Unwatch' : 'Watch'; - 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('a', { - href: 'javascript:;', - 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'); - } - $.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)); - return $.on(this.nodes.thumb.parentNode, 'mousedown', function(e) { - if (e.button === 0 && e.altKey) { - return e.preventDefault(); - } - }); - }, - ready: function() { - $.off(d, '4chanXInitFinished', ThreadWatcher.ready); - if (!Main.isThisPageLegit()) { - return; - } - ThreadWatcher.refresh(); - $.add(d.body, ThreadWatcher.dialog); - 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, k, len1, ref; - if ($.hasClass(this, 'disabled')) { - return; - } - ref = $$('a[title]', ThreadWatcher.list); - for (k = 0, len1 = ref.length; k < len1; k++) { - a = ref[k]; - $.open(a.href); - } - return $.event('CloseMenu'); - }, - pruneDeads: function() { - var boardID, data, k, len1, ref, ref1, threadID; - if ($.hasClass(this, 'disabled')) { - return; - } - ThreadWatcher.db.forceSync(); - ref = ThreadWatcher.getAll(); - for (k = 0, len1 = ref.length; k < len1; k++) { - ref1 = ref[k], 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, ref, threadID; - ref = this.parentNode.dataset.fullID.split('.'), boardID = ref[0], threadID = ref[1]; - return ThreadWatcher.rm(boardID, +threadID); - }, - post: function(e) { - var boardID, postID, ref, threadID; - 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, ref, threadID; - db = ThreadWatcher.db; - boardID = g.BOARD.ID; - db.forceSync(); - ref = db.data.boards[boardID]; - for (threadID in ref) { - data = ref[threadID]; - if (!(data != null ? data.isDead : void 0) && !(threadID in g.BOARD.threads)) { - if (Conf['Auto Prune'] || !(data && typeof data === 'object')) { - db["delete"]({ - boardID: boardID, - threadID: threadID - }); - } else { - if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { - ThreadWatcher.fetchStatus({ - boardID: boardID, - threadID: threadID, - data: data - }); - } - data.isDead = true; - 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); - } - }, - requests: [], - fetched: 0, - clearRequests: function() { - ThreadWatcher.requests = []; - ThreadWatcher.fetched = 0; - ThreadWatcher.status.textContent = ''; - return $.rmClass(ThreadWatcher.refreshButton, 'fa-spin'); - }, - abort: function() { - var k, len1, ref, req; - ref = ThreadWatcher.requests; - for (k = 0, len1 = ref.length; k < len1; k++) { - req = ref[k]; - if (req.readyState !== 4) { - req.abort(); - } - } - return ThreadWatcher.clearRequests(); - }, - fetchAuto: function() { - var db, interval, now; - clearTimeout(ThreadWatcher.timeout); - if (!Conf['Auto Update Thread Watcher']) { - return; - } - db = ThreadWatcher.db; - interval = ThreadWatcher.unreadEnabled && 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); - }, - buttonFetchAll: function() { - if (ThreadWatcher.requests.length) { - return ThreadWatcher.abort(); - } else { - return ThreadWatcher.fetchAllStatus(); - } - }, - fetchAllStatus: function() { - var k, len1, ref, thread, threads; - ThreadWatcher.db.forceSync(); - ThreadWatcher.unreaddb.forceSync(); - if ((ref = QuoteYou.db) != null) { - ref.forceSync(); - } - if (!(threads = ThreadWatcher.getAll()).length) { - return; - } - for (k = 0, len1 = threads.length; k < len1; k++) { - thread = threads[k]; - ThreadWatcher.fetchStatus(thread); - } - }, - fetchStatus: function(thread, force) { - var boardID, data, req, threadID; - boardID = thread.boardID, threadID = thread.threadID, data = thread.data; - if (data.isDead && !force) { - return; - } - if (ThreadWatcher.requests.length === 0) { - ThreadWatcher.status.textContent = '...'; - $.addClass(ThreadWatcher.refreshButton, 'fa-spin'); - } - req = $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", { - onloadend: function() { - return ThreadWatcher.parseStatus.call(this, thread); - }, - timeout: $.MINUTE - }, { - whenModified: force ? false : 'ThreadWatcher' - }); - return ThreadWatcher.requests.push(req); - }, - parseStatus: function(arg) { - var boardID, data, isDead, k, lastReadPost, len1, match, postObj, quotesYou, quotingYou, ref, ref1, regexp, threadID, unread; - boardID = arg.boardID, threadID = arg.threadID, data = arg.data; - ThreadWatcher.fetched++; - if (ThreadWatcher.fetched === ThreadWatcher.requests.length) { - ThreadWatcher.clearRequests(); - } else { - ThreadWatcher.status.textContent = (Math.round(ThreadWatcher.fetched / ThreadWatcher.requests.length * 100)) + "%"; - } - 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 (k = 0, len1 = ref.length; k < len1; k++) { - postObj = ref[k]; - if (!(postObj.no > lastReadPost)) { - continue; - } - if ((ref1 = QuoteYou.db) != null ? ref1.get({ - boardID: boardID, - threadID: threadID, - postID: postObj.no - }) : void 0) { - continue; - } - unread++; - if (!(QuoteYou.db && postObj.com)) { - continue; - } - quotesYou = false; - regexp = /]*\bhref="(?:\/([^\/]+)\/thread\/)?(\d+)?(?:#p(\d+))?"/g; - while (match = regexp.exec(postObj.com)) { - if (QuoteYou.db.get({ - boardID: match[1] || boardID, - threadID: match[2] || threadID, - postID: match[3] || match[2] || threadID - })) { - quotesYou = true; - break; - } - } - if (quotesYou && !Filter.isHidden(Build.parseJSON(postObj, boardID))) { - quotingYou++; - } - } - 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, ref, threadID, threads; - 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]; - if (data && typeof data === 'object') { - 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 (ThreadWatcher.unreadEnabled && 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 (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { - if (data.unread === 0) { - $.addClass(div, 'replies-read'); - } - 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, k, len1, len2, list, nodes, q, ref, ref1, ref2, refresher, threadID; - nodes = []; - ref = ThreadWatcher.getAll(); - for (k = 0, len1 = ref.length; k < len1; k++) { - ref1 = ref[k], 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, len2, post, q, ref2, toggler; - helper = ThreadWatcher.isWatched(thread) ? ['addClass', 'Unwatch'] : ['rmClass', 'Watch']; - if (thread.OP) { - ref2 = [thread.OP].concat(slice.call(thread.OP.clones)); - for (q = 0, len2 = ref2.length; q < len2; q++) { - post = ref2[q]; - 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 (q = 0, len2 = ref2.length; q < len2; q++) { - refresher = ref2[q]; - refresher(); - } - if (Index.nodes && Conf['Pin Watched Threads']) { - Index.sort(); - return Index.buildIndex(); - } - }, - refreshIcon: function() { - var className, k, len1, ref; - ref = ['replies-unread', 'replies-quoting-you']; - for (k = 0, len1 = ref.length; k < len1; k++) { - className = ref[k]; - ThreadWatcher.shortcut.classList.toggle(className, !!$("." + className, ThreadWatcher.dialog)); - } - }, - update: function(boardID, threadID, newData) { - var data, key, line, n, newLine, ref, val; - 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(); - } - }, - set404: function(boardID, threadID, cb) { - var data, ref; - if (!(data = (ref = ThreadWatcher.db) != null ? ref.get({ - boardID: boardID, - threadID: threadID - }) : void 0)) { - return cb(); - } - if (Conf['Auto Prune']) { - ThreadWatcher.db["delete"]({ - boardID: boardID, - threadID: threadID - }); - return cb(); - } - if (data.isDead && !((data.unread != null) || (data.quotingYou != null))) { - return cb(); - } - data.isDead = true; - delete data.unread; - delete data.quotingYou; - return ThreadWatcher.db.set({ - boardID: boardID, - threadID: threadID, - val: data - }, cb); - }, - 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 (ThreadWatcher.unreadEnabled && 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(); - }, - 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, ref, rmClass, text; - 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, k, len1, name, ref, ref1, refresh, subEntries; - 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 (k = 0, len1 = entries.length; k < len1; k++) { - ref1 = entries[k], 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; - if (name === 'Show Unread Count' && !ThreadWatcher.unreadEnabled) { - input.disabled = true; - $.addClass(entry.el, 'disabled'); - entry.el.title += '\n[Remember Last Read Post is disabled.]'; - } - $.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['Remember Last Read Post'] || Conf['Desktop Notifications'] || Conf['Quote Threading']))) { - return; - } - if (Conf['Remember Last Read Post']) { - $.sync('Remember Last Read Post', function(enabled) { - return Conf['Remember Last Read Post'] = enabled; - }); - 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, k, len1, ref, ref1; - Unread.thread = this; - Unread.title = d.title; - Unread.lastReadPost = ((ref = Unread.db) != null ? ref.get({ - boardID: this.board.ID, - threadID: this.ID - }) : void 0) || 0; - Unread.readCount = 0; - ref1 = this.posts.keys; - for (k = 0, len1 = ref1.length; k < len1; k++) { - ID = ref1[k]; - if (+ID <= Unread.lastReadPost) { - Unread.readCount++; - } - } - $.one(d, '4chanXInitFinished', Unread.ready); - return $.on(d, 'ThreadUpdate', Unread.onUpdate); - }, - ready: function() { - if (Conf['Remember Last Read Post'] && Conf['Scroll to Last Read Post']) { - Unread.scroll(); - } - Unread.setLine(true); - Unread.read(); - Unread.update(); - $.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, ref, root; - if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) { - return; - } - ReplyPruning.showIfHidden((ref = Unread.position) != null ? ref.data.nodes.root.id : void 0); - 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, k, lastReadPost, postIDs, 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 = k = ref = Unread.readCount, ref1 = postIDs.length; k < ref1; i = k += 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 = QuoteYou.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 k, len1, quotelink, ref, ref1; - ref = post.nodes.quotelinks; - for (k = 0, len1 = ref.length; k < len1; k++) { - quotelink = ref[k]; - if (!((ref1 = QuoteYou.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; - } - try { - notif = new Notification(post.info.nameBlock + " replied to you", { - body: post.info.commentDisplay, - icon: Favicon.logo - }); - notif.onclick = function() { - Header.scrollToIfNeeded(post.nodes.root, true); - return $.global(function() { - return window.focus(); - }); - }; - return notif.onshow = function() { - return setTimeout(function() { - return notif.close(); - }, 7 * $.SECOND); - }; - } catch (_error) {} - }, - 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, ref, ref1, root; - if (!Unread.posts.size && Unread.readCount !== Unread.thread.posts.keys.length) { - Unread.saveLastReadPost(); - } - if (d.hidden || !Unread.posts.size) { - return; - } - 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 ((ref1 = QuoteYou.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, k, postIDs, ref, ref1; - $.forceSync('Remember Last Read Post'); - if (!(Conf['Remember Last Read Post'] && Unread.db)) { - return; - } - postIDs = Unread.thread.posts.keys; - for (i = k = ref = Unread.readCount, ref1 = postIDs.length; k < ref1; i = k += 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 (Unread.hr.hidden || 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, isDead, 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; - } - $.forceSync('Remember Last Read Post'); - if (Conf['Remember Last Read Post'] && (!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']) { - isDead = Unread.thread.isDead; - Favicon.el.href = countQuotingYou ? Favicon[isDead ? 'unreadDeadY' : 'unreadY'] : count ? Favicon[isDead ? 'unreadDead' : 'unread'] : Favicon[isDead ? 'dead' : 'default']; - return $.add(d.head, Favicon.el); - } - } - }; - - Redirect = { - init: function() { - var archive, archives, boardID, boards, data, files, id, k, len1, len2, name, o, q, record, ref, ref1, software, type, uid, withCredentials; - o = { - thread: {}, - post: {}, - file: {}, - report: {} - }; - archives = {}; - ref = Redirect.archives; - for (k = 0, len1 = ref.length; k < len1; k++) { - data = ref[k]; - uid = data.uid, name = data.name, boards = data.boards, files = data.files, software = data.software, withCredentials = data.withCredentials; - archives[JSON.stringify(uid != null ? uid : name)] = data; - for (q = 0, len2 = boards.length; q < len2; q++) { - boardID = boards[q]; - if (!withCredentials) { - 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; - } - } - if (name === 'fgts') { - o.report[boardID] = data; - } - } - } - ref1 = Conf['selectedArchives']; - for (boardID in ref1) { - record = ref1[boardID]; - for (type in record) { - id = record[type]; - if (id === null) { - delete o[type][boardID]; - } else if (archive = archives[JSON.stringify(id)]) { - boards = type === 'file' ? archive.files : archive.boards; - if (indexOf.call(boards, boardID) >= 0) { - o[type][boardID] = archive; - } - } - } - } - return Redirect.data = o; - }, - archives: [{"uid":3,"name":"4plebs","domain":"archive.4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["adv","f","hr","o","pol","s4s","sp","tg","trv","tv","x"],"files":["adv","f","hr","o","pol","s4s","sp","tg","trv","tv","x"]},{"uid":4,"name":"Nyafuu Archive","domain":"archive.nyafuu.org","http":true,"https":true,"software":"foolfuuka","boards":["c","e","news","w","wg","wsr"],"files":["c","e","news","w","wg","wsr"]},{"uid":8,"name":"Rebecca Black Tech","domain":"rbt.asia","http":false,"https":true,"software":"fuuka","boards":["cgl","g","mu"],"files":["cgl","g","mu"]},{"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","b","cm","gd","h","hc","hm","n","out","p","po","qa","r","s","soc","toy","vp","y"],"files":["asp","b","cm","gd","h","hc","hm","n","out","p","po","qa","r","s","soc","toy","vp","y"]},{"uid":23,"name":"Desustorage","domain":"desustorage.org","http":true,"https":true,"software":"foolfuuka","boards":["a","aco","an","c","co","d","fit","gif","his","int","k","m","mlp","qa","r9k","tg","trash","vr","wsg"],"files":["a","aco","an","c","co","d","fit","gif","his","int","k","m","mlp","qa","r9k","tg","trash","vr","wsg"]},{"uid":24,"name":"fireden.net","domain":"boards.fireden.net","http":false,"https":true,"software":"foolfuuka","boards":["a","cm","ic","sci","tg","v","vg","y"],"files":["a","cm","ic","sci","tg","v","vg","y"]},{"uid":25,"name":"arch.b4k.co","domain":"arch.b4k.co","http":true,"https":true,"software":"foolfuuka","boards":["g","jp","mlp","v"],"files":[]},{"uid":5,"name":"Love is Over","domain":"deploy.loveisover.me","http":true,"https":false,"software":"foolfuuka","boards":["c","d","e","i","lgbt","t","u"],"files":["c","d","e","i","lgbt","t","u"],"search":[]},{"uid":28,"name":"bstats","domain":"archive.b-stats.org","http":true,"https":true,"software":"foolfuuka","boards":["f","cm","hm","lgbt","news","trash","y"],"files":[]}], - 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 boardID, postID, protocol, url; - boardID = arg.boardID, postID = arg.postID; - protocol = Redirect.protocol(archive); - url = "" + protocol + archive.domain + "/_/api/chan/post/?board=" + boardID + "&num=" + postID; - if (!Redirect.securityCheck(url)) { - return ''; - } - 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 === 'MD5' ? 'image' : type; - if (type === 'capcode') { - value = { - 'Developer': 'dev' - }[value] || value.toLowerCase(); - } else if (type === 'image') { - value = value.replace(/[+\/=]/g, function(c) { - return { - '+': '-', - '/': '_', - '=': '' - }[c]; - }); - } - value = encodeURIComponent(value); - path = archive.software === 'foolfuuka' ? boardID + "/search/" + type + "/" + value + "/" : type === 'image' ? boardID + "/image/" + value : boardID + "/?task=search2&search_" + type + "=" + value; - return "" + (Redirect.protocol(archive)) + archive.domain + "/" + path; - }, - report: function(archive, arg) { - var boardID, postID; - boardID = arg.boardID, postID = arg.postID; - return "https://so.fgts.jp/report/?board=" + boardID + "&no=" + postID; - }, - securityCheck: function(url) { - return /^https:\/\//.test(url) || location.protocol === 'http:' || Conf['Exempt Archives from Encryption']; - }, - navigate: function(dest, data, alternative) { - var url; - if (!Redirect.data) { - Redirect.init(); - } - url = Redirect.to(dest, data); - 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: "[Dismiss]" - }); - $.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() { - 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, k, len1, ref; - if (!Conf['Disable Autoplaying Sounds']) { - return; - } - $.addClass(doc, 'anti-autoplay'); - ref = $$('audio[autoplay]', doc); - for (k = 0, len1 = ref.length; k < len1; k++) { - audio = ref[k]; - 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, k, len1, len2, object, q, ref, ref1; - ref = $$('iframe[src*="youtube"][src*="autoplay=1"]', root); - for (k = 0, len1 = ref.length; k < len1; k++) { - iframe = ref[k]; - iframe.src = iframe.src.replace(/\?autoplay=1&?/, '?').replace('&autoplay=1', ''); - $.addClass(iframe, 'autoplay-removed'); - } - ref1 = $$('object[data*="youtube"][data*="autoplay=1"]', root); - for (q = 0, len2 = ref1.length; q < len2; q++) { - object = ref1[q]; - object.data = object.data.replace(/\?autoplay=1&?/, '?').replace('&autoplay=1', ''); - $.addClass(object, 'autoplay-removed'); - } - } - }; - - 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","79.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","256.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","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 base1, br, k, len1, name1, ref; - if (!(e.ctrlKey || e.metaKey)) { - return; - } - if ((base1 = Banner.original)[name1 = this.className] == null) { - base1[name1] = this.cloneNode(true); - } - this.contentEditable = true; - ref = $$('br', this); - for (k = 0, len1 = ref.length; k < len1; k++) { - br = ref[k]; - $.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, k, len1, ref; - ref = $$('br', this); - for (k = 0, len1 = ref.length; k < len1; k++) { - br = ref[k]; - $.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, k, len1, ref, string, string2; - className = child.className; - child.title = "Ctrl/\u2318+click to edit board " + (className.slice(5).toLowerCase()); - child.spellcheck = false; - ref = ['click', 'keydown', 'blur']; - for (k = 0, len1 = ref.length; k < len1; k++) { - event = ref[k]; - $.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 Index']) && !(Conf['JSON Index'] && 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, k, len1, link, ref; - ref = $$(selector); - for (k = 0, len1 = ref.length; k < len1; k++) { - link = ref[k]; - switch (link.pathname.replace(/\/+/g, '/')) { - case "/" + g.BOARD + "/": - if (Conf['JSON Index']) { - link.textContent = 'Index'; - } - link.href = CatalogLinks.index(); - break; - case "/" + g.BOARD + "/catalog": - link.href = CatalogLinks.catalog(); - } - if (g.VIEW === 'catalog' && Conf['JSON Index'] && 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 Index'] && 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, k, len1, m, ref; - ref = $$('a', this.nodes.comment); - for (k = 0, len1 = ref.length; k < len1; k++) { - a = ref[k]; - if (m = a.href.match(/^https?:\/\/boards\.4chan\.org\/([^\/]+)\/catalog(#s=.*)?/)) { - a.href = "//boards.4chan.org/" + m[1] + "/" + (m[2] || '#catalog'); - } - } - }, - initBoardList: function() { - if (!CatalogLinks.el) { - 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, k, len1, ref, ref1; - ref = $$('a:not([data-only])', Header.boardList).concat($$('a', Header.bottomBoardList)); - for (k = 0, len1 = ref.length; k < len1; k++) { - a = ref[k]; - if (((ref1 = a.hostname) !== 'boards.4chan.org' && ref1 !== 'catalog.neet.tv') || !(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 + "/"; - if (a.dataset.indexOptions && a.hostname === 'boards.4chan.org' && a.pathname.split('/')[2] === '') { - a.href += (a.hash ? '/' : '#') + a.dataset.indexOptions; - } - } - 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 Index'] && 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 Index'] && board !== 'f') { - 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', '#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 Index']) { - 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, k, len1, len2, len3, postObj, posts, q, quote, ref, ref1, spoilerRange, status, u; - 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 (k = 0, len1 = posts.length; k < len1; k++) { - postObj = posts[k]; - 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 (q = 0, len2 = ref.length; q < len2; q++) { - quote = ref[q]; - 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 (u = 0, len3 = ref1.length; u < len3; u++) { - callback = ref1[u]; - callback.call(post); - } - } - }; - - ExpandThread = { - statuses: {}, - init: function() { - if (g.VIEW === 'thread' || !Conf['Thread Expansion']) { - return; - } - if (Conf['JSON Index']) { - 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 = Build.summaryText.apply(Build, ['+'].concat(slice.call(a.textContent.match(/\d+/g)))); - a.style.cursor = 'pointer'; - return $.on(a, 'click', ExpandThread.cbToggle); - }, - disconnect: function(refresh) { - var ref, ref1, status, threadID; - 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); - }); - }, - 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); - } - }, - expand: function(thread, a) { - var status; - ExpandThread.statuses[thread] = status = {}; - a.textContent = Build.summaryText.apply(Build, ['...'].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, k, len1, num, postsCount, replies, reply, status; - status = ExpandThread.statuses[thread]; - delete ExpandThread.statuses[thread]; - if (status.req) { - status.req.abort(); - if (a) { - a.textContent = Build.summaryText.apply(Build, ['+'].concat(slice.call(a.textContent.match(/\d+/g)))); - } - return; - } - replies = $$('.thread > .replyContainer', threadRoot); - if (!Conf['JSON Index'] || 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 (k = 0, len1 = replies.length; k < len1; k++) { - reply = replies[k]; - if (Conf['Quote Inlining']) { - while (inlined = $('.inlined', reply)) { - inlined.click(); - } - } - postsCount++; - if ('file' in Get.postFromRoot(reply)) { - filesCount++; - } - $.rm(reply); - } - return a.textContent = Build.summaryText('+', postsCount, filesCount); - }, - parse: function(req, thread, a) { - var filesCount, k, len1, post, postData, posts, postsCount, postsRoot, ref, ref1, root; - 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 (k = 0, len1 = ref1.length; k < len1; k++) { - postData = ref1[k]; - 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 = Build.summaryText('-', 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() { - var info, oldInfo; - if (!this.file || this.isClone) { - return; - } - oldInfo = $.el('span', { - className: 'fileText-original' - }); - $.prepend(this.file.link.parentNode, oldInfo); - $.add(oldInfo, [this.file.link.previousSibling, this.file.link, this.file.link.nextSibling]); - info = $.el('span', { - className: 'file-info' - }); - FileInfo.format(Conf['fileInfo'], this, info); - return $.prepend(this.file.text, info); - }, - 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: E.cat(output) - }); - }, - formatters: { - t: function() { - return { - innerHTML: E(this.file.url.match(/[^/]*$/)[0]) - }; - }, - T: function() { - return { - innerHTML: "" + FileInfo.formatters.t.call(this).innerHTML + "" - }; - }, - l: function() { - return { - innerHTML: "" + FileInfo.formatters.n.call(this).innerHTML + "" - }; - }, - L: function() { - return { - innerHTML: "" + FileInfo.formatters.N.call(this).innerHTML + "" - }; - }, - 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: "" + E(shortname) + "" + E(fullname) + "" - }; - } - }, - N: function() { - return { - innerHTML: E(this.file.name) - }; - }, - p: function() { - return { - innerHTML: (this.file.isSpoiler ? "Spoiler, " : "") - }; - }, - 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") - }; - }, - g: function() { - return { - innerHTML: (this.file.tag ? ", " + E(this.file.tag) : "") - }; - }, - '%': function() { - return { - innerHTML: "%" - }; - } - } - }; - - Flash = { - init: function() { - if (g.BOARD.ID === 'f' && Conf['Enable Native Flash Embedding']) { - return $.ready(Flash.initReady); - } - }, - initReady: function() { - if ($.hasStorage) { - return $.global(function() { - if (JSON.parse(localStorage['4chan-settings'] || '{}').disableAll) { - return window.SWFEmbed.init(); - } - }); - } else { - if (g.VIEW === 'thread') { - $.global(function() { - return window.Main.tid = location.pathname.split(/\/+/)[3]; - }); - } - return $.global(function() { - return window.SWFEmbed.init(); - }); - } - } - }; - - Fourchan = { - init: function() { - var ref; - if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { - return; - } - if (g.BOARD.ID === 'g') { - $.on(window, 'prettyprint:cb', function(e) { - var post, pre; - if (!(post = g.posts[e.detail.ID])) { - return; - } - if (!(pre = $$('.prettyprint', post.nodes.comment)[e.detail.i])) { - return; - } - if (!$.hasClass(pre, 'prettyprinted')) { - pre.innerHTML = e.detail.html; - return $.addClass(pre, 'prettyprinted'); - } - }); - $.globalEval('window.addEventListener(\'prettyprint\', function(e) {\n window.dispatchEvent(new CustomEvent(\'prettyprint:cb\', {\n detail: {\n ID: e.detail.ID,\n i: e.detail.i,\n html: prettyPrintOne(e.detail.html)\n }\n }));\n}, false);'); - Post.callbacks.push({ - name: 'Parse /g/ code', - cb: this.code - }); - } - if (g.BOARD.ID === 'sci') { - $.global(function() { - return window.addEventListener('mathjax', function(e) { - if (window.MathJax) { - return window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub, e.target]); - } else { - if (!document.querySelector('script[src^="//cdn.mathjax.org/"]')) { - window.loadMathJax(); - window.loadMathJax = function() {}; - } - if (!e.target.classList.contains('postMessage')) { - return document.querySelector('script[src^="//cdn.mathjax.org/"]').addEventListener('load', function() { - return window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub, e.target]); - }, false); - } - } - }, 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 $.global(function() { - var k, len1, node, ref1; - window.clickable_ids = false; - ref1 = document.querySelectorAll('.posteruid, .capcode'); - for (k = 0, len1 = ref1.length; k < len1; k++) { - node = ref1[k]; - node.removeEventListener('click', window.idClick, false); - } - }); - }); - }, - code: function() { - if (this.isClone) { - return; - } - return $.ready((function(_this) { - return function() { - var i, k, len1, pre, ref; - ref = $$('.prettyprint', _this.nodes.comment); - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - pre = ref[i]; - if (!$.hasClass(pre, 'prettyprinted')) { - $.event('prettyprint', { - ID: _this.fullID, - i: i, - html: pre.innerHTML - }, window); - } - } - }; - })(this)); - }, - math: function() { - var cb, k, len1, wbr, wbrs; - if (!/\[(math|eqn)\]/.test(this.nodes.comment.textContent)) { - return; - } - if ((wbrs = $$('wbr', this.nodes.comment)).length) { - for (k = 0, len1 = wbrs.length; k < len1; k++) { - wbr = wbrs[k]; - $.rm(wbr); - } - this.nodes.comment.normalize(); - } - cb = (function(_this) { - return function() { - if (!doc.contains(_this.nodes.comment)) { - return; - } - $.off(d, 'PostsInserted', cb); - return $.event('mathjax', null, _this.nodes.comment); - }; - })(this); - $.on(d, 'PostsInserted', cb); - return cb(); - } - }; - - 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 Config.hotkeys) { - $.sync(hotkey, Keybinds.sync); - } - init = function() { - var k, len1, node, ref; - $.off(d, '4chanXInitFinished', init); - $.on(d, 'keydown', Keybinds.keydown); - ref = $$('[accesskey]'); - for (k = 0, len1 = ref.length; k < len1; k++) { - node = ref[k]; - node.removeAttribute('accesskey'); - } - }; - return $.on(d, '4chanXInitFinished', init); - }, - sync: function(key, hotkey) { - return Conf[hotkey] = key; - }, - keydown: function(e) { - var form, k, key, len1, notification, notifications, op, ref, ref1, ref2, ref3, ref4, ref5, searchInput, target, thread, threadRoot; - 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) && !/^Alt\+(\d|Up|Down|Left|Right)$/.test(key))) { - return; - } - } - if (!(((ref1 = g.VIEW) !== 'index' && ref1 !== 'thread') || g.VIEW === 'index' && Conf['JSON Index'] && Conf['Index Mode'] === 'catalog' || g.VIEW === 'index' && g.BOARD.ID === 'f')) { - 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 (k = 0, len1 = notifications.length; k < len1; k++) { - notification = notifications[k]; - $('.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['SJIS tags']: - if (target.nodeName !== 'TEXTAREA') { - return; - } - Keybinds.tags('sjis', 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 Index'] && g.BOARD.ID !== 'f')) { - return; - } - Index.update(); - break; - default: - return; - } - break; - case Conf['Watch']: - if (!(ThreadWatcher.enabled && thread)) { - return; - } - ThreadWatcher.toggle(thread); - break; - case Conf['Update thread watcher']: - if (!ThreadWatcher.enabled) { - return; - } - ThreadWatcher.buttonFetchAll(); - 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'))) { - return; - } - FappeTyme.toggle('fappe'); - break; - case Conf['werkTyme']: - if (!(Conf['Werk Tyme'] && ((ref3 = g.VIEW) === 'index' || ref3 === 'thread'))) { - return; - } - FappeTyme.toggle('werk'); - break; - case Conf['Front page']: - if (Conf['JSON Index'] && g.VIEW === 'index' && g.BOARD.ID !== 'f') { - 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' && g.BOARD.ID !== 'f')) { - return; - } - if (Conf['JSON Index']) { - 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' && g.BOARD.ID !== 'f')) { - return; - } - if (Conf['JSON Index']) { - 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' && g.BOARD.ID !== 'f')) { - return; - } - searchInput = Conf['JSON Index'] ? Index.searchInput : $.id('search-box'); - Header.scrollToIfNeeded(searchInput); - searchInput.focus(); - break; - case Conf['Paged mode']: - if (!(Conf['JSON Index'] && g.BOARD.ID !== 'f')) { - return; - } - window.location = g.VIEW === 'index' ? '#paged' : "/" + g.BOARD + "/#paged"; - break; - case Conf['Infinite scrolling mode']: - if (!(Conf['JSON Index'] && g.BOARD.ID !== 'f')) { - return; - } - window.location = g.VIEW === 'index' ? '#infinite' : "/" + g.BOARD + "/#infinite"; - break; - case Conf['All pages mode']: - if (!(Conf['JSON Index'] && g.BOARD.ID !== 'f')) { - return; - } - window.location = g.VIEW === 'index' ? '#all-pages' : "/" + g.BOARD + "/#all-pages"; - break; - case Conf['Open catalog']: - if (g.BOARD.ID === 'f') { - return; - } - window.location = CatalogLinks.catalog(); - break; - case Conf['Cycle sort type']: - if (!(Conf['JSON Index'] && g.VIEW === 'index' && g.BOARD.ID !== '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 && QuoteYou.db)) { - return; - } - QuoteYou.cb.seek('preceding'); - break; - case Conf['Next Post Quoting You']: - if (!(threadRoot && QuoteYou.db)) { - 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 32: - return 'Space'; - case 37: - return 'Left'; - case 38: - return 'Up'; - case 39: - return 'Right'; - case 40: - return 'Down'; - case 188: - return 'Comma'; - case 190: - return 'Period'; - case 191: - return 'Slash'; - case 59: - case 186: - return 'Semicolon'; - default: - if ((48 <= kc && kc <= 57) || (65 <= kc && kc <= 90)) { - return String.fromCharCode(kc).toLowerCase(); - } else if ((96 <= kc && kc <= 105)) { - return String.fromCharCode(kc - 48).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'; - case 'sjis': - return g.BOARD.ID === 'jp'; - } - })(); - 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, k, len1, next, postEl, replies, reply, root; - 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 (k = 0, len1 = replies.length; k < len1; k++) { - reply = replies[k]; - 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 k, len1, ref, thread, threadRoot; - ref = $$('.thread'); - for (k = 0, len1 = ref.length; k < len1; k++) { - threadRoot = ref[k]; - 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, ref, thread, top; - 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); - } - } - }; - - NormalizeURL = { - init: function() { - var pathname; - if (!Conf['Normalize URL']) { - return; - } - pathname = location.pathname.split(/\/+/); - switch (g.VIEW) { - case 'thread': - pathname[2] = 'thread'; - pathname = pathname.slice(0, 4); - break; - case 'index': - pathname = pathname.slice(0, 3); - } - pathname = pathname.join('/'); - if (location.pathname !== pathname) { - return history.replaceState(history.state, '', location.protocol + "//" + location.host + pathname + location.hash); - } - } - }; - - 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 Index'] && 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, k, len1, now, ref; - if (d.hidden) { - return; - } - now = new Date(); - ref = RelativeDates.stale; - for (k = 0, len1 = ref.length; k < len1; k++) { - data = ref[k]; - 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, k, len1, ref, relative, singlePost; - 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 (k = 0, len1 = ref.length; k < len1; k++) { - singlePost = ref[k]; - 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() { - return RemoveSpoilers.unspoiler(this.nodes.comment); - }, - unspoiler: function(el) { - var k, len1, span, spoiler, spoilers; - spoilers = $$('s', el); - for (k = 0, len1 = spoilers.length; k < len1; k++) { - spoiler = spoilers[k]; - span = $.el('span', { - className: 'removed-spoiler' - }); - $.replace(spoiler, span); - $.add(span, slice.call(spoiler.childNodes)); - } - } - }; - - Report = { - css: "#g-recaptcha,\n" + -":root:not(.js-enabled) #captchaContainerAlt {\n" + -" height: auto;\n" + -"}\n" + -"#captchaContainerAlt td:nth-child(2) {\n" + -" display: table-cell !important;\n" + -"}", - init: function() { - var match; - if (!(match = location.search.match(/\bno=(\d+)/))) { - return; - } - Captcha.replace.init(); - this.postID = +match[1]; - return $.ready(this.ready); - }, - ready: function() { - var passAd, prev, ref; - $.addStyle(Report.css); - if (Conf['Archive Report']) { - Report.archive(); - } - if ((passAd = $('a[href="https://www.4chan.org/pass"]'))) { - $.extend(passAd, { - textContent: 'Complain', - href: 'https://www.4chan-x.net/captchas.html', - tabIndex: -1 - }); - passAd.parentNode.normalize(); - if (((ref = (prev = passAd.previousSibling)) != null ? ref.nodeType : void 0) === Node.TEXT_NODE) { - prev.nodeValue = prev.nodeValue.replace(/4chan Pass[^\.]*\./i, 'reCAPTCHA malfunctioning?'); - } - $.after(passAd, [ - $.tn('] ['), $.el('a', { - href: 'mailto:4chanpass@4chan.org?subject=4chan%20Pass%20-%20Purchase%20Support', - textContent: 'Email 4chan', - target: '_blank', - tabIndex: -1 - }) - ]); - } - if (!Conf['Use Recaptcha v1 in Reports'] && !Conf['Force Noscript Captcha'] && Main.jsEnabled) { - return new MutationObserver(function() { - Report.fit('iframe[src^="https://www.google.com/recaptcha/api2/frame"]'); - return Report.fit('body'); - }).observe(d.body, { - childList: true, - attributes: true, - subtree: true - }); - } else { - return Report.fit('body'); - } - }, - fit: function(selector) { - var dy, el; - if (!((el = $(selector, doc)) && getComputedStyle(el).visibility !== 'hidden')) { - return; - } - dy = el.getBoundingClientRect().bottom - doc.clientHeight + 8; - if (dy > 0) { - return window.resizeBy(0, dy); - } - }, - archive: function() { - var link, message, types, url; - Redirect.init(); - if (!(url = Redirect.to('report', { - boardID: g.BOARD.ID, - postID: Report.postID - }))) { - return; - } - if ((message = $('h3')) && /Report submitted!/.test(message.textContent)) { - if (location.hash === '#redirect') { - $.globalEval('self.close = function(){};'); - window.resizeTo(700, 475); - location.replace(url); - } - return; - } - link = $.el('a', { - href: url, - textContent: 'Report to archive' - }); - $.on(link, 'click', function(e) { - if (!(e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0)) { - return window.resizeTo(700, 475); - } - }); - $.add(d.body, [$.tn(' ['), link, $.tn(']')]); - if (types = $.id('reportTypes')) { - return $.on(types, 'change', function(e) { - return $('form').action = e.target.value === 'illegal' ? '#redirect' : ''; - }); - } - } - }; - - ThreadLinks = { - init: function() { - if (!(g.VIEW === 'index' && Conf['Open Threads in New Tab'])) { - return; - } - Post.callbacks.push({ - name: 'Thread Links', - cb: this.node - }); - return CatalogThread.callbacks.push({ - name: 'Thread Links', - cb: this.catalogNode - }); - }, - node: function() { - if (this.isReply || this.isClone) { - return; - } - return ThreadLinks.process($('.replylink', this.nodes.info)); - }, - catalogNode: function() { - return ThreadLinks.process(this.nodes.thumb.parentNode); - }, - process: function(link) { - return link.target = '_blank'; - } - }; - - 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']) { - if ($.hasStorage) { - settings = JSON.parse(localStorage.getItem('4chan-settings')) || {}; - if (settings.disableAll) { - return; - } - settings.disableAll = true; - return localStorage.setItem('4chan-settings', JSON.stringify(settings)); - } else { - return $.onExists(doc, 'body', function() { - return $.global(function() { - return window.Config.disableAll = true; - }); - }); - } - } - }, - open: function(openSection) { - var dialog, k, len1, link, links, overlay, ref, section, sectionToOpen; - if (Settings.overlay) { - return; - } - $.event('CloseMenu'); - Settings.dialog = dialog = $.el('div', { - id: 'fourchanx-settings', - className: 'dialog' - }); - $.extend(dialog, { - innerHTML: "
          " - }); - 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 (k = 0, len1 = ref.length; k < len1; k++) { - section = ref[k]; - 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); - }, - warnings: { - localStorage: function(cb) { - var why; - if ($.cantSync) { - why = $.cantSet ? 'save your settings' : 'synchronize settings between tabs'; - return cb($.el('li', { - textContent: "4chan X needs local storage to " + why + ".\nEnable it on boards.4chan.org in your browser's privacy settings (may be listed as part of \"local data\" or \"cookies\")." - })); - } - }, - ads: function(cb) { - return $.onExists(doc, '.ad-cnt', function(ad) { - return $.onExists(ad, 'img', function() { - return cb($.el('li', { - innerHTML: "To protect yourself from malicious ads, you should block ads on 4chan." - })); - }); - }); - } - }, - main: function(section) { - var addWarning, arr, button, container, containers, description, div, fs, input, inputs, items, key, level, obj, ref, ref1, warning, warnings; - warnings = $.el('fieldset', { - hidden: true - }, { - innerHTML: "Warnings
            " - }); - addWarning = function(item) { - $.add($('ul', warnings), item); - return warnings.hidden = false; - }; - ref = Settings.warnings; - for (key in ref) { - warning = ref[key]; - warning(addWarning); - } - $.add(section, warnings); - items = {}; - inputs = {}; - ref1 = Config.main; - for (key in ref1) { - obj = ref1[key]; - fs = $.el('fieldset', { - innerHTML: "" + E(key) + "" - }); - containers = [fs]; - for (key in obj) { - arr = obj[key]; - description = arr[1]; - div = $.el('div', { - innerHTML: ": " + E(description) + "" - }); - if ($.engine !== 'gecko' && key === 'Remember QR Size') { - div.hidden = true; - } - 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: ": 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, ref2, ref3, thread; - hiddenThreads = arg.hiddenThreads, hiddenPosts = arg.hiddenPosts; - hiddenNum = 0; - ref2 = hiddenThreads.boards; - for (ID in ref2) { - board = ref2[ID]; - hiddenNum += Object.keys(board).length; - } - ref3 = hiddenPosts.boards; - for (ID in ref3) { - board = ref3[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; - if ($.hasStorage) { - 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) { - 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; - } - this.value = null; - 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 { - return Settings.loadSettings(JSON.parse(e.target.result), function(err) { - if (err) { - return output.textContent = 'Import failed due to an error.'; - } else 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); - }, - convertFrom: { - loadletter: function(data) { - var base1, boardID, convertSettings, key, ref, ref1, threadData, threadID, threads, val; - 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': 'Disable Native Extension', - 'Comment Auto-Expansion': '', - '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', - 'Current Page': 'Page Count in Stats', - 'Current Page Position': '', - 'Alternative captcha': 'Use Recaptcha v1', - 'Auto Submit': 'Post on Captcha Completion', - '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()); - }); - } - } - if (data.WatchedThreads) { - data.Conf['watchedThreads'] = { - boards: {} - }; - ref1 = data.WatchedThreads; - for (boardID in ref1) { - threads = ref1[boardID]; - for (threadID in threads) { - threadData = threads[threadID]; - ((base1 = data.Conf['watchedThreads'].boards)[boardID] || (base1[boardID] = {}))[threadID] = { - excerpt: threadData.textContent - }; - } - } - } - return data; - } - }, - upgrade: function(data, version) { - var boardID, changes, compareString, k, key, len1, name, record, ref, ref1, ref2, ref3, ref4, ref5, rice, set, type, uids, value; - changes = {}; - set = function(key, value) { - return data[key] = changes[key] = value; - }; - compareString = version.replace(/\d+/g, function(x) { - return ('0000' + x).slice(-5); - }); - if (compareString < '00001.00011.00008.00000') { - if (data['Fixed Thread Watcher'] == null) { - set('Fixed Thread Watcher', (ref = data['Toggleable Thread Watcher']) != null ? ref : true); - } - if (data['Exempt Archives from Encryption'] == null) { - set('Exempt Archives from Encryption', (ref1 = data['Except Archives from Encryption']) != null ? ref1 : false); - } - } - if (compareString < '00001.00011.00010.00001') { - if (data['selectedArchives'] != null) { - uids = { - "Moe": 0, - "4plebs Archive": 3, - "Nyafuu Archive": 4, - "Love is Over": 5, - "Rebecca Black Tech": 8, - "warosu": 10, - "fgts": 15, - "not4plebs": 22, - "DesuStorage": 23, - "fireden.net": 24, - "disabled": null - }; - ref2 = data['selectedArchives']; - for (boardID in ref2) { - record = ref2[boardID]; - for (type in record) { - name = record[type]; - if (name in uids) { - record[type] = uids[name]; - } - } - } - set('selectedArchives', data['selectedArchives']); - } - } - if (compareString < '00001.00011.00016.00000') { - if ((rice = Config['usercss'].match(/\/\* Board title rice \*\/(?:\n.+)*/)[0])) { - if ((data['usercss'] != null) && data['usercss'].indexOf(rice) < 0) { - set('usercss', rice + '\n\n' + data['usercss']); - } - } - } - if (compareString < '00001.00011.00017.00000') { - ref3 = ['Persistent QR', 'Color User IDs', 'Fappe Tyme', 'Werk Tyme', 'Highlight Posts Quoting You', 'Highlight Own Posts']; - for (k = 0, len1 = ref3.length; k < len1; k++) { - key = ref3[k]; - if (data[key] == null) { - set(key, key === 'Persistent QR'); - } - } - } - if (compareString < '00001.00011.00017.00006') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/^(#?\s*)http:\/\/iqdb\.org\//mg, '$1//iqdb.org/')); - } - } - if (compareString < '00001.00011.00019.00003' && !Settings.overlay) { - $.queueTask(function() { - return Settings.warnings.ads(function(item) { - return new Notice('warning', slice.call(item.childNodes)); - }); - }); - } - if (compareString < '00001.00011.00020.00003') { - ref4 = { - 'Inline Cross-thread Quotes Only': false, - 'Pass Link': true - }; - for (key in ref4) { - value = ref4[key]; - if (data[key] == null) { - set(key, value); - } - } - } - if (compareString < '00001.00011.00021.00003') { - if (data['Remember Your Posts'] == null) { - set('Remember Your Posts', (ref5 = data['Mark Quotes of You']) != null ? ref5 : true); - } - } - if (compareString < '00001.00011.00022.00000') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/^(#?\s*https:\/\/www\.google\.com\/searchbyimage\?image_url=%(?:IMG|URL))%3Fs\.jpg/mg, '$1')); - set('sauces', data['sauces'].replace(/^#?\s*https:\/\/www\.google\.com\/searchbyimage\?image_url=%(?:IMG|T?URL)(?=$|;)/mg, '$&&safe=off')); - } - } - if (compareString < '00001.00011.00022.00002') { - if ((data['Use Recaptcha v1 in Reports'] == null) && data['Use Recaptcha v1'] && !data['Use Recaptcha v2 in Reports']) { - set('Use Recaptcha v1 in Reports', true); - } - } - if (compareString < '00001.00011.00024.00000') { - if ((data['JSON Navigation'] != null) && (data['JSON Index'] == null)) { - set('JSON Index', data['JSON Navigation']); - } - } - if (compareString < '00001.00011.00026.00000') { - if ((data['Oekaki Links'] != null) && (data['Edit Link'] == null)) { - set('Edit Link', data['Oekaki Links']); - } - if (data['Inline Cross-thread Quotes Only'] == null) { - set('Inline Cross-thread Quotes Only', true); - } - } - if (compareString < '00001.00011.00030.00000') { - if (data['Quote Threading'] && (data['Thread Quotes'] == null)) { - set('Thread Quotes', true); - } - } - return changes; - }, - loadSettings: function(data, cb) { - if (data.version.split('.')[0] === '2') { - data = Settings.convertFrom.loadletter(data); - } else if (data.version !== g.VERSION) { - Settings.upgrade(data.Conf, data.version); - } - return $.clear(function(err) { - if (err) { - return cb(err); - } - return $.set(data.Conf, cb); - }); - }, - reset: function() { - if (confirm('Your current settings will be entirely wiped, are you sure?')) { - return $.clear(function(err) { - if (err) { - return $('.imp-exp-result').textContent = 'Import failed due to an error.'; - } else if (confirm('Reset successful. Reload now?')) { - return window.location.reload(); - } - }); - } - }, - filter: function(section) { - var select; - $.extend(section, { - innerHTML: "
            " - }); - select = $('select', section); - $.on(select, 'change', Settings.selectFilter); - return Settings.selectFilter.call(select); - }, - selectFilter: function() { - var div, name, ta; - div = this.nextElementSibling; - if ((name = this.value) !== 'guide') { - $.rmAll(div); - ta = $.el('textarea', { - name: name, - className: 'field', - spellcheck: false - }); - $.get(name, Conf[name], function(item) { - return ta.value = item[name]; - }); - $.on(ta, 'change', $.cb.value); - $.add(div, ta); - return; - } - $.extend(div, { - innerHTML: "
            Filter is disabled.

            Use regular expressions, one per line.
            Lines starting with a # will be ignored.
            For example, /weeaboo/i will filter posts containing the string \`weeaboo\`, case-insensitive.
            MD5 filtering uses exact string matching, not regular expressions.

              You can use these settings with each regular expression, separate them with semicolons:
            • Per boards, separate them with commas. It is global if not specified.
              For example: boards:a,jp;.
            • In case of a global rule, select boards to be excluded from the filter.
              For example: exclude:vg,v;.
            • Filter OPs only along with their threads (\`only\`), replies only (\`no\`), or both (\`yes\`, this is default).
              For example: op:only;, op:no; or op:yes;.
            • Overrule the \`Show Stubs\` setting if specified: create a stub (\`yes\`) or not (\`no\`).
              For example: stub:yes; or stub:no;.
            • Highlight instead of hiding. You can specify a class name to use with a userstyle.
              For example: highlight; or highlight:wallpaper;.
            • Highlighted OPs will have their threads put on top of the board index by default.
              For example: top:yes; or top:no;.

            Note: If you're using the native catalog rather than 4chan X's catalog, 4chan X's filters do not apply there.
            The native catalog has its own separate filter list.

            " - }); - return $('.warning', div).hidden = Conf['Filter']; - }, - sauce: function(section) { - var ta; - $.extend(section, { - innerHTML: "
            Sauce is disabled.
            Lines starting with a # will be ignored.
            You can specify a display text by appending ;text:[text] to the URL.
            You can specify the applicable boards by appending ;boards:[board1],[board2].
            You can specify the applicable file types by appending ;types:[extension1],[extension2].
            You can open links with scripts and popups disabled by appending ;sandbox.
              These parameters will be replaced by their corresponding values:
            • %TURL: Thumbnail URL.
            • %URL: Full image URL.
            • %IMG: Full image URL for GIF, JPG, and PNG; thumbnail URL for other types.
            • %MD5: MD5 hash in base64.
            • %sMD5: MD5 hash in base64 using - and _.
            • %hMD5: MD5 hash in hexadecimal.
            • %name: Original file name.
            • %board: Current board.
            • %%, %semi: Literal % and ;.
            " - }); - $('.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 aa, ab, applyCSS, archBoards, archive, boardID, boardOptions, boardSelect, boards, customCSS, files, i, input, inputs, interval, item, items, k, len1, len2, len3, len4, len5, len6, len7, name, o, q, ref, ref1, ref2, ref3, ref4, ref5, ref6, row, rows, software, ta, table, u, uid, v, warning, withCredentials, z; - $.extend(section, { - innerHTML: "
            Archiver
            404 Redirect is disabled.
            Thread redirectionPost fetchingFile redirection
            Captcha Language
            Choose from list of language codes. Leave blank to autoselect.
            Custom Board Navigation
            New lines will be converted into spaces.

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

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

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

              You can use these settings with each item, separate them with semicolons:
            • Possible items are: name, options (or equivalently email), subject and password.
            • Wrap values of items with quotes, like this: options:"sage".
            • Force values as defaults with the always keyword, for example: options:"sage";always.
            • Select specific boards for an item, separated with commas, for example: options:"sage";boards:jp;always.
            Unread Favicon is disabled.
            Thread Updater is disabled.
            Interval: seconds
            Custom Cooldown Time
            Seconds:
            " - }); - ref = $$('.warning', section); - for (k = 0, len1 = ref.length; k < len1; k++) { - warning = ref[k]; - warning.hidden = Conf[warning.dataset.feature]; - } - items = {}; - inputs = {}; - ref1 = ['captchaLanguage', 'boardnav', 'time', 'backlink', 'fileInfo', 'favicon', 'usercss', 'customCooldown']; - for (q = 0, len2 = ref1.length; q < len2; q++) { - name = ref1[q]; - 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); - if (name in Settings) { - $.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 in Settings && key !== 'usercss') { - 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 (u = 0, len3 = ref2.length; u < len3; u++) { - ref3 = ref2[u], uid = ref3.uid, name = ref3.name, boards = ref3.boards, files = ref3.files, software = ref3.software, withCredentials = ref3.withCredentials; - for (v = 0, len4 = boards.length; v < len4; v++) { - boardID = boards[v]; - o = archBoards[boardID] || (archBoards[boardID] = { - thread: [[], []], - post: [[], []], - file: [[], []] - }); - i = +(!!withCredentials); - archive = [uid != null ? uid : name, name]; - o.thread[i].push(archive); - if (software === 'foolfuuka') { - o.post[i].push(archive); - } - if (indexOf.call(files, boardID) >= 0) { - o.file[i].push(archive); - } - } - } - for (boardID in archBoards) { - o = archBoards[boardID]; - ref4 = ['thread', 'post', 'file']; - for (z = 0, len5 = ref4.length; z < len5; z++) { - item = ref4[z]; - i = o[item][0].length ? 1 : 0; - o[item][i].push([null, 'disabled']); - o[item] = o[item][0].concat(o[item][1]); - } - } - rows = []; - boardOptions = []; - ref5 = Object.keys(archBoards).sort(); - for (aa = 0, len6 = ref5.length; aa < len6; aa++) { - boardID = ref5[aa]; - 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 (ab = 0, len7 = ref6.length; ab < len7; ab++) { - item = ref6[ab]; - $.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, id, select, selectedArchives, type; - selectedArchives = arg.selectedArchives; - for (boardID in selectedArchives) { - data = selectedArchives[boardID]; - for (type in data) { - id = data[type]; - if (select = $("select[data-boardid='" + boardID + "'][data-type='" + type + "']", section)) { - select.value = JSON.stringify(id); - } - } - } - }); - }, - 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', { - value: JSON.stringify(archive[0]), - textContent: archive[1] - })); - } - $.extend(td, { - innerHTML: "" - }); - select = td.firstElementChild; - if (!(select.disabled = length === 1)) { - select.setAttribute('data-boardid', boardID); - select.setAttribute('data-type', type); - $.on(select, 'change', Settings.saveSelectedArchive); - } - $.add(select, options); - return td; - }, - saveSelectedArchive: function() { - return $.get('selectedArchives', Conf['selectedArchives'], (function(_this) { - return function(arg) { - var name1, selectedArchives; - selectedArchives = arg.selectedArchives; - (selectedArchives[name1 = _this.dataset.boardid] || (selectedArchives[name1] = {}))[_this.dataset.type] = JSON.parse(_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, - isVideo: false, - isSpoiler: true, - tag: 'Loop' - } - }; - 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, ref, tbody, tr; - $.extend(section, { - innerHTML: "
            Keybinds are disabled.
            Allowed keys: a-z, 0-9, Ctrl, Shift, Alt, Meta, Enter, Esc, Up, Down, Right, Left.
            Press Backspace to disable a keybind.
            ActionsKeybinds
            " - }); - $('.warning', section).hidden = Conf['Keybinds']; - tbody = $('tbody', section); - items = {}; - inputs = {}; - ref = Config.hotkeys; - for (key in ref) { - arr = ref[key]; - tr = $.el('tr', { - innerHTML: "" + E(arr[1]) + "" - }); - input = $('input', tr); - input.name = key; - input.spellcheck = false; - items[key] = Conf[key]; - inputs[key] = input; - $.on(input, 'keydown', Settings.keybind); - $.add(tbody, tr); - } - return $.get(items, function(items) { - var val; - for (key in items) { - val = items[key]; - inputs[key].value = val; - } - }); - }, - keybind: function(e) { - var key; - if (e.keyCode === 9) { - return; - } - e.preventDefault(); - e.stopPropagation(); - if ((key = Keybinds.keyCode(e)) == null) { - return; - } - this.value = key; - return $.cb.value.call(this); - } - }; - - Main = { - init: function() { - var db, flatten, items, k, key, len1, ref; - if (d.body && !$('title', d.head)) { - return; - } - if (window['4chan X antidup']) { - return; - } - window['4chan X antidup'] = true; - if (location.hostname === 'www.google.com') { - $.get('Captcha Fixes', true, function(arg) { - var enabled; - enabled = arg['Captcha Fixes']; - if (enabled) { - return $.ready(function() { - return Captcha.fixes.init(); - }); - } - }); - return; - } - $.global(function() { - var k, len1, nuke, prop, ref; - nuke = function(obj, prop) { - try { - return Object.defineProperty(obj, prop, { - configurable: false, - get: function() { - throw new Error(); - }, - set: function() { - throw new Error(); - } - }); - } catch (_error) {} - }; - ref = ['atOptions', 'adsterra_key', 'EpmadsConfig', 'epmads_key', 'EpomConfig', 'epom_key', 'exoDocumentProtocol']; - for (k = 0, len1 = ref.length; k < len1; k++) { - prop = ref[k]; - nuke(window, prop); - } - }); - $.on(window, 'beforescriptexecute', function(e) { - var host, ref, ref1; - host = (ref = e.target.src.split('/')[2]) != null ? (ref1 = ref.match(/[^.]+\.[^.]+$/)) != null ? ref1[0] : void 0 : void 0; - if (host === 'bnhtml.com' || host === 'ecpmrocks.com' || host === 'advertisation.com' || host === 'exoclick.com') { - return e.preventDefault(); - } - }); - $.on(d, '4chanXInitFinished', function() { - if (Main.expectInitFinished) { - return delete Main.expectInitFinished; - } else { - new Notice('error', 'Error: Multiple copies of 4chan X are enabled.'); - return $.addClass(doc, 'tainted'); - } - }); - 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); - ref = DataBoard.keys; - for (k = 0, len1 = ref.length; k < len1; k++) { - db = ref[k]; - Conf[db] = { - boards: {} - }; - } - Conf['selectedArchives'] = {}; - Conf['cooldowns'] = {}; - Conf['Index Sort'] = {}; - Conf['Except Archives from Encryption'] = false; - Conf['JSON Navigation'] = true; - Conf['Oekaki Links'] = true; - items = {}; - for (key in Conf) { - items[key] = void 0; - } - items['previousversion'] = void 0; - return $.get(items, function(items) { - return $.asap((function() { - return doc = d.documentElement; - }), function() { - var ref1, val; - if ($.cantSet) { - - } else if (items.previousversion == null) { - Main.ready(function() { - $.set('previousversion', g.VERSION); - return Settings.open(); - }); - } else if (items.previousversion !== g.VERSION) { - Main.upgrade(items); - } - for (key in Conf) { - val = Conf[key]; - Conf[key] = (ref1 = items[key]) != null ? ref1 : val; - } - return Main.initFeatures(); - }); - }); - }, - upgrade: function(items) { - var changes, previousversion; - previousversion = items.previousversion; - changes = Settings.upgrade(items, previousversion); - items.previousversion = changes.previousversion = g.VERSION; - return $.set(changes, function() { - var el, ref; - if ((ref = items['Show Updated Notifications']) != null ? ref : true) { - el = $.el('span', { - innerHTML: "4chan X has been updated to version " + E(g.VERSION) + "." - }); - return new Notice('info', el, 15); - } - }); - }, - initFeatures: function() { - var err, feature, hostname, k, len1, match, name, pathname, ref, ref1, ref2, ref3, search; - hostname = location.hostname, search = location.search; - pathname = location.pathname.split(/\/+/); - if (hostname !== 'www.4chan.org') { - g.BOARD = new Board(pathname[1]); - } - if (hostname === 'boards.4chan.org' || hostname === 'sys.4chan.org' || hostname === 'www.4chan.org') { - $.global(function() { - document.documentElement.classList.add('js-enabled'); - return window.FCX = {}; - }); - Main.jsEnabled = $.hasClass(doc, 'js-enabled'); - } - switch (hostname) { - case 'www.4chan.org': - $.onExists(doc, 'body', function() { - return $.addStyle(Main.cssWWW); - }); - Captcha.replace.init(); - return; - case 'sys.4chan.org': - if (pathname[2] === 'imgboard.php') { - if (/\bmode=report\b/.test(search)) { - Report.init(); - } else if ((match = search.match(/\bres=(\d+)/))) { - $.ready(function() { - var ref; - if (Conf['404 Redirect'] && ((ref = $.id('errmsg')) != null ? ref.textContent : void 0) === 'Error: Specified thread does not exist.') { - return Redirect.navigate('thread', { - boardID: g.BOARD.ID, - postID: +match[1] - }); - } - }); - } - } else if (pathname[2] === 'post') { - PostSuccessful.init(); - } - return; - case 'i.4cdn.org': - if (!(pathname[2] && !/s\.jpg$/.test(pathname[2]))) { - return; - } - $.asap((function() { - return d.readyState !== 'loading'; - }), function() { - var ref, video; - if (Conf['404 Redirect'] && ((ref = d.title) === '4chan - Temporarily Offline' || ref === '4chan - 404 Not Found')) { - return Redirect.navigate('file', { - boardID: g.BOARD.ID, - filename: pathname[pathname.length - 1] - }); - } 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 ((ref = pathname[2]) === 'thread' || ref === 'res') { - g.VIEW = 'thread'; - g.THREADID = +pathname[3]; - } else if ((ref1 = pathname[2]) === 'catalog' || ref1 === 'archive') { - g.VIEW = pathname[2]; - } else if (pathname[2].match(/^\d*$/)) { - g.VIEW = 'index'; - } else { - return; - } - g.threads = new SimpleDict(); - g.posts = new SimpleDict(); - $.onExists(doc, 'body', Main.initStyle); - ref2 = Main.features; - for (k = 0, len1 = ref2.length; k < len1; k++) { - ref3 = ref2[k], name = ref3[0], feature = ref3[1]; - try { - feature.init(); - } catch (_error) { - err = _error; - Main.handleErrors({ - message: "\"" + name + "\" initialization crashed.", - error: err - }); - } - } - return $.ready(Main.initReady); - }, - initStyle: function() { - var keyboard, ref; - if (!Main.isThisPageLegit()) { - 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); - if ($.engine) { - $.addClass(doc, $.engine); - } - $.onExists(doc, '.ad-cnt', function(ad) { - return $.onExists(ad, 'img', function() { - return $.addClass(doc, 'ads-loaded'); - }); - }); - if (Conf['Autohiding Scrollbar']) { - $.addClass(doc, 'autohiding-scrollbar'); - } - $.ready(function() { - if (d.body.clientHeight > doc.clientHeight && (window.innerWidth === doc.clientWidth) !== Conf['Autohiding Scrollbar']) { - Conf['Autohiding Scrollbar'] = !Conf['Autohiding Scrollbar']; - $.set('Autohiding Scrollbar', Conf['Autohiding Scrollbar']); - return $.toggleClass(doc, 'autohiding-scrollbar'); - } - }); - $.addStyle(Main.css, 'fourchanx-css'); - Main.bgColorStyle = $.el('style', { - id: 'fourchanx-bgcolor-css' - }); - keyboard = false; - $.on(d, 'mousedown', function() { - return keyboard = false; - }); - $.on(d, 'keydown', function(e) { - if (e.keyCode === 9) { - return keyboard = true; - } - }); - window.addEventListener('focus', (function() { - return doc.classList.toggle('keyboard-focus', keyboard); - }), true); - 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 bgColor, div, k, len1, styleSheet; - $.rmClass(doc, style); - style = null; - for (k = 0, len1 = styleSheets.length; k < len1; k++) { - styleSheet = styleSheets[k]; - if (styleSheet.href === (mainStyleSheet != null ? mainStyleSheet.href : void 0)) { - style = styleSheet.title.toLowerCase().replace('new', '').trim().replace(/\s+/g, '-'); - break; - } - } - if (style) { - $.addClass(doc, style); - return $.rm(Main.bgColorStyle); - } else { - div = $.el('div', { - className: 'reply' - }); - div.style.cssText = 'position: absolute; visibility: hidden;'; - $.add(d.body, div); - bgColor = window.getComputedStyle(div).backgroundColor; - $.rm(div); - Main.bgColorStyle.textContent = ".dialog, .suboption-list > div:last-of-type {\n background-color: " + bgColor + ";\n}"; - return $.after($.id('fourchanx-css'), Main.bgColorStyle); - } - }; - setStyle(); - if (!mainStyleSheet) { - return; - } - return new MutationObserver(setStyle).observe(mainStyleSheet, { - attributes: true, - attributeFilter: ['href'] - }); - }, - initReady: function() { - var msg, ref, ref1, ref2; - if (g.VIEW === 'thread' && (((ref = d.title) === '4chan - Temporarily Offline' || ref === '4chan - 404 Not Found') || ($('.board') && !$('.opContainer')))) { - ThreadWatcher.set404(g.BOARD.ID, g.THREADID, function() { - if (Conf['404 Redirect']) { - return Redirect.navigate('thread', { - boardID: g.BOARD.ID, - threadID: g.THREADID, - postID: +location.hash.match(/\d+/) - }, "/" + g.BOARD + "/"); - } - }); - return; - } - if ((ref1 = d.title) === '4chan - Temporarily Offline' || ref1 === '4chan - 404 Not Found') { - return; - } - if (((ref2 = g.VIEW) === 'index' || ref2 === 'thread') && !$('.board + *')) { - msg = $.el('div', { - innerHTML: "The page didn't load completely.
            Some features may not work unless you reload." - }); - $.on($('a', msg), 'click', function() { - return location.reload(); - }); - new Notice('warning', msg); - } - if (!(Conf['JSON Index'] && g.VIEW === 'index')) { - return Main.initThread(); - } else { - Main.expectInitFinished = true; - return $.event('4chanXInitFinished'); - } - }, - initThread: function() { - var board, err, errors, k, len1, len2, m, postRoot, posts, q, ref, ref1, scriptData, thread, threadRoot, threads; - if ((board = $('.board'))) { - threads = []; - posts = []; - ref = $$('.board > .thread', board); - for (k = 0, len1 = ref.length; k < len1; k++) { - threadRoot = ref[k]; - thread = new Thread(+threadRoot.id.slice(1), g.BOARD); - threads.push(thread); - ref1 = $$('.thread > .postContainer', threadRoot); - for (q = 0, len2 = ref1.length; q < len2; q++) { - postRoot = ref1[q]; - if ($('.postMessage', postRoot)) { - 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 len3, post, u; - for (u = 0, len3 = posts.length; u < len3; u++) { - post = posts[u]; - QuoteThreading.insert(post); - } - Main.expectInitFinished = true; - return $.event('4chanXInitFinished'); - }); - } else { - Main.expectInitFinished = true; - 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, k, len1, logs; - if (!(errors instanceof Array)) { - error = errors; - } else if (errors.length === 1) { - error = errors[0]; - } - if (error) { - new Notice('error', Main.parseError(error, Main.reportLink([error])), 15); - return; - } - div = $.el('div', { - innerHTML: E(errors.length) + " errors occurred." + Main.reportLink(errors).innerHTML + " [show]" - }); - $.on(div.lastElementChild, 'click', function() { - var ref; - return ref = this.textContent === 'show' ? ['hide', false] : ['show', true], this.textContent = ref[0], logs.hidden = ref[1], ref; - }); - logs = $.el('div', { - hidden: true - }); - for (k = 0, len1 = errors.length; k < len1; k++) { - error = errors[k]; - $.add(logs, Main.parseError(error)); - } - return new Notice('error', [div, logs], 30); - }, - parseError: function(data, reportLink) { - var context, error, lines, message, ref, ref1; - c.error(data.message, data.error.stack); - message = $.el('div', { - innerHTML: E(data.message) + (reportLink ? reportLink.innerHTML : "") - }); - error = $.el('div', { - textContent: (data.error.name || 'Error') + ": " + (data.error.message || 'see console for details') - }); - lines = ((ref = data.error.stack) != null ? (ref1 = ref.match(/\d+(?=:\d+\)?$)/mg)) != null ? ref1.join().replace(/^/, ' at ') : void 0 : void 0) || ''; - context = $.el('div', { - textContent: "(4chan X ccd0 v" + g.VERSION + " userscript on " + $.engine + lines + ")" - }); - return [message, error, context]; - }, - reportLink: function(errors) { - var data, details, ref, title, url; - data = errors[0]; - title = data.message; - if (errors.length > 1) { - title += " (+" + (errors.length - 1) + " other errors)"; - } - details = "[Please describe the steps needed to reproduce this error.]\n\nScript: 4chan X ccd0 v" + g.VERSION + " userscript\nUser agent: " + navigator.userAgent + "\nURL: " + location.href + "\n\n" + data.error + "\n" + (((ref = data.error.stack) != null ? ref.replace(data.error.toString(), '').trim() : void 0) || ''); - details = details.replace(/file:\/{3}.+\//g, ''); - url = "https://gitreports.com/issue/ccd0/4chan-x?issue_title=" + (encodeURIComponent(title)) + "&details=" + (encodeURIComponent(details)); - return { - innerHTML: " [report]" - }; - }, - 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: "/*!\n" + -" * Font Awesome 4.5.0 by @davegandy - http://fontawesome.io - @fontawesome\n" + +boards: +"/*!\n" + +" * Font Awesome 4.6.1 by @davegandy - http://fontawesome.io - @fontawesome\n" + " * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)\n" + " */\n" + "@font-face {\n" + " font-family: FontAwesome;\n" + -" src: url('data:application/font-woff;base64,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') format('woff');\n" + +" src: url('data:application/font-woff;base64,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') format('woff');\n" + " font-weight: 400;\n" + " font-style: normal;\n" + "}\n" + -".fa::before {\n" + -" font-family: FontAwesome;\n" + -" font-weight: 400;\n" + -" font-style: normal;\n" + -" -webkit-font-smoothing: antialiased;\n" + -" text-decoration: inherit;\n" + -" speak: none;\n" + -" display: inline-block;\n" + -" font-size: 13px;\n" + -" visibility: visible;\n" + -"}\n" + -":root:not(.shortcut-icons) #shortcuts .fa::before {\n" + -" display: none;\n" + -"}\n" + -":root.shortcut-icons #shortcuts .fa::before {\n" + -" font-size: 15px !important;\n" + -" margin-top: -3px !important;\n" + -" position: relative;\n" + -" top: 1px;\n" + -"}\n" + -":root.shortcut-icons #shortcuts .fa, .menu-button .fa {\n" + -" font-size: 0;\n" + -" visibility: hidden;\n" + -"}\n" + -":root.shortcut-icons .shortcut.brackets-wrap::after,\n" + -":root.shortcut-icons .shortcut.brackets-wrap::before {\n" + -" display: none;\n" + -"}\n" + -":root.shortcut-icons #shortcuts a .fa,\n" + -".menu-button .fa,\n" + -".hide-reply-button .fa,\n" + -".hide-thread-button .fa {\n" + -" display: inline;\n" + -"}\n" + ".fa-glass:before {content: \"\\f000\";}\n" + ".fa-music:before {content: \"\\f001\";}\n" + ".fa-search:before {content: \"\\f002\";}\n" + @@ -19237,6 +1099,63 @@ ".fa-bluetooth:before {content: \"\\f293\";}\n" + ".fa-bluetooth-b:before {content: \"\\f294\";}\n" + ".fa-percent:before {content: \"\\f295\";}\n" + +".fa-gitlab:before {content: \"\\f296\";}\n" + +".fa-wpbeginner:before {content: \"\\f297\";}\n" + +".fa-wpforms:before {content: \"\\f298\";}\n" + +".fa-envira:before {content: \"\\f299\";}\n" + +".fa-universal-access:before {content: \"\\f29a\";}\n" + +".fa-wheelchair-alt:before {content: \"\\f29b\";}\n" + +".fa-question-circle-o:before {content: \"\\f29c\";}\n" + +".fa-blind:before {content: \"\\f29d\";}\n" + +".fa-audio-description:before {content: \"\\f29e\";}\n" + +".fa-volume-control-phone:before {content: \"\\f2a0\";}\n" + +".fa-braille:before {content: \"\\f2a1\";}\n" + +".fa-assistive-listening-systems:before {content: \"\\f2a2\";}\n" + +".fa-asl-interpreting:before, .fa-american-sign-language-interpreting:before {content: \"\\f2a3\";}\n" + +".fa-deafness:before, .fa-hard-of-hearing:before, .fa-deaf:before {content: \"\\f2a4\";}\n" + +".fa-glide:before {content: \"\\f2a5\";}\n" + +".fa-glide-g:before {content: \"\\f2a6\";}\n" + +".fa-signing:before, .fa-sign-language:before {content: \"\\f2a7\";}\n" + +".fa-low-vision:before {content: \"\\f2a8\";}\n" + +".fa-viadeo:before {content: \"\\f2a9\";}\n" + +".fa-viadeo-square:before {content: \"\\f2aa\";}\n" + +".fa-snapchat:before {content: \"\\f2ab\";}\n" + +".fa-snapchat-ghost:before {content: \"\\f2ac\";}\n" + +".fa-snapchat-square:before {content: \"\\f2ad\";}\n" + +".fa::before {\n" + +" font-family: FontAwesome;\n" + +" font-weight: 400;\n" + +" font-style: normal;\n" + +" -webkit-font-smoothing: antialiased;\n" + +" text-decoration: inherit;\n" + +" speak: none;\n" + +" display: inline-block;\n" + +" font-size: 13px;\n" + +" visibility: visible;\n" + +"}\n" + +":root:not(.shortcut-icons) #shortcuts .fa::before {\n" + +" display: none;\n" + +"}\n" + +":root.shortcut-icons #shortcuts .fa::before {\n" + +" font-size: 15px !important;\n" + +" margin-top: -3px !important;\n" + +" position: relative;\n" + +" top: 1px;\n" + +"}\n" + +":root.shortcut-icons #shortcuts .fa, .menu-button .fa {\n" + +" font-size: 0;\n" + +" visibility: hidden;\n" + +"}\n" + +":root.shortcut-icons .shortcut.brackets-wrap::after,\n" + +":root.shortcut-icons .shortcut.brackets-wrap::before {\n" + +" display: none;\n" + +"}\n" + +":root.shortcut-icons #shortcuts a .fa,\n" + +".menu-button .fa,\n" + +".hide-reply-button .fa,\n" + +".hide-thread-button .fa {\n" + +" display: inline;\n" + +"}\n" + ".fa-spin::before {\n" + " -webkit-animation:spin 2s infinite linear;\n" + " -moz-animation:spin 2s infinite linear;\n" + @@ -20093,7 +2012,7 @@ ":root.float #updater {\n" + " padding: 0px 3px;\n" + "}\n" + -":root:not(.float) #updater {\n" + +":root:not(.float).shortcut-icons #updater {\n" + " display: inline-block;\n" + " min-width: 12pt;\n" + " text-align: right;\n" + @@ -21046,75 +2965,6 @@ ".boardSubtitle[contenteditable=\"true\"] {\n" + " cursor: text !important;\n" + "}\n" + -"/* Link Title Favicons */\n" + -".linkify.audio {\n" + -" 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;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.clyp {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAwUExURTSY22ey5E2l4KbS75rM7Y3F64C/6f///8zl9nS45r/f9PL5/UGe3bPY8Vqr4v///wNjrzUAAAABYktHRA8YugDZAAAAB3RJTUUH4AINEi85AIH95AAAAE9JREFUCNdjYMAGGBWgDGYHCM2a3hkAZmi0dzSBaKaO9o5moCqmLiCjYzNQyw4QowIodQzI6E0AKcpo72gE6+Jyb1kAMehUA9RktgdYbQYAjGIVNGGXBJkAAAAASUVORK5CYII=') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.dailymotion {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAnUExURQBk3ff6/trp+kKO5wZt3xx54q7P9Ozz/IS17zOG5WKh653E8sbc9/GbbcoAAABZSURBVAjXY2BAASyhDhAGc9oECMOjyAAiESEEYrBYpLWBGcwHxcvBjDDxHelghpF0yDQwY3kVgweEUeEQDWbMEepqAjO8FMsLIeYsU8o+BrbCdWboTAe4AwALXxWGjW41FwAAAABJRU5ErkJggg==') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.gfycat {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAjVBMVEWn3gCo3gSr3w2t4BSu4Bav4Ri35C+45DK45DO55DXA50rA50vB50zC6E/D6FTF6VjG6VvL62vN7G/P7XbQ7XfW74vY8JDa8ZTe8qDe8qLf86Pi9Kzj9K7k9LHp9sDp98Lq98Ps+Mr0++L5/O75/fD6/fH6/fL6/fP7/fT7/fb8/ff8/vj8/vn+/v7///91X4cfAAAAcklEQVR42o3M2xKBUACF4aVQckrIuRJK6H//x2sme4/MuPDfre9i6c/Cc3U5Dj87BuAxsXvGu6JvIIXEHRWwNHCHQNrCzkAFkbSBg4EM8i+Yw7PXBa3zRfuxVyf/Bis7nKwGKAcWxgC8prI5Sc315OlnDfzpDar2S9/oAAAAAElFTkSuQmCC') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.gist {\n" + -" 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;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.image {\n" + -" 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;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.installgentoo {\n" + -" 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;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.liveleak {\n" + -" 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;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.pastebin {\n" + -" 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;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.soundcloud {\n" + -" 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;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.twitchtv {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAYUExURf///2RBpWRBpWRBpWRBpWRBpWRBpf///+zQyUYAAAAGdFJOUwFdZX0lTzs4r5oAAAABYktHRAcWYYjrAAAAB3RJTUUH4AINEi42iSXRNAAAAD1JREFUCNdjYEiDAAZGGIMtjQEEUBlMCWoEGci6mGEMsxQgIy0BiB3AjLS0FAYQIw0kwABipoI1AhkBQBIAFCIXxiHgq80AAAAASUVORK5CYII=') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.twitter {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAEsUExURf///1Cf21Gg3FGi31Gh3VKj4FGh3lKj4VKk4lKl41Ol5FOn51Sp6VSo6FOn5lCf21Gg3FGh3VGi31Gi31Gh3lGg3FGg3FGg3FGg3FGh3lGg3FGi31Kk4lKj4FGh3lGi31Kk4lGh3lGg3FGh3lOm5FOm5VGi31Kj4VSo6FGi31Gh3VGg3FKj4FOn51Gi31So6FWr7VOl5FGi31On51Sq6lKk4lOo51Sp6VOm5FSq61Ws7VOn51Oo51Sq61Ol5FOm5FSq61Wr7VOo51On51Sr7FWs7VSp6lGg3FGh3VOm5FWr7VSp6lKj4VOm5FSo6FSr7FWs7VWs7VWr7VSq6lOo51Om5FOo51So6FOm5VOl5FSq61Ws7VSr7FSp6lSp6VWs7lWr7VKk4lSq6v///6E3MNsAAABVdFJOUwAAAAAAAAAAAAAAAAAAAB0Ii+3xnBVTJhfsMKb+qTEp9GwBF/7lLAbo0m4pLkUTdvk2Ev3+EZnOBo/3Z8ffCRzH/D0OqPxiLnvx3UI8m9n1++GwXQZNS29BAAAAAWJLR0QAiAUdSAAAAAd0SU1FB+ACDRIwBwy67tEAAADKSURBVBjTY2BAB4xogIGRH8IQEBQSFhEVE2eQkJQC8ZmkQ8PCI2Rk5RjkIxUUlRgZlVWioqNjYlXVGNQ14iI1tbR14qLj4+MTdJkZ9PQNosJCE0OjgPz4KEMWBiPjhPiEmKQokIJ4E1MmBmazhHg4MGdlYmCzsLSC8ROsmRkZmFht4Eps7ViADmOzd4DyHZ2YmYACTOzOLmATXd04mIBOd/eQ9owFCXh5c7KB/MLi4+vnHxAYFBzCwcYEEmBi5uLm4eHl42RmAnsSAMZBLgZiFUQ5AAAAAElFTkSuQmCC') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.video {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QAxgDGAP8nNqN7AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gMZBjQQLEEqGwAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAA5SURBVDjLY2AYaMDIwMDwn1JD/lPCZhpwL+B1wf///ykzgBhDiAoDfIYQZQAjIyP5BuDTPJqQqAQAvW0ZAMk8+EEAAAAASUVORK5CYII=') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.vimeo {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAYFBMVEUAAAAIdZUKh6sLlLkLmr4LmsAMp88NrdYVW3MZj7Acstkrt9s1e5E7vN5EfI9JvdtKwuBijp5kpbl30eiDt8aG1uqRr7qTyNehxM+k4PCy3enB3OTg6Ovv9PXw+fz////L9U5WAAAAAXRSTlMAQObYZgAAAIFJREFUeNplz90OwiAMBWAQpAoyxclkP3je/y0H2AQXz0WT8100rRD6kNI9/cRroemQL3hXhoujZYj4OHoAmBvYGcBISwbWBvfXCrytnIDUQMkbsBpagMA7zhtQdyTFQAmIG7IkYniiZuh3XGsPqoOZkMOJOpAcLqUzNFGGu/57fwc1hgtp0mVSyQAAAABJRU5ErkJggg==') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.vine {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAHCUExURQAAAAC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+j////54tRLAAAACUdFJOUwAAAEK+9/e+QQIDAwEqzskfUZmUNHz2mrT++V1w+f5tCanNFUDwfEjtjAyyvg027Hki27QMBJzaHE/1+FkNsN0iZvv6bxyAlB589lQeyud0KB8PQO+ZBUrc+eXgcRG/3CoATe316Wxw/P6BAgBt+fp4IAwh0d4zM9q7Fm76qi605EMSrvfX/PRtAivF9IAJNMLxhA2KYlJ9AAAAAWJLR0SVCGB6gwAAAAd0SU1FB+ACDRI2MOJd7FgAAADrSURBVBjTLY9VWwJgGEPfiYWBha2YYHcHditgd3d3odjdivvBfgK727nYsyPiCrw03j6+fv6AaAMCgyAI1lElJBQSFh6hBxDJqOiY2Lh4SEKiIQlITmFqWrqRJkhGJrOA7Bzm5uUXsBBSVMySUpSVs6KyqrqmFmKuY30D0NjU3NLa1t6h9jvZ1Q30WGi19fb1KzAwyKFhYGSUY+MTkwpMTXNmFpibX+Di0rICWFldW9/A5tb2zu7ePtTrg0MeHePklPYzuDRw7uDF5RWvbwC32O0d7x8en55f4DHF6xv5/vHp6f/k6/vH+evuf1LAObptvSvrAAAAAElFTkSuQmCC') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.vocaroo {\n" + -" 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;\n" + -" padding-left: 18px;\n" + -"}\n" + -".linkify.youtube {\n" + -" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAYAAABr5z2BAAABIklEQVQoz53LvUrDUBjG8bOoOammSf1IoBSvoCB4JeIqOHgBLt6AIMRBBQelWurQ2kERnMRBsBUcIp5FJSBI5oQsJVkkUHh8W0o5nhaFHvjBgef/Mq+Q46RJBMkI/vE+aOus956tnEswIZe1LV0QyJ5sE2GzgZfVMtRNIdiDpccEssdlB1mW4bvTwdvWJtRdErM7U+8S/FJykCRJX5qm+KpVce8UMNLRLbulz4iSjTAMh6Iowsd5BeNadp3nUF0VlxAEwZBotXC0Usa4ll3meZdA1iguwvf9vpvDA2wvmKgYGtSud8suDB4TyGr2PF49D/vra9jRZ1BVdknMzgwuCGSnZEObwu6sBnVTCHZiaC7BhFx2PKdxUidiAH/4lLo9Mv0DELVs9qsOHXwAAAAASUVORK5CYII=') center left no-repeat!important;\n" + -" padding-left: 18px;\n" + -"}\n" + "/* Embedding */\n" + "#embedding {\n" + " padding: 1px 4px 1px 4px;\n" + @@ -21874,6 +3724,75 @@ "{\n" + " background-image: url(\"data:image/svg+xml,\");\n" + "}\n" + +"/* Link Title Favicons */\n" + +".linkify.audio {\n" + +" 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;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.clyp {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAwUExURTSY22ey5E2l4KbS75rM7Y3F64C/6f///8zl9nS45r/f9PL5/UGe3bPY8Vqr4v///wNjrzUAAAABYktHRA8YugDZAAAAB3RJTUUH4AINEi85AIH95AAAAE9JREFUCNdjYMAGGBWgDGYHCM2a3hkAZmi0dzSBaKaO9o5moCqmLiCjYzNQyw4QowIodQzI6E0AKcpo72gE6+Jyb1kAMehUA9RktgdYbQYAjGIVNGGXBJkAAAAASUVORK5CYII=') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.dailymotion {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAnUExURQBk3ff6/trp+kKO5wZt3xx54q7P9Ozz/IS17zOG5WKh653E8sbc9/GbbcoAAABZSURBVAjXY2BAASyhDhAGc9oECMOjyAAiESEEYrBYpLWBGcwHxcvBjDDxHelghpF0yDQwY3kVgweEUeEQDWbMEepqAjO8FMsLIeYsU8o+BrbCdWboTAe4AwALXxWGjW41FwAAAABJRU5ErkJggg==') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.gfycat {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAjVBMVEWn3gCo3gSr3w2t4BSu4Bav4Ri35C+45DK45DO55DXA50rA50vB50zC6E/D6FTF6VjG6VvL62vN7G/P7XbQ7XfW74vY8JDa8ZTe8qDe8qLf86Pi9Kzj9K7k9LHp9sDp98Lq98Ps+Mr0++L5/O75/fD6/fH6/fL6/fP7/fT7/fb8/ff8/vj8/vn+/v7///91X4cfAAAAcklEQVR42o3M2xKBUACF4aVQckrIuRJK6H//x2sme4/MuPDfre9i6c/Cc3U5Dj87BuAxsXvGu6JvIIXEHRWwNHCHQNrCzkAFkbSBg4EM8i+Yw7PXBa3zRfuxVyf/Bis7nKwGKAcWxgC8prI5Sc315OlnDfzpDar2S9/oAAAAAElFTkSuQmCC') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.gist {\n" + +" 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;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.image {\n" + +" 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;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.installgentoo {\n" + +" 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;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.liveleak {\n" + +" 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;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.pastebin {\n" + +" 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;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.soundcloud {\n" + +" 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;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.twitchtv {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAYUExURf///2RBpWRBpWRBpWRBpWRBpWRBpf///+zQyUYAAAAGdFJOUwFdZX0lTzs4r5oAAAABYktHRAcWYYjrAAAAB3RJTUUH4AINEi42iSXRNAAAAD1JREFUCNdjYEiDAAZGGIMtjQEEUBlMCWoEGci6mGEMsxQgIy0BiB3AjLS0FAYQIw0kwABipoI1AhkBQBIAFCIXxiHgq80AAAAASUVORK5CYII=') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.twitter {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAEsUExURf///1Cf21Gg3FGi31Gh3VKj4FGh3lKj4VKk4lKl41Ol5FOn51Sp6VSo6FOn5lCf21Gg3FGh3VGi31Gi31Gh3lGg3FGg3FGg3FGg3FGh3lGg3FGi31Kk4lKj4FGh3lGi31Kk4lGh3lGg3FGh3lOm5FOm5VGi31Kj4VSo6FGi31Gh3VGg3FKj4FOn51Gi31So6FWr7VOl5FGi31On51Sq6lKk4lOo51Sp6VOm5FSq61Ws7VOn51Oo51Sq61Ol5FOm5FSq61Wr7VOo51On51Sr7FWs7VSp6lGg3FGh3VOm5FWr7VSp6lKj4VOm5FSo6FSr7FWs7VWs7VWr7VSq6lOo51Om5FOo51So6FOm5VOl5FSq61Ws7VSr7FSp6lSp6VWs7lWr7VKk4lSq6v///6E3MNsAAABVdFJOUwAAAAAAAAAAAAAAAAAAAB0Ii+3xnBVTJhfsMKb+qTEp9GwBF/7lLAbo0m4pLkUTdvk2Ev3+EZnOBo/3Z8ffCRzH/D0OqPxiLnvx3UI8m9n1++GwXQZNS29BAAAAAWJLR0QAiAUdSAAAAAd0SU1FB+ACDRIwBwy67tEAAADKSURBVBjTY2BAB4xogIGRH8IQEBQSFhEVE2eQkJQC8ZmkQ8PCI2Rk5RjkIxUUlRgZlVWioqNjYlXVGNQ14iI1tbR14qLj4+MTdJkZ9PQNosJCE0OjgPz4KEMWBiPjhPiEmKQokIJ4E1MmBmazhHg4MGdlYmCzsLSC8ROsmRkZmFht4Eps7ViADmOzd4DyHZ2YmYACTOzOLmATXd04mIBOd/eQ9owFCXh5c7KB/MLi4+vnHxAYFBzCwcYEEmBi5uLm4eHl42RmAnsSAMZBLgZiFUQ5AAAAAElFTkSuQmCC') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.video {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QAxgDGAP8nNqN7AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gMZBjQQLEEqGwAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAA5SURBVDjLY2AYaMDIwMDwn1JD/lPCZhpwL+B1wf///ykzgBhDiAoDfIYQZQAjIyP5BuDTPJqQqAQAvW0ZAMk8+EEAAAAASUVORK5CYII=') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.vimeo {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAYFBMVEUAAAAIdZUKh6sLlLkLmr4LmsAMp88NrdYVW3MZj7Acstkrt9s1e5E7vN5EfI9JvdtKwuBijp5kpbl30eiDt8aG1uqRr7qTyNehxM+k4PCy3enB3OTg6Ovv9PXw+fz////L9U5WAAAAAXRSTlMAQObYZgAAAIFJREFUeNplz90OwiAMBWAQpAoyxclkP3je/y0H2AQXz0WT8100rRD6kNI9/cRroemQL3hXhoujZYj4OHoAmBvYGcBISwbWBvfXCrytnIDUQMkbsBpagMA7zhtQdyTFQAmIG7IkYniiZuh3XGsPqoOZkMOJOpAcLqUzNFGGu/57fwc1hgtp0mVSyQAAAABJRU5ErkJggg==') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.vine {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAHCUExURQAAAAC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+j////54tRLAAAACUdFJOUwAAAEK+9/e+QQIDAwEqzskfUZmUNHz2mrT++V1w+f5tCanNFUDwfEjtjAyyvg027Hki27QMBJzaHE/1+FkNsN0iZvv6bxyAlB589lQeyud0KB8PQO+ZBUrc+eXgcRG/3CoATe316Wxw/P6BAgBt+fp4IAwh0d4zM9q7Fm76qi605EMSrvfX/PRtAivF9IAJNMLxhA2KYlJ9AAAAAWJLR0SVCGB6gwAAAAd0SU1FB+ACDRI2MOJd7FgAAADrSURBVBjTLY9VWwJgGEPfiYWBha2YYHcHditgd3d3odjdivvBfgK727nYsyPiCrw03j6+fv6AaAMCgyAI1lElJBQSFh6hBxDJqOiY2Lh4SEKiIQlITmFqWrqRJkhGJrOA7Bzm5uUXsBBSVMySUpSVs6KyqrqmFmKuY30D0NjU3NLa1t6h9jvZ1Q30WGi19fb1KzAwyKFhYGSUY+MTkwpMTXNmFpibX+Di0rICWFldW9/A5tb2zu7ePtTrg0MeHePklPYzuDRw7uDF5RWvbwC32O0d7x8en55f4DHF6xv5/vHp6f/k6/vH+evuf1LAObptvSvrAAAAAElFTkSuQmCC') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.vocaroo {\n" + +" 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;\n" + +" padding-left: 18px;\n" + +"}\n" + +".linkify.youtube {\n" + +" background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAYAAABr5z2BAAABIklEQVQoz53LvUrDUBjG8bOoOammSf1IoBSvoCB4JeIqOHgBLt6AIMRBBQelWurQ2kERnMRBsBUcIp5FJSBI5oQsJVkkUHh8W0o5nhaFHvjBgef/Mq+Q46RJBMkI/vE+aOus956tnEswIZe1LV0QyJ5sE2GzgZfVMtRNIdiDpccEssdlB1mW4bvTwdvWJtRdErM7U+8S/FJykCRJX5qm+KpVce8UMNLRLbulz4iSjTAMh6Iowsd5BeNadp3nUF0VlxAEwZBotXC0Usa4ll3meZdA1iguwvf9vpvDA2wvmKgYGtSud8suDB4TyGr2PF49D/vra9jRZ1BVdknMzgwuCGSnZEObwu6sBnVTCHZiaC7BhFx2PKdxUidiAH/4lLo9Mv0DELVs9qsOHXwAAAAASUVORK5CYII=') center left no-repeat!important;\n" + +" padding-left: 18px;\n" + +"}\n" + "/* XXX Moved to end of stylesheet to avoid breaking whole stylesheet in Maxthon. */\n" + "@supports (text-decoration-style: dashed) or (-moz-text-decoration-style: dashed) {\n" + " .quotelink.forwardlink,\n" + @@ -21883,13 +3802,18839 @@ " text-decoration-style: dashed;\n" + " border-bottom: none;\n" + " }\n" + -"}", - cssWWW: "#captcha-cnt {\n" + +"}\n", + +report: +"#g-recaptcha,\n" + +":root:not(.js-enabled) #captchaContainerAlt {\n" + " height: auto;\n" + -"}", - features: [['Polyfill', Polyfill], ['Normalize URL', NormalizeURL], ['Captcha Configuration', Captcha.replace], ['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], ['Thread Links', ThreadLinks], ['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], ['Cooldown', QR.cooldown], ['Pass Link', PassLink], ['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], ['Edit Link', QR.oekaki.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], ['Flash Features', Flash], ['Reply Pruning', ReplyPruning]] +"}\n" + +"#captchaContainerAlt td:nth-child(2) {\n" + +" display: table-cell !important;\n" + +"}\n", + +www: +"#captcha-cnt {\n" + +" height: auto;\n" + +"}\n" + +}; + +$ = (function() { + var $, + 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; }; + + $ = function(selector, root) { + if (root == null) { + root = d.body; + } + return root.querySelector(selector); }; - Main.init(); + $.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: "4chan X was blocked from loading the following URL:

            [More info]" + }); + $('span', message).textContent = (/^\/\//.test(url) ? location.protocol : '') + url; + return new Notice('warning', message, 30, function() { + return delete blockedURLs[url]; + }); + }; + return function(url, options, extra) { + var err, event, form, i, len, r, ref, ref1, type, upCallbacks, whenModified; + if (options == null) { + options = {}; + } + if (extra == null) { + extra = {}; + } + type = extra.type, whenModified = extra.whenModified, upCallbacks = extra.upCallbacks, form = extra.form; + url = url.replace(/^((?:https?:)?\/\/(?:\w+\.)?4c(?:ha|d)n\.org)\/adv\//, '$1//adv/'); + r = new XMLHttpRequest(); + type || (type = form && 'post' || 'get'); + try { + r.open(type, url, true); + } catch (_error) { + err = _error; + blockedError(url); + ref = ['error', 'loadend']; + for (i = 0, len = ref.length; i < len; i++) { + event = ref[i]; + r["on" + event] = options["on" + event]; + $.queueTask($.event, event, null, r); + } + return; + } + if (whenModified) { + if (((ref1 = lastModified[whenModified]) != null ? ref1[url] : void 0) != null) { + r.setRequestHeader('If-Modified-Since', lastModified[whenModified][url]); + } + $.on(r, 'load', function() { + return (lastModified[whenModified] || (lastModified[whenModified] = {}))[url] = r.getResponseHeader('Last-Modified'); + }); + } + if (/\.json$/.test(url)) { + if (options.responseType == null) { + options.responseType = 'json'; + } + } + $.extend(r, options); + if (options.responseType === 'json' && r.responseType !== 'json' && delete r.response) { + Object.defineProperty(r, 'response', { + configurable: true, + enumerable: true, + get: function() { + return JSON.parse(r.responseText); + } + }); + } + $.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, true); + }); + } 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 fn1, i, len, ref; + this.evt = e; + ref = this.callbacks; + fn1 = (function(_this) { + return function(cb) { + return $.queueTask(function() { + return cb.call(_this, e, false); + }); + }; + })(this); + for (i = 0, len = ref.length; i < len; i++) { + cb = ref[i]; + fn1(cb); + } + 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, cb) { + var el, observer; + if (el = $(selector, root)) { + return cb(el); + } + if ($.engine === 'edge' && d.readyState === 'loading') { + $.asap((function() { + return d.readyState !== 'loading' || $(selector, root); + }), function() { + return $.onExists(root, selector, cb); + }); + return; + } + observer = new MutationObserver(function() { + if (el = $(selector, root)) { + observer.disconnect(); + return cb(el); + } + }); + return observer.observe(root, { + childList: true, + subtree: true + }); + }; + + $.addStyle = function(css, id, test) { + var style; + if (test == null) { + test = 'head'; + } + style = $.el('style', { + textContent: css + }); + if (id != null) { + style.id = id; + } + $.onExists(doc, 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 != null ? el.remove() : void 0; + }; + + $.rmAll = function(root) { + return root.textContent = null; + }; + + $.tn = function(s) { + return d.createTextNode(s); + }; + + $.frag = function() { + return d.createDocumentFragment(); + }; + + $.nodes = function(nodes) { + var frag, i, len, node; + 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, properties2) { + var el; + el = d.createElement(tag); + if (properties) { + $.extend(el, properties); + } + if (properties2) { + $.extend(el, properties2); + } + 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 + })); + }; + + (function() { + var clone, err, ref, unsafeConstructors; + if (!(/PaleMoon\//.test(navigator.userAgent) && +(typeof GM_info !== "undefined" && GM_info !== null ? (ref = GM_info.version) != null ? ref.split('.')[0] : void 0 : void 0) >= 2 && typeof cloneInto === 'undefined')) { + return; + } + try { + return new CustomEvent('x', { + detail: {} + }); + } catch (_error) { + err = _error; + unsafeConstructors = { + Object: unsafeWindow.Object, + Array: unsafeWindow.Array + }; + clone = function(obj) { + var constructor, key, obj2, val; + if ((obj != null) && typeof obj === 'object' && (constructor = unsafeConstructors[obj.constructor.name])) { + obj2 = new constructor(); + for (key in obj) { + val = obj[key]; + obj2[key] = clone(val); + } + return obj2; + } else { + return obj; + } + }; + return $.event = function(event, detail, root) { + if (root == null) { + root = d; + } + return root.dispatchEvent(new CustomEvent(event, { + bubbles: true, + detail: clone(detail) + })); + }; + } + })(); + + $.open = typeof GM_openInTab !== "undefined" && GM_openInTab !== null ? GM_openInTab : function(url) { + return window.open(url, '_blank'); + }; + + $.debounce = function(wait, fn) { + var args, exec, lastCall, that, timeout; + lastCall = 0; + timeout = null; + that = null; + args = null; + exec = function() { + lastCall = Date.now(); + return fn.apply(that, args); + }; + return function() { + args = arguments; + that = this; + if (lastCall < Date.now() - wait) { + return exec(); + } + clearTimeout(timeout); + return timeout = setTimeout(exec, wait); + }; + }; + + $.queueTask = (function() { + var execTask, taskChannel, taskQueue; + taskQueue = []; + execTask = function() { + var args, func, task; + task = taskQueue.shift(); + func = task[0]; + args = Array.prototype.slice.call(task, 1); + return func.apply(func, args); + }; + if (window.MessageChannel) { + taskChannel = new MessageChannel(); + taskChannel.port1.onmessage = execTask; + return function() { + taskQueue.push(arguments); + return taskChannel.port2.postMessage(null); + }; + } else { + return function() { + taskQueue.push(arguments); + return setTimeout(execTask, 0); + }; + } + })(); + + $.globalEval = function(code) { + var script; + script = $.el('script', { + textContent: code + }); + $.add(d.head || doc, script); + return $.rm(script); + }; + + $.global = function(fn) { + if (doc) { + return $.globalEval("(" + fn + ")();"); + } else { + return fn(); + } + }; + + $.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; + }; + + $.engine = (function() { + if (/Edge\//.test(navigator.userAgent)) { + return 'edge'; + } + if (/Chrome\//.test(navigator.userAgent)) { + return 'blink'; + } + if (/WebKit\//.test(navigator.userAgent)) { + return 'webkit'; + } + if (/Gecko\/|Goanna/.test(navigator.userAgent)) { + return 'gecko'; + } + })(); + + $.platform = 'userscript'; + + try { + localStorage.getItem('x'); + $.hasStorage = true; + } catch (_error) { + $.hasStorage = false; + } + + $.item = function(key, val) { + var item; + item = {}; + item[key] = val; + return item; + }; + + $.syncing = {}; + + if (typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null) { + $.getValue = GM_getValue; + $.listValues = function() { + return GM_listValues(); + }; + } else if ($.hasStorage) { + $.getValue = function(key) { + return localStorage[key]; + }; + $.listValues = function() { + var key, results; + results = []; + for (key in localStorage) { + if (key.slice(0, g.NAMESPACE.length) === g.NAMESPACE) { + results.push(key); + } + } + return results; + }; + } else { + $.getValue = function() {}; + $.listValues = function() { + return []; + }; + } + + if (typeof GM_addValueChangeListener !== "undefined" && GM_addValueChangeListener !== null) { + $.setValue = GM_setValue; + $.deleteValue = GM_deleteValue; + } else if (typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null) { + $.oldValue = {}; + $.setValue = function(key, val) { + GM_setValue(key, val); + if (key in $.syncing) { + $.oldValue[key] = val; + if ($.hasStorage) { + return localStorage[key] = val; + } + } + }; + $.deleteValue = function(key) { + GM_deleteValue(key); + if (key in $.syncing) { + delete $.oldValue[key]; + if ($.hasStorage) { + return localStorage.removeItem(key); + } + } + }; + if (!$.hasStorage) { + $.cantSync = true; + } + } else if ($.hasStorage) { + $.oldValue = {}; + $.setValue = function(key, val) { + if (key in $.syncing) { + $.oldValue[key] = val; + } + return localStorage[key] = val; + }; + $.deleteValue = function(key) { + if (key in $.syncing) { + delete $.oldValue[key]; + } + return localStorage.removeItem(key); + }; + } else { + $.setValue = function() {}; + $.deleteValue = function() {}; + $.cantSync = $.cantSet = true; + } + + if (typeof GM_addValueChangeListener !== "undefined" && GM_addValueChangeListener !== null) { + $.sync = function(key, cb) { + return $.syncing[key] = GM_addValueChangeListener(g.NAMESPACE + key, function(key2, oldValue, newValue, remote) { + if (remote) { + if (newValue !== void 0) { + newValue = JSON.parse(newValue); + } + return cb(newValue, key); + } + }); + }; + $.forceSync = function() {}; + } else if ((typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null) || $.hasStorage) { + $.sync = function(key, cb) { + key = g.NAMESPACE + key; + $.syncing[key] = cb; + return $.oldValue[key] = $.getValue(key); + }; + (function() { + var onChange; + onChange = function(arg) { + var cb, key, newValue; + key = arg.key, newValue = arg.newValue; + if (!(cb = $.syncing[key])) { + return; + } + if (newValue != null) { + if (newValue === $.oldValue[key]) { + return; + } + $.oldValue[key] = newValue; + return cb(JSON.parse(newValue), key.slice(g.NAMESPACE.length)); + } else { + if ($.oldValue[key] == null) { + return; + } + delete $.oldValue[key]; + return cb(void 0, key.slice(g.NAMESPACE.length)); + } + }; + $.on(window, 'storage', onChange); + return $.forceSync = function(key) { + key = g.NAMESPACE + key; + return onChange({ + key: key, + newValue: $.getValue(key) + }); + }; + })(); + } else { + $.sync = function() {}; + $.forceSync = function() {}; + } + + $["delete"] = function(keys) { + var i, key, len; + if (!(keys instanceof Array)) { + keys = [keys]; + } + for (i = 0, len = keys.length; i < len; i++) { + key = keys[i]; + $.deleteValue(g.NAMESPACE + 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 = $.getValue(g.NAMESPACE + key)) { + items[key] = JSON.parse(val); + } + } + return cb(items); + }); + }; + + $.set = function(keys, val, cb) { + var key, value; + if (typeof keys === 'string') { + $.setValue(g.NAMESPACE + keys, JSON.stringify(val)); + } else { + for (key in keys) { + value = keys[key]; + $.setValue(g.NAMESPACE + key, JSON.stringify(value)); + } + cb = val; + } + return typeof cb === "function" ? cb() : void 0; + }; + + $.clear = function(cb) { + var id; + $["delete"](Object.keys(Conf)); + $["delete"](['previousversion', 'AutoWatch', '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; + })()); + try { + $["delete"]($.listValues().map(function(key) { + return key.replace(g.NAMESPACE, ''); + })); + } catch (_error) {} + return typeof cb === "function" ? cb() : void 0; + }; + + return $; + +}).call(this); + +$$ = (function() { + var slice = [].slice; + + return function(selector, root) { + if (root == null) { + root = d.body; + } + return slice.call(root.querySelectorAll(selector)); + }; + +}).call(this); + +CrossOrigin = (function() { + var CrossOrigin; + + CrossOrigin = { + binary: function(url, cb, headers) { + var options, ref, workaround; + if (headers == null) { + headers = {}; + } + url = url.replace(/^((?:https?:)?\/\/(?:\w+\.)?4c(?:ha|d)n\.org)\/adv\//, '$1//adv/'); + workaround = $.engine === 'gecko' && (typeof GM_info !== "undefined" && GM_info !== null) && /^[0-2]\.|^3\.[01](?!\d)/.test(GM_info.version); + workaround || (workaround = /PaleMoon\//.test(navigator.userAgent)); + workaround || (workaround = (typeof GM_info !== "undefined" && GM_info !== null ? (ref = GM_info.script) != null ? ref.includeJSB : void 0 : void 0) != null); + options = { + method: "GET", + url: url, + headers: headers, + onload: function(xhr) { + var contentDisposition, contentType, data, i, r, ref1, ref2; + if (workaround) { + r = xhr.responseText; + data = new Uint8Array(r.length); + i = 0; + while (i < r.length) { + data[i] = r.charCodeAt(i); + i++; + } + } else { + data = new Uint8Array(xhr.response); + } + if (typeof xhr.responseHeaders === 'object') { + contentType = xhr.responseHeaders['Content-Type']; + contentDisposition = xhr.responseHeaders['Content-Disposition']; + } else { + contentType = (ref1 = xhr.responseHeaders.match(/Content-Type:\s*(.*)/i)) != null ? ref1[1] : void 0; + contentDisposition = (ref2 = xhr.responseHeaders.match(/Content-Disposition:\s*(.*)/i)) != null ? ref2[1] : void 0; + } + return cb(data, contentType, contentDisposition); + }, + onerror: function() { + return cb(null); + }, + onabort: function() { + return cb(null); + } + }; + if (workaround) { + options.overrideMimeType = options.mimeType = 'text/plain; charset=x-user-defined'; + } else { + options.responseType = 'arraybuffer'; + } + return GM_xmlhttpRequest(options); + }, + file: function(url, cb) { + return CrossOrigin.binary(url, function(data, contentType, contentDisposition) { + var blob, match, mime, name, ref, ref1, ref2, ref3; + 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, '"'); + } + if ((typeof GM_info !== "undefined" && GM_info !== null ? (ref3 = GM_info.script) != null ? ref3.includeJSB : void 0 : void 0) != null) { + mime = QR.typeFromExtension[name.match(/[^.]*$/)[0].toLowerCase()] || 'application/octet-stream'; + } + 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 j, len, ref, response; + response = JSON.parse(xhr.responseText); + ref = callbacks[url]; + for (j = 0, len = ref.length; j < len; j++) { + cb = ref[j]; + cb(response); + } + delete callbacks[url]; + return responses[url] = response; + }, + onerror: function() { + return delete callbacks[url]; + }, + onabort: function() { + return delete callbacks[url]; + } + }); + }; + })() + }; + + return CrossOrigin; + +}).call(this); + +Board = (function() { + var Board; + + 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; + + })(); + + return Board; + +}).call(this); + +Callbacks = (function() { + var Callbacks; + + Callbacks = (function() { + Callbacks.Post = new Callbacks('Post'); + + Callbacks.Thread = new Callbacks('Thread'); + + Callbacks.CatalogThread = new Callbacks('Catalog Thread'); + + 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, keys) { + var err, errors, i, len, name, ref; + if (keys == null) { + keys = this.keys; + } + for (i = 0, len = keys.length; i < len; i++) { + name = keys[i]; + try { + if ((ref = this[name]) != null) { + ref.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; + + })(); + + return Callbacks; + +}).call(this); + +CatalogThread = (function() { + var CatalogThread; + + CatalogThread = (function() { + 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; + + })(); + + return CatalogThread; + +}).call(this); + +Connection = (function() { + var Connection, + bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + + Connection = (function() { + function Connection(target, origin, cb) { + this.target = target; + this.origin = origin; + this.cb = cb != null ? cb : {}; + this.onMessage = bind(this.onMessage, this); + this.send = bind(this.send, this); + $.on(window, 'message', this.onMessage); + } + + Connection.prototype.targetWindow = function() { + if (this.target instanceof window.HTMLIFrameElement) { + return this.target.contentWindow; + } else { + return this.target; + } + }; + + Connection.prototype.send = function(data) { + return this.targetWindow().postMessage("" + g.NAMESPACE + (JSON.stringify(data)), this.origin); + }; + + Connection.prototype.onMessage = function(e) { + var base, data, type, value; + if (!(e.source === this.targetWindow() && 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; + + })(); + + return Connection; + +}).call(this); + +DataBoard = (function() { + var DataBoard, + bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + + 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[this.key]; + $.sync(this.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(cb) { + return $.set(this.key, this.data, cb); + }; + + DataBoard.prototype["delete"] = function(arg) { + var boardID, postID, ref, threadID; + 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, cb) { + var base, base1, base2, boardID, postID, threadID, val; + 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(cb); + }; + + DataBoard.prototype.get = function(arg) { + var ID, board, boardID, defaultValue, i, len, postID, thread, threadID, val; + boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, defaultValue = arg.defaultValue; + if (board = this.data.boards[boardID]) { + if (threadID == null) { + if (postID != null) { + 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 != null ? thread[postID] : thread; + } + } + return val || defaultValue; + }; + + DataBoard.prototype.forceSync = function() { + return $.forceSync(this.key); + }; + + DataBoard.prototype.clean = function() { + var boardID, now, ref, val; + $.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) { + this.ajaxClean(boardID); + } + } + }; + + DataBoard.prototype.ajaxClean = function(boardID) { + return $.cache("//a.4cdn.org/" + boardID + "/threads.json", (function(_this) { + return function(e1) { + var ref; + if ((ref = e1.target.status) !== 200 && ref !== 404) { + return; + } + return $.cache("//a.4cdn.org/" + boardID + "/archive.json", function(e2) { + var ref1; + if ((ref1 = e2.target.status) !== 200 && ref1 !== 404) { + return; + } + return _this.ajaxCleanParse(boardID, e1.target.response, e2.target.response); + }); + }; + })(this)); + }; + + DataBoard.prototype.ajaxCleanParse = function(boardID, response1, response2) { + var ID, board, i, j, k, len, len1, len2, page, ref, thread, threads; + if (!(board = this.data.boards[boardID])) { + return; + } + threads = {}; + if (response1) { + for (i = 0, len = response1.length; i < len; i++) { + page = response1[i]; + ref = page.threads; + for (j = 0, len1 = ref.length; j < len1; j++) { + thread = ref[j]; + ID = thread.no; + if (ID in board) { + threads[ID] = board[ID]; + } + } + } + } + if (response2) { + for (k = 0, len2 = response2.length; k < len2; k++) { + ID = response2[k]; + if (ID in board) { + threads[ID] = board[ID]; + } + } + } + this.data.boards[boardID] = threads; + this.deleteIfEmpty({ + boardID: boardID + }); + return this.save(); + }; + + DataBoard.prototype.onSync = function(data) { + this.data = data || { + boards: {} + }; + return typeof this.sync === "function" ? this.sync() : void 0; + }; + + return DataBoard; + + })(); + + return DataBoard; + +}).call(this); + +Fetcher = (function() { + var Fetcher, + slice = [].slice; + + Fetcher = (function() { + function Fetcher(boardID1, threadID, postID1, root, quoter) { + var post; + this.boardID = boardID1; + this.threadID = threadID; + this.postID = postID1; + this.root = root; + this.quoter = quoter; + 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(_this) { + return function(e, isCached) { + return _this.fetchedPost(e.target, isCached); + }; + })(this)); + } else { + this.archivedPost(); + } + } + + Fetcher.prototype.insert = function(post) { + var boardID, clone, k, len, nodes, postID, quote, ref, ref1; + if (!this.root.parentNode) { + return; + } + clone = post.addClone(this.quoter.context, $.hasClass(this.root, 'dialog')); + Main.callbackNodes('Post', [clone]); + nodes = clone.nodes; + $.rmAll(nodes.root); + $.add(nodes.root, nodes.post); + ref = clone.nodes.quotelinks.concat(slice.call(clone.nodes.backlinks)); + for (k = 0, len = ref.length; k < len; k++) { + quote = ref[k]; + ref1 = Get.postDataFromLink(quote), boardID = ref1.boardID, postID = ref1.postID; + if (postID === this.quoter.ID && boardID === this.quoter.board.ID) { + $.addClass(quote, 'forwardlink'); + } + } + $.rmAll(this.root); + $.add(this.root, nodes.root); + return $.event('PostsInserted'); + }; + + Fetcher.prototype.fetchedPost = function(req, isCached) { + var api, board, k, len, post, posts, status, thread; + 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 (k = 0, len = posts.length; k < len; k++) { + post = posts[k]; + if (post.no === this.postID) { + break; + } + } + if (post.no !== this.postID) { + if (isCached) { + api = "//a.4cdn.org/" + this.boardID + "/thread/" + this.threadID + ".json"; + $.cleanCache(function(url) { + return url === api; + }); + $.cache(api, (function(_this) { + return function(e) { + return _this.fetchedPost(e.target, false); + }; + })(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 archive, url; + if (!Conf['Resurrect Quotes']) { + return false; + } + if (!(url = Redirect.to('post', { + boardID: this.boardID, + postID: this.postID + }))) { + return false; + } + archive = Redirect.data.post[this.boardID]; + if (/^https:\/\//.test(url) || location.protocol === 'http:') { + $.cache(url, (function(_this) { + return function(e) { + return _this.parseArchivedPost(e.target.response, url, archive); + }; + })(this), { + responseType: 'json', + withCredentials: archive.withCredentials + }); + return true; + } else if (Conf['Exempt 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 (!((ref = media[key]) != null ? ref.match(/^http:\/\//) : void 0)) { + delete media[key]; + } + } + } + } + return _this.parseArchivedPost(response, url, archive); + }; + })(this)); + return true; + } + return false; + }; + + Fetcher.prototype.parseArchivedPost = function(data, url, archive) { + var board, comment, greentext, i, j, key, o, post, ref, ref1, text, text2, thread, val; + if (post = g.posts[this.boardID + "." + this.postID]) { + this.insert(post); + return; + } + if (data == null) { + $.addClass(this.root, 'warning'); + this.root.textContent = "Error fetching Post No." + this.postID + " from " + archive.name + "."; + 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 k, len, results; + results = []; + for (i = k = 0, len = comment.length; k < len; i = ++k) { + text = comment[i]; + if (i % 2 === 1) { + results.push(this.archiveTags[text]); + } else { + greentext = text[0] === '>'; + text = text.replace(/(\[\/?[a-z]+):lit(\])/g, '$1$2'); + text = (function() { + var l, len1, ref, results1; + ref = text.split(/(>>(?:>\/[a-z\d]+\/)?\d+)/g); + results1 = []; + for (j = l = 0, len1 = ref.length; l < len1; j = ++l) { + text2 = ref[j]; + results1.push({ + innerHTML: ((j % 2) ? "" + E(text2) + "" : E(text2)) + }); + } + return results1; + })(); + text = { + innerHTML: ((greentext) ? "" + E.cat(text) + "" : E.cat(text)) + }; + results.push(text); + } + } + return results; + }).call(this); + comment = { + innerHTML: E.cat(comment) + }; + this.threadID = +data.thread_num; + o = { + postID: this.postID, + threadID: this.threadID, + boardID: this.boardID, + isReply: this.postID !== this.threadID + }; + o.info = { + subject: data.title, + email: data.email, + name: data.name || '', + tripcode: data.trip, + capcode: (function() { + switch (data.capcode) { + case 'M': + return 'Mod'; + case 'A': + return 'Admin'; + case 'D': + return 'Developer'; + } + })(), + uniqueID: data.poster_hash, + flagCode: data.poster_country, + flag: data.poster_country_name, + dateUTC: data.timestamp, + dateText: data.fourchan_date, + commentHTML: comment + }; + if (o.info.capcode) { + delete o.info.uniqueID; + } + if ((ref = data.media) != null ? ref.media_filename : void 0) { + ref1 = data.media; + for (key in ref1) { + val = ref1[key]; + if (/_link$/.test(key) && (val != null ? val[0] : void 0) === '/') { + data.media[key] = url.split('/', 3).join('/') + val; + } + } + o.file = { + name: data.media.media_filename, + url: data.media.media_link || data.media.remote_media_link || (location.protocol + "//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: $.bytesToString(data.media.media_size), + thumbURL: data.media.thumb_link || (location.protocol + "//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 (!/\.pdf$/.test(o.file.url)) { + o.file.dimensions = o.file.width + "x" + o.file.height; + } + if (this.boardID === 'f' && data.media.exif) { + 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); + post.kill(); + if (post.file) { + post.file.thumbURL = o.file.thumbURL; + } + post.isFetchedQuote = true; + Main.callbackNodes('Post', [post]); + return this.insert(post); + }; + + Fetcher.prototype.archiveTags = { + '\n': { + innerHTML: "
            " + }, + '[b]': { + innerHTML: "" + }, + '[/b]': { + innerHTML: "" + }, + '[spoiler]': { + innerHTML: "" + }, + '[/spoiler]': { + innerHTML: "" + }, + '[code]': { + innerHTML: "
            "
            +      },
            +      '[/code]': {
            +        innerHTML: "
            " + }, + '[moot]': { + innerHTML: "
            " + }, + '[/moot]': { + innerHTML: "
            " + }, + '[banned]': { + innerHTML: "" + }, + '[/banned]': { + innerHTML: "" + } + }; + + return Fetcher; + + })(); + + return Fetcher; + +}).call(this); + +Notice = (function() { + var Notice, + bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + + 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: "
            " + }); + 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 (this.closed) { + return; + } + 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() { + this.closed = true; + $.off(d, 'visibilitychange', this.add); + $.rm(this.el); + return typeof this.onclose === "function" ? this.onclose() : void 0; + }; + + return Notice; + + })(); + + return Notice; + +}).call(this); + +Post = (function() { + var Post, + 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; }; + + Post = (function() { + Post.prototype.toString = function() { + return this.ID; + }; + + function Post(root, thread, board) { + var capcode, clone, date, email, flag, info, j, len, name, post, ref, subject, tripcode, uniqueID; + this.thread = thread; + this.board = board; + this.ID = +root.id.slice(2); + this.fullID = this.board + "." + this.ID; + this.context = this; + root.dataset.fullID = this.fullID; + 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: [] + }; + if ($.engine === 'edge') { + Object.defineProperty(this.nodes, 'backlinks', { + configurable: true, + enumerable: true, + get: function() { + return info.getElementsByClassName('backlink'); + } + }); + } else { + this.nodes.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 || void 0; + } + 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(); + 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 (j = 0, len = ref.length; j < len; j++) { + clone = ref[j]; + clone.origin = this; + } + } + this.board.posts.push(this.ID, this); + this.thread.posts.push(this.ID, this); + g.posts.push(this.fullID, this); + } + + Post.prototype.parseComment = function() { + var abbr, bq, commentDisplay, j, k, len, len1, node, ref, spoilers; + this.nodes.comment.normalize(); + bq = this.nodes.comment.cloneNode(true); + ref = $$('.abbr + br, .exif, b, .fortune', bq); + for (j = 0, len = ref.length; j < len; j++) { + node = ref[j]; + $.rm(node); + } + if (abbr = $('.abbr', bq)) { + $.rm(abbr); + } + this.info.comment = this.nodesToText(bq); + if (abbr) { + this.info.comment = this.info.comment.replace(/\n\n$/, ''); + } + commentDisplay = this.info.comment; + if (!(Conf['Remove Spoilers'] || Conf['Reveal Spoilers'])) { + spoilers = $$('s', bq); + if (spoilers.length) { + for (k = 0, len1 = spoilers.length; k < len1; k++) { + node = spoilers[k]; + $.replace(node, $.tn('[spoiler]')); + } + commentDisplay = this.nodesToText(bq); + } + } + return this.info.commentDisplay = commentDisplay.trim().replace(/\s+$/gm, ''); + }; + + 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; + }; + + Post.prototype.parseQuotes = function() { + var j, len, quotelink, ref; + this.quotes = []; + ref = $$(':not(pre) > .quotelink', this.nodes.comment); + for (j = 0, len = ref.length; j < len; j++) { + quotelink = ref[j]; + this.parseQuote(quotelink); + } + }; + + Post.prototype.parseQuote = function(quotelink) { + var fullID, match; + match = quotelink.href.match(/^https?:\/\/boards\.4chan\.org\/+([^\/]+)\/+(?:res|thread)\/+\d+(?:\/[^#]*)?#p(\d+)$/); + if (!(match || (this.isClone && quotelink.dataset.postID))) { + 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() { + var fileEl, fileText, info, link, m, ref, ref1, ref2, size, thumb, unit; + if (!(fileEl = $('.file', this.nodes.post))) { + return; + } + if (!(link = $('.fileText > a, .fileText-original > a', fileEl))) { + return; + } + if (!(info = (ref = link.nextSibling) != null ? ref.textContent.match(/\(([\d.]+ [KMG]?B).*\)/) : void 0)) { + return; + } + fileText = fileEl.firstElementChild; + this.file = { + text: fileText, + link: link, + url: link.href, + name: fileText.title || link.title || link.textContent, + size: info[1], + isImage: /(jpg|png|gif)$/i.test(link.href), + isVideo: /webm$/i.test(link.href), + dimensions: (ref1 = info[0].match(/\d+x\d+/)) != null ? ref1[0] : void 0, + tag: (ref2 = info[0].match(/,[^,]*, ([a-z]+)\)/i)) != null ? ref2[1] : void 0 + }; + 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; + if ((thumb = $('.fileThumb > [data-md5]', fileEl))) { + return $.extend(this.file, { + thumb: thumb, + thumbURL: (m = link.href.match(/\d+(?=\.\w+$)/)) ? location.protocol + "//i.4cdn.org/" + this.board + "/" + m[0] + "s.jpg" : void 0, + MD5: thumb.dataset.md5, + isSpoiler: $.hasClass(thumb.parentNode, 'imgspoiler') + }); + } + }; + + Post.prototype.kill = function(file) { + var clone, j, k, len, len1, quotelink, ref, ref1, strong; + if (file) { + if (this.isDead || this.file.isDead) { + return; + } + this.file.isDead = true; + $.addClass(this.nodes.root, 'deleted-file'); + } else { + if (this.isDead) { + return; + } + this.isDead = true; + $.rmClass(this.nodes.root, 'deleted-file'); + $.addClass(this.nodes.root, 'deleted-post'); + } + if (!(strong = $('strong.warning', this.nodes.info))) { + strong = $.el('strong', { + className: 'warning' + }); + $.after($('input', this.nodes.info), strong); + } + strong.textContent = file ? '[File deleted]' : '[Deleted]'; + if (this.isClone) { + return; + } + ref = this.clones; + for (j = 0, len = ref.length; j < len; j++) { + clone = ref[j]; + clone.kill(file); + } + if (file) { + return; + } + ref1 = Get.allQuotelinksLinkingTo(this); + for (k = 0, len1 = ref1.length; k < len1; k++) { + quotelink = ref1[k]; + if (!(!$.hasClass(quotelink, 'deadlink'))) { + continue; + } + quotelink.textContent = quotelink.textContent + '\u00A0(Dead)'; + $.addClass(quotelink, 'deadlink'); + } + }; + + Post.prototype.resurrect = function() { + var clone, j, k, len, len1, quotelink, ref, ref1, strong; + this.isDead = false; + $.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 (j = 0, len = ref.length; j < len; j++) { + clone = ref[j]; + clone.resurrect(); + } + ref1 = Get.allQuotelinksLinkingTo(this); + for (k = 0, len1 = ref1.length; k < len1; k++) { + quotelink = ref1[k]; + if (!($.hasClass(quotelink, 'deadlink'))) { + continue; + } + quotelink.textContent = quotelink.textContent.replace('\u00A0(Dead)', ''); + $.rmClass(quotelink, 'deadlink'); + } + }; + + Post.prototype.collect = function() { + g.posts.rm(this.fullID); + this.thread.posts.rm(this); + return this.board.posts.rm(this); + }; + + Post.prototype.addClone = function(context, contractThumb) { + return new Post.Clone(this, context, contractThumb); + }; + + Post.prototype.rmClone = function(index) { + var clone, j, len, ref; + this.clones.splice(index, 1); + ref = this.clones.slice(index); + for (j = 0, len = ref.length; j < len; j++) { + clone = ref[j]; + clone.nodes.root.dataset.clone = index++; + } + }; + + return Post; + + })(); + + return Post; + +}).call(this); + +(function() { + var extend = 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; }, + hasProp = {}.hasOwnProperty, + slice = [].slice; + + Post.Clone = (function(superClass) { + extend(_Class, superClass); + + _Class.prototype.isClone = true; + + function _Class(origin, context, contractThumb) { + var base, file, i, info, inline, inlined, j, k, key, l, len, len1, len2, len3, node, nodes, post, ref, ref1, ref2, ref3, ref4, ref5, root, val; + 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] = this.origin[key]; + } + nodes = this.origin.nodes; + root = contractThumb ? this.cloneWithoutVideo(nodes.root) : nodes.root.cloneNode(true); + (base = Post.Clone).prefix || (base.prefix = 0); + ref1 = [root].concat(slice.call($$('[id]', root))); + for (j = 0, len1 = ref1.length; j < len1; j++) { + node = ref1[j]; + node.id = Post.Clone.prefix + node.id; + } + Post.Clone.prefix++; + 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: [] + }; + if ($.engine === 'edge') { + Object.defineProperty(this.nodes, 'backlinks', { + configurable: true, + enumerable: true, + get: function() { + return info.getElementsByClassName('backlink'); + } + }); + } else { + this.nodes.backlinks = info.getElementsByClassName('backlink'); + } + ref2 = $$('.inline', post); + for (k = 0, len2 = ref2.length; k < len2; k++) { + inline = ref2[k]; + $.rm(inline); + } + ref3 = $$('.inlined', post); + for (l = 0, len3 = ref3.length; l < len3; l++) { + inlined = ref3[l]; + $.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(); + this.quotes = slice.call(this.origin.quotes); + if (this.origin.file) { + this.file = {}; + ref4 = this.origin.file; + for (key in ref4) { + val = ref4[key]; + this.file[key] = val; + } + file = $('.file', post); + this.file.text = file.firstElementChild; + this.file.link = $('.fileText > a, .fileText-original', file); + 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 ((ref5 = this.file.thumb) != null ? ref5.dataset.src : void 0) { + this.file.thumb.src = this.file.thumb.dataset.src; + this.file.thumb.removeAttribute('data-src'); + } + if (this.file.thumb && contractThumb) { + ImageExpand.contract(this); + } + } + if (this.origin.isDead) { + this.isDead = true; + } + root.dataset.clone = this.origin.clones.push(this) - 1; + } + + _Class.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 _Class; + + })(Post); + +}).call(this); + +RandomAccessList = (function() { + var RandomAccessList; + + RandomAccessList = (function() { + function RandomAccessList(items) { + var i, item, 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; + + })(); + + return RandomAccessList; + +}).call(this); + +ShimSet = (function() { + var ShimSet; + + 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; + } + + return ShimSet; + +}).call(this); + +SimpleDict = (function() { + var SimpleDict, + slice = [].slice; + + 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 j, key, len, ref; + ref = slice.call(this.keys); + for (j = 0, len = ref.length; j < len; j++) { + key = ref[j]; + fn(this[key]); + } + }; + + return SimpleDict; + + })(); + + return SimpleDict; + +}).call(this); + +Thread = (function() { + var Thread; + + Thread = (function() { + 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; + this.board.threads.push(this.ID, this); + g.threads.push(this.fullID, 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; + + })(); + + return Thread; + +}).call(this); + +Redirect = (function() { + var Redirect, + 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; }; + + Redirect = { + init: function() { + var archive, archives, boardID, boards, data, files, i, id, j, len, len1, name, o, record, ref, ref1, software, type, uid, withCredentials; + o = { + thread: {}, + post: {}, + file: {}, + report: {} + }; + archives = {}; + ref = Redirect.archives; + for (i = 0, len = ref.length; i < len; i++) { + data = ref[i]; + uid = data.uid, name = data.name, boards = data.boards, files = data.files, software = data.software, withCredentials = data.withCredentials; + archives[JSON.stringify(uid != null ? uid : name)] = data; + for (j = 0, len1 = boards.length; j < len1; j++) { + boardID = boards[j]; + if (!withCredentials) { + 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; + } + } + if (name === 'fgts') { + o.report[boardID] = data; + } + } + } + ref1 = Conf['selectedArchives']; + for (boardID in ref1) { + record = ref1[boardID]; + for (type in record) { + id = record[type]; + if (id === null) { + delete o[type][boardID]; + } else if (archive = archives[JSON.stringify(id)]) { + boards = type === 'file' ? archive.files : archive.boards; + if (indexOf.call(boards, boardID) >= 0) { + o[type][boardID] = archive; + } + } + } + } + return Redirect.data = o; + }, + archives: [ + { "uid": 3, "name": "4plebs", "domain": "archive.4plebs.org", "http": true, "https": true, "software": "foolfuuka", "boards": [ "adv", "f", "hr", "o", "pol", "s4s", "sp", "tg", "trv", "tv", "x" ], "files": [ "adv", "f", "hr", "o", "pol", "s4s", "sp", "tg", "trv", "tv", "x" ] }, + { "uid": 4, "name": "Nyafuu Archive", "domain": "archive.nyafuu.org", "http": true, "https": true, "software": "foolfuuka", "boards": [ "c", "e", "news", "w", "wg", "wsr" ], "files": [ "c", "e", "news", "w", "wg", "wsr" ] }, + { "uid": 8, "name": "Rebecca Black Tech", "domain": "rbt.asia", "http": false, "https": true, "software": "fuuka", "boards": [ "cgl", "g", "mu" ], "files": [ "cgl", "g", "mu" ] }, + { "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", "b", "cm", "gd", "h", "hc", "hm", "n", "out", "p", "po", "qa", "r", "s", "soc", "toy", "vp", "y" ], "files": [ "asp", "b", "cm", "gd", "h", "hc", "hm", "n", "out", "p", "po", "qa", "r", "s", "soc", "toy", "vp", "y" ] }, + { "uid": 23, "name": "Desustorage", "domain": "desustorage.org", "http": true, "https": true, "software": "foolfuuka", "boards": [ "a", "aco", "an", "c", "co", "d", "fit", "gif", "his", "int", "k", "m", "mlp", "qa", "r9k", "tg", "trash", "vr", "wsg" ], "files": [ "a", "aco", "an", "c", "co", "d", "fit", "gif", "his", "int", "k", "m", "mlp", "qa", "r9k", "tg", "trash", "vr", "wsg" ] }, + { "uid": 24, "name": "fireden.net", "domain": "boards.fireden.net", "http": false, "https": true, "software": "foolfuuka", "boards": [ "a", "cm", "ic", "sci", "tg", "v", "vg", "y" ], "files": [ "a", "cm", "ic", "sci", "tg", "v", "vg", "y" ] }, + { "uid": 25, "name": "arch.b4k.co", "domain": "arch.b4k.co", "http": true, "https": true, "software": "foolfuuka", "boards": [ "g", "jp", "mlp", "v" ], "files": [] }, + { "uid": 5, "name": "Love is Over", "domain": "deploy.loveisover.me", "http": true, "https": false, "software": "foolfuuka", "boards": [ "c", "d", "e", "i", "lgbt", "t", "u" ], "files": [ "c", "d", "e", "i", "lgbt", "t", "u" ], "search": [] }, + { "uid": 28, "name": "bstats", "domain": "archive.b-stats.org", "http": true, "https": true, "software": "foolfuuka", "boards": [ "f", "cm", "hm", "lgbt", "news", "trash", "y" ], "files": [] } + ], + 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 boardID, postID, protocol, url; + boardID = arg.boardID, postID = arg.postID; + protocol = Redirect.protocol(archive); + url = "" + protocol + archive.domain + "/_/api/chan/post/?board=" + boardID + "&num=" + postID; + if (!Redirect.securityCheck(url)) { + return ''; + } + 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 === 'MD5' ? 'image' : type; + if (type === 'capcode') { + value = { + 'Developer': 'dev' + }[value] || value.toLowerCase(); + } else if (type === 'image') { + value = value.replace(/[+\/=]/g, function(c) { + return { + '+': '-', + '/': '_', + '=': '' + }[c]; + }); + } + value = encodeURIComponent(value); + path = archive.software === 'foolfuuka' ? boardID + "/search/" + type + "/" + value + "/" : type === 'image' ? boardID + "/image/" + value : boardID + "/?task=search2&search_" + type + "=" + value; + return "" + (Redirect.protocol(archive)) + archive.domain + "/" + path; + }, + report: function(archive, arg) { + var boardID, postID; + boardID = arg.boardID, postID = arg.postID; + return "https://so.fgts.jp/report/?board=" + boardID + "&no=" + postID; + }, + securityCheck: function(url) { + return /^https:\/\//.test(url) || location.protocol === 'http:' || Conf['Exempt Archives from Encryption']; + }, + navigate: function(dest, data, alternative) { + var url; + if (!Redirect.data) { + Redirect.init(); + } + url = Redirect.to(dest, data); + 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); + } + } + }; + + return Redirect; + +}).call(this); + +Anonymize = (function() { + var Anonymize; + + 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 Callbacks.Post.push({ + name: 'Anonymize', + cb: this.node + }); + }, + node: function() { + var email, name, ref, tripcode; + 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 i, j, len, len1, name, ref, ref1, trip; + 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); + } + }); + } + }; + + return Anonymize; + +}).call(this); + +Filter = (function() { + var Filter, + 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; }; + + Filter = { + filters: {}, + init: function() { + var boards, err, excludes, filter, hl, i, key, len, line, op, ref, ref1, ref2, ref3, ref4, ref5, ref6, regexp, stub, top; + 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'; + boards = boards === 'global' ? null : boards.split(','); + if (boards === null) { + excludes = ((ref3 = filter.match(/exclude:([^;]+)/)) != null ? ref3[1].toLowerCase().split(',') : void 0) || null; + } + 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, boards, excludes, op, stub, hl, top)); + } + if (!this.filters[key].length) { + delete this.filters[key]; + } + } + if (!Object.keys(this.filters).length) { + return; + } + return Callbacks.Post.push({ + name: 'Filter', + cb: this.node + }); + }, + createFilter: function(regexp, boards, excludes, 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, boardID, isReply) { + if (boards && indexOf.call(boards, boardID) < 0) { + return false; + } + if (excludes && indexOf.call(excludes, boardID) >= 0) { + return false; + } + if (isReply && op === 'only' || !isReply && op === 'no') { + return false; + } + if (!test(value)) { + return false; + } + return settings; + }; + }, + node: function() { + var filter, i, key, len, ref, ref1, result, value; + if (this.isClone) { + return; + } + for (key in Filter.filters) { + if ((value = Filter[key](this)) != null) { + ref = Filter.filters[key]; + for (i = 0, len = ref.length; i < len; i++) { + filter = ref[i]; + if (!(result = filter(value, this.board.ID, this.isReply))) { + continue; + } + if (result.hide && !this.isFetchedQuote) { + 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; + } + } + } + } + }, + isHidden: function(post) { + var filter, i, key, len, ref, result, value; + for (key in Filter.filters) { + if ((value = Filter[key](post)) != null) { + ref = Filter.filters[key]; + for (i = 0, len = ref.length; i < len; i++) { + filter = ref[i]; + if (result = filter(value, post.boardID, post.isReply)) { + if (result.hide) { + return true; + } + } + } + } + } + return false; + }, + postID: function(post) { + var ref; + return "" + ((ref = post.ID) != null ? ref : post.postID); + }, + name: function(post) { + return post.info.name; + }, + uniqueID: function(post) { + return post.info.uniqueID; + }, + tripcode: function(post) { + return post.info.tripcode; + }, + capcode: function(post) { + return post.info.capcode; + }, + subject: function(post) { + return post.info.subject; + }, + comment: function(post) { + var base; + return (base = post.info).comment != null ? base.comment : base.comment = Build.parseComment(post.info.commentHTML.innerHTML); + }, + flag: function(post) { + return post.info.flag; + }, + filename: function(post) { + var ref; + return (ref = post.file) != null ? ref.name : void 0; + }, + dimensions: function(post) { + var ref; + return (ref = post.file) != null ? ref.dimensions : void 0; + }, + filesize: function(post) { + var ref; + return (ref = post.file) != null ? ref.size : void 0; + }, + MD5: function(post) { + var ref; + return (ref = post.file) != null ? ref.MD5 : void 0; + }, + menu: { + init: function() { + var div, entry, i, len, ref, ref1, type; + 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 != null; + } + }; + }, + 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(); + }); + } + } + }; + + return Filter; + +}).call(this); + +PostHiding = (function() { + var PostHiding; + + 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 Callbacks.Post.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, ref, replies, thisPost; + if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Menu'] || !Conf['Reply Hiding Link']) { + return; + } + div = $.el('div', { + className: 'hide-reply-link', + textContent: 'Hide' + }); + 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' + }); + 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, i, len, quotelink, 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 i, len, quotelink, 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'); + } + } + }; + + return PostHiding; + +}).call(this); + +Recursive = (function() { + var Recursive, + 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; }; + + Recursive = { + recursives: {}, + init: function() { + var ref; + if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { + return; + } + return Callbacks.Post.push({ + name: 'Recursive', + cb: this.node + }); + }, + node: function() { + var i, j, k, len, len1, obj, quote, recursive, ref, ref1; + if (this.isClone || this.isFetchedQuote) { + return; + } + ref = this.quotes; + for (j = 0, len = ref.length; j < len; j++) { + quote = ref[j]; + if (obj = Recursive.recursives[quote]) { + ref1 = obj.recursives; + for (i = k = 0, len1 = ref1.length; k < len1; i = ++k) { + recursive = ref1[i]; + recursive.apply(null, [this].concat(slice.call(obj.args[i]))); + } + } + } + }, + add: function() { + var args, base, name, obj, post, recursive; + 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, j, len, obj, rec, ref; + if (!(obj = Recursive.recursives[post.fullID])) { + return; + } + ref = obj.recursives; + for (i = j = 0, len = ref.length; j < len; i = ++j) { + 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))); + } + }); + } + }; + + return Recursive; + +}).call(this); + +ThreadHiding = (function() { + var ThreadHiding; + + ThreadHiding = { + init: function() { + var ref; + if (((ref = g.VIEW) !== 'index' && ref !== 'catalog') || !Conf['Thread Hiding Buttons'] && !(Conf['Menu'] && Conf['Thread Hiding Link']) && !Conf['JSON Index']) { + return; + } + this.db = new DataBoard('hiddenThreads'); + if (g.VIEW === 'catalog') { + return this.catalogWatch(); + } + this.catalogSet(g.BOARD); + return Callbacks.Post.push({ + name: 'Thread Hiding', + cb: this.node + }); + }, + catalogSet: function(board) { + var hiddenThreads, threadID; + if (!$.hasStorage) { + return; + } + 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() { + if (!$.hasStorage) { + return; + } + this.hiddenThreads = JSON.parse(localStorage.getItem("4chan-hide-t-" + g.BOARD)) || {}; + return Main.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 (this.isReply || this.isClone || this.isFetchedQuote) { + return; + } + if (data = ThreadHiding.db.get({ + boardID: this.board.ID, + threadID: this.ID + })) { + ThreadHiding.hide(this.thread, data.makeStub); + } + if (!Conf['Thread Hiding Buttons']) { + return; + } + return $.prepend(this.nodes.root, ThreadHiding.makeButton(this.thread, 'hide')); + }, + onIndexBuild: function(nodes) { + var i, len, root, thread; + 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' + }); + 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 Index'] && 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', + 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 Index'] && 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 Index'] && 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: "" + }); + 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 Index']) { + 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 Index']) { + return Index.updateHideLabel(); + } + } + }; + + return ThreadHiding; + +}).call(this); + +Build = (function() { + var Build, + slice = [].slice; + + 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|#44);/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; + } + }, + spoilerThumb: function(boardID) { + var spoilerRange; + if (spoilerRange = Build.spoilerRange[boardID]) { + return Build.staticPath + "spoiler-" + boardID + (Math.floor(1 + spoilerRange * Math.random())) + ".png"; + } else { + return Build.staticPath + "spoiler.png"; + } + }, + 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; + } + }, + parseJSON: function(data, boardID) { + var o; + o = { + postID: data.no, + threadID: data.resto || data.no, + boardID: boardID, + isReply: !!data.resto, + isSticky: !!data.sticky, + isClosed: !!data.closed, + isArchived: !!data.archived, + fileDeleted: !!data.filedeleted + }; + o.info = { + subject: Build.unescape(data.sub), + email: Build.unescape(data.email), + name: Build.unescape(data.name) || '', + tripcode: data.trip, + uniqueID: data.id, + flagCode: data.country, + flag: Build.unescape(data.country_name), + dateUTC: data.time, + dateText: data.now, + commentHTML: { + innerHTML: data.com || '' + } + }; + if (data.capcode) { + o.info.capcode = data.capcode.replace(/_highlight$/, '').replace(/_/g, ' ').replace(/\b\w/g, function(c) { + return c.toUpperCase(); + }); + o.capcodeHighlight = /_highlight$/.test(data.capcode); + delete o.info.uniqueID; + } + if (data.ext) { + o.file = { + name: (Build.unescape(data.filename)) + data.ext, + url: boardID === 'f' ? location.protocol + "//i.4cdn.org/" + boardID + "/" + (encodeURIComponent(data.filename)) + data.ext : location.protocol + "//i.4cdn.org/" + boardID + "/" + data.tim + data.ext, + height: data.h, + width: data.w, + MD5: data.md5, + size: $.bytesToString(data.fsize), + thumbURL: location.protocol + "//i.4cdn.org/" + boardID + "/" + data.tim + "s.jpg", + theight: data.tn_h, + twidth: data.tn_w, + isSpoiler: !!data.spoiler, + tag: data.tag + }; + if (!/\.pdf$/.test(o.file.url)) { + o.file.dimensions = o.file.width + "x" + o.file.height; + } + } + return o; + }, + parseComment: function(html) { + html = html.replace(//gi, '\n').replace(/\n\nRolled [^<]*<\/b>/i, '').replace(/]*>/g, ''); + return Build.unescape(html); + }, + postFromObject: function(data, boardID, suppressThumb) { + var o; + o = Build.parseJSON(data, boardID); + return Build.post(o, suppressThumb); + }, + post: function(o, suppressThumb) { + var boardID, capcode, capcodeDescription, capcodeLC, capcodeLong, capcodePlural, commentHTML, container, dateText, dateUTC, email, file, fileBlock, fileThumb, fileURL, flag, flagCode, gifIcon, href, i, len, match, name, postClass, postID, postInfo, postLink, protocol, quote, quoteLink, ref, ref1, shortFilename, staticPath, subject, threadID, tripcode, uniqueID, wholePost; + postID = o.postID, threadID = o.threadID, boardID = o.boardID, file = o.file; + ref = o.info, subject = ref.subject, email = ref.email, name = ref.name, tripcode = ref.tripcode, capcode = ref.capcode, uniqueID = ref.uniqueID, flagCode = ref.flagCode, flag = ref.flag, dateUTC = ref.dateUTC, dateText = ref.dateText, commentHTML = ref.commentHTML; + staticPath = Build.staticPath, gifIcon = Build.gifIcon; + + /* Post Info */ + if (capcode) { + capcodeLC = capcode.toLowerCase(); + if (capcode === 'Founder') { + capcodePlural = 'the Founder'; + capcodeDescription = "4chan's Founder"; + } else { + capcodeLong = { + 'Admin': 'Administrator', + 'Mod': 'Moderator' + }[capcode] || capcode; + capcodePlural = capcodeLong + "s"; + capcodeDescription = "a 4chan " + capcodeLong; + } + } + postLink = Build.postURL(boardID, threadID, postID); + quoteLink = Build.sameThread(boardID, threadID) ? "javascript:quote('" + (+postID) + "');" : "/" + boardID + "/thread/" + threadID + "#q" + postID; + postInfo = { + innerHTML: "
            " + ((!o.isReply || boardID === "f" || subject) ? "" + E(subject || "") + " " : "") + "" + ((email) ? "" : "") + "" + E(name) + "" + ((tripcode) ? " " + E(tripcode) + "" : "") + ((capcode) ? " ## " + E(capcode) + "" : "") + ((email) ? "" : "") + ((boardID === "f" && !o.isReply || capcode) ? "" : " ") + ((capcode) ? " \""" : "") + ((uniqueID && !capcode) ? " (ID: " + E(uniqueID) + ")" : "") + ((flagCode) ? " " : "") + " " + E(dateText) + " No." + E(postID) + "" + ((o.isSticky) ? " \"Sticky\"" : "") + ((o.isClosed && !o.isArchived) ? " \"Closed\"" : "") + ((o.isArchived) ? " \"Archived\"" : "") + ((!o.isReply && g.VIEW === "index") ? "   [Reply]" : "") + "
            " + }; + + /* File Info */ + if (file) { + protocol = /^https?:(?=\/\/i\.4cdn\.org\/)/; + fileURL = file.url.replace(protocol, ''); + shortFilename = Build.shortFilename(file.name); + fileThumb = file.isSpoiler ? Build.spoilerThumb(boardID) : file.thumbURL.replace(protocol, ''); + } + fileBlock = { + innerHTML: ((file) ? "
            " + ((boardID === "f") ? "
            File: " + E(file.name) + "-(" + E(file.size) + ", " + E(file.dimensions) + ((file.tag) ? ", " + E(file.tag) : "") + ")
            " : "
            File: " + ((file.isSpoiler) ? "Spoiler Image" : E(shortFilename)) + " (" + E(file.size) + ", " + E(file.dimensions || "PDF") + ")
            ") + "
            " : ((o.fileDeleted) ? "
            \"File
            " : "")) + }; + + /* Whole Post */ + postClass = o.isReply ? 'reply' : 'op'; + wholePost = { + innerHTML: ((o.isReply) ? "
            >>
            " : "") + "
            " + ((o.isReply) ? (postInfo).innerHTML + (fileBlock).innerHTML : (fileBlock).innerHTML + (postInfo).innerHTML) + "
            " + (commentHTML).innerHTML + "
            " + }; + container = $.el('div', { + className: "postContainer " + postClass + "Container", + id: "pc" + postID + }); + $.extend(container, wholePost); + ref1 = $$('.quotelink', container); + for (i = 0, len = ref1.length; i < len; i++) { + quote = ref1[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] || '#'; + } else if (/^\d+(#|$)/.test(href) && !(g.VIEW === 'thread' && g.BOARD.ID === boardID)) { + quote.href = "/" + boardID + "/thread/" + href; + } + } + return container; + }, + summaryText: function(status, posts, files) { + var text; + text = ''; + if (status) { + text += status + " "; + } + text += posts + " post" + (posts > 1 ? 's' : ''); + if (+files) { + text += " and " + files + " image repl" + (files > 1 ? 'ies' : 'y'); + } + return text += " " + (status === '-' ? 'shown' : 'omitted') + "."; + }, + summary: function(boardID, threadID, posts, files) { + return $.el('a', { + className: 'summary', + textContent: Build.summaryText('', posts, files), + href: "/" + boardID + "/thread/" + threadID + }); + }, + thread: function(board, data, full) { + var OP, root; + Build.spoilerRange[board] = data.custom_spoiler; + if (OP = board.posts[data.no]) { + if (OP.isFetchedQuote) { + OP = null; + } + } + if (OP && (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, true)]; + 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, i, imgClass, j, k, l, len, len1, len2, len3, pageCount, postCount, pp, quote, ref, ref1, ref2, ref3, ref4, root, spoilerRange, src, staticPath; + 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'; + } + postCount = data.replies + 1; + fileCount = data.images + !!data.ext; + pageCount = Math.floor(Index.liveThreadIDs.indexOf(thread.ID) / Index.threadsNumPerPage) + 1; + comment = { + innerHTML: data.com || '' + }; + root = $.el('div', { + className: 'catalog-thread' + }); + $.extend(root, { + innerHTML: "
            " + E(postCount) + " / " + E(fileCount) + " / " + E(pageCount) + "
            " + ((thread.OP.info.subject) ? "
            " + E(thread.OP.info.subject) + "
            " : "") + "
            " + (comment).innerHTML + "
            " + }); + 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; + } + }; + + return Build; + +}).call(this); + +(function() { + + +}).call(this); + +Get = (function() { + var Get, + 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; }; + + 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.commentDisplay.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 index, post; + if (root == null) { + return null; + } + post = g.posts[root.dataset.fullID]; + index = root.dataset.clone; + 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)); + }, + postDataFromLink: function(link) { + var boardID, path, postID, ref, threadID; + 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, i, len, posts, qPost, quote, quotelinks, 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 i, len, ref, script; + 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 ''; + } + }; + + return Get; + +}).call(this); + +Header = (function() { + var Header; + + 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: "" + }); + 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 popstate', 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 absbot, oldFooter; + if ((oldFooter = $.id('boardNavDesktopFoot'))) { + return $.replace($('.boardList', oldFooter), Header.bottomBoardList); + } else if ((absbot = $.id('absbot'))) { + $.before(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, i, j, len, len1, node, nodes, ref, ref1, spacer, span; + Header.boardList = boardList = $.el('span', { + id: 'board-list' + }); + $.extend(boardList, { + innerHTML: "" + }); + 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|(mode|sort|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, indexOptions, 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 ''; + }); + indexOptions = []; + t = t.replace(/-(?:mode|sort):"([^"]+)"/g, function(m0, m1) { + indexOptions.push(m1.toLowerCase().replace(/\ /g, '-')); + return ''; + }); + indexOptions = indexOptions.join('/'); + 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)/)) { + if (!(boardID === 'f' && m[1] === 'catalog')) { + a.dataset.only = m[1]; + a.href = CatalogLinks[m[1]](boardID); + if (m[1] === 'catalog') { + $.addClass(a, 'catalog'); + } + } else { + return a.firstChild; + } + } + if (Conf['JSON Index'] && indexOptions) { + a.dataset.indexOptions = indexOptions; + if (a.hostname === 'boards.4chan.org' && a.pathname.split('/')[2] === '') { + a.href += (a.hash ? '/' : '#') + indexOptions; + } + } + 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' && boardID !== 'trash') { + 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() { + 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(e) { + var el, hash; + if (e) { + if (e.state) { + return; + } + if (!history.state) { + history.replaceState({}, ''); + } + } + if ((hash = location.hash.slice(1))) { + ReplyPruning.showIfHidden(hash); + if ((el = $.id(hash))) { + return $.queueTask(function() { + return Header.scrollTo(el); + }); + } + } + }, + scrollTo: function(root, down, needed) { + var height, x; + if (!root.offsetParent) { + return; + } + if (down) { + x = Header.getBottomOf(root); + if (Conf['Fixed Header'] && 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['Fixed Header'] && 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['Fixed Header'] && 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, ref, type; + 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: "4chan X needs your permission to show desktop notifications. [FAQ]
            or " + }); + 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); + } + }; + + return Header; + +}).call(this); + +Index = (function() { + var Index, + 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; }; + + Index = { + showHiddenThreads: false, + changed: {}, + init: function() { + var anchorEntry, input, j, k, label, len, len1, name, pinEntry, ref, ref1, ref2, ref3, ref4, ref5, ref6, refNavEntry, repliesEntry, select, sortEntry; + if (g.BOARD.ID === 'f' || !Conf['JSON Index'] || g.VIEW !== 'index') { + return; + } + Callbacks.CatalogThread.push({ + name: 'Catalog Features', + cb: this.catalogNode + }); + this.search = ((ref = history.state) != null ? ref.searched : void 0) || ''; + if ((ref1 = history.state) != null ? ref1.mode : void 0) { + Conf['Index Mode'] = (ref2 = history.state) != null ? ref2.mode : void 0; + } + this.currentSort = (ref3 = history.state) != null ? ref3.sort : void 0; + this.currentSort || (this.currentSort = typeof Conf['Index Sort'] === 'object' ? Conf['Index Sort'][g.BOARD.ID] || 'bump' : Conf['Index Sort']); + this.currentPage = this.getCurrentPage(); + this.processHash(); + $.addClass(doc, 'index-loading', (Conf['Index Mode'].replace(/\ /g, '-')) + "-mode"); + $.on(window, 'popstate', this.cb.popstate); + $.on(d, 'scroll', Index.scroll); + 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') + }; + sortEntry = { + el: UI.checkbox('Per-Board Sort Type', 'Per-board sort type', typeof Conf['Index Sort'] === 'object') + }; + 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') + }; + sortEntry.el.title = 'Set the sorting order of each board independently.'; + 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 (j = 0, len = ref4.length; j < len; j++) { + label = ref4[j]; + 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.resort); + } + } + $.on(sortEntry.el.firstChild, 'change', this.cb.perBoardSort); + Header.menu.addEntry({ + el: $.el('span', { + textContent: 'Index Navigation' + }), + order: 100, + subEntries: [repliesEntry, sortEntry, pinEntry, anchorEntry, refNavEntry] + }); + this.navLinks = $.el('div', { + className: 'navLinks json-index' + }); + $.extend(this.navLinks, { + innerHTML: "Index Catalog Archive Bottom ×" + }); + $('.cataloglink a', this.navLinks).href = CatalogLinks.catalog(); + if ((ref5 = g.BOARD.ID) === 'b' || ref5 === 'trash') { + $('.archlistlink', this.navLinks).hidden = true; + } + $.on($('#index-last-refresh a', this.navLinks), 'click', this.cb.refreshFront); + this.searchInput = $('#index-search', this.navLinks); + this.setupSearch(); + $.on(this.searchInput, 'input', this.onSearchInput); + $.on($('#index-search-clear', this.navLinks), 'click', this.clearSearch); + this.hideLabel = $('#hidden-label', this.navLinks); + $.on($('#hidden-toggle a', this.navLinks), 'click', this.cb.toggleHiddenThreads); + this.selectMode = $('#index-mode', this.navLinks); + this.selectSort = $('#index-sort', this.navLinks); + this.selectSize = $('#index-size', this.navLinks); + $.on(this.selectMode, 'change', this.cb.mode); + $.on(this.selectSort, 'change', this.cb.sort); + $.on(this.selectSize, 'change', $.cb.value); + $.on(this.selectSize, 'change', this.cb.size); + ref6 = [this.selectMode, this.selectSize]; + for (k = 0, len1 = ref6.length; k < len1; k++) { + select = ref6[k]; + select.value = Conf[select.name]; + } + this.selectSort.value = Index.currentSort; + this.root = $.el('div', { + className: 'board json-index' + }); + this.cb.size(); + this.pagelist = $.el('div', { + className: 'pagelist json-index' + }); + $.extend(this.pagelist, { + innerHTML: "
            " + }); + $('.cataloglink a', this.pagelist).href = CatalogLinks.catalog(); + $.on(this.pagelist, 'click', this.cb.pageNav); + this.update(true); + $.onExists(doc, 'title + *', function() { + return d.title = d.title.replace(/\ -\ Page\ \d+/, ''); + }); + $.onExists(doc, '.board > .thread > .postContainer, .board + *', function() { + var board, el, l, len2, len3, m, ref7, ref8, threadRoot, topNavPos; + Index.hat = $('.board > .thread > img:first-child'); + if (Index.hat) { + if (Index.nodes) { + ref7 = Index.nodes; + for (l = 0, len2 = ref7.length; l < len2; l++) { + threadRoot = ref7[l]; + $.prepend(threadRoot, Index.hat.cloneNode(false)); + } + } + $.addClass(doc, 'hats-enabled'); + $.addStyle(".catalog-thread::after {background-image: url(" + Index.hat.src + ");}"); + } + board = $('.board'); + $.replace(board, Index.root); + $.event('PostsInserted'); + try { + d.implementation.createDocument(null, null, null).appendChild(board); + } catch (_error) {} + ref8 = $$('.navLinks'); + for (m = 0, len3 = ref8.length; m < len3; m++) { + el = ref8[m]; + $.rm(el); + } + $.rm($.id('ctrl-top')); + topNavPos = $.id('delform').previousElementSibling; + $.before(topNavPos, $.el('hr')); + return $.before(topNavPos, Index.navLinks); + }); + return Main.ready(function() { + var pagelist; + if ((pagelist = $('.pagelist'))) { + $.replace(pagelist, Index.pagelist); + } + return $.rmClass(doc, 'index-loading'); + }); + }, + scroll: function() { + var nodes, pageNum; + if (Index.req || !Index.liveThreadData || Conf['Index Mode'] !== 'infinite' || (window.scrollY <= doc.scrollHeight - (300 + window.innerHeight))) { + return; + } + if (Index.pageNum == null) { + Index.pageNum = Index.currentPage; + } + 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 Index'] || !Conf['Menu'] || !Conf['Thread Hiding Link'] || g.BOARD.ID === 'f') { + return; + } + return Menu.menu.addEntry({ + el: $.el('a', { + href: 'javascript:;', + className: 'has-shortcut-text' + }, { + innerHTML: "Shift+click" + }), + order: 20, + open: function(arg) { + var thread; + thread = arg.thread; + if (Conf['Index Mode'] !== 'catalog') { + return false; + } + this.el.firstElementChild.textContent = thread.isHidden ? 'Unhide' : 'Hide'; + 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, j, len, type, types; + types = slice.call(Index.selectSort.options).filter(function(option) { + return !option.disabled; + }); + for (i = j = 0, len = types.length; j < len; i = ++j) { + 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() { + Index.pushState({ + mode: this.value + }); + return Index.pageLoad(false); + }, + sort: function() { + Index.pushState({ + sort: this.value + }); + return Index.pageLoad(false); + }, + resort: function() { + Index.sort(); + return Index.buildIndex(); + }, + perBoardSort: function() { + Conf['Index Sort'] = this.checked ? {} : ''; + return Index.saveSort(); + }, + 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, nCommands, page, ref, searched, sort; + if (e != null ? e.state : void 0) { + ref = e.state, searched = ref.searched, mode = ref.mode, sort = ref.sort; + page = Index.getCurrentPage(); + Index.setState({ + search: searched, + mode: mode, + sort: sort, + page: page + }); + return Index.pageLoad(false); + } else { + nCommands = Index.processHash(); + if (Conf['Refreshed Navigation'] && nCommands) { + return Index.update(); + } else { + return Index.pageLoad(); + } + } + }, + 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); + }, + refreshFront: function() { + Index.pushState({ + page: 1 + }); + return Index.update(); + } + }, + scrollToIndex: function() { + return Header.scrollToIfNeeded((Index.navLinks.getBoundingClientRect().height ? Index.navLinks : Index.root)); + }, + getCurrentPage: function() { + return +window.location.pathname.split(/\/+/)[2] || 1; + }, + userPageNav: function(page) { + Index.pushState({ + page: page + }); + if (Conf['Refreshed Navigation']) { + return Index.update(); + } else { + return Index.pageLoad(); + } + }, + hashCommands: { + mode: { + 'paged': 'paged', + 'infinite-scrolling': 'infinite', + 'infinite': 'infinite', + 'all-threads': 'all pages', + 'all-pages': 'all pages', + 'catalog': 'catalog' + }, + sort: { + 'bump-order': 'bump', + 'last-reply': 'lastreply', + 'last-long-reply': 'lastlong', + 'creation-date': 'birth', + 'reply-count': 'replycount', + 'file-count': 'filecount' + } + }, + processHash: function() { + var command, commands, hash, j, leftover, len, mode, ref, sort, state; + hash = ((ref = location.href.match(/#.*/)) != null ? ref[0] : void 0) || ''; + state = { + replace: true + }; + commands = hash.slice(1).split('/'); + leftover = []; + for (j = 0, len = commands.length; j < len; j++) { + command = commands[j]; + if ((mode = Index.hashCommands.mode[command])) { + state.mode = mode; + } else if (command === 'index') { + state.mode = Conf['Previous Index Mode']; + state.page = 1; + } else if ((sort = Index.hashCommands.sort[command])) { + state.sort = sort; + } else if (/^s=/.test(command)) { + state.search = decodeURIComponent(command.slice(2)).replace(/\+/g, ' ').trim(); + } else { + leftover.push(command); + } + } + hash = leftover.join('/'); + if (hash) { + state.hash = "#" + hash; + } + Index.pushState(state); + return commands.length - leftover.length; + }, + pushState: function(state) { + var hash, pageBeforeSearch, pathname, ref, replace, search; + search = state.search, hash = state.hash, replace = state.replace; + pageBeforeSearch = (ref = history.state) != null ? ref.oldpage : void 0; + if ((search != null) && search !== Index.search) { + state.page = search ? 1 : pageBeforeSearch || 1; + if (!search) { + pageBeforeSearch = void 0; + } else if (!Index.search) { + pageBeforeSearch = Index.currentPage; + } + } + Index.setState(state); + pathname = Index.currentPage === 1 ? "/" + g.BOARD + "/" : "/" + g.BOARD + "/" + Index.currentPage; + hash || (hash = ''); + return history[replace ? 'replaceState' : 'pushState']({ + mode: Conf['Index Mode'], + sort: Index.currentSort, + searched: Index.search, + oldpage: pageBeforeSearch + }, '', location.protocol + "//" + location.host + pathname + hash); + }, + setState: function(arg) { + var hash, mode, page, ref, search, sort; + search = arg.search, mode = arg.mode, sort = arg.sort, page = arg.page, hash = arg.hash; + if ((search != null) && search !== Index.search) { + Index.changed.search = true; + Index.search = search; + } + if ((mode != null) && mode !== Conf['Index Mode']) { + Index.changed.mode = true; + Conf['Index Mode'] = mode; + $.set('Index Mode', mode); + if (!(mode === 'catalog' || Conf['Previous Index Mode'] === mode)) { + Conf['Previous Index Mode'] = mode; + $.set('Previous Index Mode', mode); + } + } + if ((sort != null) && sort !== Index.currentSort) { + Index.changed.sort = true; + Index.currentSort = sort; + Index.saveSort(); + } + if ((ref = Conf['Index Mode']) === 'all pages' || ref === 'catalog') { + page = 1; + } + if ((page != null) && page !== Index.currentPage) { + Index.changed.page = true; + Index.currentPage = page; + } + if (hash != null) { + return Index.changed.hash = true; + } + }, + saveSort: function() { + if (typeof Conf['Index Sort'] === 'object') { + Conf['Index Sort'][g.BOARD.ID] = Index.currentSort; + } else { + Conf['Index Sort'] = Index.currentSort; + } + return $.set('Index Sort', Conf['Index Sort']); + }, + pageLoad: function(scroll) { + var hash, mode, page, ref, search, sort, threads; + if (scroll == null) { + scroll = true; + } + if (!Index.liveThreadData) { + return; + } + ref = Index.changed, threads = ref.threads, search = ref.search, mode = ref.mode, sort = ref.sort, page = ref.page, hash = ref.hash; + if (threads || search || sort) { + Index.sort(); + } + if (threads || search) { + Index.buildPagelist(); + } + if (search) { + Index.setupSearch(); + } + if (mode) { + Index.setupMode(); + } + if (sort) { + Index.setupSort(); + } + if (threads || search || mode || page || sort) { + Index.buildIndex(); + } + if (threads || search || mode || page) { + Index.setPage(); + } + if (scroll && !hash) { + Index.scrollToIndex(); + } + if (hash) { + Header.hashScroll(); + } + return Index.changed = {}; + }, + setupMode: function() { + var j, len, mode, ref; + ref = ['paged', 'infinite', 'all pages', 'catalog']; + for (j = 0, len = ref.length; j < len; j++) { + mode = ref[j]; + $[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'; + }, + setupSort: function() { + return Index.selectSort.value = Index.currentSort; + }, + 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, j, maxPageNum, nodes, pagesRoot, ref; + pagesRoot = $('.pages', Index.pagelist); + maxPageNum = Index.getMaxPageNum(); + if (pagesRoot.childElementCount !== maxPageNum) { + nodes = []; + for (i = j = 1, ref = maxPageNum; j <= ref; i = j += 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.currentPage; + 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, ref, ref1, thread, threadID; + 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(firstTime) { + var now, ref, ref1; + if ((ref = Index.req) != null) { + ref.abort(); + } + if ((ref1 = Index.notice) != null) { + ref1.close(); + } + if (Conf['Index Refresh Notifications'] && d.readyState !== 'loading') { + Index.notice = new Notice('info', 'Refreshing index...'); + } else { + now = Date.now(); + $.ready(function() { + return Index.nTimeout = setTimeout((function() { + if (Index.req && !Index.notice) { + return Index.notice = new Notice('info', 'Refreshing index...'); + } + }), 3 * $.SECOND - (Date.now() - now)); + }); + } + if (!firstTime && d.readyState !== 'loading' && !$('.board + *')) { + location.reload(); + return; + } + Index.req = $.ajax("//a.4cdn.org/" + g.BOARD + "/catalog.json", { + onabort: Index.load, + onloadend: Index.load + }, { + whenModified: 'Index' + }); + return $.addClass(Index.button, 'fa-spin'); + }, + load: function(e) { + var err, nTimeout, notice, ref, req, timeEl; + $.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; + if (notice != 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); + } else if (req.status === 304) { + Index.pageLoad(); + } + } 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; + } + if (notice) { + if (Conf['Index Refresh Notifications']) { + notice.setType('success'); + notice.el.lastElementChild.textContent = 'Index refreshed!'; + setTimeout(notice.close, $.SECOND); + } else { + notice.close(); + } + } + timeEl = $('#index-last-refresh time', Index.navLinks); + timeEl.dataset.utc = Date.parse(req.getResponseHeader('Last-Modified')); + return RelativeDates.update(timeEl); + }, + parse: function(pages) { + $.cleanCache(function(url) { + return /^\/\/a\.4cdn\.org\//.test(url); + }); + Index.parseThreadList(pages); + Index.buildThreads(); + Index.changed.threads = true; + return Index.pageLoad(); + }, + parseThreadList: function(pages) { + var ref; + Index.pagesNum = pages.length; + Index.threadsNumPerPage = ((ref = pages[0]) != null ? ref.threads.length : void 0) || 1; + 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 ref1; + if (ref1 = thread.ID, indexOf.call(Index.liveThreadIDs, ref1) < 0) { + return thread.collect(); + } + }); + }, + buildThreads: function() { + var err, errors, i, j, len, posts, ref, thread, threadData, threadRoot, threads; + if (!Index.liveThreadData) { + return; + } + Index.nodes = []; + threads = []; + posts = []; + ref = Index.liveThreadData; + for (i = j = 0, len = ref.length; j < len; i = ++j) { + 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.OP && !thread.OP.isFetchedQuote)) { + 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, j, k, lastReplies, len, len1, node, nodes, post, posts, thread, threadRoot; + posts = []; + for (j = 0, len = threadRoots.length; j < len; j++) { + threadRoot = threadRoots[j]; + thread = Get.threadFromRoot(threadRoot); + i = Index.liveThreadIDs.indexOf(thread.ID); + if (!(lastReplies = Index.liveThreadData[i].last_replies)) { + continue; + } + nodes = []; + for (k = 0, len1 = lastReplies.length; k < len1; k++) { + data = lastReplies[k]; + if ((post = thread.posts[data.no]) && !post.isFetchedQuote) { + 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, j, len, thread, threads; + threads = Index.sortedNodes.map(function(threadRoot) { + return Get.threadFromRoot(threadRoot); + }).filter(function(thread) { + return !thread.isHidden !== Index.showHiddenThreads; + }); + catalogThreads = []; + for (j = 0, len = threads.length; j < len; j++) { + thread = threads[j]; + 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, j, len, node, ratio, ref, size, thumb, width; + size = Conf['Index Size'] === 'small' ? 150 : 250; + for (j = 0, len = nodes.length; j < len; j++) { + node = nodes[j]; + 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 j, lastlong, len, liveThreadData, liveThreadIDs, nodes, sortedNodes, sortedThreadIDs, threadID; + liveThreadIDs = Index.liveThreadIDs, liveThreadData = Index.liveThreadData; + if (!liveThreadData) { + return; + } + sortedThreadIDs = (function() { + switch (Index.currentSort) { + case 'lastreply': + return 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; + }); + case 'lastlong': + lastlong = function(thread) { + var i, j, r, ref; + ref = thread.last_replies || []; + for (i = j = ref.length - 1; j >= 0; i = j += -1) { + r = ref[i]; + if (r.com && Build.parseComment(r.com).replace(/[^a-z]/ig, '').length >= 100) { + return r; + } + } + return thread; + }; + return slice.call(liveThreadData).sort(function(a, b) { + return lastlong(b).no - lastlong(a).no; + }).map(function(post) { + return post.no; + }); + case 'bump': + return liveThreadIDs; + case 'birth': + return slice.call(liveThreadIDs).sort(function(a, b) { + return b - a; + }); + case 'replycount': + return slice.call(liveThreadData).sort(function(a, b) { + return b.replies - a.replies; + }).map(function(post) { + return post.no; + }); + case 'filecount': + return slice.call(liveThreadData).sort(function(a, b) { + return b.images - a.images; + }).map(function(post) { + return post.no; + }); + } + })(); + Index.sortedNodes = sortedNodes = []; + nodes = Index.nodes; + for (j = 0, len = sortedThreadIDs.length; j < len; j++) { + threadID = sortedThreadIDs[j]; + 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, j, len, ref, threadRoot, topNodes; + topNodes = []; + bottomNodes = []; + ref = Index.sortedNodes; + for (j = 0, len = ref.length; j < len; j++) { + threadRoot = ref[j]; + (match(Get.threadFromRoot(threadRoot)) ? topNodes : bottomNodes).push(threadRoot); + } + return Index.sortedNodes = topNodes.concat(bottomNodes); + }, + buildIndex: function() { + var i, nodes, page, post; + if (!Index.liveThreadData) { + return; + } + 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.currentPage) { + Index.currentPage = page; + Index.pushState({ + page: page + }); + Index.setPage(); + } + } + nodes = Index.buildSinglePage(Index.currentPage); + } + delete Index.pageNum; + $.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 j, len, node, thumb; + for (j = 0, len = nodes.length; j < len; j++) { + node = nodes[j]; + if (thumb = $('img[data-src]', node)) { + thumb.src = thumb.dataset.src; + thumb.removeAttribute('data-src'); + } + $.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() { + 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; + } + Index.pushState({ + search: search, + replace: !!search === !!Index.search + }); + return Index.pageLoad(false); + }, + 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, j, k, key, keyword, len, len1, ref, ref1, text; + ref = thread.OP, info = ref.info, file = ref.file; + text = []; + ref1 = ['comment', 'subject', 'name', 'tripcode', 'email']; + for (j = 0, len = ref1.length; j < len; j++) { + key = ref1[j]; + if (key in info) { + text.push(info[key]); + } + } + if (file) { + text.push(file.name); + } + text = text.join(' ').toLowerCase(); + for (k = 0, len1 = keywords.length; k < len1; k++) { + keyword = keywords[k]; + if (-1 === text.indexOf(keyword)) { + return false; + } + } + return true; + } + }; + + return Index; + +}).call(this); + +Polyfill = (function() { + var Polyfill; + + Polyfill = { + init: function() { + return this.toBlob(); + }, + toBlob: function() { + if (HTMLCanvasElement.prototype.toBlob) { + return; + } + HTMLCanvasElement.prototype.toBlob = function(cb, type, encoderOptions) { + var data, i, j, l, ref, ui8a, url; + if (type == null) { + type = 'image/png'; + } + url = this.toDataURL(type, encoderOptions); + data = atob(url.slice(url.indexOf(',') + 1)); + l = data.length; + ui8a = new Uint8Array(l); + for (i = j = 0, ref = l; j < ref; i = j += 1) { + ui8a[i] = data.charCodeAt(i); + } + return cb(new Blob([ui8a], { + type: type + })); + }; + return $.globalEval("HTMLCanvasElement.prototype.toBlob = (" + HTMLCanvasElement.prototype.toBlob + ");"); + } + }; + + return Polyfill; + +}).call(this); + +Settings = (function() { + var Settings, + 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; }; + + 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']) { + if ($.hasStorage) { + settings = JSON.parse(localStorage.getItem('4chan-settings')) || {}; + if (settings.disableAll) { + return; + } + settings.disableAll = true; + return localStorage.setItem('4chan-settings', JSON.stringify(settings)); + } else { + return $.onExists(doc, 'body', function() { + return $.global(function() { + return window.Config.disableAll = true; + }); + }); + } + } + }, + open: function(openSection) { + var dialog, j, len, link, links, overlay, ref, section, sectionToOpen; + if (Settings.overlay) { + return; + } + $.event('CloseMenu'); + Settings.dialog = dialog = $.el('div', { + id: 'fourchanx-settings', + className: 'dialog' + }); + $.extend(dialog, { + innerHTML: "
            " + }); + 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 (j = 0, len = ref.length; j < len; j++) { + section = ref[j]; + 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); + }, + warnings: { + localStorage: function(cb) { + var why; + if ($.cantSync) { + why = $.cantSet ? 'save your settings' : 'synchronize settings between tabs'; + return cb($.el('li', { + textContent: "4chan X needs local storage to " + why + ".\nEnable it on boards.4chan.org in your browser's privacy settings (may be listed as part of \"local data\" or \"cookies\")." + })); + } + }, + ads: function(cb) { + return $.onExists(doc, '.ad-cnt', function(ad) { + return $.onExists(ad, 'img', function() { + return cb($.el('li', { + innerHTML: "To protect yourself from malicious ads, you should block ads on 4chan." + })); + }); + }); + } + }, + main: function(section) { + var addWarning, arr, button, container, containers, description, div, fs, input, inputs, items, key, level, obj, ref, ref1, warning, warnings; + warnings = $.el('fieldset', { + hidden: true + }, { + innerHTML: "Warnings
              " + }); + addWarning = function(item) { + $.add($('ul', warnings), item); + return warnings.hidden = false; + }; + ref = Settings.warnings; + for (key in ref) { + warning = ref[key]; + warning(addWarning); + } + $.add(section, warnings); + items = {}; + inputs = {}; + ref1 = Config.main; + for (key in ref1) { + obj = ref1[key]; + fs = $.el('fieldset', { + innerHTML: "" + E(key) + "" + }); + containers = [fs]; + for (key in obj) { + arr = obj[key]; + description = arr[1]; + div = $.el('div', { + innerHTML: ": " + E(description) + "" + }); + if ($.engine !== 'gecko' && key === 'Remember QR Size') { + div.hidden = true; + } + 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: ": 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, ref2, ref3, thread; + hiddenThreads = arg.hiddenThreads, hiddenPosts = arg.hiddenPosts; + hiddenNum = 0; + ref2 = hiddenThreads.boards; + for (ID in ref2) { + board = ref2[ID]; + hiddenNum += Object.keys(board).length; + } + ref3 = hiddenPosts.boards; + for (ID in ref3) { + board = ref3[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; + if ($.hasStorage) { + 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) { + 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; + } + this.value = null; + 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 { + return Settings.loadSettings(JSON.parse(e.target.result), function(err) { + if (err) { + return output.textContent = 'Import failed due to an error.'; + } else 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); + }, + convertFrom: { + loadletter: function(data) { + var base, boardID, convertSettings, key, ref, ref1, threadData, threadID, threads, val; + 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': 'Disable Native Extension', + 'Comment Auto-Expansion': '', + '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', + 'Current Page': 'Page Count in Stats', + 'Current Page Position': '', + 'Alternative captcha': 'Use Recaptcha v1', + 'Auto Submit': 'Post on Captcha Completion', + '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()); + }); + } + } + if (data.WatchedThreads) { + data.Conf['watchedThreads'] = { + boards: {} + }; + ref1 = data.WatchedThreads; + for (boardID in ref1) { + threads = ref1[boardID]; + for (threadID in threads) { + threadData = threads[threadID]; + ((base = data.Conf['watchedThreads'].boards)[boardID] || (base[boardID] = {}))[threadID] = { + excerpt: threadData.textContent + }; + } + } + } + return data; + } + }, + upgrade: function(data, version) { + var boardID, changes, compareString, j, key, len, name, record, ref, ref1, ref2, ref3, ref4, ref5, rice, set, type, uids, value; + changes = {}; + set = function(key, value) { + return data[key] = changes[key] = value; + }; + compareString = version.replace(/\d+/g, function(x) { + return ('0000' + x).slice(-5); + }); + if (compareString < '00001.00011.00008.00000') { + if (data['Fixed Thread Watcher'] == null) { + set('Fixed Thread Watcher', (ref = data['Toggleable Thread Watcher']) != null ? ref : true); + } + if (data['Exempt Archives from Encryption'] == null) { + set('Exempt Archives from Encryption', (ref1 = data['Except Archives from Encryption']) != null ? ref1 : false); + } + } + if (compareString < '00001.00011.00010.00001') { + if (data['selectedArchives'] != null) { + uids = { + "Moe": 0, + "4plebs Archive": 3, + "Nyafuu Archive": 4, + "Love is Over": 5, + "Rebecca Black Tech": 8, + "warosu": 10, + "fgts": 15, + "not4plebs": 22, + "DesuStorage": 23, + "fireden.net": 24, + "disabled": null + }; + ref2 = data['selectedArchives']; + for (boardID in ref2) { + record = ref2[boardID]; + for (type in record) { + name = record[type]; + if (name in uids) { + record[type] = uids[name]; + } + } + } + set('selectedArchives', data['selectedArchives']); + } + } + if (compareString < '00001.00011.00016.00000') { + if ((rice = Config['usercss'].match(/\/\* Board title rice \*\/(?:\n.+)*/)[0])) { + if ((data['usercss'] != null) && data['usercss'].indexOf(rice) < 0) { + set('usercss', rice + '\n\n' + data['usercss']); + } + } + } + if (compareString < '00001.00011.00017.00000') { + ref3 = ['Persistent QR', 'Color User IDs', 'Fappe Tyme', 'Werk Tyme', 'Highlight Posts Quoting You', 'Highlight Own Posts']; + for (j = 0, len = ref3.length; j < len; j++) { + key = ref3[j]; + if (data[key] == null) { + set(key, key === 'Persistent QR'); + } + } + } + if (compareString < '00001.00011.00017.00006') { + if (data['sauces'] != null) { + set('sauces', data['sauces'].replace(/^(#?\s*)http:\/\/iqdb\.org\//mg, '$1//iqdb.org/')); + } + } + if (compareString < '00001.00011.00019.00003' && !Settings.overlay) { + $.queueTask(function() { + return Settings.warnings.ads(function(item) { + return new Notice('warning', slice.call(item.childNodes)); + }); + }); + } + if (compareString < '00001.00011.00020.00003') { + ref4 = { + 'Inline Cross-thread Quotes Only': false, + 'Pass Link': true + }; + for (key in ref4) { + value = ref4[key]; + if (data[key] == null) { + set(key, value); + } + } + } + if (compareString < '00001.00011.00021.00003') { + if (data['Remember Your Posts'] == null) { + set('Remember Your Posts', (ref5 = data['Mark Quotes of You']) != null ? ref5 : true); + } + } + if (compareString < '00001.00011.00022.00000') { + if (data['sauces'] != null) { + set('sauces', data['sauces'].replace(/^(#?\s*https:\/\/www\.google\.com\/searchbyimage\?image_url=%(?:IMG|URL))%3Fs\.jpg/mg, '$1')); + set('sauces', data['sauces'].replace(/^#?\s*https:\/\/www\.google\.com\/searchbyimage\?image_url=%(?:IMG|T?URL)(?=$|;)/mg, '$&&safe=off')); + } + } + if (compareString < '00001.00011.00022.00002') { + if ((data['Use Recaptcha v1 in Reports'] == null) && data['Use Recaptcha v1'] && !data['Use Recaptcha v2 in Reports']) { + set('Use Recaptcha v1 in Reports', true); + } + } + if (compareString < '00001.00011.00024.00000') { + if ((data['JSON Navigation'] != null) && (data['JSON Index'] == null)) { + set('JSON Index', data['JSON Navigation']); + } + } + if (compareString < '00001.00011.00026.00000') { + if ((data['Oekaki Links'] != null) && (data['Edit Link'] == null)) { + set('Edit Link', data['Oekaki Links']); + } + if (data['Inline Cross-thread Quotes Only'] == null) { + set('Inline Cross-thread Quotes Only', true); + } + } + if (compareString < '00001.00011.00030.00000') { + if (data['Quote Threading'] && (data['Thread Quotes'] == null)) { + set('Thread Quotes', true); + } + } + return changes; + }, + loadSettings: function(data, cb) { + if (data.version.split('.')[0] === '2') { + data = Settings.convertFrom.loadletter(data); + } else if (data.version !== g.VERSION) { + Settings.upgrade(data.Conf, data.version); + } + return $.clear(function(err) { + if (err) { + return cb(err); + } + return $.set(data.Conf, cb); + }); + }, + reset: function() { + if (confirm('Your current settings will be entirely wiped, are you sure?')) { + return $.clear(function(err) { + if (err) { + return $('.imp-exp-result').textContent = 'Import failed due to an error.'; + } else if (confirm('Reset successful. Reload now?')) { + return window.location.reload(); + } + }); + } + }, + filter: function(section) { + var select; + $.extend(section, { + innerHTML: "
              " + }); + select = $('select', section); + $.on(select, 'change', Settings.selectFilter); + return Settings.selectFilter.call(select); + }, + selectFilter: function() { + var div, name, ta; + div = this.nextElementSibling; + if ((name = this.value) !== 'guide') { + $.rmAll(div); + ta = $.el('textarea', { + name: name, + className: 'field', + spellcheck: false + }); + $.get(name, Conf[name], function(item) { + return ta.value = item[name]; + }); + $.on(ta, 'change', $.cb.value); + $.add(div, ta); + return; + } + $.extend(div, { + innerHTML: "
              Filter is disabled.

              Use regular expressions, one per line.
              Lines starting with a # will be ignored.
              For example, /weeaboo/i will filter posts containing the string \`weeaboo\`, case-insensitive.
              MD5 filtering uses exact string matching, not regular expressions.

                You can use these settings with each regular expression, separate them with semicolons:
              • Per boards, separate them with commas. It is global if not specified.
                For example: boards:a,jp;.
              • In case of a global rule, select boards to be excluded from the filter.
                For example: exclude:vg,v;.
              • Filter OPs only along with their threads (\`only\`), replies only (\`no\`), or both (\`yes\`, this is default).
                For example: op:only;, op:no; or op:yes;.
              • Overrule the \`Show Stubs\` setting if specified: create a stub (\`yes\`) or not (\`no\`).
                For example: stub:yes; or stub:no;.
              • Highlight instead of hiding. You can specify a class name to use with a userstyle.
                For example: highlight; or highlight:wallpaper;.
              • Highlighted OPs will have their threads put on top of the board index by default.
                For example: top:yes; or top:no;.

              Note: If you're using the native catalog rather than 4chan X's catalog, 4chan X's filters do not apply there.
              The native catalog has its own separate filter list.

              " + }); + return $('.warning', div).hidden = Conf['Filter']; + }, + sauce: function(section) { + var ta; + $.extend(section, { + innerHTML: "
              Sauce is disabled.
              Lines starting with a # will be ignored.
              You can specify a display text by appending ;text:[text] to the URL.
              You can specify the applicable boards by appending ;boards:[board1],[board2].
              You can specify the applicable file types by appending ;types:[extension1],[extension2].
              You can open links with scripts and popups disabled by appending ;sandbox.
                These parameters will be replaced by their corresponding values:
              • %TURL: Thumbnail URL.
              • %URL: Full image URL.
              • %IMG: Full image URL for GIF, JPG, and PNG; thumbnail URL for other types.
              • %MD5: MD5 hash in base64.
              • %sMD5: MD5 hash in base64 using - and _.
              • %hMD5: MD5 hash in hexadecimal.
              • %name: Original file name.
              • %board: Current board.
              • %%, %semi: Literal % and ;.
              " + }); + $('.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, archive, boardID, boardOptions, boardSelect, boards, customCSS, files, i, input, inputs, interval, item, items, j, k, l, len, len1, len2, len3, len4, len5, len6, m, n, name, o, q, r, ref, ref1, ref2, ref3, ref4, ref5, ref6, row, rows, software, ta, table, uid, warning, withCredentials; + $.extend(section, { + innerHTML: "
              Archiver
              404 Redirect is disabled.
              Thread redirectionPost fetchingFile redirection
              Captcha Language
              Choose from list of language codes. Leave blank to autoselect.
              Custom Board Navigation
              New lines will be converted into spaces.

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

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

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

                You can use these settings with each item, separate them with semicolons:
              • Possible items are: name, options (or equivalently email), subject and password.
              • Wrap values of items with quotes, like this: options:"sage".
              • Force values as defaults with the always keyword, for example: options:"sage";always.
              • Select specific boards for an item, separated with commas, for example: options:"sage";boards:jp;always.
              Unread Favicon is disabled.
              Thread Updater is disabled.
              Interval: seconds
              Custom Cooldown Time
              Seconds:
              " + }); + ref = $$('.warning', section); + for (j = 0, len = ref.length; j < len; j++) { + warning = ref[j]; + warning.hidden = Conf[warning.dataset.feature]; + } + items = {}; + inputs = {}; + ref1 = ['captchaLanguage', 'boardnav', 'time', 'backlink', 'fileInfo', 'favicon', 'usercss', 'customCooldown']; + for (k = 0, len1 = ref1.length; k < len1; k++) { + name = ref1[k]; + 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); + if (name in Settings) { + $.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 in Settings && key !== 'usercss') { + 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 (l = 0, len2 = ref2.length; l < len2; l++) { + ref3 = ref2[l], uid = ref3.uid, name = ref3.name, boards = ref3.boards, files = ref3.files, software = ref3.software, withCredentials = ref3.withCredentials; + for (m = 0, len3 = boards.length; m < len3; m++) { + boardID = boards[m]; + o = archBoards[boardID] || (archBoards[boardID] = { + thread: [[], []], + post: [[], []], + file: [[], []] + }); + i = +(!!withCredentials); + archive = [uid != null ? uid : name, name]; + o.thread[i].push(archive); + if (software === 'foolfuuka') { + o.post[i].push(archive); + } + if (indexOf.call(files, boardID) >= 0) { + o.file[i].push(archive); + } + } + } + for (boardID in archBoards) { + o = archBoards[boardID]; + ref4 = ['thread', 'post', 'file']; + for (n = 0, len4 = ref4.length; n < len4; n++) { + item = ref4[n]; + i = o[item][0].length ? 1 : 0; + o[item][i].push([null, 'disabled']); + o[item] = o[item][0].concat(o[item][1]); + } + } + rows = []; + boardOptions = []; + ref5 = Object.keys(archBoards).sort(); + for (q = 0, len5 = ref5.length; q < len5; q++) { + boardID = ref5[q]; + 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 (r = 0, len6 = ref6.length; r < len6; r++) { + item = ref6[r]; + $.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, id, select, selectedArchives, type; + selectedArchives = arg.selectedArchives; + for (boardID in selectedArchives) { + data = selectedArchives[boardID]; + for (type in data) { + id = data[type]; + if (select = $("select[data-boardid='" + boardID + "'][data-type='" + type + "']", section)) { + select.value = JSON.stringify(id); + } + } + } + }); + }, + 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', { + value: JSON.stringify(archive[0]), + textContent: archive[1] + })); + } + $.extend(td, { + innerHTML: "" + }); + select = td.firstElementChild; + if (!(select.disabled = length === 1)) { + select.setAttribute('data-boardid', boardID); + select.setAttribute('data-type', type); + $.on(select, 'change', Settings.saveSelectedArchive); + } + $.add(select, options); + return td; + }, + saveSelectedArchive: function() { + return $.get('selectedArchives', Conf['selectedArchives'], (function(_this) { + return function(arg) { + var name1, selectedArchives; + selectedArchives = arg.selectedArchives; + (selectedArchives[name1 = _this.dataset.boardid] || (selectedArchives[name1] = {}))[_this.dataset.type] = JSON.parse(_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, + isVideo: false, + isSpoiler: true, + tag: 'Loop' + } + }; + 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, ref, tbody, tr; + $.extend(section, { + innerHTML: "
              Keybinds are disabled.
              Allowed keys: a-z, 0-9, Ctrl, Shift, Alt, Meta, Enter, Esc, Up, Down, Right, Left.
              Press Backspace to disable a keybind.
              ActionsKeybinds
              " + }); + $('.warning', section).hidden = Conf['Keybinds']; + tbody = $('tbody', section); + items = {}; + inputs = {}; + ref = Config.hotkeys; + for (key in ref) { + arr = ref[key]; + tr = $.el('tr', { + innerHTML: "" + E(arr[1]) + "" + }); + input = $('input', tr); + input.name = key; + input.spellcheck = false; + items[key] = Conf[key]; + inputs[key] = input; + $.on(input, 'keydown', Settings.keybind); + $.add(tbody, tr); + } + return $.get(items, function(items) { + var val; + for (key in items) { + val = items[key]; + inputs[key].value = val; + } + }); + }, + keybind: function(e) { + var key; + if (e.keyCode === 9) { + return; + } + e.preventDefault(); + e.stopPropagation(); + if ((key = Keybinds.keyCode(e)) == null) { + return; + } + this.value = key; + return $.cb.value.call(this); + } + }; + + return Settings; + +}).call(this); + +UI = (function() { + var Menu, checkbox, dialog, drag, dragend, dragstart, hover, hoverend, hoverstart, touchend, touchmove, + bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, + slice = [].slice; + + dialog = function(id, position, properties) { + var child, el, i, len, move, 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); + this.setPosition = bind(this.setPosition, 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 entry, i, len, menu, ref; + 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 CloseMenu', this.close); + $.on(d, 'scroll', this.setPosition); + $.on(window, 'resize', this.setPosition); + $.add(button, menu); + this.setPosition(); + entry = $('.entry', menu); + this.focus(entry); + return menu.focus(); + }; + + Menu.prototype.setPosition = function() { + var bLeft, bRect, bTop, bottom, cHeight, cWidth, left, mRect, ref, ref1, right, top; + mRect = this.menu.getBoundingClientRect(); + bRect = lastToggledButton.getBoundingClientRect(); + bTop = window.scrollY + bRect.top; + bLeft = window.scrollX + bRect.left; + cHeight = doc.clientHeight; + cWidth = doc.clientWidth; + ref = bRect.top + bRect.height + mRect.height < cHeight ? [bRect.bottom + "px", ''] : ['', (cHeight - bRect.top) + "px"], top = ref[0], bottom = ref[1]; + ref1 = bRect.left + mRect.width < cWidth ? [bRect.left + "px", ''] : ['', (cWidth - bRect.right) + "px"], left = ref1[0], right = ref1[1]; + $.extend(this.menu.style, { + top: top, + right: right, + bottom: bottom, + left: left + }); + return this.menu.classList.toggle('left', right); + }; + + Menu.prototype.insertEntry = function(entry, parent, data) { + var err, i, len, ref, subEntry, submenu; + if (typeof entry.open === 'function') { + try { + if (!entry.open(data)) { + return; + } + } catch (_error) { + err = _error; + Main.handleErrors({ + message: "Error in building the " + this.type + " menu.", + error: err + }); + 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; + $.off(d, 'click scroll CloseMenu', this.close); + $.off(d, 'scroll', this.setPosition); + return $.off(window, 'resize', this.setPosition); + }; + + 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, i, left, len, ref, ref1, ref2, right, sRect, style, submenu, top; + 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, i, len, subEntries, subEntry; + 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, ref, screenHeight, screenWidth; + 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 i, len, ref, touch; + 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 i, len, ref, touch; + 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 cb, el, endEvents, height, latestEvent, noRemove, o, ref, root; + root = arg.root, el = arg.el, latestEvent = arg.latestEvent, endEvents = arg.endEvents, 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); + o.hover(o.latestEvent); + new MutationObserver(function() { + if (el.parentNode) { + return o.hover(o.latestEvent); + } + }).observe(el, { + childList: true + }); + $.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); + }; + + hoverstart.padding = 25; + + hover = function(e) { + var clientX, clientY, height, left, ref, right, style, threshold, top; + this.latestEvent = e; + height = (this.height || this.el.offsetHeight) + hoverstart.padding; + 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 + }; + +}).call(this); + +FappeTyme = (function() { + var FappeTyme; + + FappeTyme = { + init: function() { + var el, i, lc, len, ref, ref1, type; + if (!((Conf['Fappe Tyme'] || Conf['Werk Tyme']) && ((ref = g.VIEW) === 'index' || ref === 'thread'))) { + 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')); + } + Callbacks.Post.push({ + name: 'Fappe Tyme', + cb: this.node + }); + return Callbacks.CatalogThread.push({ + name: 'Werk Tyme', + cb: this.catalogNode + }); + }, + node: function() { + return this.nodes.root.classList.toggle('noFile', !this.file); + }, + 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]); + } + } + }; + + return FappeTyme; + +}).call(this); + +Gallery = (function() { + var Gallery; + + 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 Callbacks.Post.push({ + name: 'Gallery', + cb: this.node + }); + }, + node: function() { + var ref; + if (!((ref = this.file) != null ? ref.thumb : void 0)) { + 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, i, j, key, len, len1, menuButton, nodes, post, ref, ref1, ref2, ref3, thumb, value; + cb = Gallery.cb; + 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: "
              " + }); + 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'); + $.on(nodes.frame, 'click', cb.blank); + if (Conf['Mouse Wheel Volume']) { + $.on(nodes.frame, 'wheel', Volume.wheel); + } + $.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); + } + $.on(window, 'resize', Gallery.cb.setHeight); + ref2 = $$('.post .file'); + for (j = 0, len1 = ref2.length; j < len1; j++) { + file = ref2[j]; + post = Get.postFromNode(file); + if (!((ref3 = post.file) != null ? ref3.thumb : void 0)) { + 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.thumb && (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); + }, + load: function(thumb, errorCB) { + var elType, ext, file; + ext = thumb.href.match(/\w*$/); + elType = { + 'webm': 'video', + 'pdf': 'iframe' + }[ext] || 'img'; + file = $.el(elType, { + title: thumb.title + }); + $.extend(file.dataset, thumb.dataset); + $.on(file, 'error', errorCB); + file.src = thumb.href; + return file; + }, + open: function(thumb) { + var el, file, newID, nodes, oldID, post, ref; + nodes = Gallery.nodes; + oldID = +nodes.current.dataset.id; + newID = +thumb.dataset.id; + if (el = Gallery.images[oldID]) { + $.rmClass(el, 'gal-highlight'); + } + $.addClass(thumb, 'gal-highlight'); + nodes.thumbs.scrollTop = thumb.offsetTop + thumb.offsetHeight / 2 - nodes.thumbs.clientHeight / 2; + if (((ref = Gallery.cache) != null ? ref.dataset.id : void 0) === '' + newID) { + file = Gallery.cache; + $.off(file, 'error', Gallery.cacheError); + $.on(file, 'error', Gallery.error); + } else { + file = Gallery.load(thumb, Gallery.error); + } + $.off(nodes.current, 'error', Gallery.error); + ImageCommon.pause(nodes.current); + $.replace(nodes.current, file); + nodes.current = file; + if (file.nodeName === 'VIDEO') { + file.loop = true; + Volume.setup(file); + if (Conf['Autoplay']) { + file.play(); + } + if (Conf['Show Controls']) { + ImageCommon.addControls(file); + } + } + doc.classList.toggle('gal-pdf', file.nodeName === 'IFRAME'); + Gallery.cb.setHeight(); + nodes.count.textContent = +thumb.dataset.id + 1; + nodes.name.download = nodes.name.textContent = thumb.title; + nodes.name.href = thumb.href; + nodes.frame.scrollTop = 0; + nodes.next.focus(); + if (Gallery.slideshow && (newID > oldID || (oldID === Gallery.images.length - 1 && newID === 0))) { + Gallery.setupTimer(); + } else { + Gallery.cb.stop(); + } + if (Conf['Scroll to Post'] && (post = g.posts[file.dataset.post])) { + Header.scrollTo(post.nodes.root); + } + if (isNaN(oldID) || newID === (oldID + 1) % Gallery.images.length) { + return Gallery.cache = Gallery.load(Gallery.images[(newID + 1) % Gallery.images.length], Gallery.cacheError); + } + }, + 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)); + }, + cacheError: function() { + return delete Gallery.cache; + }, + 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 (!Conf['Autoplay'] && 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); + } + $.off(window, 'resize', Gallery.cb.setHeight); + return clearTimeout(Gallery.timeoutID); + }, + setFitness: function() { + return (this.checked ? $.addClass : $.rmClass)(doc, "gal-" + (this.name.toLowerCase().replace(/\s+/g, '-'))); + }, + setHeight: $.debounce(100, function() { + var current, dim, frame, height, minHeight, ref, ref1, ref2, style, width; + ref = Gallery.nodes, current = ref.current, frame = ref.frame; + style = current.style; + if (Conf['Stretch to Fit'] && (dim = (ref1 = g.posts[current.dataset.post]) != null ? ref1.file.dimensions : void 0)) { + ref2 = dim.split('x'), width = ref2[0], height = ref2[1]; + minHeight = Math.min(doc.clientHeight - 25, height / width * frame.clientWidth); + style.minHeight = minHeight + 'px'; + return style.minWidth = (width / height * minHeight) + 'px'; + } else { + return style.minHeight = style.minWidth = null; + } + }), + 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 === 'Hide Thumbnails' || name === 'Fit Width' || name === 'Fit Height') { + $.on(input, 'change', Gallery.cb.setFitness); + } + $.event('change', null, input); + $.on(input, 'change', $.cb.checked); + if (name === 'Hide Thumbnails' || name === 'Fit Width' || name === 'Fit Height' || name === 'Stretch to Fit') { + $.on(input, 'change', Gallery.cb.setHeight); + } + return { + el: label + }; + }, + createSubEntries: function() { + var delayInput, delayLabel, item, subEntries; + subEntries = (function() { + var i, len, ref, results; + ref = ['Hide Thumbnails', 'Fit Width', 'Fit Height', 'Stretch to Fit', '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: " + }); + delayInput = delayLabel.firstElementChild; + delayInput.value = Gallery.delay; + $.on(delayInput, 'change', Gallery.cb.setDelay); + $.on(delayInput, 'change', $.cb.value); + subEntries.push({ + el: delayLabel + }); + return subEntries; + } + } + }; + + return Gallery; + +}).call(this); + +ImageCommon = (function() { + var ImageCommon; + + 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 i, len, postObj, ref; + if (this.status === 404) { + post.kill(!post.isClone); + } + 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 $.engine !== 'gecko' || (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)); + } + }; + + return ImageCommon; + +}).call(this); + +ImageExpand = (function() { + var ImageExpand, + slice = [].slice; + + 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: " contract" + }); + return Callbacks.Post.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 (!Conf['Autoplay'] && ((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() { + return g.posts.forEach(function(post) { + var file, i, len, ref, video, visible; + 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, i, len, oldHeight, ref, ref1, scrollY, top, x; + 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'); + $.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, ref, thumb; + 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 = Math.min(doc.clientHeight - file.fullImage.getBoundingClientRect().bottom - 25, Header.getBottomOf(file.fullImage)); + 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, ref, subEntries; + 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 + }; + } + } + }; + + return ImageExpand; + +}).call(this); + +ImageHover = (function() { + var ImageHover; + + ImageHover = { + init: function() { + var ref; + if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { + return; + } + if (Conf['Image Hover']) { + Callbacks.Post.push({ + name: 'Image Hover', + cb: this.node + }); + } + if (Conf['Image Hover in Catalog']) { + return Callbacks.CatalogThread.push({ + name: 'Image Hover', + cb: this.catalogNode + }); + } + }, + node: function() { + if (!(this.file && (this.file.isImage || this.file.isVideo))) { + return; + } + return $.on(this.file.thumb, 'mouseover', ImageHover.mouseover(this)); + }, + catalogNode: function() { + var file; + file = this.thread.OP.file; + if (!(file && (file.isImage || file.isVideo))) { + return; + } + return $.on(this.nodes.thumb, 'mouseover', ImageHover.mouseover(this.thread.OP)); + }, + mouseover: function(post) { + return function(e) { + var el, error, file, height, isVideo, left, maxHeight, maxWidth, ref, ref1, ref2, right, scale, width, x; + 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; + maxWidth = Math.max(left, doc.clientWidth - right); + maxHeight = doc.clientHeight - UI.hover.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', + height: scale * height, + 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)); + }; + } + }; + + return ImageHover; + +}).call(this); + +ImageLoader = (function() { + var ImageLoader, + slice = [].slice; + + 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; + } + Callbacks.Post.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: " Prefetch Images" + }); + this.el = prefetch.firstElementChild; + $.on(this.el, 'change', this.toggle); + return Header.menu.addEntry({ + el: prefetch, + order: 98 + }); + }, + 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, i, len, ref, thumb, video; + file = post.file; + thumb = file.thumb; + video = $.el('video', { + preload: 'none', + loop: true, + muted: true, + poster: thumb.src || thumb.dataset.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 clone, el, file, i, isImage, isVideo, len, match, ref, replace, thumb, type, url; + 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 || thumb.dataset.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 ($.engine === 'gecko') { + $.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; + } + thumb.src = url; + return thumb.removeAttribute('data-src'); + }); + } + 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 i, len, ref1, ref2, thumb; + 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(); + } + } + }); + } + }; + + return ImageLoader; + +}).call(this); + +Metadata = (function() { + var Metadata; + + Metadata = { + init: function() { + var ref; + if (!(Conf['WEBM Metadata'] && ((ref = g.VIEW) === 'index' || ref === 'thread') && g.BOARD.ID !== 'f')) { + return; + } + return Callbacks.Post.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: "" + }); + $.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; + } + }; + + return Metadata; + +}).call(this); + +RevealSpoilers = (function() { + var RevealSpoilers; + + RevealSpoilers = { + init: function() { + var ref; + if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Reveal Spoiler Thumbnails'])) { + return; + } + return Callbacks.Post.push({ + name: 'Reveal Spoiler Thumbnails', + cb: this.node + }); + }, + node: function() { + var thumb; + if (!(!this.isClone && this.file && this.file.thumb && this.file.isSpoiler)) { + return; + } + thumb = this.file.thumb; + thumb.removeAttribute('style'); + thumb.style.maxHeight = thumb.style.maxWidth = this.isReply ? '125px' : '250px'; + if (thumb.src) { + return thumb.src = this.file.thumbURL; + } else { + return thumb.dataset.src = this.file.thumbURL; + } + } + }; + + return RevealSpoilers; + +}).call(this); + +Sauce = (function() { + var Sauce, + 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; }; + + Sauce = { + init: function() { + var err, j, len, link, links, ref, ref1; + if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Sauce'])) { + return; + } + links = []; + ref1 = Conf['sauces'].split('\n'); + for (j = 0, len = ref1.length; j < len; j++) { + link = ref1[j]; + 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', + className: 'sauce' + }); + return Callbacks.Post.push({ + name: 'Sauce', + cb: this.node + }); + }, + sandbox: function(url) { + return E.url({ + innerHTML: "[sb] " + E(url) + "" + }); + }, + rmOrigin: function(e) { + if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) { + return; + } + $.open(this.href); + return e.preventDefault(); + }, + createSauceLink: function(link, post) { + var a, ext, i, j, key, len, m, part, parts, ref, ref1, ref2, skip, url; + if (!(link = link.trim())) { + return null; + } + parts = {}; + ref = link.split(/;(?=(?:text|boards|types|sandbox):?)/); + for (i = j = 0, len = ref.length; j < len; i = ++j) { + 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) || '?'); + ext = post.file.url.match(/[^.]*$/)[0]; + skip = false; + for (key in parts) { + parts[key] = parts[key].replace(/%(T?URL|IMG|[sh]?MD5|board|name|%|semi)/g, function(_, parameter) { + var type; + type = Sauce.formatters[parameter](post, ext); + if (type == null) { + skip = true; + return ''; + } + if (key === 'url' && (parameter !== '%' && parameter !== 'semi')) { + if (/^javascript:/i.test(parts['url'])) { + type = JSON.stringify(type); + } + type = encodeURIComponent(type); + } + return type; + }); + } + if (skip) { + return null; + } + if (!(!parts['boards'] || (ref2 = post.board.ID, indexOf.call(parts['boards'].split(','), ref2) >= 0))) { + return null; + } + if (!(!parts['types'] || indexOf.call(parts['types'].split(','), ext) >= 0)) { + return null; + } + url = parts['url']; + if (parts['sandbox'] != null) { + url = Sauce.sandbox(url); + } + a = Sauce.link.cloneNode(true); + a.href = url; + a.textContent = parts['text']; + if (/^javascript:/i.test(parts['url'])) { + a.removeAttribute('target'); + } + if (parts['sandbox'] != null) { + $.on(a, 'click', Sauce.rmOrigin); + } + return a; + }, + node: function() { + var j, len, link, node, nodes, ref; + if (this.isClone || !this.file) { + return; + } + nodes = []; + ref = Sauce.links; + for (j = 0, len = ref.length; j < len; j++) { + link = ref[j]; + if (node = Sauce.createSauceLink(link, this)) { + nodes.push($.tn('\u00A0'), node); + } + } + return $.add(this.file.text, nodes); + }, + formatters: { + TURL: function(post) { + return post.file.thumbURL; + }, + URL: function(post) { + return post.file.url; + }, + IMG: function(post, ext) { + if (ext === 'gif' || ext === 'jpg' || ext === 'png') { + return post.file.url; + } else { + return post.file.thumbURL; + } + }, + MD5: function(post) { + return post.file.MD5; + }, + sMD5: function(post) { + var ref; + return (ref = post.file.MD5) != null ? ref.replace(/[+\/=]/g, function(c) { + return { + '+': '-', + '/': '_', + '=': '' + }[c]; + }) : void 0; + }, + hMD5: function(post) { + var c; + if (post.file.MD5) { + return ((function() { + var j, len, ref, results; + ref = atob(post.file.MD5); + results = []; + for (j = 0, len = ref.length; j < len; j++) { + c = ref[j]; + results.push(("0" + (c.charCodeAt(0).toString(16))).slice(-2)); + } + return results; + })()).join(''); + } + }, + board: function(post) { + return post.board.ID; + }, + name: function(post) { + return post.file.name; + }, + '%': function() { + return '%'; + }, + semi: function() { + return ';'; + } + } + }; + + return Sauce; + +}).call(this); + +Volume = (function() { + var Volume; + + Volume = { + init: function() { + var ref, ref1, unmuteEntry, volumeEntry; + 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 (Conf['Mouse Wheel Volume']) { + Callbacks.Post.push({ + name: 'Mouse Wheel Volume', + cb: this.node + }); + } + if ((ref1 = g.BOARD.ID) !== 'gif' && ref1 !== 'wsg') { + return; + } + if (Conf['Mouse Wheel Volume']) { + Callbacks.CatalogThread.push({ + name: 'Mouse Wheel Volume', + cb: this.catalogNode + }); + } + 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: " 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, key, muted, val, volume; + muted = this.muted, volume = this.volume; + items = { + 'Allow Sound': !muted, + 'Default Volume': volume + }; + for (key in items) { + val = items[key]; + if (Conf[key] === val) { + delete items[key]; + } + } + $.set(items); + $.extend(Conf, items); + if (Volume.inputs) { + Volume.inputs.unmute.checked = !muted; + return Volume.inputs.volume.value = volume; + } + }, + node: function() { + var ref, ref1; + if (!(((ref = this.board.ID) === 'gif' || ref === 'wsg') && ((ref1 = this.file) != null ? ref1.isVideo : void 0))) { + return; + } + $.on(this.file.thumb, 'wheel', Volume.wheel.bind(Header.hover)); + return $.on($('a', this.file.text), 'wheel', Volume.wheel.bind(this.file.thumb.parentNode)); + }, + catalogNode: function() { + var file; + file = this.thread.OP.file; + if (!(file != null ? file.isVideo : void 0)) { + return; + } + return $.on(this.nodes.thumb, 'wheel', Volume.wheel.bind(Header.hover)); + }, + wheel: function(e) { + var el, volume; + if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) { + return; + } + if (!(el = $('video:not([data-md5])', this))) { + 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(); + } + }; + + return Volume; + +}).call(this); + +Embedding = (function() { + var Embedding; + + Embedding = { + init: function() { + var j, len, ref, type; + if (!(Conf['Embedding'] || Conf['Link Title'])) { + return; + } + this.types = {}; + ref = this.ordered_types; + for (j = 0, len = ref.length; j < len; j++) { + type = ref[j]; + this.types[type.key] = type; + } + if (Conf['Floating Embeds']) { + this.dialog = UI.dialog('embedding', 'top: 50px; right: 0px;', { + innerHTML: "
              " + }); + this.media = $('#media-embed', this.dialog); + $.one(d, '4chanXInitFinished', this.ready); + } + if (Conf['Link Title']) { + return $.on(d, '4chanXInitFinished PostsInserted', function() { + var key, ref1, ref2, service; + 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, j, len, match, ref, type; + href = link.href; + ref = Embedding.ordered_types; + for (j = 0, len = ref.length; j < len; j++) { + type = ref[j]; + if (!(match = type.regExp.exec(href))) { + continue; + } + if (type.dummy) { + return; + } + return { + key: type.key, + uid: match[1], + options: match[2], + link: link + }; + } + }, + embed: function(data) { + var embed, href, key, link, name, options, post, ref, uid, value; + key = data.key, uid = data.uid, options = data.options, link = data.link, post = data.post; + href = link.href; + if (Embedding.types[key].httpOnly && location.protocol !== 'http:') { + return; + } + $.addClass(link, key.toLowerCase()); + embed = $.el('a', { + className: 'embedder', + href: 'javascript:;', + textContent: '(embed)' + }); + ref = { + key: key, + uid: uid, + options: options, + href: href + }; + for (name in ref) { + value = ref[name]; + embed.dataset[name] = value; + } + $.on(embed, 'click', Embedding.cb.toggle); + $.after(link, [$.tn(' '), embed]); + if (Conf['Auto-embed'] && !Conf['Floating Embeds'] && !post.isFetchedQuote && key !== 'TwitchTV') { + 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; + } + $.addClass(link, key.toLowerCase()); + 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) + "] Title Link Blocked (are you using NoScript?)" + }); + } + } + }, + flushTitles: function(service) { + var cb, data, j, len, queue; + queue = service.queue; + if (!(queue != null ? queue.length : void 0)) { + return; + } + service.queue = []; + cb = function() { + var data, j, len; + for (j = 0, len = queue.length; j < len; j++) { + data = queue[j]; + Embedding.cb.title(this, data); + } + }; + if (!$.cache(service.api((function() { + var j, len, results; + results = []; + for (j = 0, len = queue.length; j < len; j++) { + data = queue[j]; + results.push(data.uid); + } + return results; + })()), cb, { + responseType: 'json' + })) { + for (j = 0, len = queue.length; j < len; j++) { + data = queue[j]; + $.extend(data.link, { + innerHTML: "[" + E(data.key) + "] Title Link Blocked (are you using NoScript?)" + }); + } + } + }, + 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: none; width: 640px; height: 360px;'; + return container; + }, + title: function(req, data) { + var base1, j, k, key, len, len1, link, link2, options, post, post2, ref, ref1, service, status, text, uid; + 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 (j = 0, len = ref.length; j < len; j++) { + post2 = ref[j]; + ref1 = $$('a.linkify', post2.nodes.comment); + for (k = 0, len1 = ref1.length; k < len1; k++) { + link2 = ref1[k]; + if (!(link2.href === link.href)) { + continue; + } + if ((base1 = link2.dataset).original == null) { + base1.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.dataset.href + }); + } + }, { + key: 'Dailymotion', + regExp: /^\w+:\/\/(?:(?:www\.)?dailymotion\.com\/(?:embed\/)?video|dai\.ly)\/([A-Za-z0-9]+)[^?]*(.*)/, + el: function(a) { + var el, options, start; + options = (start = a.dataset.options.match(/[?&](start=\d+)/)) ? "?" + start[1] : ''; + el = $.el('iframe', { + src: "//www.dailymotion.com/embed/video/" + a.dataset.uid + options + }); + el.setAttribute("allowfullscreen", "true"); + return el; + }, + title: { + api: function(uid) { + return "https://api.dailymotion.com/video/" + uid; + }, + text: function(_) { + return _.title; + } + } + }, { + 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: "" + E(a.dataset.uid) + "" + }; + el.src = E.url(content); + 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: "" + }); + } + }, { + 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', { + src: "http://www.liveleak.com/ll_embed?i=" + a.dataset.uid + }); + el.setAttribute("allowfullscreen", "true"); + 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)?)/, + style: 'border: 0; width: 600px; height: 406px;', + el: function(a) { + return $.el('iframe', { + src: "//strawpoll.me/embed_1/" + a.dataset.uid + }); + } + }, { + key: 'TwitchTV', + regExp: /^\w+:\/\/(?:www\.)?twitch\.tv\/(\w[^#\&\?]*)/, + style: "border: none; width: 620px; height: 378px;", + el: function(a) { + var _, channel, flashvars, id, idprefix, j, len, obj, part, ref, result, seconds, start, type; + if (result = /(\w+)\/([bcv])\/(\d+)/i.exec(a.dataset.uid)) { + _ = result[0], channel = result[1], type = result[2], id = result[3]; + idprefix = type === 'b' ? 'a' : type; + flashvars = "channel=" + channel + "&start_volume=25&auto_play=false&videoId=" + idprefix + id; + if (start = a.dataset.href.match(/\bt=(\w+)/)) { + seconds = 0; + ref = start[1].match(/\d+[hms]/g); + for (j = 0, len = ref.length; j < len; j++) { + part = ref[j]; + seconds += +part.slice(0, -1) * { + 'h': 3600, + 'm': 60, + 's': 1 + }[part.slice(-1)]; + } + flashvars += "&initial_time=" + seconds; + } + } else { + channel = (/(\w+)/.exec(a.dataset.uid))[0]; + flashvars = "channel=" + channel + "&start_volume=25&auto_play=false"; + } + obj = $.el('object', { + data: '//www-cdn.jtvnw.net/swflibs/TwitchPlayer.swf' + }); + $.extend(obj, { + innerHTML: "" + }); + obj.children[1].value = flashvars; + return obj; + } + }, { + key: 'Vocaroo', + regExp: /^\w+:\/\/(?:www\.)?vocaroo\.com\/i\/(\w+)/, + style: '', + el: function(a) { + var el, type; + el = $.el('audio', { + controls: true, + preload: 'auto' + }); + type = el.canPlayType('audio/webm') ? 'webm' : 'mp3'; + el.src = "http://vocaroo.com/media_command.php?media=" + a.dataset.uid + "&command=download_" + type; + return el; + } + }, { + 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=https://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=|\bembed\/|\bv\/))([\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, j, len, ref; + ref = data.items; + for (j = 0, len = ref.length; j < len; j++) { + item = ref[j]; + if (item.id === uid) { + return item.snippet.title; + } + } + return 'Not Found'; + } + } + }, { + key: 'Loopvid', + regExp: /^\w+:\/\/(?:www\.)?loopvid.appspot.com\/#?((?:pf|kd|lv|gd|gh|db|dx|nn|cp|wu|ig|ky|mf|pc|gc)\/[\w\-\/]+(,[\w\-\/]+)*|fc\/\w+\/\d+)/, + style: 'max-width: 80vw; max-height: 80vh;', + el: function(a) { + var _, base, el, host, j, k, len, len1, name, names, ref, ref1, type, types, url; + el = $.el('video', { + controls: true, + preload: 'auto', + loop: true + }); + ref = a.dataset.uid.match(/(\w+)\/(.*)/), _ = ref[0], host = ref[1], names = ref[2]; + types = (function() { + switch (host) { + case 'gd': + case 'wu': + case 'fc': + return ['']; + case 'gc': + return ['giant', 'fat', 'zippy']; + default: + return ['.webm', '.mp4']; + } + })(); + ref1 = names.split(','); + for (j = 0, len = ref1.length; j < len; j++) { + name = ref1[j]; + for (k = 0, len1 = types.length; k < len1; k++) { + type = types[k]; + base = "" + name + type; + url = (function() { + switch (host) { + case 'pf': + return "https://web.archive.org/web/2/http://a.pomf.se/" + base; + case 'kd': + return "http://kastden.org/loopvid/" + base; + case 'lv': + return "http://kastden.org/_loopvid_media/lv/" + 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://dl.dropboxusercontent.com/u/" + base; + case 'dx': + return "https://dl.dropboxusercontent.com/" + base; + case 'nn': + return "http://naenara.eu/loopvids/" + base; + case 'cp': + return "https://copy.com/" + base; + case 'wu': + return "http://webmup.com/" + base + "/vid.webm"; + case 'ig': + return "https://i.imgur.com/" + base; + case 'ky': + return "https://kiyo.me/" + base; + case 'mf': + return "https://d.maxfile.ro/" + base; + case 'pc': + return "http://a.pomf.cat/" + base; + case 'fc': + return "//i.4cdn.org/" + base + ".webm"; + case 'gc': + return "https://" + type + ".gfycat.com/" + name + ".webm"; + } + })(); + $.add(el, $.el('source', { + src: url + })); + } + } + return el; + } + }, { + key: 'Clyp', + regExp: /^\w+:\/\/(?:www\.)?clyp\.it\/(\w+)/, + style: '', + el: function(a) { + var el, type; + el = $.el('audio', { + controls: true, + preload: 'auto' + }); + type = el.canPlayType('audio/ogg') ? 'ogg' : 'mp3'; + el.src = "https://clyp.it/" + a.dataset.uid + "." + type; + return el; + } + }, { + 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.dataset.href, + loop: /^https?:\/\/i\.4cdn\.org\//.test(a.dataset.href) + }); + } + } + ] + }; + + return Embedding; + +}).call(this); + +Linkify = (function() { + var Linkify; + + Linkify = { + init: function() { + var ref; + if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Linkify']) { + return; + } + if (Conf['Comment Expansion']) { + ExpandComment.callbacks.push(this.node); + } + Callbacks.Post.push({ + name: 'Linkify', + cb: this.node + }); + Callbacks.CatalogThread.push({ + name: 'Linkify', + cb: this.catalogNode + }); + return Embedding.init(); + }, + node: function() { + var j, k, len, len1, link, links, ref; + if (this.isClone) { + return Embedding.events(this); + } + if (!Linkify.regString.test(this.info.comment)) { + return; + } + ref = $$('a[href^="http://i.4cdn.org/"], a[href^="https://i.4cdn.org/"]', this.nodes.comment); + for (j = 0, len = ref.length; j < len; j++) { + link = ref[j]; + $.addClass(link, 'linkify'); + Embedding.process(link, this); + } + links = Linkify.process(this.nodes.comment); + for (k = 0, len1 = links.length; k < len1; k++) { + link = links[k]; + 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, part1, part2, ref, ref1, 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') { + if ((part1 = word.match(/(https?:\/\/)?([a-z\d-]+\.)*[a-z\d-]+$/i)) && (part2 = (ref = snapshot.snapshotItem(i)) != null ? (ref1 = ref.data) != null ? ref1.match(/^(\.[a-z\d-]+)*\//i) : void 0 : void 0) && (part1[0] + part2[0]).search(Linkify.regString) === 0) { + continue; + } else { + 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|xyz|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, encodedDomain, 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; + } + if (encodedDomain = text.match(/^(https?:\/\/[^\/]*%[0-9a-f]{2})(.*)$/i)) { + text = encodedDomain[1].replace(/%([0-9a-f]{2})/ig, function(x, y) { + if (y === '25') { + return x; + } else { + return String.fromCharCode(parseInt(y, 16)); + } + }) + encodedDomain[2]; + } + a = $.el('a', { + className: 'linkify', + rel: 'nofollow noreferrer', + target: '_blank', + href: text + }); + $.add(a, range.extractContents()); + range.insertNode(a); + return a; + } + }; + + return Linkify; + +}).call(this); + +ArchiveLink = (function() { + var ArchiveLink; + + ArchiveLink = { + init: function() { + var div, entry, i, len, ref, ref1, type; + 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'], ['Capcode', 'capcode'], ['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 + }; + } + }; + + return ArchiveLink; + +}).call(this); + +DeleteLink = (function() { + var DeleteLink; + + DeleteLink = { + auto: [{}, {}], + 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:;' + }); + this.nodes = { + menu: div.firstChild, + links: [postEl, fileEl] + }; + postEntry = { + el: postEl, + open: function() { + postEl.textContent = DeleteLink.linkText(false); + $.on(postEl, 'click', DeleteLink.toggle); + return true; + } + }; + fileEntry = { + el: fileEl, + open: function(arg) { + var file; + file = arg.file; + if (!file || file.isDead) { + return false; + } + fileEl.textContent = DeleteLink.linkText(true); + $.on(fileEl, 'click', DeleteLink.toggle); + return true; + } + }; + return Menu.menu.addEntry({ + el: div, + order: 40, + open: function(post) { + if (post.isDead) { + return false; + } + DeleteLink.post = post; + DeleteLink.nodes.menu.textContent = DeleteLink.menuText(); + DeleteLink.cooldown.start(post); + return true; + }, + subEntries: [postEntry, fileEntry] + }); + }, + menuText: function() { + var seconds; + if (seconds = DeleteLink.cooldown.seconds[DeleteLink.post.fullID]) { + return "Delete (" + seconds + ")"; + } else { + return 'Delete'; + } + }, + linkText: function(fileOnly) { + var text; + text = fileOnly ? 'File' : 'Post'; + if (DeleteLink.auto[+fileOnly][DeleteLink.post.fullID]) { + text = "Deleting " + (text.toLowerCase()) + "..."; + } + return text; + }, + toggle: function() { + var auto, fileOnly, post; + post = DeleteLink.post; + fileOnly = $.hasClass(this, 'delete-file'); + auto = DeleteLink.auto[+fileOnly]; + if (auto[post.fullID]) { + delete auto[post.fullID]; + } else { + auto[post.fullID] = true; + } + this.textContent = DeleteLink.linkText(fileOnly); + if (!DeleteLink.cooldown.seconds[post.fullID]) { + return DeleteLink["delete"](post, fileOnly); + } + }, + "delete": function(post, fileOnly) { + var form, link; + link = DeleteLink.nodes.links[+fileOnly]; + delete DeleteLink.auto[+fileOnly][post.fullID]; + if (post.fullID === DeleteLink.post.fullID) { + $.off(link, 'click', DeleteLink.toggle); + } + form = { + mode: 'usrdel', + onlyimgdel: fileOnly, + pwd: QR.persona.getPassword() + }; + form[post.ID] = 'delete'; + 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, post); + } + }, { + form: $.formData(form) + }); + }, + load: function(link, post, fileOnly, resDoc) { + var el, msg; + link.textContent = DeleteLink.linkText(fileOnly); + if (resDoc.title === '4chan - Banned') { + el = $.el('span', { + innerHTML: "You can't delete posts because you are banned." + }); + return new Notice('warning', el, 20); + } else if (msg = resDoc.getElementById('errmsg')) { + new Notice('warning', msg.textContent, 20); + if (post.fullID === DeleteLink.post.fullID) { + $.on(link, 'click', DeleteLink.toggle); + } + if (QR.cooldown.data && Conf['Cooldown'] && /\bwait\b/i.test(msg.textContent)) { + DeleteLink.cooldown.start(post, 5); + DeleteLink.auto[+fileOnly][post.fullID] = true; + return DeleteLink.nodes.links[+fileOnly].textContent = DeleteLink.linkText(fileOnly); + } + } else { + if (!fileOnly) { + QR.cooldown["delete"](post); + } + if (resDoc.title === 'Updating index...') { + (post.origin || post).kill(fileOnly); + } + if (post.fullID === DeleteLink.post.fullID) { + return link.textContent = 'Deleted'; + } + } + }, + error: function(link, post) { + new Notice('warning', 'Connection error, please retry.', 20); + if (post.fullID === DeleteLink.post.fullID) { + return $.on(link, 'click', DeleteLink.toggle); + } + }, + cooldown: { + seconds: {}, + start: function(post, seconds) { + if (DeleteLink.cooldown.seconds[post.fullID] != null) { + return; + } + if (seconds == null) { + seconds = QR.cooldown.secondsDeletion(post); + } + if (seconds > 0) { + DeleteLink.cooldown.seconds[post.fullID] = seconds; + return DeleteLink.cooldown.count(post); + } + }, + count: function(post) { + var fileOnly, i, len, ref; + if (post.fullID === DeleteLink.post.fullID) { + DeleteLink.nodes.menu.textContent = DeleteLink.menuText(); + } + if (DeleteLink.cooldown.seconds[post.fullID] > 0 && Conf['Cooldown']) { + DeleteLink.cooldown.seconds[post.fullID]--; + setTimeout(DeleteLink.cooldown.count, 1000, post); + } else { + delete DeleteLink.cooldown.seconds[post.fullID]; + ref = [false, true]; + for (i = 0, len = ref.length; i < len; i++) { + fileOnly = ref[i]; + if (DeleteLink.auto[+fileOnly][post.fullID]) { + DeleteLink["delete"](post, fileOnly); + } + } + } + } + } + }; + + return DeleteLink; + +}).call(this); + +DownloadLink = (function() { + var DownloadLink; + + 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; + } + }); + } + }; + + return DownloadLink; + +}).call(this); + +Menu = (function() { + var Menu; + + 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: "" + }); + this.menu = new UI.Menu('post'); + Callbacks.Post.push({ + name: 'Menu', + cb: this.node + }); + return Callbacks.CatalogThread.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; + } + }; + + return Menu; + +}).call(this); + +ReportLink = (function() { + var ReportLink; + + 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:;' + }); + $.on(a, 'click', ReportLink.report); + return Menu.menu.addEntry({ + el: a, + order: 10, + open: function(post) { + if (!(post.isDead || (post.thread.isDead && !post.thread.isArchived))) { + a.textContent = 'Report'; + ReportLink.url = "//sys.4chan.org/" + post.board + "/imgboard.php?mode=report&no=" + post; + if ((Conf['Use Recaptcha v1 in Reports'] && Main.jsEnabled) || d.cookie.indexOf('pass_enabled=1') >= 0) { + ReportLink.url += '&altc=1'; + ReportLink.dims = 'width=350,height=275'; + } else { + ReportLink.dims = 'width=400,height=550'; + } + } else if (Conf['Archive Report']) { + a.textContent = 'Report to archive'; + ReportLink.url = Redirect.to('report', { + boardID: post.board.ID, + postID: post.ID + }); + ReportLink.dims = 'width=700,height=475'; + } else { + ReportLink.url = ''; + } + return !!ReportLink.url; + } + }); + }, + report: function() { + var dims, id, set, url; + url = ReportLink.url, dims = ReportLink.dims; + id = Date.now(); + set = "toolbar=0,scrollbars=1,location=0,status=1,menubar=0,resizable=1," + dims; + return window.open(url, id, set); + } + }; + + return ReportLink; + +}).call(this); + +AntiAutoplay = (function() { + var AntiAutoplay; + + 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); + Callbacks.Post.push({ + name: 'Disable Autoplaying Sounds', + cb: this.node + }); + Callbacks.CatalogThread.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 i, iframe, j, len, len1, object, 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', ''); + $.addClass(iframe, 'autoplay-removed'); + } + 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', ''); + $.addClass(object, 'autoplay-removed'); + } + } + }; + + return AntiAutoplay; + +}).call(this); + +Banner = (function() { + var Banner, + slice = [].slice; + + 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","79.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","256.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","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 base, br, j, 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 (j = 0, len = ref.length; j < len; j++) { + br = ref[j]; + $.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, j, len, ref; + ref = $$('br', this); + for (j = 0, len = ref.length; j < len; j++) { + br = ref[j]; + $.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, j, len, ref, string, string2; + className = child.className; + child.title = "Ctrl/\u2318+click to edit board " + (className.slice(5).toLowerCase()); + child.spellcheck = false; + ref = ['click', 'keydown', 'blur']; + for (j = 0, len = ref.length; j < len; j++) { + event = ref[j]; + $.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 + }); + } + } + } + }; + + return Banner; + +}).call(this); + +CatalogLinks = (function() { + var CatalogLinks; + + CatalogLinks = { + init: function() { + var el, input, selector; + if ((Conf['External Catalog'] || Conf['JSON Index']) && !(Conf['JSON Index'] && 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, i, len, link, ref; + ref = $$(selector); + for (i = 0, len = ref.length; i < len; i++) { + link = ref[i]; + switch (link.pathname.replace(/\/+/g, '/')) { + case "/" + g.BOARD + "/": + if (Conf['JSON Index']) { + link.textContent = 'Index'; + } + link.href = CatalogLinks.index(); + break; + case "/" + g.BOARD + "/catalog": + link.href = CatalogLinks.catalog(); + } + if (g.VIEW === 'catalog' && Conf['JSON Index'] && 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 Index'] && Conf['Use 4chan X Catalog']) { + Callbacks.Post.push({ + name: 'Catalog Link Rewrite', + cb: this.node + }); + Callbacks.CatalogThread.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, i, len, m, 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 (!CatalogLinks.el) { + 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') || !(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 + "/"; + if (a.dataset.indexOptions && a.hostname === 'boards.4chan.org' && a.pathname.split('/')[2] === '') { + a.href += (a.hash ? '/' : '#') + a.dataset.indexOptions; + } + } + 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 Index'] && 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 Index'] && board !== 'f') { + if (g.BOARD.ID === board && g.VIEW === 'index') { + return '#index'; + } else { + return "/" + board + "/#index"; + } + } else { + return "/" + board + "/"; + } + } + }; + + return CatalogLinks; + +}).call(this); + +CustomCSS = (function() { + var CustomCSS; + + CustomCSS = { + init: function() { + if (!Conf['Custom CSS']) { + return; + } + return this.addStyle(); + }, + addStyle: function() { + return this.style = $.addStyle(Conf['usercss'], 'custom-css', '#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']; + } + }; + + return CustomCSS; + +}).call(this); + +ExpandComment = (function() { + var ExpandComment; + + ExpandComment = { + init: function() { + if (g.VIEW !== 'index' || !Conf['Comment Expansion'] || Conf['JSON Index']) { + return; + } + if (g.BOARD.ID === 'g') { + this.callbacks.push(Fourchan.code); + } + if (g.BOARD.ID === 'sci') { + this.callbacks.push(Fourchan.math); + } + return Callbacks.Post.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, i, j, k, len, len1, len2, postObj, posts, quote, ref, ref1, spoilerRange, status; + 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); + } + } + }; + + return ExpandComment; + +}).call(this); + +ExpandThread = (function() { + var ExpandThread, + slice = [].slice; + + ExpandThread = { + statuses: {}, + init: function() { + if (g.VIEW === 'thread' || !Conf['Thread Expansion']) { + return; + } + if (Conf['JSON Index']) { + return $.on(d, 'IndexRefresh', this.onIndexRefresh); + } else { + return Callbacks.Thread.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 = Build.summaryText.apply(Build, ['+'].concat(slice.call(a.textContent.match(/\d+/g)))); + a.style.cursor = 'pointer'; + return $.on(a, 'click', ExpandThread.cbToggle); + }, + disconnect: function(refresh) { + var ref, ref1, status, threadID; + 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); + }); + }, + 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); + } + }, + expand: function(thread, a) { + var status; + ExpandThread.statuses[thread] = status = {}; + a.textContent = Build.summaryText.apply(Build, ['...'].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, i, inlined, len, num, postsCount, replies, reply, status; + status = ExpandThread.statuses[thread]; + delete ExpandThread.statuses[thread]; + if (status.req) { + status.req.abort(); + if (a) { + a.textContent = Build.summaryText.apply(Build, ['+'].concat(slice.call(a.textContent.match(/\d+/g)))); + } + return; + } + replies = $$('.thread > .replyContainer', threadRoot); + if (!Conf['JSON Index'] || 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 = Build.summaryText('+', postsCount, filesCount); + }, + parse: function(req, thread, a) { + var filesCount, i, len, post, postData, posts, postsCount, postsRoot, ref, ref1, root; + 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 = Build.summaryText('-', postsCount, filesCount); + } + }; + + return ExpandThread; + +}).call(this); + +FileInfo = (function() { + var FileInfo; + + FileInfo = { + init: function() { + var ref; + if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['File Info Formatting']) { + return; + } + return Callbacks.Post.push({ + name: 'File Info Formatting', + cb: this.node + }); + }, + node: function() { + var info, oldInfo; + if (!this.file || this.isClone) { + return; + } + oldInfo = $.el('span', { + className: 'fileText-original' + }); + $.prepend(this.file.link.parentNode, oldInfo); + $.add(oldInfo, [this.file.link.previousSibling, this.file.link, this.file.link.nextSibling]); + info = $.el('span', { + className: 'file-info' + }); + FileInfo.format(Conf['fileInfo'], this, info); + return $.prepend(this.file.text, info); + }, + 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: E.cat(output) + }); + }, + formatters: { + t: function() { + return { + innerHTML: E(this.file.url.match(/[^/]*$/)[0]) + }; + }, + T: function() { + return { + innerHTML: "" + (FileInfo.formatters.t.call(this)).innerHTML + "" + }; + }, + l: function() { + return { + innerHTML: "" + (FileInfo.formatters.n.call(this)).innerHTML + "" + }; + }, + L: function() { + return { + innerHTML: "" + (FileInfo.formatters.N.call(this)).innerHTML + "" + }; + }, + 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: "" + E(shortname) + "" + E(fullname) + "" + }; + } + }, + N: function() { + return { + innerHTML: E(this.file.name) + }; + }, + p: function() { + return { + innerHTML: ((this.file.isSpoiler) ? "Spoiler, " : "") + }; + }, + 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") + }; + }, + g: function() { + return { + innerHTML: ((this.file.tag) ? ", " + E(this.file.tag) : "") + }; + }, + '%': function() { + return { + innerHTML: "%" + }; + } + } + }; + + return FileInfo; + +}).call(this); + +Flash = (function() { + var Flash; + + Flash = { + init: function() { + if (g.BOARD.ID === 'f' && Conf['Enable Native Flash Embedding']) { + return $.ready(Flash.initReady); + } + }, + initReady: function() { + if ($.hasStorage) { + return $.global(function() { + if (JSON.parse(localStorage['4chan-settings'] || '{}').disableAll) { + return window.SWFEmbed.init(); + } + }); + } else { + if (g.VIEW === 'thread') { + $.global(function() { + return window.Main.tid = location.pathname.split(/\/+/)[3]; + }); + } + return $.global(function() { + return window.SWFEmbed.init(); + }); + } + } + }; + + return Flash; + +}).call(this); + +Fourchan = (function() { + var Fourchan; + + Fourchan = { + init: function() { + var ref; + if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { + return; + } + if (g.BOARD.ID === 'g') { + $.on(window, 'prettyprint:cb', function(e) { + var post, pre; + if (!(post = g.posts[e.detail.ID])) { + return; + } + if (!(pre = $$('.prettyprint', post.nodes.comment)[e.detail.i])) { + return; + } + if (!$.hasClass(pre, 'prettyprinted')) { + pre.innerHTML = e.detail.html; + return $.addClass(pre, 'prettyprinted'); + } + }); + $.globalEval('window.addEventListener(\'prettyprint\', function(e) {\n window.dispatchEvent(new CustomEvent(\'prettyprint:cb\', {\n detail: {\n ID: e.detail.ID,\n i: e.detail.i,\n html: prettyPrintOne(e.detail.html)\n }\n }));\n}, false);'); + Callbacks.Post.push({ + name: 'Parse /g/ code', + cb: this.code + }); + } + if (g.BOARD.ID === 'sci') { + $.global(function() { + return window.addEventListener('mathjax', function(e) { + if (window.MathJax) { + return window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub, e.target]); + } else { + if (!document.querySelector('script[src^="//cdn.mathjax.org/"]')) { + window.loadMathJax(); + window.loadMathJax = function() {}; + } + if (!e.target.classList.contains('postMessage')) { + return document.querySelector('script[src^="//cdn.mathjax.org/"]').addEventListener('load', function() { + return window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub, e.target]); + }, false); + } + } + }, false); + }); + Callbacks.Post.push({ + name: 'Parse /sci/ math', + cb: this.math + }); + Callbacks.CatalogThread.push({ + name: 'Parse /sci/ math', + cb: this.math + }); + } + return Main.ready(function() { + return $.global(function() { + var j, len, node, ref1; + window.clickable_ids = false; + ref1 = document.querySelectorAll('.posteruid, .capcode'); + for (j = 0, len = ref1.length; j < len; j++) { + node = ref1[j]; + node.removeEventListener('click', window.idClick, false); + } + }); + }); + }, + code: function() { + if (this.isClone) { + return; + } + return $.ready((function(_this) { + return function() { + var i, j, len, pre, ref; + ref = $$('.prettyprint', _this.nodes.comment); + for (i = j = 0, len = ref.length; j < len; i = ++j) { + pre = ref[i]; + if (!$.hasClass(pre, 'prettyprinted')) { + $.event('prettyprint', { + ID: _this.fullID, + i: i, + html: pre.innerHTML + }, window); + } + } + }; + })(this)); + }, + math: function() { + var cb, j, len, wbr, wbrs; + if (!/\[(math|eqn)\]/.test(this.nodes.comment.textContent)) { + return; + } + if ((wbrs = $$('wbr', this.nodes.comment)).length) { + for (j = 0, len = wbrs.length; j < len; j++) { + wbr = wbrs[j]; + $.rm(wbr); + } + this.nodes.comment.normalize(); + } + cb = (function(_this) { + return function() { + if (!doc.contains(_this.nodes.comment)) { + return; + } + $.off(d, 'PostsInserted', cb); + return $.event('mathjax', null, _this.nodes.comment); + }; + })(this); + $.on(d, 'PostsInserted', cb); + return cb(); + } + }; + + return Fourchan; + +}).call(this); + +IDColor = (function() { + var IDColor; + + 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 Callbacks.Post.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; + } + }; + + return IDColor; + +}).call(this); + +IDHighlight = (function() { + var IDHighlight; + + IDHighlight = { + init: function() { + var ref; + if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { + return; + } + return Callbacks.Post.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); + }; + } + }; + + return IDHighlight; + +}).call(this); + +Keybinds = (function() { + var Keybinds; + + Keybinds = { + init: function() { + var hotkey, init; + if (!Conf['Keybinds']) { + return; + } + for (hotkey in Config.hotkeys) { + $.sync(hotkey, Keybinds.sync); + } + init = function() { + var i, len, node, 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, i, key, len, notification, notifications, op, ref, ref1, ref2, ref3, ref4, ref5, searchInput, target, thread, threadRoot; + 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) && !/^Alt\+(\d|Up|Down|Left|Right)$/.test(key))) { + return; + } + } + if (!(((ref1 = g.VIEW) !== 'index' && ref1 !== 'thread') || g.VIEW === 'index' && Conf['JSON Index'] && Conf['Index Mode'] === 'catalog' || g.VIEW === 'index' && g.BOARD.ID === 'f')) { + 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['SJIS tags']: + if (target.nodeName !== 'TEXTAREA') { + return; + } + Keybinds.tags('sjis', 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 Index'] && g.BOARD.ID !== 'f')) { + return; + } + Index.update(); + break; + default: + return; + } + break; + case Conf['Watch']: + if (!(ThreadWatcher.enabled && thread)) { + return; + } + ThreadWatcher.toggle(thread); + break; + case Conf['Update thread watcher']: + if (!ThreadWatcher.enabled) { + return; + } + ThreadWatcher.buttonFetchAll(); + 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'))) { + return; + } + FappeTyme.toggle('fappe'); + break; + case Conf['werkTyme']: + if (!(Conf['Werk Tyme'] && ((ref3 = g.VIEW) === 'index' || ref3 === 'thread'))) { + return; + } + FappeTyme.toggle('werk'); + break; + case Conf['Front page']: + if (Conf['JSON Index'] && g.VIEW === 'index' && g.BOARD.ID !== 'f') { + 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' && g.BOARD.ID !== 'f')) { + return; + } + if (Conf['JSON Index']) { + 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' && g.BOARD.ID !== 'f')) { + return; + } + if (Conf['JSON Index']) { + 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' && g.BOARD.ID !== 'f')) { + return; + } + searchInput = Conf['JSON Index'] ? Index.searchInput : $.id('search-box'); + Header.scrollToIfNeeded(searchInput); + searchInput.focus(); + break; + case Conf['Paged mode']: + if (!(Conf['JSON Index'] && g.BOARD.ID !== 'f')) { + return; + } + window.location = g.VIEW === 'index' ? '#paged' : "/" + g.BOARD + "/#paged"; + break; + case Conf['Infinite scrolling mode']: + if (!(Conf['JSON Index'] && g.BOARD.ID !== 'f')) { + return; + } + window.location = g.VIEW === 'index' ? '#infinite' : "/" + g.BOARD + "/#infinite"; + break; + case Conf['All pages mode']: + if (!(Conf['JSON Index'] && g.BOARD.ID !== 'f')) { + return; + } + window.location = g.VIEW === 'index' ? '#all-pages' : "/" + g.BOARD + "/#all-pages"; + break; + case Conf['Open catalog']: + if (g.BOARD.ID === 'f') { + return; + } + window.location = CatalogLinks.catalog(); + break; + case Conf['Cycle sort type']: + if (!(Conf['JSON Index'] && g.VIEW === 'index' && g.BOARD.ID !== '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 && QuoteYou.db)) { + return; + } + QuoteYou.cb.seek('preceding'); + break; + case Conf['Next Post Quoting You']: + if (!(threadRoot && QuoteYou.db)) { + 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 32: + return 'Space'; + case 37: + return 'Left'; + case 38: + return 'Up'; + case 39: + return 'Right'; + case 40: + return 'Down'; + case 188: + return 'Comma'; + case 190: + return 'Period'; + case 191: + return 'Slash'; + case 59: + case 186: + return 'Semicolon'; + default: + if ((48 <= kc && kc <= 57) || (65 <= kc && kc <= 90)) { + return String.fromCharCode(kc).toLowerCase(); + } else if ((96 <= kc && kc <= 105)) { + return String.fromCharCode(kc - 48).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'; + case 'sjis': + return g.BOARD.ID === 'jp'; + } + })(); + 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, i, len, next, postEl, replies, reply, root; + 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'); + } + }; + + return Keybinds; + +}).call(this); + +Nav = (function() { + var Nav; + + 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 i, len, ref, thread, threadRoot; + 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, ref, thread, top; + 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); + } + } + }; + + return Nav; + +}).call(this); + +NormalizeURL = (function() { + var NormalizeURL; + + NormalizeURL = { + init: function() { + var pathname; + if (!Conf['Normalize URL']) { + return; + } + pathname = location.pathname.split(/\/+/); + switch (g.VIEW) { + case 'thread': + pathname[2] = 'thread'; + pathname = pathname.slice(0, 4); + break; + case 'index': + pathname = pathname.slice(0, 3); + } + pathname = pathname.join('/'); + if (location.pathname !== pathname) { + return history.replaceState(history.state, '', location.protocol + "//" + location.host + pathname + location.hash); + } + } + }; + + return NormalizeURL; + +}).call(this); + +PSAHiding = (function() { + var PSAHiding; + + 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: "[Dismiss]" + }); + $.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() { + 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; + } + } + }; + + return PSAHiding; + +}).call(this); + +RelativeDates = (function() { + var RelativeDates, + 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; }; + + 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 Index'] && g.BOARD.ID !== 'f') { + this.flush(); + $.on(d, 'visibilitychange ThreadUpdate', this.flush); + } + if (Conf['Relative Post Dates']) { + return Callbacks.Post.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, i, len, now, 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, i, isPost, len, ref, relative, singlePost; + 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); + } + }; + + return RelativeDates; + +}).call(this); + +RemoveSpoilers = (function() { + var RemoveSpoilers, + slice = [].slice; + + RemoveSpoilers = { + init: function() { + if (Conf['Reveal Spoilers']) { + $.addClass(doc, 'reveal-spoilers'); + } + if (!Conf['Remove Spoilers']) { + return; + } + Callbacks.Post.push({ + name: 'Reveal Spoilers', + cb: this.node + }); + Callbacks.CatalogThread.push({ + name: 'Reveal Spoilers', + cb: this.node + }); + if (g.VIEW === 'archive') { + return $.ready(function() { + return RemoveSpoilers.unspoiler($.id('arc-list')); + }); + } + }, + node: function() { + return RemoveSpoilers.unspoiler(this.nodes.comment); + }, + unspoiler: function(el) { + var i, len, span, spoiler, spoilers; + 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)); + } + } + }; + + return RemoveSpoilers; + +}).call(this); + +Report = (function() { + var Report; + + Report = { + init: function() { + var match; + if (!(match = location.search.match(/\bno=(\d+)/))) { + return; + } + Captcha.replace.init(); + this.postID = +match[1]; + return $.ready(this.ready); + }, + ready: function() { + var passAd, prev, ref; + $.addStyle(CSS.report); + if (Conf['Archive Report']) { + Report.archive(); + } + if ((passAd = $('a[href="https://www.4chan.org/pass"]'))) { + $.extend(passAd, { + textContent: 'Complain', + href: 'https://www.4chan-x.net/captchas.html', + tabIndex: -1 + }); + passAd.parentNode.normalize(); + if (((ref = (prev = passAd.previousSibling)) != null ? ref.nodeType : void 0) === Node.TEXT_NODE) { + prev.nodeValue = prev.nodeValue.replace(/4chan Pass[^\.]*\./i, 'reCAPTCHA malfunctioning?'); + } + $.after(passAd, [ + $.tn('] ['), $.el('a', { + href: 'mailto:4chanpass@4chan.org?subject=4chan%20Pass%20-%20Purchase%20Support', + textContent: 'Email 4chan', + target: '_blank', + tabIndex: -1 + }) + ]); + } + if (!Conf['Use Recaptcha v1 in Reports'] && !Conf['Force Noscript Captcha'] && Main.jsEnabled) { + return new MutationObserver(function() { + Report.fit('iframe[src^="https://www.google.com/recaptcha/api2/frame"]'); + return Report.fit('body'); + }).observe(d.body, { + childList: true, + attributes: true, + subtree: true + }); + } else { + return Report.fit('body'); + } + }, + fit: function(selector) { + var dy, el; + if (!((el = $(selector, doc)) && getComputedStyle(el).visibility !== 'hidden')) { + return; + } + dy = el.getBoundingClientRect().bottom - doc.clientHeight + 8; + if (dy > 0) { + return window.resizeBy(0, dy); + } + }, + archive: function() { + var link, message, types, url; + Redirect.init(); + if (!(url = Redirect.to('report', { + boardID: g.BOARD.ID, + postID: Report.postID + }))) { + return; + } + if ((message = $('h3')) && /Report submitted!/.test(message.textContent)) { + if (location.hash === '#redirect') { + $.globalEval('self.close = function(){};'); + window.resizeTo(700, 475); + location.replace(url); + } + return; + } + link = $.el('a', { + href: url, + textContent: 'Report to archive' + }); + $.on(link, 'click', function(e) { + if (!(e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0)) { + return window.resizeTo(700, 475); + } + }); + $.add(d.body, [$.tn(' ['), link, $.tn(']')]); + if (types = $.id('reportTypes')) { + return $.on(types, 'change', function(e) { + return $('form').action = e.target.value === 'illegal' ? '#redirect' : ''; + }); + } + } + }; + + return Report; + +}).call(this); + +ThreadLinks = (function() { + var ThreadLinks; + + ThreadLinks = { + init: function() { + if (!(g.VIEW === 'index' && Conf['Open Threads in New Tab'])) { + return; + } + Callbacks.Post.push({ + name: 'Thread Links', + cb: this.node + }); + return Callbacks.CatalogThread.push({ + name: 'Thread Links', + cb: this.catalogNode + }); + }, + node: function() { + if (this.isReply || this.isClone) { + return; + } + return ThreadLinks.process($('.replylink', this.nodes.info)); + }, + catalogNode: function() { + return ThreadLinks.process(this.nodes.thumb.parentNode); + }, + process: function(link) { + return link.target = '_blank'; + } + }; + + return ThreadLinks; + +}).call(this); + +Time = (function() { + var Time; + + Time = { + init: function() { + var ref; + if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Time Formatting'])) { + return; + } + return Callbacks.Post.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 '%'; + } + } + }; + + return Time; + +}).call(this); + +Favicon = (function() { + var Favicon; + + 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==' + }; + + return Favicon; + +}).call(this); + +MarkNewIPs = (function() { + var MarkNewIPs; + + MarkNewIPs = { + init: function() { + if (g.VIEW !== 'thread' || !Conf['Mark New IPs']) { + return; + } + return Callbacks.Thread.push({ + name: 'Mark New IPs', + cb: this.node + }); + }, + node: function() { + MarkNewIPs.ipCount = this.ipCount; + MarkNewIPs.postCount = this.posts.keys.length; + return $.on(d, 'ThreadUpdate', MarkNewIPs.onUpdate); + }, + onUpdate: function(e) { + var deletedPosts, fullID, i, ipCount, j, k, len, len1, newPosts, postCount, ref; + ref = e.detail, ipCount = ref.ipCount, postCount = ref.postCount, newPosts = ref.newPosts, deletedPosts = ref.deletedPosts; + if (ipCount == null) { + return; + } + switch (ipCount - MarkNewIPs.ipCount) { + case postCount - MarkNewIPs.postCount + deletedPosts.length: + i = MarkNewIPs.ipCount; + for (j = 0, len = newPosts.length; j < len; j++) { + fullID = newPosts[j]; + MarkNewIPs.markNew(g.posts[fullID], ++i); + } + break; + case -deletedPosts.length: + for (k = 0, len1 = newPosts.length; k < len1; k++) { + fullID = newPosts[k]; + MarkNewIPs.markOld(g.posts[fullID]); + } + } + MarkNewIPs.ipCount = ipCount; + return MarkNewIPs.postCount = postCount; + }, + 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'); + } + }; + + return MarkNewIPs; + +}).call(this); + +ReplyPruning = (function() { + var ReplyPruning; + + ReplyPruning = { + init: function() { + var el, label; + if (!(g.VIEW === 'thread' && Conf['Reply Pruning'])) { + return; + } + this.active = !(Conf['Quote Threading'] && Conf['Thread Quotes']); + this.container = $.frag(); + this.summary = $.el('span', { + hidden: true, + className: 'summary' + }); + this.summary.style.cursor = 'pointer'; + $.on(this.summary, 'click', (function(_this) { + return function() { + _this.inputs.enabled.checked = !_this.inputs.enabled.checked; + return $.event('change', null, _this.inputs.enabled); + }; + })(this)); + label = UI.checkbox('Prune Replies', 'Show Last', this.active); + el = $.el('span', { + title: 'Maximum number of replies to show.' + }, { + innerHTML: " " + }); + $.prepend(el, label); + this.inputs = { + enabled: label.firstElementChild, + replies: el.lastElementChild + }; + $.on(this.inputs.enabled, 'change', this.setEnabled); + $.on(this.inputs.replies, 'change', $.cb.value); + Header.menu.addEntry({ + el: el, + order: 190 + }); + return Callbacks.Thread.push({ + name: 'Reply Pruning', + cb: this.node + }); + }, + position: 0, + hidden: 0, + hiddenFiles: 0, + total: 0, + totalFiles: 0, + setEnabled: function() { + var other; + other = QuoteThreading.input; + if (this.checked && (other != null ? other.checked : void 0)) { + other.checked = false; + $.event('change', null, other); + } + return ReplyPruning.active = this.checked; + }, + showIfHidden: function(id) { + var ref; + if ((ref = ReplyPruning.container) != null ? ref.getElementById(id) : void 0) { + ReplyPruning.inputs.enabled.checked = false; + return $.event('change', null, ReplyPruning.inputs.enabled); + } + }, + node: function() { + var ref; + ReplyPruning.thread = this; + this.posts.forEach(function(post) { + if (post.isReply) { + ReplyPruning.total++; + if (post.file) { + return ReplyPruning.totalFiles++; + } + } + }); + if (ReplyPruning.active && /^#p\d+$/.test(location.hash) && (0 <= (ref = this.posts.keys.indexOf(location.hash.slice(2))) && ref < 1 + Math.max(ReplyPruning.total - +Conf["Max Replies"], 0))) { + ReplyPruning.active = ReplyPruning.inputs.enabled.checked = false; + } + $.after(this.OP.nodes.root, ReplyPruning.summary); + $.on(ReplyPruning.inputs.enabled, 'change', ReplyPruning.update); + $.on(ReplyPruning.inputs.replies, 'change', ReplyPruning.update); + $.on(d, 'ThreadUpdate', ReplyPruning.updateCount); + $.on(d, 'ThreadUpdate', ReplyPruning.update); + return ReplyPruning.update(); + }, + updateCount: function(e) { + var fullID, i, len, ref; + if (e.detail[404]) { + return; + } + ref = e.detail.newPosts; + for (i = 0, len = ref.length; i < len; i++) { + fullID = ref[i]; + ReplyPruning.total++; + if (g.posts[fullID].file) { + ReplyPruning.totalFiles++; + } + } + }, + update: function() { + var boardTop, frag, hidden2, oldPos, post, posts; + hidden2 = ReplyPruning.active ? Math.max(ReplyPruning.total - +Conf["Max Replies"], 0) : 0; + oldPos = d.body.clientHeight - window.scrollY; + posts = ReplyPruning.thread.posts; + if (ReplyPruning.hidden < hidden2) { + while (ReplyPruning.hidden < hidden2 && ReplyPruning.position < posts.keys.length) { + post = posts[posts.keys[ReplyPruning.position++]]; + if (post.isReply && !post.isFetchedQuote) { + $.add(ReplyPruning.container, post.nodes.root); + ReplyPruning.hidden++; + if (post.file) { + ReplyPruning.hiddenFiles++; + } + } + } + } else if (ReplyPruning.hidden > hidden2) { + frag = $.frag(); + while (ReplyPruning.hidden > hidden2 && ReplyPruning.position > 0) { + post = posts[posts.keys[--ReplyPruning.position]]; + if (post.isReply && !post.isFetchedQuote) { + $.prepend(frag, post.nodes.root); + ReplyPruning.hidden--; + if (post.file) { + ReplyPruning.hiddenFiles--; + } + } + } + $.after(ReplyPruning.summary, frag); + $.event('PostsInserted'); + } + ReplyPruning.summary.textContent = ReplyPruning.active ? Build.summaryText('+', ReplyPruning.hidden, ReplyPruning.hiddenFiles) : Build.summaryText('-', ReplyPruning.total, ReplyPruning.totalFiles); + ReplyPruning.summary.hidden = ReplyPruning.total <= +Conf["Max Replies"]; + if ((boardTop = Header.getTopOf($('.board'))) < 0) { + return window.scroll(window.scrollX, Math.max(d.body.clientHeight - oldPos, window.scrollY + boardTop)); + } + } + }; + + return ReplyPruning; + +}).call(this); + +ThreadExcerpt = (function() { + var ThreadExcerpt; + + ThreadExcerpt = { + init: function() { + if (g.BOARD.ID !== 'f' || g.VIEW !== 'thread' || !Conf['Thread Excerpt']) { + return; + } + return Callbacks.Thread.push({ + name: 'Thread Excerpt', + cb: this.node + }); + }, + node: function() { + return d.title = Get.threadExcerpt(this); + } + }; + + return ThreadExcerpt; + +}).call(this); + +ThreadStats = (function() { + var ThreadStats; + + ThreadStats = { + init: function() { + var sc, statsHTML, statsTitle; + if (g.VIEW !== 'thread' || !Conf['Thread Stats']) { + return; + } + statsHTML = { + innerHTML: "? / ?" + ((Conf["IP Count in Stats"]) ? " / ?" : "") + ((Conf["Page Count in Stats"]) ? " / ?" : "") + }; + statsTitle = 'Posts / Files'; + if (Conf['IP Count in Stats']) { + statsTitle += ' / IPs'; + } + if (Conf['Page Count in Stats']) { + statsTitle += (g.BOARD.ID === 'f' ? ' / Purge Position' : ' / 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: "
              " + (statsHTML).innerHTML + "
              " + }); + $.addClass(doc, 'float'); + $.ready(function() { + return $.add(d.body, sc); + }); + } + this.postCountEl = $('#post-count', sc); + this.fileCountEl = $('#file-count', sc); + this.ipCountEl = $('#ip-count', sc); + this.pageCountEl = $('#page-count', sc); + if (this.pageCountEl) { + $.on(this.pageCountEl, 'click', ThreadStats.fetchPage); + } + return Callbacks.Thread.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 (ThreadStats.pageCountEl) { + 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 (!ThreadStats.pageCountEl) { + return; + } + if (newPosts.length) { + ThreadStats.lastPost = g.posts[newPosts[newPosts.length - 1]].info.date; + } + if (g.BOARD.ID !== 'f' && ((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) && ipCountEl) { + ipCountEl.textContent = ipCount; + } + (thread.postLimit && !thread.isSticky ? $.addClass : $.rmClass)(postCountEl, 'warning'); + return (thread.fileLimit && !thread.isSticky ? $.addClass : $.rmClass)(fileCountEl, 'warning'); + }, + fetchPage: function() { + if (!ThreadStats.pageCountEl) { + 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: 'ThreadStats' + }); + }, + onThreadsLoad: function() { + var i, j, k, len, len1, len2, page, purgePos, ref, ref1, ref2, thread; + if (this.status === 200) { + ref = this.response; + for (i = 0, len = ref.length; i < len; i++) { + page = ref[i]; + if (g.BOARD.ID === 'f') { + purgePos = 1; + ref1 = page.threads; + for (j = 0, len1 = ref1.length; j < len1; j++) { + thread = ref1[j]; + if (thread.no < ThreadStats.thread.ID) { + purgePos++; + } + } + ThreadStats.pageCountEl.textContent = purgePos; + } else { + ref2 = page.threads; + for (k = 0, len2 = ref2.length; k < len2; k++) { + thread = ref2[k]; + 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); + ThreadStats.retry(); + return; + } + } + } + } else if (this.status === 304) { + return ThreadStats.retry(); + } + }, + retry: function() { + var ref; + if (g.BOARD.ID !== 'f' && ThreadStats.lastPost > ThreadStats.lastPageUpdate && ((ref = ThreadStats.pageCountEl) != null ? ref.textContent : void 0) !== '1') { + clearTimeout(ThreadStats.timeout); + return ThreadStats.timeout = setTimeout(ThreadStats.fetchPage, 5 * $.SECOND); + } + } + }; + + return ThreadStats; + +}).call(this); + +ThreadUpdater = (function() { + var ThreadUpdater, + 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; }; + + ThreadUpdater = { + init: function() { + var conf, el, input, name, ref, sc, subEntries, updateLink; + if (g.VIEW !== 'thread' || !Conf['Thread Updater']) { + return; + } + this.audio = $.el('audio', { + src: ThreadUpdater.beep + }); + if (Conf['Updater and Stats in Header']) { + this.dialog = sc = $.el('span', { + id: 'updater' + }); + $.extend(sc, { + innerHTML: "" + }); + $.ready(function() { + return Header.addShortcut(sc); + }); + } else { + this.dialog = sc = UI.dialog('updater', 'bottom: 0px; left: 0px;', { + innerHTML: "
              " + }); + $.addClass(doc, 'float'); + $.ready(function() { + return $.add(d.body, sc); + }); + } + this.checkPostCount = 0; + this.timer = $('#update-timer', sc); + this.status = $('#update-status', sc); + $.on(this.timer, 'click', this.update); + $.on(this.status, 'click', this.update); + updateLink = $.el('span', { + className: 'brackets-wrap updatelink' + }); + $.extend(updateLink, { + innerHTML: "Update" + }); + Main.ready(function() { + var navLinksBot; + if ((navLinksBot = $('.navLinksBot'))) { + 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.setInterval); + } + subEntries.push({ + el: el + }); + } + this.settings = $.el('span', { + innerHTML: "Interval" + }); + $.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 Callbacks.Thread.push({ + name: 'Thread Updater', + cb: this.node + }); + }, + node: function() { + ThreadUpdater.thread = this; + ThreadUpdater.root = this.OP.nodes.root.parentNode; + ThreadUpdater.outdateCount = 0; + ThreadUpdater.postIDs = []; + ThreadUpdater.fileIDs = []; + this.posts.forEach(function(post) { + ThreadUpdater.postIDs.push(post.ID); + if (post.file) { + return ThreadUpdater.fileIDs.push(post.ID); + } + }); + ThreadUpdater.cb.interval.call($.el('input', { + value: Conf['Interval'] + })); + $.on(d, 'QRPostSuccessful', ThreadUpdater.cb.checkpost); + $.on(d, 'visibilitychange', ThreadUpdater.cb.visibility); + return ThreadUpdater.setInterval(); + }, + + /* + 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', + playBeep: function() { + var audio; + audio = ThreadUpdater.audio; + if (audio.paused) { + return audio.play(); + } else { + return $.one(audio, 'ended', ThreadUpdater.playBeep); + } + }, + cb: { + checkpost: function(e) { + if (e.detail.threadID !== ThreadUpdater.thread.ID) { + return; + } + ThreadUpdater.postID = e.detail.postID; + ThreadUpdater.checkPostCount = 0; + ThreadUpdater.outdateCount = 0; + return ThreadUpdater.setInterval(); + }, + 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; + }; + }, + 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() { + var req; + req = ThreadUpdater.req; + switch (req.status) { + case 200: + ThreadUpdater.parse(req); + if (ThreadUpdater.thread.isArchived) { + return ThreadUpdater.kill(); + } else { + return ThreadUpdater.setInterval(); + } + break; + case 404: + return $.ajax("//a.4cdn.org/" + ThreadUpdater.thread.board + "/catalog.json", { + onloadend: function() { + var confirmed, i, k, len, len1, page, ref, ref1, thread; + 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 (k = 0, len1 = ref1.length; k < len1; k++) { + thread = ref1[k]; + if (thread.no === ThreadUpdater.thread.ID) { + confirmed = false; + break; + } + } + } + } else { + confirmed = false; + } + if (confirmed) { + return ThreadUpdater.kill(); + } else { + return ThreadUpdater.error(req); + } + } + }); + default: + return ThreadUpdater.error(req); + } + } + }, + kill: function() { + ThreadUpdater.thread.kill(); + ThreadUpdater.setInterval(); + return $.event('ThreadUpdate', { + 404: true, + threadID: ThreadUpdater.thread.fullID + }); + }, + error: function(req) { + if (req.status === 304) { + ThreadUpdater.set('status', ''); + } + ThreadUpdater.setInterval(); + if (!req.status) { + return ThreadUpdater.set('status', 'Connection Failed', 'warning'); + } else if (req.status !== 304) { + return ThreadUpdater.set('status', req.statusText + " (" + req.status + ")", 'warning'); + } + }, + setInterval: function() { + var cur, interval, j, limit; + clearTimeout(ThreadUpdater.timeoutID); + if (ThreadUpdater.thread.isDead) { + ThreadUpdater.set('status', (ThreadUpdater.thread.isArchived ? 'Archived' : '404'), 'warning'); + ThreadUpdater.set('timer', ''); + return; + } + if (ThreadUpdater.postID && ThreadUpdater.checkPostCount < 5) { + ThreadUpdater.set('timer', '...', 'loading'); + ThreadUpdater.timeoutID = setTimeout(ThreadUpdater.update, ++ThreadUpdater.checkPostCount * $.SECOND); + return; + } + if (!Conf['Auto Update']) { + ThreadUpdater.set('timer', 'Update'); + return; + } + interval = ThreadUpdater.interval; + if (Conf['Optional Increase']) { + limit = d.hidden ? 10 : 5; + j = Math.min(ThreadUpdater.outdateCount, limit); + cur = (Math.floor(interval * 0.1) || 1) * j * j; + ThreadUpdater.seconds = $.minmax(cur, interval, 300); + } else { + ThreadUpdater.seconds = interval; + } + return ThreadUpdater.timeout(); + }, + 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; + } + return el.className = klass != null ? klass : (text === '' ? 'empty' : ''); + }, + timeout: function() { + if (ThreadUpdater.seconds) { + ThreadUpdater.set('timer', ThreadUpdater.seconds); + ThreadUpdater.timeoutID = setTimeout(ThreadUpdater.timeout, 1000); + } else { + ThreadUpdater.outdateCount++; + ThreadUpdater.update(); + } + return ThreadUpdater.seconds--; + }, + update: function() { + var ref; + clearTimeout(ThreadUpdater.timeoutID); + ThreadUpdater.set('timer', '...', 'loading'); + 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: 'ThreadUpdater' + }); + }, + 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(req) { + var ID, OP, board, deletedFiles, deletedPosts, files, firstPost, i, index, ipCountEl, k, l, lastPost, len, len1, len2, len3, m, newPosts, node, post, postObject, postObjects, posts, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, scroll, thread, unreadCount, unreadQYCount; + postObjects = req.response.posts; + OP = postObjects[0]; + thread = ThreadUpdater.thread; + board = thread.board; + ref = ThreadUpdater.postIDs, lastPost = ref[ref.length - 1]; + if (postObjects[postObjects.length - 1].no < lastPost && new Date(req.getResponseHeader('Last-Modified')) - thread.posts[lastPost].info.date < 30 * $.SECOND) { + return; + } + Build.spoilerRange[board] = OP.custom_spoiler; + thread.setStatus('Archived', !!OP.archived); + ThreadUpdater.updateThreadStatus('Sticky', !!OP.sticky); + ThreadUpdater.updateThreadStatus('Closed', !!OP.closed); + thread.postLimit = !!OP.bumplimit; + thread.fileLimit = !!OP.imagelimit; + if (OP.unique_ips != null) { + thread.ipCount = OP.unique_ips; + } + posts = []; + index = []; + files = []; + newPosts = []; + for (i = 0, len = postObjects.length; i < len; i++) { + postObject = postObjects[i]; + ID = postObject.no; + index.push(ID); + if (postObject.fsize) { + files.push(ID); + } + if (ID <= lastPost) { + continue; + } + if ((post = thread.posts[ID]) && !post.isFetchedQuote) { + post.resurrect(); + continue; + } + newPosts.push(board + "." + ID); + node = Build.postFromObject(postObject, board.ID); + posts.push(new Post(node, thread, board)); + if (ThreadUpdater.postID === ID) { + delete ThreadUpdater.postID; + } + } + deletedPosts = []; + ref1 = ThreadUpdater.postIDs; + for (k = 0, len1 = ref1.length; k < len1; k++) { + ID = ref1[k]; + if (!(indexOf.call(index, ID) < 0)) { + continue; + } + thread.posts[ID].kill(); + deletedPosts.push(board + "." + ID); + } + ThreadUpdater.postIDs = index; + deletedFiles = []; + ref2 = ThreadUpdater.fileIDs; + for (l = 0, len2 = ref2.length; l < len2; l++) { + ID = ref2[l]; + if (!(!(indexOf.call(files, ID) >= 0 || (ref3 = board + "." + ID, indexOf.call(deletedPosts, ref3) >= 0)))) { + continue; + } + thread.posts[ID].kill(true); + deletedFiles.push(board + "." + ID); + } + ThreadUpdater.fileIDs = files; + if (!posts.length) { + ThreadUpdater.set('status', ''); + } else { + ThreadUpdater.set('status', "+" + posts.length, 'new'); + ThreadUpdater.outdateCount = 0; + unreadCount = (ref4 = Unread.posts) != null ? ref4.size : void 0; + unreadQYCount = (ref5 = Unread.postsQuotingYou) != null ? ref5.size : void 0; + Main.callbackNodes('Post', posts); + if (d.hidden || !d.hasFocus()) { + if (Conf['Beep Quoting You'] && ((ref6 = Unread.postsQuotingYou) != null ? ref6.size : void 0) > unreadQYCount) { + ThreadUpdater.playBeep(); + if (Conf['Beep']) { + ThreadUpdater.playBeep(); + } + } else if (Conf['Beep'] && ((ref7 = Unread.posts) != null ? ref7.size : void 0) > 0 && unreadCount === 0) { + ThreadUpdater.playBeep(); + } + } + scroll = Conf['Auto Scroll'] && ThreadUpdater.scrollBG() && ThreadUpdater.root.getBoundingClientRect().bottom - doc.clientHeight < 25; + firstPost = null; + for (m = 0, len3 = posts.length; m < len3; m++) { + post = posts[m]; + if (!QuoteThreading.insert(post)) { + firstPost || (firstPost = post.nodes.root); + $.add(ThreadUpdater.root, post.nodes.root); + } + } + $.event('PostsInserted'); + if (scroll) { + if (Conf['Bottom Scroll']) { + window.scrollTo(0, d.body.clientHeight); + } else { + if (firstPost) { + Header.scrollTo(firstPost); + } + } + } + } + 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'); + } + return $.event('ThreadUpdate', { + 404: false, + threadID: thread.fullID, + newPosts: newPosts, + deletedPosts: deletedPosts, + deletedFiles: deletedFiles, + postCount: OP.replies + 1, + fileCount: OP.images + !!OP.fsize, + ipCount: OP.unique_ips + }); + } + }; + + return ThreadUpdater; + +}).call(this); + +ThreadWatcher = (function() { + var ThreadWatcher, + slice = [].slice; + + ThreadWatcher = { + init: function() { + var sc; + if (!(this.enabled = 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: "
              Thread Watcher ×
              " + }); + this.status = $('#watcher-status', this.dialog); + this.list = this.dialog.lastElementChild; + this.refreshButton = $('.refresh', this.dialog); + this.closeButton = $('.move > .close', this.dialog); + this.unreaddb = Unread.db || new DataBoard('lastReadPosts'); + this.unreadEnabled = Conf['Remember Last Read Post']; + $.on(d, 'QRPostSuccessful', this.cb.post); + $.on(sc, 'click', this.toggleWatcher); + $.on(this.refreshButton, 'click', this.buttonFetchAll); + $.on(this.closeButton, '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['Fixed Thread Watcher']) { + $.addClass(doc, 'fixed-watcher'); + } + if (Conf['Toggleable Thread Watcher']) { + this.dialog.hidden = true; + Header.addShortcut(sc); + $.addClass(doc, 'toggleable-watcher'); + } + ThreadWatcher.fetchAuto(); + if (g.VIEW === 'index' && Conf['JSON Index'] && Conf['Menu'] && g.BOARD.ID !== 'f') { + Menu.menu.addEntry({ + el: $.el('a', { + href: 'javascript:;', + className: 'has-shortcut-text' + }, { + innerHTML: "Alt+click" + }), + order: 6, + open: function(arg) { + var thread; + thread = arg.thread; + if (Conf['Index Mode'] !== 'catalog') { + return false; + } + this.el.firstElementChild.textContent = ThreadWatcher.isWatched(thread) ? 'Unwatch' : 'Watch'; + 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; + } + }); + } + Callbacks.Post.push({ + name: 'Thread Watcher', + cb: this.node + }); + return Callbacks.CatalogThread.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('a', { + href: 'javascript:;', + 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'); + } + $.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)); + return $.on(this.nodes.thumb.parentNode, 'mousedown', function(e) { + if (e.button === 0 && e.altKey) { + return e.preventDefault(); + } + }); + }, + ready: function() { + $.off(d, '4chanXInitFinished', ThreadWatcher.ready); + if (!Main.isThisPageLegit()) { + return; + } + ThreadWatcher.refresh(); + $.add(d.body, ThreadWatcher.dialog); + 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, i, len, ref, ref1, threadID; + if ($.hasClass(this, 'disabled')) { + return; + } + ThreadWatcher.db.forceSync(); + 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, ref, threadID; + ref = this.parentNode.dataset.fullID.split('.'), boardID = ref[0], threadID = ref[1]; + return ThreadWatcher.rm(boardID, +threadID); + }, + post: function(e) { + var boardID, postID, ref, threadID; + 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, ref, threadID; + db = ThreadWatcher.db; + boardID = g.BOARD.ID; + db.forceSync(); + ref = db.data.boards[boardID]; + for (threadID in ref) { + data = ref[threadID]; + if (!(data != null ? data.isDead : void 0) && !(threadID in g.BOARD.threads)) { + if (Conf['Auto Prune'] || !(data && typeof data === 'object')) { + db["delete"]({ + boardID: boardID, + threadID: threadID + }); + } else { + if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { + ThreadWatcher.fetchStatus({ + boardID: boardID, + threadID: threadID, + data: data + }); + } + data.isDead = true; + 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); + } + }, + requests: [], + fetched: 0, + clearRequests: function() { + ThreadWatcher.requests = []; + ThreadWatcher.fetched = 0; + ThreadWatcher.status.textContent = ''; + return $.rmClass(ThreadWatcher.refreshButton, 'fa-spin'); + }, + abort: function() { + var i, len, ref, req; + ref = ThreadWatcher.requests; + for (i = 0, len = ref.length; i < len; i++) { + req = ref[i]; + if (req.readyState !== 4) { + req.abort(); + } + } + return ThreadWatcher.clearRequests(); + }, + fetchAuto: function() { + var db, interval, now; + clearTimeout(ThreadWatcher.timeout); + if (!Conf['Auto Update Thread Watcher']) { + return; + } + db = ThreadWatcher.db; + interval = ThreadWatcher.unreadEnabled && 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); + }, + buttonFetchAll: function() { + if (ThreadWatcher.requests.length) { + return ThreadWatcher.abort(); + } else { + return ThreadWatcher.fetchAllStatus(); + } + }, + fetchAllStatus: function() { + var i, len, ref, thread, threads; + ThreadWatcher.db.forceSync(); + ThreadWatcher.unreaddb.forceSync(); + if ((ref = QuoteYou.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, req, threadID; + boardID = thread.boardID, threadID = thread.threadID, data = thread.data; + if (data.isDead && !force) { + return; + } + if (ThreadWatcher.requests.length === 0) { + ThreadWatcher.status.textContent = '...'; + $.addClass(ThreadWatcher.refreshButton, 'fa-spin'); + } + req = $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", { + onloadend: function() { + return ThreadWatcher.parseStatus.call(this, thread); + }, + timeout: $.MINUTE + }, { + whenModified: force ? false : 'ThreadWatcher' + }); + return ThreadWatcher.requests.push(req); + }, + parseStatus: function(arg) { + var boardID, data, i, isDead, lastReadPost, len, match, postObj, quotesYou, quotingYou, ref, ref1, regexp, threadID, unread; + boardID = arg.boardID, threadID = arg.threadID, data = arg.data; + ThreadWatcher.fetched++; + if (ThreadWatcher.fetched === ThreadWatcher.requests.length) { + ThreadWatcher.clearRequests(); + } else { + ThreadWatcher.status.textContent = (Math.round(ThreadWatcher.fetched / ThreadWatcher.requests.length * 100)) + "%"; + } + 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 = QuoteYou.db) != null ? ref1.get({ + boardID: boardID, + threadID: threadID, + postID: postObj.no + }) : void 0) { + continue; + } + unread++; + if (!(QuoteYou.db && postObj.com)) { + continue; + } + quotesYou = false; + regexp = /]*\bhref="(?:\/([^\/]+)\/thread\/)?(\d+)?(?:#p(\d+))?"/g; + while (match = regexp.exec(postObj.com)) { + if (QuoteYou.db.get({ + boardID: match[1] || boardID, + threadID: match[2] || threadID, + postID: match[3] || match[2] || threadID + })) { + quotesYou = true; + break; + } + } + if (quotesYou && !Filter.isHidden(Build.parseJSON(postObj, boardID))) { + quotingYou++; + } + } + 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, ref, threadID, threads; + 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]; + if (data && typeof data === 'object') { + 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 (ThreadWatcher.unreadEnabled && 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 (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { + if (data.unread === 0) { + $.addClass(div, 'replies-read'); + } + 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, i, j, len, len1, list, nodes, ref, ref1, ref2, refresher, threadID; + 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, j, len1, post, ref2, toggler; + 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, ref, val; + 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(); + } + }, + set404: function(boardID, threadID, cb) { + var data, ref; + if (!(data = (ref = ThreadWatcher.db) != null ? ref.get({ + boardID: boardID, + threadID: threadID + }) : void 0)) { + return cb(); + } + if (Conf['Auto Prune']) { + ThreadWatcher.db["delete"]({ + boardID: boardID, + threadID: threadID + }); + return cb(); + } + if (data.isDead && !((data.unread != null) || (data.quotingYou != null))) { + return cb(); + } + data.isDead = true; + delete data.unread; + delete data.quotingYou; + return ThreadWatcher.db.set({ + boardID: boardID, + threadID: threadID, + val: data + }, cb); + }, + 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 (ThreadWatcher.unreadEnabled && 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(); + }, + 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, ref, rmClass, text; + 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, i, len, name, ref, ref1, refresh, subEntries; + 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; + if (name === 'Show Unread Count' && !ThreadWatcher.unreadEnabled) { + input.disabled = true; + $.addClass(entry.el, 'disabled'); + entry.el.title += '\n[Remember Last Read Post is disabled.]'; + } + $.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; + } + } + }; + + return ThreadWatcher; + +}).call(this); + +Unread = (function() { + var Unread; + + Unread = { + init: function() { + if (!(g.VIEW === 'thread' && (Conf['Unread Count'] || Conf['Unread Favicon'] || Conf['Unread Line'] || Conf['Remember Last Read Post'] || Conf['Desktop Notifications'] || Conf['Quote Threading']))) { + return; + } + if (Conf['Remember Last Read Post']) { + $.sync('Remember Last Read Post', function(enabled) { + return Conf['Remember Last Read Post'] = enabled; + }); + 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; + Callbacks.Thread.push({ + name: 'Unread', + cb: this.node + }); + return Callbacks.Post.push({ + name: 'Unread', + cb: this.addPost + }); + }, + node: function() { + var ID, j, len, ref, ref1; + Unread.thread = this; + Unread.title = d.title; + Unread.lastReadPost = ((ref = Unread.db) != null ? ref.get({ + boardID: this.board.ID, + threadID: this.ID + }) : void 0) || 0; + Unread.readCount = 0; + ref1 = this.posts.keys; + for (j = 0, len = ref1.length; j < len; j++) { + ID = ref1[j]; + if (+ID <= Unread.lastReadPost) { + Unread.readCount++; + } + } + $.one(d, '4chanXInitFinished', Unread.ready); + return $.on(d, 'ThreadUpdate', Unread.onUpdate); + }, + ready: function() { + if (Conf['Remember Last Read Post'] && Conf['Scroll to Last Read Post']) { + Unread.scroll(); + } + Unread.setLine(true); + Unread.read(); + Unread.update(); + $.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, ref, root; + if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) { + return; + } + ReplyPruning.showIfHidden((ref = Unread.position) != null ? ref.data.nodes.root.id : void 0); + 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, j, lastReadPost, postIDs, 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 = j = ref = Unread.readCount, ref1 = postIDs.length; j < ref1; i = j += 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 = QuoteYou.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 j, len, quotelink, ref, ref1; + ref = post.nodes.quotelinks; + for (j = 0, len = ref.length; j < len; j++) { + quotelink = ref[j]; + if (!((ref1 = QuoteYou.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; + } + try { + notif = new Notification(post.info.nameBlock + " replied to you", { + body: post.info.commentDisplay, + icon: Favicon.logo + }); + notif.onclick = function() { + Header.scrollToIfNeeded(post.nodes.root, true); + return $.global(function() { + return window.focus(); + }); + }; + return notif.onshow = function() { + return setTimeout(function() { + return notif.close(); + }, 7 * $.SECOND); + }; + } catch (_error) {} + }, + 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, ref, ref1, root; + if (!Unread.posts.size && Unread.readCount !== Unread.thread.posts.keys.length) { + Unread.saveLastReadPost(); + } + if (d.hidden || !Unread.posts.size) { + return; + } + 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 ((ref1 = QuoteYou.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, j, postIDs, ref, ref1; + $.forceSync('Remember Last Read Post'); + if (!(Conf['Remember Last Read Post'] && Unread.db)) { + return; + } + postIDs = Unread.thread.posts.keys; + for (i = j = ref = Unread.readCount, ref1 = postIDs.length; j < ref1; i = j += 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 (Unread.hr.hidden || 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, isDead, 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; + } + $.forceSync('Remember Last Read Post'); + if (Conf['Remember Last Read Post'] && (!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']) { + isDead = Unread.thread.isDead; + Favicon.el.href = countQuotingYou ? Favicon[isDead ? 'unreadDeadY' : 'unreadY'] : count ? Favicon[isDead ? 'unreadDead' : 'unread'] : Favicon[isDead ? 'dead' : 'default']; + return $.add(d.head, Favicon.el); + } + } + }; + + return Unread; + +}).call(this); + +Captcha = {}; + +(function() { + Captcha.fixes = { + imageKeys: '789456123uiojklm'.split('').concat(['Comma', 'Period']), + imageKeys16: '7890uiopjkl'.split('').concat(['Semicolon', 'm', 'Comma', 'Period', 'Slash']), + css: '.rc-imageselect-target > div:focus, .rc-image-tile-target:focus {\n outline: 2px solid #4a90e2;\n}\n.rc-imageselect-target td:focus {\n box-shadow: inset 0 0 0 2px #4a90e2;\n outline: none;\n}\n.rc-button-default:focus {\n box-shadow: inset 0 0 0 2px #0063d6;\n}', + cssNoscript: '.fbc-payload-imageselect {\n position: relative;\n}\n.fbc-payload-imageselect > label {\n position: absolute;\n display: block;\n height: 93.3px;\n width: 93.3px;\n}\nlabel[data-row="0"] {top: 0px;}\nlabel[data-row="1"] {top: 93.3px;}\nlabel[data-row="2"] {top: 186.6px;}\nlabel[data-col="0"] {left: 0px;}\nlabel[data-col="1"] {left: 93.3px;}\nlabel[data-col="2"] {left: 186.6px;}\n.fbc-payload-imageselect > input:focus + label {\n outline: 2px solid #4a90e2;\n}\n.fbc-button-verify input:focus {\n box-shadow: inset 0 0 0 2px #0063d6;\n}\nbody.focus .fbc {\n box-shadow: inset 0 0 0 2px #4a90e2;\n}', + init: function() { + switch (location.pathname.split('/')[3]) { + case 'anchor': + return this.initMain(); + case 'frame': + return this.initPopup(); + case 'fallback': + return this.initNoscript(); + } + }, + initMain: function() { + var a, j, len, ref; + $.onExists(d.body, '#recaptcha-anchor', function(checkbox) { + var focus; + focus = function() { + var ref; + if (d.hasFocus() && ((ref = d.activeElement) === d.documentElement || ref === d.body)) { + return checkbox.focus(); + } + }; + focus(); + return $.on(window, 'focus', function() { + return $.queueTask(focus); + }); + }); + ref = $$('.rc-anchor-pt a'); + for (j = 0, len = ref.length; j < len; j++) { + a = ref[j]; + a.tabIndex = -1; + } + }, + initPopup: function() { + $.addStyle(this.css); + this.fixImages(); + new MutationObserver((function(_this) { + return function() { + return _this.fixImages(); + }; + })(this)).observe(d.body, { + childList: true, + subtree: true + }); + return $.on(d, 'keydown', this.keybinds.bind(this)); + }, + initNoscript: function() { + var data, ref, token; + this.noscript = true; + data = (token = (ref = $('.fbc-verification-token > textarea')) != null ? ref.value : void 0) ? { + token: token + } : { + working: true + }; + new Connection(window.parent, '*').send(data); + d.body.classList.toggle('focus', d.hasFocus()); + $.on(window, 'focus blur', function() { + return d.body.classList.toggle('focus', d.hasFocus()); + }); + this.images = $$('.fbc-payload-imageselect > input'); + this.width = 3; + if (this.images.length !== 9) { + return; + } + $.addStyle(this.cssNoscript); + this.addLabels(); + $.on(d, 'keydown', this.keybinds.bind(this)); + return $.on($('.fbc-imageselect-challenge > form'), 'submit', this.checkForm.bind(this)); + }, + fixImages: function() { + var img, j, len, ref; + this.images = $$('.rc-image-tile-target'); + if (!this.images.length) { + this.images = $$('.rc-imageselect-target > div, .rc-imageselect-target td'); + } + this.width = $$('.rc-imageselect-target tr:first-of-type td').length || Math.round(Math.sqrt(this.images.length)); + ref = this.images; + for (j = 0, len = ref.length; j < len; j++) { + img = ref[j]; + img.tabIndex = 0; + } + if (this.images.length === 9) { + this.addTooltips(this.images); + } else { + this.addTooltips16(this.images); + } + return this.complaintLinks(); + }, + complaintLinks: function() { + var errmsg, j, len, link, ref; + ref = $$('.rc-imageselect-incorrect-response, .rc-imageselect-error-select-one, .rc-imageselect-error-select-more, .rc-imageselect-error-dynamic-more'); + for (j = 0, len = ref.length; j < len; j++) { + errmsg = ref[j]; + if (!$('a', errmsg)) { + link = $.el('a', { + href: 'https://www.4chan-x.net/captchas.html', + target: '_blank', + textContent: '[complain]' + }); + $.add(errmsg, [$.tn(' '), link]); + } + } + }, + addLabels: function() { + var checkbox, i, imageSelect, label, labels; + imageSelect = $('.fbc-payload-imageselect'); + labels = (function() { + var j, len, ref, results; + ref = this.images; + results = []; + for (i = j = 0, len = ref.length; j < len; i = ++j) { + checkbox = ref[i]; + checkbox.id = "checkbox-" + i; + label = $.el('label', { + htmlFor: checkbox.id + }); + label.dataset.row = Math.floor(i / 3); + label.dataset.col = i % 3; + $.after(checkbox, label); + results.push(label); + } + return results; + }).call(this); + return this.addTooltips(labels); + }, + addTooltips: function(nodes) { + var i, j, len, node; + for (i = j = 0, len = nodes.length; j < len; i = ++j) { + node = nodes[i]; + node.title = this.imageKeys[i] + " or " + (this.imageKeys[i + 9][0].toUpperCase()) + this.imageKeys[i + 9].slice(1); + } + }, + addTooltips16: function(nodes) { + var i, j, key, len, node, ref; + ref = this.imageKeys16; + for (i = j = 0, len = ref.length; j < len; i = ++j) { + key = ref[i]; + if (i % 4 < this.width && (node = nodes[nodes.length - (4 - Math.floor(i / 4)) * this.width + (i % 4)])) { + node.title = "" + (key[0].toUpperCase()) + key.slice(1); + } + } + }, + checkForm: function(e) { + var checkbox, j, len, n, ref; + n = 0; + ref = this.images; + for (j = 0, len = ref.length; j < len; j++) { + checkbox = ref[j]; + if (checkbox.checked) { + n++; + } + } + if (n === 0) { + return e.preventDefault(); + } + }, + keybinds: function(e) { + var dx, i, img, key, last, n, reload, verify, w, x; + if (!(this.images && doc.contains(this.images[0]))) { + return; + } + n = this.images.length; + w = this.width; + last = n + w - 1; + reload = $('#recaptcha-reload-button, .fbc-button-reload'); + verify = $('#recaptcha-verify-button, .fbc-button-verify > input'); + x = this.images.indexOf(d.activeElement); + if (x < 0) { + x = d.activeElement === verify ? last : n; + } + key = Keybinds.keyCode(e); + if (!this.noscript && key === 'Space' && x < n) { + this.images[x].click(); + } else if (n === 9 && (i = this.imageKeys.indexOf(key)) >= 0) { + this.images[i % 9].click(); + verify.focus(); + } else if (n !== 9 && (i = this.imageKeys16.indexOf(key)) >= 0 && i % 4 < w && (img = this.images[n - (4 - Math.floor(i / 4)) * w + (i % 4)])) { + img.click(); + verify.focus(); + } else if (dx = { + 'Up': n, + 'Down': w, + 'Left': last, + 'Right': 1 + }[key]) { + x = (x + dx) % (n + w); + if ((n < x && x < last)) { + x = dx === last ? n : last; + } + (this.images[x] || (x === n ? reload : void 0) || (x === last ? verify : void 0)).focus(); + } else { + return; + } + e.preventDefault(); + return e.stopPropagation(); + } + }; + +}).call(this); + +(function() { + Captcha.replace = { + init: function() { + if (!(d.cookie.indexOf('pass_enabled=1') < 0)) { + return; + } + if (location.hostname === 'sys.4chan.org' && /[?&]altc\b/.test(location.search) && Main.jsEnabled) { + $.onExists(doc, 'script[src="//www.google.com/recaptcha/api/js/recaptcha_ajax.js"]', function() { + $.global(function() { + return window.el.onload = null; + }); + return Captcha.v1.create(); + }); + return; + } + if (((Conf['Use Recaptcha v1'] && location.hostname === 'boards.4chan.org') || (Conf['Use Recaptcha v1 in Reports'] && location.hostname === 'sys.4chan.org')) && Main.jsEnabled) { + $.ready(Captcha.replace.v1); + return; + } + if (Conf['Force Noscript Captcha'] && Main.jsEnabled) { + $.ready(Captcha.replace.noscript); + return; + } + if (Conf['captchaLanguage'].trim() || Conf['Captcha Fixes']) { + if (location.hostname === 'boards.4chan.org') { + return $.onExists(doc, '#captchaFormPart', function(node) { + return $.onExists(node, 'iframe', Captcha.replace.iframe); + }); + } else { + return $.onExists(doc, 'iframe', Captcha.replace.iframe); + } + } + }, + noscript: function() { + var insert, noscript, original, span, toggle; + if (!((original = $('#g-recaptcha, #captchaContainerAlt')) && (noscript = $('noscript')))) { + return; + } + span = $.el('span', { + id: 'captcha-forced-noscript' + }); + $.replace(noscript, span); + $.rm(original); + insert = function() { + span.innerHTML = noscript.textContent; + return Captcha.replace.iframe($('iframe', span)); + }; + if ((toggle = $('#togglePostFormLink a, #form-link'))) { + return $.on(toggle, 'click', insert); + } else { + return insert(); + } + }, + v1: function() { + var form, link; + if (!$.id('g-recaptcha')) { + return; + } + Captcha.v1.replace(); + if ((link = $.id('form-link'))) { + return $.on(link, 'click', function() { + return Captcha.v1.create(); + }); + } else if (location.hostname === 'boards.4chan.org') { + form = $.id('postForm'); + return form.addEventListener('focus', (function() { + return Captcha.v1.create(); + }), true); + } else { + return Captcha.v1.create(); + } + }, + iframe: function(iframe) { + var lang, src; + if ((lang = Conf['captchaLanguage'].trim())) { + src = /[?&]hl=/.test(iframe.src) ? iframe.src.replace(/([?&]hl=)[^&]*/, '$1' + encodeURIComponent(lang)) : iframe.src + ("&hl=" + (encodeURIComponent(lang))); + if (iframe.src !== src) { + iframe.src = src; + } + } + return Captcha.replace.autocopy(iframe); + }, + autocopy: function(iframe) { + if (!(Conf['Captcha Fixes'] && /^https:\/\/www\.google\.com\/recaptcha\/api\/fallback\?/.test(iframe.src))) { + return; + } + return new Connection(iframe, 'https://www.google.com', { + working: function() { + var ref, ref1; + if ((ref = $.id('qr')) != null ? ref.contains(iframe) : void 0) { + return (ref1 = $('#qr .captcha-container textarea')) != null ? ref1.parentNode.hidden = true : void 0; + } + }, + token: function(token) { + var node, textarea; + node = iframe; + while ((node = node.parentNode)) { + if ((textarea = $('textarea', node))) { + break; + } + } + textarea.value = token; + return $.event('input', null, textarea); + } + }); + } + }; + +}).call(this); + +(function() { + Captcha.v1 = { + blank: "data:image/svg+xml,", + init: function() { + var imgContainer, input; + if (d.cookie.indexOf('pass_enabled=1') >= 0) { + return; + } + if (!(this.isEnabled = !!$('#g-recaptcha, #captchaContainerAlt'))) { + return; + } + imgContainer = $.el('div', { + className: 'captcha-img', + title: 'Reload reCAPTCHA' + }); + $.extend(imgContainer, { + innerHTML: "" + }); + input = $.el('input', { + className: 'captcha-input field', + title: 'Verification', + autocomplete: 'off', + spellcheck: false + }); + this.nodes = { + img: imgContainer.firstChild, + input: input + }; + $.on(input, 'blur', QR.focusout); + $.on(input, 'focus', QR.focusin); + $.on(input, 'keydown', QR.captcha.keydown.bind(QR.captcha)); + $.on(this.nodes.img.parentNode, 'click', QR.captcha.reload.bind(QR.captcha)); + $.addClass(QR.nodes.el, 'has-captcha', 'captcha-v1'); + $.after(QR.nodes.com.parentNode, [imgContainer, 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.replace(); + this.beforeSetup(); + if (Conf['Auto-load captcha']) { + this.setup(); + } + new MutationObserver(this.afterSetup).observe($.id('captchaContainerAlt'), { + childList: true + }); + return this.afterSetup(); + }, + replace: function() { + var container, old; + if (this.script) { + return; + } + if (!(this.script = $('script[src="//www.google.com/recaptcha/api/js/recaptcha_ajax.js"]', d.head))) { + this.script = $.el('script', { + src: '//www.google.com/recaptcha/api/js/recaptcha_ajax.js' + }); + $.add(d.head, this.script); + } + if (old = $.id('g-recaptcha')) { + container = $.el('div', { + id: 'captchaContainerAlt' + }); + return $.replace(old, container); + } + }, + create: function() { + var cont, lang; + cont = $.id('captchaContainerAlt'); + if (this.occupied) { + return; + } + this.occupied = true; + if ((lang = Conf['captchaLanguage'].trim())) { + cont.dataset.lang = lang; + } + $.onExists(cont, '#recaptcha_image', function(image) { + return $.on(image, 'click', function() { + if ($.id('recaptcha_challenge_image')) { + return $.global(function() { + return window.Recaptcha.reload(); + }); + } + }); + }); + $.onExists(cont, '#recaptcha_response_field', function(field) { + $.on(field, 'keydown', function(e) { + if (e.keyCode === 8 && !field.value) { + return $.global(function() { + return window.Recaptcha.reload(); + }); + } + }); + if (location.hostname === 'sys.4chan.org') { + return field.focus(); + } + }); + return $.global(function() { + var container, options, script; + container = document.getElementById('captchaContainerAlt'); + options = { + theme: 'clean', + tabindex: { + "boards.4chan.org": 5 + }[location.hostname], + lang: container.dataset.lang + }; + if (window.Recaptcha) { + return window.Recaptcha.create('6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc', container, options); + } else { + script = document.head.querySelector('script[src="//www.google.com/recaptcha/api/js/recaptcha_ajax.js"]'); + return script.addEventListener('load', function() { + return window.Recaptcha.create('6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc', container, options); + }, false); + } + }); + }, + cb: { + focus: function() { + return QR.captcha.setup(false, true); + } + }, + beforeSetup: function() { + var img, input, ref; + ref = this.nodes, img = ref.img, input = ref.input; + img.parentNode.hidden = true; + img.src = this.blank; + 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 && (force || this.needed()))) { + return; + } + this.create(); + if (focus) { + $.addClass(QR.nodes.el, 'focus'); + return this.nodes.input.focus(); + } + }, + afterSetup: function() { + var challenge, img, input, ref, setLifetime; + if (!(challenge = $.id('recaptcha_challenge_field_holder'))) { + return; + } + if (challenge === QR.captcha.nodes.challenge) { + return; + } + setLifetime = function(e) { + return QR.captcha.lifetime = e.detail; + }; + $.on(window, 'captcha:timeout', setLifetime); + $.global(function() { + return window.dispatchEvent(new CustomEvent('captcha:timeout', { + detail: window.RecaptchaState.timeout + })); + }); + $.off(window, 'captcha:timeout', setLifetime); + ref = QR.captcha.nodes, img = ref.img, input = ref.input; + img.parentNode.hidden = false; + input.placeholder = 'Verification'; + QR.captcha.count(); + $.off(input, 'focus click', QR.captcha.cb.focus); + QR.captcha.nodes.challenge = challenge; + new MutationObserver(QR.captcha.load.bind(QR.captcha)).observe(challenge, { + childList: true, + subtree: true, + attributes: true + }); + QR.captcha.load(); + if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) { + QR.nodes.el.style.top = null; + return QR.nodes.el.style.bottom = '0px'; + } + }, + destroy: function() { + if (!this.script) { + return; + } + $.global(function() { + return window.Recaptcha.destroy(); + }); + delete this.occupied; + if (this.nodes) { + return this.beforeSetup(); + } + }, + sync: function(captchas) { + if (captchas == null) { + captchas = []; + } + QR.captcha.captchas = captchas; + return QR.captcha.count(); + }, + getOne: function() { + var captcha, challenge, response, timeout; + this.clear(); + if (captcha = this.captchas.shift()) { + this.count(); + $.set('captchas', this.captchas); + return captcha; + } else { + challenge = this.nodes.img.alt; + timeout = this.timeout; + if (/\S/.test(response = this.nodes.input.value)) { + this.destroy(); + return { + challenge: challenge, + response: response, + timeout: timeout + }; + } else { + return null; + } + } + }, + save: function() { + var response; + if (!/\S/.test(response = this.nodes.input.value)) { + return; + } + this.nodes.input.value = ''; + this.captchas.push({ + challenge: this.nodes.img.alt, + response: response, + timeout: this.timeout + }); + this.captchas.sort(function(a, b) { + return a.timeout - b.timeout; + }); + this.count(); + this.destroy(); + this.setup(false, true); + return $.set('captchas', this.captchas); + }, + clear: function() { + var captcha, i, j, len, now, ref; + if (!this.captchas.length) { + return; + } + $.forceSync('captchas'); + now = Date.now(); + ref = this.captchas; + for (i = j = 0, len = ref.length; j < len; i = ++j) { + captcha = ref[i]; + if (captcha.timeout > now) { + break; + } + } + if (!i) { + return; + } + this.captchas = this.captchas.slice(i); + this.count(); + return $.set('captchas', this.captchas); + }, + load: function() { + var challenge, challenge_image; + if ($('#captchaContainerAlt[class~="recaptcha_is_showing_audio"]')) { + this.nodes.img.src = this.blank; + return; + } + if (!this.nodes.challenge.firstChild) { + return; + } + if (!(challenge_image = $.id('recaptcha_challenge_image'))) { + return; + } + this.timeout = Date.now() + this.lifetime * $.SECOND - $.MINUTE; + challenge = this.nodes.challenge.firstChild.value; + this.nodes.img.alt = challenge; + this.nodes.img.src = challenge_image.src; + this.nodes.input.value = ''; + return this.clear(); + }, + 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.timer); + if (count) { + return this.timer = setTimeout(this.clear.bind(this), this.captchas[0].timeout - Date.now()); + } + }, + reload: function(focus) { + $.global(function() { + if (window.Recaptcha.type === 'image') { + window.Recaptcha.reload(); + } else { + window.Recaptcha.switch_type('image'); + } + return window.Recaptcha.should_focus = false; + }); + if (focus) { + return this.nodes.input.focus(); + } + }, + keydown: function(e) { + if (e.keyCode === 8 && !this.nodes.input.value) { + this.reload(); + } else if (e.keyCode === 13 && e.shiftKey) { + this.save(); + } else { + return; + } + return e.preventDefault(); + } + }; + +}).call(this); + +(function() { + Captcha.v2 = { + lifetime: 2 * $.MINUTE, + init: function() { + var counter, root; + if (d.cookie.indexOf('pass_enabled=1') >= 0) { + return; + } + if (!(this.isEnabled = !!$('#g-recaptcha, #captchaContainerAlt, #captcha-forced-noscript'))) { + return; + } + if ((this.noscript = Conf['Force Noscript Captcha'] || !Main.jsEnabled)) { + $.addClass(QR.nodes.el, 'noscript-captcha'); + } + 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: "
              " + }); + counter = $('.captcha-counter > a', root); + this.nodes = { + root: root, + counter: counter + }; + this.count(); + $.addClass(QR.nodes.el, 'has-captcha', 'captcha-v2'); + $.after(QR.nodes.com.parentNode, root); + $.on(counter, 'click', this.toggle.bind(this)); + $.on(counter, 'keydown', (function(_this) { + return function(e) { + if (Keybinds.keyCode(e) !== 'Space') { + return; + } + _this.toggle(); + e.preventDefault(); + return e.stopPropagation(); + }; + })(this)); + return $.on(window, 'captcha:success', (function(_this) { + return function() { + return $.queueTask(function() { + return _this.save(false); + }); + }; + })(this)); + }, + timeouts: {}, + postsCount: 0, + noscriptURL: function() { + var lang, url; + url = 'https://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc'; + if ((lang = Conf['captchaLanguage'].trim())) { + url += "&hl=" + (encodeURIComponent(lang)); + } + return url; + }, + 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) { + if (!(this.isEnabled && (this.needed() || force))) { + return; + } + if (focus) { + $.addClass(QR.nodes.el, 'focus'); + this.nodes.counter.focus(); + } + if (this.timeouts.destroy) { + clearTimeout(this.timeouts.destroy); + delete this.timeouts.destroy; + return this.reload(); + } + if (this.nodes.container) { + $.queueTask((function(_this) { + return function() { + var iframe; + if (_this.nodes.container && d.activeElement === _this.nodes.counter && (iframe = $('iframe', _this.nodes.container))) { + iframe.focus(); + return QR.focus(); + } + }; + })(this)); + 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 + }); + if (this.noscript) { + return this.setupNoscript(); + } else { + return this.setupJS(); + } + }, + setupNoscript: function() { + var div, iframe, textarea; + iframe = $.el('iframe', { + id: 'qr-captcha-iframe', + src: this.noscriptURL() + }); + div = $.el('div'); + textarea = $.el('textarea'); + $.add(div, textarea); + return $.add(this.nodes.container, [iframe, div]); + }, + setupJS: function() { + return $.global(function() { + var cbNative, render; + render = function() { + var classList, container; + classList = document.documentElement.classList; + container = document.querySelector('#qr .captcha-container'); + return container.dataset.widgetID = window.grecaptcha.render(container, { + sitekey: '6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc', + theme: classList.contains('tomorrow') || classList.contains('dark-captcha') ? 'dark' : 'light', + callback: function(response) { + return window.dispatchEvent(new CustomEvent('captcha:success', { + detail: response + })); + } + }); + }; + if (window.grecaptcha) { + return render(); + } else { + cbNative = window.onRecaptchaLoaded; + return window.onRecaptchaLoaded = function() { + render(); + return cbNative(); + }; + } + }); + }, + afterSetup: function(mutations) { + var iframe, j, k, len, len1, mutation, node, ref, textarea; + for (j = 0, len = mutations.length; j < len; j++) { + mutation = mutations[j]; + ref = mutation.addedNodes; + for (k = 0, len1 = ref.length; k < len1; k++) { + node = ref[k]; + 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) { + if (!doc.contains(iframe)) { + return; + } + Captcha.replace.iframe(iframe); + $.addClass(QR.nodes.el, 'captcha-open'); + this.fixQRPosition(); + $.on(iframe, 'load', this.fixQRPosition); + if (d.activeElement === this.nodes.counter) { + iframe.focus(); + } + return $.global(function() { + var f; + f = document.querySelector('#qr iframe'); + return f.focus = f.blur = function() {}; + }); + }, + fixQRPosition: function() { + if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) { + QR.nodes.el.style.top = null; + return QR.nodes.el.style.bottom = '0px'; + } + }, + setupTextArea: function(textarea) { + return $.one(textarea, 'input', (function(_this) { + return function() { + return _this.save(true); + }; + })(this)); + }, + destroy: function() { + var garbage, i, ins, node, ref; + if (!this.isEnabled) { + return; + } + delete this.timeouts.destroy; + $.rmClass(QR.nodes.el, 'captcha-open'); + if (this.nodes.container) { + $.rm(this.nodes.container); + } + delete this.nodes.container; + garbage = $.X('//iframe[starts-with(@src, "https://www.google.com/recaptcha/api2/frame")]/ancestor-or-self::*[parent::body]'); + i = 0; + while (node = garbage.snapshotItem(i++)) { + if (((ref = (ins = node.nextSibling)) != null ? ref.nodeName : void 0) === 'INS') { + $.rm(ins); + } + $.rm(node); + } + }, + 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; + } else { + return null; + } + }, + save: function(pasted, token) { + var base, focus, ref; + $.forceSync('captchas'); + this.captchas.push({ + response: token || $('textarea', this.nodes.container).value, + timeout: Date.now() + this.lifetime + }); + this.captchas.sort(function(a, b) { + return a.timeout - b.timeout; + }); + $.set('captchas', this.captchas); + this.count(); + focus = ((ref = d.activeElement) != null ? ref.nodeName : void 0) === 'IFRAME' && /https?:\/\/www\.google\.com\/recaptcha\//.test(d.activeElement.src); + if (this.needed()) { + if (focus) { + if (QR.cooldown.auto || Conf['Post on Captcha Completion']) { + this.nodes.counter.focus(); + } 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); + } + } + if (focus) { + QR.nodes.status.focus(); + } + } + if (Conf['Post on Captcha Completion'] && !QR.cooldown.auto) { + return QR.submit(); + } + }, + clear: function() { + var captcha, i, j, len, now, ref; + if (!this.captchas.length) { + return; + } + $.forceSync('captchas'); + now = Date.now(); + ref = this.captchas; + for (i = j = 0, len = ref.length; j < len; i = ++j) { + 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(d.activeElement === QR.nodes.status); + }, + 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() { + if ($('iframe[src^="https://www.google.com/recaptcha/api/fallback?"]', this.nodes.container)) { + this.destroy(); + return this.setup(false, true); + } else { + return $.global(function() { + var container; + container = document.querySelector('#qr .captcha-container'); + return window.grecaptcha.reset(container.dataset.widgetID); + }); + } + } + }; + +}).call(this); + +PassLink = (function() { + var PassLink; + + PassLink = { + init: function() { + if (!Conf['Pass Link']) { + return; + } + return Main.ready(this.ready); + }, + ready: function() { + var passLink, styleSelector; + if (!(styleSelector = $.id('styleSelector'))) { + return; + } + passLink = $.el('span', { + className: 'brackets-wrap pass-link-container' + }); + $.extend(passLink, { + innerHTML: "4chan Pass" + }); + $.on(passLink.firstElementChild, 'click', function() { + return window.open('//sys.4chan.org/auth', Date.now(), 'width=500,height=280,toolbar=0'); + }); + return $.before(styleSelector.previousSibling, [passLink, $.tn('\u00A0\u00A0')]); + } + }; + + return PassLink; + +}).call(this); + +PostSuccessful = (function() { + var PostSuccessful; + + PostSuccessful = { + init: function() { + if (!Conf['Remember Your Posts']) { + return; + } + return $.ready(this.ready); + }, + ready: function() { + var _, db, postID, ref, threadID; + if (d.title !== 'Post successful!') { + return; + } + ref = $('h1').nextSibling.textContent.match(/thread:(\d+),no:(\d+)/), _ = ref[0], threadID = ref[1], postID = ref[2]; + postID = +postID; + threadID = +threadID || postID; + db = new DataBoard('yourPosts'); + return db.set({ + boardID: g.BOARD.ID, + threadID: threadID, + postID: postID, + val: true + }); + } + }; + + return PostSuccessful; + +}).call(this); + +QR = (function() { + var QR, + indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, + slice = [].slice; + + QR = { + mimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'application/pdf', 'application/vnd.adobe.flash.movie', 'application/x-shockwave-flash', 'video/webm'], + validExtension: /\.(jpe?g|png|gif|pdf|swf|webm)$/i, + typeFromExtension: { + 'jpg': 'image/jpeg', + 'jpeg': 'image/jpeg', + 'png': 'image/png', + 'gif': 'image/gif', + 'pdf': 'application/pdf', + 'swf': 'application/vnd.adobe.flash.movie', + 'webm': 'video/webm' + }, + extensionFromType: { + 'image/jpeg': 'jpg', + 'image/png': 'png', + 'image/gif': 'gif', + 'application/pdf': 'pdf', + 'application/vnd.adobe.flash.movie': 'swf', + 'application/x-shockwave-flash': 'swf', + 'video/webm': 'webm' + }, + init: function() { + var sc, version; + if (!Conf['Quick Reply']) { + return; + } + this.posts = []; + if (g.VIEW === 'archive') { + return; + } + version = Conf['Use Recaptcha v1'] && Main.jsEnabled ? 'v1' : 'v2'; + this.captcha = Captcha[version]; + $.on(d, '4chanXInitFinished', this.initReady); + Callbacks.Post.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(); + } + }); + return Header.addShortcut(sc); + } + }, + initReady: function() { + var link, linkBot, navLinksBot, origToggle; + $.off(d, '4chanXInitFinished', this.initReady); + QR.postingIsEnabled = !!$.id('postForm'); + if (!QR.postingIsEnabled) { + return; + } + link = $.el('h1', { + className: "qr-link-container" + }); + $.extend(link, { + innerHTML: "" + ((g.VIEW === "thread") ? "Reply to Thread" : "Start a Thread") + "" + }); + 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: "Reply to Thread" + }); + $.on(linkBot.firstElementChild, 'click', function() { + QR.open(); + return QR.nodes.com.focus(); + }); + if ((navLinksBot = $('.navLinksBot'))) { + $.prepend(navLinksBot, linkBot); + } + } + origToggle = $.id('togglePostFormLink'); + $.before(origToggle, link); + origToggle.firstElementChild.textContent = 'Original Form'; + $.on(d, 'QRGetFile', QR.getFile); + $.on(d, 'QRSetFile', QR.setFile); + $.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 j, len, post, 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 (j = 0, len = ref.length; j < len; j++) { + post = ref[j]; + post["delete"](); + } + QR.cooldown.auto = false; + QR.status(); + return QR.captcha.destroy(); + }, + focus: function() { + return $.queueTask(function() { + if (!QR.inBubble()) { + QR.hasFocus = d.activeElement && QR.nodes.el.contains(d.activeElement); + return QR.nodes.el.classList.toggle('focus', QR.hasFocus); + } + }); + }, + inBubble: function() { + var bubbles, ref; + bubbles = $$('iframe[src^="https://www.google.com/recaptcha/api2/frame"]'); + return (ref = d.activeElement, indexOf.call(bubbles, ref) >= 0) || bubbles.some(function(el) { + return getComputedStyle(el).visibility !== 'hidden' && el.getBoundingClientRect().bottom > 0; + }); + }, + 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(); + } + }, + toggleSJIS: function(e) { + e.preventDefault(); + Conf['sjisPreview'] = !Conf['sjisPreview']; + $.set('sjisPreview', Conf['sjisPreview']); + return QR.nodes.el.classList.toggle('sjis-preview', Conf['sjisPreview']); + }, + texPreviewShow: function() { + if ($.hasClass(QR.nodes.el, 'tex-preview')) { + return QR.texPreviewHide(); + } + $.addClass(QR.nodes.el, 'tex-preview'); + QR.nodes.texPreview.textContent = QR.nodes.com.value; + return $.event('mathjax', null, QR.nodes.texPreview); + }, + texPreviewHide: function() { + return $.rmClass(QR.nodes.el, 'tex-preview'); + }, + setCustomCooldown: function(enabled) { + Conf['customCooldownEnabled'] = enabled; + QR.cooldown.customCooldown = enabled; + return QR.nodes.customCooldown.classList.toggle('disabled', !enabled); + }, + toggleCustomCooldown: function() { + var enabled; + enabled = $.hasClass(this, 'disabled'); + QR.setCustomCooldown(enabled); + return $.set('customCooldownEnabled', enabled); + }, + error: function(err, focusOverride) { + var el, notice, notif; + QR.open(); + if (typeof err === 'string') { + el = $.tn(err); + } else { + el = err; + el.removeAttribute('style'); + } + notice = new Notice('warning', el); + QR.notifications.push(notice); + if (!Header.areNotificationsEnabled) { + if (d.hidden && !QR.cooldown.auto) { + return alert(el.textContent); + } + } else if (d.hidden || !(focusOverride || d.hasFocus())) { + try { + notif = new Notification(el.textContent, { + body: el.textContent, + icon: Favicon.logo + }); + notif.onclick = function() { + return $.global(function() { + return window.focus(); + }); + }; + if ($.engine !== 'gecko') { + notif.onclose = function() { + return notice.close(); + }; + return notif.onshow = function() { + return setTimeout(function() { + notif.onclose = null; + return notif.close(); + }, 7 * $.SECOND); + }; + } + } catch (_error) {} + } + }, + notifications: [], + cleanNotifications: function() { + var j, len, notification, ref; + ref = QR.notifications; + for (j = 0, len = ref.length; j < len; j++) { + notification = ref[j]; + 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; + }, + openPost: function() { + var index; + 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'); + return QR.cooldown.auto = true; + } + }, + quote: function(e) { + var ancestor, caretPos, com, frag, insideCode, j, k, l, len, len1, len2, len3, len4, len5, n, node, o, post, q, range, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, sel, text, thread; + 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 (j = 0, len = ref.length; j < len; j++) { + node = ref[j]; + $.replace(node, $.tn('\n')); + } + ref1 = $$('br', frag); + for (k = 0, len1 = ref1.length; k < len1; k++) { + node = ref1[k]; + if (node !== frag.lastChild) { + $.replace(node, $.tn('\n>')); + } + } + ref2 = $$('s, .removed-spoiler', frag); + for (l = 0, len2 = ref2.length; l < len2; l++) { + node = ref2[l]; + $.replace(node, [$.tn('[spoiler]')].concat(slice.call(node.childNodes), [$.tn('[/spoiler]')])); + } + ref3 = $$('.prettyprint', frag); + for (n = 0, len3 = ref3.length; n < len3; n++) { + node = ref3[n]; + $.replace(node, [$.tn('[code]')].concat(slice.call(node.childNodes), [$.tn('[/code]')])); + } + ref4 = $$('.linkify[data-original]', frag); + for (o = 0, len4 = ref4.length; o < len4; o++) { + node = ref4[o]; + $.replace(node, $.tn(node.dataset.original)); + } + ref5 = $$('.embedder', frag); + for (q = 0, len5 = ref5.length; q < len5; q++) { + node = ref5[q]; + if (((ref6 = node.previousSibling) != null ? ref6.nodeValue : void 0) === ' ') { + $.rm(node.previousSibling); + } + $.rm(node); + } + text += ">" + (frag.textContent.trim()) + "\n"; + } + QR.openPost(); + 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.value.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '_').length; + counter.textContent = count; + counter.hidden = count < QR.max_comment / 2; + return (count > QR.max_comment ? $.addClass : $.rmClass)(counter, 'warning'); + }, + getFile: function() { + var ref; + return $.event('QRFile', (ref = QR.selected) != null ? ref.file : void 0); + }, + setFile: function(e) { + var file, name, ref, source; + ref = e.detail, file = ref.file, name = ref.name, source = ref.source; + if (name != null) { + file.name = name; + } + if (source != null) { + file.source = source; + } + QR.open(); + return QR.handleFiles([file]); + }, + 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, j, len, ref; + if (!e.clipboardData.items) { + return; + } + files = []; + ref = e.clipboardData.items; + for (j = 0, len = ref.length; j < len; j++) { + item = ref[j]; + 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'); + }, + pasteFF: function() { + var arr, blob, bstr, i, images, img, j, k, len, m, pasteArea, ref, src; + pasteArea = QR.nodes.pasteArea; + if (!pasteArea.childNodes.length) { + return; + } + images = $$('img', pasteArea); + $.rmAll(pasteArea); + for (j = 0, len = images.length; j < len; j++) { + img = images[j]; + src = img.src; + if (m = src.match(/data:(image\/(\w+));base64,(.+)/)) { + bstr = atob(m[3]); + arr = new Uint8Array(bstr.length); + for (i = k = 0, ref = bstr.length; 0 <= ref ? k < ref : k > ref; i = 0 <= ref ? ++k : --k) { + arr[i] = bstr.charCodeAt(i); + } + blob = new Blob([arr], { + type: m[1] + }); + blob.name = "file." + m[2]; + QR.handleFiles([blob]); + } else if (/^https?:\/\//.test(src)) { + QR.handleUrl(src); + } + } + }, + handleUrl: function(urlDefault) { + var url; + url = prompt('Enter a URL:', urlDefault); + if (url === null) { + return; + } + QR.nodes.fileButton.focus(); + return CrossOrigin.file(url, function(blob) { + if (blob && !/^text\//.test(blob.type)) { + return QR.handleFiles([blob]); + } else { + return QR.error("Can't load file."); + } + }); + }, + handleFiles: function(files) { + var file, j, len; + if (this !== QR) { + files = slice.call(this.files); + this.value = null; + } + if (!files.length) { + return; + } + QR.cleanNotifications(); + for (j = 0, len = files.length; j < len; j++) { + file = files[j]; + QR.handleFile(file, files.length); + } + if (files.length !== 1) { + $.addClass(QR.nodes.el, 'dump'); + } + if (d.activeElement === QR.nodes.fileButton && $.hasClass(QR.nodes.fileSubmit, 'has-file')) { + return QR.nodes.filename.focus(); + } + }, + handleFile: function(file, nfiles) { + var isText, post; + isText = /^text\//.test(file.type); + if (nfiles === 1) { + post = QR.selected; + } else { + post = QR.posts[QR.posts.length - 1]; + if ((isText ? post.com || post.pasting : post.file)) { + post = new QR.post(); + } + } + return post[isText ? 'pasteText' : 'setFile'](file); + }, + openFileInput: function() { + if (QR.nodes.fileButton.disabled) { + return; + } + QR.nodes.fileInput.click(); + return QR.nodes.fileButton.focus(); + }, + generatePostableThreadsList: function() { + var j, len, list, options, ref, thread, val; + if (!QR.nodes) { + return; + } + list = QR.nodes.thread; + options = [list.firstElementChild]; + ref = g.BOARD.threads.keys; + for (j = 0, len = ref.length; j < len; j++) { + thread = ref[j]; + options.push($.el('option', { + value: thread, + textContent: "Thread " + 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, ref, rules, save, scriptData, setNode; + QR.nodes = nodes = { + el: dialog = UI.dialog('qr', 'top: 50px; right: 0px;', { + innerHTML: "
              ×
              No selected file
              " + }) + }; + setNode = function(name, query) { + return nodes[name] = $(query, dialog); + }; + setNode('move', '.move'); + setNode('autohide', '#autohide'); + setNode('close', '.close'); + setNode('thread', 'select'); + setNode('form', 'form'); + setNode('sjisToggle', '#sjis-toggle'); + setNode('texButton', '#tex-preview-button'); + setNode('name', '[data-name=name]'); + setNode('email', '[data-name=email]'); + setNode('sub', '[data-name=sub]'); + setNode('com', '[data-name=com]'); + setNode('charCount', '#char-count'); + setNode('texPreview', '#tex-preview'); + setNode('dumpList', '#dump-list'); + setNode('addPost', '#add-post'); + setNode('oekaki', '.oekaki'); + setNode('drawButton', '#qr-draw-button'); + setNode('fileSubmit', '#file-n-submit'); + setNode('fileButton', '#qr-file-button'); + setNode('noFile', '#qr-no-file'); + setNode('filename', '#qr-filename'); + setNode('spoiler', '#qr-file-spoiler'); + setNode('oekakiButton', '#qr-oekaki-button'); + setNode('fileRM', '#qr-filerm'); + setNode('urlButton', '#url-button'); + setNode('pasteArea', '#paste-area'); + setNode('customCooldown', '#custom-cooldown-button'); + setNode('dumpButton', '#dump-button'); + setNode('status', '[type=submit]'); + setNode('flashTag', '[name=filetag]'); + 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; + scriptData = Get.scriptData(); + QR.max_size = (m = scriptData.match(/\bmaxFilesize *= *(\d+)\b/)) ? +m[1] : 4194304; + QR.max_size_video = (m = scriptData.match(/\bmaxWebmFilesize *= *(\d+)\b/)) ? +m[1] : QR.max_size; + QR.max_comment = (m = scriptData.match(/\bcomlen *= *(\d+)\b/)) ? +m[1] : 2000; + 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'); + } + if (g.BOARD.ID === 'jp' && Conf['sjisPreview']) { + $.addClass(QR.nodes.el, 'sjis-preview'); + } + if (parseInt(Conf['customCooldown'], 10) > 0) { + $.addClass(QR.nodes.fileSubmit, 'custom-cooldown'); + $.get('customCooldownEnabled', Conf['customCooldownEnabled'], function(arg) { + var customCooldownEnabled; + customCooldownEnabled = arg.customCooldownEnabled; + QR.setCustomCooldown(customCooldownEnabled); + return $.sync('customCooldownEnabled', QR.setCustomCooldown); + }); + } + $.on(nodes.autohide, 'change', QR.toggleHide); + $.on(nodes.close, 'click', QR.close); + $.on(nodes.form, 'submit', QR.submit); + $.on(nodes.sjisToggle, 'click', QR.toggleSJIS); + $.on(nodes.texButton, 'mousedown', QR.texPreviewShow); + $.on(nodes.texButton, 'mouseup', QR.texPreviewHide); + $.on(nodes.addPost, 'click', function() { + return new QR.post(true); + }); + $.on(nodes.drawButton, 'click', QR.oekaki.draw); + $.on(nodes.fileButton, 'click', QR.openFileInput); + $.on(nodes.noFile, 'click', QR.openFileInput); + $.on(nodes.filename, 'focus', function() { + return $.addClass(this.parentNode, 'focus'); + }); + $.on(nodes.filename, 'blur', function() { + return $.rmClass(this.parentNode, 'focus'); + }); + $.on(nodes.spoiler, 'change', function() { + return QR.selected.nodes.spoiler.click(); + }); + $.on(nodes.oekakiButton, 'click', QR.oekaki.button); + $.on(nodes.fileRM, 'click', function() { + return QR.selected.rmFile(); + }); + $.on(nodes.urlButton, 'click', function() { + return QR.handleUrl(''); + }); + $.on(nodes.customCooldown, 'click', QR.toggleCustomCooldown); + $.on(nodes.dumpButton, 'click', function() { + return nodes.el.classList.toggle('dump'); + }); + $.on(nodes.fileInput, 'change', QR.handleFiles); + window.addEventListener('focus', QR.focus, true); + window.addEventListener('blur', QR.focus, true); + $.on(d, 'click', QR.focus); + if ($.engine === 'gecko') { + nodes.pasteArea.hidden = false; + new MutationObserver(QR.pasteFF).observe(nodes.pasteArea, { + childList: true + }); + } + 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 ($.engine === 'gecko' && 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.load(); + new QR.post(true); + QR.status(); + QR.cooldown.setup(); + QR.captcha.init(); + $.add(d.body, dialog); + QR.captcha.setup(); + QR.oekaki.setup(); + return $.event('QRDialogCreation', null, dialog); + }, + submit: function(e) { + var captcha, cb, err, extra, filetag, formData, options, post, ref, 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(); + threadID = post.thread; + thread = g.BOARD.threads[threadID]; + if (g.BOARD.ID === 'f' && threadID === 'new') { + filetag = QR.nodes.flashTag.value; + } + if (threadID === 'new') { + threadID = null; + if (g.BOARD.ID === 'vg' && !post.sub) { + err = 'New threads require a subject.'; + } else if (!($.hasClass(d.body, 'text_only') || 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 comment or file.'; + } else if (post.file && thread.fileLimit) { + err = 'Max limit of image replies has been reached.'; + } + if (g.BOARD.ID === 'r9k' && !((ref = post.com) != null ? ref.match(/[a-z-]/i) : void 0)) { + err || (err = 'Original comment required.'); + } + if (QR.captcha.isEnabled && !err) { + captcha = QR.captcha.getOne(); + if (!captcha) { + err = 'No valid captcha.'; + QR.captcha.setup(!QR.cooldown.auto || d.activeElement === QR.nodes.status); + } + } + 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.getPassword() + }; + 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: "Connection error while posting. [More info]" + })); + } + }; + extra = { + form: $.formData(formData), + upCallbacks: { + onload: function() { + QR.req.isUploadFinished = true; + 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) { + if (response.challenge != null) { + extra.form.append('recaptcha_challenge_field', response.challenge); + extra.form.append('recaptcha_response_field', response.response); + } else { + extra.form.append('g-recaptcha-response', 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, err, h1, isReply, lastPostToThread, m, open, post, postID, postsCount, ref, ref1, ref2, req, resDoc, seconds, threadID; + 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 + "! ;_;
              Click here to see the reason." + } : { + innerHTML: "You were issued a warning on " + ($(".board", resDoc)).innerHTML + " as " + ($(".nameBlock", resDoc)).innerHTML + ".
              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 = $.el('span', { + innerHTML: "You mistyped the CAPTCHA, or the CAPTCHA malfunctioned [complain here]." + }); + } else if (/expired/i.test(err.textContent)) { + err = 'This CAPTCHA is no longer valid because it has expired.'; + } + QR.cooldown.auto = QR.captcha.isEnabled || err === 'Connection error with sys.4chan.org.'; + QR.cooldown.addDelay(post, 2); + } else if (err.textContent && (m = err.textContent.match(/(?:(\d+)\s+minutes?\s+)?(\d+)\s+second/i)) && !/duplicate|hour/i.test(err.textContent)) { + QR.cooldown.auto = !/have\s+been\s+muted/i.test(err.textContent); + seconds = 60 * (+(m[1] || 0)) + (+m[2]); + if (/muted/i.test(err.textContent)) { + QR.cooldown.addMute(seconds); + } else { + QR.cooldown.addDelay(post, seconds); + } + } else { + QR.cooldown.auto = false; + } + QR.captcha.setup(QR.cooldown.auto && ((ref1 = d.activeElement) === QR.nodes.status || ref1 === d.body)); + if (QR.captcha.isEnabled && !QR.captcha.captchas.length) { + 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)); + } + ref2 = h1.nextSibling.textContent.match(/thread:(\d+),no:(\d+)/), _ = ref2[0], threadID = ref2[1], postID = ref2[2]; + postID = +postID; + threadID = +threadID || postID; + isReply = threadID !== 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; + lastPostToThread = !((function() { + var j, len, p, ref3; + ref3 = QR.posts.slice(1); + for (j = 0, len = ref3.length; j < len; j++) { + p = ref3[j]; + if (p.thread === post.thread) { + return true; + } + } + })()); + if (!(Conf['Persistent QR'] || postsCount)) { + QR.close(); + } else { + post.rm(); + QR.captcha.setup(d.activeElement === QR.nodes.status); + } + QR.cooldown.add(threadID, postID); + URL = threadID === postID ? window.location.origin + "/" + g.BOARD + "/thread/" + threadID : g.VIEW === 'index' && lastPostToThread && Conf['Open Post in New Tab'] ? window.location.origin + "/" + g.BOARD + "/thread/" + threadID + "#p" + postID : void 0; + if (URL) { + open = Conf['Open Post in New Tab'] || postsCount ? function() { + return $.open(URL); + } : function() { + return window.location = URL; + }; + if (threadID === postID) { + QR.waitForThread(URL, open); + } else { + open(); + } + } + return QR.status(); + }, + waitForThread: function(url, cb) { + var attempts, check; + attempts = 0; + check = function() { + return $.ajax(url, { + onloadend: function() { + attempts++; + if (attempts >= 6 || this.status === 200) { + return cb(); + } else { + return setTimeout(check, attempts * $.SECOND); + } + } + }, { + type: 'HEAD' + }); + }; + return check(); + }, + 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(); + } + }; + + return QR; + +}).call(this); + +(function() { + QR.cooldown = { + seconds: 0, + delays: { + thread: 0, + reply: 0, + image: 0, + reply_intra: 0, + image_intra: 0, + deletion: 60, + thread_global: 300 + }, + init: function() { + if (!Conf['Quick Reply']) { + return; + } + this.data = Conf['cooldowns']; + return $.sync('cooldowns', this.sync); + }, + setup: function() { + var delay, m, ref, type; + if (m = Get.scriptData().match(/\bcooldowns *= *({[^}]+})/)) { + $.extend(QR.cooldown.delays, JSON.parse(m[1])); + } + QR.cooldown.maxDelay = 0; + ref = QR.cooldown.delays; + for (type in ref) { + delay = ref[type]; + if (type !== 'thread' && type !== 'thread_global') { + QR.cooldown.maxDelay = Math.max(QR.cooldown.maxDelay, delay); + } + } + QR.cooldown.isSetup = true; + return QR.cooldown.start(); + }, + start: function() { + var data; + data = QR.cooldown.data; + if (!(Conf['Cooldown'] && QR.cooldown.isSetup && !QR.cooldown.isCounting && Object.keys(data[g.BOARD.ID] || {}).length + Object.keys(data.global || {}).length > 0)) { + return; + } + QR.cooldown.isCounting = true; + return QR.cooldown.count(); + }, + sync: function(data) { + QR.cooldown.data = data || {}; + return QR.cooldown.start(); + }, + add: function(threadID, postID) { + var boardID, start; + if (!Conf['Cooldown']) { + return; + } + start = Date.now(); + boardID = g.BOARD.ID; + QR.cooldown.set(boardID, 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(g.BOARD.ID, Date.now(), cooldown); + return QR.cooldown.start(); + }, + addMute: function(delay) { + if (!Conf['Cooldown']) { + return; + } + QR.cooldown.set(g.BOARD.ID, Date.now(), { + type: 'mute', + delay: delay + }); + return QR.cooldown.start(); + }, + "delete": function(post) { + var base, cooldown, cooldowns, id, name; + if (!QR.cooldown.data) { + return; + } + $.forceSync('cooldowns'); + cooldowns = ((base = QR.cooldown.data)[name = post.board.ID] || (base[name] = {})); + for (id in cooldowns) { + cooldown = cooldowns[id]; + if ((cooldown.delay == null) && cooldown.threadID === post.thread.ID && cooldown.postID === post.ID) { + delete cooldowns[id]; + } + } + return QR.cooldown.save([post.board.ID]); + }, + secondsDeletion: function(post) { + var cooldown, cooldowns, seconds, start; + if (!(QR.cooldown.data && Conf['Cooldown'])) { + return 0; + } + cooldowns = QR.cooldown.data[post.board.ID] || {}; + for (start in cooldowns) { + cooldown = cooldowns[start]; + if ((cooldown.delay == null) && cooldown.threadID === post.thread.ID && cooldown.postID === post.ID) { + seconds = QR.cooldown.delays.deletion - Math.floor((Date.now() - start) / $.SECOND); + return Math.max(seconds, 0); + } + } + return 0; + }, + 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) { + var base, cooldowns; + $.forceSync('cooldowns'); + cooldowns = ((base = QR.cooldown.data)[scope] || (base[scope] = {})); + cooldowns[id] = value; + return $.set('cooldowns', QR.cooldown.data); + }, + save: function(scopes) { + var data, i, len, scope; + data = QR.cooldown.data; + for (i = 0, len = scopes.length; i < len; i++) { + scope = scopes[i]; + if (scope in data && !Object.keys(data[scope]).length) { + delete data[scope]; + } + } + return $.set('cooldowns', data); + }, + count: function() { + var base, cooldown, cooldowns, elapsed, i, len, maxDelay, nCooldowns, now, ref, ref1, save, scope, seconds, start, suffix, threadID, type, update; + $.forceSync('cooldowns'); + save = []; + nCooldowns = 0; + now = Date.now(); + ref = QR.cooldown.categorize(QR.posts[0]), type = ref.type, threadID = ref.threadID; + seconds = 0; + if (Conf['Cooldown']) { + ref1 = [g.BOARD.ID, 'global']; + for (i = 0, len = ref1.length; i < len; i++) { + scope = ref1[i]; + cooldowns = ((base = QR.cooldown.data)[scope] || (base[scope] = {})); + for (start in cooldowns) { + cooldown = cooldowns[start]; + start = +start; + elapsed = Math.floor((now - start) / $.SECOND); + if (elapsed < 0) { + delete cooldowns[start]; + save.push(scope); + continue; + } + if (cooldown.delay != null) { + if (cooldown.delay <= elapsed) { + delete cooldowns[start]; + save.push(scope); + } else if ((cooldown.type === type && cooldown.threadID === threadID) || cooldown.type === 'mute') { + 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 (QR.cooldown.customCooldown) { + maxDelay = Math.max(maxDelay, parseInt(Conf['customCooldown'], 10)); + } + if (maxDelay <= elapsed) { + delete cooldowns[start]; + save.push(scope); + 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 (QR.cooldown.customCooldown) { + seconds = Math.max(seconds, parseInt(Conf['customCooldown'], 10) - elapsed); + } + } + nCooldowns += Object.keys(cooldowns).length; + } + } + if (save.length) { + QR.cooldown.save(save); + } + if (nCooldowns) { + 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(); + } + } + }; + +}).call(this); + +(function() { + QR.oekaki = { + menu: { + init: function() { + var a, ref; + if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Menu'] && Conf['Edit Link'] && Conf['Quick Reply'])) { + return; + } + a = $.el('a', { + className: 'edit-link', + href: 'javascript:;', + textContent: 'Edit image' + }); + $.on(a, 'click', this.editFile); + return Menu.menu.addEntry({ + el: a, + order: 95, + open: function(post) { + var file; + QR.oekaki.menu.post = post; + file = post.file; + return QR.postingIsEnabled && !!file && (file.isImage || file.isVideo); + } + }); + }, + editFile: function() { + var currentTime, isVideo, post, ref; + post = QR.oekaki.menu.post; + QR.quote.call(post.nodes.post); + isVideo = post.file.isVideo; + currentTime = ((ref = post.file.fullImage) != null ? ref.currentTime : void 0) || 0; + return CrossOrigin.file(post.file.url, function(blob) { + var video; + if (!blob) { + return QR.error("Can't load file."); + } else if (isVideo) { + video = $.el('video'); + $.on(video, 'loadedmetadata', function() { + $.on(video, 'seeked', function() { + var canvas; + canvas = $.el('canvas', { + width: video.videoWidth, + height: video.videoHeight + }); + canvas.getContext('2d').drawImage(video, 0, 0); + return canvas.toBlob(function(snapshot) { + snapshot.name = post.file.name.replace(/\.\w+$/, '') + '.png'; + QR.handleFiles([snapshot]); + return QR.oekaki.edit(); + }); + }); + return video.currentTime = currentTime; + }); + return video.src = URL.createObjectURL(blob); + } else { + blob.name = post.file.name; + QR.handleFiles([blob]); + return QR.oekaki.edit(); + } + }); + } + }, + setup: function() { + return $.global(function() { + var FCX; + FCX = window.FCX; + FCX.oekakiCB = function() { + return window.Tegaki.flatten().toBlob(function(file) { + var source; + source = "oekaki-" + (Date.now()); + FCX.oekakiLatest = source; + return document.dispatchEvent(new CustomEvent('QRSetFile', { + bubbles: true, + detail: { + file: file, + name: FCX.oekakiName, + source: source + } + })); + }); + }; + if (window.Tegaki) { + return document.querySelector('#qr .oekaki').hidden = false; + } + }); + }, + load: function(cb) { + var n, onload, script, style; + if ($('script[src^="//s.4cdn.org/js/painter"]', d.head)) { + return cb(); + } else { + style = $.el('link', { + rel: 'stylesheet', + href: "//s.4cdn.org/css/painter." + (Date.now()) + ".css" + }); + script = $.el('script', { + src: "//s.4cdn.org/js/painter.min." + (Date.now()) + ".js" + }); + n = 0; + onload = function() { + if (++n === 2) { + return cb(); + } + }; + $.on(style, 'load', onload); + $.on(script, 'load', onload); + return $.add(d.head, [style, script]); + } + }, + draw: function() { + return $.global(function() { + var FCX, Tegaki; + Tegaki = window.Tegaki, FCX = window.FCX; + if (Tegaki.bg) { + Tegaki.destroy(); + } + FCX.oekakiName = 'tegaki.png'; + return Tegaki.open({ + onDone: FCX.oekakiCB, + onCancel: function() { + return Tegaki.bgColor = '#ffffff'; + }, + width: +document.querySelector('#qr [name=oekaki-width]').value, + height: +document.querySelector('#qr [name=oekaki-height]').value, + bgColor: document.querySelector('#qr [name=oekaki-bg]').checked ? document.querySelector('#qr [name=oekaki-bgcolor]').value : 'transparent' + }); + }); + }, + button: function() { + if (QR.selected.file) { + return QR.oekaki.edit(); + } else { + return QR.oekaki.toggle(); + } + }, + edit: function() { + return QR.oekaki.load(function() { + return $.global(function() { + var FCX, Tegaki, cb, error, name, source; + Tegaki = window.Tegaki, FCX = window.FCX; + name = document.getElementById('qr-filename').value.replace(/\.\w+$/, '') + '.png'; + source = document.getElementById('file-n-submit').dataset.source; + error = function(content) { + return document.dispatchEvent(new CustomEvent('CreateNotification', { + bubbles: true, + detail: { + type: 'warning', + content: content, + lifetime: 20 + } + })); + }; + cb = function(e) { + var file, isVideo; + document.removeEventListener('QRFile', cb, false); + if (!e.detail) { + return error('No file to edit.'); + } + if (!/^(image|video)\//.test(e.detail.type)) { + return error('Not an image.'); + } + isVideo = /^video\//.test(e.detail.type); + file = document.createElement(isVideo ? 'video' : 'img'); + file.addEventListener('error', function() { + return error('Could not open file.', false); + }); + file.addEventListener((isVideo ? 'loadeddata' : 'load'), function() { + if (Tegaki.bg) { + Tegaki.destroy(); + } + FCX.oekakiName = name; + Tegaki.open({ + onDone: FCX.oekakiCB, + onCancel: function() { + return Tegaki.bgColor = '#ffffff'; + }, + width: file.naturalWidth || file.videoWidth, + height: file.naturalHeight || file.videoHeight, + bgColor: 'transparent' + }); + return Tegaki.activeCtx.drawImage(file, 0, 0); + }, false); + return file.src = URL.createObjectURL(e.detail); + }; + if (Tegaki.bg && Tegaki.onDoneCb === FCX.oekakiCB && source === FCX.oekakiLatest) { + FCX.oekakiName = name; + return Tegaki.resume(); + } else { + document.addEventListener('QRFile', cb, false); + return document.dispatchEvent(new CustomEvent('QRGetFile', { + bubbles: true + })); + } + }); + }); + }, + toggle: function() { + return QR.oekaki.load(function() { + return QR.nodes.oekaki.hidden = !QR.nodes.oekaki.hidden; + }); + } + }; + +}).call(this); + +(function() { + var 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; }; + + QR.persona = { + always: {}, + types: { + name: [], + email: [], + sub: [] + }, + init: function() { + var i, item, len, ref; + if (!(Conf['Quick Reply'] || (Conf['Menu'] && Conf['Delete Link']))) { + return; + } + ref = Conf['QR.personas'].split('\n'); + for (i = 0, len = ref.length; i < len; i++) { + item = ref[i]; + QR.persona.parseItem(item.trim()); + } + }, + parseItem: function(item) { + var boards, match, ref, ref1, ref2, type, val; + 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(QR.persona.types[type], val) < 0) { + return QR.persona.types[type].push(val); + } + }, + load: function() { + var arr, i, len, list, ref, type, val; + ref = QR.persona.types; + for (type in ref) { + arr = ref[type]; + 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 m; + if (QR.persona.pwd != null) { + return QR.persona.pwd; + } else if ((m = d.cookie.match(/4chan_pass=([^;]+)/))) { + return decodeURIComponent(m[1]); + } else { + return ''; + } + }, + 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 + }; + return $.set('QR.persona', persona); + }); + } + }; + +}).call(this); + +(function() { + var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, + indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, + slice = [].slice; + + QR.post = (function() { + function _Class(select) { + this.select = bind(this.select, this); + var el, event, i, j, label, len, len1, prev, ref, ref1; + el = $.el('a', { + className: 'qr-preview', + draggable: true, + href: 'javascript:;' + }); + $.extend(el, { + innerHTML: "" + }); + this.nodes = { + el: el, + rm: el.firstChild, + spoiler: $('.qr-preview-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.spoiler, 'change', (function(_this) { + return function(e) { + _this.spoiler = e.target.checked; + if (_this === QR.selected) { + return QR.nodes.spoiler.checked = _this.spoiler; + } + }; + })(this)); + ref = $$('label', el); + for (i = 0, len = ref.length; i < len; i++) { + label = ref[i]; + $.on(label, 'click', function(e) { + return e.stopPropagation(); + }); + } + $.add(QR.nodes.dumpList, el); + ref1 = ['dragStart', 'dragEnter', 'dragLeave', 'dragOver', 'dragEnd', 'drop']; + for (j = 0, len1 = ref1.length; j < len1; j++) { + event = ref1[j]; + $.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 : ''; + _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); + URL.revokeObjectURL(this.URL); + return this.dismissErrors(); + }; + + _Class.prototype.lock = function(lock) { + var i, len, name, node, 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' : ''; + 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.removeAttribute('id'); + 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 i, len, name, node, 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"] || ''; + } + (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.updateComment(); + 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.saveFilename(); + return this.updateFilename(); + case 'name': + return QR.persona.set(this); + } + }; + + _Class.prototype.forceSave = function() { + var i, len, name, node, 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.setComment = function(com) { + this.com = com || null; + if (this === QR.selected) { + QR.nodes.com.value = this.com; + } + return this.updateComment(); + }; + + _Class.prototype.updateComment = function() { + if (this === QR.selected) { + QR.characterCount(); + } + this.nodes.span.textContent = this.com; + return $.queueTask(function() { + return QR.captcha.onPostChange(); + }); + }; + + _Class.rmErrored = function(e) { + var error, errors, i, j, len, post, ref; + e.stopPropagation(); + ref = QR.posts; + for (i = ref.length - 1; i >= 0; i += -1) { + post = ref[i]; + if (errors = post.errors) { + for (j = 0, len = errors.length; j < len; j++) { + error = errors[j]; + if (!(doc.contains(error))) { + continue; + } + post.rm(); + break; + } + } + } + }; + + _Class.prototype.error = function(className, message) { + var div, ref, rm, rmAll; + div = $.el('div', { + className: className + }); + $.extend(div, { + innerHTML: E(message) + "
              [delete] [delete all]" + }); + (this.errors || (this.errors = [])).push(div); + ref = $$('a', div), rm = ref[0], rmAll = ref[1]; + $.on(div, 'click', (function(_this) { + return function() { + if (indexOf.call(QR.posts, _this) >= 0) { + return _this.select(); + } + }; + })(this)); + $.on(rm, 'click', (function(_this) { + return function(e) { + e.stopPropagation(); + if (indexOf.call(QR.posts, _this) >= 0) { + return _this.rm(); + } + }; + })(this)); + $.on(rmAll, 'click', QR.post.rmErrored); + return QR.error(div, true); + }; + + _Class.prototype.fileError = function(message) { + return this.error('file-error', this.filename + ": " + message); + }; + + _Class.prototype.dismissErrors = function(test) { + var error, i, len, ref; + if (test == null) { + test = function() { + return true; + }; + } + if (this.errors) { + ref = this.errors; + for (i = 0, len = ref.length; i < len; i++) { + error = ref[i]; + if (doc.contains(error) && test(error)) { + error.parentNode.previousElementSibling.click(); + } + } + } + }; + + _Class.prototype.setFile = function(file1) { + var ext, ref; + this.file = file1; + if (Conf['Randomize Filename'] && g.BOARD.ID !== 'f') { + this.filename = "" + (Date.now() - Math.floor(Math.random() * 365 * $.DAY)); + if (ext = this.file.name.match(QR.validExtension)) { + this.filename += ext[0]; + } + } else { + this.filename = this.file.name; + } + this.filesize = $.bytesToString(this.file.size); + this.checkSize(); + $.addClass(this.nodes.el, 'has-file'); + $.queueTask(function() { + return QR.captcha.onPostChange(); + }); + URL.revokeObjectURL(this.URL); + this.saveFilename(); + if (this === QR.selected) { + this.showFileData(); + } else { + this.updateFilename(); + } + this.nodes.el.style.backgroundImage = null; + if (ref = this.file.type, indexOf.call(QR.mimeTypes, ref) < 0) { + return this.fileError('Unsupported file type.'); + } else if (/^(image|video)\//.test(this.file.type)) { + return this.readFile(); + } + }; + + _Class.prototype.checkSize = function() { + var max; + max = QR.max_size; + if (/^video\//.test(this.file.type)) { + max = Math.min(max, QR.max_size_video); + } + if (this.file.size > max) { + return this.fileError("File too large (file: " + this.filesize + ", max: " + ($.bytesToString(max)) + ")."); + } + }; + + _Class.prototype.readFile = function() { + var el, event, isVideo, onerror, onload; + isVideo = /^video\//.test(this.file.type); + el = $.el(isVideo ? 'video' : 'img'); + if (isVideo && !el.canPlayType(this.file.type)) { + return; + } + event = isVideo ? 'loadeddata' : 'load'; + onload = (function(_this) { + return function() { + $.off(el, event, onload); + $.off(el, 'error', onerror); + _this.checkDimensions(el); + return _this.setThumbnail(el); + }; + })(this); + onerror = (function(_this) { + return function() { + $.off(el, event, onload); + $.off(el, 'error', onerror); + _this.fileError((isVideo ? 'Video' : 'Image') + " appears corrupt"); + return URL.revokeObjectURL(el.src); + }; + })(this); + $.on(el, event, onload); + $.on(el, 'error', onerror); + return el.src = URL.createObjectURL(this.file); + }; + + _Class.prototype.checkDimensions = function(el) { + var duration, height, max_height, max_width, ref, videoHeight, videoWidth, width; + if (el.tagName === 'IMG') { + height = el.height, width = el.width; + if (height > QR.max_height || width > QR.max_width) { + this.fileError("Image too large (image: " + height + "x" + width + "px, max: " + QR.max_height + "x" + QR.max_width + "px)"); + } + if (height < QR.min_height || width < QR.min_width) { + return this.fileError("Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); + } + } else { + videoHeight = el.videoHeight, videoWidth = el.videoWidth, duration = el.duration; + max_height = Math.min(QR.max_height, QR.max_height_video); + max_width = Math.min(QR.max_width, QR.max_width_video); + if (videoHeight > max_height || videoWidth > max_width) { + this.fileError("Video too large (video: " + videoHeight + "x" + videoWidth + "px, max: " + max_height + "x" + max_width + "px)"); + } + if (videoHeight < QR.min_height || videoWidth < QR.min_width) { + this.fileError("Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); + } + if (!isFinite(duration)) { + this.fileError('Video lacks duration metadata (try remuxing)'); + } else if (duration > QR.max_duration_video) { + this.fileError("Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)"); + } + if (((ref = g.BOARD.ID) !== 'gif' && ref !== 'wsg') && $.hasAudio(el)) { + return this.fileError('Audio not allowed'); + } + } + }; + + _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.removeAttribute('title'); + QR.nodes.filename.removeAttribute('title'); + this.nodes.el.style.backgroundImage = null; + $.rmClass(this.nodes.el, 'has-file'); + this.showFileData(); + URL.revokeObjectURL(this.URL); + return this.dismissErrors(function(error) { + return $.hasClass(error, 'file-error'); + }); + }; + + _Class.prototype.saveFilename = function() { + this.file.newName = (this.filename || '').replace(/[\/\\]/g, '-'); + if (!QR.validExtension.test(this.filename)) { + return this.file.newName += "." + (QR.extensionFromType[this.file.type] || 'jpg'); + } + }; + + _Class.prototype.updateFilename = function() { + var long; + long = this.filename + " (" + this.filesize + ")"; + this.nodes.el.title = long; + if (this !== QR.selected) { + return; + } + return QR.nodes.filename.title = long; + }; + + _Class.prototype.showFileData = function() { + var ref; + if (this.file) { + this.updateFilename(); + QR.nodes.filename.value = this.filename; + $.addClass(QR.nodes.oekaki, 'has-file'); + $.addClass(QR.nodes.fileSubmit, 'has-file'); + } else { + $.rmClass(QR.nodes.oekaki, 'has-file'); + $.rmClass(QR.nodes.fileSubmit, 'has-file'); + } + if (((ref = this.file) != null ? ref.source : void 0) != null) { + QR.nodes.fileSubmit.dataset.source = this.file.source; + } else { + QR.nodes.fileSubmit.removeAttribute('data-source'); + } + return QR.nodes.spoiler.checked = this.spoiler; + }; + + _Class.prototype.pasteText = function(file) { + var reader; + this.pasting = true; + reader = new FileReader(); + reader.onload = (function(_this) { + return function(e) { + var result; + result = e.target.result; + _this.setComment((_this.com ? _this.com + "\n" + result : result)); + return delete _this.pasting; + }; + })(this); + return reader.readAsText(file); + }; + + _Class.prototype.dragStart = function(e) { + var left, ref, top; + ref = this.getBoundingClientRect(), left = ref.left, top = ref.top; + e.dataTransfer.setDragImage(this, e.clientX - left, e.clientY - top); + 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; + + })(); + +}).call(this); + +QuoteBacklink = (function() { + var QuoteBacklink; + + QuoteBacklink = { + containers: {}, + init: function() { + var ref; + if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Quote Backlinks']) { + return; + } + Callbacks.Post.push({ + name: 'Quote Backlinking Part 1', + cb: this.firstNode + }); + return Callbacks.Post.push({ + name: 'Quote Backlinking Part 2', + cb: this.secondNode + }); + }, + firstNode: function() { + var a, clone, container, containers, hash, i, j, k, len, len1, len2, link, markYours, nodes, post, quote, ref, ref1, ref2; + if (this.isClone || !this.quotes.length || this.isRebuilt) { + return; + } + markYours = Conf['Mark Quotes of You'] && ((ref = QuoteYou.db) != null ? ref.get({ + boardID: this.board.ID, + threadID: this.thread.ID, + postID: this.ID + }) : void 0); + 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)' : '') + }); + ref1 = this.quotes; + for (i = 0, len = ref1.length; i < len; i++) { + quote = ref1[i]; + containers = [QuoteBacklink.getContainer(quote)]; + if ((post = g.posts[quote]) && post.nodes.backlinkContainer) { + ref2 = post.clones; + for (j = 0, len1 = ref2.length; j < len1; j++) { + clone = ref2[j]; + containers.push(clone.nodes.backlinkContainer); + } + } + for (k = 0, len2 = containers.length; k < len2; k++) { + container = containers[k]; + link = a.cloneNode(true); + nodes = container.firstChild ? [$.tn(' '), link] : [link]; + 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' + })); + } + }; + + return QuoteBacklink; + +}).call(this); + +QuoteCT = (function() { + var QuoteCT; + + 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 Callbacks.Post.push({ + name: 'Mark Cross-thread Quotes', + cb: this.node + }); + }, + node: function() { + var board, boardID, i, len, quotelink, ref, ref1, ref2, thread, threadID; + if (this.isClone && this.thread === this.context.thread) { + return; + } + ref = this.context, 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)); + } + } + } + }; + + return QuoteCT; + +}).call(this); + +QuoteInline = (function() { + var QuoteInline; + + QuoteInline = { + init: function() { + var ref; + if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Quote Inlining']) { + return; + } + if (Conf['Comment Expansion']) { + ExpandComment.callbacks.push(this.node); + } + return Callbacks.Post.push({ + name: 'Quote Inlining', + cb: this.node + }); + }, + node: function() { + var i, isClone, j, len, len1, link, process, 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); + } + }, + process: function(link, clone) { + if (Conf['Quote Hash Navigation']) { + if (!clone) { + $.after(link, QuoteInline.qiQuote(link, $.hasClass(link, 'filtered'))); + } + } + return $.on(link, 'click', QuoteInline.toggle); + }, + 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, quoter, ref, ref1, threadID; + if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) { + return; + } + ref = Get.postDataFromLink(this), boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; + if (Conf['Inline Cross-thread Quotes Only'] && g.VIEW === 'thread' && ((ref1 = g.posts[boardID + "." + postID]) != null ? ref1.nodes.root.offsetParent : void 0)) { + return; + } + e.preventDefault(); + quoter = Get.postFromNode(this); + context = quoter.context; + if ($.hasClass(this, 'inlined')) { + QuoteInline.rm(this, boardID, threadID, postID, context); + } else { + if ($.x("ancestor::div[@data-full-i-d='" + boardID + "." + postID + "']", this)) { + return; + } + QuoteInline.add(this, boardID, threadID, postID, context, quoter); + } + 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, quoter) { + var inline, isBacklink, post, qroot, root; + isBacklink = $.hasClass(quotelink, 'backlink'); + inline = $.el('div', { + className: 'inline' + }); + inline.dataset.fullID = boardID + "." + postID; + 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, quoter); + 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, ref, root; + isBacklink = $.hasClass(quotelink, 'backlink'); + root = QuoteInline.findRoot(quotelink, isBacklink); + root = $.x("following-sibling::div[@data-full-i-d='" + boardID + "." + 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'); + } + } + }; + + return QuoteInline; + +}).call(this); + +QuoteOP = (function() { + var QuoteOP, + 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; }; + + 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 Callbacks.Post.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.context.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)); + } + } + } + }; + + return QuoteOP; + +}).call(this); + +QuotePreview = (function() { + var QuotePreview, + slice = [].slice; + + 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 Callbacks.Post.push({ + name: 'Quote Previewing', + cb: this.node + }); + }, + node: function() { + var i, len, link, 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, i, len, origin, post, postID, posts, qp, ref, threadID; + if ($.hasClass(this, 'inlined') || !d.contains(this)) { + 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.postFromNode(this)); + UI.hover({ + root: this, + el: qp, + latestEvent: e, + endEvents: 'mouseout click', + cb: QuotePreview.mouseout + }); + if (Conf['Quote Highlighting'] && (origin = g.posts[boardID + "." + postID])) { + posts = [origin].concat(origin.clones); + posts.pop(); + for (i = 0, len = posts.length; i < len; i++) { + post = posts[i]; + $.addClass(post.nodes.post, 'qphl'); + } + } + }, + mouseout: function() { + var clone, i, len, post, ref, root; + 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'); + } + } + }; + + return QuotePreview; + +}).call(this); + +QuoteStrikeThrough = (function() { + var QuoteStrikeThrough; + + 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 Callbacks.Post.push({ + name: 'Strike-through Quotes', + cb: this.node + }); + }, + node: function() { + var boardID, i, len, postID, quotelink, 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'); + } + } + } + }; + + return QuoteStrikeThrough; + +}).call(this); + +QuoteThreading = +/* + <3 aeosynth + */ + +(function() { + var QuoteThreading; + + QuoteThreading = { + init: function() { + if (!(Conf['Quote Threading'] && g.VIEW === 'thread')) { + return; + } + this.controls = $.el('label', { + innerHTML: " Threading" + }); + this.threadNewLink = $.el('span', { + className: 'brackets-wrap threadnewlink', + hidden: true + }); + $.extend(this.threadNewLink, { + innerHTML: "Thread New Posts" + }); + this.input = $('input', this.controls); + this.input.checked = Conf['Thread Quotes']; + $.on(this.input, 'change', this.setEnabled); + $.on(this.input, 'change', this.rethread); + $.on(this.threadNewLink.firstElementChild, 'click', this.rethread); + $.on(d, '4chanXInitFinished', (function(_this) { + return function() { + return _this.ready = true; + }; + })(this)); + Header.menu.addEntry(this.entry = { + el: this.controls, + order: 99 + }); + Callbacks.Thread.push({ + name: 'Quote Threading', + cb: this.setThread + }); + return Callbacks.Post.push({ + name: 'Quote Threading', + cb: this.node + }); + }, + parent: {}, + children: {}, + inserted: {}, + setEnabled: function() { + var other, ref; + other = (ref = ReplyPruning.inputs) != null ? ref.enabled : void 0; + if (this.checked && (other != null ? other.checked : void 0)) { + other.checked = false; + $.event('change', null, other); + } + return $.cb.checked.call(this); + }, + setThread: function() { + QuoteThreading.thread = this; + return $.asap((function() { + return !Conf['Thread Updater'] || $('.navLinksBot > .updatelink'); + }), function() { + var navLinksBot; + if ((navLinksBot = $('.navLinksBot'))) { + return $.add(navLinksBot, [$.tn(' '), QuoteThreading.threadNewLink]); + } + }); + }, + node: function() { + var ancestor, j, lastParent, len, parent, parents, quote, ref; + if (this.isFetchedQuote || this.isClone || !this.isReply) { + return; + } + parents = new Set(); + lastParent = null; + ref = this.quotes; + for (j = 0, len = ref.length; j < len; j++) { + quote = ref[j]; + 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, j, len, posts; + posts = [post]; + if (children = QuoteThreading.children[post.fullID]) { + for (j = 0, len = children.length; j < len; j++) { + child = children[j]; + posts = posts.concat(QuoteThreading.descendants(child)); + } + } + return posts; + }, + insert: function(post) { + var base, child, children, descendants, i, j, k, l, len, name, next, nodes, order, parent, prev, prev2, threadContainer, x; + if (!(Conf['Thread Quotes'] && (parent = QuoteThreading.parent[post.fullID]) && !QuoteThreading.inserted[post.fullID])) { + return false; + } + descendants = QuoteThreading.descendants(post); + if (!Unread.posts.has(parent.ID)) { + if ((function() { + var j, len, x; + for (j = 0, len = descendants.length; j < len; j++) { + x = descendants[j]; + 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 (j = children.length - 1; j >= 0; j += -1) { + child = children[j]; + if (child.ID >= post.ID) { + i--; + } + } + if (i !== children.length) { + next = children[i]; + for (k = 0, len = descendants.length; k < len; k++) { + x = descendants[k]; + 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 (l = descendants.length - 1; l >= 0; l += -1) { + x = descendants[l]; + 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; + if (!QuoteThreading.ready) { + return; + } + thread = QuoteThreading.thread; + posts = thread.posts; + QuoteThreading.threadNewLink.hidden = true; + if (Conf['Thread Quotes']) { + 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(); + } + }; + + return QuoteThreading; + +}).call(this); + +QuoteYou = (function() { + var QuoteYou; + + QuoteYou = { + init: function() { + var ref; + if (!Conf['Remember Your Posts']) { + return; + } + this.db = new DataBoard('yourPosts'); + $.sync('Remember Your Posts', function(enabled) { + return Conf['Remember Your Posts'] = enabled; + }); + $.on(d, 'QRPostSuccessful', function(e) { + var boardID, postID, ref, threadID; + $.forceSync('Remember Your Posts'); + if (Conf['Remember Your Posts']) { + ref = e.detail, boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; + return QuoteYou.db.set({ + boardID: boardID, + threadID: threadID, + postID: postID, + val: true + }); + } + }); + if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { + 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 Callbacks.Post.push({ + name: 'Mark Quotes of You', + cb: this.node + }); + }, + node: function() { + var i, len, quotelink, ref; + if (this.isClone) { + return; + } + if (QuoteYou.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 (!(QuoteYou.db.get(Get.postDataFromLink(quotelink)))) { + continue; + } + if (Conf['Mark Quotes of You']) { + $.add(quotelink, $.tn(QuoteYou.text)); + } + $.addClass(quotelink, 'you'); + $.addClass(this.nodes.root, 'quotesYou'); + } + }, + cb: { + seek: function(type) { + var highlight, post, posts, result, str; + if (highlight = $('.highlight')) { + $.rmClass(highlight, 'highlight'); + } + if (!(QuoteYou.lastRead && doc.contains(QuoteYou.lastRead) && $.hasClass(QuoteYou.lastRead, 'quotesYou'))) { + 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(root) { + var post; + post = $('.post', root); + if (!post.getBoundingClientRect().height) { + return false; + } else { + QuoteYou.lastRead = root; + window.location = "#" + post.id; + Header.scrollTo(post); + $.addClass(post, 'highlight'); + return true; + } + } + } + }; + + return QuoteYou; + +}).call(this); + +Quotify = (function() { + var Quotify, + indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, + slice = [].slice; + + 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 Callbacks.Post.push({ + name: 'Resurrect Quotes', + cb: this.node + }); + }, + node: function() { + var deadlink, i, len, ref; + if (this.isClone) { + return; + } + ref = $$('.deadlink', this.nodes.comment); + for (i = 0, len = ref.length; i < len; i++) { + deadlink = ref[i]; + 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', + 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', + 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)); + } + }; + + return Quotify; + +}).call(this); + +Main = (function() { + var Main; + + Main = { + init: function() { + var db, flatten, items, j, key, len, ref; + if (d.body && !$('title', d.head)) { + return; + } + if (window['4chan X antidup']) { + return; + } + window['4chan X antidup'] = true; + if (location.hostname === 'www.google.com') { + $.get('Captcha Fixes', true, function(arg) { + var enabled; + enabled = arg['Captcha Fixes']; + if (enabled) { + return $.ready(function() { + return Captcha.fixes.init(); + }); + } + }); + return; + } + $.global(function() { + var j, len, nuke, prop, ref; + nuke = function(obj, prop) { + try { + return Object.defineProperty(obj, prop, { + configurable: false, + get: function() { + throw new Error(); + }, + set: function() { + throw new Error(); + } + }); + } catch (_error) {} + }; + ref = ['atOptions', 'adsterra_key', 'EpmadsConfig', 'epmads_key', 'EpomConfig', 'epom_key', 'exoDocumentProtocol']; + for (j = 0, len = ref.length; j < len; j++) { + prop = ref[j]; + nuke(window, prop); + } + }); + $.on(window, 'beforescriptexecute', function(e) { + var host, ref, ref1; + host = (ref = e.target.src.split('/')[2]) != null ? (ref1 = ref.match(/[^.]+\.[^.]+$/)) != null ? ref1[0] : void 0 : void 0; + if (host === 'bnhtml.com' || host === 'ecpmrocks.com' || host === 'advertisation.com' || host === 'exoclick.com') { + return e.preventDefault(); + } + }); + $.on(d, '4chanXInitFinished', function() { + if (Main.expectInitFinished) { + return delete Main.expectInitFinished; + } else { + new Notice('error', 'Error: Multiple copies of 4chan X are enabled.'); + return $.addClass(doc, 'tainted'); + } + }); + 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); + ref = DataBoard.keys; + for (j = 0, len = ref.length; j < len; j++) { + db = ref[j]; + Conf[db] = { + boards: {} + }; + } + Conf['selectedArchives'] = {}; + Conf['cooldowns'] = {}; + Conf['Index Sort'] = {}; + Conf['Except Archives from Encryption'] = false; + Conf['JSON Navigation'] = true; + Conf['Oekaki Links'] = true; + items = {}; + for (key in Conf) { + items[key] = void 0; + } + items['previousversion'] = void 0; + return $.get(items, function(items) { + return $.asap((function() { + var doc; + return doc = d.documentElement; + }), function() { + var ref1, val; + if ($.cantSet) { + + } else if (items.previousversion == null) { + Main.ready(function() { + $.set('previousversion', g.VERSION); + return Settings.open(); + }); + } else if (items.previousversion !== g.VERSION) { + Main.upgrade(items); + } + for (key in Conf) { + val = Conf[key]; + Conf[key] = (ref1 = items[key]) != null ? ref1 : val; + } + return Main.initFeatures(); + }); + }); + }, + upgrade: function(items) { + var changes, previousversion; + previousversion = items.previousversion; + changes = Settings.upgrade(items, previousversion); + items.previousversion = changes.previousversion = g.VERSION; + return $.set(changes, function() { + var el, ref; + if ((ref = items['Show Updated Notifications']) != null ? ref : true) { + el = $.el('span', { + innerHTML: "4chan X has been updated to version " + E(g.VERSION) + "." + }); + return new Notice('info', el, 15); + } + }); + }, + initFeatures: function() { + var err, feature, hostname, j, len, match, name, pathname, ref, ref1, ref2, ref3, search; + hostname = location.hostname, search = location.search; + pathname = location.pathname.split(/\/+/); + if (hostname !== 'www.4chan.org') { + g.BOARD = new Board(pathname[1]); + } + if (hostname === 'boards.4chan.org' || hostname === 'sys.4chan.org' || hostname === 'www.4chan.org') { + $.global(function() { + document.documentElement.classList.add('js-enabled'); + return window.FCX = {}; + }); + Main.jsEnabled = $.hasClass(doc, 'js-enabled'); + } + switch (hostname) { + case 'www.4chan.org': + $.onExists(doc, 'body', function() { + return $.addStyle(CSS.www); + }); + Captcha.replace.init(); + return; + case 'sys.4chan.org': + if (pathname[2] === 'imgboard.php') { + if (/\bmode=report\b/.test(search)) { + Report.init(); + } else if ((match = search.match(/\bres=(\d+)/))) { + $.ready(function() { + var ref; + if (Conf['404 Redirect'] && ((ref = $.id('errmsg')) != null ? ref.textContent : void 0) === 'Error: Specified thread does not exist.') { + return Redirect.navigate('thread', { + boardID: g.BOARD.ID, + postID: +match[1] + }); + } + }); + } + } else if (pathname[2] === 'post') { + PostSuccessful.init(); + } + return; + case 'i.4cdn.org': + if (!(pathname[2] && !/s\.jpg$/.test(pathname[2]))) { + return; + } + $.asap((function() { + return d.readyState !== 'loading'; + }), function() { + var ref, video; + if (Conf['404 Redirect'] && ((ref = d.title) === '4chan - Temporarily Offline' || ref === '4chan - 404 Not Found')) { + return Redirect.navigate('file', { + boardID: g.BOARD.ID, + filename: pathname[pathname.length - 1] + }); + } 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 ((ref = pathname[2]) === 'thread' || ref === 'res') { + g.VIEW = 'thread'; + g.THREADID = +pathname[3]; + } else if ((ref1 = pathname[2]) === 'catalog' || ref1 === 'archive') { + g.VIEW = pathname[2]; + } else if (pathname[2].match(/^\d*$/)) { + g.VIEW = 'index'; + } else { + return; + } + g.threads = new SimpleDict(); + g.posts = new SimpleDict(); + $.onExists(doc, 'body', Main.initStyle); + ref2 = Main.features; + for (j = 0, len = ref2.length; j < len; j++) { + ref3 = ref2[j], name = ref3[0], feature = ref3[1]; + try { + feature.init(); + } catch (_error) { + err = _error; + Main.handleErrors({ + message: "\"" + name + "\" initialization crashed.", + error: err + }); + } + } + return $.ready(Main.initReady); + }, + initStyle: function() { + var keyboard, ref; + if (!Main.isThisPageLegit()) { + 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); + if ($.engine) { + $.addClass(doc, $.engine); + } + $.onExists(doc, '.ad-cnt', function(ad) { + return $.onExists(ad, 'img', function() { + return $.addClass(doc, 'ads-loaded'); + }); + }); + if (Conf['Autohiding Scrollbar']) { + $.addClass(doc, 'autohiding-scrollbar'); + } + $.ready(function() { + if (d.body.clientHeight > doc.clientHeight && (window.innerWidth === doc.clientWidth) !== Conf['Autohiding Scrollbar']) { + Conf['Autohiding Scrollbar'] = !Conf['Autohiding Scrollbar']; + $.set('Autohiding Scrollbar', Conf['Autohiding Scrollbar']); + return $.toggleClass(doc, 'autohiding-scrollbar'); + } + }); + $.addStyle(CSS.boards, 'fourchanx-css'); + Main.bgColorStyle = $.el('style', { + id: 'fourchanx-bgcolor-css' + }); + keyboard = false; + $.on(d, 'mousedown', function() { + return keyboard = false; + }); + $.on(d, 'keydown', function(e) { + if (e.keyCode === 9) { + return keyboard = true; + } + }); + window.addEventListener('focus', (function() { + return doc.classList.toggle('keyboard-focus', keyboard); + }), true); + 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 bgColor, div, j, len, styleSheet; + $.rmClass(doc, style); + style = null; + for (j = 0, len = styleSheets.length; j < len; j++) { + styleSheet = styleSheets[j]; + if (styleSheet.href === (mainStyleSheet != null ? mainStyleSheet.href : void 0)) { + style = styleSheet.title.toLowerCase().replace('new', '').trim().replace(/\s+/g, '-'); + break; + } + } + if (style) { + $.addClass(doc, style); + return $.rm(Main.bgColorStyle); + } else { + div = $.el('div', { + className: 'reply' + }); + div.style.cssText = 'position: absolute; visibility: hidden;'; + $.add(d.body, div); + bgColor = window.getComputedStyle(div).backgroundColor; + $.rm(div); + Main.bgColorStyle.textContent = ".dialog, .suboption-list > div:last-of-type {\n background-color: " + bgColor + ";\n}"; + return $.after($.id('fourchanx-css'), Main.bgColorStyle); + } + }; + setStyle(); + if (!mainStyleSheet) { + return; + } + return new MutationObserver(setStyle).observe(mainStyleSheet, { + attributes: true, + attributeFilter: ['href'] + }); + }, + initReady: function() { + var msg, ref, ref1, ref2; + if (g.VIEW === 'thread' && (((ref = d.title) === '4chan - Temporarily Offline' || ref === '4chan - 404 Not Found') || ($('.board') && !$('.opContainer')))) { + ThreadWatcher.set404(g.BOARD.ID, g.THREADID, function() { + if (Conf['404 Redirect']) { + return Redirect.navigate('thread', { + boardID: g.BOARD.ID, + threadID: g.THREADID, + postID: +location.hash.match(/\d+/) + }, "/" + g.BOARD + "/"); + } + }); + return; + } + if ((ref1 = d.title) === '4chan - Temporarily Offline' || ref1 === '4chan - 404 Not Found') { + return; + } + if (((ref2 = g.VIEW) === 'index' || ref2 === 'thread') && !$('.board + *')) { + msg = $.el('div', { + innerHTML: "The page didn't load completely.
              Some features may not work unless you reload." + }); + $.on($('a', msg), 'click', function() { + return location.reload(); + }); + new Notice('warning', msg); + } + if (!(Conf['JSON Index'] && g.VIEW === 'index')) { + return Main.initThread(); + } else { + Main.expectInitFinished = true; + return $.event('4chanXInitFinished'); + } + }, + initThread: function() { + var board, err, errors, j, k, len, len1, m, postRoot, posts, ref, ref1, scriptData, thread, threadRoot, threads; + if ((board = $('.board'))) { + threads = []; + posts = []; + ref = $$('.board > .thread', board); + for (j = 0, len = ref.length; j < len; j++) { + threadRoot = ref[j]; + thread = new Thread(+threadRoot.id.slice(1), g.BOARD); + threads.push(thread); + ref1 = $$('.thread > .postContainer', threadRoot); + for (k = 0, len1 = ref1.length; k < len1; k++) { + postRoot = ref1[k]; + if ($('.postMessage', postRoot)) { + 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 l, len2, post; + for (l = 0, len2 = posts.length; l < len2; l++) { + post = posts[l]; + QuoteThreading.insert(post); + } + Main.expectInitFinished = true; + return $.event('4chanXInitFinished'); + }); + } else { + Main.expectInitFinished = true; + return $.event('4chanXInitFinished'); + } + }, + callbackNodes: function(klass, nodes) { + var cb, i, node; + i = 0; + cb = Callbacks[klass]; + while (node = nodes[i++]) { + cb.execute(node); + } + }, + callbackNodesDB: function(klass, nodes, cb) { + var cbs, fn, i, softTask; + i = 0; + cbs = Callbacks[klass]; + 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, j, len, logs; + if (!(errors instanceof Array)) { + error = errors; + } else if (errors.length === 1) { + error = errors[0]; + } + if (error) { + new Notice('error', Main.parseError(error, Main.reportLink([error])), 15); + return; + } + div = $.el('div', { + innerHTML: E(errors.length) + " errors occurred." + (Main.reportLink(errors)).innerHTML + " [show]" + }); + $.on(div.lastElementChild, 'click', function() { + var ref; + return ref = this.textContent === 'show' ? ['hide', false] : ['show', true], this.textContent = ref[0], logs.hidden = ref[1], ref; + }); + logs = $.el('div', { + hidden: true + }); + for (j = 0, len = errors.length; j < len; j++) { + error = errors[j]; + $.add(logs, Main.parseError(error)); + } + return new Notice('error', [div, logs], 30); + }, + parseError: function(data, reportLink) { + var context, error, lines, message, ref, ref1; + c.error(data.message, data.error.stack); + message = $.el('div', { + innerHTML: E(data.message) + ((reportLink) ? (reportLink).innerHTML : "") + }); + error = $.el('div', { + textContent: (data.error.name || 'Error') + ": " + (data.error.message || 'see console for details') + }); + lines = ((ref = data.error.stack) != null ? (ref1 = ref.match(/\d+(?=:\d+\)?$)/mg)) != null ? ref1.join().replace(/^/, ' at ') : void 0 : void 0) || ''; + context = $.el('div', { + textContent: "(4chan X ccd0 v" + g.VERSION + " " + $.platform + " on " + $.engine + lines + ")" + }); + return [message, error, context]; + }, + reportLink: function(errors) { + var data, details, ref, title, url; + data = errors[0]; + title = data.message; + if (errors.length > 1) { + title += " (+" + (errors.length - 1) + " other errors)"; + } + details = "[Please describe the steps needed to reproduce this error.]\n\nScript: 4chan X ccd0 v" + g.VERSION + " " + $.platform + "\nUser agent: " + navigator.userAgent + "\nURL: " + location.href + "\n\n" + data.error + "\n" + (((ref = data.error.stack) != null ? ref.replace(data.error.toString(), '').trim() : void 0) || ''); + details = details.replace(/file:\/{3}.+\//g, ''); + url = "https://gitreports.com/issue/ccd0/4chan-x?issue_title=" + (encodeURIComponent(title)) + "&details=" + (encodeURIComponent(details)); + return { + innerHTML: " [report]" + }; + }, + 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(); + } + }); + }, + features: [['Polyfill', Polyfill], ['Normalize URL', NormalizeURL], ['Captcha Configuration', Captcha.replace], ['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], ['Thread Links', ThreadLinks], ['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 Personas', QR.persona], ['Quick Reply', QR], ['Cooldown', QR.cooldown], ['Pass Link', PassLink], ['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], ['Edit Link', QR.oekaki.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], ['Flash Features', Flash], ['Reply Pruning', ReplyPruning]] + }; + + return Main; + +}).call(this); + +Main.init(); }).call(this); diff --git a/builds/4chan-X.zip b/builds/4chan-X.zip index 7a7755bd9..6e47d2b47 100644 Binary files a/builds/4chan-X.zip and b/builds/4chan-X.zip differ diff --git a/builds/updates-beta.xml b/builds/updates-beta.xml index f4c66585a..c58daf9bf 100644 --- a/builds/updates-beta.xml +++ b/builds/updates-beta.xml @@ -1,7 +1,7 @@ - + diff --git a/builds/updates.xml b/builds/updates.xml index 2bfaf58ef..2c1fff346 100644 --- a/builds/updates.xml +++ b/builds/updates.xml @@ -1,7 +1,7 @@ - + diff --git a/version.json b/version.json index d43bfd70a..a6887bb95 100644 --- a/version.json +++ b/version.json @@ -1,4 +1,4 @@ { - "version": "1.11.30.3", - "date": "2016-04-09T12:47:17.251Z" -} + "version": "1.11.31.0", + "date": "2016-04-21T07:02:56.784Z" +} \ No newline at end of file