function ClusterManager(){var mapStyle=null;var mapWidth=null;var mapHeight=null;var gridCells=new Array();var that=this;var emptyLatLong=new VELatLong(0,0).toString();var lastClusteredShapeType="";this.PoiPresent=false;this.ClusterLayer=new VEShapeLayer();this.ClusterLayersArray=new Array();this.ShapeArrays=new Array();this.ShapeTypes=new Array();this.MapInstance=null;this.Initialize=function(mapInstance){this.MapInstance=mapInstance};this.Update=function(e){if(!this.PoiPresent){return true}var currentStyle=mapManager.Map.GetMapStyle();if(mapStyle!=currentStyle){mapStyle=currentStyle;return true}if(mapWidth!=this.MapInstance.GetWidth()||mapHeight!=this.MapInstance.GetHeight()){GenerateGrid()}this.ClusterShapes();if(this.ShapeArrays.length==0){this.PoiPresent=false}HideLoading();return true};this.ClusterShapes=function(type){this.MapInstance.DeleteShapeLayer(this.ClusterLayer);var clusterOptions=new VEClusteringOptions();clusterOptions.Icon=new VECustomIconSpecification();clusterOptions.Icon.CustomHTML='<div class="clusterPin"><div class="clusterCount"></div></div>';this.ClusterLayer.DeleteAllShapes();this.ClusterLayer=new VEShapeLayer();var newClusterLayer=new VEShapeLayer();newClusterLayer.SetClusteringConfiguration(customCluster,clusterOptions);var shapes;for(var i=0;i<this.ShapeArrays.length;i++){shapes=new Array();shapes=this.ShapeArrays[i];for(var j=1;j<shapes.length;j++){newClusterLayer.AddShape(shapes[j],shapes[0])}}this.ClusterLayer=newClusterLayer;this.MapInstance.AddShapeLayer(this.ClusterLayer);HideLoading()};this.DeleteClusterLayer=function(type){this.MapInstance.DeleteShapeLayer(this.ClusterLayer)};this.GetClusterLayer=function(type){var clusterLayer=new VEShapeLayer();for(var i=0;i<this.ClusterLayers.length;i++){return clusterLayer[i]}};function GetClusteredShapes(poiLayer){var clusterShapes=new Array();clusterShapes=poiLayer.GetClusteredShapes(VEClusteringType.Grid);return clusterShapes}function ValidateShape(shape){var result=true;if(shape==null||shape.Primitives.length<1||shape.GetPoints()[0].toString()==emptyLatLong){result=false}return result}this.SetShapes=function(shapes){this.ClearShapes();this.ShapeArrays=new Array();for(var i=0;i<shapes.length;i++){if(ValidateShape(shapes[i])){this.ShapeArrays[0].push(shapes[i])}}};this.ClusterOff=function(type){var clusterArray=new Array();for(var i=0;i<this.ClusterLayersArray.length;i++){clusterArray=this.ClusterLayersArray[i];clusterArray[1].SetClusteringConfiguration(VEClusteringType.None)}};this.ClusterOn=function(type){var clusterOptions=new VEClusteringOptions();clusterOptions.Icon=new VECustomIconSpecification();clusterOptions.Icon.CustomHTML='<div class="clusterPin'+type+'"></div>';this.lastClusteredShapeType=type;clusterOptions.Callback=this.FormatClusterShapes;var clusterArray=new Array();for(var i=0;i<this.ClusterLayersArray.length;i++){clusterArray=this.ClusterLayersArray[i];clusterArray[1].SetClusteringConfiguration(VEClusteringType.Grid,clusterOptions)}};this.AddShapes=function(shapes,type){if(shapes==null||shapes.length==0||this.typeDisplayed(type)){return}var shapeArray=new Array();shapeArray.push(type);var clusterOptions=new VEClusteringOptions();clusterOptions.Icon=new VECustomIconSpecification();clusterOptions.Icon.CustomHTML='<div class="clusterPin'+type+'"></div>';this.lastClusteredShapeType=type;clusterOptions.Callback=this.FormatClusterShapes;var clusterLayer=new VEShapeLayer();clusterLayer.SetClusteringConfiguration(customCluster,clusterOptions);for(var i=0;i<shapes.length;i++){if(ValidateShape(shapes[i])){shapeArray.push(shapes[i]);clusterLayer.AddShape(shapes[i]);if(shapes[i]._customIcon!=undefined){var curCustomIconClass=shapes[i]._customIcon.match(/class=(["'])?(\w+)\1/)[2];if(curCustomIconClass.match(/^pin_wf|pin_v_wf|pin_nonad|pin_v_nonad|mapIcon/i)!=null){var keyInSpan=shapes[i].GetDescription();var imKey=InfoBoxManager.StripSpan(keyInSpan);if(InfoBoxManager.IsFormattedKey(imKey)){var fields=imKey.split("||");var type=fields[0];listingIndex=parseInt(fields[1])}}}YPSearchManager.updateListingShapeMap(listingIndex,shapes[i].GetID())}}this.ShapeArrays.push(shapeArray);this.ShapeTypes.push(type);clusterLayerArray=new Array();clusterLayerArray.push(type);clusterLayerArray.push(clusterLayer);this.ClusterLayersArray.push(clusterLayerArray);this.MapInstance.AddShapeLayer(clusterLayer);if(debug){console.log("In AddShapes: Done with clustering, just called AddShapeLayer(clusterLayer)")}HideLoading()};this.FormatClusterShapes=function(clusters){var clusterShape;var clusterShapeSpec;var clusterShapeSpecHTML;var clusterLatLon;var clusterArray=new Array();var zoomLevel=mapManager.Map.GetZoomLevel();var changeClusterIcon=false;if(debug){console.log("In FormatClusterShapes: Clustering Alg returned clusters.length: %d  separate clusters",clusters.length)}for(var i=0;i<clusters.length;i++){clusterArray=clusters[i].Shapes;clusterShape=clusters[i].GetClusterShape();clusterLatLon=clusters[i].LatLong;clusterArray.sort(typeAndbusNameSort);changeClusterIcon=false;var descriptionArray=new Array();var descriptionKey;var descriptionAddressArray=new Array();var descriptionAddress;var descriptionImage;var descriptionDirections;var description;var clusteredLatLonsArray=new Array();for(var j=0;j<clusterArray.length;j++){clusteredLatLonsArray.push("new VELatLong("+clusterArray[j].GetIconAnchor()+")")}var clusteredLatLonsArrayString="new Array("+clusteredLatLonsArray.join(",")+")";for(var j=0;j<clusterArray.length;j++){descriptionKey=clusterArray[j].GetDescription();descriptionKey=InfoBoxManager.StripSpan(descriptionKey);descriptionImage=InfoBoxManager.GetImage(descriptionKey);if(descriptionImage.match(/Visited/i)!=null){changeClusterIcon=true}descriptionAddress=InfoBoxManager.GetAddress(descriptionKey);descriptionAddressArray=descriptionAddress.split("<br>");descriptionAddress=descriptionAddressArray[0];shapeID=clusterArray[j].GetID();descriptionArray.push(shapeID+"')\">"+descriptionImage+'</td><td style="padding-left:7px;"><span>'+InfoBoxManager.GetName(descriptionKey)+"</span> - "+descriptionAddress+", <span>"+InfoBoxManager.GetPhone(descriptionKey))}clusterShape.SetDescription('<div class="clusterDescription"><div style="font-weight: bold; font: 12px/14px Arial;"><table><tr><td class="clusterCol1" style="cursor:pointer;" onclick="YPSearchManager.GetMPData(\''+(descriptionArray.join('</span></td></tr></table></div><div style="font-weight: bold; font: 12px/14px Arial;"><table><tr><td class="clusterCol1" style="cursor:pointer;" onclick="YPSearchManager.GetMPData(\''))+"</span></td></tr></table></div></div>");if(changeClusterIcon){clusterShape.SetCustomIcon('<div class="clusterPin100_v"></div>')}clusterShape.SetTitle('<div class="clusterPin100ClusterDialog clusterDescriptionTitle">'+resourceClusterHeader+"</div>")}if(debug){var map=mapManager.Map;var shapeLayerCount=map.GetShapeLayerCount();console.log("In FormatClusterShapes: shapeLayerCount:%d",shapeLayerCount);for(var i=0;i<shapeLayerCount;i++){var shapeLayer=map.GetShapeLayerByIndex(i);if(shapeLayer==null){break}var shapeCount=shapeLayer.GetShapeCount();if(debug){console.log("In FormatClusterShapes: shapeLayer:%d has %d shapes",i,shapeCount)}}}if(debug){console.log("In FormatClusterShapes: ... finished")}};this.GenerateDescription=function(key){var divHeight="170px";var topMargin="8px";var keys=key.split("||");var descriptionArray=new Array();var descriptionKey=(keys[0]+"||"+keys[1]);var descriptionAddressArray=new Array();var descriptionAddress;var descriptionImage=InfoBoxManager.GetImage(descriptionKey);for(var j=0;j<keys.length-1;j++){descriptionAddress=InfoBoxManager.GetAddress(descriptionKey);descriptionAddressArray=descriptionAddress.split("<br>");descriptionAddress=descriptionAddressArray[0];descriptionArray.push('<div style="font-weight: bold; font: 12px/14px Arial;"><table><tr><td>'+descriptionImage+'</td><td style="padding-left:7px;"><span>'+InfoBoxManager.GetName(descriptionKey)+"</span><span>"+descriptionAddress+"</span></td></tr></table></div>");descriptionKey=(keys[0]+"||"+keys[j+1])}key=descriptionKey;var poiImg=descriptionImage;var description='<div style="height: '+divHeight+";margin-top:"+topMargin+';"><div class="popupTop" style="overflow-y:auto; height:91%"><div class="popupTopLeft">'+descriptionArray.join("<br/>")+'</div><div class="popupTopRight" style="width:53%"><div id="AP_ACTION_'+key+'" class="popupActionArea" style="top:10px;"><div id="AP_EMPTY_'+key+'" style="height:130px; width:100px;"></div><div id="AP_TO_'+key+'" style="height:130px;display:none;"><div class="popupHeader"><strong>'+resourceDD+":</strong></div><br/>"+resourceToHere+':<br/><input type="text" id="p_toAddress'+key+'" style="width:158px;" onkeydown="ExecuteFindFromInput(\'p_imgTo'+(key)+'\', event);"/><br/><div><img id="p_imgTo'+key+'" src="'+images+'GetDD.gif" class="popupLink" style="left:100px; float: right;" onclick="POIManager.GDDForPOIPopup(\'TO\', \''+(key)+'\');" /></div></div><div id="AP_FROM_'+key+'" style="height:130px;display:none;"><div class="popupHeader"><strong>'+resourceDD+": </strong></div><br/>"+resourceFromHere+':<br/><input type="text" id="p_fromAddress'+key+'" style="width:158px;" onkeydown="ExecuteFindFromInput(\'p_imgFrom'+(key)+'\', event);"/><br/><div><img id="p_imgFrom'+(key)+'" src="'+images+'GetDD.gif" class="popupLink" style="left:100px; float: right;" onclick="POIManager.GDDForPOIPopup(\'FROM\', \''+(key)+'\');"/></div></div><div id="AP_NEAR_'+key+'" style="height:130px;display:none;"><div class="popupHeader"><strong>'+resourceWhatsNearby+': </strong></div><br/><div class="popupSubheader">'+resourceSearchForCategory+':<br/></div><input type="text" id="p_nearby'+key+'" style="width:158px;" onkeydown="ExecuteFindFromInput(\'p_imgNear'+(key)+'\', event);"/><br/><div style="float:left; width:110px">'+resourceWhatsNearbyExample+'</div><div><img id="p_imgNear'+(key)+'" src="'+images+'GetDD.gif" class="popupLink" style="margin-top:11px; left:100px; float: right;" onclick="POIManager.GNBForPOIPopup(\''+(key)+'\');"/></div></div><div id="AP_MAP_'+key+'" style="height:130px;display:none;"><div id="AP_MAP_SAVE_'+key+'" style="display:none;"><div style="float:left;"><div class="popupHeader" style="width:110px"><strong>'+resourceSaveToAMap+': </strong></div><br /><div style="width:110px">'+resourceSaveToAMapPrompt+'</div></div><div><img src="Images/'+poiImg+'" class="popupLink" style="margin-right:10px; margin-top:10px; float: right; border: 1px solid black;" /></div><div style="margin-top:10px;"><select id="mapSelect" style="width:158px;"></select><br/></div><div><img id="p_imgAdd'+(key)+'" src="'+images+'doneButton.gif" class="popupLink" style="left:100px; float: right;" onclick="POIManager.SavePOIToCustomMap('+(key)+');"/></div></div><div id="AP_MAP_WARN_'+key+'" style="float:left;display:none"><div class="popupHeader" style="width:110px"><strong>'+resourceSaveToAMap+': </strong></div><br /><div style="width:180px">'+resourceLoginNeeded+'</div></div></div></div></div></div><div class="popupBottom" style="padding-top:5px"><table><td><img src="images/drivingicon.gif" align="left" style="margin-right:3px;margin-left:3px"></img></td><td>'+resourceDD.toUpperCase()+"<div></div><span class=\"popupLink popupDrivingFunctionTo\" onclick=\"YPSearchManager.ShowActionDiv('AP_', '"+(key)+"', 'FROM');\"><img src=\"images/tohereicon.gif\"><span>"+resourceToHere.toUpperCase()+"</span></img></span> | <span class=\"popupLink popupDrivingFunctionFrom\" onclick=\"YPSearchManager.ShowActionDiv('AP_', '"+(key)+"', 'TO');\"><img src=\"images/fromhereicon.gif\"><span>"+resourceFromHere.toUpperCase()+'</span></img></span></td><td style="width:60px;margin-right:3px;"><span class="popupLink" onclick="YPSearchManager.ShowActionDiv(\'AP_\', \''+(key)+'\', \'NEAR\');"><img src="images/nearbyicon.gif" align="left" style="margin-right:3px"></img><span class="popupLink">'+resourceWhatsNearby.toUpperCase()+'</div></span></td><td style="margin-right:3px; width:70px;"><span class="popupLink" onclick="YPSearchManager.ShowActionDiv(\'AP_\', \''+(key)+'\', \'MAP\');"><img src="images/savemapicon.gif" align="left" style="margin-right:3px;margin-left:3px"></img>'+resourceAddToAMap.toUpperCase()+"</span></td></tr></table></div></div>";return description};this.DeleteShapes=function(type){if(this.typeDisplayed(type)){var newShapeArrays=new Array();var shapeArray=new Array();for(var i=0;i<this.ShapeArrays.length;i++){shapeArray=this.ShapeArrays[i];if(shapeArray[0]!=type){newShapeArrays.push(shapeArray)}}var newClusterLayersArray=new Array();var clusterArray=new Array();for(var i=0;i<this.ClusterLayersArray.length;i++){clusterArray=this.ClusterLayersArray[i];if(clusterArray[0]!=type){newClusterLayersArray.push(clusterArray)}else{this.MapInstance.DeleteShapeLayer(clusterArray[1])}}this.ShapeArrays=newShapeArrays;this.ClusterLayersArray=newClusterLayersArray}HideLoading()};this.typeDisplayed=function(type){var shapeArray=new Array();for(var i=0;i<this.ShapeArrays.length;i++){shapeArray=this.ShapeArrays[i];if(shapeArray[0]==type){return true}}return false};this.DeleteAllShapes=function(){this.ClearShapes();this.ShapeArrays=new Array();this.PoiPresent=false};this.ClearShapes=function(){var gridSize=gridCells.length;this.ClusterLayer.DeleteAllShapes();gridCells=null;gridCells=new Array(gridSize)};function GenerateLayer(shapes){var zoomLevel=that.MapInstance.GetZoomLevel();var xCells=parseInt(Math.ceil(mapWidth/gridSize));that.ClearShapes();for(var i=0;i<shapes.length;i++){var shape=shapes[i];var latLong=shape.GetPoints()[0];var pixel=that.MapInstance.LatLongToPixel(latLong);if(pixel.x<=mapWidth&&pixel.y<=mapWidth&&pixel.x>=0&&pixel.y>=0){var gridX=Math.floor(pixel.x/gridSize);var gridY=Math.floor(pixel.y/gridSize);var index=gridX+gridY*xCells;if(index<gridCells.length){if(gridCells[index]==null){gridCells[index]=new Array()}gridCells[index].push(shape)}}}for(var i=0;i<gridCells.length;i++){var cell=gridCells[i];var shape=null;if(cell!=null&&cell.length>1&&zoomLevel<minZoomLimit){var latLongs="";for(var shapeIndex=0;shapeIndex<cell.length;shapeIndex++){latLongs+=cell[shapeIndex].GetPoints()[0].toString().replace(" ","");latLongs+=(shapeIndex<=cell.length-2)?"|":""}shape=new VEShape(VEShapeType.Pushpin,cell[0].GetPoints()[0]);shape.SetTitle("cluster");shape.SetDescription(latLongs);shape.SetCustomIcon('<div class="clusterPin"><div class="clusterCount">'+cell.length+"</div></div>");this.ClusterLayer.AddShape(shape)}else{if(cell!=null&&cell.length>0){for(var shapeCount=0;shapeCount<cell.length;shapeCount++){this.ClusterLayer.AddShape(cell[shapeCount])}}}}}function GenerateGrid(){mapWidth=that.MapInstance.GetWidth();mapHeight=that.MapInstance.GetHeight();var xCells=parseInt(Math.ceil(mapWidth/gridSize));var yCells=parseInt(Math.ceil(mapHeight/gridSize));gridCells=new Array(xCells*yCells)}function ShapeToString(shape){var points=shape.GetPoints()[0];var result=points.Latitude+"|"+points.Longitude+"|"+shape.GetDescription()+"|"+shape.GetTitle+"|"+shape.GetCustomIcon();return result}}function deleteFromDist(distArray,allShapes,tmpIndex){var tmpx=Math.floor(allShapes[tmpIndex].x/10);var tmpy=Math.floor(allShapes[tmpIndex].y/10);for(var j=distArray[tmpx][tmpy].length-1;j>=0;j--){if(distArray[tmpx][tmpy][j]==tmpIndex){distArray[tmpx][tmpy].splice(j,1);j=-1}}}var totalx=0;var totaly=0;function customCluster(layer){var pins=new Array();var total=layer.GetShapeCount();var allShapes=new Array();var allShapesIndex=0;if(debug){console.log("In customCluster: ...total Shape in layer: ",total)}totalx=Math.ceil(mapManager.Map.GetWidth()/10)+1;totaly=Math.ceil(mapManager.Map.GetHeight()/10)+1;var distArray=new Array(totalx);for(var i=totalx-1;i>=0;i--){distArray[i]=new Array(totaly);for(var j=totaly-1;j>=0;j--){distArray[i][j]=new Array()}}for(var i=0;i<total;i++){var aShape=layer.GetShapeByIndex(i);var tmp=mapManager.Map.LatLongToPixel(aShape.GetPoints()[0]);var tmpArrayX=Math.floor(tmp.x/10);var tmpArrayY=Math.floor(tmp.y/10);if((tmpArrayX<0)||(tmpArrayX>=totalx)||(tmpArrayY<0)||(tmpArrayY>=totaly)){}else{aShape.x=tmp.x;aShape.y=tmp.y;allShapes.push(aShape);distArray[tmpArrayX][tmpArrayY].push(allShapesIndex);allShapesIndex++}}total=allShapesIndex;if(debug){console.log("In customCluster: total after building grid is: ",total)}if(debug){console.log("In customCluster: allShapes.length is: ",allShapes.length)}var zoomLevel=mapManager.Map.GetZoomLevel();var zoomLevelClusterCompareDist=zoomLevelClusterCompareDistMap[zoomLevel];if(debug){console.log("In customCluster: zoomLevel: %s  zoomLevelClusterCompareDist: %s",zoomLevel,zoomLevelClusterCompareDist)}var maxValue=0;var maxShapes=new Array();var maxIndex=-1;var livingIndicesToAllShapes=new Array(total);var clusterValues=new Array(total);var tmpResult;for(var i=allShapes.length-1;i>=0;i--){livingIndicesToAllShapes[i]=i;tmpResult=singlePinCluster(i,distArray,allShapes,zoomLevelClusterCompareDist);clusterValues[i]=[tmpResult[0],i,tmpResult[1]]}if(debug){console.log("In customCluster: clusterValues: ",clusterValues.length)}while(clusterValues.length>0){clusterValues.sort(clusterValueSort);maxValue=-1;maxIndex=0;var i=0;var go=true;while(go){if(i>=clusterValues.length){go=false}else{var tmp=singlePinCache(clusterValues[i][2],livingIndicesToAllShapes);if(tmp==1){clusterValues.splice(i,1)}else{if(tmp>maxValue){maxValue=tmp;maxIndex=i}if(tmp==clusterValues[i][0]){go=false}clusterValues[i][0]=tmp;i++}}}if(maxValue<=1){return pins}maxShapes=clusterValues[maxIndex][2];var tmp=new VEClusterSpecification();tmp.LatLong=allShapes[clusterValues[maxIndex][1]].GetPoints()[0];livingIndicesToAllShapes=[];var i=clusterValues.length;while(i--){livingIndicesToAllShapes[clusterValues[i][1]]=i}var toDelete=new Array(maxShapes.length);i=maxShapes.length;while(i--){toDelete[i]=livingIndicesToAllShapes[maxShapes[i]]}toDelete.sort(numSort);i=toDelete.length;while(i--){var tmpIndex=clusterValues[toDelete[i]][1];deleteFromDist(distArray,allShapes,tmpIndex);maxShapes[i]=allShapes[tmpIndex];clusterValues.splice(toDelete[i],1);livingIndicesToAllShapes[tmpIndex]=undefined}tmp.Shapes=maxShapes;pins.push(tmp)}if(debug){console.log("In customCluster: End: About to return pins: ",pins.length)}return pins}function clusterValueSort(a,b){return b[0]-a[0]}function numSort(a,b){return a-b}var clusterCompareDist=1600;function singlePinCluster(index,distArray,allShapes,zoomLevelClusterCompareDist){var arrayX=Math.floor(allShapes[index].x/10);var arrayY=Math.floor(allShapes[index].y/10);var minX=(arrayX>4)?arrayX-4:0;var minY=(arrayY>4)?arrayY-4:0;var maxX=(arrayX<(totalx-4))?arrayX+4:totalx-1;var maxY=(arrayY<(totaly-4))?arrayY+4:totaly-1;var shapes=new Array();var value=0;var i=minX-1;while(i++<maxX){var j=minY-1;while(j++<maxY){for(var k=distArray[i][j].length-1;k>=0;k--){if(distBetween(allShapes[index],allShapes[distArray[i][j][k]])<=zoomLevelClusterCompareDist){value++;shapes.push(distArray[i][j][k])}}}}return[value,shapes]}function singlePinCache(cache,livingIndices){var value=0;for(var i=cache.length-1;i>=0;i--){if(livingIndices[cache[i]]==undefined){cache.splice(i,1)}else{value++}}return value}function singlePinCacheCluster(cache,livingIndices){var shapes=[];for(var i=cache.length-1;i>=0;i--){if(livingIndices[cache[i]]!=undefined){shapes.push(cache[i])}}return shapes}function singlePinValue(index,distArray,allShapes){var arrayX=Math.floor(allShapes[index].x/10);var arrayY=Math.floor(allShapes[index].y/10);var minX=(arrayX>4)?arrayX-4:0;var minY=(arrayY>4)?arrayY-4:0;var maxX=(arrayX<(distArray.length-4))?arrayX+4:distArray.length-1;var maxY=(arrayY<(distArray[arrayX].length-4))?arrayY+4:distArray[arrayX].length-1;var value=0;for(var i=minX;i<=maxX;i++){for(var j=minY;j<=maxY;j++){for(var k=distArray[i][j].length-1;k>=0;k--){if(distBetween(allShapes[index],allShapes[distArray[i][j][k]])<=clusterCompareDist){value++}}}}return value}function distBetween(shape1,shape2){var dx=shape1.x-shape2.x;var dy=shape1.y-shape2.y;return Math.floor((dx*dx)+(dy*dy))}function typeAndbusNameSort(a,b){var a_descriptionKey=a.GetDescription();var b_descriptionKey=b.GetDescription();a_descriptionKey=InfoBoxManager.StripSpan(a_descriptionKey);var a_busName=a_descriptionKey.match(/imListing(\d+)/i)[1]+InfoBoxManager.GetName(a_descriptionKey);b_descriptionKey=InfoBoxManager.StripSpan(b_descriptionKey);var b_busName=b_descriptionKey.match(/imListing(\d+)/i)[1]+InfoBoxManager.GetName(b_descriptionKey);return a_busName.localeCompare(b_busName)};
