﻿// Get the URL parameter
function gup(name) {
    name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
    var regexS = "[\\?&]" + name + "=([^&#]*)";
    var regex = new RegExp(regexS);
    var results = regex.exec(window.location.href);
    if (results == null) return "";
    else return results[1];
}

function clearFD() {
    document.getElementById('fdback').innerHTML = '';
}

function makeCoord(instr) {
    var coord = 0.0;
    if (instr.match(/^\s*\d{1,3}\s+\d{1,2}\s+[\d\.]+\s*$/)) {
        var res = instr.match(/(\d+)\s+(\d+)\s+([\d\.]+)/);
        coord = parseFloat(res[1]) + (parseFloat(res[2]) / 60.0) + (parseFloat(res[3]) / 3600.0);
    }
    if (instr.match(/^\s*\d{1,3}\s+[\d\.]+\s*$/)) {
        var res = instr.match(/(\d+)\s+([\d\.]+)/);
        coord = parseFloat(res[1]) + (parseFloat(res[2]) / 60.0);
    }
    if (instr.match(/^\s*[\d{1,3}\.\d*]+\s*$/)) {
        var res = instr.match(/([\d\.]+)/);
        coord = parseFloat(res[1]);
    }
    return coord;
}

function testCoord(instr) {
    if (instr.match(/^\s*\d{1,3}\s+\d{1,2}\s+[\d\.]+\s*$/)) {
        return true;
    }
    if (instr.match(/^\s*\d{1,3}\s+[\d\.]+\s*$/)) {
        return true;
    }
    if (instr.match(/^\s*[\d{1,3}\.\d*]+\s*$/)) {
        return true;
    }
    return false;
}

function gotoLL() {
    var lat = 0.0;
    var lon = 0.0;

    if (testCoord(document.getElementById('lattext').value.replace(/[-\x22\x2c\x60\x27]/g, ' '))) {
        lat = makeCoord(document.getElementById('lattext').value.replace(/[-\x22\x2c\x60\x27]/g, ' '));
        if ((lat < -90.0) || (lat > 90.0)) {
            document.getElementById('fdback').innerHTML = 'Latitude out of range -90 to 90 ' + document.getElementById('lattext').value;
            return false;
        }
        else {
            var mylist = document.getElementById('latdir');
            var latdir = mylist.options[mylist.selectedIndex].text;
            if (latdir == 'S') {
                lat = lat * -1.0;
            }
        }
    }
    else {
        document.getElementById('fdback').innerHTML = 'Invalid latitude ' + document.getElementById('lattext').value;
        return false;
    }

    if (testCoord(document.getElementById('lontext').value.replace(/[-\x22\x2c\x60\x27]/g, ' '))) {
        lon = makeCoord(document.getElementById('lontext').value.replace(/[-\x22\x2c\x60\x27]/g, ' '));
        if ((lon < -180.0) || (lon > 180.0)) {
            document.getElementById('fdback').innerHTML = 'Longitude out of range -180 to 180 ' + document.getElementById('lattext').value;
            return false;
        }
        else {
            var mylist = document.getElementById('londir');
            var londir = mylist.options[mylist.selectedIndex].text;
            if (londir == 'W') {
                lon = lon * -1.0;
            }
        }
    }
    else {
        document.getElementById('fdback').innerHTML = 'Invalid longitude ' + document.getElementById('lontext').value;
        return false;
    }
    processClick(new GLatLng(parseFloat(lat), parseFloat(lon)), true);
    return true;
}

// Display a user feedback string
function setFeedback(str) {
    if (str.length > 0) {
        document.getElementById('feedback').innerHTML = str;
    }
    else {
        document.getElementById('feedback').innerHTML = '&nbsp;';
    }
}

// isLocalSearch property is 1 if currently in a LocalSearch selection
//  or 0 for a polygon selection
function getLocalSearch() {
    return isLocalSearch;
}

function setLocalSearch(nval) {
    isLocalSearch = nval;
}

function getMyIdle() {
    return myidle;
}

function getSelPnt() {
    return selpnt;
}

function idleLS() {
    myidle = 1;
    LSearch.goIdle();
    myidle = 0;
    setLocalSearch(0);
}

// create the LocalSearch control
function createLS() {
    var LS = null;
    /* Metal Mode */
    // set up pins, use the metalset
    var pins = new Array();
    pins["kml"] = "metalblue";
    pins["local"] = "metalred";

    var labels = new Array();
    labels["kml"] = "metalblue";
    labels["local"] = "metalred";

    var options = {
        listingTypes: GlocalSearch.TYPE_BLENDED_RESULTS,
        Xpins: pins,
        Xlabels: labels,
        //                    onGenerateMarkerHtmlCallback: function(marker, html, result) {
        //                        showDBG(html.innerHTML);
        //                    },
        onIdleCallback: function() {
            var inls = getLocalSearch();
            if (getMyIdle() != 1) {
                //                alert('Make new marker ' + inls);
                if (getLocalSearch() == 1) {
                    processClick(getSelPnt(), true);
                }
            }
        },
        onMarkersSetCallback: function(markers) {
            if (markers.length > 0) {
                //                            alert("marker at " + markers[0].marker.getLatLng().lat() + ' ' + markers[0].marker.getLatLng().lng());
                processClick(markers[0].marker.getLatLng(), false);
            }
            else {
                //                            alert("center at " + map.getCenter().lat() + ' ' + map.getCenter().lng());
                processClick(map.getCenter(), true);
            }
            setLocalSearch(1);
        }
    }

    var topLeft = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(100, 5));
    LS = new google.maps.LocalSearch(options);
    map.addControl(LS, topLeft);
    return LS;
}

// Main executable starts here.......................

// some global variables
var i = 0;
var polys = [];
var reslist = [];
var visreslist = [];
var jsonData = [];
var gpolyData = [];
var selectedId = null;
var ptmarker = null;
var dbgon = 1; // 1 enables debug messages to go to page
var Icon = new GIcon();
Icon.image = 'data/red_MarkerA.png';
Icon.iconSize = new GSize(20, 34);
Icon.iconAnchor = new GPoint(10, 34);
Icon.infoWindowAnchor = new GPoint(2, 30);
var isLocalSearch = 0;
var selpnt = null;
var myidle = 0;
var map = null;
var LSearch = null;

// Display the map, with some controls
function callMe() {
    if (GBrowserIsCompatible()) {
        setFeedback('Loading...');
        map = new GMap(document.getElementById("map"));
        map.addControl(new GLargeMapControl());
        map.addControl(new GMapTypeControl());
        map.addControl(new GScaleControl());
        map.setCenter(new GLatLng(52.3, -110.00), 2);


        // look for URL parameters ll is center, z is zoom level, spn is display area span
        var c = gup('ll');
        var z = gup('z');
        var spn = gup('spn');
        //                alert( 'll ' + c + ' z ' + z + ' spn ' + spn );

        if (c.length > 0) {
            var y = Number(c.substr(0, c.indexOf(',')));
            var x = Number(c.substr(c.indexOf(',') + 1));
            map.setCenter(new GLatLng(y, x));

            if (spn.length > 0) {
                dy = Number(spn.substr(0, spn.indexOf(',')));
                dy = dy / 2;
                dx = Number(spn.substr(spn.indexOf(',') + 1));
                dx = dx / 2;
                var sw = new GLatLng(Number(y - dy), Number(x - dx));
                var ne = new GLatLng(Number(y + dy), Number(x + dx));
                var bnds = new GLatLngBounds(sw, ne);
                map.setZoom(map.getBoundsZoomLevel(bnds));
            }
            else if (z.length > 0) {
                var zl = Number(z);
                map.setZoom(zl);
            }
        }

        // create the LocalSearch control
        LSearch = createLS();
        map.enableScrollWheelZoom();


        // ================================================================
        // === Define the function thats going to process the JSON file ===
        process_it = function(doc) {
            // === Parse the JSON document === 
            jsonData = eval('(' + doc + ')');
            GDownloadUrl(gpolyfile, process_gpoly);
        }

        process_gpoly = function(doc) {
            // === Parse the gpoly JSON document === 
            gpolyData = eval('(' + doc + ')');

            // === Null the polylines ===
            for (var i = 0; i < gpolyData.gpoly.length; i++) {
                polys[i] = null;
                //                    polys[i] = GPolygon.fromEncoded(gpolyData.gpoly[i]);
                //                    map.addOverlay(polys[i]);
                //            showDBG(gpolyData.gpoly[i]);
            }
            // draw the polygongs for this view
            setPolyVis(map.getZoom());
            var c = gup('ll');
            if (c.length > 0) {
                var y = Number(c.substr(0, c.indexOf(',')));
                var x = Number(c.substr(c.indexOf(',') + 1));
                processClick(new GLatLng(y, x), true);
            }
        }

        // ================================================================
        // === Fetch the JSON data file ====
        //                var file = 'enc.txt';


        if (file.length > 0) {
            GDownloadUrl(file, process_it);
            GEvent.addListener(map, "zoomend", function(oz, nz) {
                setPolyVis(nz);
                showResList(document.getElementById('side_bar'));
                setFeedback('');
            });
            GEvent.addListener(map, "movestart", function() {
                setFeedback('Moving...');
            });
            GEvent.addListener(map, "move", function() {
                setFeedback('Moving...');
            });
            GEvent.addListener(map, "moveend", function() {
                setPolyVis(map.getZoom());
                showResList(document.getElementById('side_bar'));
                setFeedback('');
            });
            GEvent.addListener(map, "click", function(overl, ll, overlll) {
                if (overl == undefined) {
                    if (getLocalSearch() == 1) {
                        idleLS();
                    }
                    processClick(ll, true);
                }
                else {
                    if (overl instanceof GPolygon) {
                        if (getLocalSearch() == 1) {
                            idleLS();
                        }
                        processClick(overlll, true);
                    }
                }
            });
        }
        else {
            alert('Unknown area');
        }
    }
    else {
        alert("Sorry, the Google Maps API is not compatible with this browser");
    }
}
// ================================================================

// does the given set of points appear in the current view
function onScreen(points, mapbnds, dateline) {
    var minlng = 99999;
    var maxlng = -99999;
    var minlat = 99999;
    var maxlat = -99999;
    for (var i = 0; i < points.length; i++) {
        if (mapbnds.containsLatLng(points[i])) {
            return true;
        }
        if (dateline == '1') {
            if (points[i].lng() < 0) {
                maxlng = Math.max(maxlng, points[i].lng());
                minlng = Math.min(minlng, points[i].lng());
            }
            maxlat = Math.max(maxlat, points[i].lat());
            minlat = Math.min(minlat, points[i].lat());
        }
        else {
            maxlng = Math.max(maxlng, points[i].lng());
            minlng = Math.min(minlng, points[i].lng());
            maxlat = Math.max(maxlat, points[i].lat());
            minlat = Math.min(minlat, points[i].lat());
        }
    }
    var b = new GLatLngBounds(new GLatLng(minlat, minlng), new GLatLng(maxlat, maxlng));
    return mapbnds.intersects(b);
}

// display only the polygons for current view, remove polygons outside of view, create new as needed
function setPolyVis(mapzoom) {
    var showcbox = document.getElementById('showAllCheck');
    setFeedback('Redrawing...');
    var mbnds = map.getBounds();
    var showall = document.getElementById('showAllCheck').checked;
    var polyonscreen = [];
    for (var k = 0; k < polys.length; k++) {
        polyonscreen[k] = false;
    }
    for (var j = 0; j < jsonData.lines.length; j++) {
        if (onScreen(jsonData.lines[j].points, mbnds, jsonData.lines[j].dateline)) {
            polyonscreen[jsonData.lines[j].polyid] = true;
        }
    }

    for (var i = 0; i < polys.length; i++) {
        if (((mapzoom >= gpolyData.info[i].minzoom) && (mapzoom <= gpolyData.info[i].maxzoom)) || showall) {
            //                        if (jsonData.lines[i].dateline == '1') {
            //                            showDBG('test ' + jsonData.lines[i].label);
            //                        }
            if (polyonscreen[i]) {
                if (polys[i] == null) {
                    var poly = null;
                    poly = GPolygon.fromEncoded(gpolyData.gpoly[i]);
                    map.addOverlay(poly);
                    polys[i] = poly;
                    //                    createPolyClick(poly, i);
                }
            }
            else {
                if (polys[i] != null) {
                    map.removeOverlay(polys[i]);
                    polys[i] = null;
                }
            }
        }
        else {
            if (polys[i] != null) {
                map.removeOverlay(polys[i]);
                polys[i] = null;
            }
        }
    }
    if (selectedId != null) {
        if (polys[selectedId] != null) {
            showSelectedPoly(selectedId);
        }
    }
    setFeedback('');
}

// display a table data item
function addDataItem(tdiv, item, tstyle) {
    var it1 = document.createElement('td');
    it1.appendChild(item);
    it1.style.cssText = tstyle;
    tdiv.appendChild(it1);
}

// display selected charts in side bar area and select the first one
function showResList(resdiv) {

    for (var i = resdiv.childNodes.length - 1; i >= 0; i--) {
        resdiv.removeChild(resdiv.childNodes[i]);
    }

    visreslist = [];
    if (reslist.length > 0) {
        var tbl = document.createElement('tbody');
        var trow = document.createElement('tr');
        addDataItem(trow, document.createTextNode('ENC'), 'font-weight:bold;text-align:center;');
        tbl.appendChild(trow);
        for (i = 0; i < reslist.length; i++) {
            //                        showDBG('hidden id ' + reslist[i] + ' ' + polys[reslist[i]].isHidden());
            var newa = document.createElement('a');
            newa.id = 'an' + reslist[i];
            if (polys[reslist[i]] == null) {
                //dbgon = 1;
                //                            showDBG('no poly ' + jsonData.lines[reslist[i]].label);
                //onScreen(jsonData.lines[reslist[i]].points, map.getBounds(), jsonData.lines[reslist[i]].dateline);
                //dbgon = 0;
            }
            else {
                visreslist.push(reslist[i]);
                //                            showDBG('multi id: ' + newa.id);
                newa.href = '#';
                newa.onclick = function() {
                    var myId = this.id.substring(2, this.id.length);
                    displaySelect(myId);
                };
            }
            var t = document.createTextNode(gpolyData.info[reslist[i]].cnum);
            newa.appendChild(t);
            trow = document.createElement('tr');
            addDataItem(trow, newa, 'text-align:left;');
            tbl.appendChild(trow);
            //                            showDBG('row ' + trow);
        }
        //                        }


        var ttbl = document.createElement('table');
        ttbl.appendChild(tbl);
        resdiv.appendChild(ttbl);

        if (visreslist.length > 0) {
            displaySelect(visreslist[0]);
        }
        else {
            clearSelectedText();
        }
    }
    else {
        clearSelectedText();
        resdiv.appendChild(document.createTextNode('Click in a polyon on the map to see product information'));
    }
}

function processClick(llval, isPoly) {
    // clear last selection
    if (selectedId != null) {
        if (polys[selectedId] != null) {
            ns = { color: "#FF0000", weight: 2, opacity: 0.0, fill: false };
            polys[selectedId].setFillStyle(ns);
        }
    }
    map.panTo(llval);

    if (ptmarker != null) {
        map.removeOverlay(ptmarker);
        ptmarker = null;
        document.getElementById('pointinfo').innerHTML = '';
    }

    if (isPoly) {
        ptmarker = new GMarker(llval, { icon: Icon, title: 'Selected' });
        map.addOverlay(ptmarker);
    }
    showMapLocation(llval);

    // clear any previous results
    resdiv = document.getElementById('side_bar');
    reslist = [];
    visreslist = [];
    selectedId = null;
    reslinks = document.getElementById('chartlinksdiv');
    for (var k = reslinks.childNodes.length - 1; k >= 0; k--) {
        reslinks.removeChild(reslinks.childNodes[k]);
    }

    // find polys at this point
    for (i = 0; i < jsonData.lines.length; i++) {
        //            showDBG(i + ' ' + jsonData.lines[i].polyid);
        if (isInside(llval, jsonData.lines[i].points, jsonData.lines[i].dateline)) {
            //                showDBG('inside i ' + i + ' chart ' + jsonData.lines[i].cnum);
            reslist.push(jsonData.lines[i].polyid);
        }
    }
    showResList(resdiv);
}

function polyClick(llval) {
    if (getLocalSearch() == 1) {
        myidle = 1;
        LSearch.goIdle();
        myidle = 0;
        setLocalSearch(0);
    }
    processClick(llval, true);
}

// create a polygon click event handler
function createPolyClick(poly, myId) {
    GEvent.addListener(poly, "click", polyClick);
}

// create the hyperlinks to other pages for the selected chart
function showLinks(pid) {

    var tdiv = document.getElementById('chartlinksdiv');
    var temp = '';

    for (var k = tdiv.childNodes.length - 1; k >= 0; k--) {
        tdiv.removeChild(tdiv.childNodes[k]);
    }

    tdiv.appendChild(document.createElement('br'));
    temp = prodstr + ' {0}';
    tdiv.appendChild(document.createTextNode(temp.replace('{0}', gpolyData.info[pid].cnum)));
    tdiv.appendChild(document.createElement('br'));

    //http://www.charts.noaa.gov/OnLineViewer/{0}.shtml
    if (link1.length > 0) {
        var newa = document.createElement('a');
        temp = link1;
        //        temp = 'http://www.charts.noaa.gov/OnLineViewer/{0}.shtml';
        newa.href = temp.replace('{0}', gpolyData.info[pid].cnum);
        newa.target = '_blank';
        newa.appendChild(document.createTextNode(link1t));
        tdiv.appendChild(newa);
        tdiv.appendChild(document.createElement('br'));
    }

    //http://ocsdata.ncd.noaa.gov/nm/Listing.asp?Chart={0}
    if (link2.length > 0) {
        newa = document.createElement('a');
        temp = link2;
        newa.href = temp.replace('{0}', gpolyData.info[pid].cnum);
        newa.target = '_blank';
        newa.appendChild(document.createTextNode(link2t));
        tdiv.appendChild(newa);
        tdiv.appendChild(document.createElement('br'));
    }

    //http://www.charts.noaa.gov/RNCs/Agreement.shtml?{0}
    if (link3.length > 0) {
        newa = document.createElement('a');
        temp = link3;
        newa.href = temp.replace('{0}', gpolyData.info[pid].cnum);
        newa.target = '_blank';
        newa.appendChild(document.createTextNode(link3t));
        tdiv.appendChild(newa);
        tdiv.appendChild(document.createElement('br'));
    }
}

// clear old selected polygon and highlight the new one
function displaySelect(theid) {
    if (selectedId != null) {
        ns = { color: "#FF0000", weight: 2, opacity: 0.0, fill: false };
        if (polys[selectedId] != null) {
            polys[selectedId].setFillStyle(ns);
        }
        var anch = document.getElementById('an' + selectedId);
        anch.style.backgroundColor = "";
    }
    showSelectedPoly(theid);
    return true;
}

// highlight the given polygon
function showSelectedPoly(theid) {
    //                    showDBG('turn on highlight ' + 'an' + theid);
    selectedId = theid;
    if ((prodid != 'state') && (prodid != 'cgd')) {
        document.getElementById('an' + theid).style.backgroundColor = "yellow";
    }
    ns = { color: "#FFFF00", weight: 2, opacity: 0.5, fill: true };
    if (polys[selectedId] == null) {
        clearSelectedText();
    }
    else {
        document.getElementById('infodiv').innerHTML = gpolyData.info[theid].infotext;
        showLinks(theid);
        polys[selectedId].setFillStyle(ns);
        if (prodid == 'cgd') {
            if (selectedId == 3) {
                polys[4].setFillStyle(ns);
            }
            if (selectedId == 4) {
                polys[3].setFillStyle(ns);
            }
        }
    }
}

function clearSelectedText() {
    document.getElementById('infodiv').innerHTML = '';
    var tdiv = document.getElementById('chartlinksdiv');
    for (var k = tdiv.childNodes.length - 1; k >= 0; k--) {
        tdiv.removeChild(tdiv.childNodes[k]);
    }
}

// convert clicked location to DMS and display
function showMapLocation(llval) {
    with (Math) {
        var flat = abs(llval.lat());
        var lat = truncNumber(flat);
        var latstr = lat.toString();
        if (lat < 10) {
            latstr = '0' + latstr;
        }
        var latmin = truncNumber((flat - lat) * 60.0);
        var latminstr = latmin.toString();
        if (latmin < 10) {
            latminstr = '0' + latminstr;
        }
        var latsec = (flat - (lat + latmin / 60.0)) * 3600.0;
        var latsecstr = latsec.toFixed(2).toString();
        if (latsec < 10) {
            latsecstr = '0' + latsecstr;
        }
        latstr += '&nbsp;&nbsp;' + latminstr + "'&nbsp;&nbsp;" + latsecstr + "''";
        if (llval.lat() > 0) {
            latstr += ' N';
        }
        else {
            latstr += ' S';
        }
        var flon = abs(llval.lng());
        var lon = truncNumber(flon);
        var lonstr = lon.toString();
        if (lon < 100) {
            lonstr = '0' + lonstr;
        }
        if (lon < 10) {
            lonstr = '0' + lonstr;
        }
        var lonmin = truncNumber((flon - lon) * 60.0);
        var lonminstr = lonmin.toString();
        if (lonmin < 10) {
            lonminstr = '0' + lonminstr;
        }
        var lonsec = (flon - (lon + lonmin / 60.0)) * 3600.0;
        var lonsecstr = lonsec.toFixed(2).toString();
        if (lonsec < 10) {
            lonsecstr = '0' + lonsecstr;
        }
        lonstr += '&nbsp;&nbsp;' + lonminstr + "'&nbsp;&nbsp;" + lonsecstr + "''";
        if (llval.lng() > 0) {
            lonstr += ' E';
        }
        else {
            lonstr += ' W';
        }

        var ptdiv = document.getElementById('pointinfo');
        selpnt = llval;
        ptdiv.innerHTML = '<img src="data/red_MarkerA.png" /><a href="#" onClick="map.panTo(selpnt);">Selected Point:</a><br />&nbsp;&nbsp;' + latstr + '<br />' + lonstr;
    }
    return true;
}

// the 'Show all charts' check box was clicked
function showAllChange() {
    setPolyVis(map.getZoom());
    showResList(document.getElementById('side_bar'));
}

// do the right kind of integer truncation
function truncNumber(num) {
    if (num < 0) {
        return Math.ceil(num);
    }
    else {
        return Math.floor(num);
    }
}

// calc slope of line for given points
function slope(ax, ay, bx, by) {
    return ((by - ay) / (bx - ax));
}

// find the b value in y = mx + b equation
function bconst(m, ax, ay) {
    if (Math.abs(m) == Infinity) {
        return (ax);
    }
    else {
        return (ay - (m * ax));
    }
}

// is x between a1 and a2
function between(x, a1, a2) {
    return ((Math.abs(x - a1) < Math.abs(a2 - a1)) && (Math.abs(x - a2) < Math.abs(a2 - a1)));
}

// does the clickat location fall inside the points array
function isInside(clickat, points, dateline) {
    if (dateline == '1') {
        //                    showDBG('lat ' + clickat.lat() + ' lon ' + clickat.lng() + ' len ' + points.length);
    }
    var intcnt = 0;
    for (var i = 0; i < points.length - 1; i++) {
        var pt1lng = points[i].lng();
        var pt2lng = points[i + 1].lng();
        if (dateline == '1') {
            if (clickat.lng() > 0) {
                if (pt1lng < 0) {
                    pt1lng += 360;
                }
                if (pt2lng < 0) {
                    pt2lng += 360;
                }
            }
            else {
                if (pt1lng > 0) {
                    pt1lng -= 360;
                }
                if (pt2lng > 0) {
                    pt2lng -= 360;
                }
            }
            //                        showDBG('pt1lng ' + pt1lng + ' pt2lng ' + pt2lng);
        }
        if (between(clickat.lat(), points[i].lat(), points[i + 1].lat())) {
            var m = slope(pt1lng, points[i].lat(), pt2lng, points[i + 1].lat());
            if (Math.abs(m) == Infinity) {
                if (pt1lng >= clickat.lng()) {
                    intcnt++;
                }
            }
            else {
                var b = bconst(m, pt1lng, points[i].lat());
                var x = (clickat.lat() - b) / m;
                if (x >= clickat.lng()) {
                    intcnt++;
                }
            }
        }
    }

    if ((intcnt % 2) == 1) {
        //                                            showDBG('intcnt ' + intcnt + ' mod ' + (intcnt % 2) + ' so inside');
        return true;
    }
    else {
        //                                        showDBG('intcnt ' + intcnt + ' mod ' + (intcnt % 2) + ' so outside');
        return false;
    }
}

function showDBG(msg) {
    if (dbgon == 1) {
        var thediv = document.getElementById('dbg');
        thediv.innerHTML = thediv.innerHTML + msg + '<br />';
    }
}
// This Javascript is based on code provided by the
// Blackpool Community Church Javascript Team
// http://www.commchurch.freeserve.co.uk/   
// http://econym.googlepages.com/index.htm

