/*  to do:
    Safari Bugs:
      Code has been changed to work around Safari bugs.  
      Specifically, Safari doesn't run more than one animation at a time well.
      Also, mouse over/out events seem to get dropped more in Safari.  Not sure if this is Safari bug or Dojo.  Will look into it.
*/


dojo.require("dojo.behavior");
dojo.require("dojo.string.extras");
dojo.require("dojo.html");
dojo.require("dojo.fx.html");

// globals
var c = null;
var inr = null;
var x = null;
var y = null;
var anim = null;
var sliderYOffest_int = 240; // place up here for tweaky convenience
var browser = dojo.render.html;
var hlOnColor = "rgb(255, 255, 255)";
var hlOffColor = "#454545";
var safariSweeperInterval = null; // seems new events terminate running functions in Safari, so the cleanup sweeper runs every 500ms in Safari

var sitepen = {};
sitepen.init= function(){
  sitepen.represent.pageParser(document.getElementsByTagName("body").item(0),sitepen.represent.outerSpan);
  sitepen.represent.outerSpan._lastOffsetTop = 0;  // need to track this to fix IE bug
  inr.appendChild(sitepen.represent.outerSpan);
}
sitepen.represent={};
sitepen.represent.spans_a = []; // contains references to all spans, so scanning them is easier.  scanning is done to get around event buggyness.
sitepen.represent.activeSpan_ref = null; //need to track this b/c mouseout event isn't always captured
sitepen.represent.outerSpan = document.createElement("span");
sitepen.represent.pageParser=function(currentElement_ref, parentSpan_ref){
  function fixAttribute(s) { return fixText(s).replace(/\"/g, "&quot;"); }
  function fixText(s) { return String(s).replace(/\&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;"); }
  function getAttributeString(node_ref){
    var a_str = "";
	  try {
      for (var ni = 0; ni < node_ref.attributes.length; ni++) {
        if (node_ref.attributes.item(ni).specified) {
          a_str +=(" " + node_ref.attributes.item(ni).nodeName.toLowerCase() + "=\"" + fixAttribute(node_ref.attributes.item(ni).nodeValue) + "\"");
        }
			}
  	} catch(e) {
        //alert(node_ref.attributes.item(ni).nodeName)
    }
    return a_str;
  };
  currentElement_ref.sitepen={}; // create pointer from page element to highlight span
  currentElement_ref.sitepen.hlSpan=parentSpan_ref; // create pointer from page element to highlight span
  var cn_c = currentElement_ref.childNodes; // get children of currentElement_ref
  for(var cn_i=0;cn_i<cn_c.length;cn_i++){ //iterate over childNodes, calling this function recursively
    var innerSpan = parentSpan_ref.appendChild(document.createElement("span")); // create new span as child node of current span
    sitepen.represent.spans_a.push(innerSpan); // collect span references for easy scanning later. 
    if(cn_c.item(cn_i).tagName){ // filter out textnodes, which need to be treated differently
      var start_str = "<" + cn_c.item(cn_i).tagName.toLowerCase() + getAttributeString(cn_c.item(cn_i)) + ">"; // make opening tag string
      innerSpan.appendChild(document.createTextNode(start_str));
      sitepen.represent.pageParser(cn_c.item(cn_i),innerSpan); // RECURSE!  that's the important part of the whole function
      if(cn_c.item(cn_i).tagName.toLowerCase()!="img"){
        var end_str = "</" + cn_c.item(cn_i).tagName.toLowerCase() + ">"; // make closing tag string
        innerSpan.appendChild(document.createTextNode(end_str));
      }
    }else{
      var start_str = cn_c.item(cn_i).nodeValue; // make textnode sting
      innerSpan.appendChild(document.createTextNode(start_str));
    }
  }
};

sitepen.represent.sweeper = function(){ // this is s kludge to fix an event problem: span highlights don't always return on mouse out.  especially in Safari
  if(browser.safari){
    var test_int = 0; // check if more that one span is highlighted
    for(var si=0; si<sitepen.represent.spans_a.length; si++){
      if(sitepen.represent.spans_a[si].style.color==hlOnColor){ // if this span is still highlighted...
        if(sitepen.represent.activeSpan_ref!=sitepen.represent.spans_a[si]){ // and it's not the currently selected one
          sitepen.represent.spans_a[si].style.color = hlOffColor;
          test_int++
        }
      }
    }
  }else{
    for(var si=0; si<sitepen.represent.spans_a.length; si++){
      if(sitepen.represent.spans_a[si].style.color==hlOnColor){ // if this span is still highlighted...
        if(sitepen.represent.activeSpan_ref!=sitepen.represent.spans_a[si]){ // and it's not the currently selected one
          dojo.fx.html.textColorFade(sitepen.represent.spans_a[si], 600, hlOnColor, hlOffColor);
        }
      }
    }
  }
}

var imageOver = {
	"image_over": {
		"onmouseover": function(evt){
			var n = evt.target;
			var src = n.src;
			n.src = src.replace(".jpg", "On.jpg");// replace the image with the On image
			// fade the code in
			if(anim) { anim.stop(); }
      var np = n.sitepen.hlSpan.parentNode; // go up 2 levels for bigger, better-looking highlight area.
      sitepen.represent.activeSpan_ref = np; // need to track this b/c mouseout event isn't always captured
      var ySlide_int = sliderYOffest_int - np.offsetTop; // get the slideTo offset
			if(browser.ie){
        ySlide_int += sitepen.represent.outerSpan._lastOffsetTop;// need to track this to fix IE bug
      }
      dojo.fx.html.textColorFade(np, 600, hlOffColor, hlOnColor);// do the highlight
      dojo.fx.html.slideTo(inr, 300, [0,ySlide_int]); // do the slide
      sitepen.represent.outerSpan._lastOffsetTop = ySlide_int;  // need to track this to fix IE bug
		},
		"onmouseout": function(evt){
			var n = evt.target;
			var src = n.src;                             
			n.src = src.replace("On.", ".");// replace the On image with the original
      if(anim) { anim.stop(); }
      if(browser.safari){
        n.sitepen.hlSpan.parentNode.style.color = hlOffColor; 
        sitepen.represent.sweeper();
      }else{
        dojo.fx.html.textColorFade(n.sitepen.hlSpan.parentNode, 600, hlOnColor, hlOffColor);// fade the code out 
        sitepen.represent.sweeper();
      }
		}
	}
};

var textOver = {
	"text_over": {
		"onmouseover": function(evt) {
			var n = evt.target;
			if(n == sitepen.represent.activeSpan_ref){ // prevent double event calls in safari
        return
      }
			if(anim) { anim.stop(); }      
      var np = n.sitepen.hlSpan.parentNode;
      if(sitepen.represent.activeSpan_ref == np){// prevent spurious multiple calls in Safari
        return;
      }
      sitepen.represent.activeSpan_ref = np; // need to track this b/c mouseout event isn't always captured
      var ySlide_int = sliderYOffest_int - np.offsetTop;
			if(browser.ie){
        ySlide_int += sitepen.represent.outerSpan._lastOffsetTop;// need to track this to fix IE bug
      }
      if(browser.safari){// running textColorFade() and slideTo() simultaneously exposes Safari bug
        np.style.color = hlOnColor;
        dojo.fx.html.slideTo(inr, 300, [0,ySlide_int]); // do the slide
      }else{
        dojo.fx.html.textColorFade(np, 600, hlOffColor, hlOnColor);// do the highlight
        dojo.fx.html.slideTo(inr, 300, [0,ySlide_int]); // do the slide
      }
      sitepen.represent.outerSpan._lastOffsetTop = ySlide_int;  // need to track this to fix IE bug
		},
		"onmouseout": function(evt) {
			var n = evt.target;
      if(anim) { anim.stop();}
      if(browser.safari){
        if(n.sitepen){ // in Safari, n is sometimes a textNode
          n.sitepen.hlSpan.parentNode.style.color = hlOffColor;
        }
        sitepen.represent.sweeper();
      }else{
        dojo.fx.html.textColorFade(n.sitepen.hlSpan.parentNode, 600, hlOnColor, hlOffColor);
        sitepen.represent.sweeper();
      }
		}
	}
};

// Fade node text color from startColor to endColor
dojo.fx.html.textColorFade = function(node, duration, startColor, endColor, callback, dontPlay) {
	if(!dojo.lang.isNumber(duration)) {
		var tmp = duration;
		duration = endColor;
		endColor = startColor;
		startColor = tmp;
	}
	node = dojo.byId(node);
	var startRgb = new dojo.graphics.color.Color(startColor).toRgb();
	var endRgb = new dojo.graphics.color.Color(endColor).toRgb();
	var anim = new dojo.animation.Animation(
		new dojo.math.curves.Line(startRgb, endRgb),
		duration||dojo.fx.duration, 0);
	  dojo.event.connect(anim, "onAnimate", function(e) {
		  node.style.color = "rgb(" + e.coordsAsInts().join(",") + ")";
	  }
  );
	if(callback) {
		dojo.event.connect(anim, "onEnd", function(e) {
			callback(node, anim);
		});
	}
	if( !dontPlay ) { anim.play(true); }
	return anim;
};

function onPageLoad(){
	c = dojo.byId("codeCont");
  inr = dojo.byId("inr");
	x = dojo.byId("xCoords");
	y = dojo.byId("yCoords");
	dojo.behavior.add(imageOver);
	dojo.behavior.add(textOver);
	dojo.behavior.apply();
  sitepen.init();
  safariSweeperInterval = setInterval("sitepen.represent.sweeper()", 500);
}
dojo.addOnLoad(onPageLoad);
