/*

Copyright (c) 2005, Daniel Juliano
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this 
      list of conditions and the following disclaimer.
    * The names of contributors to this source code may not be used to endorse 
      or promote products derived from this software without specific prior 
      written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

/*

Script Summary:

Take a two-dimensional array of contact information and paint it to a sortable
table inside the 'sort_div' <div> tag in client.php.  Features include the
ability to change what type of information is viewed in any column (name, phone,
etc), sort in ascending or descending order, and pagination links
that dynamically populate at the bottom of the div.

Usage:

  1) Call initializeSort() once the xml contacts array has loaded.
  2) Call sortDisplay() whenever the 'Sort' button is clicked on the form.

Note: the display table's row size can vary as much as you want it to
and it will repaginate as needed.  Just update client.php and fill
in more td's or tr's as needed.

*/

var sortArray = null;
var sortTags = null;
var sortIndex = 0;
var sortColumn = 0;
var sortDown = false;
var sortDefaults = "";

var sortTableHeight = 0;
var sortTableWidth = 0;

var sortPage = 0;
var sortPaginateIndex = 0;

// Run once xml doc has loaded.
function initializeSort(records, tags, tableName, defaultColumns) {
	sortArray = records;
	if (records == null) sortArray = Array();
	sortTags = tags;
	sortDefaults = defaultColumns;
	for (var i = 0; i < sortDefaults.length; i++) sortDefaults[i] = parseInt(sortDefaults[i]);
	
	sortRegisterTable(tableName);
	sortPaintColumnHeader();
}

// Run when 'Sort' button is clicked.
function sortDisplay() {
	sortPaintArrows(true);
	sortRequest();
}

// 'Register' the various td's in the display table by forcing assignment
// of id's to each td.  The first row is always the column header row.
function sortRegisterTable(tableName) {
	
	var table = document.getElementById(tableName);
	var tr = table.getElementsByTagName("TR");
	var td = tr[0].getElementsByTagName("TD");
	var id = "";
	var counter = -1;
	
	sortTableHeight = tr.length - 1; // -1 for header row
	sortTableWidth = td.length;
	
	// Set the click events for the column headers.
	for (var i = 0; i < sortTableHeight + 1; i++) {
		td = tr[i].getElementsByTagName("TD");
		for (var j = 0; j < sortTableWidth; j++) {
			if (i == 0) {
				id = "sort_title_" +  mainFormatToTwo(j);
				td[j].className = "sort_title";
				td[j].id = id;
			} else {
				id = "sort_" + mainFormatToTwo(i - 1) + "_" + mainFormatToTwo(j);
				td[j].className = "sort_td";
				td[j].onclick = function(event) { buttonDisplayAction("action_view", this); highlightSelect(this.id); };
				td[j].onmouseover = function(event) { highlightRow(this, 1); };
				td[j].onmouseout = function(event) { highlightRow(this, 0); };
				td[j].id = id;
			}
		}
	}
}


// The contacts array can be sorted against a given index instead 
// of having to build a seperate sort filter for each field we 
// want to be able to sort by.
function sortUpDown(element) {
	var column = mainParseFormatted(element.id.split("_")[2]);
	if (column == sortColumn) {
		sortDown = !sortDown;
	} else {
		sortDown = true;
		sortColumn = column;
	}
	sortPaintArrows();
	sortRequest();
}
function sortOnSelect(element) {
	sortDown = true;
	sortColumn = mainParseFormatted(element.id.split("_")[2]);
	sortPaintArrows();
	sortRequest();
}
function sortRequest() {
	
	// Initialize the row highlighting routine each time.
	highlightInit(new Array("sort_td", "sort_td_highlight", "sort_td_selected"));
	
	var id = "sort_select_" + mainFormatToTwo(sortColumn);
	sortIndex = document.getElementById(id).selectedIndex;
	if (sortDown) {
		sortArray.sort(sortDescending);
	} else {
		sortArray.sort(sortAscending);
	}
	
	sortPaintPaginate(sortIndex);
	sortPaintTable(0);
}
function sortDescending(a, b) {
	if (a[sortIndex] < b[sortIndex]) { return -1; } 
	else if (a[sortIndex] > b[sortIndex]) { return 1; } 
	else { return 0; }
}
function sortAscending(a, b) {
	if (a[sortIndex] > b[sortIndex]) { return -1; } 
	else if (a[sortIndex] < b[sortIndex]) { return 1; } 
	else { return 0; }
}


// Paint functions move records from arrays to table. The table is
// hardcoded html so that designers have something to work with
// when theming.


// When the user selects a contact to view, the contact information
// is blown into the View table.  Build the outline for this table
// once, when sortTags[] has been initialized.
function sortPaintAdd() {
	var html = "";
	html += "<table id=\"form_add_table\"><TBODY>";
	html += "<tr><td id=\"form_add_title\" colspan=\"2\">Add Contact</td></tr>\n";
	for (var i = 0; i < sortTags.length; i++) {
		html += "<tr><td>" + sortTags[i] + ":</td>";
		html +=	"<td><input type=\"text\" id=\"form_add_" + i + "\" value=\"\"></td></tr>\n";
	}
	html +=" <tr><td id=\"form_add_button\" colspan=\"2\"><input type=\"submit\" name=\"submit_add\" value=\"Update List\" onClick=\"buttonFormAction('add');\"></td></tr>";
	html += "</TBODY></table>\n";
	
	document.getElementById("form_add_div").innerHTML = html;
}
function sortPaintView() {
	var html = "";
	html += "<table id=\"form_view_table\"><TBODY>";
	html += "<tr><td id=\"form_view_title\" colspan=\"2\">View Contact</td></tr>\n";
	for (var i = 0; i < sortTags.length; i++) {
		html += "<tr><td>" + sortTags[i] + ":</td><td id=\"form_view_" + i + "\">&nbsp;</td></tr>\n";
	}
	html += "</TBODY></table>\n";
	
	document.getElementById("form_view_div").innerHTML = html;
}
function sortPaintEdit() {
	var html = "";
	html += "<table id=\"form_edit_table\"><TBODY>";
	html += "<tr><td id=\"form_edit_title\" colspan=\"2\">Edit Contact</td></tr>\n";
	for (var i = 0; i < sortTags.length; i++) {
		html += "<tr><td>" + sortTags[i] + ":</td>";
		html +=	"<td><input type=\"text\" id=\"form_edit_" + i + "\" value=\"\"></td></tr>\n";
	}
	html +=" <tr><td id=\"form_edit_button\" colspan=\"2\"><input type=\"submit\" name=\"submit_edit\" value=\"Update List\" onClick=\"buttonFormAction('edit');\"></td></tr>";
	html += "</TBODY></table>\n";
	
	document.getElementById("form_edit_div").innerHTML = html;
}

function sortPaintColumnHeader() {
	
	// Paint column headers.
	var defaults = null;
	if (sortDefaults != null) defaults = sortDefaults.split(", ");
	var checked = -1;
	var choices = "";
	var id_select = "";
	var id_img = "";
	var id_title = "";
	var id_span = "";
	var select = "";
	var img = "";
	var span = "";
	
	for (var i = 0; i < sortTableWidth; i++) {
		checked = -1;
		if (defaults[i] != null) checked = defaults[i];
		
		// Choices are a set of combobox options based on the sortTags array.
		choices = "";
		for (var j = 0; j < sortTags.length; j++) {
			if (checked != -1 && checked == j) {
				choices += "<option selected>" + sortTags[j] + "</option>\n";
			} else {
				choices += "<option>" + sortTags[j] + "</option>\n";
			}
		}
		choices += "</select>";
		
		id_select = "sort_select_" + mainFormatToTwo(i);
		select = "<select class='sort_select' id='" + id_select + "' onChange='sortOnSelect(this)'>\n";
		
		id_img = "sort_img_" + mainFormatToTwo(i);
		img = "<img class=\"sort_image\" src='support/image/circle.png' id='" + id_img + "' onClick='sortUpDown(this);'>\n";
		
//		id_span = "sort_span_" + mainFormatToTwo(i);
//		span = "<span class=\"sort_span\" id='" + id_img + "' onClick='sortRequest(\"" + id_select + "\");'>--</span>\n";
		
		id_title = "sort_title_" + mainFormatToTwo(i);
		document.getElementById(id_title).innerHTML = select + choices + img;
	}
}

// Column index sorted determines pagination.
function sortPaintPaginate(index) {
	
	if (index != null) sortPaginateIndex = index;
	
	if (sortArray.length <= sortTableHeight) {
		document.getElementById("pagination_div").innerHTML = "&nbsp;";
		return;
	}
	
	// Grab the start-to-end values of the currently sorted column.
	// For example, if we sort the phone numbers:
	//   555-1212
	//   555-1234
	//   555-1299
	// The start would be 555-1212 and the end would be 555-1299.
	
	var link_start = Array();
	var link_end = Array();
	
	var pages = Math.ceil(sortArray.length / sortTableHeight);
	for (var i = 0; i < pages; i++) {
		var start = i * sortTableHeight;
		var end = (i + 1) * sortTableHeight;
		if (end >= sortArray.length) end = sortArray.length - 1;
		
		link_start[i] = sortArray[start][sortPaginateIndex];
		link_end[i] = sortArray[end][sortPaginateIndex];
	}
	
	// One page has no need for pagination.
	if (pages == 1) return;
	
	// Amount of characters printed is determined by number of pages
	if (pages < 4) {
		for (var i = 0; i < pages; i++) {
			if (link_start[i].length > 5) link_start[i] = link_start[i].substring(0, 5);
			if (link_end[i].length > 5) link_end[i] = link_end[i].substring(0, 5);
		}
	} else if (pages < 7) {
		for (var i = 0; i < pages; i++) {
			if (link_start[i].length > 2) link_start[i] = link_start[i].substring(0, 2);
			if (link_end[i].length > 2) link_end[i] = link_end[i].substring(0, 2);
		}
	} else {
		for (var i = 0; i < pages; i++) {
			if (link_start[i].length > 1) link_start[i] = link_start[i].substring(0, 1);
			if (link_end[i].length > 1) link_end[i] = link_end[i].substring(0, 1);
		}
	}
	
	// Create links from start and end arrays.
	var links = "";
	for (var i = 0; i < pages; i++) {
		links += "<span class='sort_paginate' onClick='sortPaintTable(" + i + ", \"page_move\");'>";
		links += link_start[i] + " &gt; " + link_end[i];
		links += "</span>&nbsp;";
	}
	document.getElementById("pagination_div").innerHTML = links;
}
function sortPaintTable(page, action) {
	
	var pages = Math.ceil(sortArray.length / sortTableHeight);
	if (page != null) sortPage = page;
	
	if (action != null) {
		if (action == "add") {
			// On add, go to last page
			sortPage = pages - 1;
			sortPaintArrows(true);
			
		} else if (action == "delete") {
			// On delete, make sure page no longer exists.
			var count = pages - 1;
			if (sortPage > count) sortPage = count;
			sortPaintArrows(true);
		}
	}
	
	// Determine start and end row of requested page.
	var start = sortPage * sortTableHeight;
	var end = (sortPage + 1) * sortTableHeight;
	
	// Loop through all records pertinent to page and paint to page.
	var table_row = -1;
	var array_column = 0;
	var selectId = "";
	for(var array_row = start; array_row < end; array_row++) {
		table_row++;
		for (var i = 0; i < sortTableWidth; i++) {
			selectId = "sort_select_" + mainFormatToTwo(i);
			array_column = document.getElementById(selectId).selectedIndex;
			sortPaintRecord(table_row, i, array_row, array_column);
		}
	}
	
	// If a page select moved back to the page holding the current selection, rehighlight the correct row.
	if (action != null && action == "page_move") {
		if (currentIndex >= start && currentIndex <= end) {
			highlightSelect(null);
		}
	}
	
	// Flip footer link styles.
	if (pages > 1 && sortIndex > 0) {
		var spans = document.getElementById("pagination_div").getElementsByTagName("SPAN");
		for (var i = 0; i < spans.length; i++) {
			spans[i].className = "sort_paginate";
		}
		spans[sortPage].className = "sort_paginate_highlight";
	}
}
function sortPaintRecord(table_row, table_column, array_row, array_column) {
	var id = "sort_" + mainFormatToTwo(table_row) + "_" + mainFormatToTwo(table_column);
	document.getElementById(id).className = "sort_td";
	if (sortArray[array_row]) {
		document.getElementById(id).innerHTML = sortArray[array_row][array_column];
	} else {
		// Still need to paint empty cells to keep table inflated.
		document.getElementById(id).innerHTML = "&nbsp;";
	}
}

function sortPaintArrows(reset) {
	
	// On reset, the first column is sorted.
	if (reset) {
		sortColumn = 0;
		sortDown = true;
	}
	
	var id = "";
	var status = 0;
	for (var i = 0; i < sortTableWidth; i++) {
		
		// Sorted index gets arrow, other columns show as unsorted.
		status = 0;
		if (i == sortColumn) {
			if (sortDown) {
				status = 1;
			} else {
				status = 2;
			}
		}
		
		id = "sort_img_" + mainFormatToTwo(i);
		
		switch (status) {
			case 0:
				document.getElementById(id).src = "support/image/circle.png";
				break;
			case 1:
				document.getElementById(id).src = "support/image/arrow-down.png";
				break;
			case 2:
				document.getElementById(id).src = "support/image/arrow-up.png";
				break;
		}
	}
}


