/*



Name:			MarkedListJS.jsp

Description:	JavaScript for addtion/removal of items to a users marked list using asynchronous HTTP

				requests to the server. This is done using JavaScript and the XMLHttpRequest object.

Expects:		1) All the marked list checkboxes have an id attribute set to 'mlcb#' where # is a sequential number starting with 1,

					and have a value set to a valid marked list action url for this item.

				2) Any page importing this js file defines the following JavaScript functions:

					notifyMarkedListLimitReached()

					notifyMarkedListAddError()

					notifyMarkedListRemoveError()

					notifyMarkedListRemoveNotFound()

					notifyMarkedListHttpReqNotSupported()

					markedListAddSuccess(checkbox)

					markedListRemoveSuccess(checkbox)

Author:			Andy Blower

Usage Example:



<%-- Product specific marked list JavaScript. --%>

<script type="text/javascript" language="Javascript">

<!--

function notifyMarkedListLimitReached()

{

	alert("Your marked list is full, please delete some entries before adding more.");

}

function notifyMarkedListAddError(reason)

{

	alert("The server encountered an error, and was unable to add the entry to your marked list.");

}

function notifyMarkedListRemoveError(reason)

{

	alert("The server encountered an error, and was unable to remove the entry from your marked list.");

}

function notifyMarkedListRemoveNotFound()

{

	alert("That entry was not found in your marked list.");

}

function notifyMarkedListHttpReqNotSupported()

{

	alert("Couldn't get HttpRequest object, marked list functionality not availible! Please upgrade your browser.");

}

function markedListAddSuccess(checkbox)	{	}

function markedListRemoveSuccess(checkbox)	{	}

// -->

</script>



<%-- Core marked list JavaScript. --%>

<script	src="/javascript/MarkedList.js" type="text/javascript" language="Javascript"></script>



<%-- Set base marked list url. --%>

<%@ page import="pq.core.actions.search.*" %>

<c-rt:set var="PARAM_ITEM_NUMBER"	value="<%= DisplayItemFromResultsAction.PARAM_ITEM_NUMBER %>"/>

<c:set var="baseMLUrl"		value="/markedList/markedResultsItem.do?${typeParam}&${ResultsIDParam}&${PARAM_ITEM_NUMBER}"/>



<%-- Get the id map for the users marked list. --%>

<c:set var="markedListIdMap" value="${sessionScope.MarkedList.uniqueIdIndex}"/>



... other stuff ...



<input type="checkbox" id="mlcb<c:out value="${status.count}"/>" onClick="javascript:doMarkedList(this);"<c:if test="${not empty markedListIdMap[result.uniqueID]}"> checked</c:if>

value="<c:url value="${baseMLUrl}=${result.index}&${PARAM_ID}=${result.uniqueID}&${PARAM_CATEGORY}=${markedListCategory}&subtype=${typeValue}"><c:param name="${PARAM_TITLE}" value="${fields.title}"/><c:param name="${PARAM_DESCRIPTION}" value="${description}"/></c:url>">



*/



// Switch for debugging alert boxes.

var DEBUG = false;



// Global variables for selecting all & signaling when a users' marked list is full.

var selAllMLActive = false;

var selAllMLSignal = "";

var selAllMLCounter = 0;

var selAllMLCount = 0;



/*

** Select all marked list checkboxes on the page, adding the items to the users' marked list.

** Params:	selected - whether the checkboxes should be checked (added) or unchecked (removed)

*/

function selectAllMarkedList(selected)

{

	if (!selAllMLActive)

	{

		selAllMLActive = true;

		selAllMLSignal = "";

		// Loop through the marked list checkboxes, until there are either no more checkboxes,

		// or the list limit has been reached & we're adding.

		var i = 1;

		selAllMLCount = 0;

		while ( (checkbox = document.getElementById("mlcb" + i)) != null &&	!(selAllMLSignal == "limit" && selected) )

		{

			if (checkbox.checked != selected) {

				checkbox.checked = selected;

				checkbox.onclick();

				selAllMLCount++;

			}

			i++;

		}

		selAllMLCounter = selAllMLCount;

		if (selAllMLCount > 0)

		{

			// Disable the mark all checkbox/link/button if it has an id of 'markAllActivator'.

			var markAllActivator = document.getElementById('markAllActivator');

			if (markAllActivator) {

				markAllActivator.disabled = true;

			}

		}

		selAllMLActive = false;

	}

}



/*

** Process an action for an item, i.e. add/remove to/from the users' marked list.

** Params:	checkbox 	- the item's marked list checkbox object.

*/

function doMarkedList(checkbox)

{

	// Add the method to be executed to the parameters.

	var mlUrl;

	if (checkbox.checked == true) {

		mlUrl = checkbox.value + "&method=add";

	} else {

		mlUrl = checkbox.value + "&method=remove";

	}

	// Get an XMLHTTPConnection object.

	var mlConn = new mlXHConn();

	if (!mlConn)	// Browser doesn't support XMLHttpRequest.

		notifyMarkedListHttpReqNotSupported();



	var fnWhenDone =

		function (XHObj, selAllMLActiveOnConn)

		{

			if (XHObj.status == 200)

			{

				var response = XHObj.responseText.split(",");

				var method = response[1], result = response[2], reason = response[3];

				if (DEBUG)	alert("Response: method= " + method + ", result= " + result + ", reason= " + reason);



				// Process the response.

				if (method.indexOf("add") != -1)

				{

					if (result.indexOf("success") == -1)

					{

						// Couldn't be added, so uncheck the checkbox and give the user the reason.

						checkbox.checked = false;

						if (reason.indexOf("error") != -1) {

							notifyMarkedListAddError(reason);

						} else if (reason.indexOf("reachedLimit") != -1) {

							// Reached ML limit - if selecting all, set signal so user only notified once.

							if (selAllMLActiveOnConn) {

								if (selAllMLSignal != "limit") {

									selAllMLSignal = "limit";

									notifyMarkedListLimitReached();

								}

							} else {

								notifyMarkedListLimitReached();

							}

						}

					} else {

						markedListAddSuccess(checkbox);

					}

				}

				else if (method.indexOf("remove") != -1)

				{

					if (result.indexOf("success") == -1)

					{

						// Couldn't be removed, only recheck the checkbox if an error occurred.

						if (reason.indexOf("error") != -1) {

							checkbox.checked = true;

							notifyMarkedListRemoveError(reason);

						} else if (reason.indexOf("notfound") != -1) {

							// Notify the user only if not deselecting all. (NOTE: probably won't want to do this in a real app)

							if (selAllMLActiveOnConn) {

								notifyMarkedListRemoveNotFound(reason);

							}

						}

					} else {

						markedListRemoveSuccess(checkbox);

					}

				}

			}

			else

			{	/* For developers sight only - should never happen once deployed anyway! */

				if (DEBUG)	alert("Error with response from server. status=" + XHObj.status + ", resp=" + XHObj.responseText);

			}

		};

	if (DEBUG)

		alert("Connecting to:\n" + mlUrl);



	mlConn.connect(mlUrl, fnWhenDone);

}



/*

** mlXHConn - Simple XMLHttpRequest Interface Object, specific to marked list.

** Need an object so that many asynchronous requests can be handled simultaneously.

** Had to make this specific to marked list, see me for a general XHConn.

*/

function mlXHConn()

{

	var xmlhttp, bComplete = false;

	try {

		xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); }

		catch (e)	{ try {	xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); }

		catch (e)	{ try {	xmlhttp = new XMLHttpRequest(); }

		catch (e)	{ xmlhttp = false; }}

	}

	if (!xmlhttp)	return null;



	this.connect = function(mlUrl, fnDone)

	{

		if (!xmlhttp) return false;

		bComplete = false;



		try {

			xmlhttp.open("GET", mlUrl, true);

			if (selAllMLActive) {

				xmlhttp.onreadystatechange = function() {

					if (xmlhttp.readyState == 4 && !bComplete) {

						bComplete = true;

						fnDone(xmlhttp, true);

					}

				};

			} else {

				xmlhttp.onreadystatechange = function() {

					if (xmlhttp.readyState == 4 && !bComplete) {

						bComplete = true;

						fnDone(xmlhttp, false);

				}

				};

			}

			xmlhttp.send("");

		} catch(z) { return false; }

		return true;

	};

	return this;

}

