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]);
		}
	}
}

// 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";
	}
}

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]);
        }
    }
}

addLoadEvent(initCodeView);

