// =====================================================
// Wiggle stereograms with javascript, by Martin Sutherland 
// http://www.sunpig.com/martin/archives/2005/12/12/wiggle_stereoscopy_a_new_approach/
// http://www.sunpig.com/secondbest/2005/12/wigglestereoscopyfollowup.html
//
// Version 1.2 (3 April 2011) - fixes problem with image being width-constrained by an outer container
//
// Version history:
// Version 1.1 (27 December 2005)
//
// 
// References:
// Adding event handlers: see http://www.scottandrew.com/weblog/articles/cbs-events
// Event cache to prevent memory leaks: see http://novemberborn.net/javascript/event-cache
// =====================================================


// Array support for the push method in IE 5
Array.prototype.push = ArrayPush;
function ArrayPush(value){
	this[this.length] = value;
}

// =====================================================
// EVENT CACHE
// =====================================================

// Event Cache uses an anonymous function to create a hidden scope chain.
// This is to prevent scoping issues. */
var EventCache = function(){
	var listEvents = [];
	
	return {
		listEvents : listEvents,
	
		add : function(node, sEventName, fHandler, bCapture){
			listEvents.push(arguments);
		},
	
		flush : function(){
			var i, item;
			for(i = listEvents.length - 1; i >= 0; i = i - 1){
				item = listEvents[i];
				
				if(item[0].removeEventListener){
					item[0].removeEventListener(item[1], item[2], item[3]);
				};
				
				/* From this point on we need the event names to be prefixed with 'on" */
				if(item[1].substring(0, 2) != "on"){
					item[1] = "on" + item[1];
				};
				
				if(item[0].detachEvent){
					item[0].detachEvent(item[1], item[2]);
				};
				
				item[0][item[1]] = null;
			};
		}
	};
}();


// =====================================================
// EVENT HANDLERS
// =====================================================

// Add an event handler to an object.
function addEvent(obj, evType, fn, useCapture){
	var result;
	if (obj.addEventListener){
		obj.addEventListener(evType, fn, useCapture);
		result = true;
	} else if (obj.attachEvent){
		var r = obj.attachEvent("on"+evType, fn);
		result = r;
	} else {
		return false;
	}

	EventCache.add(obj, evType, fn, useCapture);
	return result;
}

// Remove an event handler from an object
function removeEvent(obj, evType, fn, useCapture){
	if (obj.removeEventListener){
		obj.removeEventListener(evType, fn, useCapture);
		return true;
	} else if (obj.detachEvent){
		var r = obj.detachEvent("on"+evType, fn);
		return r;
	} else {
		return false;
	}
}

// =====================================================
// EVENT CACHE FLUSH
// =====================================================

// Attach an event handler to window.unload for flushing 
// the event cache.
addEvent(window, "unload", EventCache.flush);


// =====================================================
// THE WIGGLER
// =====================================================

var Wiggler = function () {

	// Private variables
	var alt = false;
	var wigglyDivs = [];
	var wiggleInterval = 120; // ms
	
	var getNaturalDimensions = function(img) {
        var dimensions = null,
            testImage;
        if (img) {
             if (img.naturalHeight === undefined) {
                 testImage = new Image();
                 testImage.src = img.src;
                 dimensions = {w:testImage.width, h:testImage.height};
             } else {
                 dimensions = {w:img.naturalWidth, h:img.naturalHeight};
             }
        }
        return dimensions;
    }

	// Public methods
	return ({
		toggle: function() {
			for (var i=0; i<wigglyDivs.length; i++) {
				var d= wigglyDivs[i];
				d.firstChild.style.left = alt ? "-" + d.imWidth + "px"  : "0";
			}
			alt = !alt;
		},

		init: function() {
			var imgs = document.getElementsByTagName("img");
			for (var i=imgs.length-1; i>=0; i--) {
				var im = imgs[i];
				if (im.className.match(/\bwiggle\b/gi)) {
					var actualDimensions = {w:im.width, h:im.height};
					var naturalDimensions = getNaturalDimensions(im);

					// Create a new div that will serve as a container for the image.
					var dv = document.createElement("div");
					dv.imWidth = actualDimensions.w/2;
					dv.style.display = im.style.display || 'block';
					dv.style.position = im.style.position || 'relative';
					dv.style.overflow = 'hidden';
					dv.style.height = actualDimensions.h + "px";
					dv.style.width = actualDimensions.w/2 + "px";
					
					// Replace the image with the div
					im.parentNode.replaceChild(dv, im);
					
					// Re-append the image to the div
					im.style.position = 'absolute';
					im.style.height = actualDimensions.h + 'px';
					im.style.width = actualDimensions.w + 'px';
					im.style.maxWidth = actualDimensions.w + 'px';
					dv.appendChild(im);

					// Add the div to the array of wiggle divs
					wigglyDivs.push(dv);
				}
			}


			// Set a timer to wiggle 
			window.setInterval(Wiggler.toggle, wiggleInterval);
		}
	});
}();

addEvent(window, "load", Wiggler.init);


