Multiple Versions of Dojo in a Page
This Document is Out of Date. For the current documentation, please see http://docs.dojocampus.org/
As of Dojo 1.1, it is possible to run multiple versions of Dojo in a page, or to even rename the global "dojo", "dijit" and "dojox" variables to some other variable. This capability is useful if:
- You want to provide your own custom, namespaced library that uses Dojo underneath. It will be possible to use your own private Dojo version without having another version of Dojo on the page interfering with your code.
- You want to experiment with Dojo 1.1 features with a project using Dojo 1.0 or earlier.
See the Limitations section below for important restrictions on this feature.
Provide custom namespaced library
You want to create a JavaScript library that you want to distribute to others to use in their pages. The users of your library may be using Dojo on their page, and you want your version of Dojo to not interact with their version.
You call your code "coolio". As you are developing your code, you are using a normal build of Dojo 1.1+ and have your scripts laid out like so:
-scripts
-dojo
-dijit
-dojox
-coolio
-actions.js
-tests
-test.html
The interface you want to publish to others consists of just one function: coolio.actions.foo(), and it is defined inside the scripts/coolio/actions.js file:
dojo.require("dojo.dnd");
dojo.require("dijit.ProgressBar");
coolio.actions.foo = function() { /* Does something that uses dojo.dnd and dijit.ProgressBar */ }
You want to use Dojo, but you do not want it to conflict with other Dojo versions on the page. In this case you can use a djConfig.scopeMap to map dojo, dijit and dojox to different names. Your test page, tests/test.html, might be set up like so:
<script type="text/javascript">
djConfig = {
scopeMap: [
["dojo", "coolio"],
["dijit", "cooliow"],
["dojox", "cooliox"],
],
modulePaths: {
"coolio.actions": "../coolio/actions"
}
}
</script>
<script type="text/javascript" src="../scripts/dojo/dojo.js"></script>
<script type="text/javascript">
coolio.require("coolio.actions");
//Notice if you want to include some dojo functionality,
//you need to reference the "dojo" name in the require call,
//but it will be added to the "coolio" object:
coolio.require("dojo.string");
coolio.addOnLoad(function(){
//do something with coolio.actions.foo();
//Can call coolio.string.trim() too.
});
</script>
</head>
For this test page, djConfig.scopeMap has mapped "dojo" to "coolio", "dijit" to "cooliow" and "dojox" to "cooliox". dojo, dijit and dojox will not be visible to this HTML page, just coolio, cooliow and cooliox.
It is not recommended that you map dojo, dijit and dojox all to coolio. Doing so may result in some inadvertent clobbering of variables or objects, since you are basically collapsing dojo, dijit and dojox on top of each other. For example, if dojo.bar was defined and dijit.bar was defined, then one of them would clobber the other.
Also notice the modulePaths configuration for coolio.actions. If we did not do that, the coolio.require("coolio.actions") call would fail.
You can now develop your coolio.actions library in this manner. You can even use djConfig.debugAtAllCosts to do debugging (note that using debugAtAllCosts exposes dojo, dijit and dojox as global variables, so only test with your code in the page, and not mixed with code from another Dojo version).
Once you are ready to deliver your code to other people, use the Dojo build system to wrap up your code into a deliverable to give to others.
Build time
The build system allows you to "burn in" the scopeMap into the built JS file, avoiding the need for others to do that work.
Define a build profile like the below and save it as coolio.profile.js:
layers: [
{
name: "dojo.js",
dependencies: [
"coolio.actions"
]
}
],
prefixes: [
[ "dijit", "../dijit" ],
[ "dojox", "../dojox" ]
//The mapping below assumes you placed "coolio"
//as a sibling to the dojo directory. If not, adjust
//the path accordingly.
[ "coolio", "../coolio" ]
]
}
Notice the layer name is "dojo.js". This will make it so that your code is merged in with the base dojo.js, so that there is just one layer file that end users have to use. Once the build is complete, feel free to rename the file to "coolio.js" if you like.
The build command to burn in the scope map will look something like this (For Windows, change build.sh to build.bat and use ' instead of \"):
./build.sh profile=coolio releaseName=coolio version=0.1.0coolio action=release scopeMap=[[\"dojo\",\"coolio\"],[\"dijit\",\"cooliow\"],[\"dojox\",\"cooliox\"]]
The build command above assumes you saved coolio.profile.js in util/buildscripts/profiles. If you have it saved somewhere else, then replace profile=coolio with profileFile=path/to/coolio.profile.js.
This build command will generate a release/coolio directory. At this point you can rename release/coolio/dojo.js to release/coolio/coolio.js if you like.
Deliver the contents of release/coolio to the developers using your library. You can try to deliver just release/coolio/coolio.js, but depending on which dojo/dijit/dojox modules you use, that file may not be enough. You will likely need to do testing to see exactly what files are needed. If you only used the Dojo Base functionality (what comes with the normal dojo.js file), then you are fine just delivering the release/coolio/coolio.js file.
XDomain Build
If you plan on making an XDomain Build, there are a couple of other build arguments you need to pass:
./build.sh profile=coolio releaseName=coolio version=0.1.0coolio action=release loader=xdomain xdDojoScopeName=coolio xdDojoPath=http://some.domain.com/path/to/coolio scopeMap=[[\"dojo\",\"coolio\"],[\"dijit\",\"cooliow\"],[\"dojox\",\"cooliox\"]]
This command assumes you will be hosting your code at http://some.domain.com/path/to/coolio/. Under that directory would be the dojo, dijit, dojox and coolio directories.
For xdomain builds, you will want to rename release/coolio/dojo.xd.js to release/coolio/coolio.xd.js, and tell developers to reference http://some.domain.com/path/to/coolio/dojo/coolio.xd.js in their pages.
Using Dojo 1.1 with previous versions of Dojo
You may have an application running Dojo 0.4.3, but you might want to start playing with Dojo 1.1 features. It is always more efficient for the browser if you only use one version of Dojo in your page, but you may not have the time to port your whole application to Dojo 1.1 yet.
Suppose you have your code laid out like so:
-scripts
-dojo110 (Dojo 1.1.0 build)
-dojo
-dojo.js
-dijit
-dojox
-dojo043 (Dojo 0.4.3 build)
-dojo.js
-src
-...
-tests
-test.html
To use both versions in a page, the tests/test.html file would look like
<script type="text/javascript">
djConfig = {
parseOnLoad: true,
baseUrl: "../scripts/dojo110/dojo/",
scopeMap: [
["dojo", "dojo11"],
["dijit", "dijit11"],
["dojox", "dojox11"]
]
}
</script>
<script type="text/javascript" src="../scripts/dojo110/dojo/dojo.js"></script>
<script type="text/javascript">
//Notice that djConfig is being redefined here.
djConfig = {
isDebug: true,
baseRelativePath: "../scripts/dojo043/"
}
</script>
<script type="text/javascript" src="../scripts/dojo043/dojo.js"></script>
<script type="text/javascript">
dojo.require("dojo.widget.DropdownDatePicker");
//Notice the require strings use "dojo" and "dijit"
//instead of "dojo11" and "dijit11". However, the objects
//will be used on the page by their "dojo11" and "dijit11"
//names. For instance, you do a dojo11.require("dojo.string");,
//but in this page you would call dojo11.string.trim().
dojo11.require("dijit._Calendar");
dojo11.require("dojo.date.locale");
dojo11.require("dojo.parser"); // scan page for widgets
dojo.addOnLoad(function(){
//Do something with Dojo 0.4.3 in here.
});
dojo11.addOnLoad(function(){
//Do something with Dojo 1.1 in here.
});
</script>
</head>
</body>
<input dojoType="dropdowndatepicker" value="2006-10-31" containerToggle="wipe" containerToggleDuration="300" >
<p class="tundra">
<input id="calendar1" dojo11Type="dijit11._Calendar">
</body>
The important points to remember:
- You can redefine djConfig after Dojo 1.1 is included in the page. This is because Dojo 1.1 keeps an internal copy of the djConfig structure.
- Only use debugAtAllCosts with Dojo 1.1 if you remove the Dojo 0.4.3 code from the page. Otherwise, bad things will happen. You probably can use debugAtAllCosts with the Dojo 0.4.3 code while Dojo 1.1 is in the page.
For doing builds with multiple versions of Dojo, see the preceding section on custom namespaced libraries. Just replace coolio, cooliow and cooliox with dojo11, dijit11 and dojox11 respectively.
Limitations
There are some limitations to this feature:
- Always use dojo.require() to load code. Do not use script tags in HTML to load the modules. The scoping is accomplished by using the dojo.require machinery. Using raw script tags will break things.
- djConfig.debugAtAllCosts only works with one version of Dojo in the page. You can use a scopeMap, but no other versions of Dojo can be in the page.
- You must use a build of Dojo to get this behavior. It does not work with running Dojo from a source distribution.
- The order of the djConfig.scopeMap array items is important. It always needs to be dojo, dijit then dojox. In addition to the order being important, you must define mappings for all three.
- dojo.back only works with one version of Dojo in the page, and it must be named "dojo". Do not use a scopeMap.
- Printer-friendly version
- Login or register to post comments
- Unsubscribe post

IE7 fails
I'm having a wierd issue. IE7 fails to load the scoped dojo properly on the first access. If I reload the page, he properly instantiates both dojos and everything works just fine.
I have a dojo 043 application and no time to do a full port to 1.0 , so this scoping feature is a godsend. I followed the example in the ticket for this feature in trac ( http://trac.dojotoolkit.org/ticket/4573 ) and this got me by great (once I defined a proper baseUrl and baseScriptUrl for the scoped dojo).
Also, for me, this only works if I have dojo 043 loaded before 1.0 like what is described in the ticket but unlike what happens here.
I do not want to have to make a build with the namespace "bruned into" dojo.js but if I must, its certainly ok.
Any help is greatly appreciated.
UODATE: this issue also happens in the example provided in the ticket above.
cheers
Miguel
The multiple version support
The multiple version support is only available in Dojo 1.1+. In other words, you will be able to mix 0.4.3 and 1.1 together, but not 0.4.3 and 1.0.
Cudn't run it on FF3 either
I'm using FF3 and IE7 and dojo-0.4.3 with dojo1.1.1(I guess they are not source but build as I have downloaded them from download section where only builds are available )
I tried the above script and all I get is
""
FATAL exception raised: Could not load 'dojo.debug'; last tried '__package__.js'
FATAL exception raised: Could not load 'dojo.widget.DropdownDatePicker'; last tried '__package__.js'
""
Anybody please help me.
Alternative to baseRelativePath
Concerning:
FATAL exception raised: Could not load 'dojo.widget.DropdownDatePicker'; last tried '__package__.js'
I had this problem running 0.4.2 and 1.1.1, I found by setting the baseScriptUri instead of baseRelativePath in the 4.0.2 djConfig instance fixed the problem, looking at firebug it appeared it was trying to load DropdownDatePicker from 1.1.1 pathing:
djConfig = {
isDebug: false,
baseScriptUri: "./js/dojo042/"
}
If you want to know why, look at the dojo.js 4.0.2 code, you will be able to figure out.
Sytax error at the build command
The build command is missing a comma between '\"cooliow\"]' and '[\"dojox\"'.It took one half a day figuring out this.
./build.sh profile=coolio releaseName=coolio version=0.1.0coolio action=release scopeMap=[[\"dojo\",\"coolio\"],[\"dijit\",\"cooliow\"][\"dojox\",\"cooliox\"]]
Ouch! Sorry for the trouble.
Ouch! Sorry for the trouble. Thanks for the report -- I added the comma back in.
Thanks jburke
Thanks jburke for this feature! It's absolutely critical in portlet development, and especially with IBM WebSphere Portal 6.1 moving toward using dojo heavily. At my company we have lots of portlets developed using dojo 0.4.3, and we don't have the time to go back and port them all to 1.1.1 right away. This will allow us to develop new portlets using dojo 1.1.1 and include them on the same page as the old portlets.
Custom build yelds an error loading
Hi. I have an app with both 0.4.3 and 1.1.
Im trying to get a build to stuff it all into one file. The problem is, when including the dojox.grid.Grid in the build, loading the page starts off with the following error:
dojo.i18n._preloadLocalizations is not a function dojo.js()()dojo.js (line 20) [Break on this error] (function(){var _1=[["dojo","dojo10"],["...o.nls.dojo",["xx","ROOT","en","en-us"]);A bit digging in, showed me that some of the dijits used by the Grid (for inline editing) try to make use of dojo.i18n._preloadLocalizations instead of dojo10.i18n._preloadLocalizations .
I tried shuffling the order that the files are declared in the profile.js file but that didn't work.
The same happens if I try to import dijit-all (which i don't need, i was just testing).
Could this be the method that calls that dojo.i18n._preloadLocalizations is not included in the dojo name change? .
Any help, even just to say its an existing bug, would be very very appreciated.
Some details:
profile
dependencies = { layers: [ { name: "dojo.js", dependencies: [ "dijit.dijit", "dojox.data.QueryReadStore", "dojox.data.ItemFileReadStore", "dojox.grid._data.model", "dojox.grid.Grid", ] }, ], prefixes: [ [ "dijit", "../dijit" ], [ "dojox", "../dojox" ] ] }---
build command:
Sorry, this is a bug in the
Sorry, this is a bug in the build system. It was fixed in Dojo 1.2:
http://bugs.dojotoolkit.org/ticket/6878
You can either try upgrading to Dojo 1.2 or applying the changeset in the ticket mentioned above to your 1.1 util/buildscripts directory.
Thanks :)
Thank you very much for that. That seems to fix it.
Thanks again :D
In regards to custom
In regards to custom namespacing , can i do something like this;
scripts
--dojo
--MyApi
-----app.js
can i scopeMap dojo to MyApi.dojo as below , by giving these arguments while making a custom build.
djConfig = {
scopeMap: [
["dojo", "MyApi.dojo"], ]
}
I tried this using Dojo Toolbox in the advance config by renaming dojo, it seems not to accept 'MyApi.dojo' , throws not valid name. Is this configuration possible. ideally I want app.js to use something like MyApi.dojo.byId().
Thanks in Advance
Ganesh Subbiah
Sorry, dots in the scopeMap
Sorry, dots in the scopeMap name are treated as part of a directory path when mapping resource names to paths on disk to load modules. You could use "MyApi_dojo". Also note there is a bug in the multiversion support that requires you to enter scopeMap entries for dijit and dojox.
In this case I have declared
In this case I have declared MyApi as global object , I got this scenario to working, Yes I saw that bug (http://trac.dojotoolkit.org/ticket/7894)
I have this in my scopMap mapping [["dojo","MyApi.dojo"],["dijit","MyApi.dijit"],["dojox","MyApi.dojox"] , After doing this, i am able to reference MyApi.dojo which works fine, But still i see the error as mentioned in the bug 7894 (Animation not defined)
If I use 'MyApi_dojo' everything works fine. Is this because the djConfig's scopeMap supports only 'prefix based namespacing' but not 'Single Object Namespacing'
I believe the issue is the
I believe the issue is the convention that Dojo uses to map resource names (like foo.bar) to files on disk (foo/bar.js). If you put a dot in the name it will assume it is a path separator when trying to load the file.
Thanks for explanation, As
Thanks for explanation, As per convention now I have folder structure as follows
scripts
--MyApi
-----MyApi.js [ This file creates MyApi object,which is my namespace i want to use throughout my api]
-----dojo
-----app.js
I use these tags
script type="text/javascript" src="scripts/MyApi/MyApi.js">
script type="text/javascript" src="scripts/MyApi/dojo/dojo.js">
In this case with above scopemap settings (MyApi.dojo) , it should work fine right ? I tried this scenario,
I can do MyApi.dojo.byId() // works fine. Only issue is that the error dojo._animation is undefined is still present
If MyApi/MyApi.js is
If MyApi/MyApi.js is referencing dojo._Animation then i can see the problem -- the dojo.js script tag will have to come above the one for the MyApi.js file for that to work. Then, in a script block before dojo.js, you could try doing MyApi = {} to make sure that object exists before the scopeMap takes effect.
i am not referring
i am not referring dojo._Animation in this file. I have been using MyApi.js to create this MyApi={} object, it is a non-dojo js file, I am not able to include this with the build, so I create this objectby manually inserting var MyApi = {} into the post-build dojo.js file.
This is what i am doing . Look at this latest profile and command prompt settings I have been using.
Can you let us know why this error still occurs.
It occurs at this line : dojo._Animation.prototype._startTimer
This is the profile of this custom build:
dependencies = {
layers: [
{
name: "dojo.js",
dependencies: [
"myApi.app",
"myApi.core"
]
}
],
prefixes: [
[ "myApi", "../myApi" ]
]
}
batch.bat profile=myApi releaseName=latest version=1.0 action=release scopeMap=[[\"dojo\",\"myApi.dojo\"],[\"dijit\",\"myApi.dijit\"],[\"dojox\",\"myApi.dojox\"]]
I have tried this scenario in dojo 1.2.3 ( this version does not allow this above setting to execute through build script, it complains 'myApi' not defined, I set the scopeMap after the build] and also dojo1.3bv2 [ allows to set this setting during the build], After the build, I manually insert var myApi= {} into dojo.js.
Multiple Dojo 1.2.2 versions doesn't work in IE7 in 2 portlets
We are running the Dojo inside portlets and when there is more than one portlet that is using Dojo on a page, we are encoutering a failure.
When we used the Dojo 1.1, its code was wrapped in following if:
// Dojo code
}
But in Dojo 1.2.2 this check was removed for some reason.
We had to add this check to Dojo to make it work, but after this we encountered another issue with IE browsers (6 & 7): Inside the Dojo code there are the following lines that were never executed in IE when using multiple versions of Dojo:
// for Internet Explorer. readyState will not be achieved on init
// call, but dojo doesn't need it however, we'll include it
// because we don't know if there are other functions added that
// might. Note that this has changed because the build process
// strips all comments -- including conditional ones.
if(!dojo.config.afterOnLoad){
document.write('<scr'+'ipt defer src="//:" '
+ 'onreadystatechange="if(this.readyState==\'complete\'){' + dojo._scopeName + '._loadInit();}">'
+ '</scr'+'ipt>'
);
}
}
We replaced the document.write directive with the following code:
// for Internet Explorer. readyState will not be achieved on init
// call, but dojo doesn't need it however, we'll include it
// because we don't know if there are other functions added that
// might. Note that this has changed because the build process
// strips all comments -- including conditional ones.
if(!dojo.config.afterOnLoad){
document.attachEvent('onreadystatechange',function(){
if(document.readyState == 'complete'){
document.detachEvent('onreadystatechange',arguments.callee);
dojo.getObject(dojo._scopeName)._loadInit();
}
});
// If not inside an IFRAME
if(self==top){
var timer = setTimeout(function() {
try {
// Try to scroll the document in order to
// verify that the page is already loaded
doc.documentElement.doScroll("left");
} catch(e) {
return;
}
clearTimeout(timer);
dojo.getObject(dojo._scopeName)._loadInit();
},
500);
}
}
}
Now it is working and we wish to submit this patch to Dojo.
Could you please evaluate it and tell us how to proceed with the submission?
Thank you,
David Roberin
Amdocs Ltd.
davidro: So the issue is
davidro: So the issue is multiple copies of dojo.js are included in the page, but they are all the same version of Dojo? If that is the case, then I would have expected the if (typeof dojo != "undefined") check wrapped around the dojo.js base file to be enough of a fix, since that is what we did before. We did not need the extra IE loading logic you have above.
The if() check was removed as part of the scopeMap support for dojo (having mulitple versions of Dojo in a page, not copies of the same version of Dojo), but I agree it should be fixed. I opened this bug for the issue:
http://bugs.dojotoolkit.org/ticket/7689
Thank you for the prompt
Thank you for the prompt response!
But the IE loading is required, because without it we receive the Operation Aborted message in IE (6 & 7) which is explained in http://support.microsoft.com/kb/927917.
This fix solves the problem.
If there is more accurate way to check whether the page is already loaded instead of the scrolling, please let us know.
Thank you,
David Roberin
Amdocs Ltd.
It would be good to get a
It would be good to get a test page of the issue in IE. I have heard of it happening, but to date without a reproducible test case it is hard for us to accept patches for it -- we want to have a test file we can use when we need to change the onload code in the future, to make sure we do not re-introduce the issue. I can appreciate that it may be hard to give a test page though given the nature of running multiple copies of dojo in the page.