]>
Commit | Line | Data |
---|---|---|
2f01fe57 | 1 | /* |
81bea17a | 2 | Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. |
2f01fe57 AD |
3 | Available via Academic Free License >= 2.1 OR the modified BSD license. |
4 | see: http://dojotoolkit.org/license for details | |
5 | */ | |
6 | ||
7 | ||
a089699c AD |
8 | /*===== |
9 | dojo.isBrowser = { | |
10 | // example: | |
11 | // | if(dojo.isBrowser){ ... } | |
2f01fe57 | 12 | }; |
a089699c AD |
13 | |
14 | dojo.isFF = { | |
15 | // example: | |
16 | // | if(dojo.isFF > 1){ ... } | |
2f01fe57 | 17 | }; |
a089699c AD |
18 | |
19 | dojo.isIE = { | |
20 | // example: | |
21 | // | if(dojo.isIE > 6){ | |
22 | // | // we are IE7 | |
23 | // | } | |
2f01fe57 | 24 | }; |
a089699c AD |
25 | |
26 | dojo.isSafari = { | |
27 | // example: | |
28 | // | if(dojo.isSafari){ ... } | |
81bea17a | 29 | // example: |
a089699c | 30 | // Detect iPhone: |
81bea17a | 31 | // | if(dojo.isSafari && navigator.userAgent.indexOf("iPhone") != -1){ |
a089699c AD |
32 | // | // we are iPhone. Note, iPod touch reports "iPod" above and fails this test. |
33 | // | } | |
2f01fe57 | 34 | }; |
a089699c AD |
35 | |
36 | dojo = { | |
37 | // isBrowser: Boolean | |
38 | // True if the client is a web-browser | |
39 | isBrowser: true, | |
40 | // isFF: Number | undefined | |
41 | // Version as a Number if client is FireFox. undefined otherwise. Corresponds to | |
42 | // major detected FireFox version (1.5, 2, 3, etc.) | |
43 | isFF: 2, | |
44 | // isIE: Number | undefined | |
45 | // Version as a Number if client is MSIE(PC). undefined otherwise. Corresponds to | |
46 | // major detected IE version (6, 7, 8, etc.) | |
47 | isIE: 6, | |
48 | // isKhtml: Number | undefined | |
49 | // Version as a Number if client is a KHTML browser. undefined otherwise. Corresponds to major | |
50 | // detected version. | |
51 | isKhtml: 0, | |
52 | // isWebKit: Number | undefined | |
53 | // Version as a Number if client is a WebKit-derived browser (Konqueror, | |
54 | // Safari, Chrome, etc.). undefined otherwise. | |
55 | isWebKit: 0, | |
56 | // isMozilla: Number | undefined | |
57 | // Version as a Number if client is a Mozilla-based browser (Firefox, | |
58 | // SeaMonkey). undefined otherwise. Corresponds to major detected version. | |
59 | isMozilla: 0, | |
60 | // isOpera: Number | undefined | |
61 | // Version as a Number if client is Opera. undefined otherwise. Corresponds to | |
62 | // major detected version. | |
63 | isOpera: 0, | |
64 | // isSafari: Number | undefined | |
65 | // Version as a Number if client is Safari or iPhone. undefined otherwise. | |
66 | isSafari: 0, | |
67 | // isChrome: Number | undefined | |
68 | // Version as a Number if client is Chrome browser. undefined otherwise. | |
69 | isChrome: 0 | |
70 | // isMac: Boolean | |
71 | // True if the client runs on Mac | |
72 | } | |
73 | =====*/ | |
a089699c AD |
74 | if(typeof window != 'undefined'){ |
75 | dojo.isBrowser = true; | |
76 | dojo._name = "browser"; | |
77 | ||
78 | ||
79 | // attempt to figure out the path to dojo if it isn't set in the config | |
80 | (function(){ | |
81 | var d = dojo; | |
82 | ||
83 | // this is a scope protection closure. We set browser versions and grab | |
84 | // the URL we were loaded from here. | |
85 | ||
86 | // grab the node we were loaded from | |
87 | if(document && document.getElementsByTagName){ | |
88 | var scripts = document.getElementsByTagName("script"); | |
89 | var rePkg = /dojo(\.xd)?\.js(\W|$)/i; | |
90 | for(var i = 0; i < scripts.length; i++){ | |
91 | var src = scripts[i].getAttribute("src"); | |
92 | if(!src){ continue; } | |
93 | var m = src.match(rePkg); | |
94 | if(m){ | |
95 | // find out where we came from | |
96 | if(!d.config.baseUrl){ | |
97 | d.config.baseUrl = src.substring(0, m.index); | |
98 | } | |
99 | // and find out if we need to modify our behavior | |
81bea17a | 100 | var cfg = (scripts[i].getAttribute("djConfig") || scripts[i].getAttribute("data-dojo-config")); |
a089699c AD |
101 | if(cfg){ |
102 | var cfgo = eval("({ "+cfg+" })"); | |
103 | for(var x in cfgo){ | |
104 | dojo.config[x] = cfgo[x]; | |
105 | } | |
106 | } | |
107 | break; // "first Dojo wins" | |
108 | } | |
109 | } | |
110 | } | |
111 | d.baseUrl = d.config.baseUrl; | |
112 | ||
113 | // fill in the rendering support information in dojo.render.* | |
114 | var n = navigator; | |
115 | var dua = n.userAgent, | |
116 | dav = n.appVersion, | |
117 | tv = parseFloat(dav); | |
118 | ||
119 | if(dua.indexOf("Opera") >= 0){ d.isOpera = tv; } | |
120 | if(dua.indexOf("AdobeAIR") >= 0){ d.isAIR = 1; } | |
121 | d.isKhtml = (dav.indexOf("Konqueror") >= 0) ? tv : 0; | |
122 | d.isWebKit = parseFloat(dua.split("WebKit/")[1]) || undefined; | |
123 | d.isChrome = parseFloat(dua.split("Chrome/")[1]) || undefined; | |
124 | d.isMac = dav.indexOf("Macintosh") >= 0; | |
125 | ||
126 | // safari detection derived from: | |
127 | // http://developer.apple.com/internet/safari/faq.html#anchor2 | |
128 | // http://developer.apple.com/internet/safari/uamatrix.html | |
129 | var index = Math.max(dav.indexOf("WebKit"), dav.indexOf("Safari"), 0); | |
130 | if(index && !dojo.isChrome){ | |
131 | // try to grab the explicit Safari version first. If we don't get | |
132 | // one, look for less than 419.3 as the indication that we're on something | |
133 | // "Safari 2-ish". | |
134 | d.isSafari = parseFloat(dav.split("Version/")[1]); | |
135 | if(!d.isSafari || parseFloat(dav.substr(index + 7)) <= 419.3){ | |
136 | d.isSafari = 2; | |
137 | } | |
138 | } | |
139 | ||
140 | if(dua.indexOf("Gecko") >= 0 && !d.isKhtml && !d.isWebKit){ d.isMozilla = d.isMoz = tv; } | |
141 | if(d.isMoz){ | |
142 | //We really need to get away from this. Consider a sane isGecko approach for the future. | |
143 | d.isFF = parseFloat(dua.split("Firefox/")[1] || dua.split("Minefield/")[1]) || undefined; | |
144 | } | |
145 | if(document.all && !d.isOpera){ | |
146 | d.isIE = parseFloat(dav.split("MSIE ")[1]) || undefined; | |
147 | //In cases where the page has an HTTP header or META tag with | |
148 | //X-UA-Compatible, then it is in emulation mode. | |
149 | //Make sure isIE reflects the desired version. | |
150 | //document.documentMode of 5 means quirks mode. | |
151 | //Only switch the value if documentMode's major version | |
152 | //is different from isIE's major version. | |
153 | var mode = document.documentMode; | |
154 | if(mode && mode != 5 && Math.floor(d.isIE) != mode){ | |
155 | d.isIE = mode; | |
156 | } | |
157 | } | |
158 | ||
159 | //Workaround to get local file loads of dojo to work on IE 7 | |
160 | //by forcing to not use native xhr. | |
161 | if(dojo.isIE && window.location.protocol === "file:"){ | |
162 | dojo.config.ieForceActiveXXhr=true; | |
163 | } | |
164 | ||
165 | d.isQuirks = document.compatMode == "BackCompat"; | |
166 | ||
167 | // TODO: is the HTML LANG attribute relevant? | |
168 | d.locale = dojo.config.locale || (d.isIE ? n.userLanguage : n.language).toLowerCase(); | |
169 | ||
170 | // These are in order of decreasing likelihood; this will change in time. | |
171 | d._XMLHTTP_PROGIDS = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0']; | |
172 | ||
173 | d._xhrObj = function(){ | |
81bea17a | 174 | // summary: |
a089699c AD |
175 | // does the work of portably generating a new XMLHTTPRequest object. |
176 | var http, last_e; | |
177 | if(!dojo.isIE || !dojo.config.ieForceActiveXXhr){ | |
178 | try{ http = new XMLHttpRequest(); }catch(e){} | |
179 | } | |
180 | if(!http){ | |
181 | for(var i=0; i<3; ++i){ | |
182 | var progid = d._XMLHTTP_PROGIDS[i]; | |
183 | try{ | |
184 | http = new ActiveXObject(progid); | |
185 | }catch(e){ | |
186 | last_e = e; | |
187 | } | |
188 | ||
189 | if(http){ | |
190 | d._XMLHTTP_PROGIDS = [progid]; // so faster next time | |
191 | break; | |
192 | } | |
193 | } | |
194 | } | |
195 | ||
196 | if(!http){ | |
197 | throw new Error("XMLHTTP not available: "+last_e); | |
198 | } | |
199 | ||
200 | return http; // XMLHTTPRequest instance | |
201 | } | |
202 | ||
203 | d._isDocumentOk = function(http){ | |
204 | var stat = http.status || 0, | |
205 | lp = location.protocol; | |
206 | return (stat >= 200 && stat < 300) || // Boolean | |
81bea17a AD |
207 | stat == 304 || // allow any 2XX response code |
208 | stat == 1223 || // get it out of the cache | |
209 | // Internet Explorer mangled the status code | |
a089699c | 210 | // Internet Explorer mangled the status code OR we're Titanium/browser chrome/chrome extension requesting a local file |
81bea17a | 211 | (!stat && (lp == "file:" || lp == "chrome:" || lp == "chrome-extension:" || lp == "app:")); |
a089699c AD |
212 | } |
213 | ||
214 | //See if base tag is in use. | |
215 | //This is to fix http://trac.dojotoolkit.org/ticket/3973, | |
216 | //but really, we need to find out how to get rid of the dojo._Url reference | |
217 | //below and still have DOH work with the dojo.i18n test following some other | |
218 | //test that uses the test frame to load a document (trac #2757). | |
219 | //Opera still has problems, but perhaps a larger issue of base tag support | |
220 | //with XHR requests (hasBase is true, but the request is still made to document | |
221 | //path, not base path). | |
222 | var owloc = window.location+""; | |
223 | var base = document.getElementsByTagName("base"); | |
224 | var hasBase = (base && base.length > 0); | |
225 | ||
226 | d._getText = function(/*URI*/ uri, /*Boolean*/ fail_ok){ | |
227 | // summary: Read the contents of the specified uri and return those contents. | |
228 | // uri: | |
229 | // A relative or absolute uri. If absolute, it still must be in | |
230 | // the same "domain" as we are. | |
231 | // fail_ok: | |
232 | // Default false. If fail_ok and loading fails, return null | |
233 | // instead of throwing. | |
234 | // returns: The response text. null is returned when there is a | |
235 | // failure and failure is okay (an exception otherwise) | |
236 | ||
237 | // NOTE: must be declared before scope switches ie. this._xhrObj() | |
238 | var http = d._xhrObj(); | |
239 | ||
240 | if(!hasBase && dojo._Url){ | |
241 | uri = (new dojo._Url(owloc, uri)).toString(); | |
242 | } | |
243 | ||
244 | if(d.config.cacheBust){ | |
245 | //Make sure we have a string before string methods are used on uri | |
246 | uri += ""; | |
247 | uri += (uri.indexOf("?") == -1 ? "?" : "&") + String(d.config.cacheBust).replace(/\W+/g,""); | |
248 | } | |
249 | ||
250 | http.open('GET', uri, false); | |
251 | try{ | |
252 | http.send(null); | |
253 | if(!d._isDocumentOk(http)){ | |
254 | var err = Error("Unable to load "+uri+" status:"+ http.status); | |
255 | err.status = http.status; | |
256 | err.responseText = http.responseText; | |
257 | throw err; | |
258 | } | |
259 | }catch(e){ | |
260 | if(fail_ok){ return null; } // null | |
261 | // rethrow the exception | |
262 | throw e; | |
263 | } | |
264 | return http.responseText; // String | |
265 | } | |
266 | ||
267 | ||
268 | var _w = window; | |
269 | var _handleNodeEvent = function(/*String*/evtName, /*Function*/fp){ | |
270 | // summary: | |
271 | // non-destructively adds the specified function to the node's | |
272 | // evtName handler. | |
273 | // evtName: should be in the form "onclick" for "onclick" handlers. | |
274 | // Make sure you pass in the "on" part. | |
275 | var _a = _w.attachEvent || _w.addEventListener; | |
276 | evtName = _w.attachEvent ? evtName : evtName.substring(2); | |
277 | _a(evtName, function(){ | |
278 | fp.apply(_w, arguments); | |
279 | }, false); | |
280 | }; | |
281 | ||
282 | ||
283 | d._windowUnloaders = []; | |
284 | ||
285 | d.windowUnloaded = function(){ | |
286 | // summary: | |
287 | // signal fired by impending window destruction. You may use | |
288 | // dojo.addOnWindowUnload() to register a listener for this | |
289 | // event. NOTE: if you wish to dojo.connect() to this method | |
290 | // to perform page/application cleanup, be aware that this | |
291 | // event WILL NOT fire if no handler has been registered with | |
292 | // dojo.addOnWindowUnload. This behavior started in Dojo 1.3. | |
293 | // Previous versions always triggered dojo.windowUnloaded. See | |
294 | // dojo.addOnWindowUnload for more info. | |
295 | var mll = d._windowUnloaders; | |
296 | while(mll.length){ | |
297 | (mll.pop())(); | |
298 | } | |
299 | d = null; | |
300 | }; | |
301 | ||
302 | var _onWindowUnloadAttached = 0; | |
303 | d.addOnWindowUnload = function(/*Object?|Function?*/obj, /*String|Function?*/functionName){ | |
304 | // summary: | |
305 | // registers a function to be triggered when window.onunload | |
81bea17a | 306 | // fires. |
a089699c AD |
307 | // description: |
308 | // The first time that addOnWindowUnload is called Dojo | |
309 | // will register a page listener to trigger your unload | |
310 | // handler with. Note that registering these handlers may | |
311 | // destory "fastback" page caching in browsers that support | |
312 | // it. Be careful trying to modify the DOM or access | |
313 | // JavaScript properties during this phase of page unloading: | |
314 | // they may not always be available. Consider | |
315 | // dojo.addOnUnload() if you need to modify the DOM or do | |
316 | // heavy JavaScript work since it fires at the eqivalent of | |
317 | // the page's "onbeforeunload" event. | |
318 | // example: | |
319 | // | dojo.addOnWindowUnload(functionPointer) | |
320 | // | dojo.addOnWindowUnload(object, "functionName"); | |
321 | // | dojo.addOnWindowUnload(object, function(){ /* ... */}); | |
322 | ||
323 | d._onto(d._windowUnloaders, obj, functionName); | |
324 | if(!_onWindowUnloadAttached){ | |
325 | _onWindowUnloadAttached = 1; | |
326 | _handleNodeEvent("onunload", d.windowUnloaded); | |
327 | } | |
328 | }; | |
329 | ||
330 | var _onUnloadAttached = 0; | |
331 | d.addOnUnload = function(/*Object?|Function?*/obj, /*String|Function?*/functionName){ | |
332 | // summary: | |
333 | // registers a function to be triggered when the page unloads. | |
334 | // description: | |
335 | // The first time that addOnUnload is called Dojo will | |
336 | // register a page listener to trigger your unload handler | |
81bea17a | 337 | // with. |
a089699c AD |
338 | // |
339 | // In a browser enviroment, the functions will be triggered | |
340 | // during the window.onbeforeunload event. Be careful of doing | |
341 | // too much work in an unload handler. onbeforeunload can be | |
342 | // triggered if a link to download a file is clicked, or if | |
343 | // the link is a javascript: link. In these cases, the | |
344 | // onbeforeunload event fires, but the document is not | |
345 | // actually destroyed. So be careful about doing destructive | |
346 | // operations in a dojo.addOnUnload callback. | |
347 | // | |
348 | // Further note that calling dojo.addOnUnload will prevent | |
349 | // browsers from using a "fast back" cache to make page | |
81bea17a | 350 | // loading via back button instantaneous. |
a089699c AD |
351 | // example: |
352 | // | dojo.addOnUnload(functionPointer) | |
353 | // | dojo.addOnUnload(object, "functionName") | |
354 | // | dojo.addOnUnload(object, function(){ /* ... */}); | |
355 | ||
356 | d._onto(d._unloaders, obj, functionName); | |
357 | if(!_onUnloadAttached){ | |
358 | _onUnloadAttached = 1; | |
359 | _handleNodeEvent("onbeforeunload", dojo.unloaded); | |
360 | } | |
361 | }; | |
362 | ||
363 | })(); | |
364 | ||
365 | //START DOMContentLoaded | |
366 | dojo._initFired = false; | |
367 | dojo._loadInit = function(e){ | |
368 | if(dojo._scrollIntervalId){ | |
369 | clearInterval(dojo._scrollIntervalId); | |
370 | dojo._scrollIntervalId = 0; | |
371 | } | |
372 | ||
373 | if(!dojo._initFired){ | |
374 | dojo._initFired = true; | |
375 | ||
376 | //Help out IE to avoid memory leak. | |
377 | if(!dojo.config.afterOnLoad && window.detachEvent){ | |
378 | window.detachEvent("onload", dojo._loadInit); | |
379 | } | |
380 | ||
381 | if(dojo._inFlightCount == 0){ | |
382 | dojo._modulesLoaded(); | |
383 | } | |
384 | } | |
385 | } | |
386 | ||
81bea17a | 387 | if(!dojo.config.afterOnLoad){ |
a089699c AD |
388 | if(document.addEventListener){ |
389 | //Standards. Hooray! Assumption here that if standards based, | |
390 | //it knows about DOMContentLoaded. It is OK if it does not, the fall through | |
391 | //to window onload should be good enough. | |
392 | document.addEventListener("DOMContentLoaded", dojo._loadInit, false); | |
393 | window.addEventListener("load", dojo._loadInit, false); | |
394 | }else if(window.attachEvent){ | |
395 | window.attachEvent("onload", dojo._loadInit); | |
396 | ||
397 | //DOMContentLoaded approximation. Diego Perini found this MSDN article | |
398 | //that indicates doScroll is available after DOM ready, so do a setTimeout | |
399 | //to check when it is available. | |
400 | //http://msdn.microsoft.com/en-us/library/ms531426.aspx | |
401 | if(!dojo.config.skipIeDomLoaded && self === self.top){ | |
402 | dojo._scrollIntervalId = setInterval(function (){ | |
403 | try{ | |
81bea17a | 404 | //When dojo is loaded into an iframe in an IE HTML Application |
a089699c AD |
405 | //(HTA), such as in a selenium test, javascript in the iframe |
406 | //can't see anything outside of it, so self===self.top is true, | |
81bea17a | 407 | //but the iframe is not the top window and doScroll will be |
a089699c AD |
408 | //available before document.body is set. Test document.body |
409 | //before trying the doScroll trick | |
410 | if(document.body){ | |
411 | document.documentElement.doScroll("left"); | |
412 | dojo._loadInit(); | |
413 | } | |
414 | }catch (e){} | |
415 | }, 30); | |
416 | } | |
417 | } | |
418 | } | |
419 | ||
420 | if(dojo.isIE){ | |
421 | try{ | |
422 | (function(){ | |
423 | document.namespaces.add("v", "urn:schemas-microsoft-com:vml"); | |
424 | var vmlElems = ["*", "group", "roundrect", "oval", "shape", "rect", "imagedata", "path", "textpath", "text"], | |
425 | i = 0, l = 1, s = document.createStyleSheet(); | |
426 | if(dojo.isIE >= 8){ | |
427 | i = 1; | |
428 | l = vmlElems.length; | |
429 | } | |
430 | for(; i < l; ++i){ | |
431 | s.addRule("v\\:" + vmlElems[i], "behavior:url(#default#VML); display:inline-block"); | |
432 | } | |
433 | })(); | |
434 | }catch(e){} | |
435 | } | |
436 | //END DOMContentLoaded | |
437 | ||
438 | ||
439 | /* | |
440 | OpenAjax.subscribe("OpenAjax", "onload", function(){ | |
441 | if(dojo._inFlightCount == 0){ | |
442 | dojo._modulesLoaded(); | |
443 | } | |
444 | }); | |
445 | ||
446 | OpenAjax.subscribe("OpenAjax", "onunload", function(){ | |
447 | dojo.unloaded(); | |
448 | }); | |
449 | */ | |
450 | } //if (typeof window != 'undefined') | |
451 | ||
452 | //Register any module paths set up in djConfig. Need to do this | |
453 | //in the hostenvs since hostenv_browser can read djConfig from a | |
454 | //script tag's attribute. | |
2f01fe57 | 455 | (function(){ |
a089699c AD |
456 | var mp = dojo.config["modulePaths"]; |
457 | if(mp){ | |
458 | for(var param in mp){ | |
459 | dojo.registerModulePath(param, mp[param]); | |
460 | } | |
461 | } | |
2f01fe57 | 462 | })(); |
a089699c AD |
463 | |
464 | //Load debug code if necessary. | |
2f01fe57 | 465 | if(dojo.config.isDebug){ |
a089699c | 466 | dojo.require("dojo._firebug.firebug"); |
2f01fe57 | 467 | } |
a089699c | 468 | |
2f01fe57 | 469 | if(dojo.config.debugAtAllCosts){ |
81bea17a AD |
470 | // this breaks the new AMD based module loader. The XDomain won't be necessary |
471 | // anyway if you switch to the asynchronous loader | |
472 | //dojo.config.useXDomain = true; | |
473 | //dojo.require("dojo._base._loader.loader_xd"); | |
a089699c AD |
474 | dojo.require("dojo._base._loader.loader_debug"); |
475 | dojo.require("dojo.i18n"); | |
2f01fe57 | 476 | } |
81bea17a | 477 |