blob: e858af44dee56918217b852fdaee86ac6d0e2bf4 [file] [log] [blame]
/*==================================================
* Simile Ajax API
*
* Include this file in your HTML file as follows:
*
* <script src="http://simile.mit.edu/ajax/api/simile-ajax-api.js" type="text/javascript"></script>
*
*==================================================
*/
if (typeof SimileAjax == "undefined") {
var SimileAjax = {
loaded: false,
loadingScriptsCount: 0,
error: null,
params: { bundle:"true" }
};
SimileAjax.Platform = new Object();
/*
HACK: We need these 2 things here because we cannot simply append
a <script> element containing code that accesses SimileAjax.Platform
to initialize it because IE executes that <script> code first
before it loads ajax.js and platform.js.
*/
var getHead = function(doc) {
return doc.getElementsByTagName("head")[0];
};
SimileAjax.findScript = function(doc, substring) {
var heads = doc.documentElement.getElementsByTagName("head");
for (var h = 0; h < heads.length; h++) {
var node = heads[h].firstChild;
while (node != null) {
if (node.nodeType == 1 && node.tagName.toLowerCase() == "script") {
var url = node.src;
var i = url.indexOf(substring);
if (i >= 0) {
return url;
}
}
node = node.nextSibling;
}
}
return null;
};
SimileAjax.includeJavascriptFile = function(doc, url, onerror, charset) {
onerror = onerror || "";
if (doc.body == null) {
try {
var q = "'" + onerror.replace( /'/g, '&apos' ) + "'"; // "
doc.write("<script src='" + url + "' onerror="+ q +
(charset ? " charset='"+ charset +"'" : "") +
" type='text/javascript'>"+ onerror + "</script>");
return;
} catch (e) {
// fall through
}
}
var script = doc.createElement("script");
if (onerror) {
try { script.innerHTML = onerror; } catch(e) {}
script.setAttribute("onerror", onerror);
}
if (charset) {
script.setAttribute("charset", charset);
}
script.type = "text/javascript";
script.language = "JavaScript";
script.src = url;
return getHead(doc).appendChild(script);
};
SimileAjax.includeJavascriptFiles = function(doc, urlPrefix, filenames) {
for (var i = 0; i < filenames.length; i++) {
SimileAjax.includeJavascriptFile(doc, urlPrefix + filenames[i]);
}
SimileAjax.loadingScriptsCount += filenames.length;
SimileAjax.includeJavascriptFile(doc, SimileAjax.urlPrefix + "scripts/signal.js?" + filenames.length);
};
SimileAjax.includeCssFile = function(doc, url) {
if (doc.body == null) {
try {
doc.write("<link rel='stylesheet' href='" + url + "' type='text/css'/>");
return;
} catch (e) {
// fall through
}
}
var link = doc.createElement("link");
link.setAttribute("rel", "stylesheet");
link.setAttribute("type", "text/css");
link.setAttribute("href", url);
getHead(doc).appendChild(link);
};
SimileAjax.includeCssFiles = function(doc, urlPrefix, filenames) {
for (var i = 0; i < filenames.length; i++) {
SimileAjax.includeCssFile(doc, urlPrefix + filenames[i]);
}
};
/**
* Append into urls each string in suffixes after prefixing it with urlPrefix.
* @param {Array} urls
* @param {String} urlPrefix
* @param {Array} suffixes
*/
SimileAjax.prefixURLs = function(urls, urlPrefix, suffixes) {
for (var i = 0; i < suffixes.length; i++) {
urls.push(urlPrefix + suffixes[i]);
}
};
/**
* Parse out the query parameters from a URL
* @param {String} url the url to parse, or location.href if undefined
* @param {Object} to optional object to extend with the parameters
* @param {Object} types optional object mapping keys to value types
* (String, Number, Boolean or Array, String by default)
* @return a key/value Object whose keys are the query parameter names
* @type Object
*/
SimileAjax.parseURLParameters = function(url, to, types) {
to = to || {};
types = types || {};
if (typeof url == "undefined") {
url = location.href;
}
var q = url.indexOf("?");
if (q < 0) {
return to;
}
url = (url+"#").slice(q+1, url.indexOf("#")); // toss the URL fragment
var params = url.split("&"), param, parsed = {};
var decode = window.decodeURIComponent || unescape;
for (var i = 0; param = params[i]; i++) {
var eq = param.indexOf("=");
var name = decode(param.slice(0,eq));
var old = parsed[name];
if (typeof old == "undefined") {
old = [];
} else if (!(old instanceof Array)) {
old = [old];
}
parsed[name] = old.concat(decode(param.slice(eq+1)));
}
for (var i in parsed) {
if (!parsed.hasOwnProperty(i)) continue;
var type = types[i] || String;
var data = parsed[i];
if (!(data instanceof Array)) {
data = [data];
}
if (type === Boolean && data[0] == "false") {
to[i] = false; // because Boolean("false") === true
} else {
to[i] = type.apply(this, data);
}
}
return to;
};
(function() {
var javascriptFiles = [
"jquery-1.2.6.min.js",
"platform.js",
"debug.js",
"xmlhttp.js",
"json.js",
"dom.js",
"graphics.js",
"date-time.js",
"string.js",
"html.js",
"data-structure.js",
"units.js",
"ajax.js",
"history.js",
"window-manager.js"
];
var cssFiles = [
"graphics.css"
];
if (typeof SimileAjax_urlPrefix == "string") {
SimileAjax.urlPrefix = SimileAjax_urlPrefix;
} else {
var url = SimileAjax.findScript(document, "simile-ajax-api.js");
if (url == null) {
SimileAjax.error = new Error("Failed to derive URL prefix for Simile Ajax API code files");
return;
}
SimileAjax.urlPrefix = url.substr(0, url.indexOf("simile-ajax-api.js"));
}
SimileAjax.parseURLParameters(url, SimileAjax.params, {bundle:Boolean});
if (SimileAjax.params.bundle) {
SimileAjax.includeJavascriptFiles(document, SimileAjax.urlPrefix, [ "simile-ajax-bundle.js" ]);
} else {
SimileAjax.includeJavascriptFiles(document, SimileAjax.urlPrefix + "scripts/", javascriptFiles);
}
SimileAjax.includeCssFiles(document, SimileAjax.urlPrefix + "styles/", cssFiles);
SimileAjax.loaded = true;
})();
}