    hljs.initHighlightingOnLoad();
    function _jsSQL() {
        function _ajaxSQL(_url, _data, _error, _success) {
		    $.ajax({
		        type: "POST",
		        url: "../PHP/" + _url + ".php",
		        data: _data,
		        error: function (msg) {
		            _error(msg);
		        },
		        success: function (msg) {
		            _success(msg);
		        }
		    });
        };
        function _SQLtable(_url, _data, _TableName, _fnCallback) {
            _ajaxSQL(_url, _data, 
                function () {
                    _SQLtableError(_TableName);
                },
			    function(msg) {
			        _SQLtableSuccess(msg, _TableName, _fnCallback);
		        });
        }
        function _SQLtableSuccess(msg, _TableName, _fnCallback) {
	        var strJSON = eval(msg);
	        _TableName = _TableName.split(" ")[0];
	        var JSONtable = "<table><caption>" + _TableName + "</caption>";
	        JSONtable += "<thead><tr>";
	        for (var field in strJSON[0]) {
	            JSONtable += "<th>" + field + "</th>";
	        }
	        JSONtable += "</tr></thead>";
	        for (var i = 0, l = strJSON.length; i < l; i++) {
	            JSONtable += "<tr>";
	            var thisRecord = strJSON[i];
	            for (var field in thisRecord) {
		            JSONtable += "<td>" + thisRecord[field] + "</td>";
	            }
	            JSONtable += "</tr>";
	        }
	        JSONtable += "</table>";
	        $("#" + _TableName).html(JSONtable);
            if (_fnCallback) {
                _fnCallback();
            }
        }
        function _SQLtableError(_TableName) {
            $("#" + _TableName).text("Sorry - can't fetch " + _TableName + "  from the database")
        }
        function _getTable(_TableName, _fnCallback) {
            _SQLtable("MYSQL2JSON", "SQLparm=* FROM " + _TableName, _TableName, _fnCallback);
        }
        function _describeTable(_TableName, _fnCallback) {
            _SQLtable("MYSQLDESC", "SQLparm=" + _TableName, _TableName, _fnCallback);
        }
        function _cleanRun() {
            _ajaxSQL("MYSQLexec", "SQLparm=CleanSimulatedTestRun", 
                function () {
                    alert("Can't clean Test Runs");
                },
                function() {		            _getTable("TestBed");
		            _getTable("TestConditions");
		            _getTable("TestRun ORDER BY RunID", 
		                function () {
			                $("#TestRun caption").append("<form><input id='btnSTR' type='button' value='Simulate Test Run' /></form>");
		                });
		            _getTable("TestResults ORDER BY TestResultsID", 
		                function () {			                $("html,body").animate({ scrollTop: $("#btnSQL").offset().top }, 500);
			                $("#lblSQL").fadeIn("slow");
			                $("#frmSQL").removeClass("loading");
    		            });
		        }                
            );
        }
        function _generateRun(rtRunStarted,rtTestPC,rtTestBuild,rtTestCode,rtOutputMatch) {
	        _ajaxSQL("MYSQLexec", "SQLparm=SimulatedTestRun('" + rtRunStarted + "','" + rtTestPC + "','" + rtTestBuild + "'," + rtTestCode + "," + rtOutputMatch + ")",
	            function () {
	                alert("Can't create new test run");
	            },
	            function () {
		            _getTable("TestRun ORDER BY RunID", 
		                function () {
			                $("#TestRun caption").append("<form><input id='btnSTR' type='button' value='Simulate Test Run' /></form>");
		                });
		            _getTable("TestResults ORDER BY TestResultsID", 
		                function (){
			                $("#TestRun tr:last td:eq(0)").addClass("highlight");
			                $("#TestResults tr:last td:eq(0)").addClass("highlight");
			                $("html,body").animate({ scrollTop: $("#btnSQL").offset().top }, 500);
		                });
	            }
            );
        }
        return {
            getTable: function (_TableName, _fnCallback) {
                _getTable(_TableName, _fnCallback);
                return this;
            },
            describeTable: function (_TableName, _fnCallback) {
                _describeTable(_TableName, _fnCallback);
                return this;
            },
            cleanRun: function () {
                _cleanRun();
                return this;
            },
            generateRun: function (rtRunStarted,rtTestPC,rtTestBuild,rtTestCode,rtOutputMatch) {
                _generateRun(rtRunStarted,rtTestPC,rtTestBuild,rtTestCode,rtOutputMatch);
                return this;
            }
        }
    };
    $(function() {
        var jsSQL = _jsSQL();
	    $("#btnSQL").click(function() {
		    jsSQL.cleanRun();
		    return false;        });
	    $("#btnDESC").click(function() {
	        $("#frmSQL").addClass("loading");
	        jsSQL.describeTable("TestBed")
	            .describeTable("TestConditions")
	            .describeTable("TestRun")
	            .describeTable("TestResults");
	        $("#frmSQL").removeClass("loading");
	        return false;
	    });
	    $("#btnSTR").live("click",function(){
	        jsSQL.generateRun("2009-10-19 6:02:00","TestVista","1.1.0.1",100000,0);    
	        return false;
	    });
   
	//tables are chained as:
	//TB[0]-[2]TN[0]-[2]TR[1]-[0]TC
	function highlightMatchingCells(thisTR, thisCell){
	    var thisIndex = thisTR.childNodes[thisCell].innerHTML;
	    $("td:contains('" + thisIndex + "')").each(function(){
		if ($(this).context.innerHTML == thisIndex){
		    $(this).addClass("highlight");
		}
	    })
	};
	$("table").live("click", function(e){
	    $(".highlight").removeClass("highlight");
	    var thisTR = e.target.parentNode;
	    if (thisTR.tagName === "TR"){
		var thisTable = this.caption.innerHTML;
		switch (thisTable){
		    case "TestBed":
			highlightMatchingCells(thisTR, 0);
			$("#TestRun td.highlight").each(function(){
			    var thisTR = this.parentNode;
			    highlightMatchingCells(thisTR, 0);
			    });
			$("#TestResults td.highlight").each(function(){
			    var thisTR = this.parentNode;
			    highlightMatchingCells(thisTR, 1);
			    });
			break;
		    case "TestResults":
			highlightMatchingCells(thisTR, 1);
			highlightMatchingCells(thisTR, 2);
			$("#TestRun td.highlight").each(function(){
			    var thisTR = this.parentNode;
			    highlightMatchingCells(thisTR, 2);
			    });
			break;		    
		    case "TestConditions":
			highlightMatchingCells(thisTR, 0);
			$("#TestResults td.highlight").each(function(){
			    var thisTR = this.parentNode;
			    highlightMatchingCells(thisTR, 2);
			    });
			$("#TestRun td.highlight").each(function(){
			    var thisTR = this.parentNode;
			    highlightMatchingCells(thisTR, 2);
			    });
			break;
		    default: //		    case "TestRun":
			highlightMatchingCells(thisTR, 2);
			highlightMatchingCells(thisTR, 0);
			$("#TestResults td.highlight").each(function(){
			    var thisTR = this.parentNode;
			    highlightMatchingCells(thisTR, 1);
			    });
			break;
		}
		//TestResults and TestRun need to have matched columns [2][1] and [2][0]
		function removeUnmatchedColumns(rUCtable, rUC1, rUC2){
		    $("#" + rUCtable + " tr").each(function(r){
			var rUCtd1 = $("#" + rUCtable + " tr:eq(" + r + ") td:eq(" + rUC1 + ")");
			var rUCtd2 = $("#" + rUCtable + " tr:eq(" + r + ") td:eq(" + rUC2 + ")");
			if (!(rUCtd1.hasClass("highlight")&&rUCtd2.hasClass("highlight"))){
			    rUCtd1.removeClass("highlight");
			    rUCtd2.removeClass("highlight");
			}
		    });
		}
		removeUnmatchedColumns("TestResults", 1, 2);
		removeUnmatchedColumns("TestRun", 0, 2);
	    }
	});

    });
