// Adapted from Dean Edwards' addEvent.
// written by Dean Edwards, 2005
// with input from Tino Zijdel, Matthias Miller, Diego Perini

// http://dean.edwards.name/weblog/2005/10/add-event/

var addEvent_guid = 0;
var addEvent_events = {};

function addEvent_helper(handlers, handler) {
	// assign each event handler a unique ID
	if (!handler.$$guid) handler.$$guid = ++addEvent_guid;

	// store the event handler in the hash table
	handlers[handler.$$guid] = handler;
}

function addEvent(element, type, handler) {
	// get event store for element
	var events = element.$$guid ?
		addEvent_events[element.$$guid] :
		(addEvent_events[element.$$guid = ++addEvent_guid] = {});
	
	// create a hash table of event handlers for each element/event pair
	var handlers = events[type];

	if (!handlers) {
		handlers = events[type] = {};
		
		// store the existing event handler (if there is one)
		if (element["on" + type]) addEvent_helper(handlers, element["on" + type]);

		// assign a global event handler to do all the work
		element["on" + type] = handleEvent;
	}
	
	// Finally add the handler
	addEvent_helper(handlers, handler);
};

function removeEvent(element, type, handler) {
	// delete the event handler from the hash table
	if (element.$$guid && addEvent_events[element.$$guid][type]) {
		delete addEvent_events[element.$$guid][type];
	}
};

function clearEvents(element, type) {
	if(element.$$guid) {
		for(var type in addEvent_events[element.$$guid]) {
			element["on" + type] = null;
		}
		delete addEvent_events[element.$$guid];
		delete element.$$guid;
	}
}

function handleEvent(event) {
	var returnValue = true;

	// grab the event object (IE uses a global event object)
	event = event || ((this.ownerDocument || this.document || this).parentWindow || window).event;

	// get a reference to the hash table of event handlers
	var handlers = addEvent_events[this.$$guid][event.type];

	// execute each event handler
	for (var i in handlers) {
		this.$$handleEvent = handlers[i];
		try {
			if (this.$$handleEvent(event) === false) {
				returnValue = false;
			}	
		}
		finally {
			this.$$handleEvent = null;
		}
	}

	return returnValue;
};

/* get(selector)
 * Based on getElementsBySelector Version 0.4 - Simon Willison, March 25th 2003
 * Stripped down, refactored, and a bugfix.
 */

var getByTagName = function(elements, tagName) {
	var r = [];
	for(var i = 0, e; e = elements[i]; ++i) {
		var children = (tagName == '*' && e.all) ? e.all : e.getElementsByTagName(tagName);
		for(var j = 0, child; child = children[j]; ++j) {
			r[r.length] = child;
		}
	}
	
	return r;
};

// TODO: Check that element selected by id is a descendant of context.
var get = function(selector, context) {
	context = [context || document];
	var tokens = selector.split(/\s+/);
	for (var i = 0, token; token = tokens[i]; i++) {
		if(token.indexOf('#') > -1) {
			if(i != 0) throw 'The id must be at the start of the selector.';
			var bits = token.split('#'), tagName = bits[0], id = bits[1];
			var element = document.getElementById(id);
			if (!element || (tagName && element.nodeName.toLowerCase() != tagName))
				return [];
			context = [element];
		}
		else if (token.indexOf('.') > -1) {
			var bits = token.split('.'), tagName = bits[0] || '*', className = bits[1];
			var found = getByTagName(context, tagName);
			context = [];
			for (var k = 0, element; element = found[k]; k++) {
				if (element.className && element.className.match(new RegExp('(^| )'+className+'($| )'))) {
					context[context.length] = element;
				}
			}
		}
		else {
			context = getByTagName(context, token);
		}
	}
	return context;
};

// My stuff.....

function addScroller(inner, outer) {
	if(inner.scrollWidth - inner.clientWidth <= 0) return;

	var mover = null;
	var lastMove = null;
	var dir = 0;

	function mosuemove(event) {
		event = event || window.event;

		var x = typeof(event.pageX) === "number" ? event.pageX
			: (event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft);
		for(var parent = this; parent; parent = parent.offsetParent)
			x -= parent.offsetLeft;

		var width = this.offsetWidth;
		var pos = x / width;
		move(
			pos < 0.45 ? (pos - 0.45) / 0.45 * 6 :
			pos > 0.55 ? (pos - 0.55) / 0.45 * 6 :
			0);
	};

	function mouseout() {
		move(0);
	};

	addEvent(outer, "mousemove", mosuemove);
	addEvent(outer, "mouseover", mosuemove);
	addEvent(outer, "mouseout", mouseout);
	
	function moveImpl() {
		var thisMove = new Date();

		if(lastMove) {
			var distance = (thisMove - lastMove) / 10 * dir;

			inner.scrollLeft += distance;
			var pos = inner.scrollLeft;
			scrollButtonLeft.className = "left-" + (pos > 0 ? "on" : "off");
			scrollButtonRight.className = "right-" +
				(pos < (inner.scrollWidth - inner.clientWidth) ? "on" : "off");
		}

		lastMove = thisMove;
	}

	// The scroll button.
	
	var scrollButton = document.createElement('div'),
		scrollButtonLeft = document.createElement('div'),
		scrollButtonRight = document.createElement('div');

	scrollButton.className = 'leftright';
	scrollButtonLeft.className = 'left-off';
	scrollButtonRight.className = 'right-on';
	
	scrollButton.appendChild(scrollButtonLeft);
	scrollButton.appendChild(scrollButtonRight);
	outer.parentNode.insertBefore(scrollButton, outer);
	
	addEvent(scrollButtonLeft, "mouseover", function() { move(-5); });
	addEvent(scrollButtonRight, "mouseover", function() { move(+5); });
	addEvent(scrollButtonLeft, "mouseout", function() { move(0); });
	addEvent(scrollButtonRight, "mouseout", function() { move(0); });
	
	function move(d) {
		dir = d;
		if(dir) {
			if(!mover) {
				mover = setInterval(moveImpl, 25);
				lastMove = new Date();
			}
		}
		else {
			if(mover) {
				clearInterval(mover);
				mover = null;
				lastMove = null;
			}
		}
	}
}

// Suckerfish


function hover_onmouseover() { this.className += " hover"; }
function hover_onmouseout() { this.className = this.className.replace(new RegExp(" hover\\b"), ""); }

function setupHover() {
	var apply = get('.detect-hover');
	for(var i = 0; i < apply.length; ++i) {
		apply[i].onmouseover = hover_onmouseover;
		apply[i].onmouseout = hover_onmouseout;
	}
}

// Popup windows

function setupPopupWindows() {
	var links = get('a.imagelist');
	for(var i = 0; i < links.length; ++i) {
		links[i].onclick = popupWindowClick;
	}

	var window_reference = null;

	function popupWindowClick(event) {

/*@if(true)
		if(!window_reference || window_reference.closed) {
			window_reference = window.open(this.href, '_blank', "width=660,height=480,status=no,directories=no");
		}
		else {
			window_reference.open(this.href, '_self');
			window_reference.focus();
		}
@else @*/
		window.open('about:blank', 'johnkaine.org.uk.popup', "width=660,height=480,status=no,directories=no").open(this.href, "_self").focus();
//@end

		return false;
	}
}

// Call everything on load:

addEvent(window, 'load', function() {
	removeEvent(window, 'load', arguments.callee);
	var inner = get('#autoscroll-inner')[0];
	var outer = get('#autoscroll-outer')[0];
	if(inner && outer) addScroller(inner, outer);

	//@cc_on
	/*@if(@_jscript_version <= 5.6) setupHover(); @end @*/
	setupPopupWindows();
});

