/*

Code View
by dotjay, 2006
dotjay.co.uk

*/



/* --- function testing dynamically generated pre.code and running it through the code list function ---
*/

function testGeneratedCode() {
	// create a new pre.code inside a div with id = 'preview' and append it to the page
	var testPre = createElement("pre");
	addClass(testPre,"code");
	testPre.innerHTML = '<code><span class="comment">/* Clean Up */</span></code>'+"\n"
			+'<code><span class="default">$code </span><span class="keyword">= </span><span class="default">substr</span><span class="keyword">(</span><span class="default">$code</span><span class="keyword">, </span><span class="default">33</span><span class="keyword">, -</span><span class="default">16</span><span class="keyword">);</span></code>'+"\n"
			+'<code><span class="default">$code </span><span class="keyword">= </span><span class="default">str_replace</span><span class="keyword">(</span><span class="string"> </span><span class="keyword">, </span><span class="string"> </span><span class="keyword">, </span><span class="default">$code</span><span class="keyword">);</span></code>'+"\n"
			+'<code><span class="keyword"> </span></code>'+"\n";
	var previewDiv = createElement("div");
	previewDiv.id = 'preview';
	previewDiv.appendChild(testPre);
	document.getElementsByTagName("body")[0].appendChild(previewDiv);
	doCodeView(previewDiv);
}



/* --- Required helper functions ---
*/

// generic onload event function by Simon Willison, http://simonwillison.net/2004/May/26/addLoadEvent/
function addLoadEvent(func) {
    var oldonload = window.onload;
    if (typeof window.onload != 'function') window.onload = func;
    else {
        window.onload = function() {
            if (oldonload) oldonload();
            func();
        }
    }
}

function createElement(element) {
	element = element.toLowerCase();
	if (typeof document.createElementNS != 'undefined')
		return document.createElementNS('http://www.w3.org/1999/xhtml', element);
	if (typeof document.createElement != 'undefined')
		return document.createElement(element);
	return false;
}

function addClass(el,val) {
	if (!el.className) el.className = val;
	else {
		newClassName = el.className + " " + val;
		el.className = newClassName;
	}
}

function insertAfter(newElement,targetElement) {
	var parent = targetElement.parentNode;
	if (parent.lastChild == targetElement) parent.appendChild(newElement);
	else parent.insertBefore(newElement,targetElement.nextSibling);
}



/* --- code view ---
*/

// set initial view ('pre' or 'ol', defaults to 'pre')
var initialView = 'ol';
var classCodePre = "code";

function initCodeView() {
	if (!document.getElementsByTagName) return;

	// find all pre elements
	var els = document.getElementsByTagName("pre");
	var numEls = els.length;
	for (var i=0;i<numEls;i++) {
		if (els[i].className && els[i].className.match(classCodePre)) {
			// create, hide and append code list
			var elAlt = createCodeList(els[i]);

			if (initialView === 'ol') els[i].style.display = 'none';
			else elAlt.style.display = 'none';
			insertAfter(elAlt,els[i]);

			// build toggle control
			var elToggle = createElement("a");
			elToggle.appendChild(document.createTextNode("Toggle Code View"));
			elToggle.setAttribute('href',"javascript:;");

			// add toggle event
			elToggle.onclick = function (e) {
				toggleCodeView(this);
			}
			if (elToggle.captureEvents) elToggle.captureEvents(Event.ONCLICK);

			// append control to paragraph and insert before the list
			var elToggleWrap = createElement("p");
			if (initialView === 'ol') addClass(elToggleWrap,"contract");
			else addClass(elToggleWrap,"expand");
			elToggleWrap.appendChild(elToggle);
			els[i].parentNode.insertBefore(elToggleWrap,els[i]);
		}
	}
}

function doCodeView(el) {
	var els = el.childNodes;
	var numEls = els.length;

	// find all pre elements
	for (var i=0;i<numEls;i++) {
		if ((els[i].nodeName.toLowerCase() == "pre") && els[i].className && els[i].className.match(classCodePre)) {
			// create, hide and append code list
			var elAlt = createCodeList(els[i]);

			if (initialView === 'ol') els[i].style.display = 'none';
			else elAlt.style.display = 'none';
			insertAfter(elAlt,els[i]);

			// build toggle control
			var elToggle = createElement("a");
			elToggle.appendChild(document.createTextNode("Toggle Code View"));
			elToggle.setAttribute('href',"javascript:;");

			// add toggle event
			elToggle.onclick = function (e) {
				toggleCodeView(this);
			}
			if (elToggle.captureEvents) elToggle.captureEvents(Event.ONCLICK);

			// append control to paragraph and insert before the list
			var elToggleWrap = createElement("p");
			if (initialView === 'ol') addClass(elToggleWrap,"contract");
			else addClass(elToggleWrap,"expand");
			elToggleWrap.appendChild(elToggle);
			els[i].parentNode.insertBefore(elToggleWrap,els[i]);
		}
	}
}

// creates an ordered list as the alternative display for preformatted lines in code elements
// note: it is impractical to use line returns to split lines in IE, so use a code element for each line in the pre
function createCodeList(elCodePre) {
	var elCodeOl = createElement("ol");
	addClass(elCodeOl,'code');

	// iterate through list to grab lines of code
	var odd = true;
	var elsNodes = elCodePre.childNodes;
	var numNodes = elsNodes.length;
	for (var i=0;i<numNodes;i++) {
		// if we have a line of code, grab it (cheat a little and grab innerHTML)
		if (elsNodes[i].nodeName.toLowerCase() === 'code') {
			var elCode = createElement("code");
			elCode.innerHTML = elsNodes[i].innerHTML;

			var elCodeLi = createElement("li");
			elCodeLi.appendChild(elCode);

			// alternate the classes
			if (odd) {
				addClass(elCodeLi,'odd');
				odd = false;
			} else odd = true;

			elCodeOl.appendChild(elCodeLi);
		}
	}

	return elCodeOl;
}

function toggleCodeView(control) {
	var elOrig = control.parentNode.nextSibling;
	var elAlt = elOrig.nextSibling;

	if (elAlt.style.display == 'none') {
		elOrig.style.display = 'none';
		elAlt.style.display = 'block';
		control.parentNode.className = "contract";
	} else {
		elAlt.style.display = 'none';
		elOrig.style.display = 'block';
		control.parentNode.className = "expand";
	}
}

addLoadEvent(initCodeView);

