Merge branch 'v3'

Conflicts:
	builds/crx/script.js
	src/Filtering/PostHiding.coffee
	src/Filtering/ThreadHiding.coffee
	src/Quotelinks/QuoteYou.coffee
This commit is contained in:
Zixaphir 2013-08-09 19:45:24 -07:00
commit 00675c32bc
15 changed files with 344 additions and 201 deletions

View File

@ -2,9 +2,11 @@
- Update Gruntfile.coffee.
**MayhemYDG**:
- **New feature**: `Show Dice Roll` (with @carboncopy)
- Shows dice that were entered into the email field on /tg/.
- Fix impossibility to create new threads when in dead threads.
- Fix flag filtering on /sp/ and /int/.
- Update archives. (with woxxy and proplex)
- Update archives. (with @woxxy and @proplex)
- Minor fixes.
- Minor optimizations.

View File

@ -111,7 +111,7 @@
'use strict';
(function() {
var $, $$, Anonymize, ArchiveLink, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DataBoards, DeleteLink, DownloadLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Fourchan, Get, Header, IDColor, ImageExpand, ImageHover, ImageLoader, Keybinds, Linkify, Main, Menu, Nav, Notification, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Sauce, Settings, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, g,
var $, $$, Anonymize, ArchiveLink, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DataBoards, DeleteLink, Dice, DownloadLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Fourchan, Get, Header, IDColor, ImageExpand, ImageHover, ImageLoader, Keybinds, Linkify, Main, Menu, Nav, Notification, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Sauce, Settings, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, g,
__slice = [].slice,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
@ -133,6 +133,7 @@
'Thread Expansion': [true, 'Add buttons to expand threads.'],
'Index Navigation': [false, 'Add buttons to navigate between threads.'],
'Reply Navigation': [false, 'Add buttons to navigate to top / bottom of thread.'],
'Show Dice Roll': [true, 'Show dice that were entered into the email field.'],
'Check for Updates': [true, 'Check for updated versions of 4chan X.'],
'Show Updated Notifications': [true, 'Show notifications when 4chan X is successfully updated.'],
'Emoji': [false, 'Adds icons next to names for different emails'],
@ -447,7 +448,7 @@
var reqs;
reqs = {};
return function(url, cb) {
return function(url, cb, options) {
var err, req, rm;
if (req = reqs[url]) {
@ -462,25 +463,23 @@
return delete reqs[url];
};
try {
req = $.ajax(url, {
onload: function(e) {
var _i, _len, _ref;
_ref = this.callbacks;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
cb = _ref[_i];
cb.call(this, e);
}
this.evt = e;
return delete this.callbacks;
},
onabort: rm,
onerror: rm
});
req = $.ajax(url, options);
} catch (_error) {
err = _error;
return;
}
$.on(req, 'load', function(e) {
var _i, _len, _ref;
_ref = this.callbacks;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
cb = _ref[_i];
cb.call(this, e);
}
this.evt = e;
return delete this.callbacks;
});
$.on(req, 'abort error', rm);
req.callbacks = [cb];
return reqs[url] = req;
};
@ -1996,7 +1995,7 @@
}
},
postFromNode: function(root) {
return Get.postFromRoot($.x('ancestor::div[contains(@class,"postContainer")][1]', root));
return Get.postFromRoot($.x('(ancestor::div[contains(@class,"postContainer")]|following::div[contains(@class,"postContainer")])[1]', root));
},
contextFromNode: function(quotelink) {
return Get.postFromRoot($.x('ancestor::div[parent::div[@class="thread"]][1]', quotelink));
@ -2073,6 +2072,8 @@
})) {
return $.cache(url, function() {
return Get.archivedPost(this, boardID, postID, root, context);
}, {
withCredentials: url.archive.withCredentials
});
}
},
@ -2105,6 +2106,8 @@
})) {
$.cache(url, function() {
return Get.archivedPost(this, boardID, postID, root, context);
}, {
withCredentials: url.archive.withCredentials
});
} else {
$.addClass(root, 'warning');
@ -2126,6 +2129,8 @@
})) {
$.cache(url, function() {
return Get.archivedPost(this, boardID, postID, root, context);
}, {
withCredentials: url.archive.withCredentials
});
} else {
$.addClass(root, 'warning');
@ -3225,15 +3230,11 @@
var post;
post = Get.postFromNode(this);
if (post.isHidden) {
PostHiding.show(post);
} else {
PostHiding.hide(post);
}
PostHiding[(post.isHidden ? 'show' : 'hide')](post);
return PostHiding.saveHiddenState(post, post.isHidden);
},
hide: function(post, makeStub, hideRecursively) {
var a, postInfo, quotelink, _i, _len, _ref;
var a, button, postInfo, quotelink, _i, _len, _ref;
if (makeStub == null) {
makeStub = Conf['Stubs'];
@ -3259,15 +3260,12 @@
return;
}
a = PostHiding.makeButton(post, 'show');
postInfo = Conf['Anonymize'] ? 'Anonymous' : $('.nameBlock', post.nodes.info).textContent;
postInfo = Conf['Anonymize'] ? 'Anonymous' : post.info.name;
$.add(a, $.tn(" " + postInfo));
post.nodes.stub = $.el('div', {
className: 'stub'
});
$.add(post.nodes.stub, a);
if (Conf['Menu']) {
$.add(post.nodes.stub, [$.tn(' '), Menu.makeButton(post)]);
}
$.add(post.nodes.stub, !Conf['Menu'] ? a : [a, $.tn(' '), button = Menu.makeButton(post)]);
return $.prepend(post.nodes.root, post.nodes.stub);
},
show: function(post, showRecursively) {
@ -3462,11 +3460,6 @@
makeStub = $.el('label', {
innerHTML: "<input type=checkbox " + (Conf['Stubs'] ? 'checked' : '') + "> Make stub"
});
hideStubLink = $.el('a', {
textContent: 'Hide stub',
href: 'javascript:;'
});
$.on(hideStubLink, 'click', ThreadHiding.menu.hideStub);
$.event('AddMenuEntry', {
type: 'post',
el: div,
@ -3489,6 +3482,34 @@
}
]
});
div = $.el('a', {
className: 'show-thread-link',
textContent: 'Show thread',
href: 'javascript:;'
});
$.on(show, 'click', ThreadHiding.menu.show);
$.event('AddMenuEntry', {
type: 'post'
});
({
el: div,
order: 20,
open: function(_arg) {
var isReply, thread;
thread = _arg.thread, isReply = _arg.isReply;
if (isReply || !thread.isHidden) {
return false;
}
ThreadHiding.menu.thread = thread;
return true;
}
});
hideStubLink = $.el('a', {
textContent: 'Hide stub',
href: 'javascript:;'
});
$.on(hideStubLink, 'click', ThreadHiding.menu.hideStub);
return $.event('AddMenuEntry', {
type: 'post',
el: hideStubLink,
@ -3513,6 +3534,14 @@
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;
@ -3567,7 +3596,7 @@
return ThreadHiding.saveHiddenState(thread);
},
hide: function(thread, makeStub) {
var OP, a, numReplies, opInfo, span, threadRoot;
var OP, a, button, numReplies, opInfo, span, threadRoot;
if (makeStub == null) {
makeStub = Conf['Stubs'];
@ -3579,22 +3608,15 @@
threadRoot.hidden = threadRoot.nextElementSibling.hidden = true;
return;
}
numReplies = 0;
if (span = $('.summary', threadRoot)) {
numReplies = +span.textContent.match(/\d+/);
}
numReplies += $$('.opContainer ~ .replyContainer', threadRoot).length;
numReplies = numReplies === 1 ? '1 reply' : "" + numReplies + " replies";
opInfo = Conf['Anonymize'] ? 'Anonymous' : $('.nameBlock', OP.nodes.info).textContent;
numReplies = ((span = $('.summary', threadRoot)) ? +span.textContent.match(/\d+/) : 0) + $$('.opContainer ~ .replyContainer', threadRoot).length;
numReplies = numReplies === 1 ? '1 reply' : "" + (numReplies || 'No') + " replies";
opInfo = Conf['Anonymize'] ? 'Anonymous' : OP.info.name;
a = ThreadHiding.makeButton(thread, 'show');
$.add(a, $.tn(" " + opInfo + " (" + numReplies + ")"));
thread.stub = $.el('div', {
className: 'stub'
});
$.add(thread.stub, a);
if (Conf['Menu']) {
$.add(thread.stub, [$.tn(' '), Menu.makeButton(OP)]);
}
$.add(thread.stub, !Conf['Menu'] ? a : [a, $.tn(' '), button = Menu.makeButton(OP)]);
return $.prepend(threadRoot, thread.stub);
},
show: function(thread) {
@ -4203,7 +4225,9 @@
seek: function(type) {
var post, posts, result, str;
return unlses(Conf['Mark Quotes of You'] && Conf['Quick Reply']);
if (!(Conf['Mark Quotes of You'] && Conf['Quick Reply'])) {
return;
}
$.rmClass($('.highlight'), 'highlight');
if (!QuoteYou.lastRead) {
if (!(post = QuoteYou.lastRead = $('.quotesYou'))) {
@ -6993,45 +7017,48 @@
}
};
Menu = {
init: function() {
if (g.VIEW === 'catalog' || !Conf['Menu']) {
return;
}
this.menu = new UI.Menu('post');
return Post.prototype.callbacks.push({
name: 'Menu',
cb: this.node
});
},
node: function() {
var button;
Menu = (function() {
var a;
if (this.isClone) {
button = $('.menu-button', this.nodes.info);
} else {
button = Menu.makeButton(this);
$.add(this.nodes.info, [$.tn('\u00A0'), button]);
}
return $.on(button, 'click', Menu.toggle);
},
makeButton: (function() {
var a;
a = $.el('a', {
className: 'menu-button brackets-wrap',
innerHTML: '<span class=drop-marker></span>',
href: 'javascript:;'
});
return {
init: function() {
if (g.VIEW === 'catalog' || !Conf['Menu']) {
return;
}
this.menu = new UI.Menu('post');
return Post.prototype.callbacks.push({
name: 'Menu',
cb: this.node
});
},
node: function() {
var button;
a = null;
return function() {
a || (a = $.el('a', {
className: 'menu-button fourchanx-link',
innerHTML: '<i></i>',
href: 'javascript:;'
}));
return a.cloneNode(true);
};
})(),
toggle: function(e) {
return Menu.menu.toggle(e, this, Get.postFromNode(this));
}
};
if (this.isClone) {
button = $('.menu-button', this.nodes.info);
} else {
button = a.cloneNode(true);
$.add(this.nodes.info, [$.tn('\u00A0'), button]);
}
return $.on(button, 'click', Menu.toggle);
},
makeButton: function() {
var el;
el = a.cloneNode(true);
$.on(el, 'click', Menu.toggle);
return el;
},
toggle: function(e) {
return Menu.menu.toggle(e, this, Get.postFromNode(this));
}
};
})();
ReportLink = {
init: function() {
@ -8161,6 +8188,7 @@
domain: 'beta.foolz.us',
http: true,
https: true,
withCredentials: true,
software: 'foolfuuka',
boards: ['a', 'co', 'gd', 'h', 'jp', 'm', 'mlp', 'q', 'sp', 'tg', 'tv', 'u', 'v', 'vg', 'vp', 'vr', 'wsg'],
files: ['a', 'gd', 'h', 'jp', 'm', 'q', 'tg', 'u', 'vg', 'vp', 'vr', 'wsg']
@ -8253,14 +8281,16 @@
return "" + (Redirect.protocol(archive)) + archive.domain + "/" + path;
},
post: function(archive, _arg) {
var boardID, postID, protocol;
var URL, boardID, postID, protocol;
boardID = _arg.boardID, postID = _arg.postID;
protocol = Redirect.protocol(archive);
if (['Foolz', 'NSFW Foolz'].contains(archive.name)) {
protocol = 'https://';
}
return "" + protocol + archive.domain + "/_/api/chan/post/?board=" + boardID + "&num=" + postID;
URL = new String("" + protocol + archive.domain + "/_/api/chan/post/?board=" + boardID + "&num=" + postID);
URL.archive = archive;
return URL;
},
file: function(archive, _arg) {
var boardID, filename;
@ -8476,6 +8506,27 @@
}
};
Dice = {
init: function() {
if (g.BOARD.ID !== 'tg' || g.VIEW === 'catalog' || !Conf['Show Dice Roll']) {
return;
}
return Post.prototype.callbacks.push({
name: 'Show Dice Roll',
cb: this.node
});
},
node: function() {
var dicestats, roll, _ref;
if (this.isClone || !(dicestats = (_ref = this.info.email) != null ? _ref.match(/dice[+\s](\d+)d(\d+)/) : void 0)) {
return;
}
roll = $('b', this.nodes.comment).firstChild;
return roll.data = "Rolled " + dicestats[1] + "d" + dicestats[2] + " and got " + (roll.data.slice(7));
}
};
Emoji = {
init: function() {
var css, icon, name, pos, _ref;
@ -9628,7 +9679,7 @@
return Time.zeroPad(this.getSeconds());
},
y: function() {
return this.getFullYear() % 100;
return this.getFullYear().toString().slice(2);
},
Y: function() {
return this.getFullYear();
@ -10450,7 +10501,8 @@
'Thread Updater': ThreadUpdater,
'Thread Watcher': ThreadWatcher,
'Index Navigation': Nav,
'Keybinds': Keybinds
'Keybinds': Keybinds,
'Show Dice Roll': Dice
});
$.on(d, 'AddCallback', Main.addCallback);
return $.ready(Main.initReady);

View File

@ -115,7 +115,7 @@
'use strict';
(function() {
var $, $$, Anonymize, ArchiveLink, Banner, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DataBoards, DeleteLink, DownloadLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Fourchan, Get, GlobalMessage, Header, IDColor, ImageExpand, ImageHover, ImageLoader, JSColor, Keybinds, Linkify, Main, MascotTools, Mascots, Menu, Nav, Notification, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Rice, Sauce, Settings, Style, ThemeTools, Themes, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, editMascot, editTheme, g, userNavigation,
var $, $$, Anonymize, ArchiveLink, Banner, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DataBoards, DeleteLink, Dice, DownloadLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Fourchan, Get, GlobalMessage, Header, IDColor, ImageExpand, ImageHover, ImageLoader, JSColor, Keybinds, Linkify, Main, MascotTools, Mascots, Menu, Nav, Notification, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Rice, Sauce, Settings, Style, ThemeTools, Themes, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, editMascot, editTheme, g, userNavigation,
__slice = [].slice,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
@ -136,6 +136,7 @@
'Thread Expansion': [true, 'Add buttons to expand threads.'],
'Index Navigation': [false, 'Add buttons to navigate between threads.'],
'Reply Navigation': [false, 'Add buttons to navigate to top / bottom of thread.'],
'Show Dice Roll': [true, 'Show dice that were entered into the email field.'],
'Check for Updates': [true, 'Check for updated versions of appchan x.'],
'Color User IDs': [false, 'Assign unique colors to user IDs on boards that use them'],
'Remove Spoilers': [false, 'Remove all spoilers in text.'],
@ -2800,7 +2801,7 @@
var reqs;
reqs = {};
return function(url, cb) {
return function(url, cb, options) {
var err, req, rm;
if (req = reqs[url]) {
@ -2815,25 +2816,23 @@
return delete reqs[url];
};
try {
req = $.ajax(url, {
onload: function(e) {
var _i, _len, _ref;
_ref = this.callbacks;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
cb = _ref[_i];
cb.call(this, e);
}
this.evt = e;
return delete this.callbacks;
},
onabort: rm,
onerror: rm
});
req = $.ajax(url, options);
} catch (_error) {
err = _error;
return;
}
$.on(req, 'load', function(e) {
var _i, _len, _ref;
_ref = this.callbacks;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
cb = _ref[_i];
cb.call(this, e);
}
this.evt = e;
return delete this.callbacks;
});
$.on(req, 'abort error', rm);
req.callbacks = [cb];
return reqs[url] = req;
};
@ -4377,6 +4376,8 @@
})) {
return $.cache(url, function() {
return Get.archivedPost(this, boardID, postID, root, context);
}, {
withCredentials: url.archive.withCredentials
});
}
},
@ -4409,6 +4410,8 @@
})) {
$.cache(url, function() {
return Get.archivedPost(this, boardID, postID, root, context);
}, {
withCredentials: url.archive.withCredentials
});
} else {
$.addClass(root, 'warning');
@ -4430,6 +4433,8 @@
})) {
$.cache(url, function() {
return Get.archivedPost(this, boardID, postID, root, context);
}, {
withCredentials: url.archive.withCredentials
});
} else {
$.addClass(root, 'warning');
@ -5734,21 +5739,15 @@
},
menu: {
init: function() {
var apply, hide, hideStubLink, makeStub, show;
var apply, div, hideStubLink, makeStub;
if (g.VIEW !== 'index' || !Conf['Menu'] || !Conf['Thread Hiding Link']) {
return;
}
hide = $.el('div', {
div = $.el('div', {
className: 'hide-thread-link',
textContent: 'Hide thread'
});
show = $.el('a', {
className: 'show-thread-link',
textContent: 'Show thread',
href: 'javascript:;'
});
$.on(show, 'click', ThreadHiding.menu.show);
apply = $.el('a', {
textContent: 'Apply',
href: 'javascript:;'
@ -5757,14 +5756,9 @@
makeStub = $.el('label', {
innerHTML: "<input type=checkbox " + (Conf['Stubs'] ? 'checked' : '') + "> Make stub"
});
hideStubLink = $.el('a', {
textContent: 'Hide stub',
href: 'javascript:;'
});
$.on(hideStubLink, 'click', ThreadHiding.menu.hideStub);
$.event('AddMenuEntry', {
type: 'post',
el: hide,
el: div,
order: 20,
open: function(_arg) {
var isReply, thread;
@ -5784,9 +5778,17 @@
}
]
});
div = $.el('a', {
className: 'show-thread-link',
textContent: 'Show thread',
href: 'javascript:;'
});
$.on(show, 'click', ThreadHiding.menu.show);
$.event('AddMenuEntry', {
type: 'post',
el: show,
type: 'post'
});
({
el: div,
order: 20,
open: function(_arg) {
var isReply, thread;
@ -5799,6 +5801,11 @@
return true;
}
});
hideStubLink = $.el('a', {
textContent: 'Hide stub',
href: 'javascript:;'
});
$.on(hideStubLink, 'click', ThreadHiding.menu.hideStub);
return $.event('AddMenuEntry', {
type: 'post',
el: hideStubLink,
@ -10513,6 +10520,7 @@
domain: 'beta.foolz.us',
http: true,
https: true,
withCredentials: true,
software: 'foolfuuka',
boards: ['a', 'co', 'gd', 'h', 'jp', 'm', 'mlp', 'q', 'sp', 'tg', 'tv', 'u', 'v', 'vg', 'vp', 'vr', 'wsg'],
files: ['a', 'gd', 'h', 'jp', 'm', 'q', 'tg', 'u', 'vg', 'vp', 'vr', 'wsg']
@ -10605,14 +10613,16 @@
return "" + (Redirect.protocol(archive)) + archive.domain + "/" + path;
},
post: function(archive, _arg) {
var boardID, postID, protocol;
var URL, boardID, postID, protocol;
boardID = _arg.boardID, postID = _arg.postID;
protocol = Redirect.protocol(archive);
if (['Foolz', 'NSFW Foolz'].contains(archive.name)) {
protocol = 'https://';
}
return "" + protocol + archive.domain + "/_/api/chan/post/?board=" + boardID + "&num=" + postID;
URL = new String("" + protocol + archive.domain + "/_/api/chan/post/?board=" + boardID + "&num=" + postID);
URL.archive = archive;
return URL;
},
file: function(archive, _arg) {
var boardID, filename;
@ -12399,6 +12409,27 @@
}
};
Dice = {
init: function() {
if (g.BOARD.ID !== 'tg' || g.VIEW === 'catalog' || !Conf['Show Dice Roll']) {
return;
}
return Post.prototype.callbacks.push({
name: 'Show Dice Roll',
cb: this.node
});
},
node: function() {
var dicestats, roll, _ref;
if (this.isClone || !(dicestats = (_ref = this.info.email) != null ? _ref.match(/dice[+\s](\d+)d(\d+)/) : void 0)) {
return;
}
roll = $('b', this.nodes.comment).firstChild;
return roll.data = "Rolled " + dicestats[1] + "d" + dicestats[2] + " and got " + (roll.data.slice(7));
}
};
ExpandComment = {
init: function() {
if (g.VIEW !== 'index' || !Conf['Comment Expansion']) {
@ -13491,7 +13522,7 @@
return Time.zeroPad(this.getSeconds());
},
y: function() {
return this.getFullYear() % 100;
return this.getFullYear().toString().slice(2);
},
Y: function() {
return this.getFullYear();
@ -14853,7 +14884,8 @@
'Thread Stats': ThreadStats,
'Thread Watcher': ThreadWatcher,
'Index Navigation': Nav,
'Keybinds': Keybinds
'Keybinds': Keybinds,
'Show Dice Roll': Dice
});
$.on(d, 'AddCallback', Main.addCallback);
return $.ready(Main.initReady);

View File

@ -97,7 +97,7 @@
'use strict';
(function() {
var $, $$, Anonymize, ArchiveLink, Banner, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DataBoards, DeleteLink, DownloadLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Fourchan, Get, GlobalMessage, Header, IDColor, ImageExpand, ImageHover, ImageLoader, JSColor, Keybinds, Linkify, Main, MascotTools, Mascots, Menu, Nav, Notification, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Rice, Sauce, Settings, Style, ThemeTools, Themes, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, editMascot, editTheme, g, userNavigation,
var $, $$, Anonymize, ArchiveLink, Banner, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DataBoards, DeleteLink, Dice, DownloadLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Fourchan, Get, GlobalMessage, Header, IDColor, ImageExpand, ImageHover, ImageLoader, JSColor, Keybinds, Linkify, Main, MascotTools, Mascots, Menu, Nav, Notification, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Rice, Sauce, Settings, Style, ThemeTools, Themes, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, editMascot, editTheme, g, userNavigation,
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
__slice = [].slice,
__hasProp = {}.hasOwnProperty,
@ -119,6 +119,7 @@
'Thread Expansion': [true, 'Add buttons to expand threads.'],
'Index Navigation': [false, 'Add buttons to navigate between threads.'],
'Reply Navigation': [false, 'Add buttons to navigate to top / bottom of thread.'],
'Show Dice Roll': [true, 'Show dice that were entered into the email field.'],
'Color User IDs': [false, 'Assign unique colors to user IDs on boards that use them'],
'Remove Spoilers': [false, 'Remove all spoilers in text.'],
'Reveal Spoilers': [false, 'Indicate spoilers if Remove Spoilers is enabled, or make the text appear hovered if Remove Spoiler is disabled.']
@ -2783,7 +2784,7 @@
var reqs;
reqs = {};
return function(url, cb) {
return function(url, cb, options) {
var err, req, rm;
if (req = reqs[url]) {
@ -2798,25 +2799,23 @@
return delete reqs[url];
};
try {
req = $.ajax(url, {
onload: function(e) {
var _i, _len, _ref;
_ref = this.callbacks;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
cb = _ref[_i];
cb.call(this, e);
}
this.evt = e;
return delete this.callbacks;
},
onabort: rm,
onerror: rm
});
req = $.ajax(url, options);
} catch (_error) {
err = _error;
return;
}
$.on(req, 'load', function(e) {
var _i, _len, _ref;
_ref = this.callbacks;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
cb = _ref[_i];
cb.call(this, e);
}
this.evt = e;
return delete this.callbacks;
});
$.on(req, 'abort error', rm);
req.callbacks = [cb];
return reqs[url] = req;
};
@ -4391,6 +4390,8 @@
})) {
return $.cache(url, function() {
return Get.archivedPost(this, boardID, postID, root, context);
}, {
withCredentials: url.archive.withCredentials
});
}
},
@ -4423,6 +4424,8 @@
})) {
$.cache(url, function() {
return Get.archivedPost(this, boardID, postID, root, context);
}, {
withCredentials: url.archive.withCredentials
});
} else {
$.addClass(root, 'warning');
@ -4444,6 +4447,8 @@
})) {
$.cache(url, function() {
return Get.archivedPost(this, boardID, postID, root, context);
}, {
withCredentials: url.archive.withCredentials
});
} else {
$.addClass(root, 'warning');
@ -5741,21 +5746,15 @@
},
menu: {
init: function() {
var apply, hide, hideStubLink, makeStub, show;
var apply, div, hideStubLink, makeStub;
if (g.VIEW !== 'index' || !Conf['Menu'] || !Conf['Thread Hiding Link']) {
return;
}
hide = $.el('div', {
div = $.el('div', {
className: 'hide-thread-link',
textContent: 'Hide thread'
});
show = $.el('a', {
className: 'show-thread-link',
textContent: 'Show thread',
href: 'javascript:;'
});
$.on(show, 'click', ThreadHiding.menu.show);
apply = $.el('a', {
textContent: 'Apply',
href: 'javascript:;'
@ -5764,14 +5763,9 @@
makeStub = $.el('label', {
innerHTML: "<input type=checkbox " + (Conf['Stubs'] ? 'checked' : '') + "> Make stub"
});
hideStubLink = $.el('a', {
textContent: 'Hide stub',
href: 'javascript:;'
});
$.on(hideStubLink, 'click', ThreadHiding.menu.hideStub);
$.event('AddMenuEntry', {
type: 'post',
el: hide,
el: div,
order: 20,
open: function(_arg) {
var isReply, thread;
@ -5791,9 +5785,17 @@
}
]
});
div = $.el('a', {
className: 'show-thread-link',
textContent: 'Show thread',
href: 'javascript:;'
});
$.on(show, 'click', ThreadHiding.menu.show);
$.event('AddMenuEntry', {
type: 'post',
el: show,
type: 'post'
});
({
el: div,
order: 20,
open: function(_arg) {
var isReply, thread;
@ -5806,6 +5808,11 @@
return true;
}
});
hideStubLink = $.el('a', {
textContent: 'Hide stub',
href: 'javascript:;'
});
$.on(hideStubLink, 'click', ThreadHiding.menu.hideStub);
return $.event('AddMenuEntry', {
type: 'post',
el: hideStubLink,
@ -10501,6 +10508,7 @@
domain: 'beta.foolz.us',
http: true,
https: true,
withCredentials: true,
software: 'foolfuuka',
boards: ['a', 'co', 'gd', 'h', 'jp', 'm', 'mlp', 'q', 'sp', 'tg', 'tv', 'u', 'v', 'vg', 'vp', 'vr', 'wsg'],
files: ['a', 'gd', 'h', 'jp', 'm', 'q', 'tg', 'u', 'vg', 'vp', 'vr', 'wsg']
@ -10593,14 +10601,16 @@
return "" + (Redirect.protocol(archive)) + archive.domain + "/" + path;
},
post: function(archive, _arg) {
var boardID, postID, protocol;
var URL, boardID, postID, protocol;
boardID = _arg.boardID, postID = _arg.postID;
protocol = Redirect.protocol(archive);
if (['Foolz', 'NSFW Foolz'].contains(archive.name)) {
protocol = 'https://';
}
return "" + protocol + archive.domain + "/_/api/chan/post/?board=" + boardID + "&num=" + postID;
URL = new String("" + protocol + archive.domain + "/_/api/chan/post/?board=" + boardID + "&num=" + postID);
URL.archive = archive;
return URL;
},
file: function(archive, _arg) {
var boardID, filename;
@ -12387,6 +12397,27 @@
}
};
Dice = {
init: function() {
if (g.BOARD.ID !== 'tg' || g.VIEW === 'catalog' || !Conf['Show Dice Roll']) {
return;
}
return Post.prototype.callbacks.push({
name: 'Show Dice Roll',
cb: this.node
});
},
node: function() {
var dicestats, roll, _ref;
if (this.isClone || !(dicestats = (_ref = this.info.email) != null ? _ref.match(/dice[+\s](\d+)d(\d+)/) : void 0)) {
return;
}
roll = $('b', this.nodes.comment).firstChild;
return roll.data = "Rolled " + dicestats[1] + "d" + dicestats[2] + " and got " + (roll.data.slice(7));
}
};
ExpandComment = {
init: function() {
if (g.VIEW !== 'index' || !Conf['Comment Expansion']) {
@ -13479,7 +13510,7 @@
return Time.zeroPad(this.getSeconds());
},
y: function() {
return this.getFullYear() % 100;
return this.getFullYear().toString().slice(2);
},
Y: function() {
return this.getFullYear();
@ -14833,7 +14864,8 @@
'Thread Stats': ThreadStats,
'Thread Watcher': ThreadWatcher,
'Index Navigation': Nav,
'Keybinds': Keybinds
'Keybinds': Keybinds,
'Show Dice Roll': Dice
});
$.on(d, 'AddCallback', Main.addCallback);
return $.ready(Main.initReady);

View File

@ -103,6 +103,7 @@
"domain": "beta.foolz.us",
"http": true,
"https": true,
"withCredentials": true,
"software": "foolfuuka",
"boards": ["a", "co", "gd", "h", "jp", "m", "mlp", "q", "sp", "tg", "tv", "u", "v", "vg", "vp", "vr", "wsg"],
"files": ["a", "gd", "h", "jp", "m", "q", "tg", "u", "vg", "vp", "vr", "wsg"]

View File

@ -56,7 +56,8 @@ Redirect =
'Foolz Beta':
domain: 'beta.foolz.us'
http: true
https: true,
https: true
withCredentials: true
software: 'foolfuuka'
boards: ['a', 'co', 'gd', 'h', 'jp', 'm', 'mlp', 'q', 'sp', 'tg', 'tv', 'u', 'v', 'vg', 'vp', 'vr', 'wsg'],
files: ['a', 'gd', 'h', 'jp', 'm', 'q', 'tg', 'u', 'vg', 'vp', 'vr', 'wsg']
@ -150,7 +151,9 @@ Redirect =
# Remove necessary HTTPS procotol in September 2013.
if ['Foolz', 'NSFW Foolz'].contains archive.name
protocol = 'https://'
"#{protocol}#{archive.domain}/_/api/chan/post/?board=#{boardID}&num=#{postID}"
URL = new String "#{protocol}#{archive.domain}/_/api/chan/post/?board=#{boardID}&num=#{postID}"
URL.archive = archive
URL
file: (archive, {boardID, filename}) ->
"#{Redirect.protocol archive}#{archive.domain}/#{boardID}/full_image/#{filename}"

View File

@ -17,7 +17,7 @@ PostHiding =
PostHiding.hide @, data.makeStub, data.hideRecursively
else
Recursive.apply PostHiding.hide, @, data.makeStub, true
Recursive.add PostHiding.hide, @, data.makeStub, true
Recursive.add PostHiding.hide, @, data.makeStub, true
return unless Conf['Reply Hiding Buttons']
$.add $('.postInfo', @nodes.post), PostHiding.makeButton @, 'hide'
@ -161,7 +161,6 @@ PostHiding =
toggle: ->
post = Get.postFromNode @
PostHiding[(if post.isHidden then 'show' else 'hide')] post
PostHiding.saveHiddenState post, post.isHidden
@ -204,7 +203,7 @@ PostHiding =
post.isHidden = false
if showRecursively
Recursive.apply PostHiding.show, post, true
Recursive.rm PostHiding.hide, post
Recursive.rm PostHiding.hide, post
for quotelink in Get.allQuotelinksLinkingTo post
$.rmClass quotelink, 'filtered'
return

View File

@ -59,16 +59,10 @@ ThreadHiding =
init: ->
return if g.VIEW isnt 'index' or !Conf['Menu'] or !Conf['Thread Hiding Link']
hide = $.el 'div',
div = $.el 'div',
className: 'hide-thread-link'
textContent: 'Hide thread'
show = $.el 'a',
className: 'show-thread-link'
textContent: 'Show thread'
href: 'javascript:;'
$.on show, 'click', ThreadHiding.menu.show
apply = $.el 'a',
textContent: 'Apply'
href: 'javascript:;'
@ -77,14 +71,9 @@ ThreadHiding =
makeStub = $.el 'label',
innerHTML: "<input type=checkbox #{if Conf['Stubs'] then 'checked' else ''}> Make stub"
hideStubLink = $.el 'a',
textContent: 'Hide stub'
href: 'javascript:;'
$.on hideStubLink, 'click', ThreadHiding.menu.hideStub
$.event 'AddMenuEntry',
type: 'post'
el: hide
el: div
order: 20
open: ({thread, isReply}) ->
if isReply or thread.isHidden
@ -93,9 +82,15 @@ ThreadHiding =
true
subEntries: [el: apply; el: makeStub]
div = $.el 'a',
className: 'show-thread-link'
textContent: 'Show thread'
href: 'javascript:;'
$.on show, 'click', ThreadHiding.menu.show
$.event 'AddMenuEntry',
type: 'post'
el: show
type: 'post'
el: div
order: 20
open: ({thread, isReply}) ->
if isReply or !thread.isHidden
@ -103,6 +98,11 @@ ThreadHiding =
ThreadHiding.menu.thread = thread
true
hideStubLink = $.el 'a',
textContent: 'Hide stub'
href: 'javascript:;'
$.on hideStubLink, 'click', ThreadHiding.menu.hideStub
$.event 'AddMenuEntry',
type: 'post'
el: hideStubLink

View File

@ -49,6 +49,10 @@ Config =
false
'Add buttons to navigate to top / bottom of thread.'
]
'Show Dice Roll': [
true
'Show dice that were entered into the email field.'
]
<% if (type !== 'crx') { %>
'Check for Updates': [
true

View File

@ -71,8 +71,10 @@ Get =
$.cache "//api.4chan.org/#{boardID}/res/#{threadID}.json", ->
Get.fetchedPost @, boardID, threadID, postID, root, context
else if url = Redirect.to 'post', {boardID, postID}
$.cache url, ->
Get.archivedPost @, boardID, postID, root, context
$.cache url,
-> Get.archivedPost @, boardID, postID, root, context
,
withCredentials: url.archive.withCredentials
insert: (post, root, context) ->
# Stop here if the container has been removed while loading.
return unless root.parentNode
@ -97,8 +99,10 @@ Get =
unless [200, 304].contains status
# The thread can die by the time we check a quote.
if url = Redirect.to 'post', {boardID, postID}
$.cache url, ->
Get.archivedPost @, boardID, postID, root, context
$.cache url,
-> Get.archivedPost @, boardID, postID, root, context
,
withCredentials: url.archive.withCredentials
else
$.addClass root, 'warning'
root.textContent =
@ -115,8 +119,10 @@ Get =
if post.no > postID
# The post can be deleted by the time we check a quote.
if url = Redirect.to 'post', {boardID, postID}
$.cache url, ->
Get.archivedPost @, boardID, postID, root, context
$.cache url,
-> Get.archivedPost @, boardID, postID, root, context
,
withCredentials: url.archive.withCredentials
else
$.addClass root, 'warning'
root.textContent = "Post No.#{postID} was not found."
@ -228,4 +234,4 @@ Get =
when '[banned]'
'<b style="color: red;">'
when '[/banned]'
'</b>'
'</b>'

View File

@ -165,6 +165,7 @@ Main =
'Thread Watcher': ThreadWatcher
'Index Navigation': Nav
'Keybinds': Keybinds
'Show Dice Roll': Dice
# c.timeEnd 'All initializations'

View File

@ -69,7 +69,7 @@ $.ajax = (url, options, extra={}) ->
$.cache = do ->
reqs = {}
(url, cb) ->
(url, cb, options) ->
if req = reqs[url]
if req.readyState is 4
cb.call req, req.evt
@ -78,15 +78,14 @@ $.cache = do ->
return
rm = -> delete reqs[url]
try
req = $.ajax url,
onload: (e) ->
cb.call @, e for cb in @callbacks
@evt = e
delete @callbacks
onabort: rm
onerror: rm
req = $.ajax url, options
catch err
return
$.on req, 'load', (e) ->
cb.call @, e for cb in @callbacks
@evt = e
delete @callbacks
$.on req, 'abort error', rm
req.callbacks = [cb]
reqs[url] = req

View File

@ -27,4 +27,4 @@ Menu = do ->
toggle: (e) ->
Menu.menu.toggle e, @, Get.postFromNode @

View File

@ -0,0 +1,11 @@
Dice =
init: ->
return if g.BOARD.ID isnt 'tg' or g.VIEW is 'catalog' or !Conf['Show Dice Roll']
Post::callbacks.push
name: 'Show Dice Roll'
cb: @node
node: ->
return if @isClone or not dicestats = @info.email?.match /dice[+\s](\d+)d(\d+)/
# Use the text node directly, as the <b> has two <br>.
roll = $('b', @nodes.comment).firstChild
roll.data = "Rolled #{dicestats[1]}d#{dicestats[2]} and got #{roll.data.slice 7}"

View File

@ -56,5 +56,6 @@ Time =
p: -> if @getHours() < 12 then 'AM' else 'PM'
P: -> if @getHours() < 12 then 'am' else 'pm'
S: -> Time.zeroPad @getSeconds()
y: -> @getFullYear() % 100
Y: -> @getFullYear()
y: -> @getFullYear().toString()[2..]
Y: -> @getFullYear()