// ==UserScript==
// @name        Slashdot - comment tree
// @namespace   http://www.cs.uni-magdeburg.de/~vlaube/Projekte/GreaseMonkey/
// @description Allows you to collapse and expand comments
// @include     http://slashdot.org/*
// @include     http://*.slashdot.org/*
// ==/UserScript==

// This script was inspired by Matthew Gertners "Slashdot Live Comment Tree" script (http://www.allpeers.com/blog/?p=137)
// 2005/10/14 - Mark Langenhoven (http://www.langenhoven.com/code/)
// Extended the script to include a collapse button at the bottom of each comment 
// so that long comments don't require paging up to collapse again

function addGlobalStyle(css) {
	var head, style;
	head = document.getElementsByTagName('head')[0];
	if (!head) { return; }
	style = document.createElement('style');
	style.type = 'text/css';
	style.innerHTML = css;
	head.appendChild(style);
}

function addClass(node, name) {
	node.className += " "+name;
}

function removeClass(node, name) {
	var regex = new RegExp("(.*)"+name+"(.*)");
	node.className = node.className.replace(regex, "$1$2");
}

function hasClass(node, name) {
	var regex = new RegExp(".*"+name+".*")
	return node.className.match(regex);
}

function collapseComment(titlenode) {
	// get all following siblings of titlenode and its parent

      if (titlenode.firstChild.id=="sct_icon_b") {
        //Because I am too lazy to rewrite this function, I will just jump to the 
        //original node that this was worked off
        titlenode = titlenode.parentNode.firstChild.nextSibling.firstChild.nextSibling;
      }
	var xpath = "following-sibling::* | parent::div[@class='commentTop']/following-sibling::*";
	var results=document.evaluate(xpath,titlenode,null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null);
	for (var i=0; i<results.snapshotLength; i++) {
		var node = results.snapshotItem(i);
		addClass(node, "sct_collapsed");
	}
	addClass(titlenode, "sct_collapsedtitle");
}

function expandComment(titlenode) {
	// get all following siblings of titlenode and its parent
	var xpath = "following-sibling::* | parent::div[@class='commentTop']/following-sibling::*";
	var results=document.evaluate(xpath,titlenode,null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null);
	for (var i=0; i<results.snapshotLength; i++) {
		var node = results.snapshotItem(i);
		removeClass(node,"sct_collapsed");
	}
	removeClass(titlenode, "sct_collapsedtitle");
}

function setCollapsedStyle(titlenode) {
	titlenode.firstChild.firstChild.nodeValue = "[+]";
}

function setExpandedStyle(titlenode) {
	titlenode.firstChild.firstChild.nodeValue = "[-]";
}

function toggleState(event) {
	var titlenode = event.target.parentNode;
	if(hasClass(titlenode, "sct_collapsedtitle")) {
		expandComment(titlenode);
		setExpandedStyle(titlenode);
	}
	else {
		collapseComment(titlenode);
		setCollapsedStyle(titlenode);
	}
}

function addIcon(titlenode, how) {
	var icon = document.createElement("div");
      if (how=="0") {
     	  var text = document.createTextNode("[-]");
      } else {
        var text = document.createTextNode("[^]");
        icon.id="sct_icon_b";
      }

      icon.className="sct_icon";
	icon.addEventListener("mousedown", toggleState, false);
	icon.appendChild(text);

      if (how=="0") { 
    	   titlenode.insertBefore(icon, titlenode.firstChild);
      } else {
        titlenode.parentNode.insertBefore(icon, titlenode);
      }

}

addGlobalStyle("div.sct_icon { display:inline; cursor:pointer;}");
addGlobalStyle("div.sct_icon:hover { display:inline; color:white; }");
addGlobalStyle(".sct_collapsed { display:none; }");
addGlobalStyle(".sct_collapsedtitle { }");

//Add the collapse button at the bottom of each comment
var xpath="//li[@class='comment']";
var results=document.evaluate(xpath,document,null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null);
for(var i=0; i<results.snapshotLength; i++) {
	addIcon(results.snapshotItem(i).firstChild.nextSibling.nextSibling.nextSibling.nextSibling, "1");
}

var xpath="//li[@class='comment']/div[@class='commentTop']/div[@class='title']";
var results=document.evaluate(xpath,document,null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null);
for(var i=0; i<results.snapshotLength; i++) {
	addIcon(results.snapshotItem(i), "0");
}



// well, the new layout is not perfect. i have to wrap the stuff below the commentBody in a div by hand.
results=document.evaluate("//li[@class='comment']/div[@class='commentBody']",document,null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null);
for(var i=0; i<results.snapshotLength; i++) {
	var container = document.createElement("div");
	var results2=document.evaluate("following-sibling::* | following-sibling::text()",results.snapshotItem(i),null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null);
	for(var j=0; j<results2.snapshotLength; j++) {
		container.appendChild(results2.snapshotItem(j));
	}
	results.snapshotItem(i).parentNode.appendChild(container);
}

