summaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
Diffstat (limited to 'js')
-rw-r--r--js/keyboard-shortcuts.js203
1 files changed, 155 insertions, 48 deletions
diff --git a/js/keyboard-shortcuts.js b/js/keyboard-shortcuts.js
index 64b7ee15..1af672cc 100644
--- a/js/keyboard-shortcuts.js
+++ b/js/keyboard-shortcuts.js
@@ -1,55 +1,61 @@
// author: joakimoa
-// keyboard navigation option
-// v1.2
+// keyboard navigation
+// v1.4
$(document).on("ready", function() {
-// adding checkbox for turning on/off
+// adding keyboard navigation to options menu
if (window.Options && Options.get_tab('general')) {
- Options.extend_tab("general",
- "<fieldset><legend> Keyboard Navigation </legend>" +
- ("<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>" +
- "<tr><td>Next Reply</td><td><input class='field' name='next-reply' spellcheck='false'></td></tr>" +
- "<tr><td>Previous Reply</td><td><input class='field' name='previous-reply' spellcheck='false'></td></tr>" +
- "<tr><td>Expand File</td><td><input class='field' name='expando' spellcheck='false'></td></tr>" +
+ Options.extend_tab("general",
+ "<fieldset><legend> Keyboard Navigation </legend>" +
+ ("<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>" +
+ "<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-input' 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>");
}
$('.keyboardnav').on('change', function(){
- var setting = $(this).attr('id');
- localStorage[setting] = $(this).children('input').is(':checked');
+ var setting = $(this).attr('id');
+ 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) {
- localStorage.keyboardnav = 'false';
+ localStorage.keyboardnav = 'false';
}
if (!localStorage["next.reply.key"]) {
- localStorage["next.reply.key"] = 74;
+ localStorage["next.reply.key"] = nextReplyKeycode;
}
if (!localStorage["previous.reply.key"]) {
- localStorage["previous.reply.key"] = 75;
+ localStorage["previous.reply.key"] = previousReplyKeycode;
}
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
function getSetting(key) {
- return (localStorage[key] == 'true');
+ return (localStorage[key] == 'true');
}
function isKeySet(key) {
return (localStorage[key] !== false);
}
-var nextReplyInput = document.getElementsByName("next-reply")[0];
-var previousReplyInput = document.getElementsByName("previous-reply")[0];
-var expandoInput = document.getElementsByName("expando")[0];
-
-var nextReplyKeycode = 74; // j
-var previousReplyKeycode = 75; // k
-var expandoKeycode = 69; // e
+var nextReplyInput = document.getElementsByName("next-reply-input")[0];
+var previousReplyInput = document.getElementsByName("previous-reply-input")[0];
+var expandoInput = document.getElementsByName("expando-input")[0];
+var refreshThreadInput = document.getElementsByName("refresh-thread-input")[0];
if (getSetting('keyboardnav')) $('#keyboardnav>input').prop('checked', 'checked');
if (isKeySet('next.reply.key')) {
@@ -64,14 +70,20 @@ if (isKeySet('expando.key')) {
expandoKeycode = localStorage["expando.key"];
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);
-document.getElementsByName("previous-reply")[0].value = String.fromCharCode(previousReplyKeycode);
-document.getElementsByName("expando")[0].value = String.fromCharCode(expandoKeycode);
+nextReplyInput.value = String.fromCharCode(nextReplyKeycode);
+previousReplyInput.value = String.fromCharCode(previousReplyKeycode);
+expandoInput.value = String.fromCharCode(expandoKeycode);
+refreshThreadInput.value = String.fromCharCode(refreshThreadKeycode);
nextReplyInput.addEventListener("keyup", changeNextReplyKey, false);
previousReplyInput.addEventListener("keyup", changePreviousReplyKey, false);
expandoInput.addEventListener("keyup", changeExpandoKey, false);
+refreshThreadInput.addEventListener("keyup", changeRefreshThreadKey, false);
function changeNextReplyKey(e) {
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
function loadKeyboardNav() {
var replies = document.getElementsByClassName("post reply");
var current_file = null;
+ var default_color = "#333";
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;
function focusNextReply() {
if (reply_indexx < replies.length-1) {
reply_indexx++;
image_indexx = -1;
- var images = replies[reply_indexx].getElementsByClassName("file");
+ var images = getFileList(replies[reply_indexx]);
if (images.length !== 0) {
focusNextImage();
} else {
- scrollTo(replies[reply_indexx]);
+ scrollTo(replies[reply_indexx], true);
}
}
}
function focusNextImage() {
- var images = replies[reply_indexx].getElementsByClassName("file");
+ var images = getFileList(replies[reply_indexx]);
+
if (images.length === 0) {
focusNextReply();
} else {
@@ -130,7 +199,11 @@ function loadKeyboardNav() {
image_indexx = 0;
focusNextReply();
} 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() {
if (reply_indexx > 0) {
reply_indexx--;
- var images = replies[reply_indexx].getElementsByClassName("file");
+ var images = getFileList(replies[reply_indexx]);
image_indexx = images.length;
if (images.length !== 0) {
focusPreviousImage();
} else {
image_indexx = -1;
- scrollTo(replies[reply_indexx]);
+ scrollTo(replies[reply_indexx], false);
}
}
}
function focusPreviousImage() {
- var images = replies[reply_indexx].getElementsByClassName("file");
+ var images = getFileList(replies[reply_indexx]);
if (images.length === 0) {
focusPreviousReply();
} else {
@@ -159,17 +232,42 @@ function loadKeyboardNav() {
image_indexx = 0;
focusPreviousReply();
} 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) {
- if (current_file !== null) {
+ // from https://gist.github.com/jjmu15/8646226
+ 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 = 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;
}
@@ -184,12 +282,21 @@ function loadKeyboardNav() {
window.addEventListener("keydown", checkKeyPressed, false);
function checkKeyPressed(e) {
- if (e.keyCode == nextReplyKeycode) {
- focusNextImage();
- } else if (e.keyCode == previousReplyKeycode) {
- focusPreviousImage();
- } else if (e.keyCode == expandoKeycode) {
- expandFile();
+ if (!text_input_focused) {
+ replies = document.getElementsByClassName("post reply"); // if new ones via AJAX
+ if (e.keyCode == nextReplyKeycode) {
+ if (reply_indexx === -1) { // needed for initial condition
+ focusNextReply();
+ } 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();
}
-});
+}); \ No newline at end of file