Merge branch 'v3'

Conflicts:
	CHANGELOG.md
	LICENSE
	builds/crx/script.js
	src/General/Config.coffee
	src/Images/FappeTyme.coffee
	src/Linkification/Linkify.coffee
This commit is contained in:
Zixaphir 2013-12-16 14:01:47 -07:00
commit e156cc8e9c
16 changed files with 419 additions and 13162 deletions

View File

@ -1,11 +1,14 @@
### v2.6.4
*2013-12-06*
**MayhemYDG**:
- More Index Improvements:
- New setting: `Anchor Hidden Threads`, enabled by default. Hidden threads will be moved at the end of the index to fill the first pages.
- New setting: `Refreshed Navigation`, disabled by default. When enabled, navigating through pages will refresh the index.
- The last index refresh timer will now indicate the last time the index changed from 4chan's side, instead of the last time you refreshed the index.
### v2.6.3
*2013-11-27*
**noface**:
- Strawpoll.me embedding support (as usual, only works on HTTP 4chan due to lack of HTTPS)
### v2.6.2
*2013-11-27*
**Zixaphir**:
- FappeTyme and WerkTyme now persist across sessions.
### v2.6.1
*2013-11-27*
@ -22,7 +25,7 @@
- You cannot post an image reply immediately after a non-image reply anymore.
- **New option**: `Auto-hide header on scroll`.
- Added support for `4cdn.org`.
- More index navigation improvements:
- Index navigation improvements:
- Searching in the index is now possible and will show matched OPs by:
<ul>
<li> comment
@ -40,8 +43,9 @@
</ul>
- The elapsed time since the last index refresh is now indicated at the top of the index.
- New setting: `Show replies`, enabled by default. Disable it to only show OPs in the index.
- The index refreshing notification will now only appear on initial page load with slow connections.
- Index navigation improvements:
- New setting: `Anchor Hidden Threads`, enabled by default. Hidden threads will be moved at the end of the index to fill the first pages.
- New setting: `Refreshed Navigation`, disabled by default. When enabled, navigating through pages will refresh the index.
- The last index refresh timer will now indicate the last time the index changed from 4chan's side, instead of the last time you refreshed the index.
- You can now refresh the index page you are on with the refresh shortcut in the header bar or the same keybind for refreshing threads.
- You can now switch between paged and all-threads index modes via the "Index Navigation" header sub-menu:<br>
![index navigation](img/changelog/3.12.0/0.png)
@ -54,6 +58,7 @@
<li> File count
</ul>
- Navigating across index pages is now instantaneous.
- The index refreshing notification will now only appear on initial page load with slow connections.
- Added a keybind to open the catalog search field on index pages.
- Minor cooldown fix:
- You cannot post an image reply immediately after a non-image reply anymore.

View File

@ -1,5 +1,5 @@
/*
* appchan x - Version 2.6.4 - 2013-12-06
* appchan x - Version 2.6.4 - 2013-12-16
*
* Licensed under the MIT license.
* https://github.com/zixaphir/appchan-x/blob/master/LICENSE

View File

@ -1,21 +0,0 @@
// ==UserScript==
// @name 4chan X
// @version 1.2.43
// @minGMVer 1.12
// @minFFVer 22
// @namespace 4chan-X
// @description Cross-browser userscript for maximum lurking on 4chan.
// @license MIT; https://github.com/seaweedchan/4chan-x/blob/master/LICENSE
// @match *://boards.4chan.org/*
// @match *://sys.4chan.org/*
// @match *://a.4cdn.org/*
// @match *://i.4cdn.org/*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue
// @grant GM_openInTab
// @run-at document-start
// @updateURL https://github.com/seaweedchan/4chan-x/raw/stable/builds/4chan-X.meta.js
// @downloadURL https://github.com/seaweedchan/4chan-x/raw/stable/builds/4chan-X.user.js
// @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwAgMAAAAqbBEUAAAACVBMVEUAAGcAAABmzDNZt9VtAAAAAXRSTlMAQObYZgAAAHFJREFUKFOt0LENACEIBdBv4Qju4wgWanEj3D6OcIVMKaitYHEU/jwTCQj8W75kiVCSBvdQ5/AvfVHBin11BgdRq3ysBgfwBDRrj3MCIA+oAQaku/Q1cNctrAmyDl577tOThYt/Y1RBM4DgOHzM0HFTAyLukH/cmRnqAAAAAElFTkSuQmCC
// ==/UserScript==

File diff suppressed because one or more lines are too long

View File

@ -22,7 +22,7 @@
// ==/UserScript==
/*
* appchan x - Version 2.6.4 - 2013-12-06
* appchan x - Version 2.6.4 - 2013-12-16
*
* Licensed under the MIT license.
* https://github.com/zixaphir/appchan-x/blob/master/LICENSE
@ -347,11 +347,17 @@
MD5: ''
},
sauces: "https://www.google.com/searchbyimage?image_url=%TURL\nhttp://iqdb.org/?url=%TURL\n#//tineye.com/search?url=%TURL\n#http://saucenao.com/search.php?url=%TURL\n#http://3d.iqdb.org/?url=%TURL\n#http://regex.info/exif.cgi?imgurl=%URL\n# uploaders:\n#http://imgur.com/upload?url=%URL;text:Upload to imgur\n#http://ompldr.org/upload?url1=%URL;text:Upload to ompldr\n# \"View Same\" in archives:\n#//archive.foolz.us/_/search/image/%MD5/;text:View same on foolz\n#//archive.foolz.us/%board/search/image/%MD5/;text:View same on foolz /%board/\n#//archive.installgentoo.net/%board/image/%MD5;text:View same on installgentoo /%board/",
FappeT: {
fappe: false,
werk: true
},
'Custom CSS': false,
Index: {
'Index Mode': 'paged',
'Index Sort': 'bump',
'Show Replies': true
'Show Replies': true,
'Anchor Hidden Threads': true,
'Refreshed Navigation': false
},
Header: {
'Fixed Header': true,
@ -4329,7 +4335,7 @@
Index = {
init: function() {
var input, label, modeEntry, repliesEntry, sortEntry, _i, _j, _len, _len1, _ref, _ref1;
var anchorEntry, input, label, modeEntry, name, refNavEntry, repliesEntry, sortEntry, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2;
if (g.VIEW !== 'index' || g.BOARD.ID === 'f') {
return;
@ -4407,17 +4413,40 @@
innerHTML: '<input type=checkbox name="Show Replies"> Show replies'
})
};
input = repliesEntry.el.firstChild;
input.checked = Conf['Show Replies'];
$.on(input, 'change', $.cb.checked);
$.on(input, 'change', this.cb.replies);
anchorEntry = {
el: $.el('label', {
innerHTML: '<input type=checkbox name="Anchor Hidden Threads"> Anchor hidden threads',
title: 'Move hidden threads at the end of the index.'
})
};
refNavEntry = {
el: $.el('label', {
innerHTML: '<input type=checkbox name="Refreshed Navigation"> Refreshed navigation',
title: 'Refresh index when navigating through pages.'
})
};
_ref2 = [repliesEntry, anchorEntry, refNavEntry];
for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
label = _ref2[_k];
input = label.el.firstChild;
name = input.name;
input.checked = Conf[name];
$.on(input, 'change', $.cb.checked);
switch (name) {
case 'Show Replies':
$.on(input, 'change', this.cb.replies);
break;
case 'Anchor Hidden Threads':
$.on(input, 'change', this.cb.sort);
}
}
$.event('AddMenuEntry', {
type: 'header',
el: $.el('span', {
textContent: 'Index Navigation'
}),
order: 90,
subEntries: [modeEntry, sortEntry, repliesEntry]
subEntries: [modeEntry, sortEntry, repliesEntry, anchorEntry, refNavEntry]
});
$.addClass(doc, 'index-loading');
this.update();
@ -4442,14 +4471,14 @@
return $.asap((function() {
return $('.board', doc) || d.readyState !== 'loading';
}), function() {
var board, navLink, _k, _len2, _ref2;
var board, navLink, _l, _len3, _ref3;
board = $('.board');
$.replace(board, Index.root);
d.implementation.createDocument(null, null, null).appendChild(board);
_ref2 = $$('.navLinks');
for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
navLink = _ref2[_k];
_ref3 = $$('.navLinks');
for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {
navLink = _ref3[_l];
$.rm(navLink);
}
$.after($.x('child::form/preceding-sibling::hr[1]'), Index.navLinks);
@ -4503,7 +4532,7 @@
return;
}
e.preventDefault();
return Index.pageNav(+a.pathname.split('/')[2]);
return Index.userPageNav(+a.pathname.split('/')[2]);
}
},
scrollToIndex: function() {
@ -4512,6 +4541,13 @@
getCurrentPage: function() {
return +window.location.pathname.split('/')[2];
},
userPageNav: function(pageNum) {
if (Conf['Refreshed Navigation'] && Conf['Index Mode'] === 'paged') {
return Index.update(pageNum);
} else {
return Index.pageNav(pageNum);
}
},
pageNav: function(pageNum) {
if (Index.currentPage === pageNum) {
return;
@ -4586,8 +4622,8 @@
$.before(a, strong);
return $.add(strong, a);
},
update: function() {
var now, _ref, _ref1;
update: function(pageNum) {
var now, onload, _ref, _ref1;
if (!navigator.onLine) {
return;
@ -4611,15 +4647,21 @@
}), 5 * $.SECOND - (Date.now() - now));
});
}
if (typeof pageNum !== 'number') {
pageNum = null;
}
onload = function(e) {
return Index.load(e, pageNum);
};
Index.req = $.ajax("//a.4cdn.org/" + g.BOARD + "/catalog.json", {
onabort: Index.load,
onloadend: Index.load
onabort: onload,
onloadend: onload
}, {
whenModified: true
});
return $.addClass(Index.button, 'fa-spin');
},
load: function(e) {
load: function(e, pageNum) {
var err, notice, req, timeEl;
$.rmClass(Index.button, 'fa-spin');
@ -4633,7 +4675,9 @@
}
try {
if (req.status === 200) {
Index.parse(JSON.parse(req.response));
Index.parse(JSON.parse(req.response), pageNum);
} else if (req.status === 304 && (pageNum != null)) {
Index.pageNav(pageNum);
}
} catch (_error) {
err = _error;
@ -4653,16 +4697,20 @@
setTimeout(notice.close, $.SECOND);
}
timeEl = $('#index-last-refresh', Index.navLinks);
timeEl.dataset.utc = e.timeStamp / 1000;
timeEl.dataset.utc = Date.parse(req.getResponseHeader('Last-Modified'));
RelativeDates.update(timeEl);
return Index.scrollToIndex();
},
parse: function(pages) {
parse: function(pages, pageNum) {
Index.parseThreadList(pages);
Index.buildThreads();
Index.sort();
Index.buildIndex();
Index.buildPagelist();
if (pageNum != null) {
Index.pageNav(pageNum);
return;
}
Index.buildIndex();
return Index.setPage();
},
parseThreadList: function(pages) {
@ -4767,7 +4815,7 @@
return Main.callbackNodes(Post, posts);
},
sort: function() {
var i, offset, sortedThreadIDs, threadID, threadRoot, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3;
var i, sortedThreadIDs, threadID, _i, _len;
switch (Conf['Index Sort']) {
case 'bump':
@ -4814,25 +4862,31 @@
if (Index.isSearching) {
Index.sortedNodes = Index.querySearch(Index.searchInput.value) || Index.sortedNodes;
}
Index.sortOnTop(function(thread) {
return thread.isSticky;
});
if (Conf['Filter']) {
Index.sortOnTop(function(thread) {
return thread.isOnTop;
});
}
if (Conf['Anchor Hidden Threads']) {
return Index.sortOnTop(function(thread) {
return !thread.isHidden;
});
}
},
sortOnTop: function(match) {
var i, offset, threadRoot, _i, _len, _ref, _ref1;
offset = 0;
_ref = Index.sortedNodes;
for (i = _j = 0, _len1 = _ref.length; _j < _len1; i = _j += 2) {
for (i = _i = 0, _len = _ref.length; _i < _len; i = _i += 2) {
threadRoot = _ref[i];
if (Get.threadFromRoot(threadRoot).isSticky) {
if (match(Get.threadFromRoot(threadRoot))) {
(_ref1 = Index.sortedNodes).splice.apply(_ref1, [offset++ * 2, 0].concat(__slice.call(Index.sortedNodes.splice(i, 2))));
}
}
if (!Conf['Filter']) {
return;
}
offset = 0;
_ref2 = Index.sortedNodes;
for (i = _k = 0, _len2 = _ref2.length; _k < _len2; i = _k += 2) {
threadRoot = _ref2[i];
if (Get.threadFromRoot(threadRoot).isOnTop) {
(_ref3 = Index.sortedNodes).splice.apply(_ref3, [offset++ * 2, 0].concat(__slice.call(Index.sortedNodes.splice(i, 2))));
}
}
},
buildIndex: function() {
var nodes, nodesPerPage, pageNum;
@ -5036,7 +5090,7 @@
}
flag = !flagCode ? '' : boardID === 'pol' ? " <img src='" + staticPath + "country/troll/" + (flagCode.toLowerCase()) + ".gif' alt=" + flagCode + " title='" + flagName + "' class=countryFlag>" : " <span title='" + flagName + "' class='flag flag-" + (flagCode.toLowerCase()) + "'></span>";
if (file != null ? file.isDeleted : void 0) {
fileHTML = isOP ? ("<div class=file id=f" + postID + "><div class=fileInfo></div><span class=fileThumb>") + ("<img src='" + staticPath + "filedeleted" + gifIcon + "' alt='File deleted.' class=fileDeleted>") + "</span></div>" : ("<div class=file id=f" + postID + "><span class=fileThumb>") + ("<img src='" + staticPath + "filedeleted-res" + gifIcon + "' alt='File deleted.' class=fileDeletedRes>") + "</span></div>";
fileHTML = isOP ? ("<div class=file id=f" + postID + "><span class=fileThumb>") + ("<img src='" + staticPath + "filedeleted" + gifIcon + "' alt='File deleted.' class=fileDeleted>") + "</span></div>" : ("<div class=file id=f" + postID + "><span class=fileThumb>") + ("<img src='" + staticPath + "filedeleted-res" + gifIcon + "' alt='File deleted.' class=fileDeletedRes>") + "</span></div>";
} else if (file) {
ext = file.name.slice(-3);
if (!file.twidth && !file.theight && ext === 'gif') {
@ -9729,31 +9783,35 @@
FappeTyme = {
init: function() {
var el;
var el, lc, type, _i, _len, _ref;
if (!(Conf['Fappe Tyme'] || Conf['Werk Tyme']) || g.VIEW === 'catalog' || g.BOARD === 'f') {
return;
}
if (Conf['Fappe Tyme']) {
_ref = ["Fappe", "Werk"];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
type = _ref[_i];
if (!Conf["" + type + " Tyme"]) {
continue;
}
lc = type.toLowerCase();
el = $.el('a', {
href: 'javascript:;',
id: 'fappeTyme',
title: 'Fappe Tyme',
id: "" + lc + "Tyme",
title: "" + type + " Tyme",
className: 'a-icon'
});
$.on(el, 'click', FappeTyme.cb.fappe);
Header.addShortcut(el, true);
}
if (Conf['Werk Tyme']) {
el = $.el('a', {
href: 'javascript:;',
id: 'werkTyme',
title: 'Werk Tyme',
className: 'fa',
textContent: '\uf0b1'
});
$.on(el, 'click', FappeTyme.cb.werk);
if (type === 'Werk') {
el.textContent = '\uf0b1';
el.className = 'fa';
}
$.on(el, 'click', FappeTyme.cb.toggle.bind({
name: "" + lc
}));
Header.addShortcut(el, true);
if (Conf[lc]) {
FappeTyme.cb.set(type);
}
}
return Post.callbacks.push({
name: 'Fappe Tyme',
@ -9767,11 +9825,17 @@
return $.addClass(this.nodes.root, "noFile");
},
cb: {
fappe: function() {
return $.toggleClass(doc, 'fappeTyme');
set: function(type) {
FappeTyme[type].checked = Conf[type];
return $["" + (Conf[type] ? 'add' : 'rm') + "Class"](doc, "" + type + "Tyme");
},
werk: function() {
return $.toggleClass(doc, 'werkTyme');
toggle: function() {
Conf[this.name] = !Conf[this.name];
FappeTyme.cb.set(this.name);
return $.cb.checked.call({
name: this.name,
checked: Conf[this.name]
});
}
}
};
@ -12304,8 +12368,8 @@
http: true,
https: true,
software: "foolfuuka",
boards: ["hr", "tg", "tv", "x"],
files: ["hr", "tg", "tv", "x"]
boards: ["hr", "pol", "s4s", "tg", "tv", "x"],
files: ["hr", "pol", "s4s", "tg", "tv", "x"]
},
"Nyafuu": {
domain: "archive.nyafuu.org",
@ -12315,14 +12379,6 @@
boards: ["c", "w", "wg"],
files: ["c", "w", "wg"]
},
"fap archive": {
domain: "fuuka.worldathleticproject.org",
http: true,
https: true,
software: "foolfuuka",
boards: ["adv", "b", "cm", "d", "e", "h", "hc", "lgbt", "pol", "r", "s", "s4s", "soc", "trv", "u", "y"],
files: ["b", "cm", "d", "e", "h", "hc", "pol", "r", "s", "s4s", "soc", "u", "y"]
},
"Install Gentoo": {
domain: "archive.installgentoo.net",
http: false,
@ -12344,7 +12400,7 @@
http: true,
software: "fuuka",
boards: ["an", "fit", "k", "mlp", "r9k", "toy"],
files: ["an", "k", "toy"]
files: ["an", "fit", "k", "r9k", "toy"]
},
"warosu": {
domain: "fuuka.warosu.org",
@ -12354,6 +12410,14 @@
boards: ["3", "cgl", "ck", "fa", "ic", "jp", "lit", "tg", "vr"],
files: ["3", "cgl", "ck", "fa", "ic", "jp", "lit", "tg", "vr"]
},
"Bui's Archive": {
domain: "archive.bui.pm",
http: true,
https: true,
software: "foolfuuka",
boards: ["b"],
files: ["b"]
},
"Foolz Beta": {
domain: "beta.foolz.us",
http: true,
@ -14448,7 +14512,7 @@
if (!this.file || this.isClone) {
return;
}
return this.file.text.innerHTML = FileInfo.funk(FileInfo, this);
return this.file.text.innerHTML = "<span class=file-info>" + (FileInfo.funk(FileInfo, this)) + "</span>";
},
createFunc: function(format) {
var code;
@ -14952,14 +15016,18 @@
Gallery.cb.toggle();
break;
case Conf['fappeTyme']:
FappeTyme.cb.fappe();
FappeTyme.cb.toggle.call({
name: 'fappe'
});
break;
case Conf['werkTyme']:
FappeTyme.cb.werk();
FappeTyme.cb.toggle.call({
name: 'werk'
});
break;
case Conf['Front page']:
if (g.VIEW === 'index') {
Index.pageNav(0);
Index.userPageNav(0);
} else {
window.location = "/" + g.BOARD + "/";
}
@ -15020,7 +15088,7 @@
Keybinds.hl(0, threadRoot);
break;
case Conf['Hide']:
if (g.VIEW === 'index') {
if (ThreadHiding.db) {
ThreadHiding.toggle(thread);
}
break;
@ -15133,7 +15201,7 @@
}
},
hl: function(delta, thread) {
var axe, height, next, postEl, replies, reply, root, _i, _len;
var axis, height, next, postEl, replies, reply, root, _i, _len;
postEl = $('.reply.highlight', thread);
if (!delta) {
@ -15146,8 +15214,8 @@
height = postEl.getBoundingClientRect().height;
if (Header.getTopOf(postEl) >= -height && Header.getBottomOf(postEl) >= -height) {
root = postEl.parentNode;
axe = delta === +1 ? 'following' : 'preceding';
if (!(next = $.x("" + axe + "-sibling::div[contains(@class,'replyContainer')][1]/child::div[contains(@class,'reply')]", root))) {
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);
@ -15236,11 +15304,11 @@
return $('.board');
},
scroll: function(delta) {
var axe, next, thread, top;
var axis, next, thread, top;
thread = Nav.getThread();
axe = delta === +1 ? 'following' : 'preceding';
if (next = $.x("" + axe + "-sibling::div[contains(@class,'thread') and not(@hidden)][1]", thread)) {
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;

View File

@ -1,6 +1,6 @@
// Generated by CoffeeScript
/*
* appchan x - Version 2.6.4 - 2013-12-06
* appchan x - Version 2.6.4 - 2013-12-16
*
* Licensed under the MIT license.
* https://github.com/zixaphir/appchan-x/blob/master/LICENSE
@ -326,11 +326,17 @@
MD5: ''
},
sauces: "https://www.google.com/searchbyimage?image_url=%TURL\nhttp://iqdb.org/?url=%TURL\n#//tineye.com/search?url=%TURL\n#http://saucenao.com/search.php?url=%TURL\n#http://3d.iqdb.org/?url=%TURL\n#http://regex.info/exif.cgi?imgurl=%URL\n# uploaders:\n#http://imgur.com/upload?url=%URL;text:Upload to imgur\n#http://ompldr.org/upload?url1=%URL;text:Upload to ompldr\n# \"View Same\" in archives:\n#//archive.foolz.us/_/search/image/%MD5/;text:View same on foolz\n#//archive.foolz.us/%board/search/image/%MD5/;text:View same on foolz /%board/\n#//archive.installgentoo.net/%board/image/%MD5;text:View same on installgentoo /%board/",
FappeT: {
fappe: false,
werk: true
},
'Custom CSS': false,
Index: {
'Index Mode': 'paged',
'Index Sort': 'bump',
'Show Replies': true
'Show Replies': true,
'Anchor Hidden Threads': true,
'Refreshed Navigation': false
},
Header: {
'Fixed Header': true,
@ -4342,7 +4348,7 @@
Index = {
init: function() {
var input, label, modeEntry, repliesEntry, sortEntry, _i, _j, _len, _len1, _ref, _ref1;
var anchorEntry, input, label, modeEntry, name, refNavEntry, repliesEntry, sortEntry, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2;
if (g.VIEW !== 'index' || g.BOARD.ID === 'f') {
return;
@ -4420,17 +4426,40 @@
innerHTML: '<input type=checkbox name="Show Replies"> Show replies'
})
};
input = repliesEntry.el.firstChild;
input.checked = Conf['Show Replies'];
$.on(input, 'change', $.cb.checked);
$.on(input, 'change', this.cb.replies);
anchorEntry = {
el: $.el('label', {
innerHTML: '<input type=checkbox name="Anchor Hidden Threads"> Anchor hidden threads',
title: 'Move hidden threads at the end of the index.'
})
};
refNavEntry = {
el: $.el('label', {
innerHTML: '<input type=checkbox name="Refreshed Navigation"> Refreshed navigation',
title: 'Refresh index when navigating through pages.'
})
};
_ref2 = [repliesEntry, anchorEntry, refNavEntry];
for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
label = _ref2[_k];
input = label.el.firstChild;
name = input.name;
input.checked = Conf[name];
$.on(input, 'change', $.cb.checked);
switch (name) {
case 'Show Replies':
$.on(input, 'change', this.cb.replies);
break;
case 'Anchor Hidden Threads':
$.on(input, 'change', this.cb.sort);
}
}
$.event('AddMenuEntry', {
type: 'header',
el: $.el('span', {
textContent: 'Index Navigation'
}),
order: 90,
subEntries: [modeEntry, sortEntry, repliesEntry]
subEntries: [modeEntry, sortEntry, repliesEntry, anchorEntry, refNavEntry]
});
$.addClass(doc, 'index-loading');
this.update();
@ -4455,14 +4484,14 @@
return $.asap((function() {
return $('.board', doc) || d.readyState !== 'loading';
}), function() {
var board, navLink, _k, _len2, _ref2;
var board, navLink, _l, _len3, _ref3;
board = $('.board');
$.replace(board, Index.root);
d.implementation.createDocument(null, null, null).appendChild(board);
_ref2 = $$('.navLinks');
for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
navLink = _ref2[_k];
_ref3 = $$('.navLinks');
for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {
navLink = _ref3[_l];
$.rm(navLink);
}
$.after($.x('child::form/preceding-sibling::hr[1]'), Index.navLinks);
@ -4516,7 +4545,7 @@
return;
}
e.preventDefault();
return Index.pageNav(+a.pathname.split('/')[2]);
return Index.userPageNav(+a.pathname.split('/')[2]);
}
},
scrollToIndex: function() {
@ -4525,6 +4554,13 @@
getCurrentPage: function() {
return +window.location.pathname.split('/')[2];
},
userPageNav: function(pageNum) {
if (Conf['Refreshed Navigation'] && Conf['Index Mode'] === 'paged') {
return Index.update(pageNum);
} else {
return Index.pageNav(pageNum);
}
},
pageNav: function(pageNum) {
if (Index.currentPage === pageNum) {
return;
@ -4599,8 +4635,8 @@
$.before(a, strong);
return $.add(strong, a);
},
update: function() {
var now, _ref, _ref1;
update: function(pageNum) {
var now, onload, _ref, _ref1;
if (!navigator.onLine) {
return;
@ -4624,15 +4660,21 @@
}), 5 * $.SECOND - (Date.now() - now));
});
}
if (typeof pageNum !== 'number') {
pageNum = null;
}
onload = function(e) {
return Index.load(e, pageNum);
};
Index.req = $.ajax("//a.4cdn.org/" + g.BOARD + "/catalog.json", {
onabort: Index.load,
onloadend: Index.load
onabort: onload,
onloadend: onload
}, {
whenModified: true
});
return $.addClass(Index.button, 'fa-spin');
},
load: function(e) {
load: function(e, pageNum) {
var err, notice, req, timeEl;
$.rmClass(Index.button, 'fa-spin');
@ -4646,7 +4688,9 @@
}
try {
if (req.status === 200) {
Index.parse(JSON.parse(req.response));
Index.parse(JSON.parse(req.response), pageNum);
} else if (req.status === 304 && (pageNum != null)) {
Index.pageNav(pageNum);
}
} catch (_error) {
err = _error;
@ -4666,16 +4710,20 @@
setTimeout(notice.close, $.SECOND);
}
timeEl = $('#index-last-refresh', Index.navLinks);
timeEl.dataset.utc = e.timeStamp;
timeEl.dataset.utc = Date.parse(req.getResponseHeader('Last-Modified'));
RelativeDates.update(timeEl);
return Index.scrollToIndex();
},
parse: function(pages) {
parse: function(pages, pageNum) {
Index.parseThreadList(pages);
Index.buildThreads();
Index.sort();
Index.buildIndex();
Index.buildPagelist();
if (pageNum != null) {
Index.pageNav(pageNum);
return;
}
Index.buildIndex();
return Index.setPage();
},
parseThreadList: function(pages) {
@ -4780,7 +4828,7 @@
return Main.callbackNodes(Post, posts);
},
sort: function() {
var i, offset, sortedThreadIDs, threadID, threadRoot, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3;
var i, sortedThreadIDs, threadID, _i, _len;
switch (Conf['Index Sort']) {
case 'bump':
@ -4827,25 +4875,31 @@
if (Index.isSearching) {
Index.sortedNodes = Index.querySearch(Index.searchInput.value) || Index.sortedNodes;
}
Index.sortOnTop(function(thread) {
return thread.isSticky;
});
if (Conf['Filter']) {
Index.sortOnTop(function(thread) {
return thread.isOnTop;
});
}
if (Conf['Anchor Hidden Threads']) {
return Index.sortOnTop(function(thread) {
return !thread.isHidden;
});
}
},
sortOnTop: function(match) {
var i, offset, threadRoot, _i, _len, _ref, _ref1;
offset = 0;
_ref = Index.sortedNodes;
for (i = _j = 0, _len1 = _ref.length; _j < _len1; i = _j += 2) {
for (i = _i = 0, _len = _ref.length; _i < _len; i = _i += 2) {
threadRoot = _ref[i];
if (Get.threadFromRoot(threadRoot).isSticky) {
if (match(Get.threadFromRoot(threadRoot))) {
(_ref1 = Index.sortedNodes).splice.apply(_ref1, [offset++ * 2, 0].concat(__slice.call(Index.sortedNodes.splice(i, 2))));
}
}
if (!Conf['Filter']) {
return;
}
offset = 0;
_ref2 = Index.sortedNodes;
for (i = _k = 0, _len2 = _ref2.length; _k < _len2; i = _k += 2) {
threadRoot = _ref2[i];
if (Get.threadFromRoot(threadRoot).isOnTop) {
(_ref3 = Index.sortedNodes).splice.apply(_ref3, [offset++ * 2, 0].concat(__slice.call(Index.sortedNodes.splice(i, 2))));
}
}
},
buildIndex: function() {
var nodes, nodesPerPage, pageNum;
@ -5049,7 +5103,7 @@
}
flag = !flagCode ? '' : boardID === 'pol' ? " <img src='" + staticPath + "country/troll/" + (flagCode.toLowerCase()) + ".gif' alt=" + flagCode + " title='" + flagName + "' class=countryFlag>" : " <span title='" + flagName + "' class='flag flag-" + (flagCode.toLowerCase()) + "'></span>";
if (file != null ? file.isDeleted : void 0) {
fileHTML = isOP ? ("<div class=file id=f" + postID + "><div class=fileInfo></div><span class=fileThumb>") + ("<img src='" + staticPath + "filedeleted" + gifIcon + "' alt='File deleted.' class=fileDeleted>") + "</span></div>" : ("<div class=file id=f" + postID + "><span class=fileThumb>") + ("<img src='" + staticPath + "filedeleted-res" + gifIcon + "' alt='File deleted.' class=fileDeletedRes>") + "</span></div>";
fileHTML = isOP ? ("<div class=file id=f" + postID + "><span class=fileThumb>") + ("<img src='" + staticPath + "filedeleted" + gifIcon + "' alt='File deleted.' class=fileDeleted>") + "</span></div>" : ("<div class=file id=f" + postID + "><span class=fileThumb>") + ("<img src='" + staticPath + "filedeleted-res" + gifIcon + "' alt='File deleted.' class=fileDeletedRes>") + "</span></div>";
} else if (file) {
ext = file.name.slice(-3);
if (!file.twidth && !file.theight && ext === 'gif') {
@ -9715,31 +9769,35 @@
FappeTyme = {
init: function() {
var el;
var el, lc, type, _i, _len, _ref;
if (!(Conf['Fappe Tyme'] || Conf['Werk Tyme']) || g.VIEW === 'catalog' || g.BOARD === 'f') {
return;
}
if (Conf['Fappe Tyme']) {
_ref = ["Fappe", "Werk"];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
type = _ref[_i];
if (!Conf["" + type + " Tyme"]) {
continue;
}
lc = type.toLowerCase();
el = $.el('a', {
href: 'javascript:;',
id: 'fappeTyme',
title: 'Fappe Tyme',
id: "" + lc + "Tyme",
title: "" + type + " Tyme",
className: 'a-icon'
});
$.on(el, 'click', FappeTyme.cb.fappe);
Header.addShortcut(el, true);
}
if (Conf['Werk Tyme']) {
el = $.el('a', {
href: 'javascript:;',
id: 'werkTyme',
title: 'Werk Tyme',
className: 'fa',
textContent: '\uf0b1'
});
$.on(el, 'click', FappeTyme.cb.werk);
if (type === 'Werk') {
el.textContent = '\uf0b1';
el.className = 'fa';
}
$.on(el, 'click', FappeTyme.cb.toggle.bind({
name: "" + lc
}));
Header.addShortcut(el, true);
if (Conf[lc]) {
FappeTyme.cb.set(type);
}
}
return Post.callbacks.push({
name: 'Fappe Tyme',
@ -9753,11 +9811,17 @@
return $.addClass(this.nodes.root, "noFile");
},
cb: {
fappe: function() {
return $.toggleClass(doc, 'fappeTyme');
set: function(type) {
FappeTyme[type].checked = Conf[type];
return $["" + (Conf[type] ? 'add' : 'rm') + "Class"](doc, "" + type + "Tyme");
},
werk: function() {
return $.toggleClass(doc, 'werkTyme');
toggle: function() {
Conf[this.name] = !Conf[this.name];
FappeTyme.cb.set(this.name);
return $.cb.checked.call({
name: this.name,
checked: Conf[this.name]
});
}
}
};
@ -12296,8 +12360,8 @@
http: true,
https: true,
software: "foolfuuka",
boards: ["hr", "tg", "tv", "x"],
files: ["hr", "tg", "tv", "x"]
boards: ["hr", "pol", "s4s", "tg", "tv", "x"],
files: ["hr", "pol", "s4s", "tg", "tv", "x"]
},
"Nyafuu": {
domain: "archive.nyafuu.org",
@ -12307,14 +12371,6 @@
boards: ["c", "w", "wg"],
files: ["c", "w", "wg"]
},
"fap archive": {
domain: "fuuka.worldathleticproject.org",
http: true,
https: true,
software: "foolfuuka",
boards: ["adv", "b", "cm", "d", "e", "h", "hc", "lgbt", "pol", "r", "s", "s4s", "soc", "trv", "u", "y"],
files: ["b", "cm", "d", "e", "h", "hc", "pol", "r", "s", "s4s", "soc", "u", "y"]
},
"Install Gentoo": {
domain: "archive.installgentoo.net",
http: false,
@ -12336,7 +12392,7 @@
http: true,
software: "fuuka",
boards: ["an", "fit", "k", "mlp", "r9k", "toy"],
files: ["an", "k", "toy"]
files: ["an", "fit", "k", "r9k", "toy"]
},
"warosu": {
domain: "fuuka.warosu.org",
@ -12346,6 +12402,14 @@
boards: ["3", "cgl", "ck", "fa", "ic", "jp", "lit", "tg", "vr"],
files: ["3", "cgl", "ck", "fa", "ic", "jp", "lit", "tg", "vr"]
},
"Bui's Archive": {
domain: "archive.bui.pm",
http: true,
https: true,
software: "foolfuuka",
boards: ["b"],
files: ["b"]
},
"Foolz Beta": {
domain: "beta.foolz.us",
http: true,
@ -14440,7 +14504,7 @@
if (!this.file || this.isClone) {
return;
}
return this.file.text.innerHTML = FileInfo.funk(FileInfo, this);
return this.file.text.innerHTML = "<span class=file-info>" + (FileInfo.funk(FileInfo, this)) + "</span>";
},
createFunc: function(format) {
var code;
@ -14944,14 +15008,18 @@
Gallery.cb.toggle();
break;
case Conf['fappeTyme']:
FappeTyme.cb.fappe();
FappeTyme.cb.toggle.call({
name: 'fappe'
});
break;
case Conf['werkTyme']:
FappeTyme.cb.werk();
FappeTyme.cb.toggle.call({
name: 'werk'
});
break;
case Conf['Front page']:
if (g.VIEW === 'index') {
Index.pageNav(0);
Index.userPageNav(0);
} else {
window.location = "/" + g.BOARD + "/";
}
@ -15012,7 +15080,7 @@
Keybinds.hl(0, threadRoot);
break;
case Conf['Hide']:
if (g.VIEW === 'index') {
if (ThreadHiding.db) {
ThreadHiding.toggle(thread);
}
break;
@ -15125,7 +15193,7 @@
}
},
hl: function(delta, thread) {
var axe, height, next, postEl, replies, reply, root, _i, _len;
var axis, height, next, postEl, replies, reply, root, _i, _len;
postEl = $('.reply.highlight', thread);
if (!delta) {
@ -15138,8 +15206,8 @@
height = postEl.getBoundingClientRect().height;
if (Header.getTopOf(postEl) >= -height && Header.getBottomOf(postEl) >= -height) {
root = postEl.parentNode;
axe = delta === +1 ? 'following' : 'preceding';
if (!(next = $.x("" + axe + "-sibling::div[contains(@class,'replyContainer')][1]/child::div[contains(@class,'reply')]", root))) {
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);
@ -15228,11 +15296,11 @@
return $('.board');
},
scroll: function(delta) {
var axe, next, thread, top;
var axis, next, thread, top;
thread = Nav.getThread();
axe = delta === +1 ? 'following' : 'preceding';
if (next = $.x("" + axe + "-sibling::div[contains(@class,'thread') and not(@hidden)][1]", thread)) {
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;

View File

@ -540,8 +540,8 @@ a.hide-announcement {
}
/* File */
.fileText:hover .fntrunc,
.fileText:not(:hover) .fnfull,
.file-info:hover .fntrunc,
.file-info:not(:hover) .fnfull,
.expanded-image > .post > .file > .fileThumb > img[data-md5],
:not(.expanded-image) > .post > .file > .fileThumb > .full-image {
display: none;

View File

@ -51,8 +51,8 @@ Redirect =
http: true
https: true
software: "foolfuuka"
boards: ["hr", "tg", "tv", "x"]
files: ["hr", "tg", "tv", "x"]
boards: ["hr", "pol", "s4s", "tg", "tv", "x"]
files: ["hr", "pol", "s4s", "tg", "tv", "x"]
"Nyafuu":
domain: "archive.nyafuu.org"
@ -62,14 +62,6 @@ Redirect =
boards: ["c", "w", "wg"]
files: ["c", "w", "wg"]
"fap archive":
domain: "fuuka.worldathleticproject.org"
http: true
https: true
software: "foolfuuka"
boards: ["adv", "b", "cm", "d", "e", "h", "hc", "lgbt", "pol", "r", "s", "s4s", "soc", "trv", "u", "y"]
files: ["b", "cm", "d", "e", "h", "hc", "pol", "r", "s", "s4s", "soc", "u", "y"]
"Install Gentoo":
domain: "archive.installgentoo.net"
http: false
@ -91,7 +83,7 @@ Redirect =
http: true
software: "fuuka"
boards: ["an", "fit", "k", "mlp", "r9k", "toy"]
files: ["an", "k", "toy"]
files: ["an", "fit", "k", "r9k", "toy"]
"warosu":
domain: "fuuka.warosu.org"
@ -101,6 +93,14 @@ Redirect =
boards: ["3", "cgl", "ck", "fa", "ic", "jp", "lit", "tg", "vr"]
files: ["3", "cgl", "ck", "fa", "ic", "jp", "lit", "tg", "vr"]
"Bui's Archive":
domain: "archive.bui.pm"
http: true
https: true
software: "foolfuuka"
boards: ["b"]
files: ["b"]
"Foolz Beta":
domain: "beta.foolz.us"
http: true

View File

@ -124,7 +124,7 @@ Build =
if file?.isDeleted
fileHTML = if isOP
"<div class=file id=f#{postID}><div class=fileInfo></div><span class=fileThumb>" +
"<div class=file id=f#{postID}><span class=fileThumb>" +
"<img src='#{staticPath}filedeleted#{gifIcon}' alt='File deleted.' class=fileDeleted>" +
"</span></div>"
else

View File

@ -836,12 +836,18 @@ http://iqdb.org/?url=%TURL
#//archive.installgentoo.net/%board/image/%MD5;text:View same on installgentoo /%board/
"""
FappeT:
fappe: false
werk: true
'Custom CSS': false
Index:
'Index Mode': 'paged'
'Index Sort': 'bump'
'Show Replies': true
'Anchor Hidden Threads': true
'Refreshed Navigation': false
Header:
'Fixed Header': true

View File

@ -38,18 +38,33 @@ Index =
$.on input, 'change', @cb.sort
repliesEntry =
el: $.el 'label', innerHTML: '<input type=checkbox name="Show Replies"> Show replies'
input = repliesEntry.el.firstChild
input.checked = Conf['Show Replies']
$.on input, 'change', $.cb.checked
$.on input, 'change', @cb.replies
el: $.el 'label',
innerHTML: '<input type=checkbox name="Show Replies"> Show replies'
anchorEntry =
el: $.el 'label',
innerHTML: '<input type=checkbox name="Anchor Hidden Threads"> Anchor hidden threads'
title: 'Move hidden threads at the end of the index.'
refNavEntry =
el: $.el 'label',
innerHTML: '<input type=checkbox name="Refreshed Navigation"> Refreshed navigation'
title: 'Refresh index when navigating through pages.'
for label in [repliesEntry, anchorEntry, refNavEntry]
input = label.el.firstChild
{name} = input
input.checked = Conf[name]
$.on input, 'change', $.cb.checked
switch name
when 'Show Replies'
$.on input, 'change', @cb.replies
when 'Anchor Hidden Threads'
$.on input, 'change', @cb.sort
$.event 'AddMenuEntry',
type: 'header'
el: $.el 'span',
textContent: 'Index Navigation'
order: 90
subEntries: [modeEntry, sortEntry, repliesEntry]
subEntries: [modeEntry, sortEntry, repliesEntry, anchorEntry, refNavEntry]
$.addClass doc, 'index-loading'
@update()
@ -111,13 +126,18 @@ Index =
return
return if a.textContent is 'Catalog'
e.preventDefault()
Index.pageNav +a.pathname.split('/')[2]
Index.userPageNav +a.pathname.split('/')[2]
scrollToIndex: ->
Header.scrollToIfNeeded Index.root
getCurrentPage: ->
+window.location.pathname.split('/')[2]
userPageNav: (pageNum) ->
if Conf['Refreshed Navigation'] and Conf['Index Mode'] is 'paged'
Index.update pageNum
else
Index.pageNav pageNum
pageNav: (pageNum) ->
return if Index.currentPage is pageNum
history.pushState null, '', if pageNum is 0 then './' else pageNum
@ -174,7 +194,7 @@ Index =
$.before a, strong
$.add strong, a
update: ->
update: (pageNum) ->
return unless navigator.onLine
Index.req?.abort()
Index.notice?.close()
@ -189,13 +209,15 @@ Index =
return unless Index.req and !Index.notice
Index.notice = new Notice 'info', 'Refreshing index...'
), 5 * $.SECOND - (Date.now() - now)
pageNum = null if typeof pageNum isnt 'number' # event
onload = (e) -> Index.load e, pageNum
Index.req = $.ajax "//a.4cdn.org/#{g.BOARD}/catalog.json",
onabort: Index.load
onloadend: Index.load
onabort: onload
onloadend: onload
,
whenModified: true
$.addClass Index.button, 'fa-spin'
load: (e) ->
load: (e, pageNum) ->
$.rmClass Index.button, 'fa-spin'
{req, notice} = Index
delete Index.req
@ -207,7 +229,10 @@ Index =
return
try
Index.parse JSON.parse req.response if req.status is 200
if req.status is 200
Index.parse JSON.parse(req.response), pageNum
else if req.status is 304 and pageNum?
Index.pageNav pageNum
catch err
c.error 'Index failure:', err.stack
# network error or non-JSON content for example.
@ -225,15 +250,18 @@ Index =
setTimeout notice.close, $.SECOND
timeEl = $ '#index-last-refresh', Index.navLinks
timeEl.dataset.utc = e.timeStamp <% if (type === 'userscript') { %>/ 1000<% } %>
timeEl.dataset.utc = Date.parse req.getResponseHeader 'Last-Modified'
RelativeDates.update timeEl
Index.scrollToIndex()
parse: (pages) ->
parse: (pages, pageNum) ->
Index.parseThreadList pages
Index.buildThreads()
Index.sort()
Index.buildIndex()
Index.buildPagelist()
if pageNum?
Index.pageNav pageNum
return
Index.buildIndex()
Index.setPage()
parseThreadList: (pages) ->
Index.pagesNum = pages.length
@ -319,15 +347,15 @@ Index =
Index.sortedNodes.push Index.nodes[i], Index.nodes[i + 1]
if Index.isSearching
Index.sortedNodes = Index.querySearch(Index.searchInput.value) or Index.sortedNodes
# Put the sticky threads on top of the index.
# Sticky threads
Index.sortOnTop (thread) -> thread.isSticky
# Highlighted threads
Index.sortOnTop((thread) -> thread.isOnTop) if Conf['Filter']
# Non-hidden threads
Index.sortOnTop((thread) -> !thread.isHidden) if Conf['Anchor Hidden Threads']
sortOnTop: (match) ->
offset = 0
for threadRoot, i in Index.sortedNodes by 2 when Get.threadFromRoot(threadRoot).isSticky
Index.sortedNodes.splice offset++ * 2, 0, Index.sortedNodes.splice(i, 2)...
return unless Conf['Filter']
# Put the highlighted thread & <hr> on top of the index
# while keeping the original order they appear in.
offset = 0
for threadRoot, i in Index.sortedNodes by 2 when Get.threadFromRoot(threadRoot).isOnTop
for threadRoot, i in Index.sortedNodes by 2 when match Get.threadFromRoot threadRoot
Index.sortedNodes.splice offset++ * 2, 0, Index.sortedNodes.splice(i, 2)...
return
buildIndex: ->

View File

@ -150,11 +150,11 @@ a {
.fixed.top-header #header-bar {
border-bottom-width: 1px;
}
.fixed.bottom #header-bar {
.fixed.bottom-header #header-bar {
box-shadow: 0 -1px 2px rgba(0, 0, 0, .15);
border-top-width: 1px;
}
.fixed.bottom #header-bar .menu-button i {
.fixed.bottom-header #header-bar .menu-button i {
border-top: none;
border-bottom: 6px solid;
}
@ -170,7 +170,7 @@ a {
-webkit-transform: translateY(-100%);
transform: translateY(-100%);
}
.fixed.bottom #header-bar.autohide:not(:hover) {
.fixed.bottom-header #header-bar.autohide:not(:hover) {
-webkit-transform: translateY(100%);
transform: translateY(100%);
}
@ -666,10 +666,15 @@ a.hide-announcement {
max-width: 75%;
padding-bottom: 16px;
}
/* Fappe Tyme */
.fappeTyme .thread > .noFile,
.fappeTyme .threadContainer > .noFile {
display: none;
}
/* Werk Tyme */
.werkTyme .post .file {
display: none;
}
/* Index/Reply Navigation */
#navlinks {

View File

@ -2,28 +2,21 @@ FappeTyme =
init: ->
return if !(Conf['Fappe Tyme'] or Conf['Werk Tyme']) or g.VIEW is 'catalog' or g.BOARD is 'f'
if Conf['Fappe Tyme']
for type in ["Fappe", "Werk"] when Conf["#{type} Tyme"]
lc = type.toLowerCase()
el = $.el 'a',
href: 'javascript:;'
id: 'fappeTyme'
title: 'Fappe Tyme'
id: "#{lc}Tyme"
title: "#{type} Tyme"
className: 'a-icon'
if type is 'Werk'
el.textContent = '\uf0b1'
el.className = 'fa'
$.on el, 'click', FappeTyme.cb.fappe
Header.addShortcut el, true
if Conf['Werk Tyme']
el = $.el 'a',
href: 'javascript:;'
id: 'werkTyme'
title: 'Werk Tyme'
className: 'fa'
textContent: '\uf0b1'
$.on el, 'click', FappeTyme.cb.werk
$.on el, 'click', FappeTyme.cb.toggle.bind {name: "#{lc}"}
Header.addShortcut el, true
FappeTyme.cb.set type if Conf[lc]
Post.callbacks.push
name: 'Fappe Tyme'
@ -34,7 +27,11 @@ FappeTyme =
$.addClass @nodes.root, "noFile"
cb:
fappe: ->
$.toggleClass doc, 'fappeTyme'
werk: ->
$.toggleClass doc, 'werkTyme'
set: (type) ->
FappeTyme[type].checked = Conf[type]
$["#{if Conf[type] then 'add' else 'rm'}Class"] doc, "#{type}Tyme"
toggle: ->
Conf[@name] = !Conf[@name]
FappeTyme.cb.set @name
$.cb.checked.call {name: @name, checked: Conf[@name]}

View File

@ -8,7 +8,7 @@ FileInfo =
cb: @node
node: ->
return if !@file or @isClone
@file.text.innerHTML = FileInfo.funk FileInfo, @
@file.text.innerHTML = "<span class=file-info>#{FileInfo.funk FileInfo, @}</span>"
createFunc: (format) ->
code = format.replace /%(.)/g, (s, c) ->
if c of FileInfo.formatters
@ -21,11 +21,10 @@ FileInfo =
return "#{size.toFixed()} Bytes"
i = 1 + ['KB', 'MB'].indexOf unit
size /= 1024 while i--
size =
if unit is 'MB'
Math.round(size * 100) / 100
else
size.toFixed()
size = if unit is 'MB'
Math.round(size * 100) / 100
else
size.toFixed()
"#{size} #{unit}"
escape: (name) ->
name.replace /<|>/g, (c) ->

View File

@ -81,13 +81,13 @@ Keybinds =
when Conf['Open Gallery']
Gallery.cb.toggle()
when Conf['fappeTyme']
FappeTyme.cb.fappe()
FappeTyme.cb.toggle.call {name: 'fappe'}
when Conf['werkTyme']
FappeTyme.cb.werk()
FappeTyme.cb.toggle.call {name: 'werk'}
# Board Navigation
when Conf['Front page']
if g.VIEW is 'index'
Index.pageNav 0
Index.userPageNav 0
else
window.location = "/#{g.BOARD}/"
when Conf['Open front page']
@ -126,7 +126,7 @@ Keybinds =
when Conf['Deselect reply']
Keybinds.hl 0, threadRoot
when Conf['Hide']
ThreadHiding.toggle thread if g.VIEW is 'index'
ThreadHiding.toggle thread if ThreadHiding.db
when Conf['Previous Post Quoting You']
QuoteYou.cb.seek 'preceding'
when Conf['Next Post Quoting You']
@ -223,11 +223,11 @@ Keybinds =
{height} = postEl.getBoundingClientRect()
if Header.getTopOf(postEl) >= -height and Header.getBottomOf(postEl) >= -height # We're at least partially visible
root = postEl.parentNode
axe = if delta is +1
axis = if delta is +1
'following'
else
'preceding'
return unless next = $.x "#{axe}-sibling::div[contains(@class,'replyContainer')][1]/child::div[contains(@class,'reply')]", root
return unless next = $.x "#{axis}-sibling::div[contains(@class,'replyContainer') and not(@hidden) and not(child::div[@class='stub'])][1]/child::div[contains(@class,'reply')]", root
Header.scrollToIfNeeded next, delta is +1
@focus next
$.rmClass postEl, 'highlight'

View File

@ -43,11 +43,11 @@ Nav =
scroll: (delta) ->
thread = Nav.getThread()
axe = if delta is +1
axis = if delta is +1
'following'
else
'preceding'
if next = $.x "#{axe}-sibling::div[contains(@class,'thread') and not(@hidden)][1]", thread
if next = $.x "#{axis}-sibling::div[contains(@class,'thread') and not(@hidden)][1]", thread
# Unless we're not at the beginning of the current thread,
# and thus wanting to move to beginning,
# or we're above the first thread and don't want to skip it.