/* Script by Neil Anderson */                         
/* 

  NOTES & CAVEATS
  
	#I use DOM 1 attachments for the mousout events 
	  THERE can be no other events of this type firing on the images
	
*/

//NAMESPACE
var nja = {};

//config
nja.config = {
  left: 0, //left from image
	top: -4 //top from image
  }

//UTILITIES

/*
* EVENT
# addLoadEvent -- comma seperated list of functions
# addEvent -- element, event type, function
* DOM GETTERS
# £ -- comma seperated strings
# class -- [node], comma seperated strings
* CSS
# hasClass -- element, class
# getOffsets -- element
*/

//EVENT UTILITIES
//load cache
nja.loadCache = [];

(function(){
  var fn = function(){
	  if(document.body){//ready??
		  var f = nja.loadCache.length - 1;
	    for(f; f >= 0; f--){
			  try{
			    nja.loadCache[f].apply(document);
				  nja.loadCache.splice(f, 1);		
			  }
			  catch(err){				
				  break;//to maintain the correct order of events	
			  }
		  }
		  if(nja.loadCache.length === 0){
		    window.clearInterval(loading);
		  }
		}
	}
  var loading = window.setInterval(fn, 10);
})();


//add an event handler to be called the window context when the DOM is ready 
nja.addLoadEvent = function(args){
	//push into load cache
  for(var f = 0; f < arguments.length; f++){
    nja.loadCache.unshift(arguments[f]);
	}
};
	

//good enough [!!] add event
//factory
nja.addEvent=(function(){
  if (window.addEventListener){ //w3c DOM model
    return nja.addEvent = function(el, typ, funct){
      el.addEventListener(typ, funct, false);	 
    }
  }
  else if(window.attachEvent){ //IE DOM model
    return nja.addEvent = function(el, typ, funct){
		  //wrapped handler
			var wrapped = function(e){
			  var e = e || window.event;
				var event = { //synthetic event object
				  target: e.srcElement,
					clientX: e.clientX,
					clientY: e.clientY,
					preventDefault: function(){
					  e.returnValue = false;
					  },
					stopPropagation: function(){
					  e.cancelBubble = true;
					  }
				}
			  //call the original function
				funct.call(el, event);		
			}
			//now bind the wrapped handler to the event
			el.attachEvent('on' + typ, wrapped);		
		}
	}
})();


//DOM UTILITIES

//element[s] by id
//returns an array of node references
nja.id = function(){
  var len = arguments.length; 
  if (len == 1){//single 
    return document.getElementById(arguments[0]); 
  } 
  else { 
    var elements = []; 
		for (var i = 0; i < len; i++){ 
		  elements.push(document.getElementById(arguments[i])); 
		} 
		return elements; 
	} 
}; 


nja.byClass = function(klass, node){ 
	var elements = []; 
	var nodes, classes;
	if (arguments[0].nodeType){//node supplied 
	  nodes = arguments[0].getElementsByTagName('*');  
		classes = 1; 
	} 
	else{ //no node use document
	  nodes = document.getElementsByTagName('*'); 
	  classes = 0; 
	} 
	var argLen = arguments.length; 
	for(classes; classes < argLen; classes++){//loop thru classes 
	  var reg = new RegExp('\\b' + arguments[classes] + '\\b'); 
	  for(var node = 0, len = nodes.length; node < len; node++){
	    //loop thru nodes 
		  if(reg.exec(nodes[node].className)){//has right class 
		    elements.push(nodes[node]);
		  } 
	  }
	} 
	return elements; 
}


//CSS

//document scroll
nja.getScroll = function(){
	var scrollTop = document.body.scrollTop;
  if (scrollTop == 0){
    if (window.pageYOffset){
      scrollTop = window.pageYOffset;
    }
    else{
      scrollTop = (document.body.parentElement) ? document.body.parentElement.scrollTop : 0;
    }
  }
  return scrollTop;
}

//getStyle is chancy at best -- it will return different values for different browsers
// well for ie and DOM complient ones anyway
//factory
nja.getStyle = (function(){
  if(document.defaultView && document.defaultView.getComputedStyle){
    return nja.getStyle = function(el, prop){
		  return document.defaultView.getComputedStyle(el, null)[prop];
		}
  } 
	else{
	//we assume that we're using the IE model
	//but we'll save later
    return getStyle = function(el, prop){
			if(el.currentStyle){
			  return el.currentStyle[prop];
			}
			else{
			  return el.style[prop];//the save!!!
			}		
		}
  }
})();

//has a class
nja.hasClass = function(el, clas){
  if(el.className){
	  var reg = new RegExp('\\b' + clas + '\\b');
		var result = el.className.match(reg);
    if(result) return true;
	}
	else{
	  return false;
	}
};

//get the offsets of an element
nja.getOffsets = function (node){
  var y = 0;
  var x = 0;
	while(node){
    y += node.offsetTop;
		x += node.offsetLeft;		
	  node = node.offsetParent;
	}
	return [x, y]
};


//MAGNIFY SPECIFIC FUNCTIONS
//underscore seperated

//UTILITIES

//make a display box for the large image
nja.make_zoombox = function(path){
  var there = nja.id('nja_zoombox');
	var img = new Image();
	img.src = path;	
	if(there){
	  outer = there;
		outer.style['display'] = 'block';
		outer.removeChild(outer.firstChild);
	}
	else{
    var outer = document.createElement('div');
	  outer.id = 'nja_zoombox';
	}
	var inner = document.createElement('div');
	inner.style['width'] = img.width + 'px';
	inner.style['height'] = img.height + 'px';
	outer.appendChild(inner);
	inner.appendChild(img); 
  return outer;
};

//make the display box for the the magnify
nja.make_box = function(path){
  var there_box = nja.id('nja_magnified_viewport');
  if(there_box){
	  there_box.style['display'] = 'block';
		there_box.firstChild.src = path; //needs new path
	  return nja.id('nja_magnified_viewport');
	}
	var box = document.createElement('div');
  var imago = document.createElement('img');
  box.id = 'nja_magnified_viewport';
  imago.src = path;
  box.appendChild(imago);
  return box; 
};

//hide the magify box
nja.hide_box = function(){
  var there_box = nja.id('nja_magnified_viewport');
	if(there_box){
	  there_box.style['display'] = 'none';
	}
};

//hide the zoom box
nja.hide_zoom = function(){
  var there_box = nja.id('nja_zoombox');
	if(there_box){
	  there_box.style['display'] = 'none';
	}
}

//CONTROLLERS

//move the 'big' image behind the viewport
nja.move_magnified = function(e){
  //Algorythmn
	/*
	We have a [control] image and the magnified image -- a big image behind the smaller viewport
	We calculate the percentage left/top we are on the control
	And negitively position the large image by that percent * the difference between the size of
	the control and the big image.
	*/
  var me = e.target;
	var me_width = me.width;
	var me_height = me.height;
  var offs = nja.getOffsets(me);
	//per centage of samll image
	var x_percent = (e.clientX - offs[0])/me.width;
  var y_percent = ((e.clientY + nja.getScroll())- offs[1]) / me.height;
	//large image size
	var big_image = nja.id('nja_magnified_viewport').firstChild;
	var ht = big_image.height;
	var wd = big_image.width;
  big_image.style['left'] = parseInt((wd - me.width) * x_percent) * -1 + 'px';
  big_image.style['top'] = parseInt((ht - me_height) * y_percent) * -1 + 'px';
};


//magnify controller
nja.magnify = function(e){
  var img = e.target;
  //create or show the viewport
	var viewport = nja.make_box(img.parentNode.href);
	//position it
	var offs = nja.getOffsets(img);
	viewport.style['left'] = offs[0] + img.width + nja.config.left + 'px'; 
	viewport.style['top'] = offs[1] + nja.config.top + 'px';
	document.body.appendChild(viewport);
	//mousemove event
	nja.addEvent(img, 'mousemove', nja.move_magnified);
	//we'll use a dom 1 attachment here
	//add a mouseout event
	img.onmouseout = nja.hide_box;
};

//zoom controller
nja.zoom = function(e){
  var trg = e.target;
	var img = (trg.tagName.toUpperCase() === 'IMG') ? trg : trg.firstChild;	
	if(!nja.hasClass(img, 'nja_magnify')) return;
  e.preventDefault();
	//hide the magnified box
	nja.hide_box();
	var box = nja.make_zoombox(img.parentNode.href);
	box.style['top'] = nja.getScroll() + 10 + 'px';
	document.body.appendChild(box);
	//click to close
	nja.addEvent(box, 'click', nja.hide_zoom);
};

//initiation function
nja.init_magnify = function(){
  //add a delegate handler for zooming
	nja.addEvent(document.body, 'click', nja.zoom);
  //add mouseover handlers to all images with the right class name
  var mags = nja.byClass('nja_magnify');
  for(var i =0, len = mags.length; i < len; i++){
	  nja.addEvent(mags[i], 'mouseover', nja.magnify);
		//cache the images
		var img = new Image();
		img.src = mags[i].parentNode.href;
	}
}

//call the events onload
nja.addLoadEvent(nja.init_magnify);

// -->