blob: 19b6473013bdf4289d47ffad39f5e3d615121272 [file] [log] [blame]
/*
Copyright (c) 2004-2006, The Dojo Foundation
All Rights Reserved.
Licensed under the Academic Free License version 2.1 or above OR the
modified BSD license. For more information on Dojo licensing, see:
http://dojotoolkit.org/community/licensing.shtml
*/
/*
* Adobe SVG Viewer host environment
*/
if(typeof window == 'undefined'){
dojo.raise("attempt to use adobe svg hostenv when no window object");
}
with(dojo.render){
name = navigator.appName;
ver = parseFloat(navigator.appVersion, 10);
switch(navigator.platform){
case "MacOS":
os.osx = true;
break;
case "Linux":
os.linux = true;
break;
case "Windows":
os.win = true;
break;
default:
os.linux = true;
break;
};
svg.capable = true;
svg.support.builtin = true;
svg.adobe = true;
};
// browserEval("alert(window.location);");
dojo.hostenv.println = function(s){
try{
// FIXME: this may not work with adobe's viewer, as we may first need a
// reference to the svgDocument
// FIXME: need a way to determine where to position the text for this
var ti = document.createElement("text");
ti.setAttribute("x","50");
var yPos = 25 + 15*document.getElementsByTagName("text").length;
ti.setAttribute("y",yPos);
var tn = document.createTextNode(s);
ti.appendChild(tn);
document.documentElement.appendChild(ti);
}catch(e){
}
}
dojo.debug = function() {
if (!djConfig.isDebug) { return; }
var args = arguments;
if(typeof dojo.hostenv.println != 'function'){
dojo.raise("attempt to call dojo.debug when there is no dojo.hostenv println implementation (yet?)");
}
var isJUM = dj_global["jum"];
var s = isJUM ? "": "DEBUG: ";
for(var i=0;i<args.length;++i){ s += args[i]; }
if(isJUM){ // this seems to be the only way to get JUM to "play nice"
jum.debug(s);
}else{
dojo.hostenv.println(s);
}
}
dojo.hostenv.startPackage("dojo.hostenv");
dojo.hostenv.name_ = 'adobesvg';
dojo.hostenv.anonCtr = 0;
dojo.hostenv.anon = {};
dojo.hostenv.nameAnonFunc = function(anonFuncPtr, namespaceObj){
var ret = "_"+this.anonCtr++;
var nso = (namespaceObj || this.anon);
while(typeof nso[ret] != "undefined"){
ret = "_"+this.anonCtr++;
}
nso[ret] = anonFuncPtr;
return ret;
}
dojo.hostenv.modulesLoadedFired = false;
dojo.hostenv.modulesLoadedListeners = [];
dojo.hostenv.getTextStack = [];
dojo.hostenv.loadUriStack = [];
dojo.hostenv.loadedUris = [];
dojo.hostenv.modulesLoaded = function(){
if(this.modulesLoadedFired){ return; }
if((this.loadUriStack.length==0)&&(this.getTextStack.length==0)){
if(this.inFlightCount > 0){
dojo.debug("couldn't initialize, there are files still in flight");
return;
}
this.modulesLoadedFired = true;
var mll = this.modulesLoadedListeners;
for(var x=0; x<mll.length; x++){
mll[x]();
}
}
}
dojo.hostenv.getNewAnonFunc = function(){
var ret = "_"+this.anonCtr++;
while(typeof this.anon[ret] != "undefined"){
ret = "_"+this.anonCtr++;
}
// this.anon[ret] = function(){};
eval("dojo.nostenv.anon."+ret+" = function(){};");
return [ret, this.anon[ret]];
}
dojo.hostenv.displayStack = function(){
var oa = [];
var stack = this.loadUriStack;
for(var x=0; x<stack.length; x++){
oa.unshift([stack[x][0], (typeof stack[x][2])]);
}
dojo.debug("<pre>"+oa.join("\n")+"</pre>");
}
dojo.hostenv.unwindUriStack = function(){
var stack = this.loadUriStack;
for(var x in dojo.hostenv.loadedUris){
for(var y=stack.length-1; y>=0; y--){
if(stack[y][0]==x){
stack.splice(y, 1);
}
}
}
var next = stack.pop();
if((!next)&&(stack.length==0)){
return;
}
for(var x=0; x<stack.length; x++){
if((stack[x][0]==next[0])&&(stack[x][2])){
next[2] == stack[x][2]
}
}
var last = next;
while(dojo.hostenv.loadedUris[next[0]]){
last = next;
next = stack.pop();
}
while(typeof next[2] == "string"){ // unwind as far as we can
try{
// dojo.debug("<pre><![CDATA["+next[2]+"]]></pre>");
dj_eval(next[2]);
next[1](true);
}catch(e){
dojo.debug("we got an error when loading "+next[0]);
dojo.debug("error: "+e);
// for(var x in e){ alert(x+" "+e[x]); }
}
dojo.hostenv.loadedUris[next[0]] = true;
dojo.hostenv.loadedUris.push(next[0]);
last = next;
next = stack.pop();
if((!next)&&(stack.length==0)){ break; }
while(dojo.hostenv.loadedUris[next[0]]){
last = next;
next = stack.pop();
}
}
if(next){
stack.push(next);
dojo.debug("### CHOKED ON: "+next[0]);
}
}
/**
* Reads the contents of the URI, and evaluates the contents.
* Returns true if it succeeded. Returns false if the URI reading failed. Throws if the evaluation throws.
* The result of the eval is not available to the caller.
*/
dojo.hostenv.loadUri = function(uri, cb){
if(dojo.hostenv.loadedUris[uri]){
return;
}
var stack = this.loadUriStack;
stack.push([uri, cb, null]);
var tcb = function(contents){
// gratuitous hack for Adobe SVG 3
if(contents.content){
contents = contents.content;
}
// stack management
var next = stack.pop();
if((!next)&&(stack.length==0)){
dojo.hostenv.modulesLoaded();
return;
}
if(typeof contents == "string"){
stack.push(next);
for(var x=0; x<stack.length; x++){
if(stack[x][0]==uri){
stack[x][2] = contents;
}
}
next = stack.pop();
}
if(dojo.hostenv.loadedUris[next[0]]){
// dojo.debug("WE ALREADY HAD: "+next[0]);
dojo.hostenv.unwindUriStack();
return;
}
// push back onto stack
stack.push(next);
if(next[0]!=uri){
// and then unwind as far as we can
if(typeof next[2] == "string"){
dojo.hostenv.unwindUriStack();
}
}else{
if(!contents){
next[1](false);
}else{
var deps = dojo.hostenv.getDepsForEval(next[2]);
if(deps.length>0){
eval(deps.join(";"));
}else{
dojo.hostenv.unwindUriStack();
}
}
}
}
this.getText(uri, tcb, true);
}
/**
* loadModule("A.B") first checks to see if symbol A.B is defined.
* If it is, it is simply returned (nothing to do).
* If it is not defined, it will look for "A/B.js" in the script root directory, followed
* by "A.js".
* It throws if it cannot find a file to load, or if the symbol A.B is not defined after loading.
* It returns the object A.B.
*
* This does nothing about importing symbols into the current package.
* It is presumed that the caller will take care of that. For example, to import
* all symbols:
*
* with (dojo.hostenv.loadModule("A.B")) {
* ...
* }
*
* And to import just the leaf symbol:
*
* var B = dojo.hostenv.loadModule("A.B");
* ...
*
* dj_load is an alias for dojo.hostenv.loadModule
*/
dojo.hostenv.loadModule = function(modulename, exact_only, omit_module_check){
// alert("dojo.hostenv.loadModule('"+modulename+"');");
var module = this.findModule(modulename, 0);
if(module){
return module;
}
// dojo.debug("dojo.hostenv.loadModule('"+modulename+"');");
// protect against infinite recursion from mutual dependencies
if (typeof this.loading_modules_[modulename] !== 'undefined'){
// NOTE: this should never throw an exception!! "recursive" includes
// are normal in the course of app and module building, so blow out of
// it gracefully, but log it in debug mode
// dojo.raise("recursive attempt to load module '" + modulename + "'");
dojo.debug("recursive attempt to load module '" + modulename + "'");
}else{
this.addedToLoadingCount.push(modulename);
}
this.loading_modules_[modulename] = 1;
// convert periods to slashes
var relpath = modulename.replace(/\./g, '/') + '.js';
var syms = modulename.split(".");
var nsyms = modulename.split(".");
if(syms[0]=="dojo"){ // FIXME: need a smarter way to do this!
syms[0] = "src";
}
var last = syms.pop();
syms.push(last);
// figure out if we're looking for a full package, if so, we want to do
// things slightly diffrently
var _this = this;
var pfn = this.pkgFileName;
if(last=="*"){
modulename = (nsyms.slice(0, -1)).join('.');
var module = this.findModule(modulename, 0);
// dojo.debug("found: "+modulename+"="+module);
if(module){
_this.removedFromLoadingCount.push(modulename);
return module;
}
var nextTry = function(lastStatus){
if(lastStatus){
module = _this.findModule(modulename, false); // pass in false so we can give better error
if((!module)&&(syms[syms.length-1]!=pfn)){
dojo.raise("Module symbol '" + modulename + "' is not defined after loading '" + relpath + "'");
}
if(module){
_this.removedFromLoadingCount.push(modulename);
dojo.hostenv.modulesLoaded();
return;
}
}
syms.pop();
syms.push(pfn);
// dojo.debug("syms: "+syms);
relpath = syms.join("/") + '.js';
if(relpath.charAt(0)=="/"){
relpath = relpath.slice(1);
}
// dojo.debug("relpath: "+relpath);
_this.loadPath(relpath, ((!omit_module_check) ? modulename : null), nextTry);
}
nextTry();
}else{
relpath = syms.join("/") + '.js';
modulename = nsyms.join('.');
var nextTry = function(lastStatus){
// dojo.debug("lastStatus: "+lastStatus);
if(lastStatus){
// dojo.debug("inital relpath: "+relpath);
module = _this.findModule(modulename, false); // pass in false so we can give better error
// if(!module){
if((!module)&&(syms[syms.length-1]!=pfn)){
dojo.raise("Module symbol '" + modulename + "' is not defined after loading '" + relpath + "'");
}
if(module){
_this.removedFromLoadingCount.push(modulename);
dojo.hostenv.modulesLoaded();
return;
}
}
var setPKG = (syms[syms.length-1]==pfn) ? false : true;
syms.pop();
if(setPKG){
syms.push(pfn);
}
relpath = syms.join("/") + '.js';
if(relpath.charAt(0)=="/"){
relpath = relpath.slice(1);
}
// dojo.debug("relpath: "+relpath);
_this.loadPath(relpath, ((!omit_module_check) ? modulename : null), nextTry);
}
this.loadPath(relpath, ((!omit_module_check) ? modulename : null), nextTry);
}
return;
}
/**
* Read the contents of the specified uri and return those contents.
*
* FIXME: Make sure this is consistent with other implementations of getText
* @param uri A relative or absolute uri. If absolute, it still must be in the same "domain" as we are.
* @param async_cb If not specified, returns false as synchronous is not
* supported. If specified, load asynchronously, and use async_cb as the handler which receives the result of the request.
* @param fail_ok Default false. If fail_ok and !async_cb and loading fails, return null instead of throwing.
*/
dojo.hostenv.async_cb = null;
dojo.hostenv.unWindGetTextStack = function(){
if(dojo.hostenv.inFlightCount>0){
setTimeout("dojo.hostenv.unWindGetTextStack()", 100);
return;
}
// we serialize because this environment is too messed up
// to know how to do anything else
dojo.hostenv.inFlightCount++;
var next = dojo.hostenv.getTextStack.pop();
if((!next)&&(dojo.hostenv.getTextStack.length==0)){
dojo.hostenv.inFlightCount--;
dojo.hostenv.async_cb = function(){};
return;
}
dojo.hostenv.async_cb = next[1];
// http = window.getURL(uri, dojo.hostenv.anon[cbn]);
window.getURL(next[0], function(result){
dojo.hostenv.inFlightCount--;
dojo.hostenv.async_cb(result.content);
dojo.hostenv.unWindGetTextStack();
});
}
dojo.hostenv.getText = function(uri, async_cb, fail_ok){
// dojo.debug("Calling getText()");
try{
if(async_cb){
dojo.hostenv.getTextStack.push([uri, async_cb, fail_ok]);
dojo.hostenv.unWindGetTextStack();
}else{
return dojo.raise("No synchronous XMLHTTP implementation available, for uri " + uri);
}
}catch(e){
return dojo.raise("No XMLHTTP implementation available, for uri " + uri);
}
}
/**
* Makes an async post to the specified uri.
*
* FIXME: Not sure that we need this, but adding for completeness.
* More details about the implementation of this are available at
* http://wiki.svg.org/index.php/PostUrl
* @param uri A relative or absolute uri. If absolute, it still must be in the same "domain" as we are.
* @param async_cb If not specified, returns false as synchronous is not
* supported. If specified, load asynchronously, and use async_cb as the progress handler which takes the xmlhttp object as its argument. If async_cb, this function returns null.
* @param text Data to post
* @param fail_ok Default false. If fail_ok and !async_cb and loading fails, return null instead of throwing.
* @param mime_type optional MIME type of the posted data (such as "text/plain")
* @param encoding optional encoding for data. null, 'gzip' and 'deflate' are possible values. If browser does not support binary post this parameter is ignored.
*/
dojo.hostenv.postText = function(uri, async_cb, text, fail_ok, mime_type, encoding){
var http = null;
var async_callback = function(httpResponse){
if (!httpResponse.success) {
dojo.raise("Request for uri '" + uri + "' resulted in " + httpResponse.status);
}
if(!httpResponse.content) {
if (!fail_ok) dojo.raise("Request for uri '" + uri + "' resulted in no content");
return null;
}
// FIXME: wtf, I'm losing a reference to async_cb
async_cb(httpResponse.content);
}
try {
if(async_cb) {
http = window.postURL(uri, text, async_callback, mimeType, encoding);
} else {
return dojo.raise("No synchronous XMLHTTP post implementation available, for uri " + uri);
}
} catch(e) {
return dojo.raise("No XMLHTTP post implementation available, for uri " + uri);
}
}
/*
* It turns out that if we check *right now*, as this script file is being loaded,
* then the last script element in the window DOM is ourselves.
* That is because any subsequent script elements haven't shown up in the document
* object yet.
*/
function dj_last_script_src() {
var scripts = window.document.getElementsByTagName('script');
if(scripts.length < 1){
dojo.raise("No script elements in window.document, so can't figure out my script src");
}
var li = scripts.length-1;
var xlinkNS = "http://www.w3.org/1999/xlink";
var src = null;
var script = null;
while(!src){
script = scripts.item(li);
src = script.getAttributeNS(xlinkNS,"href");
li--;
if(li<0){ break; }
// break;
}
if(!src){
dojo.raise("Last script element (out of " + scripts.length + ") has no src");
}
return src;
}
if(!dojo.hostenv["library_script_uri_"]){
dojo.hostenv.library_script_uri_ = dj_last_script_src();
}
// dojo.hostenv.loadUri = function(uri){
/* FIXME: adding a script element doesn't seem to be synchronous, and so
* checking for namespace or object existance after loadUri using this
* method will error out. Need to figure out some other way of handling
* this!
*/
/*
var se = document.createElement("script");
se.src = uri;
var head = document.getElementsByTagName("head")[0];
head.appendChild(se);
// document.write("<script type='text/javascript' src='"+uri+"' />");
return 1;
}
*/