// photography.danwright.info/javascript.js
// Copyright (c) 2004-2008 Dan Wright
// photography.danwright.info/contact

// don't frame me in!
if (top != self)
	top.location.href = location.href;

if (!dan) var dan = {};

function runOnLoad(func)
{
	var oldfunc = window.onload;
	if (typeof window.onload != 'function')
		window.onload = func;
	else
		window.onload = function() { oldfunc(); func(); };
}

function addDocumentLoadFunc(func)
{
	runOnLoad(func);
}

function assert(expr, message)
{
	if (typeof Debug != 'undefined')
		{
		try {
			if (arguments.length > 2 && typeof arguments[2] == 'object')
				Debug.assert(expr, message, arguments[2]);
			else
				{
				if (arguments.length > 2)
					alert("extra argument, typeof == " + typeof arguments[2]);
				Debug.assert(expr, message);
				}
			}
		catch (e)
			{
			}
		}
}

function log(message)
{
	if (typeof Debug != 'undefined')
		{
		try {
			Debug.log(message);
			}
		catch (e)
			{
			}
		}
}

function addEventProc(element, name, observer, useCapture)
{
	var element = $(element);
	useCapture = useCapture || false;
	if (element.addEventListener)
		element.addEventListener(name, observer, useCapture);
	else if (element.attachEvent)
		element.attachEvent('on' + name, observer);
	else 
		element['on' + name] = observer;
}

function setStyleWhileLoading(cssSelector, styleInfo)
{
	document.write("<style>\n<!--\n" + cssSelector + " {\n" + styleInfo + "\n}\n-->\n</style>\n");
}

// hideCSSSelectorWhileLoading is used to hide an element while the page is being
// loaded (hence, possibly before all elements have been loaded) from JavaScript.
// This can be used to hide elements only when JavaScript is enabled by the browser.
function hideCSSSelectorWhileLoading(cssSelector)
{
	setStyleWhileLoading(cssSelector, 'display: none;');
}

function writeEmailLink(address,description) 
{
	var i = address.indexOf('kah');
	var fixedEmail = address.substring(i+3,address.length) + String.fromCharCode(64) + address.substring(0,i);
	var prefix = '&#109;&#97;&#105;' + '&#108;&#116;&#111;&#58;';  // Unicode for 'mai' + 'lto:'
	var linkStr = '<a href="' + prefix + fixedEmail + '" title="' + fixedEmail + '">';
	document.write(linkStr + description + '<\/a>');
}

function inlineMail(address) 
{
	var i = address.indexOf('kah');
	var fixedEmail = address.substring(i+3,address.length) + String.fromCharCode(64) + address.substring(0,i);
	var prefix = '&#109;&#97;&#105;' + '&#108;&#116;&#111;&#58;';  // Unicode for 'mai' + 'lto:'
	var linkStr = '<a href="' + prefix + fixedEmail + '" title="' + fixedEmail + '">';
	document.write(linkStr + fixedEmail + '<\/a>');
}
	
// it's absolutely disgusting that I have not one, not two, but THREE ways -- in JavaScript alone --
// for evading spammers. This one is not nearly as messy in the xhtml -- because I start out (in the xhtml)
// with a simple web link -- in case JavaScript is disabled -- and then fix it up here if we can do better.
// The "real" address is stored (obfuscated) in the link 'name'.
function fixupEmailLinks()
{
	var i;
	for (i = 0; i < document.links.length; i++)
		{
		// first method:
		//		<a href="nospam:domain attn user"></a>
		//		==> <a href="mailto:user@domain" title="user@domain">user</a>
		if (document.links[i].protocol == 'nospam:')
			{
			var path = document.links[i].pathname;
			var j = path.indexOf(' attn ');
			if (j >= 0)
				{
				var name = path.substring(j+6,path.length);
				var fixedEmail = name + String.fromCharCode(64) + path.substring(0,j);
				document.links[i].href = 'mailto:' + fixedEmail;
				document.links[i].title = fixedEmail;
				var txt = document.createTextNode(name);
				document.links[i].appendChild(txt);
				}
			}
		// second method:
		//		<a href="contact.html" name="domainattnuser">whatever</a>
		//		==> <a href="mailto:user@domain" title="user@domain">whatever</a>
		// This method is designed for compatibility when JavaScript is disabled/unsupported.
		// The contact.html presumably contains a form that submits a message via CGI script, 
		// avoiding "mailto" links altogether.
		if (document.links[i].protocol == 'http:' && document.links[i].name != null)
			{
			var name = document.links[i].name;
			var j = name.indexOf('attn');
			if (j >= 0)
				{
				var fixedEmail = name.substring(j+4,name.length) + String.fromCharCode(64) + name.substring(0,j);
				document.links[i].href = 'mailto:' + fixedEmail;
				document.links[i].title = fixedEmail;
				}
			}
		}
}

function clearPlaceholder(elem)
{
	if (elem != null)
		{
		if (elem.value == elem.getAttribute('placeholder'))
			{
			elem.value = "";
			elem.style.color = '#000000';
			}
		}
	return true;
}

function resetPlaceholder(elem)
{
	if (elem != null)
		{
		if (elem.value == "")
			{
			elem.style.color = '#999999';
			elem.value = elem.getAttribute('placeholder');
			}
		}
	return true;
}

runOnLoad(function()// fix placeholders
	{
	if (typeof(Prototype) == "undefined") return;
	var elems = $$('input#terms');
	if (elems != null && elems.length > 0)
		{
		if (isObsoleteIE())
			{
			var elem = $('terms');
			addEventProc(elem, 'focus', function() { clearPlaceholder(elem); }, false);
			addEventProc(elem, 'blur',  function() { resetPlaceholder(elem); }, false);
			elem.style.color = '#999999';
			elem.value = elem.getAttribute('placeholder');
			}
		else
			{
			$A(elems).each( function (elem)
				{
				elem.observe('focus', function() { clearPlaceholder(elem); });
				elem.observe('blur',  function() { resetPlaceholder(elem); });
				elem.style.color = '#999999';
				elem.value = elem.getAttribute('placeholder');
				});
			}
		}
	});

var pOIS_extraWidthCached = 40;
var pOIS_extraHeightCached = 44;

function prepOneImageShadow(elem, firstTry)
{
	// Element.getStyle is a prototype.js method
	var valueL = Element.getStyle(elem, 'padding-left');
	var valueR = Element.getStyle(elem, 'padding-right');
	var valueT = Element.getStyle(elem, 'padding-top');
	var valueB = Element.getStyle(elem, 'padding-bottom');
	var extraWidth = parseInt(valueL) + parseInt(valueR);
	var extraHeight = parseInt(valueT) + parseInt(valueB);
	if (valueL != null && valueR != null && valueL != "" && valueR != "")
		pOIS_extraWidthCached = extraWidth;
	else
		extraWidth = pOIS_extraWidthCached;
	if (valueT != null && valueB != null && valueT != "" && valueB != "")
		pOIS_extraHeightCached = extraHeight;
	else
		extraHeight = pOIS_extraHeightCached;
	// IE (6) requires this silly logic, because when you ask it for elem.width, IE returns offsetwidth
	// instead.
	// IE 7 reports that elem.width == 0 and elem.height == 0 if the item isn't visible, even when the 
	// element explicitly specifies its dimensions. IE should just be taken behind the shed...
	var totalDim = elem.getDimensions();
	var totalWidth = (elem.offsetWidth > extraWidth ? elem.offsetWidth : (elem.width + extraWidth)) + "px";
	var totalHeight = (elem.offsetHeight > extraHeight ? elem.offsetHeight : (elem.height + extraHeight)) + "px";
	if (firstTry && !elem.complete && ((elem.offsetHeight > extraHeight && elem.offsetHeight < 100)
									|| (elem.offsetHeight <= extraHeight && (elem.height + extraHeight) < 100)))
		{
		elem.onload = function () { prepOneImageShadow(elem, false); };
		return;
		}
	if (elem.offsetHeight > extraHeight && elem.offsetHeight < 100)
		log("1: elem.offsetHeight=" +elem.offsetHeight + "; elem.height=" + elem.height + "; extraHeight=" + extraHeight);
	else if (elem.offsetHeight <= extraHeight && (elem.height + extraHeight) < 100)
		log("2: elem.offsetHeight=" +elem.offsetHeight + "; elem.height=" + elem.height + "; extraHeight=" + extraHeight);
		
	var shadowDiv = document.createElement('div');
	shadowDiv.className = 'shadow';
	shadowDiv.style.width = totalWidth; 
	shadowDiv.style.height = totalHeight;
	
	var targetNode = elem;
	var parentNode = elem.parentNode;
	if (parentNode.nodeName == 'A')
		{
		targetNode = parentNode;
		parentNode = targetNode.parentNode;
		}
	shadowDiv.appendChild(targetNode.cloneNode(true));
	var topLeft = document.createElement('div');
	topLeft.className = 'topleft';
	shadowDiv.appendChild(topLeft);
	var topRight = document.createElement('div');
	topRight.className = 'topright';
	shadowDiv.appendChild(topRight);
	var bottomLeft = document.createElement('div');
	bottomLeft.className = 'bottomleft';
	shadowDiv.appendChild(bottomLeft);
	var bottomRight = document.createElement('div');
	bottomRight.className = 'bottomright';
	shadowDiv.appendChild(bottomRight);
	parentNode.replaceChild(shadowDiv, targetNode);
}

runOnLoad(function() // prep image shadows
	{
	if (typeof(Prototype) == "undefined") return;
	var imgs = $$('img.shadow');
	pOIS_extraWidthCached = 40;
	pOIS_extraHeightCached = 44;
	if (imgs != null)
		imgs.each( function(elem) { prepOneImageShadow(elem, true); } );
	});

runOnLoad(fixupEmailLinks);
//runOnLoad(fixupPlaceholder);
//runOnLoad(fixupImagesForShadows);

function getDomain()
{
	var delim = /\//;
	if( navigator.appName == "Microsoft Internet Explorer" )
		var url = window.document.location.href;
	else
		var url = window.location.href;
	var urlArray = url.split( delim );
	if( navigator.appName == "Microsoft Internet Explorer" )
			return urlArray[1];
	else
		return urlArray[2];
}

function splitURLToDomain()
{
	return getDomain();
}

function isLocalDomain()
{
	return getDomain().indexOf(".local") > 0;
}

function haveDOM()
{
	return (document.getElementById && document.createTextNode);
}

function replaceParaText(paraid, newtext)
{
	var txt = document.createTextNode(newtext);
	var elem = document.getElementById(paraid);
	var oldTxt = elem.replaceChild(txt, elem.firstChild);
	return true;
}

function hasClass(elem, className)
{
	var e = (typeof elem == 'string') ? document.getElementById(elem) : elem;
	return new RegExp('\\b'+className+'\\b').test(elem.className);
}

function addClass(elem, className)
{
	var e = (typeof elem == 'string') ? document.getElementById(elem) : elem;
	assert(elem != null, "addClass: element is null",
					(arguments.length > 2 && typeof arguments[2] == 'object') ? arguments[2] : arguments);
	assert(className != null && className != '', "addClass: bad className", 
					(arguments.length > 2 && typeof arguments[2] == 'object') ? arguments[2] : arguments);
	if (!hasClass(elem, className))
		e.className += e.className ? (' '+className) : className;
}

function removeClass(elem, className)
{
	var e = (typeof elem == 'string') ? document.getElementById(elem) : elem;
	assert(elem != null, "removeClass: element is null");
	var rep = e.className.match(' '+className) ? (' '+className) : className;
	e.className = e.className.replace(rep, '');
}

function fetchByTagAndClass(root, tag, className)
{
	var elems;
	if (root != null && root instanceof Array)
		elems = root;
	else
		elems = $A((root || document).getElementsByTagName(tag));
	var results = new Array();
	var regex = new RegExp('\\b'+className+'\\b');
	elems.each( function(elem) {
				if (regex.test(elem.className))
					results.push(elem); } );
	return results;
}

function fetchByClass(root, className)
{
	return fetchByTagAndClass(root, '*', className);
}

// fetchByClasses matches items with BOTH classes
function fetchByTagAndClasses(root, tag, className1, className2)
{
	var elems;
	if (root != null && root instanceof Array)
		elems = root;
	else
		elems = $A((root || document).getElementsByTagName(tag));
	var results = new Array();
	var regex1 = new RegExp('\\b' + className1 + '\\b');
	var regex2 = new RegExp('\\b' + className2 + '\\b');
	elems.each( function(elem) {
				if (regex1.test(elem.className) && regex2.test(elem.className))
					results.push(elem); } );
	return results;
}

// fetchBySelector is an optimised version of $$() (see prototype.js)
// ... it speeds up the case $$('#identifier tag');
// ... it speeds up the case $$('.className tag');
// ... it speeds up the case $$('#identifier .className');
function fetchBySelector(selector)
{
	if (document.querySelectorAll && typeof document.querySelectorAll == 'function')
		return $A(document.querySelectorAll(selector));
		
	var matches = /^#(\w+)\s+(\w+)$/.exec(selector);
	// $$ requires prototype.js!
	if (matches)
		{
		try {
		return $A($(matches[1]).getElementsByTagName(matches[2]));
		} catch (e)
			{
			log("could not find any matches for selector " + selector);
			}
		return new Array();
		}
	matches = /^\.(\w+)\s+(\w+)$/.exec(selector);
	if (matches)
		{
		//alert("using class optimization: " + selector);
		var classElems = $A(fetchByClass(null, matches[1]));
		var tagName = matches[2];
		var results = new Array();
		classElems.each(function(elem) {
							var results0 = $A(elem.getElementsByTagName(tagName));
							results = results.concat(results0);
							});
		return $A(results);
		}
	matches = /^#(\w+)\s+\.(\w+)$/.exec(selector);
	if (matches)
		{
		return $A(fetchByClass($(matches[1]), matches[2]));
		}
		
	return $$(selector);
}

dan.$$ = function(selector)
{
	return fetchBySelector(selector);
}

function measurePerformance(func, count)
{
	count = count || 1;
	var start = new Date();
	while (count--) func();
	var stop = new Date();
	return (stop.getTime() - start.getTime())/1000;
}

var imagesButtons = new Object();

function loadButtonImages()
{
	if (document.images)
		{
		imagesButtons["buybutton-onblk"] = new Image(23,73);
		imagesButtons["buybutton-onblk"].src = "/images/buybutton-onblk.png";
		imagesButtons["buybuttononblkpressed"] = new Image(23,73);
		imagesButtons["buybuttononblkpressed"].src = "/images/buybutton-onblk-pressed.png";
		}
}

function setImage(imgElem, imgName)
{
	if (document.images)
		{
		document.images[imgElem].src = imagesButtons[imgName].src;
		}
}

function parse_webkit_version(version)
{
	var bits = version.split(".");
	var is_nightly = (version[version.length - 1] == "+");
	if (is_nightly)
		{
		var minor = "+";
		}
	else
		{
		var minor = parseInt(bits[1]);
		if (isNaN(minor))
			minor = "";
		}
	return {major: parseInt(bits[0]), minor: minor, is_nightly: is_nightly};
}

function get_webkit_version()
{
	var regex = new RegExp("\\(.*\\) AppleWebKit/(.*) \\((.*)");
	var matches = regex.exec(navigator.userAgent);
	if (matches)
		{
		var webkit_version = parse_webkit_version(matches[1]);

		regex = new RegExp("\\(KHTML, like Gecko(, like Safari)?\\) (\w+)/(.*)");
		matches = regex.exec(navigator.userAgent);
		if (matches)
			{
			webkit_version.browser = matches[2];
			webkit_version.browser_version = matches[3];
			}
		return webkit_version;
		}
		
	
	return null;
}

function get_ie_version()
{
	var regex = new RegExp("MSIE ([\\d\\.]+)");
	var matches = regex.exec(navigator.userAgent);
	if (matches)
		{
		var bits = matches[1].split(".");
		return {browser: 'MSIE', version: matches[1], major: bits[0], minor: bits[1]};
		}
	return null;
}

function isAppleWebKit()
{
	return (navigator.appVersion.indexOf('AppleWebKit') > 0);
}

function isIE()
{
	return (navigator.appVersion.indexOf('MSIE') > 0);
}

function isObsoleteIE()
{
	return isIE() && get_ie_version().major < 7;
}

function isVeryObsoleteIE()
{
	return isIE() && get_ie_version().major < 6;
}

function isNetscape()
{
	return (navigator.appVersion.indexOf('Netscape') > 0);
}

function isPlatformMac()
{
	return (navigator.platform.indexOf('MacPPC') == 0
			|| navigator.platform.indexOf('MacIntel') == 0);
}

function getExpDate(days, hours, minutes)
{
	var expDate = new Date();
	if (typeof days == "number" && typeof hours == "number" && typeof minutes == "number")
		{
		expDate.setDate(expDate.getDate() + parseInt(days));
		expDate.setHours(expDate.getHours() + parseInt(hours));
		expDate.setMinutes(expDate.getMinutes() + parseInt(minutes));
		return expDate.toGMTString();
		}
}

function getCookieVal(offset)
{
	var endstr = document.cookie.indexOf(";", offset);
	if (endstr == -1)
		endstr = document.cookie.length;
	return unescape(document.cookie.substring(offset, endstr));
}


function getCookie(name)
{
	var arg = name + "=";
	var alen = arg.length;
	var clen = document.cookie.length;
	var i = 0;
	while (i < clen)
		{
		var j = i + alen;
		if (document.cookie.substring(i, j) == arg)
			return getCookieVal(j);
		i = document.cookie.indexOf(" ", i) + 1;
		if (i == 0) break;
		}
	return "";
}

function setCookie(name, value, expires, path, domain, secure)
{
	document.cookie = name + "=" + escape(value) + 
					(expires ? "; expires=" + expires : "") +
					(path ? "; path=" + path : "") +
					(domain ? "; domain=" + domain : "") +
					(secure ? "; secure" : "");
}

function getGlobalPositionOfElement(elem)
{ // preq: prototype.js
	var pos = Position.cumulativeOffset(elem);
	return {x: pos[0], y: pos[1]};
}

function getGlobalCenterOfElement(elem)
{ // preq: prototype.js
	var pos = Position.cumulativeOffset(elem);
	var cx = pos[0] + elem.offsetWidth/2;
	var cy = pos[1] + elem.offsetHeight/2;
	return {x: cx, y: cy};
}

function setGlobalLeft(elem, x)
{ // preq: prototype.js
	var pos = Position.cumulativeOffset(elem);
	var originX = pos[0] - elem.offsetLeft;
	var newLeft = x - originX;
	//log("setGlobalLeft: x_global="+x+", elem.pos[0]="+pos[0]+",originX="+originX+",newLeft="+newLeft);
	elem.style.left = newLeft + "px";
	//elem.style.zIndex = 125;
}

function setGlobalTop(elem, y)
{ // preq: prototype.js
	var pos = Position.cumulativeOffset(elem);
	var originY = pos[1] - elem.offsetTop;
	var newTop = y - originY;
	elem.style.top = newTop + "px";
}

function getElemDesc(el)
{
	var id = el.getAttribute('id');
	if (id)
		return el.tagName + " ['" + id + "']";
	return el.tagName;
}

function getCenterPositionedElements()
{
	if (!document.body) return;
	var horz_array = new Array();
	var vert_array = new Array();
	var allElem = document.all;
	var i;
	for (i = 0; i < allElem.length; i++)
		{
		var el = allElem[i];
		var st = el.style;
		var cs = el.currentStyle;
		if (cs.position == 'absolute')
			{
			if (cs.left != 'auto' && cs.right != 'auto')
				horz_array[horz_array.length] = el;
			if (cs.top != 'auto' && cs.bottom != 'auto')
				vert_array[vert_array.length] = el;
			}
		}
	return {horz: horz_array, vert: vert_array};
}


function repositionCenterPositionedElements(hv)
{
	var horz = hv.horz;
	var vert = hv.vert;
	
	var fakeEl = document.createElement('div');
	fakeEl.style.visibility = 'hidden';
	fakeEl.style.position = 'absolute';
	fakeEl.style.top = '-5em';
	fakeEl.style.left = '0';
	fakeEl.style.width = '1px';
	fakeEl.style.height = '1px';
	fakeEl.setAttribute('id', 'fakeEl');
	document.body.appendChild(fakeEl);
	
	var i, el, st, cs, parent, zSaved;
	var x, y, tmp, dx, dy, dx2, dy2, autoleft;
	for (i = horz.length; i-->0; )
		{
		el = horz[i];
		st = el.style;
		cs = el.currentStyle;
		log(getElemDesc(el) + " (horiz)... [cs.left=" + cs.left + ", cs.right=" + cs.right + "]");
		zSaved = cs.zIndex;
		var x_left = el.offsetLeft;
		x = el.offsetLeft;
		tmp = cs.left; st.left = 'auto';
		var base_left = el.offsetLeft;
		var left_in_pixels = (base_left - x);
		var right_edge = el.offsetLeft + el.offsetWidth;		
		st.left = tmp;
		parent = el.offsetParent;

		log("... x=" + x + ", base_left=" + base_left + ", left_in_pixels=" + left_in_pixels + ", right_edge=" + right_edge + "]");

		dx = right_edge - x;
		
		log("... width=" + dx + 'px');
		st.width = dx + 'px';
		log("... zSaved = " + zSaved + ", st.zIndex=" + st.zIndex);
		st.zIndex = zSaved;
		}
	for (i = vert.length; i-->0; )
		{
		el = vert[i];
		log(getElemDesc(el) + " (vert)...");
		st = el.style;
		cs = el.currentStyle;
		y = el.offsetTop;
		tmp = cs.top; st.top = 'auto';
		dy = el.offsetTop - x;
		st.top = tmp;
		parent = el.offsetParent;
		st.height = st.bottom; // translate st.bottom (px, pt, em, in, cm,...) to px
		dy2 = el.offsetHeight; // .. voila!
		dy = (parent.offsetHeight - dy - dy2);
		log("... height=" + dy + 'px');
		st.height = dy + 'px';
		}
}

function correctCenterPositionedElements()
{
/*@cc_on
@if (@_win32 && @_jscript_version>4)
	var elements = getCenterPositionedElements();
	if (elements)
		repositionCenterPositionedElements(elements);
@end @*/
}
