// Javascript library file for Dreamlyrics custom content islands
// Copyright (c) 2009-2011 www.dreamlyrics.co.uk
// Version: 1.3

var gvsCustomIslandDetails = new Array;	// Each element holds the details for a particular custom content island
var gbCustomIslandsRegistered = false;	// Flag controlling whether we've registered triggering the custom content islands with the BODY tag's onload event.
var gvhoXmlHttpRequests = new Array;	// Each element holds the current XmlHttpRequest object for a content island

function displayTab( iSetId, sTabId ) {
	var hoTab, hoTabButton;
	if (gvsCustomIslandDetails[iSetId] && gvsCustomIslandDetails[iSetId].lastTab) {
		hoTabButton = document.getElementById("b"+iSetId+gvsCustomIslandDetails[iSetId].lastTab);
		hoTab       = document.getElementById("t"+iSetId+gvsCustomIslandDetails[iSetId].lastTab);
		if (hoTabButton != null ) {
		  hoTabButton.className='tab_grippy';
		}
		if (hoTab != null ) {
		  hoTab.className='hiddenTab';
		}
	}
	hoTabButton = document.getElementById("b"+iSetId+sTabId);
	hoTab = document.getElementById("t"+iSetId+sTabId);
	hoTabButton.className = 'tab_grippy_sel';
	hoTab.className = 'visibleTab';
	gvsCustomIslandDetails[iSetId].lastTab = sTabId;
}


// Define the XMLHttpRequest class for IE if necessary.
if ( typeof XMLHttpRequest == "undefined" ) XMLHttpRequest = function() {
  try { return new ActiveXObject("Msxml2.XMLHTTP.6.0") } catch(e) {}
  try { return new ActiveXObject("Msxml2.XMLHTTP.3.0") } catch(e) {}
  try { return new ActiveXObject("Msxml2.XMLHTTP") }     catch(e) {}
  try { return new ActiveXObject("Microsoft.XMLHTTP") }  catch(e) {}
  throw new Error( "This browser does not support XMLHttpRequest." )
};


function fetchDocument( sUrl, sTargetId ) {
  var hoTargetContainer;
  var hoXmlHttp = new XMLHttpRequest();
  
  if (hoXmlHttp == null) {
    // Can't handle AJAX - quit
    return null;
  }

  sUrl += "&amp;isAjax=1";
  hoXmlHttp.open("GET", sUrl, false);
  hoXmlHttp.send(null);
  
  // Unify caching behaviour on the client to ensure that we always get the latest available version.
  if ( !hoXmlHttp.getResponseHeader("Date")) {
    // No date => fetched from cache in IE and not validated to check if it's the latest version of the data
    var hoCached = hoXmlHttp;
    
    hoXmlHttp = new XMLHttpRequest();
    var ifModifiedSince = hoCached.getResponseHeader("Last-Modified");
    ifModifiedSince = (ifModifiedSince) ? ifModifiedSince : new Date(0); // January 1, 1970
    // Refetch the actual data (if we got here, we didn't actually make a HTTP request last time as it just came from the cache)
    hoXmlHttp.open("GET", sUrl, false);
    hoXmlHttp.setRequestHeader("If-Modified-Since", ifModifiedSince);
    hoXmlHttp.send("");
    if(hoXmlHttp.status == 304) {
      // Data not modified since it was cached in browser - use the cached version
      hoXmlHttp = hoCached;
    }
  }

  hoTargetContainer = document.getElementById(sTargetId);
  if (hoTargetContainer) {
    if (hoXmlHttp.status == 200) {
      // 200 = OK
      hoTargetContainer.innerHTML = hoXmlHttp.responseText;
    }
    else {
      hoTargetContainer.innerHTML = "<p>Unable to retrieve data. Error "+hoResults.status+": "+hoResults.statusText+"</p>";
    }
  }
}

function fetchDocumentAsync( iSetId, sUrl, sTargetId, sEval ) {
	var hoTargetContainer;
	var hoXmlHttp = new XMLHttpRequest();
	
	if (hoXmlHttp == null) {
		// Can't handle AJAX - quit
		return null;
	}

	var hoTargetContainer = document.getElementById(sTargetId);
	hoTargetContainer.innerHTML = "<p>Loading content...</p>";

	gvhoXmlHttpRequests[iSetId] = hoXmlHttp;
	sUrl += "&amp;isAjax=1";
	hoXmlHttp.open("GET", sUrl, true);
	hoXmlHttp.sTargetId = sTargetId;
	hoXmlHttp.sEval     = sEval;
	hoXmlHttp.iSetId    = iSetId;
	hoXmlHttp.onreadystatechange = function()
		{
			if (this.readyState == 4) {
				var hoResults = this;

				// Unify caching behaviour on the client to ensure that we always get the latest available version.
				if ( !this.getResponseHeader("Date")) {
					// No date => fetched from cache in IE and not validated to check if it's the latest version of the data
					hoResults = new XMLHttpRequest();
					hoResults.sTargetId = this.sTargetId;
					hoResults.sEval     = this.sEval;
					hoResults.iSetId    = this.iSetId;

					var ifModifiedSince = this.getResponseHeader("Last-Modified");
					ifModifiedSince = (ifModifiedSince) ? ifModifiedSince : new Date(0); // January 1, 1970
					// Refetch the actual data (if we got here, we didn't actually make a HTTP request last time as it just came from the cache)
					hoResults.open("GET", sUrl, false);
					hoResults.setRequestHeader("If-Modified-Since", ifModifiedSince);
					hoResults.send("");
					if (hoResults.status == 304) {
						// Data not modified since it was cached in browser - use the cached version
						hoResults = this;
					}
				}
				gvhoXmlHttpRequests[this.iSetId] = null;

				var hoTargetContainer = document.getElementById(hoResults.sTargetId);
				if (hoTargetContainer) {
					if (hoResults.status == 200) {
						// 200 = OK
						hoTargetContainer.innerHTML = hoResults.responseText;
						eval(hoResults.sEval);
					}
					else {
						hoTargetContainer.innerHTML = "<p>Unable to retrieve data. Error "+hoResults.status+": "+hoResults.statusText+"</p>";
					}
				}
			}
		};

	hoXmlHttp.send(null);
}

function findFirstFormElementOfType( hoForm, sType )
{
  var i;
  var sValue;
  var bSkip;
  
  if (hoForm == null) {
    // Can't find form - ignore
    return false;
  }
  
  for ( i = 0; i < hoForm.elements.length; i++ )
  {
    if (hoForm.elements[i].type == sType )
    {
      return hoForm.elements[i];
    }
  }
  return null;
}

// Serialises a form's values ready for submission via AJAX.
// Doesn't handle File upload forms.
function serialiseFormValues( sFormName ) {
  var hoForm = document.forms[sFormName];
  var sValues = "";
  var i;
  var sValue;
  var bSerialiseValue;
  var hoValues = new Array;
  
  if (hoForm == null) {
    // Can't find form - ignore
//  alert("Can't find form '" + sFormName + "'");
    return null;
  }
  
  for ( i = 0; i < hoForm.elements.length; i++ )
  {
    bSerialiseValue = true;
    switch (hoForm.elements[i].type)
    {
    case 'hidden':
    case 'password':
    case 'select-one':
    case 'text':
      sValue = hoForm.elements[i].value;
      break;
    case 'radio':
    case 'checkbox':
      if (hoForm.elements[i].checked)
      {
        sValue = hoForm.elements[i].value;
      }
      else
      {
        bSerialiseValue = false;
      }
      break;
    default:  // Buttons and other stuff we can't/shouldn't send automatically.
      bSerialiseValue = false;
    }
    if (bSerialiseValue)
    {
      sValue = escape(sValue);
      sValue = sValue.replace( /\+/g, "%2b" );
      sVar = hoForm.elements[i].name;
      if (hoValues[sVar])
      {
        hoValues[sVar] = hoValues[sVar]+","+sValue;
      }
      else
      {
        hoValues[sVar] = sValue;
      }
    }
  }
  sValues = "";
  for ( sVar in hoValues )
  {
    sValues += sVar+"="+hoValues[sVar]+"&";
  }
  return sValues;
}

function postResults( sUrl, sFormName, sTargetId, sTriggerName, sTriggerValue )
{
  var hoTargetContainer;
  var hoXmlHttp = new XMLHttpRequest();
  
  if (hoXmlHttp == null)
  {
    // Can't handle AJAX - quit
//alert("No Ajax control");
    return true;
  }
  
  sFormValues = serialiseFormValues( sFormName );
  if (sFormValues == null)
  {
    // Form not found
//alert("No form found");
    return true;
  }
  sFormValues += sTriggerName + "=" + escape(sTriggerValue);
  sFormValues += "&isAjax=1";
//alert("Submitting: " + sFormValues);

  hoXmlHttp.open("POST", sUrl, false);
  hoXmlHttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
  hoXmlHttp.send(sFormValues);
  
  hoTargetContainer = document.getElementById(sTargetId);
  if (hoTargetContainer)
  {
    if (hoXmlHttp.status == 200)
    {
      // 200 = OK
      hoTargetContainer.innerHTML = hoXmlHttp.responseText;
    }
    else
    {
      hoTargetContainer.innerHTML = "<p>Unable to retrieve data</p>";
    }
  }
  return false;
}

function postFormResults( hoFormElement, sTargetId, sTriggerName, sTriggerValue )
{
  var sFormName;
  var sUrl;
  var hoForm = hoFormElement;
  var hoTop = document.body;
  
  while ( hoForm != hoTop && hoForm.tagName != "FORM" )
  {
    hoForm = hoForm.parentNode;
  }
  if ( hoForm.tagName == "FORM" )
  {
//alert("Found Form " + hoForm.name);
    // Post
    sUrl      = hoForm.action;
    sFormName = hoForm.name;
//alert("Got URL " + sUrl + ", name " + sFormName);
    if ( !sTriggerName )
    {
      hoSubmit = hoFormElement;
      if ( hoSubmit.type != "submit" )
      {
//alert("Finding submit button");
        hoSubmit = findFirstFormElementOfType( hoForm, "submit" );
      }
      if ( hoSubmit )
      {
        sTriggerName  = hoSubmit.name;
        sTriggerValue = hoSubmit.value;
//alert("Found submit button named " + sTriggerName + " = " + sTriggerValue);
      }
    }
//alert("postResults()");
    return postResults( sUrl, sFormName, sTargetId, sTriggerName, sTriggerValue );
  }
//alert("Didn't find Form");
  return true;
}

function setAllCheckboxes( sFormName, bValue )
{
  var hoForm = document.forms[sFormName];
  var i;
  
  if (hoForm == null) {
    // Can't find form - ignore
    return false;
  }
  
  for ( i = 0; i < hoForm.elements.length; i++ )
  {
    if (hoForm.elements[i].type == 'checkbox' )
    {
      hoForm.elements[i].checked = bValue;
    }
  }
  return true;
}

function tickAllCheckboxes( sFormName )
{
  return setAllCheckboxes( sFormName, true );
}

function untickAllCheckboxes( sFormName )
{
  return setAllCheckboxes( sFormName, false );
}


function launchContentInPane( hoSource, sPaneContentId, sName )
{
  var sPaneId = sPaneContentId+"_container"
  var hoPane;
  var hoParent;
  
  hoPane = document.getElementById(sPaneId);
  if ( hoPane == null )
  {
    hoPane = document.createElement("DIV");
    hoParent = document.body;
    hoPane.id = sPaneId;
    hoPane.className = 'floatingPane';
    hoPane.style.top = '200px';
    hoPane.style.left = '100px';
    hoParent.appendChild(hoPane);
  }

  hoPane.innerHTML = '<div style="float: right; position: relative;"><a href="" onclick="closePane(\''+sPaneId+'\'); return false;">[X]</a></div><div class="moveable-titlebar" onMouseDown="beginDrag(this.parentNode, event);"><h1>'+sName+'</h1></div><div id="'+sPaneContentId+'" class="paneContent"></div>';
  fetchDocumentAsync( 0, hoSource.href, sPaneContentId, "" );
  return false;
}

function closePane( sPaneId )
{
  var hoPane = document.getElementById(sPaneId);
  var hoParent;
  
  if ( hoPane == null )
  {
    return false;
  }
  hoParent = document.body;
  if ( hoParent == null )
  {
    return false;
  }
  hoParent.removeChild(hoPane);
  return true;
}

function beginDrag( hoFloatingWindow, event )
{
	var deltaX = event.clientX - parseInt(hoFloatingWindow.style.left);
	var deltaY = event.clientY - parseInt(hoFloatingWindow.style.top);
	
//		alert(hoFloatingWindow.id + ": deltaX="+ hoFloatingWindow.style.left + ", deltaY=" + hoFloatingWindow.style.top);
	if (document.addEventListener) {
		document.addEventListener("mousemove", moveHandler, true);
		document.addEventListener("mouseup", upHandler, true);
	}
	else if (document.attachEvent) {
		document.attachEvent("onmousemove", moveHandler);
		document.attachEvent("onmouseup", upHandler);
	}
	else {
		var oldmovehandler = document.onmousemove;
		var olduphandler = document.onmouseup;
		document.onmousemove = moveHandler;
		document.onmouseup = upHandler;
	}
	if (event.stopPropagation) event.stopPropagation();
	else event.cancelBubble = true;
	if (event.preventDefault) event.preventDefault();
	else event.returnValue = false;

	function moveHandler(e){
		if (!e) e = window.event;
		hoFloatingWindow.style.left = (e.clientX - deltaX) + "px";
		hoFloatingWindow.style.top = (e.clientY - deltaY) + "px";
		if (e.stopPropagation) e.stopPropagation();
		else e.cancelBubble = true;
	}

	function upHandler(e){
		if (!e) e = window.event;
		if (document.removeEventListener) {
			document.removeEventListener("mouseup", upHandler, true);
			document.removeEventListener("mousemove", moveHandler, true);
		}
		else if (document.detachEvent){
			document.detachEvent("onmouseup", upHandler);
			document.detachEvent("onmousemove", moveHandler);
		}
		else {
			document.onmouseup = olduphandler;
			document.onmousemove = oldmovehandler;
		}
		if (e.stopPropagation) e.stopPropagation();
		else e.cancelBubble = true;
	}
}


// -- Initialisation functions
window.onunload = function() {
	for ( var hoXmlHttp in gvhoXmlHttpRequests ) {
		if (hoXmlHttp === null) {
			hoXmlHttp.abort();
		}
	}
}

function registerCustomIslands( iSetId, sUrl, sNodeId, sInitialTab )
{
  gvsCustomIslandDetails[iSetId] = { url: sUrl, id: sNodeId, initialTab: sInitialTab, lastTab: "" };
  if (!gbCustomIslandsRegistered)
  {
    window.onload = initialiseCustomIslands;
    gbCustomIslandsRegistered = true;
  }
}

function initialiseCustomIslands()
{
  var iSetId, sUrl, sNodeId, sInitialTab;

  for (iSetId in gvsCustomIslandDetails)
  {
    if (gvsCustomIslandDetails[iSetId])
    {
      sUrl        = gvsCustomIslandDetails[iSetId].url;
      sNodeId     = gvsCustomIslandDetails[iSetId].id;
      sInitialTab = gvsCustomIslandDetails[iSetId].initialTab;
      fetchDocumentAsync( iSetId, sUrl, sNodeId, "displayTab("+iSetId+",'"+sInitialTab+"');" );
//      fetchDocument( sUrl, sNodeId, "" );
//      displayTab( iSetId, sInitialTab );
    }
  }
}


