Merge pull request #110 from joakimoa/master
v1.4 bugfixes, improvements and a refresh hotkey.
This commit is contained in:
commit
c888e691c1
@ -1,55 +1,61 @@
|
|||||||
// author: joakimoa
|
// author: joakimoa
|
||||||
// keyboard navigation option
|
// keyboard navigation
|
||||||
// v1.2
|
// v1.4
|
||||||
|
|
||||||
$(document).on("ready", function() {
|
$(document).on("ready", function() {
|
||||||
|
|
||||||
// adding checkbox for turning on/off
|
// adding keyboard navigation to options menu
|
||||||
if (window.Options && Options.get_tab('general')) {
|
if (window.Options && Options.get_tab('general')) {
|
||||||
Options.extend_tab("general",
|
Options.extend_tab("general",
|
||||||
"<fieldset><legend> Keyboard Navigation </legend>" +
|
"<fieldset><legend> Keyboard Navigation </legend>" +
|
||||||
("<label class='keyboardnav' id='keyboardnav' style='padding:0px;'><input type='checkbox' /> Enable Keyboard Navigation</label>") +
|
("<label class='keyboardnav' id='keyboardnav' style='padding:0px;'><input type='checkbox' /> Enable Keyboard Navigation</label>") +
|
||||||
"<table><tr><td>Action</td><td>Key (a-z)</td></tr>" +
|
"<table><tr><td>Action</td><td>Key (a-z)</td></tr>" +
|
||||||
"<tr><td>Next Reply</td><td><input class='field' name='next-reply' spellcheck='false'></td></tr>" +
|
"<tr><td>Next Reply</td><td><input class='field' name='next-reply-input' spellcheck='false'></td></tr>" +
|
||||||
"<tr><td>Previous Reply</td><td><input class='field' name='previous-reply' spellcheck='false'></td></tr>" +
|
"<tr><td>Previous Reply</td><td><input class='field' name='previous-reply-input' spellcheck='false'></td></tr>" +
|
||||||
"<tr><td>Expand File</td><td><input class='field' name='expando' spellcheck='false'></td></tr>" +
|
"<tr><td>Expand File</td><td><input class='field' name='expando-input' spellcheck='false'></td></tr>" +
|
||||||
|
"<tr><td>Refresh Thread</td><td><input class='field' name='refresh-thread-input' spellcheck='false'></td></tr>" +
|
||||||
"</table></fieldset>");
|
"</table></fieldset>");
|
||||||
}
|
}
|
||||||
|
|
||||||
$('.keyboardnav').on('change', function(){
|
$('.keyboardnav').on('change', function(){
|
||||||
var setting = $(this).attr('id');
|
var setting = $(this).attr('id');
|
||||||
localStorage[setting] = $(this).children('input').is(':checked');
|
localStorage[setting] = $(this).children('input').is(':checked');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var nextReplyKeycode = 74; // j
|
||||||
|
var previousReplyKeycode = 75; // k
|
||||||
|
var expandoKeycode = 69; // e
|
||||||
|
var refreshThreadKeycode = 82; // r
|
||||||
|
|
||||||
if (!localStorage.keyboardnav) {
|
if (!localStorage.keyboardnav) {
|
||||||
localStorage.keyboardnav = 'false';
|
localStorage.keyboardnav = 'false';
|
||||||
}
|
}
|
||||||
if (!localStorage["next.reply.key"]) {
|
if (!localStorage["next.reply.key"]) {
|
||||||
localStorage["next.reply.key"] = 74;
|
localStorage["next.reply.key"] = nextReplyKeycode;
|
||||||
}
|
}
|
||||||
if (!localStorage["previous.reply.key"]) {
|
if (!localStorage["previous.reply.key"]) {
|
||||||
localStorage["previous.reply.key"] = 75;
|
localStorage["previous.reply.key"] = previousReplyKeycode;
|
||||||
}
|
}
|
||||||
if (!localStorage["expando.key"]) {
|
if (!localStorage["expando.key"]) {
|
||||||
localStorage["expando.key"] = 69;
|
localStorage["expando.key"] = expandoKeycode;
|
||||||
|
}
|
||||||
|
if (!localStorage["refresh.thread.key"]) {
|
||||||
|
localStorage["refresh.thread.key"] = refreshThreadKeycode;
|
||||||
}
|
}
|
||||||
|
|
||||||
// getting locally stored setting
|
// getting locally stored setting
|
||||||
function getSetting(key) {
|
function getSetting(key) {
|
||||||
return (localStorage[key] == 'true');
|
return (localStorage[key] == 'true');
|
||||||
}
|
}
|
||||||
|
|
||||||
function isKeySet(key) {
|
function isKeySet(key) {
|
||||||
return (localStorage[key] !== false);
|
return (localStorage[key] !== false);
|
||||||
}
|
}
|
||||||
|
|
||||||
var nextReplyInput = document.getElementsByName("next-reply")[0];
|
var nextReplyInput = document.getElementsByName("next-reply-input")[0];
|
||||||
var previousReplyInput = document.getElementsByName("previous-reply")[0];
|
var previousReplyInput = document.getElementsByName("previous-reply-input")[0];
|
||||||
var expandoInput = document.getElementsByName("expando")[0];
|
var expandoInput = document.getElementsByName("expando-input")[0];
|
||||||
|
var refreshThreadInput = document.getElementsByName("refresh-thread-input")[0];
|
||||||
var nextReplyKeycode = 74; // j
|
|
||||||
var previousReplyKeycode = 75; // k
|
|
||||||
var expandoKeycode = 69; // e
|
|
||||||
|
|
||||||
if (getSetting('keyboardnav')) $('#keyboardnav>input').prop('checked', 'checked');
|
if (getSetting('keyboardnav')) $('#keyboardnav>input').prop('checked', 'checked');
|
||||||
if (isKeySet('next.reply.key')) {
|
if (isKeySet('next.reply.key')) {
|
||||||
@ -64,14 +70,20 @@ if (isKeySet('expando.key')) {
|
|||||||
expandoKeycode = localStorage["expando.key"];
|
expandoKeycode = localStorage["expando.key"];
|
||||||
expandoInput.value = expandoKeycode;
|
expandoInput.value = expandoKeycode;
|
||||||
}
|
}
|
||||||
|
if (isKeySet('refresh.thread.key')) {
|
||||||
|
refreshThreadKeycode = localStorage["refresh.thread.key"];
|
||||||
|
refreshThreadInput.value = refreshThreadKeycode;
|
||||||
|
}
|
||||||
|
|
||||||
document.getElementsByName("next-reply")[0].value = String.fromCharCode(nextReplyKeycode);
|
nextReplyInput.value = String.fromCharCode(nextReplyKeycode);
|
||||||
document.getElementsByName("previous-reply")[0].value = String.fromCharCode(previousReplyKeycode);
|
previousReplyInput.value = String.fromCharCode(previousReplyKeycode);
|
||||||
document.getElementsByName("expando")[0].value = String.fromCharCode(expandoKeycode);
|
expandoInput.value = String.fromCharCode(expandoKeycode);
|
||||||
|
refreshThreadInput.value = String.fromCharCode(refreshThreadKeycode);
|
||||||
|
|
||||||
nextReplyInput.addEventListener("keyup", changeNextReplyKey, false);
|
nextReplyInput.addEventListener("keyup", changeNextReplyKey, false);
|
||||||
previousReplyInput.addEventListener("keyup", changePreviousReplyKey, false);
|
previousReplyInput.addEventListener("keyup", changePreviousReplyKey, false);
|
||||||
expandoInput.addEventListener("keyup", changeExpandoKey, false);
|
expandoInput.addEventListener("keyup", changeExpandoKey, false);
|
||||||
|
refreshThreadInput.addEventListener("keyup", changeRefreshThreadKey, false);
|
||||||
|
|
||||||
function changeNextReplyKey(e) {
|
function changeNextReplyKey(e) {
|
||||||
nextReplyInput.value = "";
|
nextReplyInput.value = "";
|
||||||
@ -97,31 +109,88 @@ function changeExpandoKey(e) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function changeRefreshThreadKey(e) {
|
||||||
|
refreshThreadInput.value = "";
|
||||||
|
if (e.keyCode >= 65 && e.keyCode <= 90) {
|
||||||
|
refreshThreadInput.value = String.fromCharCode(e.keyCode);
|
||||||
|
localStorage["refresh.thread.key"] = e.keyCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// loads the main function
|
// loads the main function
|
||||||
function loadKeyboardNav() {
|
function loadKeyboardNav() {
|
||||||
var replies = document.getElementsByClassName("post reply");
|
var replies = document.getElementsByClassName("post reply");
|
||||||
var current_file = null;
|
var current_file = null;
|
||||||
|
var default_color = "#333";
|
||||||
var highlight_color = "#555";
|
var highlight_color = "#555";
|
||||||
var default_color = "black";
|
|
||||||
if (replies.length > 0) default_color = window.getComputedStyle(replies[0], null).getPropertyValue("background-color");
|
|
||||||
|
|
||||||
var reply_indexx = 0;
|
// grabs base and highlight colors
|
||||||
|
if (replies.length > 0) {
|
||||||
|
if (replies[0].classList.contains("highlighted")) {
|
||||||
|
replies[0].classList.remove('highlighted');
|
||||||
|
default_color = window.getComputedStyle(replies[0], null).getPropertyValue("background-color");
|
||||||
|
replies[0].classList.add('highlighted');
|
||||||
|
highlight_color = window.getComputedStyle(replies[0], null).getPropertyValue("background-color");
|
||||||
|
} else {
|
||||||
|
default_color = window.getComputedStyle(replies[0], null).getPropertyValue("background-color");
|
||||||
|
replies[0].classList.add('highlighted');
|
||||||
|
highlight_color = window.getComputedStyle(replies[0], null).getPropertyValue("background-color");
|
||||||
|
replies[0].classList.remove('highlighted');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if user is in textareas where hotkeys needs to be disabled
|
||||||
|
var text_input_focused = false;
|
||||||
|
function checkFocused () {
|
||||||
|
var el = document.activeElement;
|
||||||
|
if (el && (el.tagName.toLowerCase() == 'input' && el.type == 'text' ||
|
||||||
|
el.tagName.toLowerCase() == 'textarea')) {
|
||||||
|
text_input_focused = true;
|
||||||
|
} else {
|
||||||
|
text_input_focused = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('focus',function(e){
|
||||||
|
checkFocused();
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
document.addEventListener('blur',function(e){
|
||||||
|
text_input_focused = false;
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
// strips out <a href="" class="file"> tags
|
||||||
|
function getFileList(e) {
|
||||||
|
var arr = [];
|
||||||
|
var e = e.getElementsByClassName("file");
|
||||||
|
if (e.length > 0) {
|
||||||
|
for (i = 0; i < e.length; i++) {
|
||||||
|
if (e[i].tagName === "DIV") {
|
||||||
|
arr.push(e[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
var reply_indexx = -1; // might change back to 0
|
||||||
var image_indexx = -1;
|
var image_indexx = -1;
|
||||||
function focusNextReply() {
|
function focusNextReply() {
|
||||||
if (reply_indexx < replies.length-1) {
|
if (reply_indexx < replies.length-1) {
|
||||||
reply_indexx++;
|
reply_indexx++;
|
||||||
image_indexx = -1;
|
image_indexx = -1;
|
||||||
var images = replies[reply_indexx].getElementsByClassName("file");
|
var images = getFileList(replies[reply_indexx]);
|
||||||
if (images.length !== 0) {
|
if (images.length !== 0) {
|
||||||
focusNextImage();
|
focusNextImage();
|
||||||
} else {
|
} else {
|
||||||
scrollTo(replies[reply_indexx]);
|
scrollTo(replies[reply_indexx], true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function focusNextImage() {
|
function focusNextImage() {
|
||||||
var images = replies[reply_indexx].getElementsByClassName("file");
|
var images = getFileList(replies[reply_indexx]);
|
||||||
|
|
||||||
if (images.length === 0) {
|
if (images.length === 0) {
|
||||||
focusNextReply();
|
focusNextReply();
|
||||||
} else {
|
} else {
|
||||||
@ -130,7 +199,11 @@ function loadKeyboardNav() {
|
|||||||
image_indexx = 0;
|
image_indexx = 0;
|
||||||
focusNextReply();
|
focusNextReply();
|
||||||
} else {
|
} else {
|
||||||
scrollTo(images[image_indexx]);
|
var im = images[image_indexx].getElementsByClassName("full-image");
|
||||||
|
if (im.length === 0) {
|
||||||
|
im = images[image_indexx].getElementsByClassName("post-image");
|
||||||
|
}
|
||||||
|
scrollTo(im[0], true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -138,19 +211,19 @@ function loadKeyboardNav() {
|
|||||||
function focusPreviousReply() {
|
function focusPreviousReply() {
|
||||||
if (reply_indexx > 0) {
|
if (reply_indexx > 0) {
|
||||||
reply_indexx--;
|
reply_indexx--;
|
||||||
var images = replies[reply_indexx].getElementsByClassName("file");
|
var images = getFileList(replies[reply_indexx]);
|
||||||
image_indexx = images.length;
|
image_indexx = images.length;
|
||||||
if (images.length !== 0) {
|
if (images.length !== 0) {
|
||||||
focusPreviousImage();
|
focusPreviousImage();
|
||||||
} else {
|
} else {
|
||||||
image_indexx = -1;
|
image_indexx = -1;
|
||||||
scrollTo(replies[reply_indexx]);
|
scrollTo(replies[reply_indexx], false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function focusPreviousImage() {
|
function focusPreviousImage() {
|
||||||
var images = replies[reply_indexx].getElementsByClassName("file");
|
var images = getFileList(replies[reply_indexx]);
|
||||||
if (images.length === 0) {
|
if (images.length === 0) {
|
||||||
focusPreviousReply();
|
focusPreviousReply();
|
||||||
} else {
|
} else {
|
||||||
@ -159,17 +232,42 @@ function loadKeyboardNav() {
|
|||||||
image_indexx = 0;
|
image_indexx = 0;
|
||||||
focusPreviousReply();
|
focusPreviousReply();
|
||||||
} else {
|
} else {
|
||||||
scrollTo(images[image_indexx]);
|
var im = images[image_indexx].getElementsByClassName("full-image");
|
||||||
|
if (im.length === 0) {
|
||||||
|
im = images[image_indexx].getElementsByClassName("post-image")
|
||||||
|
}
|
||||||
|
scrollTo(im[0], false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function scrollTo(e) {
|
// from https://gist.github.com/jjmu15/8646226
|
||||||
if (current_file !== null) {
|
function isInViewport(element) {
|
||||||
|
var rect = element.getBoundingClientRect();
|
||||||
|
var html = document.documentElement;
|
||||||
|
return (
|
||||||
|
rect.top >= 0 &&
|
||||||
|
rect.left >= 0 &&
|
||||||
|
rect.bottom <= (window.innerHeight || html.clientHeight) &&
|
||||||
|
rect.right <= (window.innerWidth || html.clientWidth)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrollTo(e, direction_down) {
|
||||||
|
if (current_file !== null && !current_file.classList.contains("highlighted")) {
|
||||||
current_file.style.backgroundColor = default_color;
|
current_file.style.backgroundColor = default_color;
|
||||||
}
|
}
|
||||||
current_file = e;
|
current_file = e;
|
||||||
e.scrollIntoView();
|
if (!isInViewport(e)) {
|
||||||
|
if (direction_down) {
|
||||||
|
e.scrollIntoView(false);
|
||||||
|
window.scrollBy(0, 30);
|
||||||
|
} else {
|
||||||
|
e.scrollIntoView();
|
||||||
|
window.scrollBy(0, -30);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
e.style.backgroundColor = highlight_color;
|
e.style.backgroundColor = highlight_color;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,12 +282,21 @@ function loadKeyboardNav() {
|
|||||||
window.addEventListener("keydown", checkKeyPressed, false);
|
window.addEventListener("keydown", checkKeyPressed, false);
|
||||||
|
|
||||||
function checkKeyPressed(e) {
|
function checkKeyPressed(e) {
|
||||||
if (e.keyCode == nextReplyKeycode) {
|
if (!text_input_focused) {
|
||||||
focusNextImage();
|
replies = document.getElementsByClassName("post reply"); // if new ones via AJAX
|
||||||
} else if (e.keyCode == previousReplyKeycode) {
|
if (e.keyCode == nextReplyKeycode) {
|
||||||
focusPreviousImage();
|
if (reply_indexx === -1) { // needed for initial condition
|
||||||
} else if (e.keyCode == expandoKeycode) {
|
focusNextReply();
|
||||||
expandFile();
|
} else {
|
||||||
|
focusNextImage();
|
||||||
|
}
|
||||||
|
} else if (e.keyCode == previousReplyKeycode) {
|
||||||
|
focusPreviousImage();
|
||||||
|
} else if (e.keyCode == expandoKeycode) {
|
||||||
|
expandFile();
|
||||||
|
} else if (e.keyCode == refreshThreadKeycode) {
|
||||||
|
document.getElementById("update_thread").click();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -199,4 +306,4 @@ if (getSetting('keyboardnav') && document.getElementsByClassName("thread").lengt
|
|||||||
loadKeyboardNav();
|
loadKeyboardNav();
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
Loading…
Reference in New Issue
Block a user