Pull to refresh

Отделяем зерна от плевел в Google Reader

Reading time6 min
Views716

GreasemonkeyНа работе я стараюсь не читать Хабр и другие тематические сайты, они слишком затягивают. Можно потратить весь день на чтение статей, а по работе так ничего и не сделать. Но пропускать что-то новое и интересное я тоже не хочу, поэтому подписываюсь на различные RSS-каналы. После работы, а чаще в выходные, я открываю Google Reader и просматриваю весь список накопившихся постов. Некоторые из них написаны на интересные для меня темы, остальные — нет. Это напоминает мне чтение электронной почты, только входящие письма и спам попадают в одну папку.

Сначала я с этим мирился, но на этих выходных, с помощью Greasemonkey скрипта, исправил ситуацию.


Google Reader Screenshot

В Google Reader появилась новая кнопка: «Mark selected as read», а у каждой статьи - checkbox.

Теперь, просматривая список постов, я сразу же отмечаю неинтересные для меня и «прочитываю» их одной кнопкой. Остаются только те, что заслуживают дальнейшего внимательного изучения.

Если вам понравилась идея, можете установить Greasemonkey скрипт. Для его работы требуется Mozilla Firefox и расширение Greasemonkey.

Из недостатков стоить отметить невозможность работы скрипта в Google Chrome. Причиной этому служит ошибка браузера в обработке созданных KeyboardEvent.

На всякий случай публикую исходный код скрипта:
// ==UserScript==
// @name     Google Reader - Mark selected items as read
// @namespace   twitter.com/rodiontsev
// @description  This script adds a button "Mark selected as read" and checkbox for each item.
// @include    htt*://www.google.tld/reader/view/*
// ==/UserScript==

/*
Version history

1.0 on 10/01/2009:
  - Initial version.
*/

var buttonText = "Mark selected as read";
var buttonId = "mark-selected-as-read";
var articles = new Array();

document.addEventListener("DOMNodeInserted", function(event){nodeInserted(event);}, true);

function nodeInserted(event) {
  var entries = document.getElementById("entries");
  if (entries && matchClass(entries, "list")) {
    var button = document.getElementById(buttonId);
    if (!button) {
      articles = new Array();
      appendButton();
    }
    
    var element = event.target;
    if (element. className && element.className.match(/entry\s+entry-\d+/) != null) {
      articles.push(element);
      
      var checkbox = document.createElement("input");
      checkbox.type = "checkbox";
      checkbox.className = "mark-selected-as-read-checkbox-class";
      checkbox.style.marginRight = "9px";
      checkbox.style.verticalAlign = "top";
      checkbox.addEventListener("click", function(event) {event.stopPropagation();}, true);
      var entrySecondary = element.getElementsByClassName("entry-secondary")[0];
      entrySecondary.insertBefore(checkbox, entrySecondary.firstChild);
    }
  }
}

function appendButton() {
  var viewerTopControlsId = "viewer-top-controls";
  var markAllAsReadId = "mark-all-as-read-split-button";

  var divVewerTopControls = document.getElementById(viewerTopControlsId);
  var btnMarkAllAsRead = document.getElementById(markAllAsReadId);

  if ((divVewerTopControls != null) && (btnMarkAllAsRead != null)) {
    var button = document.createElement("div");
    button.className = "goog-button goog-button-base unselectable goog-inline-block goog-button-float-left goog-button-tight scour-disabled viewer-buttons";
    button.id = buttonId;
    button.innerHTML = "<div class=\"goog-button-base-outer-box goog-inline-block\">"
             + "<div class=\"goog-button-base-inner-box goog-inline-block\">"
             + "<div class=\"goog-button-base-pos\">"
             + "<div class=\"goog-button-base-top-shadow\"> </div>"
             + "<div class=\"goog-button-base-content\">"
             + "<div class=\"goog-button-body\">" + buttonText + "</div>"
             + "</div>"
             + "</div>"
             + "</div>"
             + "</div>";
    button.addEventListener("click", markSelectedAsRead, false);
    divVewerTopControls.insertBefore(button, btnMarkAllAsRead);
  }
}

function matchClass (element, sClassName) {
  return (sClassName
     && element.className
     && element.className.length
     && element.className.match(new RegExp("(^|\\s+)(" + sClassName +")($|\\s+)")));
}

function simulateClick(node) {
  var event = node.ownerDocument.createEvent("MouseEvents");
  event.initMouseEvent("click", true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
  node.dispatchEvent(event);
}

function simulateKeypress(node, keyCode) {
  var event = node.ownerDocument.createEvent("KeyboardEvent");
  event.initKeyEvent("keypress", true, true, null, false, false, false, false, keyCode, 0);
  node.dispatchEvent(event);
}

function simulateRead(node) {
  simulateKeypress(node, 77); //"m" button - mark entry as read.
}

function simulateCollapse(node) {
  simulateKeypress(node, 79); //"o" button - expand/collapse entry.
}

function getArticleIcon(article) {
  var divs = article.getElementsByTagName("div");
  for (var i = 0; i < divs.length; i++) {
    var div = divs[i];
    if (matchClass(div, "entry-icons")) return div;
  }
  return null;
}

function markSelectedAsRead() {
  var container = document.getElementById("entries");
  container.style.display = "none";
  for (var i = 0; i < articles.length; i++) {
    var article = articles[i];
    var checkbox = article.getElementsByTagName("input")[0];
    if (checkbox.checked) {
      if (!(matchClass(article, "read"))) {
        var articleIcon = getArticleIcon(article);
        simulateClick(articleIcon);
        if (!(matchClass(article, "read"))) {
          simulateRead(articleIcon);
        }
        if (matchClass(article, "expanded")) {
          simulateCollapse(articleIcon);
        }
      }
      checkbox.checked = false;
    }
  }
  container.style.display = "block";
}

* This source code was highlighted with Source Code Highlighter.
Tags:
Hubs:
Total votes 63: ↑52 and ↓11+41
Comments46

Articles