added LaTeXMathML files
[lambda.git] / jsMath / jsMath-global.html
1 <html>
2 <head>
3 <!--
4  | jsMath-global.html
5  |
6  | Part of the jsMath package for mathematics on the web.
7  | 
8  | This file is used to store persistent data across multiple
9  | documents, for example, the cookie data when files are loaded
10  | locally, or cached typset math data.
11  |
12  | The file opens a frameset with one frame containing the
13  | actual document to view, and stores the global data in the
14  | outer document.  That way, when the frame changes documents
15  | the global data is still available.
16  | 
17  | ---------------------------------------------------------------------
18  | 
19  | Copyright 2006 by Davide P. Cervone
20  |
21  | Licensed under the Apache License, Version 2.0 (the "License");
22  | you may not use this file except in compliance with the License.
23  | You may obtain a copy of the License at
24  |
25  |     http://www.apache.org/licenses/LICENSE-2.0
26  |
27  | Unless required by applicable law or agreed to in writing, software
28  | distributed under the License is distributed on an "AS IS" BASIS,
29  | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
30  | See the License for the specific language governing permissions and
31  | limitations under the License.
32 -->
33 <title>jsMath Global Frame</title>
34 <style></style>
35
36 <script>
37 var jsMath = {
38   isGlobal:  1,  // to pervent FRAME from inheriting this jsMath
39   isOpera:   (window.opera != null && window.Packages != null),
40   isSafari:  (window.clientInformation && document.implementation.createCSSStyleSheet != null),
41   isMSIEmac: (screen.updateInterval != null && !window.SyntaxError && !window.print),
42   msieDelay: 1000,  // MSIE/mac delay time for checking for offsite pages
43
44   /***************************************************************/
45
46   /*
47    *  This will be shared with the jsMath in the frameset
48    */
49   Global: {
50     isHidden: 0,
51     cookie: '',
52     cache: {T: {}, D: {}, R: {}, B: {}},
53     ClearCache: function () {jsMath.Global.cache = {T: {}, D: {}, R: {}, B: {}}},
54     Init: function () {}
55   },
56
57   /*
58    *  Called by jsMath to attach to the Global data area.
59    */
60   Register: function (w) {
61     w.jsMath.Global = jsMath.Global;
62     w.jsMath.Controls.localSetCookie = jsMath.localSetCookie;
63     w.jsMath.Controls.localGetCookie = jsMath.localGetCookie;
64     if (window.location.protocol != 'mk:') {
65       document.title = w.document.title;
66       this.ShowURL(w.location);
67       jsMath.SetUnload();
68     }
69   },
70
71   /***************************************************************/
72
73   /*
74    *  Initialize the global data and load the contents of the frame
75    */
76   Init: function () {
77     if (this.inited) return;
78     this.controls = document.getElementById('jsMath_controls');
79     this.frame    = document.getElementById('jsMath_frame');
80     this.window   = this.FrameWindow();
81     var URL;
82     if (!this.isOpera) {try {URL = this.window.document.URL} catch (err) {}}
83     if (!URL || URL == "about:blank" || URL.match(/jsMath-global.html$/))
84       {this.frame.src = this.src}
85
86     this.Global.frame = this.frame;
87     this.Global.Show = this.Show;
88     this.Global.GoLocal = this.GoLocal;
89     if (this.hide) {this.Hide()}
90     this.inited = 1;
91   },
92
93   GetURL: function () {
94     var src = unescape(document.location.search.substr(1));
95     if (src == '') {src = unescape(document.location.hash.substr(1))}
96     src = src.replace(/\?(.*)/,'');
97     if (RegExp.$1) {this.Global.cookie = unescape(RegExp.$1)}
98     return src;
99   },
100
101   FrameWindow: function (force) {
102     if (this.window && !force) {return this.window}
103     if (this.frame.contentWindow) {return this.frame.contentWindow}
104     if (document.frames && document.frames.jsMath_frame) 
105       {return document.frames.jsMath_frame}
106     return null;
107   },
108
109   /*
110    *  Called whenever the FRAME loads a new file.
111    *  (Update the title, etc.)
112    */
113   Loaded: function () {
114     if (!jsMath.inited) {jsMath.Init()}
115     if (!jsMath.window) {jsMath.window = jsMath.FrameWindow()}
116     if (!jsMath.window || window.location.protocol == 'mk:') return;
117     var URL; try {URL = jsMath.frame.src} catch (err) {}
118     var title; try {title = jsMath.window.document.title} catch (err) {}
119     if (URL != null && URL == jsMath.URL) return;
120     if (title != null) {
121       document.title = title;
122       jsMath.ShowURL(jsMath.window.location);
123       jsMath.SetUnload();
124     } else {
125       jsMath.Offsite();
126     }
127   },
128
129   /*
130    *  Mark the page as offsite and can't be read
131    */
132   Offsite: function () {
133     document.title = "jsMath Global: Offsite document -- can't read title";
134     jsMath.ShowURL("(Offsite document -- cant' read URL)");
135     if (jsMath.print && !jsMath.Global.isHidden) {
136       jsMath.print.disabled  = true;
137       jsMath.reload.disabled = true;
138     }
139     jsMath.window = null;
140   },
141
142   //
143   //  Safari doesn't fire onload for offsite URL's, so use in unload
144   //  handler to look for these and mark them.
145   //  MSIE/mac doesn't fire onload events at all, so use unload
146   //  handler to simulate them.
147   //
148   SetUnload: function () {
149     if (jsMath.isMSIEmac || jsMath.isSafari) {
150       try {jsMath.oldUnload = jsMath.window.unload} catch (err) {}
151       try {jsMath.window.onunload = jsMath.Unload} catch (err) {}
152     }
153   },
154   Unload: function (event) {
155     if (jsMath.oldUnload) {jsMath.oldUnload(event)}
156     try {setTimeout('jsMath.StateChange(0)',1)} catch (err) {}
157   },
158   StateChange: function (i) {
159     jsMath.ShowURL(jsMath.window.location);
160     var state = 'unknown'; try {state = jsMath.window.document.readyState} catch (err) {};
161     if (state == 'unknown' || i++ == 20) {jsMath.Offsite(); return}
162     if (state != 'complete') {setTimeout('jsMath.StateChange('+i+')',50*i); return}
163     document.title = jsMath.window.document.title;
164     jsMath.ShowURL(jsMath.window.location);
165     if (window.location.host == jsMath.window.location.host) 
166       {jsMath.SetUnload(); return}
167     if (jsMath.isMSIEmac) {
168       jsMath.oldLocation = jsMath.window.location;
169       setTimeout('jsMath.MSIEcheckDocument()',jsMath.msieDelay);
170     }
171   },
172   MSIEcheckDocument: function () {
173     if (window.location.host == jsMath.window.location.host) {
174       jsMath.StateChange(0)
175     } else {
176       if (jsMath.oldLocation != jsMath.window.location) {
177         jsMath.ShowURL(jsMath.window.location);
178         document.title = jsMath.window.document.title;
179       }
180       setTimeout('jsMath.MSIEcheckDocument()',jsMath.msieDelay);
181     }
182   },
183
184   /*
185    *  Replacements for standard localSetCookie/localGetCookie that
186    *  use the global cache for storing the cookie data rather than
187    *  the document.location's search field.
188    */
189   localSetCookie: function (cookie,warn) {
190     if (cookie != "") {cookie = 'jsMath='+cookie}
191     if (cookie == jsMath.Global.cookie) return;
192     jsMath.Global.cookie = cookie;
193   },
194   localGetCookie: function () {return (jsMath.Global.cookie || "")},
195
196   /*
197    *  Set the URL in the controls window
198    */
199   ShowURL: function (URL) {
200     try {
201       jsMath.URL = URL; if (jsMath.url) {jsMath.url.value = URL}
202       if (jsMath.print && !jsMath.Global.isHidden) {
203         jsMath.print.disabled  = !window.print;
204         jsMath.reload.disabled = false;
205       }
206     } catch (err) {}
207   },
208   SetURL: function () {this.frame.src = jsMath.url.value},
209
210   /*
211    *  Handle actions for the document frame
212    */
213   Print: function () {if (this.window) {this.window.document.body.focus(); this.window.print()}},
214   Reload: function () {if (this.window) {this.window.location.reload()}},
215   GoLocal: function () {
216     if (jsMath.window) {
217       jsMath.UpdateCookie();
218       if (jsMath.isMSIEmac) {
219         alert("MSIE/Mac has a bug that causes it not to go local properly.  "
220             + "After you press OK below, your browser will appear to hang.  "
221             + "When this happens, press Command-. to cancel the action.  "
222             + "The window should clear and the page location will appear "
223             + "in the address area at the top of the screen.  Press the "
224             + "REFRESH button to load the page correctly.");
225       }
226       jsMath.location = jsMath.window.location;
227       if (jsMath.window.location.protocol == 'file:' && jsMath.Global.cookie)
228         {jsMath.location += '?' + escape(jsMath.Global.cookie)}
229       setTimeout('window.location = jsMath.location',1);
230       return;
231     }
232     alert("You are viewing a web page from a site other than the "
233         + "one where you loaded jsMath-Global, so jsMath can't read "
234         + "its URL to load it locally.\n\n"
235         + "Check to see if your browser has a contextual menu item to "
236         + "open the active frame in a separate window.");
237   },
238
239   /*
240    *  Read the cookie data, set the hiddenGlobal and global fields
241    *  and save the cookie again.
242    */
243   UpdateCookie: function () {
244     var cookie = []; var cookies = jsMath.window.document.cookie;
245     if (window.location.protocol == 'file:') {cookies = jsMath.Global.cookie}
246     if (cookies.match(/jsMath=([^;]+)/)) {
247       var data = RegExp.$1.split(/,/);
248       for (var i = 0; i < data.length; i++) {
249         var x = data[i].match(/(.*):(.*)/);
250         if (x[2].match(/^\d+$/)) {x[2] = 1*x[2]} // convert from string
251         cookie[x[1]] = x[2];
252       }
253     }
254     cookie.hiddenGlobal = jsMath.Global.isHidden;
255     cookie.global = "never"; cookies = [];
256     for (var id in cookie) {cookies[cookies.length] = id + ':' + cookie[id]}
257     cookies = cookies.join(',');
258     if (window.location.protocol == 'file:') {
259       jsMath.Global.cookie = 'jsMath='+cookies;
260     } else {
261       cookies += '; path=/';
262       if (cookie.keep && cookie.keep != '0D') {
263         var ms = {
264           D: 1000*60*60*24,
265           W: 1000*60*60*24*7,
266           M: 1000*60*60*24*30,
267           Y: 1000*60*60*24*365
268         };
269         var exp = new Date;
270         exp.setTime(exp.getTime() +
271             cookie.keep.substr(0,1) * ms[cookie.keep.substr(1,1)]);
272         cookies += '; expires=' + exp.toGMTString();
273       }
274       jsMath.window.document.cookie = 'jsMath='+cookies;
275     }
276   },
277
278   /*
279    *  Check if the control panel should be hidden
280    */
281   SetControls: function (rows) {
282     if (!jsMath.rows) {
283       jsMath.rows = rows;
284       var cookie = document.cookie;
285       if (String(window.location.protocol).match(/^(file|mk):$/))
286         {cookie = jsMath.Global.cookie}
287       if (cookie.match(/jsMath=([^;]+)/)) {cookie = RegExp.$1}
288       if (!cookie.match("hiddenGlobal:0")) {
289         if (this.inited) {setTimeout('jsMath.Hide()',1)} else {jsMath.hide = 1}
290         return;
291       }
292     }
293     document.body.rows = rows;
294   },
295
296   /*
297    *  Remove the frame that holds the control panel
298    */ 
299   Hide: function () {
300     if (jsMath.Global.isHidden) return;
301     if (this.isMSIEmac) {
302       //
303       //  MSIE/Mac can't remove the frame, so hide it (and the drag bar)
304       //
305       document.body.rows = "-6,*";
306     } else if (this.isOpera) {
307       //
308       //  Opera can remove it, but it is unstable for that, but
309       //  setting the size to -1 seems to remove it as well.
310       //
311       document.body.rows = "-1,*";
312     } else {
313       document.body.removeChild(this.controls);
314       document.body.rows = "*";
315       jsMath.window = jsMath.FrameWindow(1);
316     }
317     this.Global.isHidden = 1;
318   },
319
320   /*
321    *  Put back the control-panel frame
322    */
323   Show: function (bubble) {
324     if (!jsMath.Global.isHidden) {
325       if (bubble && jsMath.window) {jsMath.window.jsMath.Controls.Panel()}
326       return;
327     }
328     if (!jsMath.isMSIEmac) {
329       document.body.insertBefore(jsMath.controls,jsMath.frame);
330       //
331       //  Opera doesn't refresh the frames properly, so reload them
332       //
333       if (jsMath.isOpera) {
334         setTimeout(
335           'jsMath.controls.src = "about:blank";\n' +
336           'jsMath.controls.src = jsMath.root+"jsMath-global-controls.html"+jsMath.domain;\n' +
337           'jsMath.frame.src = jsMath.window.location;',1
338         );
339       }
340     }
341     document.body.rows = jsMath.rows;
342     jsMath.window = jsMath.FrameWindow(1);
343     jsMath.Global.isHidden = 0;
344   },
345
346   /*
347    *  Empty the cache
348    */
349   Empty: function () {
350     var OK = confirm('Really empty the equation cache?');
351     if (OK) {jsMath.Global.ClearCache()}
352   },
353
354   /*
355    *  Find the largest common domain between the source file
356    *  and the location of the jsMath files
357    */
358   Domain: function () {
359     this.domain = '';
360     // MSIE/Mac can't do domain changes, so don't bother trying
361     if (navigator.appName == 'Microsoft Internet Explorer' &&
362         !navigator.platform.match(/Mac/) && navigator.userProfile != null) return;
363     if (this.src == '') {
364       if (window == parent) return;
365       var oldDomain = document.domain;
366       try {
367         while (true) {
368           try {if (parent.document.title != null) return} catch (err) {}
369           if (!document.domain.match(/\..*\./)) break;
370           document.domain = document.domain.replace(/^[^.]*\./,'');
371         }
372       } catch (err) {}
373       document.domain = oldDomain;
374     } else {
375       if (!this.src.match(new RegExp('^[^:]+:\/\/([^/]+)(:[0-9]+)?\/'))) return;
376       if (document.domain == RegExp.$1) return;
377       var src = RegExp.$1.split(/\./);
378       var loc = String(window.location.host).split(/\./);
379       var si, li; si = src.length-2; li = loc.length-2
380       while (si >= 0 && li >= 0 && src[si] == loc[li]) {li--; si--}
381       document.domain = src.slice(si+1).join('.');
382       this.domain = '?'+document.domain;
383     }
384   },
385
386   /*
387    *  Create the document content based on whether this is the initial
388    *  call to this file, or the secondary one
389    */
390   Content: function () {
391     if (this.src != '') {
392       this.root = (!this.isOpera) ? '' : 
393         String(window.location).replace(/\/jsMath-global.html\??.*/,'/');
394       document.writeln('<frameset rows="0,*" onload="jsMath.Init()">');
395       document.writeln('<frame src="'+this.root+'jsMath-global-controls.html'+this.domain+'" frameborder="0" scrolling="no" id="jsMath_controls" />');
396       document.writeln('<frame src="'+this.root+'jsMath-global.html" frameborder="0" onload="jsMath.Loaded()" id="jsMath_frame" />');
397       document.writeln('</frameset>');
398     } else {
399       document.writeln('<body><br/></body>');
400     }
401   }
402
403 };
404
405 </script>
406 </head>
407
408 <script>
409 jsMath.src = jsMath.GetURL();
410 jsMath.Domain();
411 jsMath.Content();
412 </script>
413
414 </html>