Issue loading Search widget intermittently

1673
7
Jump to solution
11-18-2016 11:45 AM
NhuMai
by
New Contributor II

I am attempting to implement a few widgets in my app: search, identify, print, and third-party TOC widget. Each widget works individually, but when bringing it all together, the search widget does not work intermittently (sometimes it works, sometimes it doesn't). The request for the feature returns a result, but the map does not zoom to the feature.

I realized that when the Search doesn't work, the Search.js file does not load at all.

A breakpoint on line 35 of Search.js  is only reached when the widget works..this is not surprising. However, I cannot see what is keeping us from getting there.
var sources = search.get("sources");

UPDATE: This is particularly confusing, as setting enableInfoWindow and showInfoWindowOnSelect to true succeeds in finding the feature and opening the infoWindow for the search. Clicking on the default zoom link succeeds in zooming to the window. However, my app doesn't enable infoWindows for the search, as certain Identify elements are signaled by the opening of infoWindows.

var search = new Search({
 enableButtonMode: true, //this enables the search widget to display as a single button
 enableLabel: false,
 enableInfoWindow: true,
 showInfoWindowOnSelect: true,
 map: map
 }, "search");

The source code is in a public github repository.

When everything works:

When Search does not work--but map loads, print works, and identify works:

The code is also below, if you are willing to take a look:

index.html:

<!DOCTYPE html>
<html dir="ltr">
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no" />
 <title>A title</title>
 <link rel="stylesheet" href="http://js.arcgis.com/3.17/dijit/themes/claro/claro.css">
 <link rel="stylesheet" href="http://js.arcgis.com/3.17/esri/css/esri.css">
 <link rel="stylesheet" href="http://js.arcgis.com/3.18/dojox/layout/resources/ExpandoPane.css">
 <link rel="stylesheet" href="css/widget_styles.css">

<script>
 var dojoConfig = {
 //parseOnLoad: true,
 packages: [
 {
 name: "agsjs",
 //location: location.pathname.replace(/\/[^/]+$/, "") + '../../agsjs'
 "location": '/SPE_SIG/agsjs' // for xdomain load
 }]
 };
 </script>

<script src="http://js.arcgis.com/3.17/"></script>

<script type="text/javascript">
 dojo.require("dojox.layout.ExpandoPane");
 </script>

<script src="js/Map.js"></script>
<script src="js/Legend.js"></script>
<script src="js/Search.js"></script>
<script src="js/Print.js"></script>
<script src="js/Identify.js"></script>


</head>

<body class="claro">

<div id="content"
 data-dojo-type="dijit/layout/BorderContainer"
 data-dojo-props="design:'headline', gutters:true"
 style="width: 100%; height: 100%; margin: 0;">

<div id="rightPane"
 data-dojo-type="dojox/layout/ExpandoPane"
 data-dojo-props="region:'right',title:'Outils',startExpanded:false">

<div data-dojo-type="dijit/layout/AccordionContainer">
 <div data-dojo-type="dijit/layout/ContentPane" id="legendPane"
 data-dojo-props="title:'Légende', selected:true">
 <div id="legendDiv"></div>
 </div>
 <div data-dojo-type="dijit/layout/ContentPane"
 data-dojo-props="title:'Impressions'">
 <div id="print_button"></div>
 </div>
 </div>
 </div>

<div id="map"
 data-dojo-type="dijit/layout/ContentPane"
 data-dojo-props="region:'center'"
 style="overflow: hidden;width: 100%; height: 100%; margin: 0;">
 </div>
 <div id="tabs" dojoType="dijit/layout/TabContainer" style="width:385px; height:150px;">
 <div id="eCompteTab" dojoType="dijit/layout/ContentPane" title="E_COMPTE"></div>
 <div id="eTroncoTab" dojoType="dijit/layout/ContentPane" title="E_TRONCO"></div>
 </div>
 <div id="search"></div>
 </div>
</body>

</html>

css:

html, body {
 height: 97%;
 width: 98%;
 margin: 1%;
}

#search {
 display: block;
 position: absolute;
 z-index: 2;
 top: 20px;
 left: 74px;
}

#rightPane {
 width: 20%;
}

#map {
 width: 75%;
}

#legendPane {
 border: solid #97DCF2 1px;
}

h3 { margin: 0 0 5px 0; border-bottom: 1px solid #444; padding: 0 0 5px 0; text-align: center; }
.shadow {
 -moz-box-shadow: 0 0 5px #888;
 -webkit-box-shadow: 0 0 5px #888;
 box-shadow: 0 0 5px #888;
}

#feedback {
 background: #fff;
 color: #000;
 position: absolute;
 font-family: arial;
 height: auto;
 right: 20px;
 margin: 5px;
 padding: 10px;
 top: 20px;
 width: 300px;
 z-index: 40;
}
#feedback a {
 border-bottom: 1px solid #888;
 color: #444;
 text-decoration: none;
}
#feedback a:hover, #feedback a:active, #feedback a:visited {
 border: none;
 color: #444;
 text-decoration: none;
}
#note { font-size: 80%; font-weight: 700; padding: 0 0 10px 0; }
#info { padding: 10px 0 0 0; }

Identify.js:

var eCompteResults
var eTroncoResults

require([
 "esri/map",
 "esri/layers/ArcGISDynamicMapServiceLayer",
 "esri/layers/FeatureLayer",
 "esri/symbols/SimpleFillSymbol",
 "esri/symbols/SimpleLineSymbol",
 "esri/symbols/SimpleMarkerSymbol",
 "esri/tasks/IdentifyTask",
 "esri/tasks/IdentifyParameters",
 "dojo/on",
 "dojo/parser",
 "esri/Color",
 "dijit/registry",
 "dijit/form/Button",
 "dijit/layout/ContentPane",
 "dijit/layout/TabContainer",
 "dojo/domReady!"
 ],
 function (
 Map, ArcGISDynamicMapServiceLayer, FeatureLayer, SimpleFillSymbol, SimpleLineSymbol, SimpleMarkerSymbol,
 IdentifyTask, IdentifyParameters, on, parser, Color, registry
 ) {

parser.parse();

var identifyTask, identifyParams;

// map = new Map("mapDiv", {
 // basemap: "streets",
 // center: [-83.275, 42.573],
 // zoom: 18
 // });
 //map.on("layers-add-result", initFunctionality);
 initFunctionality();
 // var landBaseLayer = new ArcGISDynamicMapServiceLayer("https://sampleserver3.arcgisonline.com/ArcGIS/rest/services/BloomfieldHillsMichigan/Parcels/MapServer", {
 // opacity: 0.2
 // });
 map.infoWindow.on("show", function () {
 registry.byId("tabs").resize();
 });
 //map.addLayer(landBaseLayer);

function initFunctionality () {
 map.on("click", doIdentify);

identifyTask = new IdentifyTask("https://sampleserver3.arcgisonline.com/ArcGIS/rest/services/BloomfieldHillsMichigan/Parcels/MapServer");

identifyParams = new IdentifyParameters();
 identifyParams.tolerance = 3;
 identifyParams.returnGeometry = true;
 //identifyParams.layerIds = [1, 15];
 identifyParams.layerIds = [0, 2];
 identifyParams.layerOption = IdentifyParameters.LAYER_OPTION_ALL;
 identifyParams.width = map.width;
 identifyParams.height = map.height;

map.infoWindow.resize(415, 200);
 map.infoWindow.setContent(registry.byId("tabs").domNode);
 map.infoWindow.setTitle("Identify Results");


 // symbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID,
 // new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
 // new Color([255, 0, 0]), 2),
 // new Color([255, 255, 0, 0.25]));
 }

function doIdentify (event) {
 map.graphics.clear();
 identifyParams.geometry = event.mapPoint;
 identifyParams.mapExtent = map.extent;
 identifyTask.execute(identifyParams, function (idResults) {
 addToMap(idResults, event);
 });
 }

function addToMap (idResults, event) {
 eCompteResults = { displayFieldName: null, features: [] };
 eTroncoResults = { displayFieldName: null, features: [] };

for (var i = 0, il = idResults.length; i < il; i++) {
 var idResult = idResults;
 if (idResult.layerId === 1) {
 symbol = new SimpleMarkerSymbol(SimpleFillSymbol.STYLE_SQUARE,
 new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
 new Color([255, 0, 0]), 2),
 new Color([255, 255, 0, 0.25]));

if (!eCompteResults.displayFieldName) { eCompteResults.displayFieldName = idResult.displayFieldName; }
 eCompteResults.features.push(idResult.feature);
 }
 else if (idResult.layerId === 15) {
 symbol = new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
 new Color([255, 0, 0]), 2);
 if (!eTroncoResults.displayFieldName) { eTroncoResults.displayFieldName = idResult.displayFieldName; }
 eTroncoResults.features.push(idResult.feature);
 }
 }
 registry.byId("eCompteTab").set("content", eCompteResultTabContent(eCompteResults));
 registry.byId("eTroncoTab").set("content", eTroncoResultTabContent(eTroncoResults));

map.infoWindow.show(event.screenPoint,
 map.getInfoWindowAnchor(event.screenPoint));
 }

function eCompteResultTabContent (results) {
 var template = "";
 var features = results.features;

template += "<i>Nombre d'entités trouvées: " + features.length + "</i>";
 template += "<table border='1'>";
 template += "<tr><th>NUMERO</th><th>DIAMETRE</th><th>DATE DE POSE</th><th>UD</th></tr>";

var numeroCPTPPT;
 var diametreCPTPPT;
 for (var i = 0, il = features.length; i < il; i++) {
 numeroECOMPTEPPT = features.attributes['NUMERO'];
 diametreECOMPTEPPT = features.attributes['DIAMETRE'];
 dateposeECOMPTEPPT = features.attributes['DATEPOSE'];
 udECOMPTEPPT = features.attributes['UD'];

template += "<tr>";
 template += "<td>" + numeroECOMPTEPPT + " <a href='#' onclick='showFeature(eCompteResults.features[" + i + "]); return false;'>(afficher)</a></td>";
 template += "<td>" + diametreECOMPTEPPT + "</td>";
 template += "<td>" + dateposeECOMPTEPPT + "</td>";
 template += "<td>" + udECOMPTEPPT + "</td>";
 template += "</tr>";
 }

template += "</table>";

return template;
 }

function eTroncoResultTabContent (results) {
 var template = "";
 var features = results.features;

template = "<i>Nombre d'entités trouvées: " + features.length + "</i>";
 template += "<table border='1'>";
 template += "<tr><th>DIAMETRE</th><th>MATERIAU</th><th>DATE DE POSE</th><th>LONGUEUR</th><th>PROFONDEUR</th><th>SECTO</th><th>UD</th></tr>";

var diametreETRONCOPPT;
 var materiauETRONCOPPT;
 var dateposeETRONCOPPT;
 var longueurETRONCOPPT;
 var profondETRONCOPPT;
 var sectoETRONCOPPT;
 var udETRONCOPPT;
 for (var i = 0, il = features.length; i < il; i++) {
 diametreETRONCOPPT = features.attributes['DIAMETRE'];
 materiauETRONCOPPT = features.attributes['MATERIAU'];
 dateposeETRONCOPPT = features.attributes['DATEPOSE'];
 longueurETRONCOPPT = features.attributes['LONGCALC'];
 profondETRONCOPPT = features.attributes['PROFOND'];
 sectoETRONCOPPT = features.attributes['SECTO'];
 udETRONCOPPT = features.attributes['UD'];

template += "<tr>";
 template += "<td>" + diametreETRONCOPPT + " <a href='#' onclick='showFeature(eTroncoResults.features[" + i + "]); return false;'>(afficher)</a></td>";
 template += "<td>" + materiauETRONCOPPT + "</td>";
 template += "<td>" + dateposeETRONCOPPT + "</td>";
 template += "<td>" + longueurETRONCOPPT + "</td>";
 template += "<td>" + profondETRONCOPPT + "</td>";
 template += "<td>" + sectoETRONCOPPT + "</td>";
 template += "<td>" + udETRONCOPPT + "</td>";
 template += "</tr>";
 }

template += "</table>";

return template;
 }
 });

function showFeature (feature) {
 map.graphics.clear();
 feature.setSymbol(symbol);
 map.graphics.add(feature);
 }



Legend.js:

var toc, layerInfo;

 require([
 "esri/map", "esri/layers/ArcGISDynamicMapServiceLayer",
 "dojo/_base/array", "dojo/parser", "agsjs/dijit/TOC",
 "dijit/layout/BorderContainer", "dijit/layout/ContentPane",
 "dijit/layout/AccordionContainer", "dojo/domReady!"
 ], function (
 Map, ArcGISDynamicMapServiceLayer,
 arrayUtils, parser, TOC
 ) {
 parser.parse();

 map.on("layers-add-result", function (evt) {
 toc = new TOC({
 map: map,
 layerInfos: [
 {
 layer: baseMapLayerWorld,
 title: "FDP Esri",
 collapsed: true
 //layerList: layerInfo
 }
 ]
 }, 'legendDiv');
 toc.startup();
 });

 });

Map.js:

var map;
var baseMapLayerWorld;





require([
 "esri/map",
 "esri/dijit/Search",
 "esri/layers/ArcGISDynamicMapServiceLayer",
 "esri/layers/FeatureLayer",
 "esri/InfoTemplate",
 "dijit/layout/BorderContainer",
 "dijit/layout/ContentPane",
 "dojo/domReady!"
], function (Map, Search, DynamicMapServiceLayer, FeatureLayer, InfoTemplate) {




baseMapLayerWorld = new esri.layers.ArcGISTiledMapServiceLayer("http://services.arcgisonline.com/arcgis/rest/services/World_Street_Map/MapServer");





 map = new Map("map", {
 center: [-150, -17], // lon, lat
 zoom: 8
 });




map.addLayers([baseMapLayerWorld]);




});

Print.js:

require([
 "esri/map",
 "esri/layers/FeatureLayer",
 "esri/dijit/Print",
 "esri/tasks/PrintTemplate",
 "esri/request",
 "esri/config",
 "dojo/_base/array",
 "dojo/dom",
 "dojo/parser",
 "dijit/layout/BorderContainer",
 "dijit/layout/ContentPane",
 "dojo/domReady!"
], function(
 Map, FeatureLayer,
 Print, PrintTemplate,
 esriRequest, esriConfig,
 arrayUtils, dom, parser
) {
 parser.parse();
 
 var printUrl = "http://sampleserver6.arcgisonline.com/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%20Web%20Map%20Task";
 
 esriConfig.defaults.io.proxyUrl = "http://csslsystem-072/dotnet1/proxy.ashx";
 
 // get print templates from the export web map task
 var printInfo = esriRequest({
 "url": printUrl,
 "content": { "f": "json" }
 });
 printInfo.then(handlePrintInfo, handleError);
 
 function handlePrintInfo(resp) {
 var layoutTemplate, templateNames, mapOnlyIndex, templates;
 
 layoutTemplate = arrayUtils.filter(resp.parameters, function(param, idx) {
 return param.name === "Layout_Template";
 });
 
 if ( layoutTemplate.length === 0 ) {
 console.log("print service parameters name for templates must be \"Layout_Template\"");
 return;
 }
 templateNames = layoutTemplate[0].choiceList;
 
 // remove the MAP_ONLY template then add it to the end of the list of templates
 mapOnlyIndex = arrayUtils.indexOf(templateNames, "MAP_ONLY");
 if ( mapOnlyIndex > -1 ) {
 var mapOnly = templateNames.splice(mapOnlyIndex, mapOnlyIndex + 1)[0];
 templateNames.push(mapOnly);
 }
 
 // create a print template for each choice
 templates = arrayUtils.map(templateNames, function(ch) {
 var plate = new PrintTemplate();
 plate.layout = plate.label = ch;
 plate.format = "PDF";
 plate.layoutOptions = {
 "authorText": "Made by: Esri's JS API Team",
 "copyrightText": "<copyright info here>",
 "legendLayers": [],
 "titleText": "Pool Permits",
 "scalebarUnit": "Miles"
 };
 return plate;
 });
 
 // create the print dijit
 printer = new Print({
 "map": map,
 "templates": templates,
 url:printUrl
 }, dom.byId("print_button"));
 printer.startup();
 }
 
 function handleError(err) {
 console.log("Something broke: ", err);
 }
});

Search.js:

require([
 "esri/map", "esri/dijit/Search", "esri/layers/ArcGISDynamicMapServiceLayer","esri/layers/FeatureLayer", "esri/InfoTemplate", "dojo/domReady!"
], function (Map, Search, DynamicMapServiceLayer, FeatureLayer, InfoTemplate) {

var search = new Search({
 enableButtonMode: true, //this enables the search widget to display as a single button
 enableLabel: false,
 enableInfoWindow: false,
 showInfoWindowOnSelect: false,
 map: map
 }, "search");

var sources = search.get("sources");

//Push the sources used to search, by default the ArcGIS Online World geocoder is included. In addition there is a feature layer of US congressional districts. The districts search is set up to find the "DISTRICTID". Also, a feature layer of senator information is set up to find based on the senator name.
 sources.push({
 featureLayer: new FeatureLayer("https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/CongressionalDistricts/FeatureServer/0"),
 searchFields: ["DISTRICTID"],
 displayField: "DISTRICTID",
 exactMatch: false,
 outFields: ["DISTRICTID", "NAME", "PARTY"],
 name: "Congressional Districts",
 placeholder: "3708",
 maxResults: 6,
 maxSuggestions: 6,

//Create an InfoTemplate and include three fields
 infoTemplate: new InfoTemplate("Congressional District", "District ID: ${DISTRICTID}</br>Name: ${NAME}</br>Party Affiliation: ${PARTY}"),
 enableSuggestions: true,
 minCharacters: 0
 });

sources.push({
 featureLayer: new FeatureLayer("https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/US_Senators/FeatureServer/0"),
 searchFields: ["Name"],
 displayField: "Name",
 exactMatch: false,
 name: "Senator",
 outFields: ["*"],
 placeholder: "Senator name",
 maxResults: 6,
 maxSuggestions: 6,

//Create an InfoTemplate

infoTemplate: new InfoTemplate("Senator information", "Name: ${Name}</br>State: ${State}</br>Party Affiliation: ${Party}</br>Phone No: ${Phone_Number}<br><a href=${Web_Page} target=_blank ;'>Website</a>"),

enableSuggestions: true,
 minCharacters: 0
 });

//Set the sources above to the search widget
 search.set("sources", sources);

search.startup();

});
Tags (1)
0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Nhu,

   I updated a lot of your code but the main thing was to call all your other scripts after the map was loaded as many of them were dependent on the map.

View solution in original post

0 Kudos
7 Replies
RobertScheitlin__GISP
MVP Emeritus

Nhu,

   I updated a lot of your code but the main thing was to call all your other scripts after the map was loaded as many of them were dependent on the map.

0 Kudos
NhuMai
by
New Contributor II

Hi Robert,

Thank you for taking an in depth look at my app. I can see that you have restructured a lot of things, like you said, notably related to the way the scripts are called. This is extremely helpful.

To deploy your version of the app I made two changes:
-updated the proxy url to our local url, as I think the sample proxy I had included originally is now expired.
-updated the identification task url to use our own service instead of the sample, because it was giving me an error related to CORS. This service has been used for identification task before with success.

The app was mainly tested using Chrome. Testing the app on Firefox produces the same results, but not the same errors messages.

When testing this your version, I sometimes had a couple of issues. I say sometimes, because emptying the cache and refreshing sometimes succeeded in loading the content pane (first issue on list still exists) :
- While the search now works, identification no longer works. Clicking on the map produces an error: Error processing 'imageDisplay' for identify operation.
- the right pane doesn't load (including the legend, an print button--when the right pane does load the print widget seems to work fine and the legend is properly populated).

I can't tell if it's related to this error on line 26 of Identify.js: Uncaught TypeError: Cannot read property 'domNode' of undefined(...) (using Chrome).
The line it refers to is this: window.myMap.infoWindow.setContent(registry.byId("tabs").domNode);
I wonder if this thread is similar to my issue--however, moving the "tabs" div within the "content" div did not seem to remove this error.

I have also tried to integrate your changes into my application--the source code is here if you think looking at the updated app would help you help me : D.
The issues in terms of app functionality are the same as mentioned above.

As far as I can tell (by checking the sources tab in Google Chrome developers tools), all the js files were loaded.

Mahalo!

0 Kudos
NhuMai
by
New Contributor II

Okay, I responded too quickly. I found the reason why Identify doesn't work. It's because the width and height of identifyParams still refers to var map and not window.myMap.

That being said, identify now works, search works, print works....now the legend won't populate...! Setting a breakpoint at toc.startup(), but it is never reached.

Just giving you an update in case you see anything flagrant that may be causing this. On a big picture scale, though, I will accept your answer.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Nhu,

   I changed the package location for the code to work on my end so you probably need to change it back:

packages: [
{
name: "agsjs",
"location": '/js/nhu/SPE_SIG/agsjs' // for xdomain load
}, {

0 Kudos
NhuMai
by
New Contributor II

Oups--I had forgotten to mention that I did make that change to reflect my package location.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Strange it worked on my end

0 Kudos
NhuMai
by
New Contributor II

Okay figured it out--have to create the legend and start it up directly instead of doing it this way:

 map.on("layers-add-result", function (evt) {}
0 Kudos