// ljwho user script
// version 0.21 BETA!
//
// 2006-11-26
// Copyright (c) 2006, Thomas Boutell and Boutell.Com, Inc.
// Released under the GPL license
// http://www.gnu.org/copyleft/gpl.html
//
// --------------------------------------------------------------------
//
// This is a Greasemonkey user script.
//
// To install, you need Greasemonkey: http://greasemonkey.mozdev.org/
// Then restart Firefox and revisit this script.
// Under Tools, there will be a new menu item to "Install User Script".
// Accept the default configuration and install.
//
// To uninstall, go to Tools/Manage User Scripts,
// select "ljwho", and click Uninstall.
//
// WHAT'S NEW (changelog):
//
// Version 0.21:
// Correctly handles more than one _ in a name.
//
// Version 0.2: 
// Allow _ as well as - in names.
// Allow community.livejournal.com.
// Allow syndicated.livejournal.com.
// Ignore links that don't contain the username in text. This
//   prevents most unnecessary RN's from appearing.
// 
// --------------------------------------------------------------------
//
// ==UserScript==
// @name          ljwho
// @namespace     http://www.boutell.com/greasemonkey/
// @description   Attach private real-name notes to LJ usernames. Notes are stored on YOUR drive, NO ONE ELSE can see them.
// @include       http://livejournal.com/*
// @include       http://*.livejournal.com/*
// ==/UserScript==

var allLinks, thisLink;
allLinks = document.evaluate(
    '//a[@href]',
    document,
    null,
    XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
    null);

for (var i = 0; i < allLinks.snapshotLength; i++) {
    var thisLink = allLinks.snapshotItem(i);
    var who = getLJNameFromLink(thisLink);
    if (who) {
		var realName = GM_getValue("realnames:" + who);
		if (realName == "") {
			realName = null;
		}
		if (realName) {
			thisLink.setAttribute("title", realName);
		}
		var parent = thisLink.parentNode;
		var child = document.createElement('span');
		child.setAttribute("class", "ljwhospan");
		child.setAttribute("ljwhoname", who);
		var color = "#88FF88;";
		if (!realName) {
			color = "#FF8888";
		}
		child.setAttribute("style", 
			"cursor: pointer; " + 
			"margin: 4px; font-weight: bold; font-size: 8px; " +
			"background-color: black; color: " + color + ";");
		if (realName) {
			child.setAttribute("title", realName);
			
		}
		var text = "RN";
		var textNode = document.createTextNode(text);
		child.appendChild(textNode);
		parent.insertBefore(child, thisLink.nextSibling);
		child.addEventListener("click", editRealName, true);
	}
}

function getLJNameFromLink(link)
{
    var href = link.getAttribute("href");
    var who;
    if (href) {
      matched = href.match(/([\w\-\_]+)\.livejournal.com\/?$/);
      if (matched) {
        who = matched[1];
      } else {
        matched = href.match(/^http\:\/\/(livejournal.com\/users|www.livejournal.com\/users|community.livejournal.com|syndicated.livejournal.com)\/([\w\_\-]+)\/?$/);
        if (matched) {
          who = matched[2];
        }
      }	 
      // Undoubtedly this list is too short
      if (who && (who != 'www') && (who != 'stat') && (who != 'my') &&
	(who != 'news')) {
        // 0.2: make sure there's a text child node that
        // contains the username. If there isn't, this is
        // a usericon next to a separate username link, or
        // an "my lj" link, "entries" link, etc.
        // so displaying RN would be redundant. 
        text = getCompleteText(link);
        // Work around LJ's _/- equivalence
	// 0.21: global for multi-underscore names like foo_bar_blam
        text = text.replace(/_/g, "-");
        whoC = who.replace(/_/g, "-");
        if (text.search(whoC) != -1) {
          return who;
        }
      }
    }
    return null;	
}

function getCompleteText(node)
{
  var i;
  var text = "";
  for (i = 0; (i < node.childNodes.length); i++) {
    var c = node.childNodes[i];
    if (c.nodeName == "#text") {
      text += c.nodeValue;
    } else {
      text += getCompleteText(c);
    }
  }
  return text;
}

function editRealName()
{
	var who = this.getAttribute("ljwhoname");
	var realName;
	if (who) {
		realName = GM_getValue("realnames:" + who);
	}
	if (!realName) {
		// Prettier than "Undefined"
		realName = "";
	}
	realName = prompt("Real name for " + who + ":", realName);
	if (realName != null) { 
		GM_setValue("realnames:" + who, realName); 	
		var allLinks, thisLink;
		allLinks = document.evaluate(
		    '//a[@href]',
		    document,
		    null,
		    XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
		    null);

		for (var i = 0; i < allLinks.snapshotLength; i++) {
		    var thisLink = allLinks.snapshotItem(i);
		    var linkWho = getLJNameFromLink(thisLink);
		    if (who == linkWho) {
		       thisLink.setAttribute("title", realName);
                    }
                }
		var allSpans, thisSpan;
		allSpans = document.evaluate(
		    "//span[@class='ljwhospan']",
		    document,
		    null,
		    XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
		    null);

		for (var i = 0; i < allSpans.snapshotLength; i++) {
		    var thisSpan = allSpans.snapshotItem(i);
		    var spanWho = thisSpan.getAttribute('ljwhoname');
		    if (who == spanWho) {
		       thisSpan.setAttribute("title", realName);
		       if (realName != "") {
	 	         thisSpan.style.color = "#88FF88;";
		       } else {
		         thisSpan.style.color = "#FF8888";
		       }
                    }
                }
	}
}


