/*
javascript portion of To-Do list
by Jon Dubovsky (jon@dubovsky.com)
Some extremely primitive code to demonstrate AJAX and DHTML.

Note: for any real user, this must run over https with Apache managing user login.  This
code makes no security checks on the AJAX messages, so malicious users could delete all
their to-do tasks at will.  You have been warned.

v0.2 - initial alpha release
v0.3 - moved to XML responses
	- "new task" now adds appropriate HTML elements to list container
v0.4 - can now handle task descriptions with HTML entities and quotes (allows use of HTML tags in tasks)
*/

// Makes an XML HTTP (AJAX) request
// (str) is a POST string encoded by encodeURI
// example: MakeAjaxRequest( "action=login&name=" + encodeURI(strName) )
function MakeAjaxRequest(str)
{
	//alert("about to send:" + str);
	// TODO: fix SID security hole here
	var url = "index.php"	//?sid=" + Math.random() + "&q=" + str
	var formdata = str;		//key + "=" + encodeURI(str)
	xmlHttp = GetXmlHttpObject(stateChanged)
	xmlHttp.open("POST", url, true)
	xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	xmlHttp.setRequestHeader("Content-length", formdata.length);
	xmlHttp.send(formdata)
}

// state change callback for XMLHttp (lets us know when we're complete)
function stateChanged() 
{ 
	if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete")
	{
		//alert("about to handle status(" + xmlHttp.status + ") with text: " + xmlHttp.responseText + " -- XML " + xmlHttp.responseXML);
		if (xmlHttp.status == 200)		// only work on HTTP OK
		{
			/* server response:
			<response>
				<method>UpdateTask</method>
				<taskid>1</taskid>
				<sortorder>90</sortorder>
				<deadline>123444</deadline>
				<complete>0</complete>
				<username>guest</username>
				<descr>Walk the dog</descr>
			</response>
			*/
			response = xmlHttp.responseXML.documentElement;
			method = response.getElementsByTagName('method')[0].firstChild.data;
			taskId = response.getElementsByTagName('taskid')[0].firstChild.data;
			
			tempCh = response.getElementsByTagName('sortorder')[0].firstChild;
			if (tempCh)
				sortOrder = tempCh.data
			else
				sortOrder = undefined;
				
			tempCh = response.getElementsByTagName('deadline')[0].firstChild;
			if (tempCh && tempCh.data)
				deadline = tempCh.data
			else
				deadline = undefined;
			
			tempCh = response.getElementsByTagName('complete')[0].firstChild;
			if (tempCh)
				complete = tempCh.data;
			else
				complete = 0;

			tempCh = response.getElementsByTagName('username')[0].firstChild;
			if (tempCh)
				username = tempCh.data;
			else
				username = '';

			tempCh = response.getElementsByTagName('descr')[0].firstChild;
			if (tempCh)
				taskText = tempCh.data;
			else
				taskText = '';
			// replace any double quotes in taskText (so eval doesn't puke)
			taskText = taskText.replace(/\"/g, '\\"');
			eval( method + '(' + taskId + ',' + complete + ',"' + taskText + '")' );
		}
		else
			alert("Error response from the server: " + req.statusText);
	}
}

// returns a task to the "normal" state (not editing, enabled, etc.)
function MakeTaskNormalView(taskId, bShowDelete)
{
	el = document.getElementById("editcon-task" + taskId)
	el.className = "hidden";
	el = document.getElementById("edit-task" + taskId);
	el.disabled = true;
	// show the display text
	el = document.getElementById("def-task" + taskId);
	el.className = "";
	// handle checkbox
	el = document.getElementById("check-task" + taskId);
	if (bShowDelete)
		el.disabled = false;
	else
		el.disabled = true;
	// handle delete button
	el = document.getElementById("del-task" + taskId);
	if (el)
	{
		if (bShowDelete)
			el.className = ""
		else
			el.className = "hidden"
	}
}

function UpdateTask(taskId, nComplete, taskText)
{
	//document.getElementById("disp-task" + taskId).innerHTML = taskText
	// hide the edit form
	el = document.getElementById("editcon-task" + taskId)
	if (!el)
	{
		// this is a new task -- add the html for it
		
		strNewTask = document.getElementById("taskadd").innerHTML;
		strNewTask = strNewTask.replace(/add/g, taskId);
		newListItem = document.createElement("li");
		newListItem.id = "task" + taskId;
		newListItem.innerHTML = strNewTask;
		
		// first, re-enable the "add a new task" list item
		el = document.getElementById("edit-taskadd");
		el.value = '';		// blank the input editbox
		MakeTaskNormalView('add', false);
		
		listCont = document.getElementById("todolist");
		//listCont.appendChild(newListItem);

		el = document.getElementById("taskadd");
		listCont.insertBefore(newListItem, el.nextSibling);

		el = document.getElementById("editcon-task" + taskId);
		// TODO: change to insertBefore (syntax?)
	}
	
	el.className = "hidden";
	el = document.getElementById("edit-task" + taskId);
	el.disabled = true;
	// show the display text
	el = document.getElementById("def-task" + taskId);
	el.innerHTML = taskText;
	el.className = "";
	// handle checkbox
	el = document.getElementById("check-task" + taskId);
	elListItem = document.getElementById("task" + taskId);
	if (nComplete == "2")	// deleted (hidden)
	{
		el.checked = true;
		elListItem.className = "hidden";
	}
	else if (nComplete == "1")	// complete
	{
		el.checked = true;
		elListItem.className = "complete";
	}
	else					// not complete
	{
		el.checked = false;
		elListItem.className = "";
	}
	el.disabled = false;
	// handle delete button
	el = document.getElementById("del-task" + taskId);
	if (el)
		el.className = "";
}

// browser-independent XmlHttp factory
function GetXmlHttpObject(handler)
{ 
	var objXmlHttp = null
	if (window.XMLHttpRequest)	// good for modern browsers (Mozilla, Safari, IE7, etc.)
	{
		objXmlHttp = new XMLHttpRequest()
		objXmlHttp.onload = handler
		objXmlHttp.onerror = handler 
		return objXmlHttp
	}

	if (window.ActiveXObject)	// try methods for old IE (5.x and 6)
	{
		var strName="Msxml2.XMLHTTP"
		if (navigator.appVersion.indexOf("MSIE 5.5") >= 0)
			strName="Microsoft.XMLHTTP"
		
		try
		{
			objXmlHttp = new ActiveXObject(strName)
			objXmlHttp.onreadystatechange = handler 
			return objXmlHttp
		}
		catch (e)
		{ 
			alert("Error: cannot create XMLHttp object.  Scripting for ActiveX might be disabled.")
			return null
		}
	}
}

// called when the user completes changing the task text edit box
function TaskTextChange(taskId)
{
	el = document.getElementById("edit-task" + taskId);
	strTaskText = el.value;
	el.disabled = true;		// don't let user type anything new until server okays this write

	if (taskId == "add")
	{
		MakeAjaxRequest( "action=add" +
			"&descr=" + encodeURI(strTaskText) );
	}
	else
	{
		// modify an existing task
		MakeAjaxRequest( "action=modify" +
			"&id=" + encodeURI(taskId) +
			"&descr=" + encodeURI(strTaskText) );
	}
}

// called when a key event happens on the task text edit control
// simply intercepts enter (to submit data to the server)
function editTaskKey(taskId, event)
{
	if (event && (event.which == 13 || event.keyCode == 13))
	{
		TaskTextChange(taskId);
		return false;
	}
	else
		return true;
}

// called when the user clicks the task text -- swaps in the edit form for that
//  task and sets the focus to the input box
function editTask(strId) {
	// hide the display text
	el = document.getElementById("def-task" + strId);
	el.className = "hidden";
	// hidee the delete button
	el = document.getElementById("del-task" + strId);
	if (el)		// may not exist for new tasks
		el.className = "hidden";
	// show the edit form
	el = document.getElementById("editcon-task" + strId);
	el.className = "";
	el = document.getElementById("edit-task" + strId);
	el.disabled = false;
	
	el.focus();		// note: doesn't work in Opera
	return true;
}

// called when user checks/unchecks the "complete" checkbox
function checkboxTask(strId)
{
	el = document.getElementById("check-task" + strId);
	el.disabled = true;			// don't let user change it until server okays this write
	strComplete = "0";
	if (el.checked)
		strComplete = "1";
	MakeAjaxRequest( "action=modify" +
		"&id=" + encodeURI(strId) +
		"&complete=" + encodeURI(strComplete) );
	return true;
}

// called when user clicks the "delete task" link
function deleteTask(strId)
{
	// make sure the user really wants to
	if (!confirm("Delete the task?"))
		return false;
	el = document.getElementById("del-task" + strId);
	el.disabled = true;			// don't let user change it until server okays this write
	MakeAjaxRequest( "action=delete" +
		"&id=" + encodeURI(strId) )
	return true;
}


