// jsHighlighter.  (C) 2003 Arve Bersvendsen
// http://virtuelvis.com/
// Free for personal / non-commercial use, provided
// this notice is intact.  For commercial usage,
// contact the author.  Contact information available at
// http://virtuelvis.com/help/contact.html

var isIE = false;
/*@cc_on
var isIE = true; @*/

/*
  Does haystack have needle?
*/
Array.prototype.hasValue = function(needle){
  for (var i = 0; i < this.length; i++){
      if (this[i] == needle){
        return true;
      }
  }
  return false;
}   

var snippets = new Array();
var codeLang = new Array();
var tabWidth = 2;

function setKeywords(inStr) {
  var inStr;
      if (codeLang[currentClass].colorA){
        var colorA = codeLang[currentClass].colorA;
        for (var j = 0; j < colorA.length; j++) {
          var keyWord = new RegExp ("\([^a-zA-Z0-9])("+colorA[j]+")([^a-zA-Z0-9])","img");
          inStr = inStr.replace(keyWord, "$1<span class='chReserved'>$2</span>$3");
        }
      }

      if (codeLang[currentClass].colorB){
        var colorB = codeLang[currentClass].colorB;
        for (var j = 0; j < colorB.length; j++) {
          var keyWord = new RegExp ("(\:.*)\([^a-zA-Z0-9])("+colorB[j]+")([^a-zA-Z0-9])","img");
          inStr = inStr.replace(keyWord, "$1$2<span class='chProps'>$3</span>$4");
        }
      }  
      return inStr;
}

function setCodeBlocks() {
  // shorthand property
  var elm = document.getElementsByTagName('pre');
  
  // block delimeters
  var blockStart, blockEnd;
  for (var i = 0; i < elm.length; i++) {
    currentClass = elm[i].className;
    
    // are there syntax rules available
    // for the <pre> we're currently 
    // processing?
    if (codeLang[currentClass]) {
      // IE 'breaks' with nodeValue
      // isIE is being set by a MSIE-specific 
      // preprocessor-directive (see top)
      if (isIE) {
        inStr = elm[i].innerHTML;   
      } else {
        inStr = elm[i].firstChild.nodeValue;
      }
      var outStr = "";
    	var elementContext = 0;
      
      // colorize keywords
      inStr = setKeywords(inStr);

      // get the actual block delimeters
      var blockStart = codeLang[currentClass].blockDelims[0];
      var blockEnd = codeLang[currentClass].blockDelims[1];

      // special character handling.
      for (q = 0; q < inStr.length; q++){
				switch (inStr.charAt(q)) {
          // set up context for markup already defined
          case "<":
            elementContext++;
            outStr += "<";
            break;
          case ">":
            elementContext--;
            outStr += ">";
            break;
          // Are there collapsible blocks?
          case blockStart:
            outStr+= "<span class='chBlockStart' title='Click to expand/collapse block'>";
            outStr+= inStr.charAt(q);
            outStr+= "</span><span class='chBlock'>";
            break;
          case blockEnd:
            outStr+= "</span><span class='chBlockEnd'>";
            outStr+= inStr.charAt(q);
            outStr+= "</span>";
            break;
          // spaces. &nbsp; if not inside element context
          case "\x20":
            if (elementContext == 0) {
              outStr += "&nbsp;";
            } else {
              outStr += " ";
            }
            break;
          // fix carriage returns and linefeeds so result
          // looks similar in MSIE and other browsers
          // isIE is being set by a MSIE-specific 
          // preprocessor-directive (see top)
          case "\r":
            if (!isIE) {
              outStr += "\r";            
            } else {
              outStr += "&nbsp;<br />";
            }
            break;
          case "\n":
            if (!isIE) {
              outStr += "\n";            
            } else {
              outStr += "";
            }   
            break;
          // reformat tabs to use &nbsp;s
          case "\x09":
            for (var z = 1; z <= tabWidth; z++) {
              outStr+="&nbsp;";
            }
            break;
          // if no other condition is met, output input
          default:
            outStr += inStr.charAt(q);
            break;
				}
      }
      
      elm[i].innerHTML = outStr;

      // Attach events to opening block delimeter
      // so we can collapse code
			var spans = elm[i].getElementsByTagName("span");
      attachCollapseEvent(spans);     
    }
  }
  return true;
}

function attachCollapseEvent(spans) {
  for (var w = 0; w < spans.length; w++){
    if ( spans[w].className == "chBlockStart"){
      spans[w].onclick = toggleNextVisibility;     
    } else if (spans[w].className == "chBlockEnd"){
      spans[w].onclick = togglePrevVisibility;     
    }
  }
  return true;
}


function toggleNextVisibility(){
  if (this.nextSibling.style.display != "none"){
    // create some notice of hidden text
    this.nextSibling.style.display = "none";
  } else {
    this.nextSibling.style.display = "inline";
  }
}


function togglePrevVisibility(){
  if (this.previousSibling.style.display != "none"){
    // create some notice of hidden text
    this.previousSibling.style.display = "none";
  } else {
    this.previousSibling.style.display = "inline";
  }
}

// initialize codeHighlighter
function init(){
  var foo = new Date();
  setCodeBlocks();
  var bar = new Date();
  document.getElementById('measure').firstChild.nodeValue = (bar - foo);
  return false;

}

window.onload = init;