]>
Commit | Line | Data |
---|---|---|
1354d172 | 1 | // TODO: this file needs to be converted to the v1.7 loader |
2f01fe57 | 2 | |
a089699c AD |
3 | // a host environment specifically built for Mozilla extensions, but derived |
4 | // from the browser host environment | |
5 | if(typeof window != 'undefined'){ | |
6 | dojo.isBrowser = true; | |
7 | dojo._name = "browser"; | |
8 | ||
9 | ||
10 | // FIXME: PORTME | |
11 | // http://developer.mozilla.org/en/mozIJSSubScriptLoader | |
12 | ||
13 | ||
14 | // attempt to figure out the path to dojo if it isn't set in the config | |
15 | (function(){ | |
a089699c AD |
16 | // this is a scope protection closure. We set browser versions and grab |
17 | // the URL we were loaded from here. | |
18 | ||
19 | // FIXME: need to probably use a different reference to "document" to get the hosting XUL environment | |
20 | ||
1354d172 | 21 | dojo.baseUrl = dojo.config.baseUrl; |
a089699c AD |
22 | |
23 | // fill in the rendering support information in dojo.render.* | |
24 | var n = navigator; | |
25 | var dua = n.userAgent; | |
26 | var dav = n.appVersion; | |
27 | var tv = parseFloat(dav); | |
28 | ||
1354d172 AD |
29 | dojo.isMozilla = dojo.isMoz = tv; |
30 | if(dojo.isMoz){ | |
31 | dojo.isFF = parseFloat(dua.split("Firefox/")[1]) || undefined; | |
a089699c AD |
32 | } |
33 | ||
34 | // FIXME | |
1354d172 | 35 | dojo.isQuirks = document.compatMode == "BackCompat"; |
a089699c AD |
36 | |
37 | // FIXME | |
38 | // TODO: is the HTML LANG attribute relevant? | |
1354d172 | 39 | dojo.locale = dojo.config.locale || n.language.toLowerCase(); |
a089699c | 40 | |
1354d172 | 41 | dojo._xhrObj = function(){ |
a089699c | 42 | return new XMLHttpRequest(); |
1354d172 | 43 | }; |
a089699c AD |
44 | |
45 | // monkey-patch _loadUri to handle file://, chrome://, and resource:// url's | |
1354d172 AD |
46 | var oldLoadUri = dojo._loadUri; |
47 | dojo._loadUri = function(uri, cb){ | |
a089699c AD |
48 | var handleLocal = ["file:", "chrome:", "resource:"].some(function(prefix){ |
49 | return String(uri).indexOf(prefix) == 0; | |
50 | }); | |
51 | if(handleLocal){ | |
52 | // see: | |
53 | // http://developer.mozilla.org/en/mozIJSSubScriptLoader | |
54 | var l = Components.classes["@mozilla.org/moz/jssubscript-loader;1"] | |
55 | .getService(Components.interfaces.mozIJSSubScriptLoader); | |
1354d172 | 56 | var value = l.loadSubScript(uri, dojo.global); |
a089699c AD |
57 | if(cb){ cb(value); } |
58 | return true; | |
59 | }else{ | |
60 | // otherwise, call the pre-existing version | |
1354d172 | 61 | return oldLoadUri.apply(dojo, arguments); |
a089699c | 62 | } |
1354d172 | 63 | }; |
a089699c AD |
64 | |
65 | // FIXME: PORTME | |
1354d172 | 66 | dojo._isDocumentOk = function(http){ |
a089699c AD |
67 | var stat = http.status || 0; |
68 | return (stat >= 200 && stat < 300) || // Boolean | |
69 | stat == 304 || // allow any 2XX response code | |
70 | stat == 1223 || // get it out of the cache | |
1354d172 AD |
71 | (!stat && (location.protocol == "file:" || location.protocol == "chrome:") ); |
72 | }; | |
a089699c AD |
73 | |
74 | // FIXME: PORTME | |
75 | // var owloc = window.location+""; | |
76 | // var base = document.getElementsByTagName("base"); | |
77 | // var hasBase = (base && base.length > 0); | |
78 | var hasBase = false; | |
79 | ||
1354d172 | 80 | dojo._getText = function(/*URI*/ uri, /*Boolean*/ fail_ok){ |
a089699c AD |
81 | // summary: Read the contents of the specified uri and return those contents. |
82 | // uri: | |
83 | // A relative or absolute uri. If absolute, it still must be in | |
84 | // the same "domain" as we are. | |
85 | // fail_ok: | |
86 | // Default false. If fail_ok and loading fails, return null | |
87 | // instead of throwing. | |
88 | // returns: The response text. null is returned when there is a | |
89 | // failure and failure is okay (an exception otherwise) | |
90 | ||
91 | // alert("_getText: " + uri); | |
92 | ||
93 | // NOTE: must be declared before scope switches ie. this._xhrObj() | |
1354d172 | 94 | var http = dojo._xhrObj(); |
a089699c AD |
95 | |
96 | if(!hasBase && dojo._Url){ | |
97 | uri = (new dojo._Url(uri)).toString(); | |
98 | } | |
1354d172 | 99 | if(dojo.config.cacheBust){ |
a089699c AD |
100 | //Make sure we have a string before string methods are used on uri |
101 | uri += ""; | |
1354d172 | 102 | uri += (uri.indexOf("?") == -1 ? "?" : "&") + String(dojo.config.cacheBust).replace(/\W+/g, ""); |
a089699c AD |
103 | } |
104 | var handleLocal = ["file:", "chrome:", "resource:"].some(function(prefix){ | |
105 | return String(uri).indexOf(prefix) == 0; | |
106 | }); | |
107 | if(handleLocal){ | |
108 | // see: | |
109 | // http://forums.mozillazine.org/viewtopic.php?p=921150#921150 | |
110 | var ioService = Components.classes["@mozilla.org/network/io-service;1"] | |
111 | .getService(Components.interfaces.nsIIOService); | |
1354d172 | 112 | var scriptableStream = Components |
a089699c AD |
113 | .classes["@mozilla.org/scriptableinputstream;1"] |
114 | .getService(Components.interfaces.nsIScriptableInputStream); | |
115 | ||
116 | var channel = ioService.newChannel(uri, null, null); | |
117 | var input = channel.open(); | |
118 | scriptableStream.init(input); | |
119 | var str = scriptableStream.read(input.available()); | |
120 | scriptableStream.close(); | |
121 | input.close(); | |
122 | return str; | |
123 | }else{ | |
124 | http.open('GET', uri, false); | |
125 | try{ | |
126 | http.send(null); | |
127 | // alert(http); | |
1354d172 AD |
128 | if(!dojo._isDocumentOk(http)){ |
129 | var err = Error("Unable to load " + uri + " status:" + http.status); | |
a089699c AD |
130 | err.status = http.status; |
131 | err.responseText = http.responseText; | |
132 | throw err; | |
133 | } | |
134 | }catch(e){ | |
1354d172 AD |
135 | if(fail_ok){ |
136 | return null; | |
137 | } // null | |
a089699c AD |
138 | // rethrow the exception |
139 | throw e; | |
140 | } | |
141 | return http.responseText; // String | |
142 | } | |
1354d172 AD |
143 | }; |
144 | ||
145 | dojo._windowUnloaders = []; | |
146 | ||
a089699c | 147 | // FIXME: PORTME |
1354d172 | 148 | dojo.windowUnloaded = function(){ |
a089699c AD |
149 | // summary: |
150 | // signal fired by impending window destruction. You may use | |
151 | // dojo.addOnWIndowUnload() or dojo.connect() to this method to perform | |
152 | // page/application cleanup methods. See dojo.addOnWindowUnload for more info. | |
1354d172 | 153 | var mll = dojo._windowUnloaders; |
a089699c AD |
154 | while(mll.length){ |
155 | (mll.pop())(); | |
156 | } | |
1354d172 | 157 | }; |
a089699c AD |
158 | |
159 | // FIXME: PORTME | |
1354d172 | 160 | dojo.addOnWindowUnload = function(/*Object?*/obj, /*String|Function?*/functionName){ |
a089699c AD |
161 | // summary: |
162 | // registers a function to be triggered when window.onunload fires. | |
163 | // Be careful trying to modify the DOM or access JavaScript properties | |
164 | // during this phase of page unloading: they may not always be available. | |
165 | // Consider dojo.addOnUnload() if you need to modify the DOM or do heavy | |
166 | // JavaScript work. | |
167 | // example: | |
168 | // | dojo.addOnWindowUnload(functionPointer) | |
169 | // | dojo.addOnWindowUnload(object, "functionName") | |
170 | // | dojo.addOnWindowUnload(object, function(){ /* ... */}); | |
1354d172 AD |
171 | |
172 | dojo._onto(dojo._windowUnloaders, obj, functionName); | |
173 | }; | |
a089699c AD |
174 | |
175 | // XUL specific APIs | |
176 | var contexts = []; | |
177 | var current = null; | |
178 | dojo._defaultContext = [ window, document ]; | |
179 | ||
180 | dojo.pushContext = function(/*Object|String?*/g, /*MDocumentElement?*/d){ | |
181 | // summary: | |
182 | // causes subsequent calls to Dojo methods to assume the | |
183 | // passed object and, optionally, document as the default | |
184 | // scopes to use. A 2-element array of the previous global and | |
185 | // document are returned. | |
186 | // description: | |
187 | // dojo.pushContext treats contexts as a stack. The | |
188 | // auto-detected contexts which are initially provided using | |
189 | // dojo.setContext() require authors to keep state in order to | |
190 | // "return" to a previous context, whereas the | |
191 | // dojo.pushContext and dojo.popContext methods provide a more | |
192 | // natural way to augment blocks of code to ensure that they | |
193 | // execute in a different window or frame without issue. If | |
194 | // called without any arguments, the default context (the | |
195 | // context when Dojo is first loaded) is instead pushed into | |
196 | // the stack. If only a single string is passed, a node in the | |
197 | // intitial context's document is looked up and its | |
198 | // contextWindow and contextDocument properties are used as | |
199 | // the context to push. This means that iframes can be given | |
200 | // an ID and code can be executed in the scope of the iframe's | |
201 | // document in subsequent calls easily. | |
202 | // g: | |
203 | // The global context. If a string, the id of the frame to | |
204 | // search for a context and document. | |
205 | // d: | |
206 | // The document element to execute subsequent code with. | |
207 | var old = [dojo.global, dojo.doc]; | |
208 | contexts.push(old); | |
209 | var n; | |
210 | if(!g && !d){ | |
211 | n = dojo._defaultContext; | |
212 | }else{ | |
213 | n = [ g, d ]; | |
214 | if(!d && dojo.isString(g)){ | |
215 | var t = document.getElementById(g); | |
216 | if(t.contentDocument){ | |
217 | n = [t.contentWindow, t.contentDocument]; | |
218 | } | |
219 | } | |
220 | } | |
221 | current = n; | |
222 | dojo.setContext.apply(dojo, n); | |
223 | return old; // Array | |
224 | }; | |
225 | ||
226 | dojo.popContext = function(){ | |
227 | // summary: | |
228 | // If the context stack contains elements, ensure that | |
229 | // subsequent code executes in the *previous* context to the | |
230 | // current context. The current context set ([global, | |
231 | // document]) is returned. | |
232 | var oc = current; | |
233 | if(!contexts.length){ | |
234 | return oc; | |
235 | } | |
236 | dojo.setContext.apply(dojo, contexts.pop()); | |
237 | return oc; | |
238 | }; | |
239 | ||
81bea17a | 240 | // FIXME: |
a089699c AD |
241 | // don't really like the current arguments and order to |
242 | // _inContext, so don't make it public until it's right! | |
243 | dojo._inContext = function(g, d, f){ | |
244 | var a = dojo._toArray(arguments); | |
245 | f = a.pop(); | |
246 | if(a.length == 1){ | |
247 | d = null; | |
248 | } | |
249 | dojo.pushContext(g, d); | |
250 | var r = f(); | |
251 | dojo.popContext(); | |
252 | return r; | |
253 | }; | |
254 | ||
255 | })(); | |
256 | ||
257 | dojo._initFired = false; | |
258 | // BEGIN DOMContentLoaded, from Dean Edwards (http://dean.edwards.name/weblog/2006/06/again/) | |
259 | dojo._loadInit = function(e){ | |
260 | dojo._initFired = true; | |
261 | // allow multiple calls, only first one will take effect | |
262 | // A bug in khtml calls events callbacks for document for event which isnt supported | |
263 | // for example a created contextmenu event calls DOMContentLoaded, workaround | |
264 | var type = (e && e.type) ? e.type.toLowerCase() : "load"; | |
265 | if(arguments.callee.initialized || (type != "domcontentloaded" && type != "load")){ return; } | |
266 | arguments.callee.initialized = true; | |
267 | if(dojo._inFlightCount == 0){ | |
268 | dojo._modulesLoaded(); | |
269 | } | |
1354d172 | 270 | }; |
a089699c AD |
271 | |
272 | /* | |
273 | (function(){ | |
274 | var _w = window; | |
275 | var _handleNodeEvent = function(evtName, fp){ | |
276 | // summary: | |
277 | // non-destructively adds the specified function to the node's | |
278 | // evtName handler. | |
279 | // evtName: should be in the form "onclick" for "onclick" handlers. | |
280 | // Make sure you pass in the "on" part. | |
281 | var oldHandler = _w[evtName] || function(){}; | |
282 | _w[evtName] = function(){ | |
283 | fp.apply(_w, arguments); | |
284 | oldHandler.apply(_w, arguments); | |
285 | }; | |
286 | }; | |
287 | // FIXME: PORT | |
288 | // FIXME: dojo.unloaded requires dojo scope, so using anon function wrapper. | |
289 | _handleNodeEvent("onbeforeunload", function() { dojo.unloaded(); }); | |
290 | _handleNodeEvent("onunload", function() { dojo.windowUnloaded(); }); | |
291 | })(); | |
292 | */ | |
1354d172 | 293 | |
a089699c AD |
294 | |
295 | // FIXME: PORTME | |
296 | // this event fires a lot, namely for all plugin XUL overlays and for | |
297 | // all iframes (in addition to window navigations). We only want | |
298 | // Dojo's to fire once..but we might care if pages navigate. We'll | |
299 | // probably need an extension-specific API | |
300 | if(!dojo.config.afterOnLoad){ | |
1354d172 | 301 | window.addEventListener("DOMContentLoaded", function(e){ |
a089699c AD |
302 | dojo._loadInit(e); |
303 | // console.log("DOM content loaded", e); | |
304 | }, false); | |
305 | } | |
306 | ||
307 | } //if (typeof window != 'undefined') | |
308 | ||
309 | //Register any module paths set up in djConfig. Need to do this | |
310 | //in the hostenvs since hostenv_browser can read djConfig from a | |
311 | //script tag's attribute. | |
2f01fe57 | 312 | (function(){ |
a089699c AD |
313 | var mp = dojo.config["modulePaths"]; |
314 | if(mp){ | |
315 | for(var param in mp){ | |
316 | dojo.registerModulePath(param, mp[param]); | |
317 | } | |
318 | } | |
2f01fe57 | 319 | })(); |
a089699c AD |
320 | |
321 | //Load debug code if necessary. | |
2f01fe57 | 322 | if(dojo.config.isDebug){ |
a089699c AD |
323 | // logging stub for extension logging |
324 | console.log = function(m){ | |
325 | var s = Components.classes["@mozilla.org/consoleservice;1"].getService( | |
326 | Components.interfaces.nsIConsoleService | |
1354d172 | 327 | ); |
a089699c | 328 | s.logStringMessage(m); |
1354d172 | 329 | }; |
a089699c AD |
330 | console.debug = function(){ |
331 | console.log(dojo._toArray(arguments).join(" ")); | |
1354d172 | 332 | }; |
a089699c | 333 | // FIXME: what about the rest of the console.* methods? And is there any way to reach into firebug and log into it directly? |
2f01fe57 | 334 | } |