/*\
 | Copyright (C) 2009-2010 Link Digital
 | http://www.linkdigital.com.au/
 | All rights reserved.
 | Unauthorised copying, distribution or derivation is prohibited.
\*/


/****************************** Helper Functions ******************************/

if (typeof (String.prototype.ltrim)	=== "undefined")	{ String.prototype.ltrim		= function (chars)	{ return this.replace (new RegExp ("^[" + (chars || "\\s") + "]+",  "g"), "");	}; }
if (typeof (String.prototype.rtrim)	=== "undefined")	{ String.prototype.rtrim		= function (chars)	{ return this.replace (new RegExp ( "[" + (chars || "\\s") + "]+$", "g"), "");	}; }
if (typeof (String.prototype.trim)	=== "undefined")	{ String.prototype.trim 		= function (chars)	{ return this.ltrim (chars).rtrim (chars);					}; }

Array.min												= function (array)	{ return Math.min.apply (Math, array); };
Array.max												= function (array)	{ return Math.max.apply (Math, array); };

/****************************** General Utility *******************************/

// Set all <a> tags with rel="ext" to open in new window
function a_init_ext (element)
{
	if (!(element = $ (element)))	return;

	element.observe ("click", function (event) { window.open (this.readAttribute ("href")); event.stop (); });
}

// Set all <a> tags with rel="rmv" to delete their parent element when clicked
function a_init_rmv (element)
{
	if (!(element = $ (element)))	return;

	element.observe ("click", function (event) { this.up ().hide (); if (this.readAttribute ("href") == "#") event.stop (); });
}

function a_init_fade (element)
{
	if (!(element = $ (element)))	return;

	var	effect;
	var	img		= element.down ();

	img.setStyle ({visibility	: "visible" });
	img.setStyle ({opacity		: 0 });

	element.observe ("mouseover",	function (event)
	{
		if (effect) effect.cancel ();

		effect = new Effect.Opacity (img,
		{
			duration	: 0.5,
			to		: 1.0
		});
	});

	element.observe ("mouseout",	function (event)
	{
		if (effect) effect.cancel ();

		effect = new Effect.Opacity (img,
		{
			duration	: 0.7,
			to		: 0.0
		});
	});
}

// Set an input text box to clear its default text on focus
function input_init_srch (element)
{
	if (!(element = $ (element)))	return;

	var temp		= $F (element);

	element.setValue (element.readAttribute ("title"));
	element.defaultValue	= $F (element);

	element.observe ("focus", function ()
	{
		if ($F (this) === this.defaultValue)
		{
			this.clear ();
			this.removeClassName ("dflt");
		}
	});

	element.observe ("blur",  function ()
	{
		if (!this.present ())
		{
			this.setValue (this.defaultValue);
			this.addClassName ("dflt");
		}
	});

	if (temp)
		element.setValue (temp);
	else	element.addClassName ("dflt");
}

// Set an input password box to show plaintext until focus
function input_init_pass (element)
{
	if (!(element = $ (element)))	return;
	element.removeClassName ("lc_pass");
	element.setValue ("");

	//var newelem = element.clone (); 		// IE won't let us just change the type attribute, OR clone the element >:(
	var newelem = new Element ("input",
	{
		name:		"-1",
		type:		"text",
		value:		"Password",
		title:		"Password",
		tabindex:	parseInt (element.getAttribute ("tabindex")) + 1,
		className:	element.className
	});

	element.twin = newelem;
	newelem.twin = element;

	newelem.observe ("focus", function () { this.replace (this.twin); this.twin.activate (); });	// this.twin.focus doesn't work right in IE for some reason
	element.observe ("blur",  function () { if (!this.present ()) this.replace (this.twin); });

	element.focus ();
	element.blur ();
}

/***************************** Element Rotator(s) *****************************/

function linkCMS_Snippet (snipID, xmlPath)
{
	var snipX		= 0;
	var snipZ		= 0;
	var snipM		= 0;
	var snipC		= $ (snipID + "_ctr");
	var snipL		= $ (snipID + "_ctl");
	var snip1;
	var snip2;

	//if (!(snipID = $ (snipID + "_ctr"))) return 0;
	if (!snipC || !snipL) return 0;

	new Ajax.Request (xmlPath,
	{
		method: 	"get",
		onSuccess:	snip_Init,
		onFailure:	function (response) { alert ("FAIL: " + response); }
	});


	function snip_Label (label, x)
	{
		return snipID + "_snip" + label + "_" + x;
	}

	function snip_Init (response)
	{
		var xml 	= response.responseXML;

		var imgs	= xml.getElementsByTagName ("item");
		var tFade	= 1.5;	// xml.getElementsByTagName ("fadeInTime")[0].getAttribute ("val");
		var tHold	= 5.0;	// xml.getElementsByTagName ("holdTime"  )[0].getAttribute ("val");
		var hLen	=  50;
		var dLen	= 150;

		snipM		= imgs.length;

		snipC.store ("tFade",	tFade);
		snipC.store ("tHold",	tHold);
		snipC.relativize ();

		var dMonths	=	// I can't believe there's no nicer way of doing this >:(
		[
			"January",
			"February",
			"March",
			"April",
			"May",
			"June",
			"July",
			"August",
			"September",
			"October",
			"November",
			"December",
		];

		$R (0, snipM, true).each (function (x)
		{
			var ttl 		= imgs[x].getElementsByTagName ("title" 	)[0].childNodes[0].nodeValue.trim ();
			var pub 		= imgs[x].getElementsByTagName ("pubDate"	)[0].childNodes[0].nodeValue;
			var href		= imgs[x].getElementsByTagName ("link"		)[0].childNodes[0].nodeValue;

			var desc;
			var temp		= imgs[x].getElementsByTagName ("description"	)[0].childNodes;

			// Can't reverse through this one for extra speediness :-(
			for (var y = 0; y < temp.length; y++) if (temp[y].nodeName == "#cdata-section")
			{
				desc		= temp[y].nodeValue.stripTags ().replace ("&nbsp;", " ").trim ();
				break;
			}

			if (ttl.length  > hLen)
				ttl			= ttl.substring  (0, hLen).replace (/\w+$/, "") + "...";

			if (desc.length > dLen)
				desc			= desc.substring (0, dLen).replace (/\w+$/, "") + "...";

			pub			= new Date (pub);
			pub			= pub.getDate () + " " + dMonths[pub.getMonth ()] + " " + pub.getFullYear ();

			var elD 		= new Element ("div",
			{
				id:		snip_Label ("Div", x)
			});

			elD.store ("prev", snip_Label ("Div", ((x - 1 + snipM) % snipM)));		// Because Modulo doesn't work on negative numbers
			elD.store ("next", snip_Label ("Div", ((x + 1 + snipM) % snipM)));

			if (x)	elD.hide ();

			elD.insert (new Element ("h1").update (pub));
			elD.insert (new Element ("h2").update (ttl));
			elD.insert (new Element ("p").update (desc));
			elD.insert ("<p class=\"more\"><a href=\"" + href + "\">More</a></p>");

			snipC.insert (elD);

			if (snipL)
			{
				var elL 		= new Element ("a",
				{
					id:		snip_Label ("Lnk", x),
					title:		x + 1,
					href:		"#"
				});

				elL.store ("jump", x);
				elL.store ("targ", snip_Label ("Img", x));
				elL.observe ("click",		function (event) { snip_Jump (this.retrieve ("jump")); this.blur (); event.stop (); });

				if (!x) elL.addClassName ("at");

				snipL.insert (elL);
			}
		});

		if (snipM > 1) snip_Next ();
	}


	function snip_Next ()
	{
		var elI 		= $ (snip_Label ("Div", snipX));
		var elP 		= $ (elI.retrieve ("prev"));
		var elN 		= $ (elI.retrieve ("next"));

		snipX			= ++snipX % snipM;

		elP.hide ();
		elN.hide ();

		elI.setStyle ({zIndex:	 0});
		elN.setStyle ({zIndex:	 1});

		snip1			= new Effect.Appear (elN.id,
		{
			from:		0,
			to:		1,
			duration:	snipC.retrieve ("tFade"),
			delay:		snipC.retrieve ("tHold"),
			afterFinish:	snip_Next,
			afterSetup:	function ()
			{
				snipL.childElements ().invoke ("removeClassName", "at");
				$ (snip_Label ("Lnk", snipX)).addClassName ("at");
			}
		});
	}


	function snip_Jump (jumpTo)
	{
		jumpTo			= jumpTo % snipM;

		var elI 		= $ (snip_Label ("Div", snipX));
		var elN 		= $ (snip_Label ("Div", jumpTo));

		snipX			= jumpTo;

		elN.hide ();

		elI.setStyle ({zIndex:	 0});
		elN.setStyle ({zIndex:	 1});

		snip1.cancel ();

		snip1			= new Effect.Appear (elN.id,
		{
			from:		0,
			to:		1,
			duration:	snipC.retrieve ("tFade") / 2,
			afterFinish:	snip_Next,
			afterSetup:	function ()
			{
				snipL.childElements ().invoke ("removeClassName", "at");
				$ (snip_Label ("Lnk", snipX)).addClassName ("at");
			}
		});
	}

	return 1;
}



// Load everything
document.observe ("dom:loaded", function ()
{
	// Count AJAX objects
	var complex	= 0;
	var ajax	= 0;

	Ajax.Responders.register
	({
		onCreate:	function ()			{ ++ajax; },
		onComplete:	function ()			{ if (!--ajax) linkCMS_Load (); },			// Load normal stuff once AJAX has finished
		onException:	function (request, exception)
		{
			alert (Object.inspect (request) + "\r\n\r\n" + Object.inspect (exception));
		}
	});


	// Complex stuff - uncomment as needed
	complex		+= linkCMS_Snippet ("snippet_news", "_news.xml");
	complex		+= linkCMS_Snippet ("snippet_blog", "_blog.xml");


	// Normal stuff
	if (!complex)	   linkCMS_Load ();
});

// Normal stuff
function linkCMS_Load ()
{
	$$ ("a[rel~=ext]").each 		(a_init_ext);		// Anchor OnClicks - Open in new tab
	$$ ("a[rel~=rmv]").each 		(a_init_rmv);		// Anchor OnClicks - Remove the link

	$$ ("a.lc_fade").each			(a_init_fade);		// Anchor Hover - fade in alternate state

	$$ ("input.lc_srch").each		(input_init_srch);	// Search field niceness
	$$ ("input.lc_pass").each		(input_init_pass);	// Password field niceness
}

