function GetXmlHttpObject() {
	var xmlHttp = null;
	try {
		// Firefox, Opera 8.0+, Safari
		xmlHttp = new XMLHttpRequest();
	}
	catch (e) {
		// Internet Explorer
		try {
			xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
		}
		catch (e) {
			xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
		}
	}
	
	return xmlHttp;
}

/** Keep hold of the current table being dragged */
var currenttable = null;

/** Capture the onmousemove so that we can see if a row from the current
 *  table if any is being dragged.
 * @param ev the event (for Firefox and Safari, otherwise we use window.event for IE)
 */
document.onmousemove = function(ev){
    if (currenttable && currenttable.dragObject) {
		var rows = currenttable.dragObject;
        ev   = ev || window.event;
        var mousePos = currenttable.mouseCoords(ev);
		//document.getElementById("debug").innerHTML = "hey:"+mousePos.x+", "+mousePos.y;
        var y = mousePos.y - currenttable.mouseOffset.y;
        if (y != currenttable.oldY) {
            // work out if we’re going up or down…
            var movingDown = y > currenttable.oldY;
            // update the old value
            currenttable.oldY = y;
            // update the style to show we’re dragging
			for (var m = 0; m < rows.length; m++) {
				var cells = rows[m].getElementsByTagName("td");
				var myclass;
				
				for (var n = 1; n < cells.length-1; n++) {
					myclass = cells[n].className;
					
					if (myclass == "rowheaderleft")
						myclass = "rowheaderleftselect";
					else if (myclass == "rowheader")
						myclass = "rowheaderselect";
					else if (myclass == "rowheaderright")
						myclass = "rowheaderrightselect";
					else if (myclass == "subrowheaderleft")
						myclass = "subrowheaderleftselect";
					else if (myclass == "subrowheader")
						myclass = "subrowheaderselect";
					else if (myclass == "subrowheaderright")
						myclass = "subrowheaderrightselect";					
					
            		cells[n].className = myclass;
				}
			}
            // If we’re over a row then move the dragged row to there so that the user sees the
            // effect dynamically
            var currentRow = currenttable.findDropTargetRow(y);
			var dragType = rows[0].id.split("_")[0];
			var firstRow = null;
			
			var tableRows = table.tBodies[0].rows;
			
            if (currentRow && dragType == "sub") {				
                if (movingDown && rows[0].id != currentRow.id) {
                    rows[0].parentNode.insertBefore(rows[0], currentRow.nextSibling);
                } else if (! movingDown && rows[0].id != currentRow.id) {
					for (var k=0; k<tableRows.length; k++) {
						arrCurr = tableRows[k].id.split("_");
						if (firstRow == null && arrCurr[0] == "row"&& tableRows[k].id == currentRow.id)
							return false;
						else if (firstRow == null && arrCurr[0] == "row")
							firstRow = tableRows[k];
					}
					
                    rows[0].parentNode.insertBefore(rows[0], currentRow);
                }
            }
			else if (currentRow && dragType == "row") {
				var arr2 = currentRow.id.split("_");
				
				for (var j = 0; j < rows.length; j++) {
					if (currentRow.id == rows[j].id) {
						return false;
					}
				}
				
				var insertpoint = null;
				var tableRows = table.tBodies[0].rows;
				
				if (movingDown) {
					var prevRow = null;
					
					for (var k=0; k<tableRows.length; k++) {
						arrCurr = tableRows[k].id.split("_");
						if (prevRow != null && arrCurr[0] == "sub") {
							arrPrev = prevRow.id.split("_");
							if (arrPrev[0] == "sub" && prevRow.id == currentRow.id)
								return false;
							else if (arrPrev[0] == "row" && prevRow.id == currentRow.id)
								return false;						
						}
						
						prevRow = tableRows[k];
					}
					
					insertpoint = currentRow.nextSibling;
				}
				else {
					if (arr2[0] != "row")
						return false;
						
					insertpoint = currentRow;
				}
				
				for (var l = 0; l < rows.length; l++) {
					rows[l].parentNode.insertBefore(rows[l], insertpoint);
				}					
			}
        }

        return false;
    }
}

// Similarly for the mouseup
document.onmouseup = function(ev){
    if (currenttable && currenttable.dragObject) {
		var droppedRows = currenttable.dragObject;
		var myclass = "";
        // If we have a dragObject, then we need to release it,

        // The row will already have been moved to the right place so we just reset stuff
		for (var i = 0; i < droppedRows.length; i++) {
			var cells = droppedRows[i].getElementsByTagName("td");				
				
			for (var j = 1; j < cells.length-1; j++) {
				myclass = cells[j].className;
				
				if (myclass == "rowheaderleftselect")
					myclass = "rowheaderleft";
				else if (myclass == "rowheaderselect")
					myclass = "rowheader";
				else if (myclass == "rowheaderrightselect")
					myclass = "rowheaderright";
				else if (myclass == "subrowheaderleftselect")
					myclass = "subrowheaderleft";
				else if (myclass == "subrowheaderselect")
					myclass = "subrowheader";
				else if (myclass == "subrowheaderrightselect")
					myclass = "subrowheaderright";					
				
				cells[j].className = myclass;
			}
		}
		
        currenttable.dragObject  = null;
        // And then call the onDrop method in case anyone wants to do any post processing
        currenttable.onDrop(currenttable.table, droppedRows);
    }
}

/** get the source element from an event in a way that works for IE and Firefox and Safari
 * @param evt the source event for Firefox (but not IE–IE uses window.event) */
function getEventSource(evt) {
    if (window.event) {
        evt = window.event; // For IE
        return evt.srcElement;
    } else {
        return evt.target; // For Firefox
    }
}

// TABLE ROW DRAG & DROP
function TableDnD() {
    /** Keep hold of the current drag object if any */
    this.dragObject = null;
    /** The current mouse offset */
    this.mouseOffset = null;
    /** The current table */
    this.table = null;
    /** Remember the old value of Y so that we don’t do too much processing */

    this.oldY = 0;

    // rest of the code goes here…
	/** Initialise the drag and drop by capturing mouse move events */

    this.init = function(table) {
        this.table = table;
        var rows = table.tBodies[0].rows; //getElementsByTagName("tr")
        for (var i=0; i<rows.length; i++) {
            // John Tarr: added to ignore rows for which the NoDrag attribute is set
            var nodrag = rows[i].getAttribute("nodrag")
            if (nodrag == null || nodrag == "undefined") { 
				// There is no NoDrag attribute so make draggable
                this.makeDraggable(rows[i]);
            }
        }
    }

	/** This function is called when you drop a row, so redefine it in your code
        to do whatever you want, for example use Ajax to update the server */
    this.onDrop = function(table, droppedRows) {
		//alert("hi");
		var rows = table.tBodies[0].rows;
		var orderStr = "";
		var bar = "";
		var parent = "0";
		
		for (var i=0; i<rows.length; i++) {
			var arr = rows[i].id.split("_");
			if (arr[0] == "row") {
				orderStr += bar + arr[1] + ".0";
				parent = arr[1];
				bar = "|";
			} else if (arr[0] == "sub") {
				orderStr += bar + arr[1] + "." + parent;
				bar = "|";
			}	
		}
		reorderRows(orderStr);
    }

	/** Get the position of an element by going up the DOM tree and adding up all the offsets */
    this.getPosition = function(e){
        var left = 0;
        var top  = 0;

        while (e.offsetParent){
            left += e.offsetLeft;
            top  += e.offsetTop;
            e     = e.offsetParent;
        }

        left += e.offsetLeft;
        top  += e.offsetTop;

        return {x:left, y:top};
    }

    /** Get the mouse coordinates from the event (allowing for browser differences) */
    this.mouseCoords = function(ev) {
        if(ev.pageX || ev.pageY){
            return {x:ev.pageX, y:ev.pageY};
        }
        return {
            x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,
            y:ev.clientY + document.body.scrollTop  - document.body.clientTop
        };
    }

    /** Given a target element and a mouse event, get the mouse offset from that element.
        To do this we need the element’s position and the mouse position */
    this.getMouseOffset = function(target, ev){
        ev = ev || window.event;

        var docPos    = this.getPosition(target);
        var mousePos  = this.mouseCoords(ev);
        return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y};
    }
	
	 /** Take an item and add an onmousedown method so that we can make it draggable */
    this.makeDraggable = function(item){
        if(!item) return;
        var self = this; // Keep the context of the TableDnd inside the function
        item.onmousedown = function(ev){
            // get the event source in a browser independent way
            var target = getEventSource(ev);
            // if it’s an INPUT or a SELECT, then let the event bubble through, don’t do a drag
            if (target.tagName == "INPUT" || target.tagName == "SELECT" || target.tagName == "A") return true;
			
			var arr = item.id.split("_");
			var mydrag = new Array();
			if (arr[0] == "sub") {
				mydrag[0] = this;
				self.dragObject = mydrag;
			}
			else if (arr[0] == "row") {
				var parentid = "0";
				var rows = table.tBodies[0].rows;
				var newindex = 0;
				
				for (var i=0; i<rows.length; i++) {
					var arr2 = rows[i].id.split("_");
					if (parentid == "0" && arr2[0] == "row" && arr2[1] == arr[1]) {
						parentid = arr2[1];
						mydrag[newindex] = rows[i];
						newindex++;
					}
					else if (parentid == arr[1] && arr2[0] == "sub") {
						mydrag[newindex] = rows[i];
						newindex++;
					}
					else {
						parentid = "0"
					}
				}
				
				self.dragObject = mydrag;
			}
			else {
            	self.dragObject  = null;
			}
            self.mouseOffset = self.getMouseOffset(this, ev);
            return false;
        }
        item.style.cursor = "move";
    }

    /** We’re only worried about the y position, we can only move rows up and down */
    this.findDropTargetRow = function(y) {
        var rows = this.table.tBodies[0].rows;
        for (var i=0; i<rows.length; i++) {
            var row = rows[i];
            // John Tarr added to ignore rows that I’ve added the NoDrop attribute to (Header rows)
            var nodrop = row.getAttribute("nodrop");
            if (nodrop == null || nodrop == "undefined") {  //There is no NoDrop attribute on rows I want to drag
                var rowY    = this.getPosition(row).y;
                var rowHeight = parseInt(row.offsetHeight)/2;
                if (row.offsetHeight == 0) {
                    rowY = this.getPosition(row.firstChild).y;
                    rowHeight = parseInt(row.firstChild.offsetHeight)/2;
                }
                // Because we always have to insert before, we need to offset the height a bit
                if ((y > rowY - rowHeight) && (y < (rowY + rowHeight))) {
                    // that’s the row we’re over

                    return row;
                }
            }
        }
        return null;
    }

}

function reorderRows (orderStr) {
	xmlHttp = GetXmlHttpObject();
	if (xmlHttp == null) {
		alert ("Your browser does not support AJAX!");
		return;
	} 
	
	var url = "pages_ReorderRows.php";
	var tableName = document.getElementById("tableName").value;
	var idCol = document.getElementById("IDColumnName").value;
	var parentCol = document.getElementById("ParentColumnName").value;
	var orderCol = document.getElementById("OrderColumnName").value;
	var setParent = document.getElementById("SetParent").value;
	 
	url = url + "?sid=" + Math.random();
	
	if (orderStr != "") { 
		url = url + "&tableName="+tableName;
		url = url + "&idCol="+idCol;			
		url = url + "&parentCol="+parentCol;			
		url = url + "&orderCol="+orderCol;			
		url = url + "&orderStr="+orderStr;						
		url = url + "&setParent="+setParent;
	}
	
	xmlHttp.onreadystatechange = function () {
		if (xmlHttp.readyState == 4) {
			 // do nothing
		}
	}
	
	xmlHttp.open("GET", url, true);
	xmlHttp.send(null);
}




