/* ----------------------------------------------------------------------------------------------
# mapUtils has the following function:
# 1) Custom Icon configuration
# 2) Custom slider and pan control
# 3) Custom Marker & Info window
# 4) Clustering function for the google map
# 5) CustomMarkerUtils
---------------------------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------------------------------
#  1)  Custom Slider and pan Control
---------------------------------------------------------------------------------------------- */

// CONFIGURATION FOR THE MAP
var mapCONFIG = {
    gIcons: [],
    gIconImages: [],
    initialize: function(){
        // set up pulte icons for the 3 sites + marker
        var mapIcon = new GIcon();
        mapIcon.shadow = "/images/global/googleIcon-flagShadow.png";
        mapIcon.iconSize = new GSize(16, 31);
        mapIcon.shadowSize = new GSize(35, 32);
        mapIcon.iconAnchor = new GPoint(8, 31);
        mapIcon.infoWindowAnchor = new GPoint(16, 10);
        mapIcon.printShadow = "/images/global/googleIcon-flagShadow.gif";
        // pulte flag icon
        this.gIcons["pulte"] = new GIcon(mapIcon);
        this.gIcons["pulte"].image = "/images/Pulte/googleIcon-flag.png";
        this.gIcons["pulte"].printImage = "/images/Pulte/googleIcon-flag.gif";
        this.gIcons["pulte"].mozPrintImage = "/images/Pulte/googleIcon-flag.gif";
        // coming-soon flag icon
        this.gIcons["pulteSoon"] = new GIcon(mapIcon);
        this.gIcons["pulteSoon"].image = "/images/Pulte/googleIcon-flagSoon.png";
        this.gIcons["pulteSoon"].printImage = "/images/Pulte/googleIcon-flagSoon.gif";
        this.gIcons["pulteSoon"].mozPrintImage = "/images/Pulte/googleIcon-flagSoon.gif";
        // delwebb flag icon
        this.gIcons["delwebb"] = new GIcon(mapIcon);
        this.gIcons["delwebb"].image = "/images/DelWebb/googleIcon-flag.png";
        this.gIcons["delwebb"].printImage = "/images/DelWebb/googleIcon-flag.gif";
        this.gIcons["delwebb"].mozPrintImage = "/images/DelWebb/googleIcon-flag.gif";
        // coming-soon flag icon
        this.gIcons["delwebbSoon"] = new GIcon(mapIcon);
        this.gIcons["delwebbSoon"].image = "/images/DelWebb/googleIcon-flagSoon.png";
        this.gIcons["delwebbSoon"].printImage = "/images/DelWebb/googleIcon-flagSoon.gif";
        this.gIcons["delwebbSoon"].mozPrintImage = "/images/DelWebb/googleIcon-flagSoon.gif";
        // divosta flag icon
        this.gIcons["divosta"] = new GIcon(mapIcon);
        this.gIcons["divosta"].image = "/images/DiVosta/googleIcon-flag.png";
        this.gIcons["divosta"].printImage = "/images/DiVosta/googleIcon-flag.gif";
        this.gIcons["divosta"].mozPrintImage = "/images/DiVosta/googleIcon-flag.gif";
        // coming-soon flag icon
        this.gIcons["divostaSoon"] = new GIcon(mapIcon);
        this.gIcons["divostaSoon"].image = "/images/DiVosta/googleIcon-flagSoon.png";
        this.gIcons["divostaSoon"].printImage = "/images/DiVosta/googleIcon-flagSoon.gif";
        this.gIcons["divostaSoon"].mozPrintImage = "/images/DiVosta/googleIcon-flagSoon.gif";
        // centex flag icon
        this.gIcons["centex"] = new GIcon(mapIcon);
        this.gIcons["centex"].image = "/images/Centex/googleIcon-flag.png";
        this.gIcons["centex"].printImage = "/images/Centex/googleIcon-flag.gif";
        this.gIcons["centex"].mozPrintImage = "/images/Centex/googleIcon-flag.gif";
        // centex coming-soon flag icon
        this.gIcons["centexSoon"] = new GIcon(mapIcon);
        this.gIcons["centexSoon"].image = "/images/Centex/googleIcon-flagSoon.png";
        this.gIcons["centexSoon"].printImage = "/images/Centex/googleIcon-flagSoon.gif";
        this.gIcons["centexSoon"].mozPrintImage = "/images/Centex/googleIcon-flagSoon.gif";
        // marker icon
        this.gIcons["marker"] = new GIcon();
        this.gIcons["marker"].image = "/images/global/googleIcon-marker.png";
        this.gIcons["marker"].shadow = "/images/global/googleIcon-markerShadow.png";
        this.gIcons["marker"].iconSize = new GSize(20, 32);
        this.gIcons["marker"].shadowSize = new GSize(47, 34);
        this.gIcons["marker"].iconAnchor = new GPoint(10, 32);
        this.gIcons["marker"].infoWindowAnchor = new GPoint(20, 10);
        this.gIcons["marker"].printImage = "/images/global/googleIcon-marker.gif";
        this.gIcons["marker"].mozPrintImage = "/images/global/googleIcon-marker.gif";
        this.gIcons["marker"].printShadow = "/images/global/googleIcon-markerShadow.gif";
        // on images
        this.gIconImages["pulte"] = {imageOn: "/images/Pulte/googleIcon-flagOn.png", imageOff: "/images/Pulte/googleIcon-flag.png"};
        this.gIconImages["pulteSoon"] = {imageOn: "/images/Pulte/googleIcon-flagOn.png", imageOff: "/images/Pulte/googleIcon-flagSoon.png"};
        this.gIconImages["delwebb"] = {imageOn: "/images/DelWebb/googleIcon-flagOn.png", imageOff:"/images/DelWebb/googleIcon-flag.png"};
        this.gIconImages["delwebbSoon"] = {imageOn: "/images/DelWebb/googleIcon-flagOn.png", imageOff:"/images/DelWebb/googleIcon-flagSoon.png"};
        this.gIconImages["divosta"] = {imageOn: "/images/DiVosta/googleIcon-flagOn.png", imageOff:"/images/DiVosta/googleIcon-flag.png"};
        this.gIconImages["divostaSoon"] = {imageOn: "/images/DiVosta/googleIcon-flagOn.png", imageOff:"/images/DiVosta/googleIcon-flagSoon.png"};
        this.gIconImages["centex"] = {imageOn: "/images/Centex/googleIcon-flagOn.png", imageOff:"/images/Centex/googleIcon-flag.png"};
        this.gIconImages["centexSoon"] = {imageOn: "/images/Centex/googleIcon-flagOn.png", imageOff:"/images/Centex/googleIcon-flagSoon.png"};
        this.gIconImages["marker"] = {imageOn: "/images/global/googleIcon-markerOn.png", imageOff:"/images/global/googleIcon-marker.png"};


        // centex custom marker
        this.gIcons["centexMarker"] = new GIcon(this.gIcons["marker"]);
        this.gIcons["centexMarker"].image = "/images/Centex/googleIcon-marker.png";
        this.gIconImages["centexMarker"] = {imageOn: "/images/Centex/googleIcon-markerOn.png", imageOff:"/images/Centex/googleIcon-marker.png"};

    }
};

mapCONFIG.initialize();
// end of map configuration ----------------------------------------

/* ----------------------------------------------------------------------------------------------
#  2)  Custom Slider and pan Control
---------------------------------------------------------------------------------------------- */

// GLOBAL VARIABLES FOR MAPSLIDER CONTROL FUNCTION

var SLIDERCONFIG = {
    maxZoom: 16,
    maxZoomLevel: 18,
    topConstraint: 0,
    btmConstraint: 122,
    scaleFactor: 0.12,
    posFactor: 8.133,
    zoomTextNode: [{zoomName: "Street", zoomStyleId: "zStreet", zoomIndex: 17},
            {zoomName: "Neighborhood", zoomStyleId: "zNeighborhood", zoomIndex: 16},
            {zoomName: "City", zoomStyleId: "zCity", zoomIndex: 14},
            {zoomName: "County/Metro", zoomStyleId: "zCounty", zoomIndex: 12},
            {zoomName: "Region", zoomStyleId: "zRegion", zoomIndex: 9},
            {zoomName: "State", zoomStyleId: "zState", zoomIndex: 6},
            {zoomName: "Country", zoomStyleId: "zCountry", zoomIndex: 4}
            ],
    zoomDirectionNode: [ {zoomName: "", zoomURL: ""},
            {zoomName: "Pan up", zoomURL: "javascript:map.panDirection(0,1);", zoomId: "panUp"},
            {zoomName: "", zoomURL: ""},
            {zoomName: "Pan left", zoomURL: "javascript:map.panDirection(1,0);", zoomId: "panLeft"},
            {zoomName: "Return to last result", zoomURL: "javascript:map.returnToSavedPosition();", zoomId: "panReset"},
            {zoomName: "Pan right", zoomURL: "javascript:map.panDirection(-1,0);", zoomId: "panRite"},
            {zoomName: "", zoomURL: ""},
            {zoomName: "Pan down", zoomURL: "javascript:map.panDirection(0,-1);", zoomId: "panDown"},
            {zoomName: "", zoomURL: ""}
            ],
    zoomInAndOutNode: [ {zoomStyle: "zoomInControl", zoomTitle: "Zoom in", zoomURL: "javascript:mapZoomIn();", btnStyle: "zoomInBtn"},
            {zoomStyle: "zoomOutControl", zoomTitle: "Zoom Out", zoomURL: "javascript:map.zoomOut();", btnStyle: "zoomOutBtn"}
        ],
    zoomButtonStyle: "zoomButton",
    spaceImg: "/images/global/spacer.gif"
};

var mapSlider;

// making sure we are not zoom in to a level taht does not have image
function mapZoomIn(){
    var maxRes = G_NORMAL_MAP.getTileLayers()[0].maxResolution();
    if(map.getZoom() < maxRes){
        map.zoomIn();
    }
}

// ----------------------------------------------------------------------------------------------

// MAPSLIDERCONTROL GOOGLE CONTROL

function MapSliderControl() {};
MapSliderControl.prototype = new GControl();

// This function positions the slider to match the specified zoom level ==
MapSliderControl.prototype.setSlider = function(zoom) {
    var z = SLIDERCONFIG["maxZoomLevel"] - zoom;
    mapSlider.setPositionByZoom(z);
}

MapSliderControl.prototype.setZoom = function(zoom){
    var maxRes = G_NORMAL_MAP.getTileLayers()[0].maxResolution();
    if(zoom > maxRes){
        zoom = maxRes;
    }
    this.map.setZoom(zoom);
}
MapSliderControl.prototype.zoomIn = function(){

}
// Initialize the MapSlider google
MapSliderControl.prototype.initialize = function(map) {
    // obtain Function Closure on a reference to "this"
    var that=this;
    // store a reference to the map so that we can call setZoom() on it
    this.map = map;

    var navContainer = this.createZoomHTML();

    // create the YUI Slider
    mapSlider = YAHOO.widget.Slider.getVertSlider("map-slider-bg", "map-slider-thumb", SLIDERCONFIG["topConstraint"], SLIDERCONFIG["btmConstraint"]);
    mapSlider.animate = false;
    mapSlider.keyIncrement = SLIDERCONFIG["posFactor"];
    mapSlider.getRealValue = function() {
        return Math.round(this.getValue() / SLIDERCONFIG["posFactor"]);
    }

    // create a function to return the scaled value from the slider
    mapSlider.setPositionByZoom = function(zoom){
        var pos = Math.round(zoom * SLIDERCONFIG["posFactor"]);
        try {this.setValue(pos);} catch(err) {}
        return true;
    }

    // attach the control to the map
    map.getContainer().appendChild(navContainer);

    // Listen for other things changing the zoom level and move the slider
    GEvent.addListener(map, "zoomend", function(a,b) {that.setSlider(b)});

    mapSlider.subscribe("change", function(offsetFromStart) {
        var zoomLevel = SLIDERCONFIG["maxZoomLevel"] - mapSlider.getRealValue();
        that.setZoom(zoomLevel);
    });

    return navContainer;
};

// create HTML element for the custom slider control
MapSliderControl.prototype.createZoomHTML = function(){
    var navContainer = document.createElement("ul");
    navContainer.id = "mapZoomNav";
    var li = document.createElement("li");

    // create the background graphic as a <div> containing an image
    var container = document.createElement("div");
    container.className = "googleZoomControl";

    // create direction control panel and add to container
    container.appendChild(this.createDirectionZoom());

    // create zoom In Button and add to container
    container.appendChild(this.createZoomButton(0));

    // create zoom Slider background and add to container
    container.appendChild(this.createZoomSlider());

    // create zoom out btn and add to container
    container.appendChild(this.createZoomButton(1));

    li.appendChild(container);
    navContainer.appendChild(li);

    return navContainer;

};

// create HTML element for text zoom menu
MapSliderControl.prototype.createTextZoomMenu = function(){
    var container = document.createElement("ul");
    var li = document.createElement("li");
    li.id = "mapTextZoom";
    for(var i=0; i < SLIDERCONFIG["zoomTextNode"].length; i++){
        var temp_a = document.createElement("a");
        temp_a.className = SLIDERCONFIG["zoomButtonStyle"];
        temp_a.appendChild(document.createTextNode(SLIDERCONFIG["zoomTextNode"][i].zoomName));
        temp_a.href="#";
        temp_a.title = SLIDERCONFIG["zoomTextNode"][i].zoomName;
        temp_a.id = SLIDERCONFIG["zoomTextNode"][i].zoomStyleId;
        temp_a.zoomIndex =SLIDERCONFIG["zoomTextNode"][i].zoomIndex;
        temp_a.onclick = function(){
            map.setZoom(this.zoomIndex);
        }
        li.appendChild(temp_a);
    }
    container.appendChild(li);
    return container;
};

// create HTML element for direction zoom
MapSliderControl.prototype.createDirectionZoom = function(){

    var dirDiv = document.createElement("div");
    dirDiv.className = "directionControl";
    var temp_div, temp_span, temp_a, temp_txt

    for(var i = 0; i < SLIDERCONFIG["zoomDirectionNode"].length; i++){
        if(i%3 == 0){
            if(i > 0){dirDiv.appendChild(temp_div);}
            temp_div = document.createElement("div");
            temp_div.className = "dirRow";
        }
        temp_span = document.createElement("span");
        if((i+1)%3 == 0){
            temp_span.className = "last";
        }
        if(SLIDERCONFIG["zoomDirectionNode"][i].zoomName == ""){
            temp_span.appendChild(document.createTextNode(" "));
        } else {
            temp_a = document.createElement("a");
            temp_a.href = SLIDERCONFIG["zoomDirectionNode"][i].zoomURL;
            temp_a.title = SLIDERCONFIG["zoomDirectionNode"][i].zoomName;
            temp_a.id = SLIDERCONFIG["zoomDirectionNode"][i].zoomId;
            temp_txt = document.createElement("em");
            temp_txt.appendChild(document.createTextNode(SLIDERCONFIG["zoomDirectionNode"][i].zoomName));
            temp_a.appendChild(temp_txt);
            temp_span.appendChild(temp_a);
        }
        temp_div.appendChild(temp_span);
    }

    dirDiv.appendChild(temp_div);
    return dirDiv;

};

// create HTML element for Zoom in and zoom out button
MapSliderControl.prototype.createZoomButton = function(zIndex){

    var temp_img, temp_a;
    var zoomDiv = document.createElement("div");
    zoomDiv.className = SLIDERCONFIG["zoomInAndOutNode"][zIndex].zoomStyle;
    temp_a = document.createElement("a");
    temp_a.title = SLIDERCONFIG["zoomInAndOutNode"][zIndex].zoomTitle;
    temp_a.href = SLIDERCONFIG["zoomInAndOutNode"][zIndex].zoomURL;
    temp_img = document.createElement("img");
    temp_img.className = SLIDERCONFIG["zoomInAndOutNode"][zIndex].btnStyle;
    temp_img.src = SLIDERCONFIG["spaceImg"];
    temp_img.width = "19";
    temp_img.height = "19";
    temp_a.appendChild(temp_img);
    zoomDiv.appendChild(temp_a);

    return zoomDiv;

};

// create the HTML element for the slider
MapSliderControl.prototype.createZoomSlider = function(){

    var zoomSliderDiv = document.createElement("div");
    zoomSliderDiv.className = "zoomSliderControl";

    var zoomBground = document.createElement("div");
    zoomBground.className = "sliderBground";
    zoomBground.id = "map-slider-bg";

    var knob = document.createElement("div");
    knob.className = "zoomSlider";
    knob.id = "map-slider-thumb";
    zoomBground.appendChild(knob);

    zoomSliderDiv.appendChild(zoomBground);

    return zoomSliderDiv;
};

//Set the default position for the MapSlider Control on the map
MapSliderControl.prototype.getDefaultPosition = function() {
return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(7, 7));
}

/* ---------------------------------------------------------------------------------------------------------------------
#  3)  Custom Marker and Info window
----------------------------------------------------------------------------------------------------------------------*/

/*
 PdMarker

 Purpose: extends Google Map API GMap and GMarker (hover effects, image swapping, moving)
 Details: http://www.pixeldevelopment.com/pdmarker.asp
 Updated: [see getPdMarkerRevisionInfo]
 Author:  Peter Jones
 Notes:   Relies on undocumented features of the Google Map API which may change.
	    Based on my own PJToolTip and ideas from GxMarker, TLabel and the Google Maps API forum.

 Contact http://www.pixeldevelopment.com for your custom Google Map needs
*/
/*
    Added label function to PdMarker
*/

function getPdMarkerRevisionInfo() {
var cr = "<br/>";
var s =
"2.03  10/02/07 - fixed zindex bug (setMarkerZIndex, topMarkerZIndex)" + cr +
"2.02  05/22/07 - fixed minor issues (blink, initDetailWin)" + cr +
"2.01  04/29/07 - improved left hand side detail window positioning, uses new Google setImage &amp; show " +
"routines for added reliability, fixed zoomToMarkers for single marker case." + cr +
"2.00  04/22/07 - fix for setImage when using Explorer 7." + cr +
"1.99f 07/09/06 - zoomToMarkers now takes into account markers not displayed." + cr +
"1.99e 05/05/06 - fixed zoomed tooltip positioning &amp; non-centered marker graphics." + cr +
"1.99d 05/01/06 - fixed display &amp; blink when defining .transparent." + cr +
"1.99c 04/25/06 - added display and blink." + cr +
"1.99b 04/21/06 - added 'Powered By' version &amp; marker count display." + cr +
"1.99a 04/18/06 - revised for Google Maps API Version 2, GMap2 required." + cr +
"0.99c 01/30/06 - added setDetailWinClass and resetDetailWinClass." + cr +
"0.99a 10/12/05 - now handles maps in containers with undefined widths" + cr +
"define a div with id 'pdmarkerwork' to reduce flicker" + cr +
"0.99  10/03/05 - added setImageEnabled, allowLeftTooltips (global)" + cr +
"0.98  09/30/05 - fixed zoomToMarkers" + cr +
"0.97  09/24/05 - added setHoverImage, setShowDetailOnClick, setDetailWinHTML, showDetailWin, closeDetailWin" + cr +
"0.96  09/22/05 - added setTooltipHiding, getTooltipHiding" + cr +
"0.95  09/20/05 - handle zoom for lingering tooltips mouseOutEnabled(false) " +
		   "disables setImage and restoreImage" + cr +
"0.94  09/20/05 - added setTooltipClass and resetTooltipClass" + cr +
"0.93  09/19/05 - added slopPercentage [optional] parameter to zoomToMarkers" + cr +
"0.92  09/18/05 - added getMouseOutEnabled, setMouseOutEnabled" + cr +
"0.91  09/17/05 - fixed setOpacity";
return s;
}

function getPdMarkerVersion() {
	return getPdMarkerRevisionInfo().substring(0,15);
}

function getPdMarkerShortVersion() {
	return getPdMarkerRevisionInfo().substring(0,5);
}

var APIkey = "";

function getGoogleMapsVersion() {
	var i, a, b, c;
	var v = "unknown";

	if (document.getElementsByTagName)
		for(i=0; (a = document.getElementsByTagName("script")[i]); i++)
			if(a.getAttribute("src"))
			{
				b = a.getAttribute("src");
				c = b.indexOf("/mapfiles/maps"); // /mapfiles/maps
				d = b.indexOf("http://maps.google.com/maps?file=api");
				e = b.indexOf("key=");
				f = b.indexOf("/mapfiles/");
				g = b.indexOf("/maps");
				if (c > 0)
					v = parseFloat(b.substring(c+14));
				else if (f > 0)
					v = "2." + b.substring(f+10,g);
				if (d >= 0)
					if (e > 0)
						APIkey = b.substring(e+4);
			}
	return v;
}

function latLongToPixel(map,coord,zoom) {
    return map.fromLatLngToDivPixel(coord);
}


var pdMarkerExtList = [];

function PdMarkerAddToExtList(marker) {
    if(PdMarkerFindInExtList(marker.internalId)) return;
    pdMarkerExtList.push(marker);
}

function PdMarkerRemoveFromExtList(id) {
	for (var i=0; i<pdMarkerExtList.length; i++)
		if (pdMarkerExtList[i].internalId == id)
			pdMarkerExtList.splice(i,1);
}

function PdMarkerFindInExtList(id) {
	for (var i=0; i<pdMarkerExtList.length; i++)
		if (pdMarkerExtList[i].internalId == id)
			return pdMarkerExtList[i];
}

function PdMarkerClose(id) {
    for (var i=0; i<pdMarkerExtList.length; i++)
		if (pdMarkerExtList[i].internalId == id)
			{
                pdMarkerExtList[i].closeDetailWin();
				pdMarkerExtList[i].isClicked = false;
                pdMarkerExtList.splice(i,1);
			}
}

function PdMarkerBlinkOnOff(id) {
	var marker = PdMarkerFindInExtList(id);
	if (marker)
	{
		if (!marker.blinking) return;
		marker.blinkOn = !marker.blinkOn;
		marker.display(marker.blinkOn);
		setTimeout("PdMarkerBlinkOnOff(" + marker.getId() + ");", marker.blinkSpeed);
	}
}

// GMap extension for walking through PdMarker list
// Note: some overlays are not markers, some may not be PdMarkers

function isPdMarker(a) {
	if (a.isMarker)
		return true;
	return false;
}

function getPdMarkerCount(a) {
	if (a.pdMarkers)
		return a.pdMarkers.length;
	return 0;
}

GMap2.prototype.getMarkerById = function(id) {
	var count = getPdMarkerCount(this);
	for (var i = 0; i < count; i++)
		if (isPdMarker(this.pdMarkers[i]))
			if (this.pdMarkers[i].internalId == id)
			{
				this.cursor = i;
				return this.pdMarkers[i];
			}
	return null;
}

GMap2.prototype.getFirstMarker = function() {
	var count = getPdMarkerCount(this);
	for (var i = 0; i < count; i++)
		if (isPdMarker(this.pdMarkers[i]))
		{
			this.cursor = i;
			return this.pdMarkers[i];
		}
	return null;
}

GMap2.prototype.getNextMarker = function() {
	var count = getPdMarkerCount(this);
	if (count > 0)
		if (this.cursor >= 0)
			for (var i = this.cursor+1; i < count; i++)
				if (isPdMarker(this.pdMarkers[i]))
				{
					this.cursor = i;
					return this.pdMarkers[i];
				}
	return null;
}

GMap2.prototype.getNthMarker = function(nTh) {
	var count = getPdMarkerCount(this);
	for (var i = 0; i < count; i++)
		if (isPdMarker(this.pdMarkers[i]))
		{
			nTh--;
			if (nTh == 0)
			{
				this.cursor = i;
				return this.pdMarkers[i];
			}
		}
	return null;
}

GMap2.prototype.getMarkerCount = function() {
	return getPdMarkerCount(this);
}

GMap2.prototype.boxMap = function(center, span) {
	var spec = this.spec;
	var zoom = spec.getLowestZoomLevel(center, span, this.viewSize);
	this.centerAndZoom(new GPoint(center.x, center.y), zoom);
}

GMap2.prototype.zoomToMarkers = function(slopPercentage, heightOffsetPct) {
	var count = 0;
	var thePoint, x, y, minX, maxX, minY, maxY, span;
	var marker = this.getFirstMarker();
	while (marker != null)
	{
		if (!marker.isHidden())
		{
			thePoint = marker.getPoint();
			x = thePoint.lat(); y = thePoint.lng();
			if (count == 0)
			{
				minX = x; maxX = x; minY = y; maxY = y;
			}
			else
			{
				if (x < minX) minX = x;
				if (x > maxX) maxX = x;
				if (y < minY) minY = y;
				if (y > maxY) maxY = y;
			}
			count++;
		}
		marker = this.getNextMarker();
	}
	if (count == 1)
		this.setCenter(new GLatLng(x,y), this.getZoom());
	else if (count > 1)
	{
		var center = new GLatLng((minX + maxX) / 2, (minY + maxY) / 2);
		span = new GSize(Math.abs(maxX - minX), Math.abs(maxY - minY));
		slopWid = 0;
		slopHgt = 0;
		if (typeof slopPercentage != "undefined")
		{
			slopWid = span.width * slopPercentage / 200;
			slopHgt = span.height * slopPercentage / 200;
			span.width  *= 1 + slopPercentage / 100;
			span.height *= 1 + slopPercentage / 100;
		}
		deltaHgt = 0;
		if (typeof heightOffsetPct != "undefined")
		{
			deltaHgt = span.height * heightOffsetPct / 100;
			center = new GLatLng(center.lat() + deltaHgt, center.lng());
		}
		// needs slop
		var bounds = new GLatLngBounds(new GLatLng(minX-slopHgt, minY-slopWid), new GLatLng(maxX+slopHgt, maxY+slopWid)); // sw, ne
		var zoom = this.getBoundsZoomLevel(bounds);
		this.setCenter(center, zoom);
	}
}

function shorten(x) {
	var factor = 1000000
	return Math.round(x * factor) / factor;
}

function poweredByClick(map) {
	var center = map.getCenter();
	var span = map.getBounds().toSpan();
	var zoom = map.getZoom();
	var url = "http://maps.google.com/maps?ll=" + center.lat() + "," + center.lng() + "&spn=" + shorten(span.lat()) + "," + shorten(span.lng()) + "&z=" + zoom + "&key=" + APIkey;
	document.location = url;
}

function poweredByMouseover(map) {
	var marker = map.getFirstMarker();
	var bounds = map.getBounds();
	var visibleCount = 0;
	var totalCount = 0;
	while (marker != null) {
		if (!marker.isHidden())
		{
			var point = marker.getPoint();
			if (bounds.contains(point))
				visibleCount++;
			totalCount = totalCount + 1;
		}
		marker = map.getNextMarker();
	}
	var title = map.poweredByTitle + " (" + visibleCount + " markers of " + totalCount + " visible)"
	map.poweredByObj.setAttribute("title",title);
	map.poweredByObj.setAttribute("alt",title);
}

function getPoweredBy(map) {
	try {
		var tooltip = "GMap " + getGoogleMapsVersion() + " & PdMarker " + getPdMarkerShortVersion();
		map.poweredByTitle = tooltip;
		var b = document.createElement("img");
		b.setAttribute("src","http://www.google.com/intl/en_ALL/mapfiles/transparent.gif");
		b.setAttribute("width",62);
		b.setAttribute("alt",tooltip);
		b.setAttribute("title",tooltip);
		b.setAttribute("height",30);
		b.style.display = "block";
		b.style.position = "absolute";
		b.style.left    = "2px";
		b.style.bottom  = "0px";
		b.style.width   = "62px";
		b.style.height  = "30px";
		b.style.cursor  = "pointer";
		b.style.zIndex  = 600001;
		b.onclick = function() { poweredByClick(map); };
		b.onmouseover = function() { poweredByMouseover(map); };
	      map.getPane(G_MAP_FLOAT_PANE).parentNode.parentNode.appendChild(b);
		return b;
	}
	catch (e) {
	}
	return true;
}

function setPoweredBy(map) {
	if (!map.poweredByObj) {
		getGoogleMapsVersion(); // possibly reduce IE memory leak, unchecked
		map.poweredByObj = getPoweredBy(map);
	}
}

// keep track of previsouly click marker, pass the mark as an object
var curClickedMarker;

// PdMarker code
function PdMarkerNamespace() {

var userAgent = navigator.userAgent.toLowerCase();
var n4=(document.layers);
var n6=(document.getElementById&&!document.all);
var ie=(document.all);
var o6=(userAgent.indexOf("opera") != -1);
var safari=(userAgent.indexOf("safari") != -1);
var msie  = (userAgent.indexOf("msie") != -1) && (userAgent.indexOf("opera") == -1);
var msiePre7 = false;
if (msie)
	msiePre7 = userAgent.substr(userAgent.indexOf("msie")+5,2) < 7;

var nextMarkerId = 10;
var permitLeft = true;

var icon = new GIcon();
icon.shadow = "http://www.google.com/mapfiles/shadow50.png";
icon.iconSize = new GSize(20, 34);
icon.shadowSize = new GSize(37, 34);
icon.iconAnchor = new GPoint(9, 34);
icon.infoWindowAnchor = new GPoint(9, 2);
icon.infoShadowAnchor = new GPoint(18, 25);
icon.image = "http://www.google.com/mapfiles/marker.png";

// Globals - careful of multiple maps

function PdMarker(a, b, label_opts) {
    this.inheritFrom = GMarker;
	if (typeof b == "undefined") // pmj oct 23, 2005
		b = icon;
	this.inheritFrom(a,b);
    this.pendingTitle = "";

	if (typeof b != "undefined")
		this.oldImagePath = b.image;
	else
		this.oldImagePath = "http://www.google.com/mapfiles/marker.png";

    this.internalId = nextMarkerId;
	nextMarkerId += 1;
	this.zIndexSaved = false;
	this.pendingCursor = "";
	this.percentOpacity = 100;
	this.mouseOutEnabled = true;
	this.setImageOn = true;
	this.hidingEnabled = true;
	this.showDetailOnClick = true;
	this.detailOpen = false;
	this.userData = "";
	this.displayed = true;
    this.isLabeledMarker = false;
    this.isClicked = false; // keep track if the marker is click
    this.allowLeftTooltips(false);
    this.latlng_ = a;
    this.timerId = null;
    this.mouseOverLisId = null;
    this.mouseOutListId = null;
    // added labeledMarker info
    if(typeof label_opts != "undefined"){

        this.isLabeledMarker = true;
        this.labelText_ = label_opts.labelText || "";
        this.labelClass_ = label_opts.labelClass || "LabeledMarker_markerLabel";
        this.labelOffset_ = label_opts.labelOffset || new GSize(0, 0);
        this.clickable_ = label_opts.clickable || true;
        this.labelTitle_ = label_opts.title || "";
        this.labelVisibility_  = true;
    }

}

// PdMarker.prototype = new GMarker;
PdMarker.prototype = new GMarker(new GLatLng(1, 1));


function addMarkerToMapList(map,marker) {
	try {
		if (map.pdMarkers.length) ;
	}
	catch(e) {
		map.pdMarkers = new Array();
	}
	// add to list
	map.pdMarkers.push(marker);
}

function removeMarkerFromMapList(map,marker) {
	var id = marker.internalId;
    if(map.pdMarkers && map.pdMarkers.length){
        for (var i=0; i<map.pdMarkers.length; i++){
            if (map.pdMarkers[i].internalId == id)
            {
                map.pdMarkers.splice(i,1);
                return;
            }
       }
    }
}

PdMarker.prototype.initialize = function(a) {
    if (typeof a == "GMap")
	{
		return;
	}
	addMarkerToMapList(a,this);
	try
	{
		GMarker.prototype.initialize.call(this, a);
		this.isMarker = true;
		if (this.pendingTitle.length > 0)
			this.setTitle(this.pendingTitle);
		if (this.pendingCursor.length > 0)
			this.setCursor(this.pendingCursor);

		this.map = a;
		// if it is a labeled marker
        if(this.isLabeledMarker){
            this.div_ = document.createElement("div");
            this.div_.className = this.labelClass_;
            this.div_.innerHTML = this.labelText_;
            this.div_.style.position = "absolute";
            this.div_.style.cursor = "pointer";

            this.div_.title = this.labelText_;

            this.map.getPane(G_MAP_MARKER_PANE).appendChild(this.div_);

            if (this.clickable_) {
                function newEventPassthru(obj, event) {
                    return function() { GEvent.trigger(obj, event);};
                }

                // Pass through events fired on the text div to the marker.
                var eventPassthrus = ['click', 'dblclick', 'mousedown', 'mouseup', 'mouseover', 'mouseout'];
                for(var i = 0; i < eventPassthrus.length; i++) {
                    var name = eventPassthrus[i];
                    GEvent.addDomListener(this.div_, name, newEventPassthru(this, name));
                }
            }
        }
        // end of labeledmarker special
        setPoweredBy(a);

		GEvent.bindDom(this, "mouseover", this, this.onMouseOver);
		GEvent.bindDom(this, "mouseout",  this, this.onMouseOut);
		GEvent.bindDom(this, "click",  this, this.onClick);
		GEvent.bind(this.map, "zoomend", this, this.reZoom);
	}
	catch(e) {
		alert("PdMarker initialize error: " + e);
	}
}

PdMarker.prototype.allowLeftTooltips = function(a){
	permitLeft = a;
}

PdMarker.prototype.reZoom = function(){
	var didSet = false;
	if (this.tooltipObject)
		if (this.tooltipObject.style.display == "block")
		{
			setTTPosition(this);
			didSet = true;
		}
	if (this.detailObject)
	{
		if (!didSet)
			setTTPosition(this);
	}
}

PdMarker.prototype.setId = function(id) {
	this.internalId = id;
}

PdMarker.prototype.getId = function() {
	return this.internalId;
}

PdMarker.prototype.setName = function(a) {
	this.name = a;
}

PdMarker.prototype.getName = function() {
	if (this.name)
		return this.name;
	else
		return null;
}

PdMarker.prototype.setUserData = function(a) {
	this.userData = a;
}

PdMarker.prototype.getUserData = function() {
	if (this.userData)
		return this.userData;
	else
//		return null;
		return "";
}

PdMarker.prototype.setUserData2 = function(a) {
	this.userData2 = a;
}

PdMarker.prototype.getUserData2 = function() {
	if (this.userData2)
		return this.userData2;
	else
		return "";
}

PdMarker.prototype.setImageEnabled = function(a) {
	this.setImageOn = a;
}

var PdMIN = "";
var PdMIA = "";

function PdCompPdMIN(marker) {
	if (PdMIN.length == 0)
		for (var i in marker)
			if (eval("typeof marker." + i) == "object")
				try {
					if (eval("typeof marker." + i + "[0].src") != "undefined")
					{
						PdMIA = "this." + i;
						PdMIN = PdMIA + "[0]";
					}
				}
				catch (e) {}
}

PdMarker.prototype.setImageOld = function(a) {
	var msFilter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + a + '")';
    if (this.mouseOutEnabled && this.setImageOn)
	{
		PdCompPdMIN(this);
		try {
			if (this.oldImagePath.length == 0)
				eval("this.oldImagePath = " + PdMIN + ".src");
			if (msie && msiePre7)
				eval(PdMIN + ".style.filter = msFilter");
			else
				eval(PdMIN + ".src = a");
		}
		catch (e) {}
	}
}

PdMarker.prototype.setImage = function(a) {

    if (this.mouseOutEnabled && this.setImageOn){
        GMarker.prototype.setImage.call(this, a);
        }
}

PdMarker.prototype.restoreImage = function() {
    if (this.mouseOutEnabled && this.setImageOn && this.oldImagePath.length > 0){
        this.setImage(this.oldImagePath);
        }
}

PdMarker.prototype.display = function(a) {
	if (a)
		this.show();
	else
		this.hide();
}

PdMarker.prototype.blink = function(a,b) {
	if (a)
	{
		this.blinkOn = true;
		this.blinkSpeed = b;
		if (!this.blinking)
		{
			this.blinking = a;
			PdMarkerAddToExtList(this);
			PdMarkerBlinkOnOff(this.getId());
		}
	}
	else
	{
		this.blinking = a;
		this.display(true);
		PdMarkerRemoveFromExtList(this);
	}
}

PdMarker.prototype.setIcon = function(a) {
	this.remove();
	this.icon = a;
	this.initialize(this.map);
	this.redraw(true);
}

PdMarker.prototype.setMarkerZIndex = function(a) {
	PdCompPdMIN(this);
	if (!this.zIndexSaved)
	{
		this.zIndexSaved = true;
		this.oldZIndex = eval(PdMIN + ".style.zIndex");
	}
    eval(PdMIN + ".style.zIndex = a")
	this.redraw(true);
}

PdMarker.prototype.topMarkerZIndex = function() {
	this.setMarkerZIndex (600000);
}

PdMarker.prototype.restoreMarkerZIndex = function() {
	PdCompPdMIN(this);
	if (this.zIndexSaved)
	{
		this.zIndexSaved = false;
		eval(PdMIN + ".style.zIndex = this.oldZIndex")
		this.redraw(true);
	}
}

PdMarker.prototype.onInfoWindowOpen = function() {
	this.hideTooltip();
	GMarker.prototype.onInfoWindowOpen.call(this);
}

PdMarker.prototype.setHoverImage = function(a) {
	this.hoverImage = a;
}

var inMouseOver = false;

PdMarker.prototype.onMouseOver = function() {
    if (this.timerId) clearTimeout(this.timerId);
    if (inMouseOver){
        return;
    }
    inMouseOver = true;
	if (this.hoverImage){
        this.setImage(this.hoverImage);
    }
    if (!this.detailOpen){
        this.showDetailWin();
    }
    inMouseOver = false;
}

PdMarker.prototype.onMouseOut = function() {

    var curMaker = this;
    this.timerId = window.setTimeout(function(){
        if (curMaker.hoverImage){
            curMaker.restoreImage();
        }
        if (curMaker.mouseOutEnabled){
            if(curMaker.detailOpen){
                curMaker.closeDetailWin();
            }
        }
    }, 100);
}

PdMarker.prototype.setMouseOutEnabled = function(a) {
	this.mouseOutEnabled = a;
}

PdMarker.prototype.getMouseOutEnabled = function() {
	return this.mouseOutEnabled;
}

PdMarker.prototype.setTooltipHiding = function(a) {
	this.hidingEnabled = a;
}

PdMarker.prototype.getTooltipHiding = function() {
	return this.hidingEnabled;
}

PdMarker.prototype.setTitle = function(a) {
	this.tooltipText = "";
	PdCompPdMIN(this);
	try {
		eval(PdMIN + ".title = a");
	}
	catch (e) {
		this.pendingTitle = a;
	}
}

PdMarker.prototype.setCursor = function(a) {
	PdCompPdMIN(this);
	try {
		eval(PdMIN + ".style.cursor = a");
	}
	catch (e) {
		this.pendingCursor = a;
	}
}

PdMarker.prototype.setTooltipClass = function(a) {
	this.pendingClassName = a;
	if (this.tooltipObject)
	{
		var showing = (this.tooltipObject.style.display != "none");
		this.deleteObjects();
		if (this.tooltipRaw)
			this.setTooltipNoResize(this.tooltipRaw);
		if (showing)
			this.showTooltip();

	}
	else
		if (this.tooltipRaw)
			this.setTooltipNoResize(this.tooltipRaw);
}

PdMarker.prototype.resetTooltipClass = function() {
	this.setTooltipClass("markerTooltip");
}

PdMarker.prototype.getTooltip = function() {
	try {
		return this.tooltipRaw;
	}
	catch (e)
	{
		return "";
	}
}

PdMarker.prototype.setTooltipNoResize = function(a) {
	this.setTitle("");
	var ttClass = "markerTooltip";
	if (this.pendingClassName)
		ttClass = this.pendingClassName;
	this.tooltipRaw = a;
	this.tooltipText = "<div class='" + ttClass + "'>" + a + "</div>";
	if (this.tooltipObject)
		this.tooltipObject.innerHTML = this.tooltipText;
}

PdMarker.prototype.setTooltip = function(a) {
	this.setTooltipNoResize(a);
	this.deleteObjects();
}

PdMarker.prototype.showTooltip = function() {
	if (this.tooltipText)
	{
		if (!this.tooltipObject)
			initTooltip(this);
		setTTPosition(this);
		this.tooltipObject.style.display = "block";
	}
}

PdMarker.prototype.hideTooltip = function() {
	if (this.tooltipObject)
		if (this.hidingEnabled)
			this.tooltipObject.style.display = "none";
}

PdMarker.prototype.onClick = function(a) {
    this.isClicked = true;
    if(curClickedMarker != null && curClickedMarker.internalId != this.internalId){
        curClickedMarker.closeDetailWin();
    }
    if (this.showDetailOnClick && this.detailWinHTML)
    {
        this.showDetailWin();
    }
    curClickedMarker = this;
}

PdMarker.prototype.setShowDetailOnClick = function(a) {
	this.showDetailOnClick = a;
}

PdMarker.prototype.setDetailWinHTML = function(a) {
	this.detailWinHTML = a;
}


PdMarker.prototype.setDetailWinClass = function(a) {
	this.pendingDetailClassName = a;
}

PdMarker.prototype.resetDetailWinClass = function() {
	this.setDetailWinClass("markerDetail");
}



PdMarker.prototype.showDetailWin = function() {

    if (this.detailOpen)
	{
        if(!this.isClicked){
            this.closeDetailWin();
		    return;
        }
	}

    if(this.isClicked)
        this.setMouseOutEnabled(false);

	var winClass = "markerDetail";
	if (this.pendingWinClassName)
		winClass = this.pendingWinClassName;

	var html = "<table><tr><td>" + this.detailWinHTML + "</td><td class='closeBtn' valign='top'><a class='markerDetailClose' href='javascript:PdMarkerClose(" + this.internalId + ")'><img src='http://www.google.com/mapfiles/close.gif' width='14' height='13'></a></td></tr></table>";
	html = "<div class='" + winClass + "'><span class='bubbleTop'></span><span class='bubbleMid'>" + html + "</span><span class='bubbleBtm'></span></div>";
	this.detailOpen = true;

    initDetailWin(this, html);

    this.mouseOverLisId = GEvent.addDomListener(this.detailObject, "mouseover", addDetailWindowListener(this, "mouseover"));
    this.mouseOutListId = GEvent.addDomListener(this.detailObject, "mouseout", addDetailWindowListener(this, "mouseout"));
    PdMarkerAddToExtList(this);
}

PdMarker.prototype.closeDetailWin = function() {

    this.detailOpen = false;
	if (this.detailObject)
	{
        if(this.mouseOverLisId) GEvent.removeListener(this.mouseOverLisId);
        if(this.mouseOutListId) GEvent.removeListener(this.mouseOutListId);
        if(this.isClicked){
            this.setMouseOutEnabled(true);
            this.onMouseOut();
            this.isClicked = false;
        }
        
        var mapDiv = document.getElementById("google-map");
        if(!mapDiv){
            mapDiv = document.getElementById("google-directions");
        }
        mapDiv.removeChild(this.detailObject);

		this.detailObject = null;
	}
}

PdMarker.prototype.deleteObjects = function() {
    var mapDiv = document.getElementById("google-map");
    if(!mapDiv){
        mapDiv = document.getElementById("google-directions");
    }
    if (this.tooltipObject)
	{
	    mapDiv.removeChild(this.tooltipObject);
		this.tooltipObject = null;
	}
	if (this.detailObject)
	{
        var detailObj = document.getElementById(this.detailId);
        if(detailObj){
            mapDiv.removeChild(detailObj);
        }
        this.detailObject = null;
	}
}

PdMarker.prototype.remove = function(a) {
	removeMarkerFromMapList(this.map, this);
	PdMarkerRemoveFromExtList(this.getId());
    // labeled marker
    if(this.isLabeledMarker){
        GEvent.clearInstanceListeners(this.div_);
        if (this.div_.outerHTML) {
            this.div_.outerHTML = ""; //prevent pseudo-leak in IE
        }
        if (this.div_.parentNode) {
            this.div_.parentNode.removeChild(this.div_);
        }
        this.div_ = null;
    }
    GMarker.prototype.remove.call(this);
    this.deleteObjects();

}

PdMarker.prototype.setOpacity = function(b) {
	if (b < 0)
		b=0;
	if (b >= 100)
		b=100;
	var c = b / 100;
	this.percentOpacity = b;
	var d = document.getElementById(this.objId);
	if (d)
	{
		if(typeof(d.style.filter)=='string'){d.style.filter='alpha(opacity:'+b+')';}
		if(typeof(d.style.KHTMLOpacity)=='string'){d.style.KHTMLOpacity=c;}
		if(typeof(d.style.MozOpacity)=='string'){d.style.MozOpacity=c;}
		if(typeof(d.style.opacity)=='string'){d.style.opacity=c;}
	}
}

PdMarker.prototype.setOpacityNew = function(b) {
	setObjOpacity(this.objId);
	this.percentOpacity = b;
}

// ---------------------- added labelmarker function to pdMarker -----------------------------------

/**
 * Move the text div based on current projection and zoom level, call the redraw()
 * handler in GMarker.
 *
 * @param {Boolean} force will be true when pixel coordinates need to be recomputed.
 */

PdMarker.prototype.redraw = function(force) {
  GMarker.prototype.redraw.apply(this, arguments);

  var p = this.map.fromLatLngToDivPixel(this.latlng_);

  if(this.isLabeledMarker){
        // Calculate the DIV coordinates of two opposite corners of our bounds to
        // get the size and position of our rectangle
        var z = GOverlay.getZIndex(this.latlng_.lat());
        // Now position our div based on the div coordinates of our bounds
        if(this.div_){
            this.div_.style.left = (p.x + this.labelOffset_.width) + "px";
            this.div_.style.top = (p.y + this.labelOffset_.height) + "px";
            this.div_.style.zIndex = z; // in front of the marker
        }
  }

}

/**
 * Shows the marker, and shows label if it wasn't hidden. Note that this function
 * triggers the event GMarker.visibilitychanged in case the marker is currently hidden.
 */

PdMarker.prototype.show = function() {
  GMarker.prototype.show.apply(this, arguments);
  if (this.labelVisibility_) {
    this.showLabel();
  } else {
    this.hideLabel();
  }
}

/**
 * Hides the marker and label if it is currently visible. Note that this function
 * triggers the event GMarker.visibilitychanged in case the marker is currently visible.
 */

PdMarker.prototype.hide = function() {
  GMarker.prototype.hide.apply(this, arguments);
  this.hideLabel();
}


/**
 * Sets the visibility of the label, which will be respected during show/hides.
 * If marker is visible when set, it will show or hide label appropriately.
 */

PdMarker.prototype.setLabelVisibility = function(visibility) {
  this.labelVisibility_ = visibility;
  if (!this.isHidden()) { // Marker showing, make visible change
    if (this.labelVisibility_) {
      this.showLabel();
    } else {
      this.hideLabel();
    }
  }
}


/**
 * Returns whether label visibility is set on.
 * @return {Boolean}
 */

PdMarker.prototype.getLabelVisibility = function() {
  return this.labelVisibility_;
}


/**
 * Hides the label of the marker.
 */
PdMarker.prototype.hideLabel = function() {
  this.div_.style.visibility = 'hidden';
}

/**
 * Shows the label of the marker.
 */
PdMarker.prototype.showLabel = function() {
  this.div_.style.visibility = 'visible';
}

// ----------------------------------------------------------------------------------------------

// PRIVATE ROUTINES

function setObjOpacity(objId, b) {
	if (b < 0)
		b=0;
	if (b >= 100)
		b=100;
	var c = b / 100;
	var d = document.getElementById(objId);
	if (d)
	{
		if(typeof(d.style.filter)=='string'){d.style.filter='alpha(opacity:'+b+')';}
		if(typeof(d.style.KHTMLOpacity)=='string'){d.style.KHTMLOpacity=c;}
		if(typeof(d.style.MozOpacity)=='string'){d.style.MozOpacity=c;}
		if(typeof(d.style.opacity)=='string'){d.style.opacity=c;}
	}
}

function idToElemId(id) {
	return "ttobj" + id;
}

function initTooltip(theObj) {
	theObj.objId = idToElemId(theObj.internalId);
	theObj.anchorLatLng = theObj.point;

	var b = document.createElement('span');
	theObj.tooltipObject = b;
	b.setAttribute('id',theObj.objId);
	b.innerHTML = theObj.tooltipText;

	// append to body for size calculations
	var c = document.body;
	var d = document.getElementById("pdmarkerwork");
	if (d)
		c = d;
	c.appendChild(b);
	b.style.position = "absolute";
	b.style.bottom = "5px";
	b.style.left = "5px";
	b.style.zIndex = 1;
	if (theObj.percentOpacity)
		theObj.setOpacity(theObj.percentOpacity);
	var tempObj = document.getElementById(theObj.objId);
	theObj.ttWidth  = tempObj.offsetWidth;
	theObj.ttHeight = tempObj.offsetHeight;
	c.removeChild(b);

	b.style.zIndex = 600000;
	b.style.bottom = "";
	b.style.left = "";
	theObj.map.getPane(G_MAP_FLOAT_PANE).appendChild(b);
}

function initDetailWin(theObj, html) {

    if(document.getElementById("detail" + theObj.internalId)) return;
    // append to the google map id div tag
    var mapDiv = document.getElementById("google-map");
    if(!mapDiv){
        mapDiv = document.getElementById("google-directions");
    }
    theObj.detailId = "detail" + theObj.internalId;
	var b = document.createElement('span');
	b.setAttribute('id',theObj.detailId);
    b.innerHTML = html;
	b.style.display = "block";
	b.style.position = "absolute";
    b.style.top = 0;
    b.style.left = 0;
	b.style.zIndex = 1;
    theObj.detailObject = b;
    mapDiv.appendChild(b);

    var content = YUD.getElementsByClassName("markerDetail", "div", b)[0];

    theObj.ttWidth = content.offsetWidth;
	theObj.ttHeight = content.offsetHeight;
    setTTPosition(theObj);


    b.style.top  = theObj.ttTop + "px";
	if (theObj.rightSide)
		b.style.left = theObj.ttLeft + "px";
	else
		b.style.right = -theObj.ttLeft + "px";
		b.style.zIndex = 600001;
}

// set the mouse over and mouse out event listener when user mouse over the detail window
function addDetailWindowListener(obj, event){
    return function() {GEvent.trigger(obj, event);};
}

function subGPoints(a,b) {
    return new GPoint(a.x-b.x, a.y-b.y);
}

function setTTPosition(theObj) {
	var gap = -24;
	var map = theObj.map;
	var pt  = theObj.getPoint();
    var TlcLatLng = map.fromContainerPixelToLatLng(new GPoint(0,0),true);
    var TlcDivPixel = map.fromLatLngToDivPixel(TlcLatLng);
    var pointDivPixel = map.fromLatLngToDivPixel(pt);
    var ttPos = subGPoints(pointDivPixel, TlcDivPixel);

    var theIcon = theObj.getIcon();
    ttPos.y -= Math.floor(theIcon.iconAnchor.y);
    var rightSide = true;
	var bounds = map.getBounds();
	var boundsSpan	= bounds.toSpan();
	var longSpan = boundsSpan.lng();
	var mapWidth = map.getSize().width;

	var tooltipWidthInDeg = (theObj.ttWidth + theIcon.iconSize.width + 6) / mapWidth * longSpan;
	if (pt.lng() + tooltipWidthInDeg > bounds.getNorthEast().lng() && permitLeft)
		rightSide = false;
    ttPos.y -= Math.floor(theObj.ttHeight - 1);
	delta = (theIcon.iconSize.width - theIcon.iconAnchor.x) + gap;
    // display only on the right hand site

    if (rightSide)
		ttPos.x += delta;
	else
		ttPos.x -= delta;

	theObj.rightSide = rightSide;
    theObj.ttLeft = ttPos.x;
	theObj.ttTop  = ttPos.y;
	if (theObj.tooltipObject)
	{
        if (rightSide) {
			theObj.tooltipObject.style.left = ttPos.x + "px";
			theObj.tooltipObject.style.right = null;
		}
		else {
			theObj.tooltipObject.style.left = null;
			theObj.tooltipObject.style.right = -ttPos.x + "px";
		}
		theObj.tooltipObject.style.top  = ttPos.y + "px";
	}
    if(theObj.detailObject){
        if (rightSide) {
			theObj.detailObject.style.left = ttPos.x + "px";
			theObj.detailObject.style.right = null;
		}
		else {
			theObj.detailObject.style.left = null;
			theObj.detailObject.style.right = -ttPos.x + "px";
		}
		theObj.detailObject.style.top  = ttPos.y + "px";
    }
}

function makeInterface(a) {
	var b = a || window;
	b.PdMarker = PdMarker;
}

makeInterface();
}


PdMarkerNamespace();

/* ---------------------------------------------------------------------------------------------------------------------
#  4)  Clustering function for google map
----------------------------------------------------------------------------------------------------------------------*/
// Copyright © 2005,2006 by Jef Poskanzer <jef@mail.acme.com>.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
// For commentary on this license please see http://www.acme.com/license.html


// Constructor.
Clusterer = function ( map )
    {
    this.map = map;
    this.markers = [];
    this.clusters = [];
    this.timeout = null;
    this.currentZoomLevel = map.getZoom();
    this.maxVisibleMarkers = Clusterer.defaultMaxVisibleMarkers;
    this.gridSize = Clusterer.defaultGridSize;
    this.minMarkersPerCluster = Clusterer.defaultMinMarkersPerCluster;
    this.maxLinesPerInfoBox = Clusterer.defaultMaxLinesPerInfoBox;
    this.icon = Clusterer.defaultIcon;
    this.isSearch = true;
    };


Clusterer.defaultMaxVisibleMarkers = 8;
Clusterer.defaultGridSize = 15;
Clusterer.defaultMinMarkersPerCluster = 2;
Clusterer.defaultMaxLinesPerInfoBox = 4;

Clusterer.defaultIcon = new GIcon();
Clusterer.defaultIcon.image = '/images/global/googleIcon-marker.png';
Clusterer.defaultIcon.shadow = '/images/global/googleIcon-markerShadow.png';
Clusterer.defaultIcon.iconSize = new GSize(20, 32);
Clusterer.defaultIcon.shadowSize = new GSize(47, 34);
Clusterer.defaultIcon.iconAnchor = new GPoint(10, 32);
Clusterer.defaultIcon.infoWindowAnchor = new GPoint(20, 10);
Clusterer.defaultIcon.infoShadowAnchor = new GPoint( 44, 13 );


// Call this to change the cluster icon.
Clusterer.prototype.SetIcon = function ( icon )
    {
    this.icon = icon;
    };


// Changes the maximum number of visible markers before clustering kicks in.
Clusterer.prototype.SetMaxVisibleMarkers = function ( n )
    {
    this.maxVisibleMarkers = n;
    };


// Sets the minumum number of markers for a cluster.
Clusterer.prototype.SetMinMarkersPerCluster = function ( n )
    {
    this.minMarkersPerCluster = n;
    };


// Sets the maximum number of lines in an info box.
Clusterer.prototype.SetMaxLinesPerInfoBox = function ( n )
    {
    this.maxLinesPerInfoBox = n;
    };


// Call this to add a marker.
Clusterer.prototype.AddMarker = function ( marker, title )
{
    marker.title = title;
    marker.onMap = false;
    this.markers.push( marker );
    this.DisplayLater();
};


// Call this to remove a marker.
Clusterer.prototype.RemoveMarker = function ( marker )
{
    for ( var i = 0; i < this.markers.length; ++i )
	if ( this.markers[i] == marker )
	    {
	    if ( marker.onMap ){
            this.map.removeOverlay( marker );
        }

	    for ( var j = 0; j < this.clusters.length; ++j )
		{
		var cluster = this.clusters[j];
		if ( cluster != null )
		    {
		    for ( var k = 0; k < cluster.markers.length; ++k )
			if ( cluster.markers[k] == marker )
			    {
			    cluster.markers[k] = null;
			    --cluster.markerCount;
			    break;
			    }
		    if ( cluster.markerCount == 0 )
			{
			this.ClearCluster( cluster );
			this.clusters[j] = null;
			}
		    else if ( cluster == this.poppedUpCluster )
			Clusterer.RePop( this );
		    }
		}
	    this.markers[i] = null;
        marker.remove();
        break;
	    }
    this.DisplayLater();
};


Clusterer.prototype.DisplayLater = function ()
{
    if ( this.timeout != null )
	clearTimeout( this.timeout );
    this.timeout = setTimeout( Clusterer.MakeCaller( Clusterer.Display, this ), 50 );
};


Clusterer.Display = function ( clusterer )
{
    var i, j, marker, cluster;
    clearTimeout( clusterer.timeout );
    var newZoomLevel = clusterer.map.getZoom();
    if ( newZoomLevel != clusterer.currentZoomLevel )
	{
        // When the zoom level changes, we have to remove all the clusters.
        for (i = 0; i < clusterer.clusters.length; ++i )
            if ( clusterer.clusters[i] != null )
            {
            clusterer.ClearCluster( clusterer.clusters[i] );
            clusterer.clusters[i] = null;
            }
        clusterer.clusters = [];
        clusterer.clusters.length = 0;
        clusterer.currentZoomLevel = newZoomLevel;
    }
    // Get the current bounds of the visible area.
    var bounds = clusterer.map.getBounds();
    // Expand the bounds a little, so things look smoother when scrolling
    // by small amounts.
    var sw = bounds.getSouthWest();
    var ne = bounds.getNorthEast();
    var dx = ne.lng() - sw.lng();
    var dy = ne.lat() - sw.lat();

    if ( dx < 300 && dy < 150 )
	{
	dx *= 0.10;
	dy *= 0.10;
	bounds = new GLatLngBounds(
	  new GLatLng( sw.lat() - dy, sw.lng() - dx ),
	  new GLatLng( ne.lat() + dy, ne.lng() + dx ) );
	}
    // Partition the markers into visible and non-visible lists.
    var visibleMarkers = [];
    var nonvisibleMarkers = [];
    for ( i = 0; i < clusterer.markers.length; ++i )
	{
	marker = clusterer.markers[i];
	if ( marker != null )
	    if ( bounds.contains( marker.getPoint() ) )
		visibleMarkers.push( marker );
	    else
		nonvisibleMarkers.push( marker );
	}
    // Take down the non-visible markers.
    for ( i = 0; i < nonvisibleMarkers.length; ++i )
	{
	marker = nonvisibleMarkers[i];
	if ( marker.onMap )
	    {
	    clusterer.map.removeOverlay( marker );
	    marker.onMap = false;
	    }
	}

    // Take down the non-visible clusters.
    for ( i = 0; i < clusterer.clusters.length; ++i )
	{
        cluster = clusterer.clusters[i];
        if ( cluster != null && ! bounds.contains( cluster.marker.getPoint() ) && cluster.onMap ){
            clusterer.map.removeOverlay( cluster.marker );
            cluster.onMap = false;
        }
	}
    
    // Clustering!  This is some complicated stuff.  We have three goals
    // here.  One, limit the number of markers & clusters displayed, so the
    // maps code doesn't slow to a crawl.  Two, when possible keep existing
    // clusters instead of replacing them with new ones, so that the app pans
    // better.  And three, of course, be CPU and memory efficient.


    // Add to the list of clusters by splitting up the current bounds
    // into a grid.
    var latRange = bounds.getNorthEast().lat() - bounds.getSouthWest().lat();
    var latInc = latRange / clusterer.gridSize;
    var lngInc = latInc / Math.cos( ( bounds.getNorthEast().lat() + bounds.getSouthWest().lat() ) / 2.0 * Math.PI / 180.0 );

    // add # of possible cluster grid size size in the clusters array
    for ( var lat = bounds.getSouthWest().lat(); lat <= bounds.getNorthEast().lat(); lat += latInc ){
        for ( var lng = bounds.getSouthWest().lng(); lng <= bounds.getNorthEast().lng(); lng += lngInc )
        {
        cluster = new Object();
        cluster.clusterer = clusterer;

        //grid size bounds
        cluster.bounds = new GLatLngBounds( new GLatLng( lat, lng ), new GLatLng( lat + latInc, lng + lngInc ) );
        cluster.markers = [];
        cluster.markerCount = 0;
        cluster.onMap = false;
        cluster.marker = null;
        clusterer.clusters.push( cluster );
        }
    }

    // Put all the unclustered visible markers into a cluster - the first
    // one it fits in, which favors pre-existing clusters.
    for ( i = 0; i < visibleMarkers.length; ++i )
    {
        marker = visibleMarkers[i];
        if ( marker != null && ! marker.inCluster )
        {
            for ( j = 0; j < clusterer.clusters.length; ++j )
                {
                    cluster = clusterer.clusters[j];
                    if ( cluster != null && cluster.bounds.contains( marker.getPoint() ) )
                    {
                        cluster.markers.push( marker );
                        ++cluster.markerCount;
                        marker.inCluster = true;
                    }
                }
        }
    }

    // Get rid of any clusters containing only a few markers.
    for ( i = 0; i < clusterer.clusters.length; ++i ){
        if ( clusterer.clusters[i] != null && clusterer.clusters[i].markerCount < clusterer.minMarkersPerCluster )
        {
            clusterer.ClearCluster( clusterer.clusters[i] );
            clusterer.clusters[i] = null;
        }
    }

    // Shrink the clusters list.
    var processCnt = 0;
    var totalCnt = clusterer.clusters.length;
    var skipIndex = 0;
    while(processCnt < totalCnt){
        processCnt +=1;
        if(clusterer.clusters[skipIndex] == null){
            clusterer.clusters.splice(skipIndex,1);
        } else {
            skipIndex += 1;
        }
    }

    // Ok, we have our clusters.  Go through the markers in each
    // cluster and remove them from the map if they are currently up.
    for ( i = 0; i < clusterer.clusters.length; ++i ){
        cluster = clusterer.clusters[i];
        if ( cluster != null ){
            for ( j = 0; j < cluster.markers.length; ++j ){
                marker = cluster.markers[j];
                if ( marker != null && marker.onMap )
                {
                    clusterer.map.removeOverlay( marker );
                    marker.onMap = false;
                }
            }
        }
    }

    // Now make cluster-markers for any clusters that need one.
    for ( i = 0; i < clusterer.clusters.length; ++i ){
        cluster = clusterer.clusters[i];
        if ( cluster != null && cluster.marker == null )
        {
            // Figure out the average coordinates of the markers in this cluster and the zoom level to de-cluster the marker
            var xTotal = 0.0, yTotal = 0.0;
            var thePoint, x, y, minX, maxX, minY, maxY;
            for ( j = 0; j < cluster.markers.length; ++j ){
                marker = cluster.markers[j];
                if ( marker != null )
                {
                    x = marker.getPoint().lat();
                    y = marker.getPoint().lng();
                    xTotal += ( + marker.getPoint().lng() );
                    yTotal += ( + marker.getPoint().lat() );
                    if (j == 0) {minX = x; maxX = x; minY = y; maxY = y;}
                    else{
                        if (x < minX) minX = x;
                        if (x > maxX) maxX = x;
                        if (y < minY) minY = y;
                        if (y > maxY) maxY = y;
                    }

                }
            }

            // calculate the proper zoom level for the markers
            var center = new GLatLng((minX + maxX) / 2, (minY + maxY) / 2)
            var span = new GSize(Math.abs(maxX - minX), Math.abs(maxY - minY));
            var slopWid = 0;
            var slopHgt = 0;
            var slopPercentage = 15; // 10% padding on the map
            var heightOffsetPct = 15;  // 10% padding on the map
            slopWid = span.width * slopPercentage / 200;
            slopHgt = span.height * slopPercentage / 200;
            span.width  *= 1 + slopPercentage / 100;
            span.height *= 1 + slopPercentage / 100;
            var deltaHgt = 0;
            deltaHgt = span.height * heightOffsetPct / 100;
            var markerBounds = new GLatLngBounds(new GLatLng(minX-slopHgt, minY-slopWid), new GLatLng(maxX+slopHgt, maxY+slopWid)); // sw, ne
            var zoom = clusterer.map.getBoundsZoomLevel(markerBounds);

            // create a labeledMarker
            var opts = {
              "clickable": true,
              "title": cluster.markers.length,
              "labelText": cluster.markers.length,
              "labelOffset": new GSize(-5, -30),
              "labelClass": "markerLabel"
            };

            marker = Clusterer.CreateClusterMarker(center, clusterer.icon, opts, zoom, clusterer.isSearch);
            cluster.marker = marker;
        }
    }

    var maxZoom = G_NORMAL_MAP.getTileLayers()[0].maxResolution();
    // if we reach the max zoom level, no clustering
    if(newZoomLevel >= maxZoom){

        for ( i = 0; i < visibleMarkers.length; ++i ){
            marker = visibleMarkers[i];
            if ( marker != null && ! marker.onMap ){
                clusterer.map.addOverlay( marker );
                marker.onMap = true;
                marker.inCluster = false;
            }
        }
    } else {

        // Display the visible markers not already up and not in clusters.
        for ( i = 0; i < visibleMarkers.length; ++i ){
            marker = visibleMarkers[i];
            if ( marker != null && ! marker.onMap && ! marker.inCluster ){
                clusterer.map.addOverlay( marker );
                marker.onMap = true;
            }
        }

        // Display the visible clusters not already up.
        for ( i = 0; i < clusterer.clusters.length; ++i )
        {
            cluster = clusterer.clusters[i];
            if ( cluster != null && ! cluster.onMap && bounds.contains( cluster.marker.getPoint() ) ){
                clusterer.map.addOverlay( cluster.marker );
                cluster.onMap = true;
            }
        }
    }

    // In case a cluster is currently popped-up, re-pop to get any new
    // markers into the infobox.
    Clusterer.RePop( clusterer );
};


Clusterer.CreateClusterMarker = function(point, icon, opts, zoom, isSearch)
{
    var marker;

    // Custom centex icons for clusters
    if (getCurrSite().toLowerCase() == "centex") {
        marker = new PdMarker(point, mapCONFIG.gIcons['centexMarker'], opts);
        marker.setHoverImage(mapCONFIG.gIconImages['centexMarker'].imageOn);
    }
    else {
        marker = new PdMarker(point, mapCONFIG.gIcons['marker'], opts);
        marker.setHoverImage(mapCONFIG.gIconImages['marker'].imageOn);
    }

    var zoomFunction = 'MapSearch.zoomToCluster';
    if(!isSearch){
        zoomFunction = 'customMarkerUtils.zoomToCluster';
    }
    var html = '<a href="javascript:' + zoomFunction + '(' + point.lat() + ',' + point.lng() + ',' + zoom + ');">' + opts.labelText;
    html += (parseInt(opts.labelText)>1)? " neighborhoods":" neighborhood";
    html += "</a>"
    marker.setDetailWinHTML(html);

    return marker;
};

Clusterer.PopUp = function ( cluster )
    {
    var clusterer = cluster.clusterer;
    var html = cluster.markers.length + ' neighborhoods';
    clusterer.map.closeInfoWindow();
    cluster.marker.openInfoWindowHtml( html );
    clusterer.poppedUpCluster = cluster;
    };


Clusterer.RePop = function ( clusterer )
    {
    if ( clusterer.poppedUpCluster != null )
	Clusterer.PopUp( clusterer.poppedUpCluster );
    };


Clusterer.PopDown = function ( clusterer )
    {
    clusterer.poppedUpCluster = null;
    };


Clusterer.prototype.ClearCluster = function ( cluster )
{
    var i, marker;
    for ( i = 0; i < cluster.markers.length; ++i ){
        if ( cluster.markers[i] != null )
            {
            cluster.markers[i].inCluster = false;
            cluster.markers[i] = null;
            }
    }
    cluster.markers.length = 0;
    cluster.markerCount = 0;
    if ( cluster.onMap )
	{
        this.map.removeOverlay( cluster.marker );
        cluster.onMap = false;
        try {cluster.marker.remove();}
		catch (e) {cluster.marker = null;}
    }
};


// This returns a function closure that calls the given routine with the
// specified arg.
Clusterer.MakeCaller = function ( func, arg ){
    return function () { func( arg ); };
};

Clusterer.prototype.ActivateListener = function(){
    GEvent.addListener( this.map, 'zoomend', Clusterer.MakeCaller( Clusterer.Display, this ) );
    GEvent.addListener( this.map, 'moveend', Clusterer.MakeCaller( Clusterer.Display, this ) );
};
// ---------------------------------------------------- end of clustering ----------------------------------------------


/* ----------------------------------------------------------------------------------------------
#  5)  CustomMarkerUtils
---------------------------------------------------------------------------------------------- */
var customMarkerUtils = {
    //buildDynamicCluster
    gmap: null,

    buildDynamicMarkers: function(markers, isMaster){
        var xTotal = 0.0, yTotal = 0.0;
        var x, y, minX, maxX, minY, maxY;
        var marker, bubbleContent;
        var defaultImg = '<img src="/images/global/google-propertySample.gif" alt="" width="68" height="44" class="propertyImg" />';
        var isMasterPage = true;
        var mapCluster;
        if(typeof isMaster == "undefined"){
            isMasterPage = false;
            mapCluster = new Clusterer(customMarkerUtils.gmap);
            mapCluster.isSearch = false;
            mapCluster.ActivateListener();
        }
        var defaultBrand = getCurrSite().toLowerCase();
        for(var i=0;i< markers.length; i++)
        {
            // calculate map center and zoom level
            x = markers[i].point.latitude;
            y = markers[i].point.longitude;
            xTotal += ( + markers[i].point.longitude );
            yTotal += ( + markers[i].point.latitude );
            if (i == 0) {minX = x; maxX = x; minY = y; maxY = y;}
            else{
                if (x < minX) minX = x;
                if (x > maxX) maxX = x;
                if (y < minY) minY = y;
                if (y > maxY) maxY = y;
            }

            var curBrand = defaultBrand;
            if(markers[i].brandId){
                var mBrand = customMarkerUtils.getMarkerBrand(markers[i].brandId);
                curBrand = (mBrand == "")?defaultBrand:mBrand;
            }
            
            var comingSoonDesc = '';
            if(markers[i].soonFlag){
                curBrand += "Soon";
                comingSoonDesc = '<br />Coming Soon';
            }

            var pImg = defaultImg;

            if(markers[i].propertyImage){
                pImg = '<img src="' + markers[i].propertyImage + '" alt="" width="68" height="27" class="propertyImg" />';
            }
            if(!isMasterPage){
                var homesAvailableLink = '';
                if(markers[i].HomesAvailable && markers[i].HomesAvailable > 0) {
                  if(markers[i].linkURL) {
                    homesAvailableLink = '<tr><td colspan=2><a href="' + markers[i].linkURL + '?selected=homes-available-now' + '">Quick Move-In Home' + ((parseInt(markers[i].HomesAvailable)>1)?'s':'') + '(' + markers[i].HomesAvailable + ')</a></td></tr>';
                  } else {
                    homesAvailableLink = '<tr><td colspan=2><strong>Quick Move-In Home' + ((parseInt(markers[i].HomesAvailable)>1)?'s':'') + '(' + markers[i].HomesAvailable + ')</strong></td></tr>';
                  }
                }
                if(markers[i].linkURL) {  
                  bubbleContent = '<table border=0 cellpadding=0 cellspacing=0><tr><td><a href="' + markers[i].linkURL + '">' + pImg + '</a></td><td><a href="' + markers[i].linkURL + '" class="propertyName">' + markers[i].communityName  + '</a><br />' + markers[i].city + ", " + markers[i].state + ((markers[i].planType != null && markers[i].planType != "")?('<br />' + markers[i].planType):'') + comingSoonDesc + ((parseInt(markers[i].price) == 0)?('<br />Price Coming Soon'):('<br />From $' + StringUtils.addCommas(markers[i].price))) + '</td></tr>' + homesAvailableLink + '</table>';
                } else {
                  bubbleContent = '<table border=0 cellpadding=0 cellspacing=0><tr><td>' + pImg + '</td><td><strong>' + markers[i].communityName  + '</strong><br />' + markers[i].city + ", " + markers[i].state + ((markers[i].planType != null && markers[i].planType != "")?('<br />' + markers[i].planType):'') + comingSoonDesc + ((parseInt(markers[i].price) == 0)?('<br />Price Coming Soon'):('<br />From $' + StringUtils.addCommas(markers[i].price))) + '</td></tr>' + homesAvailableLink + '</table>';
                }
            } else {
                bubbleContent = '<table border=0 cellpadding=0 cellspacing=0><tr><td><strong>' + markers[i].communityName  + '</strong><br />' + markers[i].address1 + '<br />' + ((markers[i].address2 != "")?(markers[i].address2 + '<br />'):"" ) +  markers[i].city + ", " + markers[i].state + ' ' + markers[i].zip + comingSoonDesc + '<br /><br /><a href="' + markers[i].linkURL + '">' + markers[i].linkText + '</a></td></tr></table>';
            }

            if(markers[i].point.latitude && markers[i].point.longitude){
                var markerPoint = new GLatLng(markers[i].point.latitude,markers[i].point.longitude);
                marker = this.createMarker(markerPoint, bubbleContent, curBrand);
                if(isMasterPage)
                    this.gmap.addOverlay(marker);
                else{
                    mapCluster.AddMarker(marker);
                }
            }
        }

        var center = new GLatLng((minX + maxX) / 2, (minY + maxY) / 2);
        var span = new GSize(Math.abs(maxX - minX), Math.abs(maxY - minY));
        var slopWid = 0;
        var slopHgt = 0;
        var slopPercentage = 15; // 10% padding on the map
        var heightOffsetPct = 15;  // 10% padding on the map
        slopWid = span.width * slopPercentage / 200;
        slopHgt = span.height * slopPercentage / 200;
        span.width  *= 1 + slopPercentage / 100;
        span.height *= 1 + slopPercentage / 100;
        var deltaHgt = 0;
        deltaHgt = span.height * heightOffsetPct / 100;
        var markerBounds = new GLatLngBounds(new GLatLng(minX-slopHgt, minY-slopWid), new GLatLng(maxX+slopHgt, maxY+slopWid)); // sw, ne
        var zoom = this.gmap.getBoundsZoomLevel(markerBounds);
        this.gmap.setCenter(center, zoom);
        

    },
    // ------------------------------- end of buildDynamicCluster ------------------------------------------------------

    // getMarkerBrand
    getMarkerBrand: function(brandId){
        var markerBrand = "";
        if(!brandId || brandId == '') return "";
        switch(brandId){
            case 1: markerBrand = 'pulte'; break;
            case 2: markerBrand = 'delwebb'; break;
            case 3: markerBrand = 'divosta'; break;
            case 4: markerBrand = 'centex'; break;
        }
        return markerBrand;
    },
    // ----------------------------------- end of getMarkerBrand -------------------------------------------------------

    // function to craete marker
    createMarker: function (point, html, curBrand) {
        var marker;
        marker = new PdMarker(point, mapCONFIG.gIcons[curBrand]);
        marker.setHoverImage(mapCONFIG.gIconImages[curBrand].imageOn);
        marker.setDetailWinHTML(html);

        // click event for PDMarker class
        GEvent.addListener(marker, "click", function() {
            if (marker.getMouseOutEnabled()){marker.setMouseOutEnabled(false);}
            else{marker.setMouseOutEnabled(true);}
            });

        return marker;
    },
    // -------------------------------------- end craeteMarker function ------------------------------------------------
    // cluster zoom
    zoomToCluster: function (lat, lng, zoom){
        if(curClickedMarker){
            curClickedMarker.closeDetailWin();
        }
        var center = new GLatLng(lat, lng);
        zoom = this.getMaxZoom(zoom);
        this.gmap.setCenter(center, zoom);
    },
    // --------------------------- end zoomtoCluster -------------------------------------------------------------------
    //getMaxZoom Level from Normal map
    getMaxZoom: function(zoom){
        var maxRes = G_NORMAL_MAP.getTileLayers()[0].maxResolution();
        if(zoom > maxRes){
            zoom = maxRes;
        }
        return zoom;
    },
    // ------------------------ end of getMaxZoom ----------------------------------------------------------------------

    createStaticMarker: function(point){
        var marker;
        var curBrand = getCurrSite().toLowerCase();
        marker = new GMarker(point, mapCONFIG.gIcons[curBrand]);
        return marker;
    }
};
