File:  [LON-CAPA] / loncom / html / adm / jsMath / plugins / autoload.js
Revision 1.4: download - view: text, annotated - select for diffs
Tue Oct 9 21:29:28 2007 UTC (16 years, 9 months ago) by albertel
Branches: MAIN
CVS tags: version_2_9_X, version_2_9_99_0, version_2_9_1, version_2_9_0, version_2_8_X, version_2_8_99_1, version_2_8_99_0, version_2_8_2, version_2_8_1, version_2_8_0, version_2_7_X, version_2_7_99_1, version_2_7_99_0, version_2_7_1, version_2_7_0, version_2_6_X, version_2_6_99_1, version_2_6_99_0, version_2_6_3, version_2_6_2, version_2_6_1, version_2_6_0, version_2_5_99_1, version_2_5_99_0, version_2_12_X, version_2_11_X, version_2_11_5, version_2_11_4_uiuc, version_2_11_4_msu, version_2_11_4, version_2_11_3_uiuc, version_2_11_3_msu, version_2_11_3, version_2_11_2_uiuc, version_2_11_2_msu, version_2_11_2_educog, version_2_11_2, version_2_11_1, version_2_11_0_RC3, version_2_11_0_RC2, version_2_11_0_RC1, version_2_11_0, version_2_10_X, version_2_10_1, version_2_10_0_RC2, version_2_10_0_RC1, version_2_10_0, loncapaMITrelate_1, language_hyphenation_merge, language_hyphenation, bz6209-base, bz6209, bz5969, bz2851, PRINT_INCOMPLETE_base, PRINT_INCOMPLETE, HEAD, GCI_3, GCI_2, GCI_1, BZ5971-printing-apage, BZ5434-fox, BZ4492-merge, BZ4492-feature_horizontal_radioresponse
- jsMath 3.4e

    1: /*
    2:  *  autoload.js
    3:  *  
    4:  *  Part of the jsMath package for mathematics on the web.
    5:  *
    6:  *  This file is a plugin that checks if a page contains any math
    7:  *  that must be processed by jsMath, and only loads jsMath.js
    8:  *  when there is.
    9:  *  
   10:  *  You can control the items to look for via the variables
   11:  *  
   12:  *      jsMath.Autoload.findTeXstrings
   13:  *      jsMath.Autoload.findLaTeXstrings
   14:  *      jsMath.Autoload.findCustomStrings
   15:  *      jsMath.Autoload.findCustomSettings
   16:  *  
   17:  *  which control whether to look for TeX strings that will be converted
   18:  *  by jsMath.ConvertTeX(), or LaTeX strings that will be converted by
   19:  *  jsMath.ConvertLaTeX().  By default, the first is true and the second
   20:  *  and third are false.  The findCustomStrings can be used to specify your
   21:  *  own delimiters for in-line and display mathematics, e.g.
   22:  *  
   23:  *      jsMath.Autoload.findCustomStrings = [
   24:  *         '[math],'[/math]',          // start and end in-line math
   25:  *         '[display]','[/display]'    // start and end display math
   26:  *      ];
   27:  *  
   28:  *  Finally, findCustomSettings can be set to an object reference whose
   29:  *  name:value pairs control the individual search settings for tex2math.  
   30:  *  (See the plugins/tex2math.js file for more details).
   31:  *  
   32:  *  If any math strings are found, jsMath.js will be loaded automatically, 
   33:  *  but not loaded otherwise.  If any of the last four are set and TeX math
   34:  *  strings are found, then plugins/tex2ath.js will be loaded
   35:  *  automatically.  jsMath.Autoload.needsJsMath will be set to true or
   36:  *  false depending on whether jsMath needed to be loaded.
   37:  *  
   38:  *  The value of jsMath.Autoload.element controls the element to be
   39:  *  searched by the autoload plug-in.  If unset, the complete document will
   40:  *  be searched.  If set to a string, the element with that name will be
   41:  *  searched.  If set to a DOM object, that object and its children will
   42:  *  be searched.
   43:  *  
   44:  *  Finally, there are two additional parameters that control files to
   45:  *  be loaded after jsMath.js, should it be needed.  These are
   46:  *  
   47:  *      jsMath.Autoload.loadFonts
   48:  *      jsMath.Autoload.loadFiles
   49:  *  
   50:  *  If jsMath.js is loaded, the fonts contained in the loadFonts array
   51:  *  will be loaded, and the JavaScript files listed in the loadFiles array
   52:  *  will be run.  Relative URL's are loaded based from the URL containing
   53:  *  jsMath.js.
   54:  *  
   55:  *  The autoload plugin can be loaded in the document HEAD or in the BODY. 
   56:  *  If it is loaded in the HEAD, you will need to call jsMath.Autoload.Check()
   57:  *  at the end of the BODY (say in the window.onload handler) in order to
   58:  *  get it to check the page for math that needs to be tagged, otherwise load
   59:  *  the file at the bottom of the BODY and it will run the check automatically.
   60:  *
   61:  *  You can call jsMath.Autoload.Run() after the check has been performed
   62:  *  in order to call the appropriate tex2math routines for the given Autoload
   63:  *  settings.  You can call jsMath.Autoload.Run() even when jsMath isn't loaded.
   64:  *  
   65:  *  ---------------------------------------------------------------------
   66:  *
   67:  *  Copyright 2004-2006 by Davide P. Cervone
   68:  * 
   69:  *  Licensed under the Apache License, Version 2.0 (the "License");
   70:  *  you may not use this file except in compliance with the License.
   71:  *  You may obtain a copy of the License at
   72:  * 
   73:  *      http://www.apache.org/licenses/LICENSE-2.0
   74:  * 
   75:  *  Unless required by applicable law or agreed to in writing, software
   76:  *  distributed under the License is distributed on an "AS IS" BASIS,
   77:  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   78:  *  See the License for the specific language governing permissions and
   79:  *  limitations under the License.
   80:  */
   81: 
   82: /*************************************************************************/
   83: 
   84: /*
   85:  *  Make sure jsMath.Autoload is available
   86:  */
   87: if (!window.jsMath) {window.jsMath = {}}
   88: if (jsMath.Autoload == null) {jsMath.Autoload = {}}
   89: jsMath.Add = function (dst,src) {for (var id in src) {dst[id] = src[id]}},
   90: jsMath.document = document; // tex2math needs this
   91: 
   92: jsMath.Add(jsMath.Autoload,{
   93:   
   94:   Script: {
   95: 
   96:     request: null,  // XMLHttpRequest object (if we can get it)
   97:     iframe: null,   // the hidden iframe (if not)
   98: 
   99:     /*
  100:      *  Get XMLHttpRequest object, if possible, and look up the URL root
  101:      *  (MSIE can't use xmlReuest to load local files, so avoid that)
  102:      */
  103:     Init: function () {
  104:       if (!(document.URL && document.URL.match(/^file:\/\/.*\\/))) {
  105:         if (window.XMLHttpRequest) {try {this.request = new XMLHttpRequest} catch (err) {}}
  106:         if (!this.request && window.ActiveXObject) {
  107:           var xml = ["MSXML2.XMLHTTP.5.0","MSXML2.XMLHTTP.4.0","MSXML2.XMLHTTP.3.0",
  108:                      "MSXML2.XMLHTTP","Microsoft.XMLHTTP"];
  109:           for (var i = 0; i < xml.length && !this.request; i++) {
  110:             try {this.request = new ActiveXObject(xml[i])} catch (err) {}
  111:           }
  112:         }
  113:       }
  114:       this.Root();
  115:     },
  116: 
  117:     /*
  118:      *  Load an external JavaScript file
  119:      */
  120:     Load: function (url) {
  121:       if (this.request) {
  122:         setTimeout(function () {jsMath.Autoload.Script.xmlLoad(url)},1);
  123:       } else {
  124:         this.startLoad(url);
  125:       }
  126:     },
  127: 
  128:     /*
  129:      *  Load an external JavaScript file via XMLHttpRequest
  130:      */
  131:     xmlLoad: function (url) {
  132:       try {
  133:         this.request.open("GET",jsMath.Autoload.root+url,false);
  134:         this.request.send(null);
  135:       } catch (err) {
  136:         throw "autoload: can't load the file '"+url+"'\n"
  137:             + "Message: "+err.message;
  138:       }
  139:       if (this.request.status && this.request.status >= 400) {
  140:         throw "autoload: can't load the file '"+url+"'\n"
  141:             + "Error status: "+this.request.status;
  142:       }
  143:       window.eval(this.request.responseText);
  144:       this.endLoad();
  145:     },
  146: 
  147:     /*
  148:      *  Load an external JavaScript file via jsMath-autoload.html
  149:      */
  150:     startLoad: function (url) {
  151:       this.iframe = document.createElement('iframe');
  152:       this.iframe.style.visibility = 'hidden';
  153:       this.iframe.style.position = 'absolute';
  154:       this.iframe.style.width  = '0px';
  155:       this.iframe.style.height = '0px';
  156:       if (document.body.firstChild) {
  157:         document.body.insertBefore(this.iframe,document.body.firstChild);
  158:       } else {
  159:         document.body.appendChild(this.iframe);
  160:       }
  161:       this.url = url; setTimeout('jsMath.Autoload.Script.setURL()',100);
  162:     },
  163:     endLoad: function () {setTimeout('jsMath.Autoload.Script.AfterLoad()',1)},
  164: 
  165:     /*
  166:      *  Use location.replace() to avoid browsers placing the file in
  167:      *  the history (and messing up the BACK button action).  Not
  168:      *  completely effective in Firefox 1.0.x.  Safari won't handle
  169:      *  replace() if the document is local (not sure if that's really
  170:      *  the issue, but that's the only time I see it).
  171:      */
  172:     setURL: function () {
  173:       var url = jsMath.Autoload.root+"jsMath-autoload.html";
  174:       var doc = this.iframe.contentDocument;
  175:       if (!doc && this.iframe.contentWindow) {doc = this.iframe.contentWindow.document}
  176:       if (navigator.vendor == "Apple Computer, Inc." &&
  177:           document.location.protocol == 'file:') {doc = null}
  178:       if (doc) {doc.location.replace(url)} else {this.iframe.src = url}
  179:     },
  180: 
  181:     /*
  182:      *  Queue items that need to be postponed until jsMath has run
  183:      */
  184:     queue: [],
  185:     Push: function (name,data) {this.queue[this.queue.length] = [name,data]},
  186:     RunStack: function () {
  187:       if (this.tex2math) {jsMath.Autoload.Check2(); return}
  188:       for (var i = 0; i < this.queue.length; i++) {
  189:         var name = this.queue[i][0];
  190:         var data = this.queue[i][1];
  191:         if (data.length == 1) {jsMath[name](data[0])}
  192:           else {jsMath[name](data[0],data[1],data[2],data[3])}
  193:       }
  194:      this.queue = [];
  195:     },
  196:   
  197:     AfterLoad: function () {jsMath.Autoload.Script.RunStack()},
  198: 
  199:     /*
  200:      *  Look up the jsMath root directory, if it is not already supplied
  201:      */
  202:     Root: function () {
  203:       if (jsMath.Autoload.root) return;
  204:       var script = document.getElementsByTagName('script');
  205:       if (script) {
  206:         for (var i = 0; i < script.length; i++) {
  207:           var src = script[i].src;
  208:           if (src && src.match('(^|/|\\\\)plugins/autoload.js$')) {
  209:             jsMath.Autoload.root = src.replace(/plugins\/autoload.js$/,'');
  210:             break;
  211:           }
  212:         }
  213:       }
  214:     }
  215: 
  216:   },
  217:   
  218:   /**************************************************************/
  219:   
  220:   /*
  221:    *  Load tex2math first (so we can call its search functions
  222:    *  to look to see if anything needs to be turned into math)
  223:    *  if it is needed, otherwise go on to the second check.
  224:    */
  225:   Check: function () {
  226:     if (this.checked) return; this.checked = 1;
  227:     if ((this.findTeXstrings || this.findLaTeXstrings ||
  228:          this.findCustomStrings || this.findCustomSettings) &&
  229:          (!jsMath.tex2math || !jsMath.tex2math.loaded)) {
  230:       this.Script.tex2math = 1;
  231:       this.Script.Load('plugins/tex2math.js');
  232:     } else {
  233:       if (!jsMath.tex2math) {jsMath.tex2math = {}}
  234:       this.Check2();
  235:     }
  236:   },
  237:   ReCheck: function () {
  238:     if (jsMath.loaded) return;
  239:     this.InitStubs();
  240:     this.checked = 0;
  241:     this.Script.queue = [];
  242:     this.Check();
  243:   },
  244: 
  245:   /*
  246:    *  Once tex2math is loaded, use it to check for math that
  247:    *  needs to be tagged for jsMath, and load jsMath if it is needed
  248:    */
  249:   Check2: function () {
  250:     this.Script.tex2math = 0; this.needsJsMath = 0;
  251:     if (this.checkElement == null) {this.checkElement = null}
  252: 
  253:     if (this.findTeXstrings)     {jsMath.tex2math.ConvertTeX(this.checkElement)}
  254:     if (this.findLaTeXstrings)   {jsMath.tex2math.ConvertLaTeX(this.checkElement)}
  255:     if (this.findCustomSettings) {jsMath.tex2math.Convert(this.checkElement,this.findCustomSettings)}
  256:     if (this.findCustomStrings)  {
  257:       var s = this.findCustomStrings;
  258:       jsMath.tex2math.CustomSearch(s[0],s[1],s[2],s[3]);
  259:       jsMath.tex2math.ConvertCustom(this.checkElement);
  260:     }
  261: 
  262:     this.needsJsMath = this.areMathElements(this.checkElement);
  263:     if (this.needsJsMath) {
  264:       this.LoadJsMath();
  265:     } else {
  266:       jsMath.Process = function () {};
  267:       jsMath.ProcessBeforeShowing = function () {};
  268:       jsMath.ConvertTeX = function () {};
  269:       jsMath.ConvertTeX2 = function () {};
  270:       jsMath.ConvertLaTeX = function () {};
  271:       jsMath.ConvertCustom = function () {};
  272:       jsMath.CustomSearch = function () {};
  273:       jsMath.Macro = function () {};
  274:       jsMath.Synchronize = function (code,data) {
  275:         if (typeof(code) == 'string') {eval(code)} else {code(data)}
  276:       };
  277:       jsMath.Autoload.Script.RunStack(); // perform pending commands
  278:       jsMath.Autoload.setMessage();
  279:     }
  280:   },
  281: 
  282:   /*
  283:    *  A callback used in the tex2math searches to signal that
  284:    *  some math has been found.
  285:    */
  286:   tex2mathCallback: function () {
  287:     jsMath.Autoload.needsJsMath = 1;
  288:     return false;
  289:   },
  290: 
  291:   /*
  292:    *  jsMath.Autoload.Run() is now longer needed
  293:    */
  294:   Run: function (data) {},
  295: 
  296:   /*
  297:    *  Look to see if there are SPAN or DIV elements of class "math".
  298:    */
  299:   areMathElements: function (obj) {
  300:     if (!obj) {obj = document}
  301:     if (typeof(obj) == 'string') {obj = document.getElementById(obj)}
  302:     if (!obj.getElementsByTagName) {return false}
  303:     var math = obj.getElementsByTagName('div');
  304:     for (var k = 0; k < math.length; k++) 
  305:       {if (math[k].className.match(/(^| )math( |$)/)) {return true}}
  306:     math = obj.getElementsByTagName('span');
  307:     for (var k = 0; k < math.length; k++) 
  308:       {if (math[k].className.match(/(^| )math( |$)/)) {return true}}
  309:     return false;
  310:   },
  311: 
  312:   /*
  313:    *  When math tags are found, load the jsMath.js file,
  314:    *  and afterward, load any auxiliary files or fonts,
  315:    *  and then do any pending commands.
  316:    */
  317:   LoadJsMath: function () {
  318:     if (this.loading) return;
  319:     if (jsMath.loaded) {this.afterLoad(); return}
  320:     if (this.root) {
  321:       this.loading = 1;
  322:       this.setMessage('Loading jsMath...');
  323:       this.Script.AfterLoad = this.afterLoad;
  324:       this.Script.Load('jsMath.js');
  325:     } else {
  326:       alert("Can't determine URL for jsMath.js");
  327:     }
  328:   },
  329:   afterLoad: function () {
  330:     jsMath.Autoload.loading = 0;
  331:     if (jsMath.tex2math.window) {jsMath.tex2math.window.jsMath = jsMath}
  332:     //
  333:     //  Handle MSIE bug where jsMath.window both is and is not the actual window
  334:     //
  335:     if (jsMath.browser == 'MSIE') {window.onscroll = jsMath.window.onscroll};
  336:     var fonts = jsMath.Autoload.loadFonts;
  337:     if (fonts) {
  338:       if (typeof(fonts) != 'object') {fonts = [fonts]}
  339:       for (var i = 0; i < fonts.length; i++) {jsMath.Font.Load(fonts[i])}
  340:     }
  341:     var files = jsMath.Autoload.loadFiles;
  342:     if (files) {
  343:       if (typeof(files) != 'object') {files = [files]}
  344:       for (var i = 0; i < files.length; i++) {jsMath.Setup.Script(files[i])}
  345:     }
  346:     jsMath.Synchronize(function () {jsMath.Autoload.Script.RunStack()});
  347:     jsMath.Autoload.setMessage();
  348:   },
  349: 
  350:   /*
  351:    *  Display a message in a small box at the bottom of the screen
  352:    */
  353:   setMessage: function (message) {
  354:     if (message) {
  355:       this.div = document.createElement('div');
  356:       if (!document.body.hasChildNodes) {document.body.appendChild(this.div)}
  357:         else {document.body.insertBefore(this.div,document.body.firstChild)}
  358:       var style = {
  359:         position:'fixed', bottom:'1px', left:'2px',
  360:         backgroundColor:'#E6E6E6', border:'solid 1px #959595',
  361:         margin:'0px', padding:'1px 8px', zIndex:102,
  362:         color:'black', fontSize:'75%', width:'auto'
  363:       };
  364:       for (var id in style) {this.div.style[id] = style[id]}
  365:       this.div.appendChild(jsMath.document.createTextNode(message));
  366:     } else if (this.div) {
  367:       this.div.firstChild.nodeValue = "";
  368:       this.div.style.visibility = 'hidden';
  369:     }
  370:   },
  371: 
  372:   /*
  373:    *  Queue these so we can do them after jsMath has been loaded
  374:    */
  375:   stubs: {
  376:     Process: function (data) {jsMath.Autoload.Script.Push('Process',[data])},
  377:     ProcessBeforeShowing: function (data) {jsMath.Autoload.Script.Push('ProcessBeforeShowing',[data])},
  378:     ConvertTeX: function (data) {jsMath.Autoload.Script.Push('ConvertTeX',[data])},
  379:     ConvertTeX2: function (data) {jsMath.Autoload.Script.Push('ConvertTeX2',[data])},
  380:     ConvertLaTeX: function (data) {jsMath.Autoload.Script.Push('ConvertLaTeX',[data])},
  381:     ConvertCustom: function (data) {jsMath.Autoload.Script.Push('ConvertCustom',[data])},
  382:     CustomSearch: function (d1,d2,d3,d4) {jsMath.Autoload.Script.Push('CustomSearch',[d1,d2,d3,d4])},
  383:     Synchronize: function (data) {jsMath.Autoload.Script.Push('Synchronize',[data])},
  384:     Macro: function (cs,def,params) {jsMath.Autoload.Script.Push('Macro',[cs,def,params])}
  385:   },
  386: 
  387:   InitStubs: function () {jsMath.Add(jsMath,jsMath.Autoload.stubs)}
  388:   
  389: });
  390: 
  391: /*
  392:  *  Initialize
  393:  */
  394: 
  395: if (jsMath.Autoload.findTeXstrings == null)   {jsMath.Autoload.findTeXstrings = 0}
  396: if (jsMath.Autoload.findLaTeXstrings == null) {jsMath.Autoload.findLaTeXstrings = 0}
  397: 
  398: jsMath.Autoload.Script.Init();
  399: jsMath.Autoload.InitStubs();
  400: if (document.body) {jsMath.Autoload.Check()}

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>