endeca

Liferay portlet ESRI esri.map.graphics init timing issue

Discussion created by endeca on Oct 13, 2010
Latest reply on Oct 15, 2010 by endeca
I have a liferay portlet which is rendering a map using the javascript api v2.0, and then plotting points on the map.  I am using an ajax call to update the map as user queries change, and have an issue in firefox when my first ajax render call is made (in IE8 it works fine).  The problem is that I call esri.map.graphics.clear before adding each new point, and my javascript throws an exception at that call stating (in firebug) "this.esriMap.graphics is null".  My graphics manipulation and esri.map initialization is happening in a js file called by my view.jsp.  If I place an alert() just prior to the object call to init my esri.map, which is done just prior to making the ajax call to reload the graphics, this problem disappears.  If I place the alert after the init but prior to the ajax call the problem still exists.  I have tried writing wait loops to wait for the graphics obj to init, but they wait forever.  Again, the same code works fine in IE.  Thoughts?  Some of my code:

view.jsp:

e<portlet:namespace/> = new MyObj.Portlets.EsriMap('<portlet:namespace/>', ${showMarkers});
       e<portlet:namespace/>.baseApplyGeoUrl = "<c:out value="${geoActionUrl}" escapeXml="false" />";
       e<portlet:namespace/>.baseGetTileUrl = "<c:out value="${getTileResourceUrl}" escapeXml="false" />";
       e<portlet:namespace/>.latLngParamName = "<c:out value="${LatLngParamName}" escapeXml="false" />";
       e<portlet:namespace/>.latLngValueParamName = "<c:out value="${LatLngValueParamName}" escapeXml="false" />";
       e<portlet:namespace/>.radiusParamName = "<c:out value="${radiusParamName}" escapeXml="false" />";
       e<portlet:namespace/>.baseGetDataUrl = "<c:out value="${getDataResourceUrl}" escapeXml="false" />";
       e<portlet:namespace/>.analyticsBased = "<c:out value="${analyticsBased}" escapeXml="false" />";
       e<portlet:namespace/>.filterOnMove = ${enableFilterOnMove};
       
       e<portlet:namespace/>.initMap("heatmap_map_<portlet:namespace/>", "${geoCodeProperty}", ${prefsHeatMap}, "${esriMapService}");
     e<portlet:namespace/>.testAsync = function(){
      if(typeof(asyncObj<portlet:namespace/>) != 'undefined'){
       e<portlet:namespace/>.asyncObject = asyncObj<portlet:namespace/>;
       e<portlet:namespace/>.reloadMap(); 
      }else{
       setTimeout("e<portlet:namespace/>.testAsync();", 100);
      }
       };
       e<portlet:namespace/>.testAsync();


back-end js

  initMap: function(mapElement, geocodeField, enableHeatMap, esriTiledMapService, renderDataFunc) {
  //TODO - do we need to check for existing map and clear it?
 
  this.geoCodeField = geocodeField;
    this.enableHeatMap = enableHeatMap;
    this.mapElement = mapElement;
    
  this.esriMap = new esri.Map(mapElement);
  var mapLayer = new esri.layers.ArcGISTiledMapServiceLayer(esriTiledMapService);
  this.esriMap.addLayer(mapLayer);
     dojo.connect(this.esriMap, "onLoad", this.initToolbar());
  //ASYNC should do below calls as it sets data elements on page
  //this.autozoom();
       //this.plotmarkers();
     this.enableGeoFilter = false;
  jQuery('#modeButton_' + this.portletId).addClass("buttonUnClicked");
  jQuery('#modeButton_' + this.portletId).removeClass("buttonClicked");
   },
   
   initToolbar: function() {
  this.esriToolbar = new esri.toolbars.Draw(this.esriMap);

    var instance = this;
  // Set range filter event handler...
        dojo.connect(this.esriToolbar, "onDrawEnd", function (geometry) {
         instance.toggleSelectionMode();
        var symbol = instance.esriToolbar.fillSymbol;
        instance.esriMap.graphics.add(new esri.Graphic(geometry, symbol));
        
      var centerLat = (geometry.ymax+geometry.ymin)/2;
      var centerLng = (geometry.xmax+geometry.xmin)/2;
      var radius = instance.distanceBetween(centerLat, centerLng, geometry.ymin, geometry.xmin);
          instance.applyGeoFilter(instance.geoCodeField, centerLat, centerLng, radius,
            "("+geometry.ymin+","+geometry.xmin+", "+geometry.ymax+","+geometry.xmax+")");
       });
   },

   plotmarkers: function(){
     try {
      this.esriMap.graphics.clear();

      var dataPoints = jQuery('#' + this.portletId).data('dataPoints');
      if(!dataPoints){
       setTimeout("e"+this.portletId+".plotmarkers()",500);
         return false;
        }
 
      //var symbol = new esri.symbol.PictureMarkerSymbol('./images/marker.gif', 13, 13);
      var symbol = new esri.symbol.SimpleMarkerSymbol(esri.symbol.SimpleMarkerSymbol.STYLE_CIRCLE, 15,
        new esri.symbol.SimpleLineSymbol(), new dojo.Color([255,255,0,0.5]));
 
      for (var i=1;i<dataPoints.length;i++){
       var marker=dataPoints[i];
       if (marker.lat==''||marker.lon=='') continue;
       if (marker.lon>180 || marker.lon<-180) continue;
       if (marker.lat<0) continue;
       
       var lat=parseFloat(marker.lat);
       var lon=parseFloat(marker.lon);
       
       if (lat!=marker.lat||lon!=marker.lon) continue;
       
       var geometry=new esri.geometry.Point(lon,lat, new esri.SpatialReference({ wkid: 4326 }));
       var info = new esri.InfoTemplate("<div class=\"popUpDiv\"><pre>"+marker.popupString + "</pre></div>");
       //var info = new esri.InfoTemplate("Record: "+marker.lbl, "<a href=\""+marker.url+"\">"+marker.lbl+"</a>");
       var graphic = new esri.Graphic(geometry, symbol);
       graphic.setInfoTemplate(info);
       this.esriMap.graphics.add(graphic);  
      }    
         //initialize onmouseover and onmouseout listeners for markers
      var map = this.esriMap;
         dojo.connect(this.esriMap.graphics, "onMouseOver", function(evt) {
             var overGraphic = evt.graphic;
             map.infoWindow.setTitle(overGraphic.getTitle());
             map.infoWindow.setContent(overGraphic.getContent()+"<br>lat,lon: " + evt.mapPoint.y + "," + evt.mapPoint.x);
             map.infoWindow.show(evt.screenPoint,map.getInfoWindowAnchor(evt.mapPoint));
         });
         dojo.connect(this.esriMap.graphics, "onMouseOut", function(evt) {
             map.infoWindow.hide();
         });

        this.asyncObject.stopSpinner();
       }
       catch(e)
       {
        this.asyncObject.stopSpinner();
        if(console)
         console.log(e);
       }  
    },
    
   reloadMap: function() {
    this.asyncObject.startSpinner();
    jQuery('#' + this.portletId).removeData('dataPoints'); 
    this.updateMapContent();
   },
   
   updateMapContent: function() { 
    // Trigger AJAX request
  var url = this.baseGetDataUrl;
  var instance = this;
  jQuery.ajax({
   url:url,
   cache: false,
   type: "GET",
   data:this.callbackParamName + "=?&" +
    this.latLngParamName + "=" + this.geoCodeField +
    "&PortletId=" + this.portletId+"&reloadType="+this.reloadType,
   success: function(data) {
    var jData = jQuery("<div/>").html(data);
    var paging = jData.find(".ResultsPagination");
    var vizContainer = jQuery("#container_" + instance.portletId);
    if(instance.showMarkers){
     vizContainer.find(".ResultsPagination").empty().append(paging.children());
     var resultsControls = jData.find(".ResultsControls");
     vizContainer.find(".ResultsControls").empty().append(resultsControls.children());
    }
    var results = jData.find(".encodedResults");
    vizContainer.find(".encodedResults").empty().append(results.children());
    
    instance.plotmarkers();
    instance.autozoom();
      }
  }); 
   }
   

Outcomes