# Map Application Requires Refresh to Initialize

I tried this question over on StackOverflow but didn't get any answers. Hoping you all might be able to help.

Creating a web mapping application in Javascript/Dojo:

When I load the app in a browser it loads the html elements but then stops processing. I have to refresh the browser to get it to load the rest of the page and the javascript.

I have done testing and debugging all day and figured out I had my external JS files in the wrong spot (I'm a rookie). Fixed that and the app loads great...EXCEPT one of my files isn't getting read correctly, or at all.

When I move the contents of the external JS file in question to the main code in the default, the functionality that they contain, work fine... BUT the map requires the refresh again.

Stumped. Below is the code in the external JS file that is causing my issue. I can't figure out why it is a problem because the functions work as expected when it is not external.

Any help is greatly appreciated.

//Toggles
function basemapToggle() {
basemaptoggler = new dojo.fx.Toggler({
node: "basemaptoggle",
showFunc : dojo.fx.wipeIn,
showDuration: 1000,
hideDuration: 1000,
hideFunc : dojo.fx.wipeOut
})
}
dojo.addOnLoad(basemapToggle);

function layerToggle() {
layertoggler = new dojo.fx.Toggler({
node: "layertoggle",
showFunc : dojo.fx.wipeIn,
showDuration: 750,
hideDuration: 750,
hideFunc : dojo.fx.wipeOut
})
}
dojo.addOnLoad(layerToggle);

function legendToggle() {
legendtoggler = new dojo.fx.Toggler({
node: "legendtoggle",
showFunc : dojo.fx.wipeIn,
hideFunc : dojo.fx.wipeOut
})
}
dojo.addOnLoad(legendToggle);


Here is the front part of my code

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=7, IE=8, IE=9" />
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
<title>
Zoning Classifications
</title>
<link rel="Stylesheet" href="ZoningClassifications.css" />
<link rel="stylesheet" type="text/css" href="http://serverapi.arcgisonline.com/jsapi/arcgis/3.0/js/dojo/dijit/themes/claro/claro.css">
<link rel="stylesheet" type="text/css" href="http://serverapi.arcgisonline.com/jsapi/arcgis/3.0/js/esri/dijit/css/Popup.css">
<link rel="stylesheet" type="text/css" href="http://serverapi.arcgisonline.com/jsapi/arcgis/3.0/js/dojo/dojox/grid/resources/Grid.css">
<link rel="stylesheet" type="text/css" href="http://serverapi.arcgisonline.com/jsapi/arcgis/3.0/js/dojo/dojox/grid/resources/claroGrid.css">
<style type="text/css">
</style>

<script src="JS/layers.js"></script>
<script src="JS/search.js"></script>
<script src="JS/basemapgallery.js"></script>

<script src="JS/identify.js"></script>
<script src="JS/toggles.js"></script>
<script type="text/javascript">
var djConfig = {
parseOnLoad: true
};
</script>
<script type="text/javascript" src="http://serverapi.arcgisonline.com/jsapi/arcgis/?v=3.0"></script>
<script type="text/javascript">

dojo.require("dijit.dijit"); // optimize: load dijit layer
dojo.require("dijit.layout.BorderContainer");
dojo.require("dijit.layout.ContentPane");
dojo.require("esri.map");
dojo.require("dijit.TitlePane");
dojo.require("esri.dijit.BasemapGallery");
dojo.require("esri.arcgis.utils");
dojo.require("esri.tasks.locator");
dojo.require("esri.dijit.Legend");
dojo.require("esri.dijit.Popup");
dojo.require("dijit.form.Button");
dojo.require("dojo.fx");
dojo.require("dijit.Dialog");
dojo.require("dojo.ready");
dojo.require("dijit.TooltipDialog");
dojo.require("dojox.grid.DataGrid");
dojo.require("dojo.data.ItemFileReadStore");
dojo.require("esri.tasks.find");


EDIT 2 I've completely rewritten the app placing all the code (except the css) in the main default.html file. I tested piece by piece to make sure it functioned how I want. Adding the toggles code is the only code that throws it and causes the extra refresh.

So for now I am using dijit.TitlePane to hold the drop down elements (basemap gallery, layers, legend). However with this you can not change the look and feel to make them images, which is my end goal.

Can anybody suggest an alternative so I can use 3 different images so that when you click on the image and drop down menu opens holding the basemap gallery, layer list and legend?

-
I don't see a head/body tag in here, is all your javascript code loaded in the header or not ? –  Glenn Plas Oct 18 '12 at 13:14
Sorry. Fixed it. Somehow it got formatted out when I started the post. –  Craig Oct 18 '12 at 13:18
–  Mapperz Oct 18 '12 at 17:08
tried it, but nothing. I am almost certain the issue is with my dojo.fx.Toggler functions. All my other external js files work perfectly. Not sure why I'm getting trouble. Contacted ESRI and they are looking into it, so hopefully I'll have a resolution soon. –  Craig Oct 18 '12 at 17:24
Have you tried using something like the Chrome developer tools to see what external files are actually getting loaded? This might at least tell you how far your page is getting in loading the files and where any errors are. –  pecoanddeco Oct 24 '12 at 14:53

## 3 Answers

I would consolidate all of those dojo.addOnLoad() calls. I suspect something isn't getting loaded before a function is getting called.

Strip all dojo.addOnLoad calls from all of your external javascript files and bundle them into one call in your main HTML file. Put all the functions you want to fire on load into a new function at the bottom of your javascript like this:

function init() {
basemapToggle();
layerToggle();
whatEver();
}
dojo.addOnLoad(init);


This will ensure that everything has loaded before trying to fire off any functions.

-

If you want to finecontrol / test this deeper, outside what any framework (jquery/dojo) has to start this. You could try this little library:

var stack = [],
interval,
loaded; // has window.onload fired?

function doPoll() {
var notFound = [];
for (var i=0; i<stack.length; i++) {
if (document.getElementById(stack[i].id)) {
stack[i].callback();
} else {
notFound.push(stack[i]);
}
}
stack = notFound;
if (notFound.length < 1 || loaded) {
stopPolling();
}
}

function startPolling() {
if (interval) {return;}
interval = setInterval(doPoll, 10);
}

function stopPolling() {
if (!interval) {return;}
clearInterval(interval);
interval = null;
}

function onAvailable(id, callback) {
stack.push({id:id, callback:callback});
startPolling();
}

window.onload = function() {
loaded = true;
doPoll();
};


And then use it like this :

onAvailable('map', function () {
// Only do stuff here once the map div is available (this always happens after the DOM is ready)
....
});


Basically what you do is say: wait to do stuff until this div exists. It behaves differently than document.ready , 'firing' a tad later. so for you , you would put the code with dojo.* here.

It's a great test to see if you happen to get bitten by the load order of some javascript code. I'm giving this because it has been of good use to (troubleshoot) sort out these sort of problems.

-
I've tried incorporating your suggestion to my code without any luck. Can you help further explain where this should go in my existing mess? –  Craig Oct 23 '12 at 12:17
put the top block in a seperate js file, include it in the header, then test for your dom elements you act on, in your code : onAvailable('basemapToggle', function () { dojo.addOnLoad(basemapToggle); });It's not a solution directly but it will help you understand your load order problem –  Glenn Plas Oct 23 '12 at 14:57

It looks like you're having a script order issue. Your toggles.js relies on dojo being loaded. However, in your html, you're calling toggles.js before loading ESRI's javascript api, which loads dojo. Here's a suggestion as to how you could reorganize your scripts.

...
<style type="text/css"></style>

<script type="text/javascript">
var djConfig = { parseOnLoad: true };
</script>
<script type="text/javascript" src="http://serverapi.arcgisonline.com/jsapi/arcgis/?v=3.0"></script>
<script type="text/javascript">

dojo.require("dijit.dijit"); // optimize: load dijit layer
dojo.require("dijit.layout.BorderContainer");
dojo.require("dijit.layout.ContentPane");
dojo.require("esri.map");
dojo.require("dijit.TitlePane");
dojo.require("esri.dijit.BasemapGallery");
dojo.require("esri.arcgis.utils");
dojo.require("esri.tasks.locator");
dojo.require("esri.dijit.Legend");
dojo.require("esri.dijit.Popup");
dojo.require("dijit.form.Button");
dojo.require("dojo.fx");
dojo.require("dijit.Dialog");
dojo.require("dojo.ready");
dojo.require("dijit.TooltipDialog");
dojo.require("dojox.grid.DataGrid");
dojo.require("dojo.data.ItemFileReadStore");
dojo.require("esri.tasks.find");
</script>
<script src="JS/layers.js"></script>
<script src="JS/search.js"></script>
<script src="JS/basemapgallery.js"></script>

<script src="JS/identify.js"></script>
<script src="JS/toggles.js"></script>
...

-
I tried re ordering the scripts. When I place the external scripts after the API script, only the html loads (header, logo, subheader). I then have to refresh to get the javascript to load. –  Craig Oct 22 '12 at 18:34
I edited my last answer. Try also putting the dojo.requires script ahead of your external files. Also, you might consider moving your external scripts to the bottom of the html body, to ensure that all DOM elements have loaded before those scripts run. –  raykendo Oct 22 '12 at 18:48
both of your edited options result in the same error, needing to refresh to load the js. –  Craig Oct 22 '12 at 18:59