tftv keyboard shortcuts

Adds keyboard shortcuts for navigating forum pages on teamfortress.tv

Per 02-09-2015. Zie de nieuwste versie.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==UserScript==
// @name        tftv keyboard shortcuts
// @namespace   Lense
// @description Adds keyboard shortcuts for navigating forum pages on teamfortress.tv
// @include     /^https?://(www\.)?teamfortress.tv/.*/
// @version     0.5
// @grant       none
// ==/UserScript==

// Toggle highlighting of focused post. With this off, there are no visual changes.
var focus_highlight = true;

/*
 * Style post with a highlight
 */
function focus_post(post) {
  if(!focus_highlight) {
    return;
  }
  post.style.background = "#fff";
  post.style.boxShadow = "1px 1px 8px";
  post.style.zIndex = "1";
}

/*
 * Reset style to normal
 */
function unfocus_post(post) {
  post.style.background = "";
  post.style.boxShadow = "";
  post.style.zIndex = "";
}

/*
 * Helper function to scroll to post by id
 */
function goto_post(id) {
  if(prev_post_id != 0) {
    unfocus_post(document.getElementById(prev_post_id));
  }
  prev_post_id = id;

  var post = document.getElementById(id);
  post.scrollIntoView();
  // Show upper border
  window.scrollBy(0,-1);
  // Highlight the current post
  focus_post(post);
}

/*
 * Update styles on plus/minus frag and send the http request
 * id is the post id
 * frag_action is either plus or minus
 */
function frag(id, frag_action) {
  var btn_container = document.querySelector('.post-frag-container[data-post-id="'+id+'"]');
  var type;
  if(btn_container.classList.contains("self")) {
    // This post doesn't actually have frags; it's the OP.
    type = "thread";
    btn_container = document.querySelector('.thread-frag-container' + (type=="post" ? '[data-'+type+'-id="'+id+'"]' : ''));
  } else {
    type = "post";
  }

  // Most of this is ripped+modified from tftv js
  var frag_status = btn_container.attributes["data-frag-status"].value;
  if(frag_status == 'neutral' && frag_action == 'plus' || frag_status == 'minused' && frag_action == 'minus')
    var diff = 1;
  if(frag_status == 'neutral' && frag_action == 'minus' || frag_status == 'plused' && frag_action == 'plus')
    var diff = -1;
  if(frag_status == 'minused' && frag_action == 'plus')
    var diff = 2;
  if(frag_status == 'plused' && frag_action == 'minus')
    var diff = -2;
  var frag_count_container = type=="post" ? btn_container.firstElementChild : btn_container.querySelector("#thread-frag-count");
  var new_frag_count = parseInt(frag_count_container.textContent, 10) + diff;
  frag_count_container.textContent = new_frag_count;
  if(type == "post") {
    btn_container.children[0].classList.remove("positive");
    btn_container.children[0].classList.remove("negative");
    btn_container.children[0].classList.remove("neutral");
    btn_container.children[0].classList.add(new_frag_count > 0 ? "positive" : (new_frag_count < 0 ? "negative" : "neutral"));
  }

  if(frag_status == 'plused' && frag_action == 'plus' || frag_status == 'minused' && frag_action == 'minus')
    new_status = 'neutral';
  if(frag_action == 'plus' && frag_status !== 'plused')
    new_status = 'plused';
  if(frag_action == 'minus' && frag_status !== 'minused')
    new_status = 'minused';
  btn_container.setAttribute("data-frag-status", new_status);

  var plus_classes = btn_container.querySelector("." + type + "-frag-btn.plus").classList;
  var minus_classes = btn_container.querySelector("." + type + "-frag-btn.minus").classList;
  if(frag_action == "plus") {
    if(plus_classes.contains("clicked")) {
      plus_classes.remove("clicked");
    } else {
      plus_classes.add("clicked");
    }
    minus_classes.remove("clicked");
  } else {
    if(minus_classes.contains("clicked")) {
      minus_classes.remove("clicked");
    } else {
      minus_classes.add("clicked");
    }
    plus_classes.remove("clicked");
  }

  var xmlhttp = new XMLHttpRequest();
  xmlhttp.onreadystatechange = function() {
    if(xmlhttp.readyState == XMLHttpRequest.DONE) {
      if(xmlhttp.status != 200) {
        alert('VOTE NOT SENT');
      }
    }
  }
  xmlhttp.open("POST", '/' + type + '/frag/' + (type=="post" ? id : btn_container.attributes["data-thread-id"].value) + '/' + frag_action, true);
  xmlhttp.send();
}

/*
 * Find the number of pages in the thread
 */
var pageList = document.querySelectorAll(".page-btn");
var lastPage = parseInt(pageList[pageList.length-2].textContent);

var posts = document.querySelectorAll(".post");
focus_post(posts[0]);
var cur_post_index = 0;
var prev_post_id = 0;

/*
 * Handle keypresses
 */
document.onkeypress = function(e) {
  // Not entirely sure why this is useful, but it can't break anything that isn't already broken
  e = e || window.event;
  // Ignore keypresses in text boxes, but allow if nothing or a link is selected
  if(e.target.nodeName != "BODY" && e.target.nodeName != "A") {
    // Got keypress, but it's probably in a textbox, so ignore it
    return;
  }

  // Current page number
  var page = window.location.search == "" || parseInt(window.location.search.match("page=([0-9]*)")[1]);

  switch(e["key"]) {
    /*
     * Pages (left/right)
     */
    case "d":
      if(page != lastPage) {
        page = (page+1).toString();
        window.location.search = "?page=" + page;
      }
      break;
    case "a":
      if(page != 1) {
        page = (page-1).toString();
        window.location.search = "?page=" + page;
      }
      break;
    case "D":
      if(page != lastPage) {
        window.location.search = "?page=" + lastPage.toString();
      }
      break;
    case "A":
      if(page != 1) {
        window.location.search = "?page=1";
      }
      break;
    /*
     * Posts (up/down)
     */
    case "w":
      if(cur_post_index > 0) {
        cur_post_index--;
      }
      goto_post(posts[cur_post_index].id);
      break;
    case "s":
      if(cur_post_index < posts.length - 1) {
        cur_post_index++;
      }
      goto_post(posts[cur_post_index].id);
      break;
    case "W":
      cur_post_index = 0;
      goto_post(posts[cur_post_index].id);
      break;
    case "S":
      cur_post_index = posts.length - 1;
      goto_post(posts[cur_post_index].id);
      break;
    /*
     * Frags (+/-)
     */
    case "q":
      frag(posts[cur_post_index].id.slice(8), "plus");
      break;
    case "e":
      frag(posts[cur_post_index].id.slice(8), "minus");
      break;
  }};