// ABQIAAAAEgcYcfNygNfRXCzJoNhAhhSbcmAoyLEti-m2acezMtWYkLlTSRSXDfVMTvV5ExcCounz7sPpwgSL2g
// http://yellowarrow.net/capitolofpunk-bak/map/setup2.xml 
var isDebug = false;
onerror = handleErrors
var msg = null
var d = new Date();
var activeBubble=-1;//~~add MM
var activeFP;
var _ENTER_ASAP=false;
function handleErrors(errorMessage, url, line) {
    msg = "There was an error on this page.\n\n";
    msg += "An internal programming error may keep\n";
    msg += "this page from displaying properly.\n";
    msg += "Click OK to continue.\n\n";
    msg += "Error message: " + errorMessage + "\n";
    msg += "URL: " + url + "\n";
    msg += "Line #: " + line;
   //alert(msg);
    return true;
} 

function debug(msg) {
 
    if ( !isDebug) return;
    var d = document.getElementById("debug") ?
        document.getElementById("debug") : document.body;
    d.appendChild(document.createTextNode("[" + new Date() + "] "));
    d.appendChild(document.createTextNode(msg));
    d.appendChild(document.createElement("br"));
}

var map;
function loadMap(setupFile) {
A('loadmap');
    if ( !setupFile ) {
        alert("Unable to load the map without knowing setup");
    }
    else if ( typeof setupFile == "object" ) {
        debug("Attempting to load setup from object");
        map = new MapLoader();
        map.parseSetup(setupFile);
    } else {
        debug("Attempting to load setup from remoteURL: " + setupFile);
        map = new MapLoader();
        map.loadSetup(setupFile);
    }
}

function navigatePrev() {
    if ( map.openedWindow )
        map.navigateMarkers(map.openedWindow - 1);
}

function navigateNext() {

A('function navigateNext() : activebbl='+activeBubble +' of '+map.orderedMarkers.length);
    if ( activeBubble!=-1 ){
        var nx=activeBubble+1;
        map.stopAnyFlash();        
        if(nx==map.orderedMarkers.length){nx=1;}
        var marker = map.orderedMarkers[nx];
        A('goto: '+nx);
        GEvent.trigger(marker.marker, "click", marker.marker);
    }    
}

function closeInfoWindow() {
    map.closeInfoWindow();
}

function MapLoader() {
    this.initialize();
};

var TIMEOUT = "Sorry, there was a problem loading the data requested.  Please try your request again later.";
var DATA_ERROR = "Sorry, there was an unexpected problem loading the data.  Please try your request again later.";

MapLoader.prototype.initialize = function() {
    try {
        if ( typeof GMap2 != "undefined" && GBrowserIsCompatible() ) {
            this.gmapReady   = true;
            /* The icon array */
            this.loadedIcons = new Array();
            this.orderedMarkers = new Array();
        } else {
            debug("Can't locate Google Maps functions, or browser is not compatible.");
            throw "GMap2 not loaded";
        }
         this._buildPopupContent_id=1;
    } catch(e) {
        alert("Sorry, Google Maps requires a leader webbrowser to properly work.  Your webbrowser does not seem to be compatible.\n" + e);
    }
}

MapLoader.prototype.loadSetup  = function(setupFile) {
    if ( this.gmapReady ) {
        var _this = this;
        debug("Requesting remote file: " + setupFile);
A("1.Requesting remote file: " + setupFile);
//~~ MM rewritten for Safar, the google api fails on safari, the whole load xml -> convert to string -> parse again to xml is bulls**t anyway
	 loadXMLDoc(setupFile,function(XML,TEXT){_this.setupToObj(XML);});
/*
        G~DownloadUrl(setupFile,
            function(data, responseCode) {
                try { _this.setupToObj(data) }
                catch(e) { debug(e); A(e); alert(e+">>Sorry, there was an error loading this page.  Please try your request again later.  If it continues, or if you believe you received this message in error, please contact the site administrator.");
                }
            }
        );*/
    }
    
}

/*
 Go from XML to a configuration structure
*/
MapLoader.prototype.setupToObj = function(setupXML) {
    debug("Loading remote data...");
//alert("Loading remote data... :"+typeof(setupXML));
//    var xmlData = GXml.parse(setupRes); //~~MM removed the G~Download .... GXml paradigm because it crashes Safari
//A("parsed!");
  var xmlData=setupXML;
//~~DAMN XML why cant you use a nice iframe    
	var mapInfo=xmlData.documentElement;
    var attachPoint = mapInfo.getAttribute("attachPoint");
A("got attachpoint !");
    
    if ( !attachPoint || !document.getElementById(attachPoint) ) {
        throw("Invalid configuration, no attach point specifed in document element.");
    }
    var setup = new Object();

    debug("Will attach map to: " + attachPoint);
A("Will attach map to: " + attachPoint);
    setup.attachPoint = attachPoint;
    if ( mapInfo.getAttribute("width") )
        setup.width  = mapInfo.getAttribute("width");
    if ( mapInfo.getAttribute("height") )
        setup.height = mapInfo.getAttribute("height");
    if ( mapInfo.getAttribute("defaultLatitude") &&
         mapInfo.getAttribute("defaultLongitude") )
    {
        setup.defaultCoords = new GLatLng(
            mapInfo.getAttribute("defaultLatitude"),
            mapInfo.getAttribute("defaultLongitude")
        );
    }
    setup.defaultZoom = mapInfo.getAttribute("defaultZoom");

    /* Keys to load:
     *  dataSource   - remote data source.
     *  markers      - list of markers to use in the map.
     *  splashScreen - a splash screen to use, can be valid XHTML in the
     *                 container or a pointer to a DIV on the page.
     *  loadingScreen - a loading screen to use, can be valid XHTML in the
     *                 container or a pointer to a DIV on the page.
    */
    var dataSrc    = mapInfo.getElementsByTagName("dataSource");
    debug("Data Sources: " + dataSrc.length);
A("Data Sources: " + dataSrc.length);
    setup.dataSources = [];
    if ( dataSrc.length > 0 ) {
        for ( var i = 0; i < dataSrc.length; i++ ) {
            if ( dataSrc[i].getAttribute("source") ) {
                debug("Adding datasource: "+dataSrc[i].getAttribute("source"));
                setup.dataSources.push(dataSrc[i].getAttribute("source"));
            } else {
                debug("Can't add datasource, invalid syntax.");
            }
        }
    }
    var tmplSrc = xmlData.documentElement.getElementsByTagName("template");
    debug("Template Sources: " + tmplSrc.length);
A("Template Sources: " + tmplSrc.length);
    setup.templateSources = [];
    for ( var i = 0; i < tmplSrc.length; i++ ) {
        if ( tmplSrc[i].getAttribute("source") ) {
             var template = new Object();
             template.source = tmplSrc[i].getAttribute("source");
             template.label =
                tmplSrc[i].getAttribute("label") || template.source;
             setup.templateSources.push(template);
        }
    }
    /*
     * Load the marker types
    */
    var markerList = xmlData.documentElement.getElementsByTagName("marker");
    if ( markerList.length > 0 ) {
        setup.customMarkers = [];
        debug("Loading " + markerList.length + " custom markers...");
A("Loading " + markerList.length + " custom markers...");
        for ( var i = 0; i < markerList.length; i++ ) {
            var label  = markerList[i].getAttribute("label");
            debug("   ---> " + label);
            var icon   = markerList[i].getElementsByTagName("icon");
            var shadow = markerList[i].getElementsByTagName("shadow");
            var anchor = markerList[i].getElementsByTagName("anchor");
            if ( icon.length > 0 && shadow.length > 0 && anchor.length > 0 &&
                 label )
            {
                var marker = new Object();
                marker.label = label;
                if ( icon[0].getAttribute("src") && icon[0].getAttribute("size") ) {
                    var size = icon[0].getAttribute("size").split(',');
                    marker.iconSize = new GSize(
                        parseInt(size[0]), parseInt(size[1]));
                    marker.iconSrc = icon[0].getAttribute("src");
                }
                if ( shadow[0].getAttribute("src") && shadow[0].getAttribute("size") ) {
                    var size = shadow[0].getAttribute("size").split(',');
                    marker.shadowSize = new GSize(
                        parseInt(size[0]), parseInt(size[1]));
                    marker.shadowSrc = shadow[0].getAttribute("src");
                }
                if ( anchor[0].getAttribute("icon") ) {
                    var size = anchor[0].getAttribute("icon").split(',');
                    marker.iconAnchor = new GPoint(
                        parseInt(size[0]), parseInt(size[1]));
                }
                if ( anchor[0].getAttribute("info") ) {
                    var size = anchor[0].getAttribute("info").split(',');
                    marker.infoAnchor = new GPoint(
                        parseInt(size[0]), parseInt(size[1]));
                }
                if ( anchor[0].getAttribute("tooltip") ) {
                    var size = anchor[0].getAttribute("tooltip").split(',');
                    marker.tooltipOffset = new GSize(
                        parseInt(size[0]), parseInt(size[1]));
                }
                if ( marker.iconSrc && marker.iconAnchor ) {
                    debug("Adding " + marker.label + " with src " + marker.iconSrc);
                    setup.customMarkers.push(marker);
                }
            } else {
                debug("Missing data, can't load "+ label || "undefined marker");
A("Missing data, can't load "+ label || "undefined marker");
            }
        }
    }
    var loadScreen =
        xmlData.documentElement.getElementsByTagName("loadingScreen");
    var splashScreen =
        xmlData.documentElement.getElementsByTagName("splashScreen");
    if ( splashScreen && splashScreen.length > 0 ) {
        splashScreen = splashScreen[0]; // Only get the first splash screen
        setup.splashScreen = new Object();
        if ( splashScreen.getAttribute("blockUntilClosed") &&
             /^true|yes$/.test(splashScreen.getAttribute("blockUntilClosed")) )
        {
            setup.splashScreen.blockLoad = true;
        }
        if ( splashScreen.getAttribute("closeElement") ) {
            setup.splashScreen.closeElement =
                splashScreen.getAttribute("closeElement");
        }
        // Remote Source (slowest way, but lowest maintenance cost)
        if ( splashScreen.getAttribute("src") ) {
            setup.splashScreen.srcUrl = splashScreen.getAttribute("src");
            debug("Fetching remote content: " + setup.splashScreen.srcURL);
A("Fetching remote content: " + setup.splashScreen.srcURL);
            /*
            This is a special case.  We load the URL, but exit out of this
            function without parsing the setup because we're going to wait
            until we can download the remote source URL.
            */
            var _this = this;
/*            
            G*DownloadUrl(setup.splashScreen.srcUrl + "?cb=" + d.getTime(),
                function(data, responseCode) {
                    try {
                        debug("Got response, setting content to: " + data);
A("Got response, setting content to: [DATA]");
 
                        setup.splashScreen.content = data;
                        _this.parseSetup(setup);
                    } catch(e) {
                        debug(e);
                    }
                }
            );
*/
		    loadXMLDoc(setup.splashScreen.srcUrl + "?cb=" + d.getTime(),
				function(XML,TEXT){
                    try {
                        var data=TEXT;
                        debug("Got response, setting content to: " + data);
A("Got response, setting content to: [DATA]");
 
                        setup.splashScreen.content = data;
                        _this.parseSetup(setup);
                    } catch(e) {
                        debug(e);
                    }
                }
            );        
            return;
        }
        // Load the splash screen from a DIV on the HTML page (fastest way)
        else if ( splashScreen.getAttribute("sourceDiv") &&
                  document.getElementById(splashScreen.getAttribute("sourceDiv")) )
        {
            setup.splashScreen.srcDiv = splashScreen.getAttribute("sourceDiv");
            setup.splashScreen.content =
                document.getElementById(splashScreen.getAttribute("sourceDiv")).innerHTML;
            setup.splashScreen.style =
                document.getElementById(splashScreen.getAttribute("sourceDiv")).style;
            this.splashScreenDiv = document.getElementById(splashScreen.getAttribute("sourceDiv"));
        }
        // Load the splash screen from the XML file (faster way)
        else if ( splashScreen.childNodes.length > 0 ) {
            var string = "";
            for ( var j = 0; j < splashScreen.childNodes.length; j++ )
                string += GXml.value(splashScreen.childNodes[j]);
            setup.splashScreen.content = string;
        } else {
A("Invalid splash screen configuration, aborting using it.");
            debug("Invalid splash screen configuration, aborting using it.");
            setup.splashScreen = null;
        }
    }
    this.parseSetup(setup);
}

/*
 Parse the configuration structure and apply it to the page.  This is the point
 where the DOM starts being interacted with, and the map is initially loaded.
*/
MapLoader.prototype.parseSetup = function(setupObj) {
    if ( setupObj.attachPoint && setupObj.dataSources ) {
        var _this = this;
        this.width  = setupObj.width ||
            document.getElementById(setupObj.attachPoint).offsetWidth;
        this.height = setupObj.height ||
            document.getElementById(setupObj.attachPoint).offsetHeight;

        this.setupLoaded = true;
        this.attachPoint = setupObj.attachPoint;
        this.mapDiv = document.getElementById(this.attachPoint);
        this.defaultCoords = setupObj.defaultCoords ||
            new GLatLng(45.604075, -122.5103);
        this.defaultZoom   = setupObj.defaultZoom || 12;
        if ( setupObj.dataSources && setupObj.dataSources.length > 0 ) {
            debug("Parsing "+setupObj.dataSources.length + " data sources...");            
A("Parsing "+setupObj.dataSources.length + " data sources...");
            this.dataSources = setupObj.dataSources;
        } else {
            this.dataSources = new Array();
        }

        this.templateSources = new Array();
        this.templates       = new Array();
        if ( setupObj.templateSources ) {
            for ( var i = 0; i < setupObj.templateSources.length; i++ ) {
                var tmpl = setupObj.templateSources[i];
                debug("Loading template: " + tmpl.source);                
A("Loading template: " + tmpl.source);

//~~same old story, GM impl sucks : G*DownloadUrl(tmpl.source + "?cb=" + d.getTime(),
				loadXMLDoc(tmpl.source + "?cb=" + d.getTime(),					
                    function(XML,data) {
                        try {
                            if ( XML ) _this.parseTemplate(XML);
                        } catch(e) {
                            debug(e);
                            alert("Sorry, there was an error loading the template " + tmpl.source);
                        }
                    }
                );
            }
        }
        for ( var i = 0; i < setupObj.customMarkers.length; i++ ) {
            var marker = new GIcon();
            marker.image      = setupObj.customMarkers[i].iconSrc;
            marker.iconSize   = setupObj.customMarkers[i].iconSize;
            marker.shadow     = setupObj.customMarkers[i].shadowSrc || "";
            marker.shadowSize = setupObj.customMarkers[i].shadowSize;
            marker.iconAnchor = setupObj.customMarkers[i].iconAnchor || new GPoint(0,0);
            marker.tooltipOffset = setupObj.customMarkers[i].tooltipOffset || new GPoint(0,0);
            marker.infoWindowAnchor = setupObj.customMarkers[i].infoAnchor || new GPoint(0,0);
            debug("Created GIcon for " + setupObj.customMarkers[i].label.toLowerCase());
A("Created GIcon for " + setupObj.customMarkers[i].label.toLowerCase());
            this.loadedIcons[setupObj.customMarkers[i].label.toLowerCase()] = marker;
        }

        if ( setupObj.splashScreen ) {
            this.splashScreen = setupObj.splashScreen;
        }

        if ( this.setupLoaded && !this.splashScreen ) {
            this.createMap();
        } else if ( this.setupLoaded ) {
            debug("Using splash screen for loading...");
A("Using splash screen for loading...");
            this.setSplashScreen(this.splashScreen);
    		if(_ENTER_ASAP){
				this.hideSplashScreen(); 	
			}            
        }
    }
}

/*
 * Method: parseTemplate(data)
 * Takes a remote template, inserts it into the MapLoader template registry for
 * use, and sets up the attach points.
 * If the type is "default" it only has one attach point which is "content"
 * If the type is comment or movie, it has custom attach points.  If there
 * are more widget types this feature should be broken out into other functions
*/
MapLoader.prototype.parseTemplate = function(data) {
    var type  = data.documentElement.getAttribute("type") || "default";
    var title = data.documentElement.getAttribute("title");
    if ( type && title ) {
        type = type.toLowerCase(); title = title.toLowerCase();
        debug("Parsing remotely loaded template: " + title);
        var tmplObj     = new Object();
        tmplObj.title   = title;
        tmplObj.struct  = data.documentElement;
        this.templates[title] = tmplObj;
    } else {
        debug("Can't load remote template, invalid syntax.");
    }
}

MapLoader.prototype.createMap = function() {
    if ( this.mapDiv ) {
        debug("Creating map: " + this.mapDiv + " at " + this.defaultCoords.lat() + ", " + this.defaultCoords.lng() +            " @ " + this.defaultZoom);            
A("Creating map: " + this.mapDiv + " at " + this.defaultCoords.lat() + ", " + this.defaultCoords.lng() +            " @ " + this.defaultZoom);            
        this.map = new GMap2(this.mapDiv);
        this.map.addControl(new GSmallMapControl());
        this.map.addControl(new GMapTypeControl());
        this.map.setCenter(this.defaultCoords, parseInt(this.defaultZoom));
		this.map.setMapType(G_SATELLITE_MAP);        

        for ( var i = 0; i < this.templateSources.length; i++ ) {
         //~~etsi you dont get in here, where's the loadTemplate func anyway?
            debug("Loading template " + this.templateSources[i]);
            this.loadTemplate(this.templateSources[i]);
        }

        /*
         * Make usre to clean up info windows if we use templates.  Since
         * the templated info windows are a new stack of windows it requires
         * an explicit call to close them since Google Maps can't cleanup
         * an external stack.
        */
        GEvent.bind(this.map, "infowindowopen", this, this.closeInfoWindow);

GEvent.addListener(this.map.getInfoWindow(),"closeclick", this.stopAnyFlash);	
		 
        for ( var i = 0; i < this.dataSources.length; i++ ) {
            // TODO, implement automatic refresh period and event updates
            debug("Loading " + this.dataSources[i]);
            A("Loading " + this.dataSources[i]);
            
            this.loadRemoteXML(this.dataSources[i]);
        }
        GEvent.bind(this.map, "goto", this, this.navigateMarkers);
        debug("Internal Properties: " + this.map.Ga);
    }
    else
        throw("Unable to create map: attach point cannot be found.");
}

MapLoader.prototype.navigateMarkers = function(gotoPoint, inc) {
    this.closeInfoWindow(true);
    if ( typeof this.orderedMarkers[gotoPoint] == "undefined" ) {
        if ( gotoPoint > 1 ) { gotoPoint = 1; }
        else { gotoPoint = this.orderedMarkers.length - 1; }
    }
    var marker;
    for (var i = gotoPoint; i > 0 && i < this.orderedMarkers.length; i += inc) {
        if ( this.orderedMarkers[i] ) {
            marker = this.orderedMarkers[i];
            GEvent.trigger(marker.marker, "click", marker.marker);
            return;
        }
    }
}

MapLoader.prototype.stopAnyFlash = function(){
            var FPMO=getFlashMovieObject("playback");
			if(FPMO){
			 A('Flash object still present. should stop.'+activeBubble);
//				FPMO.StopPlay();
			}
			else{
			 A('Flash object NOT present. '+activeBubble);
 
			}
			activeBubble=-1;
		 }
MapLoader.prototype.setLoadingScreen = function(loadingDiv, preMapLoad) {}

MapLoader.prototype.setSplashScreen  = function(splashConfig) {
    if ( !this.splashScreenDiv ) {
        this.splashScreenDiv = document.createElement("div");
        with ( this.splashScreenDiv.style ) {
            zIndex     = "1";
            width      = this.width + "px";
            height     = this.height + "px";
            position   = "absolute";
            overflow   = "hidden";
            if ( splashConfig.srcDiv && splashConfig.srcDiv.style ) {
                background = splashConfig.srcDiv.style.background || "#fff";
                border     = splashConfig.srcDiv.style.border || "none";
            } else {
                background = this.mapDiv ? this.mapDiv.style.background:"#fff";
                border     = this.mapDiv ? this.mapDiv.style.border : "none";
            }
        };
        if ( splashConfig.content )
            this.splashScreenDiv.innerHTML = splashConfig.content;
        document.body.appendChild(this.splashScreenDiv);
    }
    if ( splashConfig.closeElement &&
         document.getElementById(splashConfig.closeElement) )
    {
        var _this = this;
        if(!_ENTER_ASAP){
	        document.getElementById(splashConfig.closeElement).style.display='block';
	        GEvent.addDomListener(
	            document.getElementById(splashConfig.closeElement), "click",
	            function() { _this.hideSplashScreen(); }
        );
		}
    }
    
    if ( this.mapDiv ) {
//~~ MM rewritten: the Splash should be where the map container is, but why so 
//~~ unreliably???  
/*   
        var posX = getTotalOffset(this.mapDiv, "left", false);
        var posY = getTotalOffset(this.mapDiv, "top", false);
        debug("positioning at " + posX + ", " + posY);
        this.splashScreenDiv.style.left = posX + "px";
        this.splashScreenDiv.style.top  = posY + "px";             */        
//_______________________________________________________________        

        this.splashScreenDiv.style.left = this.mapDiv.style.left;
        this.splashScreenDiv.style.top  =  this.mapDiv.style.top;
        this.splashScreenDiv.style.margin='0px 0px 0px 0px';
//_______________________________________________________________        
    }
    this.splashScreenDiv.style.display = "";
    if ( !splashConfig.blockLoad ) {
        this.createMap();
    } else {
        this.splashBlockedLoad = true;
        debug("Blocking load until splash screen is closed");
    }

}
function releaseObject(OBJ) {
 A('RELEASING SPLASH');
	OBJ.innerHTML='';
	OBJ.style.width="0px";	OBJ.style.height="0px";
	OBJ.style.top="0px";	OBJ.style.left="0px"; 
} 
MapLoader.prototype.hideSplashScreen  = function() {
    if ( this.splashBlockedLoad && !this.map ) {
        releaseObject(this.splashScreenDiv);
        this.createMap();
        var _this = this;
        GEvent.addListener(this, "loaded", function() {
            debug("Map fully loaded, get rid of the splash screen");
            //~~MM : forget about the splashscreen, release RAM
			//_this.splashScreenDiv.style.display = "none";        
			});
    } else {
            //~~MM : forget about the splashscreen, release RAM
            //releaseObject(this.splashScreenDiv);
            //_this.splashScreenDiv.style.display = "none";   
		    }
}

function fadeElement( element ) {
    var fadeFunc = function(element) {
        if ( element.style.opacity > 0 ) {
            var newVal = parseFloat( element.style.opacity );
            newVal    -= 0.05;
            element.style.opacity    = newVal;
            element.style.MozOpacity = newVal;
            element.style.filter     = "alpha(opacity=" + (newVal * 100) + ")";
            setTimeout(element, 100);
        } else {
            element.style.display = "none";
        }
    };
    window.setTimeout( element, 100 );
}

MapLoader.prototype.showStatusPopup = function(message) {
    debug(message);
    alert(message);
}

MapLoader.prototype.hideLoadingScreen = function() {}

MapLoader.prototype.loadRemoteData = function(setupFile) {}

MapLoader.prototype.loadRemoteXML  = function(url, timeout) {
    if ( this.loadTimeout )
        clearTimeout(this.loadTimeout);

    var _this = this;
    debug("Loading remote XML: " + url);
//~~same crap...    G*DownloadUrl(url + "?cb=" + d.getTime(),
      loadXMLDoc(url + "?cb=" + d.getTime(),
        function(XML, TEXT) {
            clearTimeout(_this.loadTimeout);
       
            try { _this.parseRemoteXMLData(XML) }
            catch(e) { debug(e); A(e); alert(e+"> Sorry, there was an error loading the data for this page.  Please try your request again later.  If it continues, or if you believe you received this message in error, please contact the site administrator.");
        }
    });
}

/*
 parseRemoteData expects an XML data structure from a remote source.  This
 is translated into a JavaScript datagram which is then passed to addMarkers
*/
MapLoader.prototype.parseRemoteXMLData = function(xmlDoc) {
    debug("Parsing remote XML data..." + xmlDoc);
    A("Parsing remote XML data... | " + typeof(xmlDoc));
    A('init markers...'); 
//&&    alert(xmlDoc.getElementsByTagName("marker"));
//if ( !xmlDoc || !xmlDoc.documentElement.getElementsByTagName )
/*&&    if ( !xmlDoc || typeof xmlDoc.documentElement.getElementsByTagName == "undefined" ) {
        debug("Can't get valid document ref");
        return this.showStatusPopup(DATA_ERROR);
    }
&&*/    
       
//&    var markers = xmlDoc.documentElement.getElementsByTagName('marker');
        var markers = xmlDoc.getElementsByTagName("marker");
    A('markers loaded');
    A(markers.length+' markers total');
    // Should we assume a data error here?   [ASK]
    if ( markers.length == 0 ) {
        debug("There are no markers in this data file, it is useless to me!");
        return this.showStatusPopup(DATA_ERROR);
    }
    A('flush markers');
    this.flushMarkers();
    
    for ( var i = 0; i < markers.length; i++ ) {
        if ( markers[i].getAttribute("latitude") &&
             markers[i].getAttribute("longitude") )
        {
            var config = new Object();
            debug("Adding marker: " + i + " at " +
                markers[i].getAttribute("latitude") + ", " +
                markers[i].getAttribute("longitude"));
            var icon = markers[i].getElementsByTagName("icon");
            if ( icon.length > 0 ) {
                if ( icon[0].getAttribute("type") ) {
                    var iconToUse = icon[0].getAttribute("type").toLowerCase();
                    if ( this.loadedIcons[iconToUse] )
                        config.marker = this.loadedIcons[iconToUse];
                }
            }

            var contentTags = markers[i].getElementsByTagName("content");
            config.content = new Array();
            debug("Marker has " + contentTags.length + " content elements.");
            for ( var j = 0; j < contentTags.length; j++ ) {
                var ctn = contentTags[j];
                var content = new Object();
                if ( ctn.getAttribute("title") ) {
                    content.label = ctn.getAttribute("title");
                }
                
                if ( ctn.getAttribute("lPopup") ) {
                    content.swfUrl       = ctn.getAttribute("flashPopup");
                    content.width  = parseInt(ctn.getAttribute("width"))
                        || 200;
                    content.height = parseInt(ctn.getAttribute("height"))
                        || 150;
                }
                if ( ctn.getAttribute("movie") ) {
                    content.type = "movie";
                    content.movie = new Object();
                    content.movie.url    = ctn.getAttribute("movie");
                    content.movie.width  = ctn.getAttribute("width");
                    content.movie.height = ctn.getAttribute("height");
                }
                if ( ctn.getAttribute("comments") ) {
                    content.type = "comments";
                    content.comments = new Object();
                    content.comments.url    = ctn.getAttribute("comments");
                    content.comments.width  = ctn.getAttribute("width");
                    content.comments.height = ctn.getAttribute("height");
                }
                if ( ctn.childNodes.length > 0 ) {
                    content.type = "default";
                    var div = document.createElement("div");
                    if ( ctn.getAttribute("width") )
                        div.style.width = parseInt(ctn.getAttribute("width")) + "px";
                    if ( ctn.getAttribute("height") )
                        div.style.height = parseInt(ctn.getAttribute("height")) + "px";
                    var string = "";
                    for ( var k = 0; k < ctn.childNodes.length; k++ )
                        string += GXml.value(ctn.childNodes[k]);
                    div.innerHTML = '***'; //~~was: div.innerHTML =string;
					//content.HTMLcode = string; //~~MM added, load content
											//	 ONLY when the bubble appears.
//~~remove MM:>>>   if ( div.innerHTML )
//~~--                        content.content = div;
                    content.content = string;
                }
                if ( ctn.getAttribute("template") ) {
                    debug("Looking up template: " + ctn.getAttribute("template"));
                    var tmpl = this.templates[ctn.getAttribute("template")];
                    if ( tmpl ) {
                        config.isTemplated = true;
                        debug("Content is using template: " + tmpl.title);
                        content.template = tmpl;
                    }
                }
                config.content.push(content);
            }
            var tooltip = markers[i].getElementsByTagName("tooltip");
            if ( tooltip && tooltip.length > 0 ) {
                tooltip = tooltip[0];
                config.tooltip = new Object();
                config.tooltip.label = tooltip.firstChild.nodeValue;
                /*
                 * @DOC
                 * Two ways to set the offset: the tooltip (higher order)
                 * or the marker can set a tooltip anchor point in the
                 * setup XML file
                */
                if ( tooltip.getAttribute("offset") &&
                     /^\s*-?\d+\s*,\s*-?\d+\s*$/.test(tooltip.getAttribute("offset")) )
                {
                    var offset = tooltip.getAttribute("offset").split(',');
                    config.tooltip.offset = new GSize(parseInt(offset[0]), parseInt(offset[1]));
                }
                else if ( config.marker && config.marker.tooltipOffset ) {
                    debug("Inheriting tooltip offset: " + config.marker.tooltipOffset);
                    config.tooltip.offset = config.marker.tooltipOffset;
                }
                if ( tooltip.getAttribute("static") &&
                    /^true|yes|1$/.test(tooltip.getAttribute("static").toLowerCase()) )
                {
                    config.tooltip.isStatic = true;
                }
                if ( tooltip.getAttribute("class") )
                    config.tooltip.className = tooltip.getAttribute("class");
            }
            if ( markers[i].getAttribute("order") )
                config.order = parseInt(markers[i].getAttribute("order"));

            var m = new Marker( this, new GLatLng(
                markers[i].getAttribute("latitude"),
                markers[i].getAttribute("longitude")
            ), config);
            if ( config.order )
                this.orderedMarkers[config.order] = m;
            this.addMarker(m, m.show, true);
        } else {
            throw "Invalid marker syntax specified in data file (" + i + " marker)";
        }
    }
    this.queueCounter = 0;
    this.renderMarkers();
    GEvent.trigger(this, "loaded");
}

/*
 Kept as a stub in case further work requires JSON or other formats
*/
MapLoader.prototype.loadRemoteJSON = function(setupFile) {}

/*
 flushMarkers will clear all the markers.  To be more efficient, it actually
 hides every marker and sets the reuse index to 0.  This way, new markers are
 not allocated but updated older markers.  This method rovides a considerably
 faster load and response time.
*/
MapLoader.prototype.flushMarkers  = function() {
    debug("Flushing markers...");
    this.map.clearOverlays();
}

MapLoader.prototype.addMarker = function(marker, showFunc, apply) {
    if ( !this.queue )
        this.queue = new Array();
    debug("Creating single fire closure");
    this.queue.push( _SingleFireClosure(marker, showFunc, apply) );
}

MapLoader.prototype.renderMarkers = function() {
    debug("Have " + this.queue.length + " markers to add");
    while ( this.queue && this.queueCounter < this.queue.length ) {
        debug("Adding " + this.queueCounter + " out of " + this.queue.length);
        this.queue[this.queueCounter]();
        // Clean up our single-fire closure
        this.queue[this.queueCounter++] = null;
    }
    this.queue = null;
    this.queueCounter = 0;
}
/*
 * renderMovieWindow returns generated HTML for displaying a FLV movie
*/
MapLoader.prototype.renderMovieHtml = function(movie, width, height) {
    if ( !width ) width = 150;
    if ( !height ) height = 150;
    var divContainer = document.createElement("div");
    divContainer.className    = "flashMovie";
    divContainer.style.width  = parseInt(width) + "px";
    divContainer.style.height = parseInt(height) + "px";
    divContainer.style.border = "1px solid #000";
    /* Don't cover the close button */
    divContainer.style.marginTop = "16px";
    divContainer.id = "flashLoaderDiv";
    divContainer.appendChild(document.createTextNode("Loading..."));
    GEvent.addListener(this.map, "infowindowopen", function() {
        debug("Replacing content... " + movie);
        document.getElementById("flashLoaderDiv").innerHTML =
        "<object classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" codebase=\"http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0\" width=\"" + width + "\" height=\"" + height + "\" title=\"race\">" +
        "<param name=\"movie\" value=\"" + movie + "\" />" +
        "<param name=\"quality\" value=\"high\" />" +
        "<embed src=\"" + movie + "\" quality=\"high\" pluginspage=\"http://www.macromedia.com/go/getflashplayer\" type=\"application/x-shockwave-flash\" width=\"" + width + "\" height=\"" + height + "\"></embed>" +
        "</object>";
        GEvent.removeListener(this);
    });
    return divContainer;
}

/*
 * Info Window Overloads - This allows templated info windows.
*/
/*
MapLoader.prototype.buildPopupContent = function(contentPane, order) {
    var content = document.createElement("div");
    content.id='buildPopupContent'+this._buildPopupContent_id;
    this._buildPopupContent_id++;
    content.className = "defaultPopupStyle";

    if ( contentPane.movieURL ) {
        debug("Loading content");
        if ( contentPane.movieURL ) {
            var movie = this.renderMovieHtml(
                contentPane.movieURL,
                contentPane.width, contentPane.height
            );
            content.appendChild(movie);
        }
    }
    if ( contentPane.commentData ) {
        var commentContainer = document.createElement("div");
        commentContainer.className = "commentContainer";
        var commentList = document.createElement("ul");
        commentList.className = "popupCommentListStyle";
        generateCommentList(commentList, contentPane.commentData);
        commentContainer.appendChild(commentList);
        content.appendChild(commentContainer);
    }
    if ( contentPane.content ) {

alert('order = '+order+'  pe aici '+typeof(contentPane.content)+'\n\n'+contentPane.content);
        if ( typeof contentPane.content == "object" ) {
            content.appendChild(contentPane.content);
        } else {
            content.innerHTML = '<div id="infoBubble'+order+'">'+contentPane.content+'</div>';
            activeBubble=order;	
        }
    }
    if ( typeof order != "undefined" && parseInt(order) > 0 ) {
        var navControl = generatePagination(this.map, parseInt(order));
        content.appendChild(navControl);
    }
    var clearBr = document.createElement("br");
    clearBr.style.clear = "both";
    content.appendChild(clearBr);
    return content;
}
*/
MapLoader.prototype.buildPopupContent = function(contentPane, order) {
 
    var content = '<div class="defaultPopupStyle" id="buildPopupContent'+this._buildPopupContent_id+'">';
    this._buildPopupContent_id++;

    if ( contentPane.movieURL ) {
        A("Loading content");
        if ( contentPane.movieURL ) {
            var movie = this.renderMovieHtml(
                contentPane.movieURL,
                contentPane.width, contentPane.height
            );
            content.appendChild(movie);
        }
    }
    if ( contentPane.commentData ) {
        var commentContainer = document.createElement("div");
        commentContainer.className = "commentContainer";
        var commentList = document.createElement("ul");
        commentList.className = "popupCommentListStyle";
        generateCommentList(commentList, contentPane.commentData);
        commentContainer.appendChild(commentList);
        content.appendChild(commentContainer);
    }
    if ( contentPane.content ) {

//alert('order = '+order+'  pe aici '+typeof(contentPane.content)+'\n\n'+contentPane.content);
        if ( typeof contentPane.content == "object" ) {
            content.appendChild(contentPane.content);
        } else {
            content+= '<div id="infoBubble'+order+'" style="overflow:hidden">'+contentPane.content+'</div>';
            activeBubble=order;	
        }
    }

    if ( typeof order != "undefined" && parseInt(order) > 0 ) {
        //var navControl = generatePagination(this.map, parseInt(order));
        //content.appendChild(navControl);
        //content+=navControl.innerHTML;
        //navControl.innerHTML='';navControl=false;
        content+='&nbsp;<a href="javascript:navigateNext()">NEXT LOCATION &gt;</a>';
    }
    content+='<br style="clear:both"></div>';
//alert('Content as HTML = \n\n'+content);
    return content;
}



function FlashOverlay(flashCfg, marker) {
    this.flashCfg = flashCfg;
    this.marker   = marker;
    this.anchor   = marker.getPoint();
}

FlashOverlay.prototype = new GOverlay();
FlashOverlay.prototype.initialize = function(map) {
    this.map = map;
    var flashCfg = this.flashCfg;
    var marker   = this.marker;
    var _this = this;

    if ( !this.flashContainer ) {
        this.flashContainer = document.createElement("div");
        with ( this.flashContainer.style ) {
            position = "absolute";
            margin   = "0";
            padding  = "0";
            display  = "none";
        }
        var pane = this.map.getPane(G_MAP_FLOAT_PANE);
        pane.appendChild(this.flashContainer);
    }
    this.width = parseInt(flashCfg.width) > 0 ? 
        parseInt(flashCfg.width) : 200;
    this.height = parseInt(flashCfg.height) > 0 ? 
        parseInt(flashCfg.height) : 150;
    this.flashContainer.style.width  = this.width + "px";
    this.flashContainer.style.height = this.height + "px";
    this.flashContainer.innerHTML =
        "<object classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" codebase=\"http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0\" width=\"" + this.width + "\" height=\"" + this.height + "\" title=\"race\">" +
        "<param name=\"movie\" value=\"" + flashCfg.swfUrl + "\" />" +
        "<param name=\"quality\" value=\"high\" />" +
        "<embed src=\"" + flashCfg.swfUrl + "\" quality=\"high\" pluginspage=\"http://www.macromedia.com/go/getflashplayer\" type=\"application/x-shockwave-flash\" width=\"" + this.width + "\" height=\"" + this.height + "\"></embed>" +
        "</object>";
}

FlashOverlay.prototype.remove = function() {
    this.flashContainer.parentNode.removeChild(this.flashContainer);
    this.flashContainer = null;
}

FlashOverlay.prototype.copy = function() {
}

FlashOverlay.prototype.redraw = function(force) {
    if ( this.isVisible ) {
        this.flashContainer.style.display = "";
        var pix = this.map.fromLatLngToDivPixel(this.anchor);
        debug("redraw(" + force + ") @ " + pix +")");
        debug("Showing flash info at " + this.anchor + " = " + pix.x + ", " + pix.y);
        this.flashContainer.style.left = pix.x + "px";
        this.flashContainer.style.top  = ( pix.y - this.height ) + "px";
        if ( force ) {
            this.map.panTo(
                this.map.fromDivPixelToLatLng(new GPoint(pix.x, pix.y - this.height))
            );
        }
    }

}

FlashOverlay.prototype.show = function(point) {
    var p = point || this.marker.getPoint();
    this.anchor = p;
    debug("show(" + this.anchor +") -> setting fresh draw to true");
    this.isVisible = true;
    this.redraw(true);

    var _this = this;
}

FlashOverlay.prototype.hide = function() {
    this.flashContainer.style.display = "none";
    this.isVisible = false;
}

MapLoader.prototype.openFlashPopup = function(marker, flashCfg) {
    this.flashOverlay = new FlashOverlay(flashCfg, marker);
    this.map.addOverlay(this.flashOverlay);
    var _this = this;
    GEvent.addListener(marker, "click", function() {
try {
        if ( flashCfg["order"] ) this.openedWindow = flashCfg["order"];
        _this.closeInfoWindow(true);
        _this.flashOverlay.show(marker.getPoint());
} catch(e) { alert(e); }
    });

    GEvent.addListener(this.map, "zoomend", function() {
        _this.closeFlashPopup();
    });
    GEvent.addListener(this.map, "dragstart", function() {
        _this.closeFlashPopup();
    });
}

MapLoader.prototype.closeFlashPopup = function() {
    debug("Closing flash popup.");
    this.flashOverlay.hide();
}
MapLoader.prototype.openWindow = function(marker, ContentPanes, opts) {
    if ( this.openedWindow )
        this.openedWindow.hide();

    var contentTokens = {};
    if ( opts.isTemplated ) {
        this.closeInfoWindow(true);
        if ( ContentPanes.length > 1 ) {
            debug("Opening a tabbed window: " + ContentPanes[0].template);
            this.openInfoWindowTabs(marker.getPoint(), ContentPanes, {
                "templates":    opts.templates,
                "order":        opts.order,
                "anchorOffset": marker.getIcon().infoWindowAnchor
            });
        } else {
            debug("TMPL:: Order: " + opts.order);
            this.openInfoWindow(marker.getPoint(),
                ContentPanes[0], {
                "template": ContentPanes[0].template,
                "order":    opts.order,
                "anchorOffset": marker.getIcon().infoWindowAnchor });
        }
    } else {
        if ( ContentPanes.length > 1 ) {
            var tabs = new Array();
            for ( var i = 0; i < ContentPanes.length; i++ ) {
                var tab = new GInfoWindowTab(ContentPanes[i].label,
                    this.buildPopupContent(ContentPanes[i], opts.order));
                tabs.push(tab);
            }
            marker.openInfoWindowTabs(tabs);
        } else {
            var content = this.buildPopupContent(ContentPanes[0], opts.order);
            var dtt=new Date(); //~~FORCE refresh of buffer for IE damn activeX
            while(content.indexOf('?movie=')!=-1){
				content=content.replace('?movie=','?cb='+dtt.getTime()+'&movie=');
			}
 //			alert('popup : '+opts.order);
var tabs = new Array();
var tab = new GInfoWindowTab('Details',content);
tabs.push(tab);
//alert(content);//°
var s_height='height="';
var kh=250;
if(content.indexOf(s_height)!=-1){
	kh=content.substring(content.indexOf(s_height)+s_height.length);
 	kh=kh.substring(0,kh.indexOf('"') );
}
kh=parseInt(kh)+30;
	tab = new GInfoWindowTab('Blog','<iframe src="blog.php?id='+DBIDs[opts.order]+'" frameborder="0" style="margin:0px 0px 0px 0px;background:#FFAAFF;width:490px;height:'+kh+'px;overflow:auto"></iframe>');
tabs.push(tab);
marker.openInfoWindowTabs(tabs);
//         marker.openInfoWindowHtml(content);
            var FPMO=getFlashMovieObject("playback");
			if(FPMO){
			 A('FPMO exist,loaded '+PercentLoaded());
				activeFP=FPMO;
			}
        }
    }
}

MapLoader.prototype.openInfoWindow = function(point, node, opts) {
    this.map.closeInfoWindow(true);
    var win = this.getInfoWindow(opts ? opts.template : null);
    if ( win.isTemplated ) {
        this.templatedInfoWindow = win;
        win.openInfoWindow(point, node, opts);
    }
    else {
        this.map.defaultOpenInfoWindow(point, node, opts);
    }
}

MapLoader.prototype.openInfoWindowTabs = function(point, tabs, opts) {
    this.map.closeInfoWindow(true);

    var win = this.getInfoWindow(opts ? opts.templates[0] : null);
    if ( win.isTemplated ) {
        this.templatedInfoWindow = win;
        win.openInfoWindowTabs(point,tabs,opts);
    }
    else {
        this.map.defaultOpenInfoWindowTabs(point, tabs, opts);
    }
}

MapLoader.prototype.closeInfoWindow = function(closeAll) {

A('MapLoader.prototype.closeInfoWindow, we have '+this.orderedMarkers.length);
 for(i=0;i<=this.orderedMarkers.length;i++){
    if(i==activeBubble){continue;}
    var X = document.getElementById('infoBubble'+i);
	if(X){
		A('destroying : \n\n'+i);
		X.innerHTML='*//*';
	}	
 }
    if ( this.flashOverlay ) {
        this.flashOverlay.hide(true);
    }
    if ( this.templatedInfoWindow ) {
        debug("CLOSE:: Closing previous info window.");
        this.templatedInfoWindow.hide();
        this.templatedInfoWindow = null;
    }
    if ( closeAll ) {
        debug("CLOSE:: Closing any default windows.");
        this.map.closeInfoWindow();
    }
}

MapLoader.prototype.getInfoWindow = function(template) {
    if ( template ) {
        if ( !this.templatedWindows )
            this.templatedWindows = new Array();
        var templatedInfoWindow = this.templatedWindows[template.title];
        if ( !templatedInfoWindow ) {
            debug("Creating new template popup: " + template.struct);
            templatedInfoWindow = new TemplatedPopup(template);
            this.templatedWindows[template.title] = templatedInfoWindow;
            this.map.addOverlay(templatedInfoWindow);
        }
        return templatedInfoWindow;
    } else {
        debug("Using default popups");
        return this.map.getInfoWindow();
    }
}

/*
 zoomToMarkers will zoom out until all markers are visible
*/
MapLoader.prototype.zoomToMarkers = function() {}

function _SingleFireClosure(obj, func, arg) {
    return ( function() {
        obj.func = func;
        obj.func(arg);
        arg      = null;
        obj.func = null;
        obj      = null;
    });
}

// From http://laurens.vd.oever.nl/weblog/items2005/closures/
Function.prototype.closure = function(obj) {
    // Init object storage.
    if (!window.__objs) {
        window.__objs = [];
        window.__funs = [];
    }

    // For symmetry and clarity.
    var fun = this;

    // Make sure the object has an id and is stored in the object store.
    var objId = obj.__objId;
    if (!objId)
        __objs[objId = obj.__objId = __objs.length] = obj;

    // Make sure the function has an id and is stored in the function store.
    var funId = fun.__funId;
    if (!funId)
        __funs[funId = fun.__funId = __funs.length] = fun;

    // Init closure storage.
    if (!obj.__closures)
        obj.__closures = [];

    // See if we previously created a closure for this object/function pair.
    var closure = obj.__closures[funId];
    if (closure)
        return closure;

    // Clear references to keep them out of the closure scope.
    obj = null;
    fun = null;

    // Create the closure, store in cache and return result.
    return __objs[objId].__closures[funId] = function () {
        return __funs[funId].apply(__objs[objId], arguments);
    };
}

/*
 * Extension Objects -- What follows are objects that are used, but not
 * part of the default MapLoader class.
*/

/*
 * Label - The tooltip to hover or place over markers
*/
function Label(label, config) {
    this.label = label;
    if ( typeof config != "object" ) throw "Invalid label configuration";
    this.className = config.className || "MarkerTooltip";
    if ( config.isStatic ) {
        this.isStatic = true;
    }
    if ( config.marker && typeof config.marker.getPoint != "undefined" ) {
        this.anchor = config.marker.getPoint();
        if ( !this.isStatic ) {
            var _this = this;
            debug("Creating marker mouse events");
            GEvent.bind(config.marker, "mouseover", this, this.show);
            GEvent.bind(config.marker, "mouseout", this, this.hide);
        }
    }
    else if ( config.anchor && config.anchor.lat )
        this.anchor = config.anchor;
    if ( config.pane )
        this.pane = config.pane;

    if ( config.offset ) {
        this.offset = config.offset;
    } else
        this.offset = new GSize(0,0);

    if ( !this.anchor )
        throw "Invalid label configuration: no anchor point";
}

if ( typeof GOverlay != "undefined" )
    Label.prototype = new GOverlay();

Label.prototype.initialize = function(map) {
    this.map = map;
    debug("Initializing label..." + this.label + "(class: " + this.className + ")");
    // Default to right above the markers
    this.pane = map.getPane(this.pane || G_MAP_FLOAT_SHADOW_PANE);
    this.container = document.createElement("div");
    this.container.style.position   = "absolute";
    this.container.innerHTML = "<div class=\"" + this.className + "\">" + this.label + "</div>";
    if ( !this.isStatic )
        this.container.style.display = "none";
    this.pane.appendChild(this.container);
}

Label.prototype.remove = function() {
    this.container.parentNode.removeChild(this.container);
}

Label.prototype.copy   = function() {
    return new Label(this.label, this);
}

Label.prototype.setAnchor = function(anchor) {
    this.anchor = anchor;
    this.redraw(true);
}

Label.prototype.redraw = function(force) {
    var pix = this.map.fromLatLngToDivPixel(this.anchor);
/*
 Useful for debugging label offsets, but spams the debug log quite severely:
    debug("Redrawing label: " + this.anchor.lat() + ", " + this.anchor.lng() +
          " => " + pix.y + ", " + pix.x +
          " (Offset: " + this.offset.width + ", " + this.offset.height + ")");
*/
    this.container.style.left = (pix.x + this.offset.width) + "px";
    this.container.style.top  = (pix.y + this.offset.height) + "px";
}

Label.prototype.show = function(point) {
    if ( point && typeof point.lat != "undefined" ) {
        var pix = this.map.fromLatLngToDivPixel(point);
        this.container.style.left = (pix.x + this.offset.width) + "px";
        this.container.style.top  = (pix.y + this.offset.height) + "px";
    }
    this.container.style.display = "";
}

Label.prototype.hide = function() {
    this.container.style.display = "none";
}

var orderedMarkerList = new Array();

function Marker(loader, pos, config) {
    this.map = loader.map;
    this.pos = pos;
    var marker;
    var _this = this;
    debug("Creating marker at " + pos.lat() + ", " + pos.lng());
    debug("Marker tooltip? " + config["tooltip"].label + "; Marker? " + config.marker);
    marker = new GMarker(this.pos, config.marker);

    if ( config && config["tooltip"] && config["tooltip"].label ) {
    	var oldInit = marker.initialize;
        var ttCfg = config["tooltip"];
        ttCfg.marker = marker;
        this.label  = new Label(ttCfg.label, ttCfg);
        var _l = this.label;
        marker.initialize = function(map) {
            debug("Initializing extended marker");
            map.addOverlay(_l);
            oldInit.apply(marker, [map]);
        };
    }
    if ( config["order"] )
        this.order = config["order"];

/*
 * TODO: Continue development for tabbed info windows here
*/
    var ContentPanes  = new Array();
    var TemplatesUsed = new Array();
    var flashCfg    = false;
    for ( var i = 0; config.content && i < config.content.length; i++ ) {
        var content = config.content[i];
        var contentObj = new Object;
        contentObj.label = content.label || ("Tab " + (i + 1));
        if ( content.swfUrl ) {
            flashCfg = content;
            break;
        }
        if ( content.template ) {
            TemplatesUsed.push(content.template);
            /* Pick a template, any template (as long as it is defined in the
             * setup XML file and properly loaded.  This is checked for sanity
             * later, we're just building a config object now.
            */
            contentObj.template = content.template;
        }
        if ( content.movie ) {
            /* Just a reference, we don't need to preload it... let Flash
             * do that
            */
            contentObj.movieURL    = content.movie.url;
            contentObj.movieWidth  = content.movie.width;
            contentObj.movieHeight = content.movie.height;
        }
        if ( content.comments ) {
            /*
             * Needs to be loaded remotely, so lets start that now.
            */
            contentObj.commentURL  = content.comments.url;
            contentObj.loadComment = function(url, retObj) {
                debug("Downloading comment URL: " + url);
                GDownloadUrl(url, function(data, status) {
                    retObj.commentLoading = false;
                    retObj.commentDoc     = GXml.parse(data);
                    retObj.commentData    =
                        retObj.commentDoc.getElementsByTagName("comment");
                });
            };
            contentObj.loadComment(contentObj.commentURL, contentObj);
        }
        if ( content.content ) {
            contentObj.content = content.content;
        }
        ContentPanes.push(contentObj);
    }
    var _this = this;
    if ( flashCfg ) {
        flashCfg.order = this.order;
        loader.openFlashPopup(marker, flashCfg);
    }
    else if ( ContentPanes.length > 0 ) {
        GEvent.addListener(marker, "click", function() {
            if ( this.order ) this.openedWindow = this.order;
            if ( _this.label ) _this.label.hide(); // Safari issue
            _this.map.setCenter(marker.getPoint());
            loader.openWindow(marker, ContentPanes, {
                "order": config.order, "isTemplated": config.isTemplated,
                "templates": TemplatesUsed
            } )
        });
    }
    this.marker = marker;
}

Marker.prototype.show = function(isOn) {
    this.map.addOverlay(this.marker); 
}

/*
 * There can be only one!  This is basically a duplicate of the GInfoWindow
 * object and we add it to the map.  This causes _some_ problems because the
 * default GMap2 class decides what the info window should be so we have to
 * reassign the info window to our current TemplatedPopup object.  The
 * perk of doing this is that subsequent open calls will continue to use the
 * same template, but it is a bit hacky to update internal properties of the
 * GMap2 object.  Unfortunately, Google fails to provide a method to overload
 * the GInfoWindow without doing that.
*/
function TemplatedPopup(template) {
    if ( template.struct ) {
        this.isTemplated = true;
        debug("Constructing new template popup: " + template.struct);
        this.domStruct = template.struct;
    }
}

/* Inherit from GInfoWindow */
if ( typeof GOverlay != "undefined" )
    TemplatedPopup.prototype = new GOverlay();

TemplatedPopup.prototype.initialize = function(map) {
    this.map  = map;
    this.pane = map.getPane(G_MAP_FLOAT_PANE);
    this.attachPoint = {};
    this.container = document.createElement("div");
    debug("Constructing DOM tree from " + this.domStruct);
    this.recursiveCopy(this.container, this.domStruct);
    this.container.style.className = "templatedPopupWindow";
    this.container.style.position  = "absolute";
    this.container.style.display   = "none";
    this.pane.appendChild(this.container);
}

TemplatedPopup.prototype.recursiveCopy = function(parent, child) {
    debug("TMPL:: Going to copy " + child.childNodes.length + " nodes.");
    for ( var i = 0; i < child.childNodes.length; i++ ) {
        var node = child.childNodes[i];
        debug("TMPL:: Node " + i + " = " + node.nodeName + " (" + node.nodeType + ")");
        /* Tag */
        if ( node.nodeType == 1 ) {
            var newNode = document.createElement(node.nodeName);
            for ( var j = 0; j < node.attributes.length; j++ )
                newNode.setAttribute(node.attributes[j].name, node.attributes[j].value);
            if ( node.nodeValue && node.nodeValue.toString().length > 0 ) {
                debug("TMPL:: Node Value: " + node.nodeValue);
                newNode.appendChild(document.createTextNode(node.nodeValue));
            }
            if ( node.getAttribute("attachPoint") ) {
                var attach = node.getAttribute("attachPoint");
                debug("TMPL:: Attach Point: " + attach);
                this.attachPoint[attach] = newNode;
                if ( attach == "closeElement" ) {
                    if ( node.nodeName.toLowerCase() == "a" ) {
                        newNode.href = "javascript:void(0)";
                    }
                    GEvent.bindDom(newNode, "click", this, this.hide);
                }
            }
            if ( node.childNodes.length > 0 ) {
                debug("TMPL:: Node has children");
                this.recursiveCopy(newNode, node);
            } else {
                debug("TMPL:: No children!");
            }
            parent.appendChild(newNode);
        }
        /* Text Node */
        else if ( node.nodeType == 3 ) {
            if ( node.nodeValue && node.nodeValue.toString().length > 0 ) {
                debug("TMPL:: Node Value: " + node.nodeValue);
                parent.appendChild(document.createTextNode(node.nodeValue));
            }
        }
    }
}

TemplatedPopup.prototype.copy = function() {
    debug("TemplatedPopup:: copy");
}

TemplatedPopup.prototype.remove = function() {
    debug("TemplatedPopup:: remove");
}

TemplatedPopup.prototype.redraw = function(force) {
    debug("TemplatedPopup:: redraw");
}

TemplatedPopup.prototype.show = function(point) {
    debug("TemplatedPopup:: Showing");
    this.container.style.display = "";
}

TemplatedPopup.prototype.hide = function() {
    debug("TemplatedPopup:: Hiding");
    this.container.style.display = "none";
}

TemplatedPopup.prototype.positionContainer = function(point, anchor) {
    if ( point ) {
        this.map.setCenter(point);
        var pix = this.map.fromLatLngToDivPixel(point);
        if ( anchor ) {
            pix.x += anchor.x;
            pix.y += anchor.y;
        }
        this.container.style.zIndex = 10000;
        this.container.style.top  = pix.y + "px";
        this.container.style.left = pix.x + "px";
    }
}

TemplatedPopup.prototype.setupInfoWindow = function(node, opts) {
    debug("TemplatedPopup.setupInfoWindow()");
    if ( node && node.content && this.attachPoint["content"] ) {
        var c = this.attachPoint["content"];
        if ( typeof node.content != "object" ) {
            debug("Doing innerHTML replace (node is not an object)");
            c.innerHTML = node.content;
        }
        else if ( c.parentNode ) {
            if ( !node.content.tagName ) debug("No tag name... probably broken.");
            debug("Replacing content attribute... ");
            for ( var j = 0; j < c.attributes.length; j++ )
                node.content.setAttribute(c.attributes[j].name, c.attributes[j].value);
            c.parentNode.replaceChild(node.content, c);
            this.attachPoint["content"] = node.content;
        }
        try { c.style.display = ""; } catch(e) { alert("Can't set style on C: " + c); }
    }
    else if ( this.attachPoint["content"] ) {
        this.attachPoint["content"].style.display = "none";
    }

    if ( node && node.commentData && this.attachPoint["comments"] ) {
        var c = this.attachPoint["comments"];
        if ( c.tagName.toUpperCase() != "UL" ) {
            var ul = document.createElement("UL");
            ul.className = "popupCommentListStyle";
            c.parentNode.replaceChild(ul, c);
            for ( var j = 0; j < c.attributes.length; j++ )
                ul.setAttribute(c.attributes[j].name, c.attributes[j].value);
            this.attachPoint["comments"] = ul;
            c = ul;
        }
        generateCommentList(ul, node.commentData);
        this.attachPoint["comments"].style.display = "";
    }
    else if ( this.attachPoint["comments"] ) {
        this.attachPoint["comments"].style.display = "none";
    }

    if ( node && node.movieURL && this.attachPoint["movie"] ) {
        var movie  = node.movieURL;
        var width  = node.movieWidth;
        var height = node.movieHeight;

        this.attachPoint["movie"].innerHTML =
            "<object classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" codebase=\"http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0\" width=\"" + width + "\" height=\"" + height + "\" title=\"race\">" +
            "<param name=\"movie\" value=\"" + movie + "\" />" +
            "<param name=\"quality\" value=\"high\" />" +
            "<embed src=\"" + movie + "\" quality=\"high\" pluginspage=\"http://www.macromedia.com/go/getflashplayer\" type=\"application/x-shockwave-flash\" width=\"" + width + "\" height=\"" + height + "\"></embed>" +
            "</object>";
        this.attachPoint["movie"].style.display = "";
    }
    else if ( this.attachPoint["movie"] ) {
        this.attachPoint["movie"].style.display = "none";
    }

    if ( opts && opts.order && this.attachPoint["navControl"] ) {
        var c = this.attachPoint["navControl"];
        var navControl = generatePagination(this.map, opts.order);
        for ( var j = 0; j < c.attributes.length; j++ )
            navControl.setAttribute(c.attributes[j].name, c.attributes[j].value);
        c.parentNode.replaceChild(navControl, c);
        this.attachPoint["navControl"] = navControl;
        this.attachPoint["navControl"].style.display = "";
    }
    else if ( this.attachPoint["navControl"] ) {
        this.attachPoint["navControl"].style.display = "none";
    }
}

TemplatedPopup.prototype.openInfoWindow = function(point, node, opts) {
try {
    this.setupInfoWindow(node, opts);
    if ( node && this.attachPoint["tabControl"] ) {
        this.attachPoint["tabControl"].style.display = "none";
    }
} catch(e) { alert(e); }
    debug("Done, positioning window and showing it.");
    this.positionContainer(point, opts ? opts.anchorOffset : null);
    this.show();
}

TemplatedPopup.prototype.switchTabs = function(tabIndex) {
    if ( this.currentTabs[tabIndex] ) {
try {
        this.selectedTab = tabIndex;
        if ( this.order ) {
            this.setupInfoWindow(this.currentTabs[tabIndex],
                { "order": this.order });
        } else
            this.setupInfoWindow(this.currentTabs[tabIndex]);
        this.setupTabSwitch(tabIndex);
} catch(e) { alert(e); }
    } else {
        debug("Can't switch tab: " + tabIndex + " does not exist in stack.");
    }
}

TemplatedPopup.prototype.setupTabSwitch = function(selectedtab) {
    var tabs = this.currentTabs;
    if ( this.attachPoint["tabControl"] ) {
        var _this = this;
        var c = this.attachPoint["tabControl"];
        if ( c.tagName.toUpperCase() != "UL" ) {
            var ul = document.createElement("ul");
            for ( var i = 0; i < c.attributes.length; i++ )
                ul.setAttribute(c.attributes[i].name, c.attributes[i].value);
            c.parentNode.replaceChild(ul, c);
            c = ul;
        }
        /* Get rid of all children. */
        while ( c.childNodes.length > 0 )
            c.removeChild(c.childNodes[0]);
        for ( var i = 0; i < tabs.length; i++ ) {
            var li = document.createElement("li");
            var a  = document.createElement("a");
            a.appendChild(
                document.createTextNode(tabs[i].label || ("Tab " + (i+1))));
            a.href = "javascript:void(" + i + ")";
            GEvent.addDomListener(a, "click", this.tabSwitchClosure(i));
            li.appendChild(a);
            c.appendChild(li);
        }
        this.attachPoint["tabControl"].style.display = "";
    } else {
        debug("Opening a templated window with tabs, but no tab attach point exists.");
    }
}

TemplatedPopup.prototype.openInfoWindowTabs = function(point, tabs, opts) {
    this.selectedTab = 0;
    this.currentTabs = tabs;
    if ( opts.order )
        this.order = opts.order;
    this.setupInfoWindow(tabs[0], opts);
    this.setupTabSwitch(0);

    this.positionContainer(point, opts ? opts.anchorOffset : null);
    this.show(point);
    return this;
}

TemplatedPopup.prototype.tabSwitchClosure = function(tab) {
    var _this = this;
    return function() { var i = tab; tab = null; _this.switchTabs(i); }
}

/*
 * Custom Helper Functions
*/

function generateCommentList(list, data) {
    debug("We have " + data.length + " comments to display.");
try {
    for ( var i = 0; i < data.length; i++ ) {
        var li = document.createElement("li");

        var postedBy   = document.createElement("span");
        postedBy.className = "commentAuthor";
        postedBy.appendChild(
            document.createTextNode(
                (data[i].getAttribute("by") || "Unknown User")));

        var postedDate = document.createElement("span");
        postedDate.className = "commentPostDate";
        postedDate.appendChild(
            document.createTextNode(
                " " + (data[i].getAttribute("date") || "") + ": "));
        var subject = null;
        if ( data[i].getAttribute("subject") ) {
            subject = document.createElement("p");
            subject.className = "commentSubject";
            subject.appendChild(
                document.createTextNode(
                    data[i].getAttribute("subject") || "[no subject]"));
        }
        var body = document.createElement("span");
        body.className = "commentPostBody";
        body.innerHTML = GXml.value(data[i]);
        if ( subject )
            li.appendChild(subject);
        li.appendChild(postedBy);
        li.appendChild(postedDate);
        li.appendChild(body);

        list.appendChild(li);
    }
}catch(e){debug(e);}
}

function generatePagination(map, order) {
    var control = document.createElement("div");
    control.className = "popupOrderControl";
    var prevLink = document.createElement("a");
    prevLink.href = "javascript:void(" + order + ")";
/* FIXME (Well, fix google maps)
    GEvent.addDomListener(prevLink, "click", function() {
        try {
        debug("Going to: " + (order - 1));
        GEvent.trigger(map, "goto", order-1, -1)
        } catch(e) { alert(e); }
    } );
*/
    prevLink.onclick = function() {
        GEvent.trigger(map, "goto", order-1, -1);
    };
    prevLink.appendChild(document.createTextNode(""));
    var nextLink = document.createElement("a");
    nextLink.href = "javascript:void(" + order + ")";
    nextLink.appendChild(document.createTextNode("NEXT LOCATION >"));
/* FIXME (Well, fix google maps)
    GEvent.addDomListener(nextLink, "click", function() {
        try {
        debug("Going to: " + (order + 1));
        GEvent.trigger(map, "goto", order+1, 1)
        } catch(e) { alert(e); }
    } );
*/
    nextLink.onclick = function() {
        GEvent.trigger(map, "goto", order+1, 1);
    };
    var separator = document.createTextNode("");
    control.appendChild(prevLink);
    control.appendChild(separator);
    control.appendChild(nextLink);
    return control;
}

/*******************************************************************************
 * Helper Functions: Imported public domain sources                            *
 ******************************************************************************/

/*
 * These functions are taken from the dojo toolkit, as it provides the best
 * cross-platform sizing model.  See http://www.dojotoolkit.org for mroe details
*/
function sumAncestorProperties(node, typeScroll) {
    node = dojo.byId(node);
    if (!node) { return 0; }

    var retVal = 0;
    while (node) {
        var val = node[prop];
        if (val) {
            retVal += val - 0;
        }
        node = node.parentNode;
    }
    return retVal;
}

function getScrollTop() {
    return document.documentElement.scrollTop || document.body.scrollTop || 0;
}

function getScrollLeft() {
    return document.documentElement.scrollLeft || document.body.scrollLeft || 0;
}

function getTotalOffset(element, type, includeScroll) {
    var node;
    if ( typeof element == "object" && element.style )
        node = element;
    else if ( document.getElementById(element) )
        node = document.getElementById(element);
    var typeStr = (type=="top") ? "offsetTop" : "offsetLeft";
    var typeScroll = (type=="top") ? "scrollTop" : "scrollLeft";

    var coord = (type=="top") ? "y" : "x";
    var offset = 0;
    if(node["offsetParent"]){
        var endNode;
        /* in Safari, if the node is an absolutly positioned child of the body
         * and the body has a margin the offset of the child and the body
         * contain the body's margins, so we need to end at the body
        */
        if ( navigator.userAgent.indexOf("Safari") >= 0 
            && node.style.getPropertyValue("position") == "absolute"
            && node.parentNode == document.body)
        {
            endNode = document.body;
        } else {
            endNode = document.body.parentNode;
        }

        if(includeScroll && node.parentNode != document.body) {
            offset -= sumAncestorProperties(node, typeScroll);
        }
        // FIXME: this is known not to work sometimes on IE 5.x since nodes
        // sometimes need to be "tickled" before they will display their
        // offset correctly
        do {
            var n = node[typeStr];
            offset += isNaN(n) ? 0 : n;
            node = node.offsetParent;
        } while (node != endNode && node != null);
    }else if(node[coord]){
        var n = node[coord];
        offset += isNaN(n) ? 0 : n;
    }

    // Account for any document scrolling
    //dojo.debug("Before: "+offset);
    offset += (type=="top") ? getScrollTop() : getScrollLeft();
    //dojo.debug("After: "+offset);
    return offset;
}

if ( typeof GDownloadUrl == "undefined" ) {
    GDownloadUrl = function(url, completeFn) {
        var req = false;
        if(window.XMLHttpRequest) {
            try {
                req = new XMLHttpRequest();
            } catch(e) {
                req = false;
            }
        } else if ( window.ActiveXObject ) {
            try {
                req = new ActiveXObject("Msxml2.XMLHTTP");
            } catch(e) {
                try {
                    req = new ActiveXObject("Microsoft.XMLHTTP");
                } catch(e) { req = false; }
            }
        }
        if ( req ) {
            req.onreadystatechange = function() {
                if ( req.readyState == 4 ) {
                    var statusCode = req.status;
                    completeFn({
                            "responseText": req.responseText,
                            "responseXML":  req.responseXML,
                            "status":       req.status
                        });
                }
            };
            req.open("GET", url, true);
            req.send("");
        }
    }
}

function ajaxSubmitForm(formElement, url, completeFn, errorFn) {
    var formObj = {
        "from":      formElement.from.value,
        "from_addr": formElement.from_addr.value,
        "to":        formElement.to.value,
        "to_addr":   formElement.to_addr.value
    };
    var qStr = new Array();
    for ( var i in formObj ) {
        if ( typeof i == "undefined" || formObj[i].length < 1 ) {
            errorFn("Missing fields, please make sure all fields are populated");
            return false;
        }
        qStr.push(i + "=" + formObj[i]);
    }
    if ( url.indexOf("?") >= 0 )
        url = url + "&" + qStr.join("&");
    else
        url = url + "?" + qStr.join("&");
    GDownloadUrl(url, completeFn);
}

function getFlashMovieObject(movieName)
{
  if (window.document[movieName]) 
  {
      return window.document[movieName];
  }
  if (navigator.appName.indexOf("Microsoft Internet")==-1)
  {
    if (document.embeds && document.embeds[movieName])
      return document.embeds[movieName]; 
  }
  else // if (navigator.appName.indexOf("Microsoft Internet")!=-1)
  {
    return document.getElementById(movieName);
  }
  return false;
}

var debugLog=false;
var bkc='#FFDDDD';
var messagesLog='';
function A(O){
  return;
 	if(bkc=='#FFDDDD'){
		bkc='#DDFFDD';
	}
	else{
		bkc='#FFDDDD';
	}
	
	if(debugLog){
	}
	else{			
		debugLog=window.open('about:blank','new',"menubar=0,resizable=1,width=170,height=700,scrollbars=yes "		);	
		debugLog.moveTo(850,0);
		messagesLog+='<title>JAVASCRIPT MESSAGE LOG</title>' ;			
	}
	messagesLog+='<font style="font-family:Verdana,Arial,Helvetica;font-size:10px;background:'+bkc+'">'+O+'</font><br>';
	debugLog.document.write(messagesLog);
	debugLog.document.close();
}

var req=false;
function loadXMLDoc(url,callbk){
	req = false;
    // branch for native XMLHttpRequest object
    if(window.XMLHttpRequest) {
    	try {
			req = new XMLHttpRequest();
        } catch(e) {
			req = false;
        }
    // branch for IE/Windows ActiveX version
    } else if(window.ActiveXObject) {
       	try {
        	req = new ActiveXObject("Msxml2.XMLHTTP");
      	} catch(e) {
        	try {
          		req = new ActiveXObject("Microsoft.XMLHTTP");
        	} catch(e) {
          		req = false;
        	}
		}
    }
	if(req) {

		req.onreadystatechange = function() {
		    // only if req shows "loaded"
		    if (req.readyState == 4) {
		        // only if "OK"
		        if (req.status == 200) {
		            // ...processing statements go here...
		            var s = escape(req.responseText);s=s.substring(0,10);
		            A('XML loaded successfully : '+s+'...');
		            callbk(req.responseXML,req.responseText);
		        } else {
		            alert("There was a problem retrieving the XML data:\n" +
		                req.statusText);
		        }
		    }
		};
		req.open("GET", url, true);
		req.send("");
	}
}

function puladecal(){
	    var FPMO=getFlashMovieObject("playback");
	if(FPMO){
		 alert(FPMO.Playing     );
	} 
}
function opm(x){
 if(!map.map){
  map.hideSplashScreen();
  setTimeout("opm("+x+")",2000);
	return;
}
		activeBuuble=x;
        var marker = map.orderedMarkers[ x];
        GEvent.trigger(marker.marker, "click", marker.marker);
	 
}
