Pinboard - Taglist Highlighting in Posting Page

By murklins Last update Oct 10, 2011 — Installed 2,489 times.
// ==UserScript==
// @name Pinboard - Taglist Highlighting in Posting Page
// @description When adding a bookmark using the "popup with tags" page, highlight assigned tags in the taglist.
// @include http://pinboard.in/add*
// @include http://www.pinboard.in/add*
// @include https://pinboard.in/add*
// @include https://www.pinboard.in/add*
// ==/UserScript==

//***** CONFIGURATION *****

var highlightStyle = "background-color: rgb(255, 248, 198);";

//***** CODE ******

highlightStyle = highlightStyle.trim();
if (highlightStyle.charAt(highlightStyle.length-1) == ";") {
  highlightStyle = highlightStyle.substring(0, highlightStyle.length-1);
}

// Only bother with this whole process if we can identify the "tags" form element
var tagsInput = document.getElementById("tags");
if (!tagsInput) {
  GM_log("Can't find tags element. Exiting script.");
  return;
}	

// get the tags in the taglist
var taglist = document.evaluate("//div/a[contains(@onclick, 'add_tag')]", document, null,
                                  XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
                                  null);
if (taglist.snapshotLength == 0) {
    GM_log("Couldn't find tag list. Exiting script.");
    return;    
}

var prevTags = [];
addEventListeners();

// get autocomplete div -- can take a while since it has to be 
// constructed by the page before it's available
var pinAC = null;
var maxPinACAttempts = 3;
for (var i = 0; i < maxPinACAttempts; i++) {
  window.setTimeout(function() { getPinAC(); }, i * 300);
}

function getPinAC() {
  if (pinAC == null) {
    var nodes = document.evaluate("//div[contains(@class, 'pin-ac')]", document, null,
                              XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
                              null);
    if (nodes.snapshotLength == 1) {
      // track mousedowns on the autocomplete dropdown
      pinAC = nodes.snapshotItem(0);
      pinAC.addEventListener("mousedown", function(event) {highlightTags();}, false);
    }
  }
}

function addEventListeners() {
  for (var i = 0; i < taglist.snapshotLength; i++) {
    var t = taglist.snapshotItem(i);
    
    // give each tag link a unique ID based on its innerHTML
    var tagName = escapeTag(t.innerHTML.trim());
    t.id = "gm_highlightTags_" + tagName.toLowerCase();
    
    // and listen to every tag link click
    t.addEventListener("click", function(event) {highlightTags();}, false);
  }
  
  // track events on the tags input
  tagsInput.addEventListener("keyup", function(event) {highlightTags();}, false);
  tagsInput.addEventListener("change", function(event) {highlightTags();}, false);
    
  // highlight any pre-assigned tags
  highlightTags();
}

// the function that highlights the tags!
function highlightTags() {

  // check the difference between the tags that are now in the tags input and
  // the ones that were in there the last time we highlighted
  var newTags = tagsInput.value.trim().toLowerCase();
  if (newTags == "") {
    newTags = [];
  }
  else {
    newTags = newTags.split(/\s+/);
  }
  var addHighlight = diff(newTags, prevTags);
  var removeHighlight = diff(prevTags, newTags);
  
  // remove highlighting from tags that got deleted
  for (var i = 0; i < removeHighlight.length; i++) {
    var tagId = "gm_highlightTags_" + escapeTag(removeHighlight[i]);
    var tnode = document.getElementById(tagId);
    if (tnode) {
      var style = tnode.getAttribute("style");
      var newStyle = removeStyle(highlightStyle, style);
      tnode.setAttribute("style", newStyle);
    }
  }
  
  // highlight the tags that were added
  for (var i = 0; i < addHighlight.length; i++) {
    var tagId = "gm_highlightTags_" + escapeTag(addHighlight[i]);
    var tnode = document.getElementById(tagId);
    if (tnode) {
      style = tnode.getAttribute("style");
      var newStyle = addStyle(highlightStyle, style);
      tnode.setAttribute("style", newStyle);
    }
  }
  
  // set the current tags
  prevTags = newTags;
}

function removeStyle(styleToDelete, wholeStyle) {
  var style = wholeStyle.trim().split(/\s*;\s*/);
  var newStyle = "";
  for (var s = 0; s < style.length; s++) {
    if ((style[s].trim() != styleToDelete) && (style[s].trim() != "")) {
      newStyle = style[s] + ";";
    }
  }
  return newStyle;
}

function addStyle(styleToAdd, wholeStyle) {
  var style = wholeStyle.trim();
  if (style.charAt(style.length-1) != ";") {
    style = style + ";";
  }
  return style + styleToAdd + ";";
}

function escapeTag(tag) {
  var escapedTag = tag.replace(/[\']/g,"_");
  return escapedTag.replace(/[\"]/g,"__");
}

String.prototype.trim = function() {
	return this.replace(/^\s+|\s+$/g,"");
};

function diff(a, b) {
  var diff = [];
  var match = false;
  for (var i = 0; i < a.length; i++) {
    for (var j = 0; j < b.length; j++) {
      if (a[i] === b[j]) {
        match = true;
        break;
      }
    }
    match ? match = false :  diff.push(a[i]);
  }
  return diff;
}