1/*================================================== 2 * Simile Ajax API 3 * 4 * Include this file in your HTML file as follows: 5 * 6 * <script src="http://simile.mit.edu/ajax/api/simile-ajax-api.js" type="text/javascript"></script> 7 * 8 *================================================== 9 */ 10 11if (typeof SimileAjax == "undefined") { 12 var SimileAjax = { 13 loaded: false, 14 loadingScriptsCount: 0, 15 error: null, 16 params: { bundle:"true" } 17 }; 18 19 SimileAjax.Platform = new Object(); 20 /* 21 HACK: We need these 2 things here because we cannot simply append 22 a <script> element containing code that accesses SimileAjax.Platform 23 to initialize it because IE executes that <script> code first 24 before it loads ajax.js and platform.js. 25 */ 26 27 var getHead = function(doc) { 28 return doc.getElementsByTagName("head")[0]; 29 }; 30 31 SimileAjax.findScript = function(doc, substring) { 32 var heads = doc.documentElement.getElementsByTagName("head"); 33 for (var h = 0; h < heads.length; h++) { 34 var node = heads[h].firstChild; 35 while (node != null) { 36 if (node.nodeType == 1 && node.tagName.toLowerCase() == "script") { 37 var url = node.src; 38 var i = url.indexOf(substring); 39 if (i >= 0) { 40 return url; 41 } 42 } 43 node = node.nextSibling; 44 } 45 } 46 return null; 47 }; 48 SimileAjax.includeJavascriptFile = function(doc, url, onerror, charset) { 49 onerror = onerror || ""; 50 if (doc.body == null) { 51 try { 52 var q = "'" + onerror.replace( /'/g, '&apos' ) + "'"; // " 53 doc.write("<script src='" + url + "' onerror="+ q + 54 (charset ? " charset='"+ charset +"'" : "") + 55 " type='text/javascript'>"+ onerror + "</script>"); 56 return; 57 } catch (e) { 58 // fall through 59 } 60 } 61 62 var script = doc.createElement("script"); 63 if (onerror) { 64 try { script.innerHTML = onerror; } catch(e) {} 65 script.setAttribute("onerror", onerror); 66 } 67 if (charset) { 68 script.setAttribute("charset", charset); 69 } 70 script.type = "text/javascript"; 71 script.language = "JavaScript"; 72 script.src = url; 73 return getHead(doc).appendChild(script); 74 }; 75 SimileAjax.includeJavascriptFiles = function(doc, urlPrefix, filenames) { 76 for (var i = 0; i < filenames.length; i++) { 77 SimileAjax.includeJavascriptFile(doc, urlPrefix + filenames[i]); 78 } 79 SimileAjax.loadingScriptsCount += filenames.length; 80 SimileAjax.includeJavascriptFile(doc, SimileAjax.urlPrefix + "scripts/signal.js?" + filenames.length); 81 }; 82 SimileAjax.includeCssFile = function(doc, url) { 83 if (doc.body == null) { 84 try { 85 doc.write("<link rel='stylesheet' href='" + url + "' type='text/css'/>"); 86 return; 87 } catch (e) { 88 // fall through 89 } 90 } 91 92 var link = doc.createElement("link"); 93 link.setAttribute("rel", "stylesheet"); 94 link.setAttribute("type", "text/css"); 95 link.setAttribute("href", url); 96 getHead(doc).appendChild(link); 97 }; 98 SimileAjax.includeCssFiles = function(doc, urlPrefix, filenames) { 99 for (var i = 0; i < filenames.length; i++) { 100 SimileAjax.includeCssFile(doc, urlPrefix + filenames[i]); 101 } 102 }; 103 104 /** 105 * Append into urls each string in suffixes after prefixing it with urlPrefix. 106 * @param {Array} urls 107 * @param {String} urlPrefix 108 * @param {Array} suffixes 109 */ 110 SimileAjax.prefixURLs = function(urls, urlPrefix, suffixes) { 111 for (var i = 0; i < suffixes.length; i++) { 112 urls.push(urlPrefix + suffixes[i]); 113 } 114 }; 115 116 /** 117 * Parse out the query parameters from a URL 118 * @param {String} url the url to parse, or location.href if undefined 119 * @param {Object} to optional object to extend with the parameters 120 * @param {Object} types optional object mapping keys to value types 121 * (String, Number, Boolean or Array, String by default) 122 * @return a key/value Object whose keys are the query parameter names 123 * @type Object 124 */ 125 SimileAjax.parseURLParameters = function(url, to, types) { 126 to = to || {}; 127 types = types || {}; 128 129 if (typeof url == "undefined") { 130 url = location.href; 131 } 132 var q = url.indexOf("?"); 133 if (q < 0) { 134 return to; 135 } 136 url = (url+"#").slice(q+1, url.indexOf("#")); // toss the URL fragment 137 138 var params = url.split("&"), param, parsed = {}; 139 var decode = window.decodeURIComponent || unescape; 140 for (var i = 0; param = params[i]; i++) { 141 var eq = param.indexOf("="); 142 var name = decode(param.slice(0,eq)); 143 var old = parsed[name]; 144 if (typeof old == "undefined") { 145 old = []; 146 } else if (!(old instanceof Array)) { 147 old = [old]; 148 } 149 parsed[name] = old.concat(decode(param.slice(eq+1))); 150 } 151 for (var i in parsed) { 152 if (!parsed.hasOwnProperty(i)) continue; 153 var type = types[i] || String; 154 var data = parsed[i]; 155 if (!(data instanceof Array)) { 156 data = [data]; 157 } 158 if (type === Boolean && data[0] == "false") { 159 to[i] = false; // because Boolean("false") === true 160 } else { 161 to[i] = type.apply(this, data); 162 } 163 } 164 return to; 165 }; 166 167 (function() { 168 var javascriptFiles = [ 169 "jquery-1.2.6.min.js", 170 "platform.js", 171 "debug.js", 172 "xmlhttp.js", 173 "json.js", 174 "dom.js", 175 "graphics.js", 176 "date-time.js", 177 "string.js", 178 "html.js", 179 "data-structure.js", 180 "units.js", 181 182 "ajax.js", 183 "history.js", 184 "window-manager.js" 185 ]; 186 var cssFiles = [ 187 "graphics.css" 188 ]; 189 190 if (typeof SimileAjax_urlPrefix == "string") { 191 SimileAjax.urlPrefix = SimileAjax_urlPrefix; 192 } else { 193 var url = SimileAjax.findScript(document, "simile-ajax-api.js"); 194 if (url == null) { 195 SimileAjax.error = new Error("Failed to derive URL prefix for Simile Ajax API code files"); 196 return; 197 } 198 199 SimileAjax.urlPrefix = url.substr(0, url.indexOf("simile-ajax-api.js")); 200 } 201 202 SimileAjax.parseURLParameters(url, SimileAjax.params, {bundle:Boolean}); 203 if (SimileAjax.params.bundle) { 204 SimileAjax.includeJavascriptFiles(document, SimileAjax.urlPrefix, [ "simile-ajax-bundle.js" ]); 205 } else { 206 SimileAjax.includeJavascriptFiles(document, SimileAjax.urlPrefix + "scripts/", javascriptFiles); 207 } 208 SimileAjax.includeCssFiles(document, SimileAjax.urlPrefix + "styles/", cssFiles); 209 210 SimileAjax.loaded = true; 211 })(); 212} 213