Add Keybinds.

This commit is contained in:
Nicolas Stepien 2013-02-18 00:17:00 +01:00
parent d546654cf2
commit c77e012a52
5 changed files with 509 additions and 49 deletions

View File

@ -20,7 +20,7 @@
// @icon data:image/gif;base64,R0lGODlhEAAQAKECAAAAAGbMM////////yH5BAEKAAIALAAAAAAQABAAAAIxlI+pq+D9DAgUoFkPDlbs7lGiI2bSVnKglnJMOL6omczxVZK3dH/41AG6Lh7i6qUoAAA7 // @icon data:image/gif;base64,R0lGODlhEAAQAKECAAAAAGbMM////////yH5BAEKAAIALAAAAAAQABAAAAIxlI+pq+D9DAgUoFkPDlbs7lGiI2bSVnKglnJMOL6omczxVZK3dH/41AG6Lh7i6qUoAAA7
// ==/UserScript== // ==/UserScript==
/* 4chan X Alpha - Version 3.0.0 - 2013-02-17 /* 4chan X Alpha - Version 3.0.0 - 2013-02-18
* http://mayhemydg.github.com/4chan-x/ * http://mayhemydg.github.com/4chan-x/
* *
* Copyright (c) 2009-2011 James Campos <james.r.campos@gmail.com> * Copyright (c) 2009-2011 James Campos <james.r.campos@gmail.com>
@ -43,7 +43,7 @@
*/ */
(function() { (function() {
var $, $$, Anonymize, ArchiveLink, AutoGIF, Board, Build, Clone, Conf, Config, DeleteLink, DownloadLink, ExpandComment, ExpandThread, Favicon, FileInfo, Filter, Get, Header, ImageExpand, ImageHover, Main, Menu, Nav, Notification, Polyfill, Post, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, Quotify, Recursive, Redirect, RelativeDates, ReplyHiding, ReportLink, RevealSpoilers, Sauce, Settings, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, d, doc, g, var $, $$, Anonymize, ArchiveLink, AutoGIF, Board, Build, Clone, Conf, Config, DeleteLink, DownloadLink, ExpandComment, ExpandThread, Favicon, FileInfo, Filter, Get, Header, ImageExpand, ImageHover, Keybinds, Main, Menu, Nav, Notification, Polyfill, Post, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, Quotify, Recursive, Redirect, RelativeDates, ReplyHiding, ReportLink, RevealSpoilers, Sauce, Settings, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, d, doc, g,
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
__hasProp = {}.hasOwnProperty, __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; }; __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; };
@ -141,28 +141,29 @@
fileInfo: '%l (%p%s, %r)', fileInfo: '%l (%p%s, %r)',
favicon: 'ferongr', favicon: 'ferongr',
hotkeys: { hotkeys: {
'open QR': ['q', 'Open QR with post number inserted.'], 'Open empty QR': ['q', 'Open QR without post number inserted.'],
'open empty QR': ['Q', 'Open QR without post number inserted.'], 'Open QR': ['Shift+q', 'Open QR with post number inserted.'],
'open options': ['alt+o', 'Open Options.'], 'Open options': ['Alt+o', 'Open Options.'],
'close': ['Esc', 'Close Options or QR.'], 'Close': ['Esc', 'Close Settings, Notifications or QR.'],
'spoiler tags': ['ctrl+s', 'Insert spoiler tags.'], 'Spoiler tags': ['Ctrl+s', 'Insert spoiler tags.'],
'code tags': ['alt+c', 'Insert code tags.'], 'Code tags': ['Alt+c', 'Insert code tags.'],
'submit QR': ['alt+s', 'Submit post.'], 'Submit QR': ['Alt+s', 'Submit post.'],
'watch': ['w', 'Watch thread.'], 'Watch': ['w', 'Watch thread.'],
'update': ['u', 'Update the thread now.'], 'Update': ['u', 'Update the thread now.'],
'expand image': ['E', 'Expand selected image.'], 'Expand image': ['Shift+e', 'Expand selected image.'],
'expand images': ['e', 'Expand all images.'], 'Expand images': ['e', 'Expand all images.'],
'front page': ['0', 'Jump to page 0.'], 'Front page': ['0', 'Jump to page 0.'],
'next page': ['Right', 'Jump to the next page.'], 'Open front page': ['Shift+0', 'Open page 0 in a new tab.'],
'previous page': ['Left', 'Jump to the previous page.'], 'Next page': ['Right', 'Jump to the next page.'],
'next thread': ['Down', 'See next thread.'], 'Previous page': ['Left', 'Jump to the previous page.'],
'previous thread': ['Up', 'See previous thread.'], 'Next thread': ['Down', 'See next thread.'],
'expand thread': ['ctrl+e', 'Expand thread.'], 'Previous thread': ['Up', 'See previous thread.'],
'open thread': ['o', 'Open thread in current tab.'], 'Expand thread': ['Ctrl+e', 'Expand thread.'],
'open thread tab': ['O', 'Open thread in new tab.'], 'Open thread': ['o', 'Open thread in current tab.'],
'next reply': ['j', 'Select next reply.'], 'Open thread tab': ['Shift+o', 'Open thread in new tab.'],
'previous reply': ['k', 'Select previous reply.'], 'Next reply': ['j', 'Select next reply.'],
'hide': ['x', 'Hide thread.'] 'Previous reply': ['k', 'Select previous reply.'],
'Hide': ['x', 'Hide thread.']
}, },
updater: { updater: {
checkbox: { checkbox: {
@ -2233,6 +2234,271 @@
} }
}; };
Keybinds = {
init: function() {
if (g.VIEW === 'catalog' || !Conf['Keybinds']) {
return;
}
$.on(d, 'keydown', Keybinds.keydown);
return $.on(d, '4chanXInitFinished', function() {
var node, _i, _len, _ref, _results;
_ref = $$('[accesskey]');
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
node = _ref[_i];
_results.push(node.removeAttribute('accesskey'));
}
return _results;
});
},
keydown: function(e) {
var form, key, notification, notifications, target, thread, threadRoot, _i, _len, _ref;
if (!(key = Keybinds.keyCode(e))) {
return;
}
target = e.target;
if ((_ref = target.nodeName) === 'INPUT' || _ref === 'TEXTAREA') {
if (!((key === 'Esc') || (/(Alt|Ctrl|Meta)\+/.test(key)))) {
return;
}
}
threadRoot = Nav.getThread();
thread = Get.postFromNode($('.op', threadRoot)).thread;
switch (key) {
case Conf['Open empty QR']:
Keybinds.qr(threadRoot);
break;
case Conf['Open QR']:
Keybinds.qr(threadRoot, true);
break;
case Conf['Open options']:
Settings.open();
break;
case Conf['Close']:
if ($.id('settings')) {
Options.close();
} else if ((notifications = $$('.notification')).length) {
for (_i = 0, _len = notifications.length; _i < _len; _i++) {
notification = notifications[_i];
$('.close', notification).click();
}
} else if (QR.el) {
QR.close();
}
break;
case Conf['Spoiler tags']:
if (target.nodeName !== 'TEXTAREA') {
return;
}
Keybinds.tags('spoiler', target);
break;
case Conf['Code tags']:
if (target.nodeName !== 'TEXTAREA') {
return;
}
Keybinds.tags('code', target);
break;
case Conf['Submit QR']:
if (QR.el && !QR.status()) {
QR.submit();
}
break;
case Conf['Watch']:
ThreadWatcher.toggle(thread);
break;
case Conf['Update']:
ThreadUpdater.update();
break;
case Conf['Expand image']:
Keybinds.img(threadRoot);
break;
case Conf['Expand images']:
Keybinds.img(threadRoot, true);
break;
case Conf['Front page']:
window.location = "/" + g.BOARD + "/0#delform";
break;
case Conf['Open front page']:
$.open(url("/" + g.BOARD + "/#delform"));
break;
case Conf['Next page']:
if (form = $('.next form')) {
window.location = form.action;
}
break;
case Conf['Previous page']:
if (form = $('.prev form')) {
window.location = form.action;
}
break;
case Conf['Next thread']:
if (g.VIEW === 'thread') {
return;
}
Nav.scroll(+1);
break;
case Conf['Previous thread']:
if (g.VIEW === 'thread') {
return;
}
Nav.scroll(-1);
break;
case Conf['Expand thread']:
ExpandThread.toggle(thread);
break;
case Conf['Open thread']:
Keybinds.open(thread);
break;
case Conf['Open thread tab']:
Keybinds.open(thread, true);
break;
case Conf['Next reply']:
Keybinds.hl(+1, threadRoot);
break;
case Conf['Previous reply']:
Keybinds.hl(-1, threadRoot);
break;
case Conf['Hide']:
ThreadHiding.toggle(thread);
break;
default:
return;
}
return e.preventDefault();
},
keyCode: function(e) {
var kc, key;
key = (function() {
switch (kc = e.keyCode) {
case 8:
return '';
case 13:
return 'Enter';
case 27:
return 'Esc';
case 37:
return 'Left';
case 38:
return 'Up';
case 39:
return 'Right';
case 40:
return 'Down';
default:
if ((48 <= kc && kc <= 57) || (65 <= kc && kc <= 90)) {
return String.fromCharCode(kc).toLowerCase();
} else {
return null;
}
}
})();
if (key) {
if (e.altKey) {
key = 'Alt+' + key;
}
if (e.ctrlKey) {
key = 'Ctrl+' + key;
}
if (e.metaKey) {
key = 'Meta+' + key;
}
if (e.shiftKey) {
key = 'Shift+' + key;
}
}
return key;
},
qr: function(thread, quote) {
if (!Conf['Quick Reply']) {
return;
}
QR.open();
if (quote) {
QR.quote.call($('input', $('.post.highlight', thread) || thread));
}
return $('textarea', QR.el).focus();
},
tags: function(tag, ta) {
var range, selEnd, selStart, value;
value = ta.value;
selStart = ta.selectionStart;
selEnd = ta.selectionEnd;
ta.value = value.slice(0, selStart) + ("[" + tag + "]") + value.slice(selStart, selEnd) + ("[/" + tag + "]") + value.slice(selEnd);
range = ("[" + tag + "]").length + selEnd;
ta.setSelectionRange(range, range);
return $.event('input', null, ta);
},
img: function(thread, all) {
var input, post;
if (all) {
input = ImageExpand.expandAllInput;
input.checked = !input.checked;
return ImageExpand.cb.all.call(input);
} 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 = "//boards.4chan.org/" + thread.board + "/res/" + thread;
if (tab) {
return $.open(url);
} else {
return location.href = url;
}
},
hl: function(delta, thread) {
var headRect, next, postEl, rect, replies, reply, root, topMargin, _i, _len;
headRect = $.id('header-bar').getBoundingClientRect();
topMargin = headRect.top + headRect.height;
if (postEl = $('.reply.highlight', thread)) {
$.rmClass(postEl, 'highlight');
rect = postEl.getBoundingClientRect();
if (rect.bottom >= topMargin && rect.top <= d.documentElement.clientHeight) {
root = postEl.parentNode;
next = $.x('child::div[contains(@class,"post reply")]', delta === +1 ? root.nextElementSibling : root.previousElementSibling);
if (!next) {
this.focus(postEl);
return;
}
if (!(g.VIEW === 'thread' || $.x('ancestor::div[parent::div[@class="board"]]', next) === thread)) {
return;
}
rect = next.getBoundingClientRect();
if (rect.top < 0 || rect.bottom > d.documentElement.clientHeight) {
if (delta === -1) {
window.scrollBy(0, rect.top - topMargin);
} else {
next.scrollIntoView(false);
}
}
this.focus(next);
return;
}
}
replies = $$('.reply', thread);
if (delta === -1) {
replies.reverse();
}
for (_i = 0, _len = replies.length; _i < _len; _i++) {
reply = replies[_i];
rect = reply.getBoundingClientRect();
if (delta === +1 && rect.top >= topMargin || delta === -1 && rect.bottom <= d.documentElement.clientHeight) {
this.focus(reply);
return;
}
}
},
focus: function(post) {
$.addClass(post, 'highlight');
return $('a[title="Highlight this post"]', post).focus();
}
};
Nav = { Nav = {
init: function() { init: function() {
var next, prev, span; var next, prev, span;
@ -3818,6 +4084,7 @@
switch (type) { switch (type) {
case 'Expand all': case 'Expand all':
$.on(input, 'change', ImageExpand.cb.all); $.on(input, 'change', ImageExpand.cb.all);
ImageExpand.expandAllInput = input;
break; break;
case 'Fit width': case 'Fit width':
case 'Fit height': case 'Fit height':
@ -5044,7 +5311,7 @@
text = ""; text = "";
sel = d.getSelection(); sel = d.getSelection();
selectionRoot = $.x('ancestor::div[contains(@class,"postContainer")][1]', sel.anchorNode); selectionRoot = $.x('ancestor::div[contains(@class,"postContainer")][1]', sel.anchorNode);
post = Get.postFromRoot($.x('ancestor::div[contains(@class,"postContainer")][1]', this)); post = Get.postFromNode(this);
thread = g.BOARD.posts[Get.contextFromLink(this).thread]; thread = g.BOARD.posts[Get.contextFromLink(this).thread];
if ((s = sel.toString().trim()) && post.nodes.root === selectionRoot) { if ((s = sel.toString().trim()) && post.nodes.root === selectionRoot) {
s = s.replace(/\n/g, '\n>'); s = s.replace(/\n/g, '\n>');
@ -6148,6 +6415,7 @@
initFeature('Thread Updater', ThreadUpdater); initFeature('Thread Updater', ThreadUpdater);
initFeature('Thread Watcher', ThreadWatcher); initFeature('Thread Watcher', ThreadWatcher);
initFeature('Index Navigation', Nav); initFeature('Index Navigation', Nav);
initFeature('Keybinds', Keybinds);
console.timeEnd('All initializations'); console.timeEnd('All initializations');
$.on(d, '4chanMainInit', Main.initStyle); $.on(d, '4chanMainInit', Main.initStyle);
return $.ready(Main.initReady); return $.ready(Main.initReady);

View File

@ -130,33 +130,34 @@ Config =
favicon: 'ferongr' favicon: 'ferongr'
hotkeys: hotkeys:
# QR & Options # QR & Options
'open QR': ['q', 'Open QR with post number inserted.'] 'Open empty QR': ['q', 'Open QR without post number inserted.']
'open empty QR': ['Q', 'Open QR without post number inserted.'] 'Open QR': ['Shift+q', 'Open QR with post number inserted.']
'open options': ['alt+o', 'Open Options.'] 'Open options': ['Alt+o', 'Open Options.']
'close': ['Esc', 'Close Options or QR.'] 'Close': ['Esc', 'Close Settings, Notifications or QR.']
'spoiler tags': ['ctrl+s', 'Insert spoiler tags.'] 'Spoiler tags': ['Ctrl+s', 'Insert spoiler tags.']
'code tags': ['alt+c', 'Insert code tags.'] 'Code tags': ['Alt+c', 'Insert code tags.']
'submit QR': ['alt+s', 'Submit post.'] 'Submit QR': ['Alt+s', 'Submit post.']
# Thread related # Thread related
'watch': ['w', 'Watch thread.'] 'Watch': ['w', 'Watch thread.']
'update': ['u', 'Update the thread now.'] 'Update': ['u', 'Update the thread now.']
# Images # Images
'expand image': ['E', 'Expand selected image.'] 'Expand image': ['Shift+e', 'Expand selected image.']
'expand images': ['e', 'Expand all images.'] 'Expand images': ['e', 'Expand all images.']
# Board Navigation # Board Navigation
'front page': ['0', 'Jump to page 0.'] 'Front page': ['0', 'Jump to page 0.']
'next page': ['Right', 'Jump to the next page.'] 'Open front page': ['Shift+0', 'Open page 0 in a new tab.']
'previous page': ['Left', 'Jump to the previous page.'] 'Next page': ['Right', 'Jump to the next page.']
'Previous page': ['Left', 'Jump to the previous page.']
# Thread Navigation # Thread Navigation
'next thread': ['Down', 'See next thread.'] 'Next thread': ['Down', 'See next thread.']
'previous thread': ['Up', 'See previous thread.'] 'Previous thread': ['Up', 'See previous thread.']
'expand thread': ['ctrl+e', 'Expand thread.'] 'Expand thread': ['Ctrl+e', 'Expand thread.']
'open thread': ['o', 'Open thread in current tab.'] 'Open thread': ['o', 'Open thread in current tab.']
'open thread tab': ['O', 'Open thread in new tab.'] 'Open thread tab': ['Shift+o', 'Open thread in new tab.']
# Reply Navigation # Reply Navigation
'next reply': ['j', 'Select next reply.'] 'Next reply': ['j', 'Select next reply.']
'previous reply': ['k', 'Select previous reply.'] 'Previous reply': ['k', 'Select previous reply.']
'hide': ['x', 'Hide thread.'] 'Hide': ['x', 'Hide thread.']
updater: updater:
checkbox: checkbox:
'Beep': [false, 'Beep on new post to completely read thread.'] 'Beep': [false, 'Beep on new post to completely read thread.']

View File

@ -1025,6 +1025,196 @@ ArchiveLink =
open: open open: open
} }
Keybinds =
init: ->
return if g.VIEW is 'catalog' or !Conf['Keybinds']
$.on d, 'keydown', Keybinds.keydown
$.on d, '4chanXInitFinished', ->
for node in $$ '[accesskey]'
node.removeAttribute 'accesskey'
keydown: (e) ->
return unless key = Keybinds.keyCode e
{target} = e
if target.nodeName in ['INPUT', 'TEXTAREA']
return unless (key is 'Esc') or (/(Alt|Ctrl|Meta)\+/.test key)
threadRoot = Nav.getThread()
thread = Get.postFromNode($('.op', threadRoot)).thread
switch key
# QR & Options
when Conf['Open empty QR']
Keybinds.qr threadRoot
when Conf['Open QR']
Keybinds.qr threadRoot, true
when Conf['Open options']
Settings.open()
when Conf['Close']
if $.id 'settings'
Options.close()
else if (notifications = $$ '.notification').length
for notification in notifications
$('.close', notification).click()
else if QR.el
QR.close()
when Conf['Spoiler tags']
return if target.nodeName isnt 'TEXTAREA'
Keybinds.tags 'spoiler', target
when Conf['Code tags']
return if target.nodeName isnt 'TEXTAREA'
Keybinds.tags 'code', target
when Conf['Submit QR']
QR.submit() if QR.el and !QR.status()
# Thread related
when Conf['Watch']
ThreadWatcher.toggle thread
when Conf['Update']
ThreadUpdater.update()
# Images
when Conf['Expand image']
Keybinds.img threadRoot
when Conf['Expand images']
Keybinds.img threadRoot, true
# Board Navigation
when Conf['Front page']
window.location = "/#{g.BOARD}/0#delform"
when Conf['Open front page']
$.open url "/#{g.BOARD}/#delform"
when Conf['Next page']
if form = $ '.next form'
window.location = form.action
when Conf['Previous page']
if form = $ '.prev form'
window.location = form.action
# Thread Navigation
when Conf['Next thread']
return if g.VIEW is 'thread'
Nav.scroll +1
when Conf['Previous thread']
return if g.VIEW is 'thread'
Nav.scroll -1
when Conf['Expand thread']
ExpandThread.toggle thread
when Conf['Open thread']
Keybinds.open thread
when Conf['Open thread tab']
Keybinds.open thread, true
# Reply Navigation
when Conf['Next reply']
Keybinds.hl +1, threadRoot
when Conf['Previous reply']
Keybinds.hl -1, threadRoot
when Conf['Hide']
ThreadHiding.toggle thread
else
return
e.preventDefault()
keyCode: (e) ->
key = switch kc = e.keyCode
when 8 # return
''
when 13
'Enter'
when 27
'Esc'
when 37
'Left'
when 38
'Up'
when 39
'Right'
when 40
'Down'
else
if 48 <= kc <= 57 or 65 <= kc <= 90 # 0-9, A-Z
String.fromCharCode(kc).toLowerCase()
else
null
if key
if e.altKey then key = 'Alt+' + key
if e.ctrlKey then key = 'Ctrl+' + key
if e.metaKey then key = 'Meta+' + key
if e.shiftKey then key = 'Shift+' + key
key
qr: (thread, quote) ->
return unless Conf['Quick Reply']
QR.open()
if quote
QR.quote.call $ 'input', $('.post.highlight', thread) or thread
$('textarea', QR.el).focus()
tags: (tag, ta) ->
value = ta.value
selStart = ta.selectionStart
selEnd = ta.selectionEnd
ta.value =
value[...selStart] +
"[#{tag}]" + value[selStart...selEnd] + "[/#{tag}]" +
value[selEnd..]
# Move the caret to the end of the selection.
range = "[#{tag}]".length + selEnd
ta.setSelectionRange range, range
# Fire the 'input' event
$.event 'input', null, ta
img: (thread, all) ->
if all
input = ImageExpand.expandAllInput
input.checked = !input.checked
ImageExpand.cb.all.call input
else
post = Get.postFromNode $('.post.highlight', thread) or $ '.op', thread
ImageExpand.toggle post
open: (thread, tab) ->
return if g.VIEW isnt 'index'
url = "//boards.4chan.org/#{thread.board}/res/#{thread}"
if tab
$.open url
else
location.href = url
hl: (delta, thread) ->
headRect = $.id('header-bar').getBoundingClientRect()
topMargin = headRect.top + headRect.height
if postEl = $ '.reply.highlight', thread
$.rmClass postEl, 'highlight'
rect = postEl.getBoundingClientRect()
if rect.bottom >= topMargin and rect.top <= d.documentElement.clientHeight # We're at least partially visible
root = postEl.parentNode
next = $.x 'child::div[contains(@class,"post reply")]',
if delta is +1 then root.nextElementSibling else root.previousElementSibling
unless next
@focus postEl
return
return unless g.VIEW is 'thread' or $.x('ancestor::div[parent::div[@class="board"]]', next) is thread
rect = next.getBoundingClientRect()
if rect.top < 0 or rect.bottom > d.documentElement.clientHeight
if delta is -1
window.scrollBy 0, rect.top - topMargin
else
next.scrollIntoView false
@focus next
return
replies = $$ '.reply', thread
replies.reverse() if delta is -1
for reply in replies
rect = reply.getBoundingClientRect()
if delta is +1 and rect.top >= topMargin or delta is -1 and rect.bottom <= d.documentElement.clientHeight
@focus reply
return
focus: (post) ->
$.addClass post, 'highlight'
$('a[title="Highlight this post"]', post).focus()
Nav = Nav =
init: -> init: ->
return if g.VIEW isnt 'index' or !Conf['Index Navigation'] return if g.VIEW isnt 'index' or !Conf['Index Navigation']
@ -2388,6 +2578,7 @@ ImageExpand =
switch type switch type
when 'Expand all' when 'Expand all'
$.on input, 'change', ImageExpand.cb.all $.on input, 'change', ImageExpand.cb.all
ImageExpand.expandAllInput = input
when 'Fit width', 'Fit height' when 'Fit width', 'Fit height'
$.on input, 'change', ImageExpand.cb.setFitness $.on input, 'change', ImageExpand.cb.setFitness
if config if config

View File

@ -345,6 +345,7 @@ Main =
initFeature 'Thread Updater', ThreadUpdater initFeature 'Thread Updater', ThreadUpdater
initFeature 'Thread Watcher', ThreadWatcher initFeature 'Thread Watcher', ThreadWatcher
initFeature 'Index Navigation', Nav initFeature 'Index Navigation', Nav
initFeature 'Keybinds', Keybinds
console.timeEnd 'All initializations' console.timeEnd 'All initializations'
$.on d, '4chanMainInit', Main.initStyle $.on d, '4chanMainInit', Main.initStyle

View File

@ -231,7 +231,7 @@ QR =
sel = d.getSelection() sel = d.getSelection()
selectionRoot = $.x 'ancestor::div[contains(@class,"postContainer")][1]', sel.anchorNode selectionRoot = $.x 'ancestor::div[contains(@class,"postContainer")][1]', sel.anchorNode
post = Get.postFromRoot $.x 'ancestor::div[contains(@class,"postContainer")][1]', @ post = Get.postFromNode @
thread = g.BOARD.posts[Get.contextFromLink(@).thread] thread = g.BOARD.posts[Get.contextFromLink(@).thread]
if (s = sel.toString().trim()) and post.nodes.root is selectionRoot if (s = sel.toString().trim()) and post.nodes.root is selectionRoot
@ -249,7 +249,6 @@ QR =
ta = $ 'textarea', QR.el ta = $ 'textarea', QR.el
if QR.threadSelector and !ta.value and g.BOARD.ID isnt 'f' if QR.threadSelector and !ta.value and g.BOARD.ID isnt 'f'
QR.threadSelector.value = thread.ID QR.threadSelector.value = thread.ID
# Make sure we get the correct number, even with XXX censors
caretPos = ta.selectionStart caretPos = ta.selectionStart
# Replace selection for text. # Replace selection for text.