var toc={
	generate:function() {
		this.loopElements(document.body);
		this.debug();
	},
	ul:null,
	level:null,
	tagNameMatch:/^[hH][123456]$/,
	debug:function() {
		return;
		if (this.ul!=null) {
			var ul=this.ul;
			while(ul && ul.className!='toc') {
				ul=ul.parentNode;
			}
			var tmp=document.createElement('div');
			tmp.style.border='1px solid #FF0000';
			ul.parentNode.insertBefore(tmp,ul);
			tmp.appendChild(document.createTextNode(ul.innerHTML));
		}
	},
	newTOC:function(h1) {
		this.debug();
		this.ul=document.createElement('div');
		this.ul.className='toc';
		h1.parentNode.insertBefore(this.ul,h1.nextSibling);
		this.level=1;
	},
	nextHeader:function(el) {
		var level=el.tagName.substr(1,1);
		if (level==1) {
			this.newTOC(el);
		}
		while (level<this.level) {
			this.ul=this.ul.parentNode;
			while (this.ul.tagName.toLowerCase()=='li') {
				this.ul=this.ul.parentNode;
			}
			this.level--;
		}
		while (level>this.level) {
			var tmp=document.createElement('ul');
			if (this.ul.tagName.toLowerCase()=='ul') {
				var tmp2=this.ul.lastChild;
				while (tmp2 && tmp2.nodeType!=1) {
					tmp2=tmp2.previousSibling;
				}
				if (!tmp2 || tmp2.tagName.toLowerCase()!='li') {
					tmp2=document.createElement('li');
					this.ul.appendChild(tmp2);
				}
				this.ul=tmp2;
			}
			this.ul.appendChild(tmp);
			this.ul=tmp;
			this.level++;
		}
		var parent=this.ul;
		if (level==1) {
			parent=document.createElement('span');
			parent.className='h1';
			this.ul.appendChild(parent);
		} else if (parent.tagName.toLowerCase()=='ul') {
			parent=document.createElement('li');
			this.ul.appendChild(parent);
		}
		parent.appendChild(this.maybeLink(
			this.findTarget(el),this.elementText(el)
		));
	},
	loopElements:function(el) {
		for(
			el=el.firstChild;
			el;
			el=el.nextSibling
		) {
			if (el.nodeType==1) {
				if (el.tagName.match(this.tagNameMatch)) {
					this.nextHeader(el);
				}
				this.loopElements(el);
			}
		}
	},
	elementText:function(el) {
		var text='';
		for(
			el=el.firstChild;
			el;
			el=el.nextSibling
		) {
			switch (el.nodeType) {
				case 1:text+=this.elementText(el);break;
				case 3:
				case 4:text+=el.nodeValue;break;
			}
		}
		return text;
	},
	maybeLink:function(target,text) {
		var txt=document.createTextNode(text);
		if (target!=null) {
			var link=document.createElement('a');
			link.href='#'+target;
			link.appendChild(txt);
			return link;
		}
		return txt;
	},
	findTarget:function(header) {
		var node=header.previousSibling;
		while (node && node.nodeType!=1) {
			node=node.previousSibling;
		}
		if (node && node.tagName.toLowerCase()=='a' && node.name!='') {
			return node.name;
		}
		return null;
	}
}

