Features: - scroll through comments with 'j' and 'k'
- scroll through parent comments with 'J' and 'K'
- vote on comments with ',' and '.'
- automatically load more comments on end of page
---
modules/page-modes/reddit.js | 313 ++++++++++++++++++++++++++++++++++++++++---
1 file changed, 294 insertions(+), 19 deletions(-)
diff --git a/modules/page-modes/reddit.js b/modules/page-modes/reddit.js
index 3da6282..da30f73 100644
--- a/modules/page-modes/reddit.js
+++ b/modules/page-modes/reddit.js
@@ -34,12 +34,41 @@ function reddit_scroll_into_view (window, element) {
element.scrollIntoView();
}
+/* Select the next entry down from the currently highlighted one.
+ * Checks the URL to figure out if one a link page or comment page.
+ */
+function reddit_next (I) {
+ var doc = I.buffer.document;
+
+ // Not on comment page, so highlight next link
+ if (doc.URL.search("/comments/") == -1)
+ reddit_next_link(I);
+
+ // On comment page, so highlight next comment
+ else
+ reddit_next_comment(I, true);
+}
+interactive("reddit-next",
+ "Move the 'cursor' to the next reddit entry.",
+ reddit_next);
+
+/* Selects the next parent comment if on a comment page.
+ */
+function reddit_next_parent_comment (I) {
+ var doc = I.buffer.document;
+
+ if (doc.URL.search("/comments/") != -1)
+ reddit_next_comment(I, false);
+}
+interactive("reddit-next-parent-comment",
+ "Move the 'cursor' to the next comment which isn't a child of
another comment.",
+ reddit_next_parent_comment);
/* Move select the next link down from the currently highlighted one.
* When the end of the page is reached, the behavior is controlled by
* the variable reddit_end_behavior.
*/
-function reddit_next (I) {
+function reddit_next_link (I) {
var doc = I.buffer.document;
// the behavior of this command depends on whether we have downloaded
// enough of the page to include all of the article links.
@@ -103,15 +132,162 @@ function reddit_next (I) {
reddit_scroll_into_view(I.buffer.focused_frame, next);
}
interactive("reddit-next-link",
- "Move the 'cursor' to the next reddit entry.",
- reddit_next);
+ "Move the 'cursor' to the next reddit link.",
+ reddit_next_link);
+
+/* Checks if comment is a child of parent. Used on collapsed
+ * parents, to determine whether the child should be selected or
+ * not.
+ */
+function comment_is_child (parent, comment) {
+var parent_comments = parent.querySelectorAll(".comment");
+
+ for (var i = 0, llen = parent_comments.length; i < llen; i++) {
+ if (parent_comments[i].getAttribute("data-fullname") ==
comment.getAttribute("data-fullname"))
+ return true;
+ }
+
+ return false;
+}
+
+/* Returns entries (top link + comments) that are visible (are not
+ * collapsed).
+ */
+function get_entries_without_collapsed_comments (entries) {
+ var entries_without_collapsed = new Array();
+ var collapsed_parent = null;
+
+ for (var i = 0, elen = entries.length; i < elen; i++) {
+ if (collapsed_parent) {
+ // Discard the 'load more comments' buttons
+ var current_classname =
entries[i].getElementsByTagName("span")[0].className;
+
+ if (!comment_is_child(collapsed_parent, entries[i].parentNode) &&
current_classname != "morecomments")
+ collapsed_parent = null;
+
+ // Skip collapsed comments
+ else
+ continue;
+ }
+
+ // Collapsed comment
+ if (i != 0 && entries[i].getElementsByTagName("div")[1].style.display
== "none")
+ collapsed_parent = entries[i].parentNode;
+
+ entries_without_collapsed.push(entries[i]);
+ }
+
+ return entries_without_collapsed;
+}
+
+/* Select the next comment down from the currently highlighted one.
+ * When select_all_comments is true, select the next comment. When
+ * it's false select the next comment which isn't a child of another
+ * comment.
+ */
+function reddit_next_comment (I, select_all_comments) {
+ var doc = I.buffer.document;
+ // Get all comments plus the top link
+ var entries = doc.querySelectorAll("body>.content .entry");
+ // Remove all the collapsed comments
+ entries = get_entries_without_collapsed_comments(entries);
+ // Get the div which contains all comments
+ var comments_div = doc.getElementsByClassName("nestedlisting")[0];
+
+ var first = null;
+ var current = null;
+ var next = null;
+ var parent_div_current = null;
+
+ for (var i = 0, elen = entries.length; i < elen && !next; i++) {
+ parent_div_current = entries[i].parentElement.parentElement;
+
+ // Next link/comment can be selected if either:
+ // 1) All comments have to be selected
+ // 2) It's the first entry, which is the top link
+ // 3) It's a top level comment
+ if (select_all_comments || i == 0 || parent_div_current.id ==
comments_div.id) {
+ if (!first)
+ first = entries[i];
+ if (current)
+ next = entries[i];
+ }
+
+ if (entries[i].className.indexOf("last-clicked") >= 0)
+ current = entries[i];
+ }
+
+ // There are no comments on the page
+ if (!first)
+ return;
+
+ // Last comment on page, try to load more
+ if (current && !next) {
+ load_more_link = comments_div.querySelector(".nestedlisting >
.morechildren .button");
+
+ if (load_more_link) {
+ // Go to the previous comment first, since the current one will
disappear
+ reddit_prev_comment(I, true);
+ browser_object_follow(I.buffer, FOLLOW_DEFAULT, load_more_link);
+ }
+
+ return;
+ }
+
+ // No next yet, because there is no current. So make the first entry the
next one
+ if (!next)
+ next = first;
+
+ // Dehighlight old
+ if (current)
+ dom_remove_class(current, "last-clicked");
+
+ // Highlight the next comment
+ dom_add_class(next, "last-clicked");
+
+ // Focus the link on the comment page
+ var anchor = doc.querySelector("body>.content .last-clicked a.title");
+ browser_set_element_focus(I.buffer, anchor);
+ reddit_scroll_into_view(I.buffer.focused_frame, next);
+}
+interactive("reddit-next-comment",
+ "Move the 'cursor' to the next reddit comment.",
+ reddit_next_comment);
+
+
+/* Select the next entry up from the currently highlighted one.
+ * Checks the URL to figure out if one a link page or comment page.
+ */
+function reddit_prev (I) {
+ var doc = I.buffer.document;
+
+ // Not on comment page, so highlight prev link
+ if (doc.URL.search("/comments/") == -1)
+ reddit_prev_link(I);
+
+ // On comment page, so highlight prev comment
+ else
+ reddit_prev_comment(I, true);
+}
+interactive("reddit-prev",
+ "Move the 'cursor' to the previous reddit entry.",
+ reddit_prev);
+
+function reddit_prev_parent_comment (I) {
+ var doc = I.buffer.document;
+ if (doc.URL.search("/comments/") != -1)
+ reddit_prev_comment(I, false);
+}
+interactive("reddit-prev-parent-comment",
+ "Move the 'cursor' to the previous comment which isn't a child of
another comment.",
+ reddit_prev_parent_comment);
/* Select the link before the currently highlighted one. When the
* beginning of the page is reached, behavior is controlled by the
* variable reddit_end_behavior.
*/
-function reddit_prev (I) {
+function reddit_prev_link (I) {
var doc = I.buffer.document;
// the behavior of this command depends on whether we have downloaded
// enough of the page to include all of the article links.
@@ -172,8 +348,67 @@ function reddit_prev (I) {
reddit_scroll_into_view(I.buffer.focused_frame, prev);
}
interactive("reddit-prev-link",
- "Move the 'cursor' to the previous reddit entry.",
- reddit_prev);
+ "Move the 'cursor' to the previous reddit link.",
+ reddit_prev_link);
+
+/* Select the prev comment down from the currently highlighted
+ * one. When select_all_comments is true, select the previous
+ * comment. When it's false select the previous comment which
+ * isn't a child of another comment.
+ */
+function reddit_prev_comment (I, select_all_comments) {
+ var doc = I.buffer.document;
+ // Get all comments plus the top link
+ var entries = doc.querySelectorAll("body>.content .entry");
+ // Remove all the collapsed comments
+ entries = get_entries_without_collapsed_comments(entries);
+ // Get the div which contains all comments
+ var comments_div = doc.getElementsByClassName("nestedlisting")[0];
+
+ var first = null;
+ var current = null;
+ var prev = null;
+ var prev_parent = null;
+ var parent_div_current = null;
+
+ for (var i = 0, elen = entries.length; i < elen && !current; i++) {
+ if (entries[i].className.indexOf("last-clicked") >= 0) {
+ current = entries[i];
+
+ // Don't bother if the top link is selected, since
+ // that means there is no previous entry
+ if(i != 0) {
+ if (select_all_comments)
+ prev = entries[i - 1];
+ else
+ prev = prev_parent;
+ }
+ }
+
+ parent_div_current = entries[i].parentElement.parentElement;
+
+ // Remember the last parent comment and consider the top
+ // link to be a parent comment
+ if (i == 0 || parent_div_current.id == comments_div.id)
+ prev_parent = entries[i];
+ }
+
+ // Nothing is selected yet or there are no comments on the page.
+ if (!prev)
+ return;
+
+ // Dehighlight old
+ if (current)
+ dom_remove_class(current, "last-clicked");
+
+ // Highlight the prev comment
+ dom_add_class(prev, "last-clicked");
+
+ reddit_scroll_into_view(I.buffer.focused_frame, prev);
+}
+interactive("reddit-prev-comment",
+ "Move the 'cursor' to the previous reddit comment.",
+ reddit_prev_comment);
function reddit_open_comments (I, target) {
@@ -196,28 +431,66 @@ interactive("reddit-open-comments",
function reddit_vote_up (I) {
- // get the current article and send a click to its vote-up button.
var doc = I.buffer.document;
- var link = doc.querySelector("body>.content .last-clicked .midcol .up");
- if (link)
- browser_object_follow(I.buffer, FOLLOW_DEFAULT, link);
+
+ if (doc.URL.search("/comments/") == -1)
+ reddit_vote_link(I, true);
+
+ else
+ reddit_vote_comment(I, true);
}
interactive("reddit-vote-up",
- "Vote the currently selected link up.",
+ "Vote the currently selected entry up.",
reddit_vote_up);
-
function reddit_vote_down (I) {
- // get the current article and send a click to its vote-down button.
var doc = I.buffer.document;
- var link = doc.querySelector("body>.content .last-clicked .midcol .down");
- if (link)
- browser_object_follow(I.buffer, FOLLOW_DEFAULT, link);
+
+ if (doc.URL.search("/comments/") == -1)
+ reddit_vote_link(I, false);
+
+ else
+ reddit_vote_comment(I, false);
}
interactive("reddit-vote-down",
- "Vote the currently selected link down.",
+ "Vote the currently selected entry down.",
reddit_vote_down);
+function reddit_vote_link (I, upvote) {
+ // get the current article and send a click to its vote button.
+ var doc = I.buffer.document;
+ var arrow_class = "";
+
+ if (upvote)
+ arrow_class = ".up";
+ else
+ arrow_class = ".down";
+
+ var link = doc.querySelector("body>.content .last-clicked .midcol " +
arrow_class);
+ if (link)
+ browser_object_follow(I.buffer, FOLLOW_DEFAULT, link);
+}
+
+function reddit_vote_comment (I, upvote) {
+ // get the current entry and send a click to its vote button.
+ var doc = I.buffer.document;
+ var link = doc.querySelector("body>.content .last-clicked");
+ var arrow_class = "";
+
+ if (upvote)
+ arrow_class = ".up";
+ else
+ arrow_class = ".down";
+
+ // Is there anything selected?
+ if (link && link.getElementsByTagName("span")[0].className !=
"morecomments") {
+ // Get the vote arrow
+ link =
link.parentNode.getElementsByClassName("midcol")[0].querySelector(arrow_class)
+
+ if (link)
+ browser_object_follow(I.buffer, FOLLOW_DEFAULT, link);
+ }
+}
define_browser_object_class("reddit-current", null,
function (I, prompt) {
@@ -228,8 +501,10 @@ define_browser_object_class("reddit-current", null,
define_keymap("reddit_keymap", $display_name = "reddit");
-define_key(reddit_keymap, "j", "reddit-next-link");
-define_key(reddit_keymap, "k", "reddit-prev-link");
+define_key(reddit_keymap, "j", "reddit-next");
+define_key(reddit_keymap, "J", "reddit-next-parent-comment");
+define_key(reddit_keymap, "k", "reddit-prev");
+define_key(reddit_keymap, "K", "reddit-prev-parent-comment");
define_key(reddit_keymap, ",", "reddit-vote-up");
define_key(reddit_keymap, ".", "reddit-vote-down");
define_key(reddit_keymap, "h", "reddit-open-comments");
--
1.8.1.2
_______________________________________________
Conkeror mailing list
[email protected]
https://www.mozdev.org/mailman/listinfo/conkeror