﻿/******************************************************    
Expected map XML format:
<map>
    <latitude></latitude>
    <longitude></longitude>
    <zoom></zoom>
    <markers>
        <marker>
            <latitude></latitude>
            <longitude></longitude>
            <info></info>
            <iconImage></iconImage>
            <shadow></shadow>
            <iconWidth></iconWidth>
            <iconHeight></iconHeight>
            <shadowWidth></shadowWidth>
            <shadowHeight></shadowHeight>
            <iconAnchorX></iconAnchorX>
            <iconAnchorY></iconAnchorY>
            <infoAnchorX></infoAnchorX>
            <infoAnchorY></infoAnchorY>
        </marker>
    </markers>
</map>
******************************************************    
 Loads the google map
******************************************************/
function loadMap()
{    
    try
    {
        if (GBrowserIsCompatible()) 
        {
            var mapXml = formRef[fieldname].value;
            
            //Get the values from the xml
            setInitLatLng(mapXml);
            
            map = new GMap2(document.getElementById(mapRef));
            map.setCenter(new GLatLng(mapLat, mapLng), mapZoom);
            
            //Add map nav
            map.addControl(new GSmallMapControl());
            
            //add map type
            map.addControl(new GMapTypeControl());
            
            //Add map overlay
            map.addControl(new GOverviewMapControl());
            
            //Init markers
            baseIcon = createBaseIcon();
            
            //add map onclick listener
            GEvent.addListener(map, "click", function(marker, point) 
            {
                if(!marker)
                {
                    addMarkerToMap(point);
                }
            });
            
            GEvent.addListener(map, "moveend", function() 
            {
                var mapLatLng = map.getCenter();
                mapLat = mapLatLng.lat();
                mapLng = mapLatLng.lng();
            });
            
            GEvent.addListener(map, "zoomend", function(oldLevel,  newLevel) 
            {
                mapZoom = newLevel;
            });
            
            mapLoaded = 1;
            //Add the initial markers
            setInitMarkers(mapXml);
        }
    }
    catch(e)
    {
        showMapErrorMsg();
    }
    
    if (!mapLoaded)
    {
        showMapErrorMsg();
    }
}
/******************************************************    
    Sets the initial center point of the map as defined in the map 
    XML.
    
    Parameters:
        mapXML - the XML defining the map
******************************************************/
function setInitLatLng(mapXml)
{        
    if(mapXml != "")
    {
        try
        {
            xDoc = parseXml(mapXml); 
            mapLat = parseFloat(xDoc.getElementsByTagName("latitude").item(0).firstChild.data);
            mapLng = parseFloat(xDoc.getElementsByTagName("longitude").item(0).firstChild.data);
            mapZoom = parseInt(xDoc.getElementsByTagName("zoom").item(0).firstChild.data);
        }
        catch(e)
        {
            //Nada - but must kill the error so that the map still loads
        }
    }
    if (mapLat == 0 || mapLng== 0 || isNaN(mapLat) || isNaN(mapLng) || isNaN(mapZoom))
    {
        mapLat = initLatitude;
        mapLng = initLongitude;
        mapZoom = initZoom;
    }    
}
/******************************************************    
    Adds the initial markers to the map as defined in the map 
    XML.
    
    Parameters:
        mapXML - the XML defining the map
******************************************************/
function setInitMarkers(mapXml)
{        
    if(mapXml != "")
    {
        try
        {
            var xDoc = parseXml(mapXml); 
            var mArray = xDoc.getElementsByTagName("marker");                
            
            var markerNode = null;    
            var ptLat = 0;
            var ptLng = 0;
            var ptInfo = "";
            var iconImage = "";
            
            var newMarker = null;
            var markerIcon = null;
            var tempVar = null;
            
            for (var i =0; i < mArray.length; i++)
            {
                markerNode = mArray[i];
                
                ptLat = getNodeData(markerNode, "latitude", 0);
                ptLng = getNodeData(markerNode, "longitude", 0);
                
                if(!isNaN(ptLat) && !isNaN(ptLat))
                {
                    markerIcon = selectedIcon;
                                
                    ptInfo = getNodeXml(markerNode, "info", "");
                    
                    //Remove <![CDATA[]]> - due to XSL transform
                    ptInfo = ptInfo.replace(/^ *<\!\[CDATA\[/i, "");
                    ptInfo = ptInfo.replace(/\]\]> *$/i, "");
                    
                    iconImage = getNodeData(markerNode, "iconImage", "");
                    
                    if(iconImage.length != 0 && iconImage.indexOf("http://") == -1)
                    {
                        try
                        {
                            markerIcon.image = iconImage;
                            markerIcon.shadow = getNodeData(markerNode, "shadow", "");
                            markerIcon.iconSize = new GSize(
                                parseFloat(getNodeData(markerNode, "iconWidth", 0)), 
                                parseFloat(getNodeData(markerNode, "iconHeight", 0)));
                                
                            markerIcon.shadowSize = new GSize(
                                parseFloat(getNodeData(markerNode, "shadowWidth", 0)), 
                                parseFloat(getNodeData(markerNode, "shadowHeight", 0)));
                                
                            markerIcon.iconAnchor = new GPoint(
                                parseFloat(getNodeData(markerNode, "iconAnchorX", 0)),
                                parseFloat(getNodeData(markerNode, "iconAnchorY", 0)));
                            
                            
                            markerIcon.infoWindowAnchor = new GPoint(
                                parseFloat(getNodeData(markerNode, "infoAnchorX", 0)),
                                parseFloat(getNodeData(markerNode, "infoAnchorY", 0)));
                                
                            markerIcon.infoShadowAnchor = new GPoint(
                                parseFloat(getNodeData(markerNode, "shadowAnchorX", 0)),
                                parseFloat(getNodeData(markerNode, "shadowAnchorY", 0)));
                        }
                        catch(e)
                        {
                            markerIcon = selectedIcon;
                            alert(e.message);
                        }
                    }
                    
                    newMarker = createMarker(new GPoint(ptLng, ptLat), markerIcon, ptInfo, markerArray.length);
                    
                    map.addOverlay(newMarker);
                    markerArray.push(newMarker);
                }
            }
        }
        catch(e)
        {
            //Nada - but must kill the error so that the map still loads
        }
        
        var markerCntDisplay = document.getElementById("mapMarkerCounter");
        if(markerCntDisplay)
        {
            markerCntDisplay.innerHTML = markerArray.length;
        }
    }
}
/******************************************************    
    Unloads the map
******************************************************/
function unloadMap()
{
    if(mapLoaded)
    {
        try
        {
            GUnload();
            markerArray = new Array();
        }
        catch(e)
        {
            showMapErrorMsg();
        }
    }
}
/******************************************************    
    Displays an error message if the map fails to load.
******************************************************/
function showMapErrorMsg()
{
    document.getElementById("mapMain").style.display = "none";
    document.getElementById("mapErrorMsg").style.display = "block";
}    
/******************************************************    
    Adds a point to the map as a marker.
    
    Parameters:
        point - A GPoint object to add to the map.
******************************************************/
function addMarkerToMap(point)
{
    if (markerArray.length >= maxNumMarkers)
    {
        if (maxNumMarkers == 1)
        {
            alert("You may only place 1 marker on this map.");
        }
        else
        {
            alert("You may only place a maximum of " + maxNumMarkers + " markers on this map.");
        }                        
    }
    else
    {
          var marker = createMarker(point, selectedIcon, "", markerArray.length);        
        map.addOverlay(marker);
        markerArray.push(marker);
        
        var markerCntDisplay = document.getElementById("mapMarkerCounter");
        if(markerCntDisplay)
        {
            markerCntDisplay.innerHTML = markerArray.length;
        }
    }
}
/******************************************************    
    Returns true if the coordinates are within the bounds of the
    map, otherwise false is returned.
    
    Parameters:
        lat - An integer representing the latitude value
        lng - An integer representing the longitude value
******************************************************/
function isInBounds(lat, lng)
{
    var bounds = map.getBounds();
    var southWest = bounds.getSouthWest();
    var northEast = bounds.getNorthEast();
    var lngSpan = northEast.lng() - southWest.lng();
    var latSpan = northEast.lat() - southWest.lat();
    
    if(lat > northEast.lat() || lat < southWest.lat())
    {
        return false;
    }
    
    if(lng > northEast.lng() || lng < southWest.lat())
    {
        return false;
    }
    
    return true;
}
/******************************************************    
    Sets the google map form field value to the map XML then 
    closes the pop up window.
******************************************************/
function saveMap()
{
    formRef[fieldname].value = getMapXml();
    window.close();
}
/******************************************************    
    Returns the map XML
******************************************************/
function getMapXml()
{
    var mapCenter = map.getCenter();
    var mapZoom = map.getZoom();
    
    var mapXml;
    var ptLatLng;
    var ptLat;
    var ptLng;
    var ptIcon;
            
    mapXml = "<map>";
    mapXml += "<latitude>" + mapCenter.lat() + "</latitude>";
    mapXml += "<longitude>" + mapCenter.lng() + "</longitude>";
    mapXml += "<zoom>" + mapZoom + "</zoom>";
    mapXml += "<markers>";
    
    for (var i in markerArray)
    {
        if (markerArray[i])
        {
            ptLatLng = markerArray[i].getPoint();
            ptIcon = markerArray[i].getIcon();
            
            mapXml += "<marker>";
            
            mapXml += "<latitude>" + ptLatLng.lat() + "</latitude>";
            mapXml += "<longitude>" + ptLatLng.lng() + "</longitude>";
                            
            mapXml += "<info><![CDATA[" + markerArray[i].customInfo + "]]></info>";
            
            mapXml += "<iconImage>" + ptIcon.image + "</iconImage>";
            mapXml += "<shadow>" + ptIcon.shadow + "</shadow>";
            
            mapXml += "<iconWidth>" + ptIcon.iconSize.width + "</iconWidth>";
            mapXml += "<iconHeight>" + ptIcon.iconSize.height + "</iconHeight>";
            
            mapXml += "<shadowWidth>" + ptIcon.shadowSize.width + "</shadowWidth>";
            mapXml += "<shadowHeight>" + ptIcon.shadowSize.height + "</shadowHeight>";
            
            mapXml += "<iconAnchorX>" + ptIcon.iconAnchor.x + "</iconAnchorX>";
            mapXml += "<iconAnchorY>" + ptIcon.iconAnchor.y + "</iconAnchorY>";
            
            mapXml += "<infoAnchorX>" + ptIcon.infoWindowAnchor.x + "</infoAnchorX>";
            mapXml += "<infoAnchorY>" + ptIcon.infoWindowAnchor.y + "</infoAnchorY>";
                
            mapXml += "</marker>";
        }
        
    }
    mapXml += "</markers>";
    mapXml += "</map>";
    
    return mapXml;
}
        
/******************************************************    
    Returns a GMarker object for the specified point, mIcon, info
    
    Parameters:
        point - A GPoint object representing the marker coordinates
        mIcon - The GIcon object to use
        info - The XHTML to display in the marker's info window
******************************************************/
function createMarker(point, mIcon, info, idx)
{
    var marker = new GMarker(point, {draggable: true,icon:mIcon});
    
    marker.customIndex = idx;
    marker.customInfo = info;
    
    GEvent.addListener(marker, "dragstart", function() {  map.closeInfoWindow();  });
    GEvent.addListener(marker, "click", function(){
        map.closeInfoWindow();
        map.removeOverlay(marker);
        
        //Remove from the array
        markerArray.splice(this.customIndex, 1);
    });
    
    GEvent.addListener(marker, "mouseover", function() {  
        if(!isEditing)
        {
            var markerXHMTL = getToolTip(this);
            this.openInfoWindowHtml(markerXHMTL);
        }
    });
    
    GEvent.addListener(marker, "infowindowbeforeclose", function() { 
        closeEditor(this.customIndex);
    });
    
    return marker;
}
/******************************************************    
    Called when a user clicks on the area inside a marker's info 
    window. This opens up the edit mode.
    
    Parameters:
        index - The index of the marker in the marker array
******************************************************/
function editInfo(index)
{
    isEditing = true;
    var info = markerArray[index].customInfo;
    var html = '<div id="editor_'+index+'" style="width:200px;height:100px;">'+info+'</div>';
    
    currentEditingIndex = index;
    markerArray[index].openInfoWindowHtml(html);
    isEditing = true;
    setTimeout("loadEditor(1)", 1);
}
/******************************************************    
    Loads the Wysiwyg
******************************************************/
function loadEditor(numTries)
{
    if(numTries < 5)
    {
        if(document.getElementById("editor_"+currentEditingIndex))
        {
            tinyMCE.idCounter = 0;
            tinyMCE.execCommand('mceAddControl', false, "editor_"+currentEditingIndex);
            tinyMCE.execCommand('mceFocus', false, "editor_"+currentEditingIndex);
        }
        else
        {
            setTimeout("loadEditor("+(numTries + 1)+")", 1);
        }
    }
}
/******************************************************    
    Called when a user clicks on the save icon of the wysiwyg 
    while in edit mode. This saves the changes and returns to 
    view mode.
******************************************************/
function saveInfoEdit()
{
    var index = currentEditingIndex;
    markerArray[index].customInfo = tinyMCE.getContent();
    
    var html = getToolTip(markerArray[index]);
    closeEditor(index);
    markerArray[index].openInfoWindowHtml(html);
}
/******************************************************    
    Unloads the wysiwyg
******************************************************/
function closeEditor(index)
{
    if(tinyMCE.idCounter > 0)
    {
        tinyMCE.execCommand('mceFocus', false, "editor_"+index);
        tinyMCE.execCommand('mceRemoveControl', false, "editor_"+index);
    }
    
    isEditing = false;
}
/******************************************************    
    Creates the extra XHTML for the tool tip editing
******************************************************/
function getToolTip(marker)
{
    var markerXHMTL = "";
    
    if(marker.customInfo.length != 0)
    {
        markerXHMTL = '<div onclick="editInfo('+marker.customIndex+')" style="cursor:pointer;">'+marker.customInfo+'</div>';
    }
    else
    {
        markerXHMTL = '<div onclick="editInfo('+marker.customIndex+')" style="cursor:pointer;width:200px;height:100px;"> </div>';
    }
    
    if(hasIconOptions == 1)
    {
        markerXHMTL = '<div>'+markerXHMTL+'<br/><div onclick="openCustomIconChooser(this, '+marker.customIndex+')"><a href="##">Edit Icon</a></div></div>';
    }
    
    return markerXHMTL;
}
/******************************************************    
    Returns a generic base icon as a GIcon object.
******************************************************/
function createBaseIcon()
{
    var bIcon = new GIcon();
    bIcon.shadow = iconWebPath+"shadowDefault.png";
    bIcon.iconSize = new GSize(20, 34);
    bIcon.shadowSize = new GSize(37, 34);
    bIcon.iconAnchor = new GPoint(9, 34);
    bIcon.infoWindowAnchor = new GPoint(9, 2);
    bIcon.infoShadowAnchor = new GPoint(18, 25);
    
    return bIcon;
}
/******************************************************    
    Returns the text inside a node
    
    Parameters:
        parent - The parent Node
        nodeName - The name of the value node
        defaultValue - If the valueNode does not exist then this 
        value is used
******************************************************/
function getNodeData(parent, nodeName, defaultValue)
{
    var result = defaultValue;
    var tempVar = parent.getElementsByTagName(nodeName);
    
    if(tempVar.length != 0 && tempVar[0].firstChild)
    {
        result = tempVar[0].firstChild.data;
    }
    
    return result;
}
/******************************************************    
    Returns the xml inside a node
    
    Parameters:
        parent - The parent Node
        nodeName - The name of the value node
        defaultValue - If the valueNode does not exist then this 
        value is used
******************************************************/
function getNodeXml(parent, nodeName, defaultValue)
{
    var result = defaultValue;
    var tempVar = parent.getElementsByTagName(nodeName);
    
    if(tempVar.length != 0)
    {
        result = getInnerXML(tempVar[0]);
    }
    return result;
}
/******************************************************    
    Sets the selected icon
    
    Parameters:
        idx - The index of the icon in the iconArray
******************************************************/
function chooseCustomIcon(idx)
{
    selectedIcon = iconArray[idx];
    
    var currentMarker = markerArray[currentEditingIndex];
    
    map.removeOverlay(currentMarker);
    currentMarker = createMarker(currentMarker.getPoint(), 
                                            selectedIcon, 
                                            currentMarker.customInfo, 
                                            currentMarker.customIndex);
    map.addOverlay(currentMarker);
    currentMarker.openInfoWindowHtml(getToolTip(currentMarker));
    
    markerArray[currentEditingIndex] = currentMarker;
    closeCustomIconChooser();
}
/******************************************************    
    Closes the icon chooser
******************************************************/
function closeCustomIconChooser()
{
    
    var chooser = document.getElementById("customIconBox");
    
    if(chooser)
    {
        chooser.style.display = "none";
    }
}
/******************************************************    
    Opens the icon chooser
******************************************************/
function openCustomIconChooser(parentElement, markerIdx)
{
    var chooser = document.getElementById("customIconBox");
    
    if(chooser)
    {
        currentEditingIndex = markerIdx;
        chooser.style.display = "inline";
    }
}
/******************************************************    
    Adds a marker by coordinates
******************************************************/
function addMarkerByCoords()
{
    closeCustomIconChooser();
    var lat = document.mapForm.markerLat.value;
    var lon = document.mapForm.markerLon.value;
    
    if(isNaN(lat) || isNaN(lon))
    {
        alert("Please specify valid latitude or longitude values.");
    }
    else
    {
        var point = new GLatLng(lat, lon);
        addMarkerToMap(point);
        
        if(!isInBounds(lat, lon))
        {
            map.setCenter(new GLatLng(lat, lon), map.getBoundsZoomLevel(map.getBounds()));
        }
    
    }
}
/******************************************************    
    Clears the map of all markers.
******************************************************/
function clearMap()
{
    map.clearOverlays();
    markerArray = new Array();
    var markerCntDisplay = document.getElementById("mapMarkerCounter");
    if(markerCntDisplay)
    {
        markerCntDisplay.innerHTML = "0";
    }
}
/******************************************************    
    Creates a standard gIcon
    
    Parameters:
        color - the icon colour {r,g,b}
******************************************************/
function createStandardIcon(color, idx)
{
    var standardIcon = createBaseIcon();
    if(idx == 0)
    {
        idx = "";
    }
    
    standardIcon.image = iconWebPath + "mapIcon" + color + idx + ".png";
    return standardIcon;
}
/******************************************************    
    Load icon collection
******************************************************/
function loadIcons()
{
    gotoIconPage(0);
}
/******************************************************    
    Displays the relative icon page of the icon chooser.
    
    Parameters:
        startIdx - The index of the first icon on the page. 
******************************************************/
function gotoIconPage(startIdx)
{
    var tempXHtml = "";
    var iconChooserBox = document.getElementById("customIconBoxBody");
    var iconChooserPaging = document.getElementById("customIconBoxFooter");
    var numPages = Math.ceil(iconArray.length/iconDisplayNumPerPage);
    var endIdx = 0;
    
    iconDisplayIndex = startIdx;
    if(iconChooserBox)
    {
        //Display icons (chooser body)
        endIdx = startIdx + iconDisplayNumPerPage;
        
        if(endIdx > iconArray.length)
        {
            endIdx = iconArray.length;
        }
        
        for(var idx = startIdx; idx< endIdx; idx++)
        {
            tempXHtml += '<a href="##" class="customIcon"><img src="'+iconArray[idx].image+'" alt="click to select" border="0" onclick="chooseCustomIcon('+idx+')"/></a>';
        }
        
        iconChooserBox.innerHTML = tempXHtml;
        
        //Display Paging (chooser Footer)
        
        if(startIdx != 0)
        {
            tempXHtml = '<a href="javascript:gotoIconPage('+ (startIdx - iconDisplayNumPerPage) +')">Prev</a><span>|</span>';
        }
        else
        {
            tempXHtml = "<span>Prev</span><span>|</span>";
        }
        
        for(var idx = 0; idx < iconArray.length; idx += iconDisplayNumPerPage)
        {
            if(idx == startIdx)
            {
                tempXHtml += '<span class="selectedIconPage">'+(idx/iconDisplayNumPerPage + 1)+'</span><span>|</span>';
            }
            else
            {
                tempXHtml += '<a href="javascript:gotoIconPage('+idx+')">'+(idx/iconDisplayNumPerPage + 1)+'</a><span>|</span>';
            }
        }
        
        if(endIdx < iconArray.length)
        {
            tempXHtml  += '<a href="javascript:gotoIconPage('+ (startIdx + iconDisplayNumPerPage) +')">Next</a>';
        }
        else
        {
            tempXHtml += "<span>Next</span><span>|</span>";
        }
        
        iconChooserPaging.innerHTML = tempXHtml;
    }
}