--- loncom/html/adm/jsMath/uncompressed/jsMath.js 2006/03/27 19:32:36 1.1 +++ loncom/html/adm/jsMath/uncompressed/jsMath.js 2007/10/09 21:29:34 1.3 @@ -10,7 +10,7 @@ * * for the latest version, and for documentation on how to use jsMath. * - * Copyright 2004-2006 by Davide P. Cervone + * Copyright 2004-2007 by Davide P. Cervone * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,15 +29,10 @@ /* * Prevent running everything again if this file is loaded twice */ - if (!window.jsMath || !window.jsMath.loaded) { -// handle bug in MSIE/Mac in autoload -if (window.parent && window.parent.jsMath) {jsMath = window.parent.jsMath} - var jsMath_old = window.jsMath; // save user customizations - // // debugging routine // @@ -70,13 +65,16 @@ if (!document.getElementById || !documen /***************************************************************************/ -jsMath = { +window.jsMath = { - version: "3.2", // change this if you edit the file + version: "3.4e", // change this if you edit the file, but don't edit this file document: document, // the document loading jsMath window: window, // the window of the of loading document + platform: (navigator.platform.match(/Mac/) ? "mac" : + navigator.platform.match(/Win/) ? "pc" : "unix"), + // Font sizes for \tiny, \small, etc. (must match styles below) sizes: [50, 60, 70, 85, 100, 120, 144, 173, 207, 249], @@ -84,67 +82,91 @@ jsMath = { // The styles needed for the TeX fonts // styles: { - '.math': 'font-family: serif; font-style: normal; font-weight: normal', + '.math': 'font-family:serif; font-style:normal; font-weight:normal', - '.typeset': 'font-family: serif; font-style: normal; font-weight: normal', - 'div.typeset': 'text-align: center; margin: 1em 0px;', - 'span.typeset': 'text-align: left', - '.typeset span': 'text-align: left; border:0px; margin:0px; padding:0px', - - '.typeset .normal': 'font-family: serif; font-style: normal; font-weight: normal', - - '.typeset .size0': 'font-size: 50%', // tiny (\scriptscriptsize) - '.typeset .size1': 'font-size: 60%', // (50% of \large for consistency) - '.typeset .size2': 'font-size: 70%', // scriptsize - '.typeset .size3': 'font-size: 85%', // small (70% of \large for consistency) - '.typeset .size4': 'font-size: 100%', // normalsize - '.typeset .size5': 'font-size: 120%', // large - '.typeset .size6': 'font-size: 144%', // Large - '.typeset .size7': 'font-size: 173%', // LARGE - '.typeset .size8': 'font-size: 207%', // huge - '.typeset .size9': 'font-size: 249%', // Huge - - '.typeset .cmr10': 'font-family: jsMath-cmr10, serif', - '.typeset .cmbx10': 'font-family: jsMath-cmbx10, jsMath-cmr10', - '.typeset .cmti10': 'font-family: jsMath-cmti10, jsMath-cmr10', - '.typeset .cmmi10': 'font-family: jsMath-cmmi10', - '.typeset .cmsy10': 'font-family: jsMath-cmsy10', - '.typeset .cmex10': 'font-family: jsMath-cmex10', - - '.typeset .textit': 'font-family: serif; font-style:italic', - '.typeset .textbf': 'font-family: serif; font-weight:bold', - - '.typeset .link': 'text-decoration: none', - '.typeset .error': 'font-size: 10pt; font-style: italic; ' - + 'background-color: #FFFFCC; padding: 1px; ' - + 'border: 1px solid #CC0000', + '.typeset': 'font-family:serif; font-style:normal; font-weight:normal; line-height:normal', + 'div.typeset': 'text-align:center; margin:1em 0px;', + 'span.typeset': 'text-align:left', + '.typeset span': 'text-align:left; border:0px; margin:0px; padding:0px', + + '.typeset .normal': 'font-family:serif; font-style:normal; font-weight:normal', + + '.typeset .size0': 'font-size:50%', // tiny (\scriptscriptsize) + '.typeset .size1': 'font-size:60%', // (50% of \large for consistency) + '.typeset .size2': 'font-size:70%', // scriptsize + '.typeset .size3': 'font-size:85%', // small (70% of \large for consistency) + '.typeset .size4': 'font-size:100%', // normalsize + '.typeset .size5': 'font-size:120%', // large + '.typeset .size6': 'font-size:144%', // Large + '.typeset .size7': 'font-size:173%', // LARGE + '.typeset .size8': 'font-size:207%', // huge + '.typeset .size9': 'font-size:249%', // Huge + + '.typeset .cmr10': 'font-family:jsMath-cmr10, serif', + '.typeset .cmbx10': 'font-family:jsMath-cmbx10, jsMath-cmr10', + '.typeset .cmti10': 'font-family:jsMath-cmti10, jsMath-cmr10', + '.typeset .cmmi10': 'font-family:jsMath-cmmi10', + '.typeset .cmsy10': 'font-family:jsMath-cmsy10', + '.typeset .cmex10': 'font-family:jsMath-cmex10', + + '.typeset .textit': 'font-family:serif; font-style:italic', + '.typeset .textbf': 'font-family:serif; font-weight:bold', + + '.typeset .link': 'text-decoration:none', + '.typeset .error': 'font-size:10pt; font-style:italic; ' + + 'background-color:#FFFFCC; padding:1px; ' + + 'border:1px solid #CC0000', '.typeset .blank': 'display:inline-block; overflow:hidden; border:0px none; width:0px; height:0px;', '.typeset .spacer': 'display:inline-block', + + '#jsMath_hiddenSpan': 'visibility:hidden; position:absolute; top:0px;left:0px; ' + + 'line-height:normal; text-indent:0px', - '#jsMath_message': 'position:fixed; bottom:1px; left:2px; background-color:#E6E6E6; ' - + 'border: solid 1px #959595; margin:0px; padding: 1px 8px; ' - + 'z-index:102; color: black; font-size:small; width:auto;', - '#jsMath_panel': 'position:fixed; bottom:1.5em; right:1.5em; padding: 10px 20px; ' - + 'background-color:#DDDDDD; border: outset 2px; ' - + 'z-index:103; width:auto;', - '#jsMath_button': 'position:fixed; bottom:1px; right:2px; background-color:white; ' - + 'border: solid 1px #959595; margin:0px; padding: 0px 3px 1px 3px; ' - + 'z-index:102; color:black; text-decoration:none; font-size:x-small; ' - + 'width:auto; cursor:pointer; cursor:hand;', - '#jsMath_float': 'position:absolute; top:0px; left:0px; max-width:80%; ' - + 'z-index:101; width:auto; height:auto;', - '#jsMath_float .drag': 'background-color:#DDDDDD; border: outset 1px; height:12px; font-size: 1px;', - '#jsMath_float .close': 'background-color:#E6E6E6; border: inset 1px; width:8px; height:8px; margin: 1px 2px;', - '#jsMath_float .source': 'background-color:#E2E2E2; border: outset 1px; ' - + 'width:auto; height:auto; padding: 8px 15px; ' - + 'font-family: courier, fixed; font-size: 90%', - '#jsMath_noFont': 'text-align: center; padding: 10px 20px; border: 3px solid #DD0000; ' - + 'background-color: #FFF8F8; color: #AA0000; font-size:small; width:auto;', - '#jsMath_noFont .link': 'padding: 0px 5px 2px 5px; border: 2px outset; background-color:#E8E8E8; ' - + 'color:black; font-size:80%; width:auto; cursor:pointer; cursor:hand;', - - '@media print': '#jsMath_button {display:none}' + '#jsMath_message': 'position:fixed; bottom:1px; left:2px; background-color:#E6E6E6; ' + + 'border:solid 1px #959595; margin:0px; padding:1px 8px; ' + + 'z-index:102; color: black; font-size:small; width:auto;', + '#jsMath_panel': 'position:fixed; bottom:1.5em; right:1.5em; padding:.8em 1.6em; ' + + 'background-color:#DDDDDD; border:outset 2px; ' + + 'z-index:103; width:auto; color:black; font-size:10pt; font-style:normal', + '#jsMath_panel .disabled': 'color:#888888', + '#jsMath_panel .infoLink': 'font-size:85%', + '#jsMath_panel *': 'font-size:inherit; font-style:inherit; font-family:inherit; line-height:normal', + '#jsMath_panel div': 'background-color:inherit; color:inherit;', + '#jsMath_panel span': 'background-color:inherit; color:inherit;', + '#jsMath_panel td': 'border:0px; padding:0px; margin:0px; background-color:inherit; color:inherit;', + '#jsMath_panel tr': 'border:0px; padding:0px; margin:0px; background-color:inherit; color:inherit;', + '#jsMath_panel table': 'border:0px; padding:0px; margin:0px; background-color:inherit; color:inherit;', + + '#jsMath_button': 'position:fixed; bottom:1px; right:2px; background-color:white; ' + + 'border:solid 1px #959595; margin:0px; padding:0px 3px 1px 3px; ' + + 'z-index:102; color:black; text-decoration:none; font-size:x-small; ' + + 'width:auto; cursor:hand;', + '#jsMath_button *': 'padding:0px; border:0px; margin:0px; line-height:normal; ' + + 'font-size:inherit; font-style:inherit; font-family:inherit', + + '#jsMath_global': 'font-style:italic;', + '#jsMath_float': 'position:absolute; top:0px; left:0px; max-width:80%; ' + + 'z-index:101; width:auto; height:auto;', + '#jsMath_float .drag': 'background-color:#DDDDDD; border:outset 1px; height:12px; font-size:1px;', + '#jsMath_float .close': 'background-color:#E6E6E6; border:inset 1px; width:8px; height:8px; margin:1px 2px;', + '#jsMath_float .source': 'background-color:#E2E2E2; border:outset 1px; ' + + 'width:auto; height:auto; padding:8px 15px; ' + + 'font-family:courier, fixed; font-size:90%', + + '#jsMath_noFont .message': 'text-align: center; padding:.8em 1.6em; border:3px solid #DD0000; ' + + 'background-color:#FFF8F8; color: #AA0000; font-size:small; width:auto;', + '#jsMath_noFont .link': 'padding:0px 5px 2px 5px; border:2px outset; background-color:#E8E8E8; ' + + 'color:black; font-size:80%; width:auto; cursor:hand;', + + '#jsMath_PrintWarning .message': + 'text-align:center; padding:.8em 1.6em; border:3px solid #DD0000; ' + + 'background-color: #FFF8F8; color: #AA0000; font-size:x-small; width:auto;', + + '@media print': '#jsMath_button {display:none}\n' + + '#jsMath_Warning {display:none}', + + '@media screen': '#jsMath_PrintWarning {display:none}' }, @@ -168,23 +190,35 @@ jsMath = { }, /* - * Get the width and height (in ems) of an HTML string + * Get the width and height (in ems) of an HTML string. + * Check the cache first to see if we've already measured it. */ EmBoxFor: function (s) { - var bbox = this.BBoxFor(s); - return {w: bbox.w/this.em, h: bbox.h/this.em}; + var cache = jsMath.Global.cache.R; + if (!cache[this.em]) {cache[this.em] = {}} + if (!cache[this.em][s]) { + var bbox = this.BBoxFor(s); + cache[this.em][s] = {w: bbox.w/this.em, h: bbox.h/this.em}; + } + return cache[this.em][s]; }, /* - * For browsers that don't handle sizes of italics properly (MSIE) + * For browsers that don't handle sizes of italics properly (MSIE). + * Check the cache first to see if we've already measured it. */ EmBoxForItalics: function (s) { - var bbox = this.BBoxFor(s); - if (s.match(/|class=\"(icm|italic|igreek|iaccent)/i)) { - bbox.w = this.BBoxFor(s+jsMath.Browser.italicString).w - - jsMath.Browser.italicCorrection; + var cache = jsMath.Global.cache.R; + if (!cache[this.em]) {cache[this.em] = {}} + if (!cache[this.em][s]) { + var bbox = this.BBoxFor(s); + if (s.match(/|class=\"(icm|italic|igreek|iaccent)/i)) { + bbox.w = bbox.Mw = this.BBoxFor(s+jsMath.Browser.italicString).w + - jsMath.Browser.italicCorrection; + } + cache[this.em][s] = {w: bbox.w/this.em, h: bbox.h/this.em}; } - return {w: bbox.w/this.em, h: bbox.h/this.em}; + return cache[this.em][s]; }, /* @@ -193,26 +227,30 @@ jsMath = { */ Init: function () { if (jsMath.Setup.inited != 1) { - if (jsMath.Setup.inited) { + if (!jsMath.Setup.inited) {jsMath.Setup.Body()} + if (jsMath.Setup.inited != 1) { + if (jsMath.Setup.inited == -100) return; alert("It looks like jsMath failed to set up properly (error code " + jsMath.Setup.inited + "). " - + "I'll will try to keep going, but it could get ugly."); + + "I will try to keep going, but it could get ugly."); jsMath.Setup.inited = 1; - } else { - alert("You must call jsMath.Setup.Body() explicitly when jsMath is" + - "loaded as part of the section"); } - jsMath.Setup.Body(); // may fail to load fallback files properly } - this.em = this.BBoxFor('').w/10; + this.em = this.BBoxFor('').w/13; if (this.em == 0) { // handle older browsers - this.em = this.BBoxFor('').w/10; + this.em = this.BBoxFor('').w/13; } - if (jsMath.Browser.italicString) - jsMath.Browser.italicCorrection = jsMath.BBoxFor(jsMath.Browser.italicString).w; - var bb = this.BBoxFor('x'); var h = bb.h; - var d = this.BBoxFor('x'+jsMath.HTML.Rule(1,h/jsMath.em)).h - h; + var cache = jsMath.Global.cache.B; + if (!cache[this.em]) { + cache[this.em] = {}; + cache[this.em].bb = this.BBoxFor('x'); var hh = cache[this.em].bb.h; + cache[this.em].d = this.BBoxFor('x'+jsMath.HTML.Rule(1,hh/jsMath.em)).h - hh; + if (jsMath.Browser.italicString) + {cache[this.em].ic = jsMath.BBoxFor(jsMath.Browser.italicString).w} + } + jsMath.Browser.italicCorrection = cache[this.em].ic; + var bb = cache[this.em].bb; var h = bb.h; var d = cache[this.em].d this.h = (h-d)/this.em; this.d = d/this.em; this.hd = this.h + this.d; this.xWidth = bb.w; // used to tell if scale has changed @@ -252,7 +290,7 @@ jsMath = { 'ConvertTeX','ConvertTeX2','ConvertLaTeX','ConvertCustom', 'CustomSearch', 'Synchronize', 'Macro', 'document']; for (var i = 0; i < override.length; i++) { - if (jsMath_old[override[i]]) {jsMath_old[override[i]] = null} + if (jsMath_old[override[i]]) {delete jsMath_old[override[i]]} } } if (jsMath_old) {this.Insert(jsMath,jsMath_old)} @@ -281,7 +319,87 @@ jsMath = { }, Package: function (obj,def) {this.Insert(obj.prototype,def)} -} +}; + + +/***************************************************************************/ + + /* + * Implements items associated with the global cache. + * + * This object will be replaced by a global version when + * (and if) jsMath-global.html is loaded. + */ +jsMath.Global = { + isLocal: 1, // a local copy if jsMath-global.html hasn't been loaded + cache: {T: {}, D: {}, R: {}, B: {}}, + + /* + * Clear the global (or local) cache + */ + ClearCache: function () {jsMath.Global.cache = {T: {}, D: {}, R: {}, B: {}}}, + + /* + * Initiate global mode + */ + GoGlobal: function (cookie) { + var url = String(jsMath.window.location); + var c = (jsMath.isCHMmode ? '#' : '?'); + if (cookie) {url = url.replace(/\?.*/,'') + '?' + cookie} + jsMath.Controls.Reload(jsMath.root + "jsMath-global.html" + c +escape(url)); + }, + + /* + * Check if we need to go to global mode + */ + Init: function () { + if (jsMath.Controls.cookie.global == "always" && !jsMath.noGoGlobal) { + if (navigator.accentColorName) return; // OmniWeb crashes on GoGlobal + if (!jsMath.window) {jsMath.window = window} + jsMath.Controls.loaded = 1; + jsMath.Controls.defaults.hiddenGlobal = null; + this.GoGlobal(jsMath.Controls.SetCookie(2)); + } + }, + + /* + * Try to register with a global.html window that contains us + */ + Register: function () { + var parent = jsMath.window.parent; + if (!jsMath.isCHMode) + {jsMath.isCHMmode = (jsMath.window.location.protocol == 'mk:')} + try { + if (!jsMath.isCHMmode) this.Domain(); + if (parent.jsMath && parent.jsMath.isGlobal) + {parent.jsMath.Register(jsMath.window)} + } catch (err) {jsMath.noGoGlobal = 1} + }, + + /* + * If we're not the parent window, try to set the domain to + * match the parent's domain (so we can use the Global data + * if the surrounding frame is a Global frame. + */ + Domain: function () { + // MSIE/Mac can't do domain changes, so don't bother trying + if (navigator.appName == 'Microsoft Internet Explorer' && + jsMath.platform == 'mac' && navigator.userProfile != null) return; + if (window == parent) return; + var oldDomain = jsMath.document.domain; + try { + while (true) { + try {if (parent.document.title != null) return} catch (err) {} + if (!document.domain.match(/\..*\./)) break; + jsMath.document.domain = jsMath.document.domain.replace(/^[^.]*\./,''); + } + } catch (err) {} + jsMath.document.domain = oldDomain; + } + +}; + + /***************************************************************************/ @@ -304,10 +422,18 @@ jsMath.Script = { */ Init: function () { if (!(jsMath.Controls.cookie.asynch && jsMath.Controls.cookie.progress)) { - if (window.XMLHttpRequest) { - this.request = new XMLHttpRequest; - } else if (window.ActiveXObject) { - try {this.request = new ActiveXObject("Microsoft.XMLHTTP")} catch (err) {} + if (window.XMLHttpRequest && + // MSIE can't use xmlRequest on local files, but we don't have + // jsMath.browser yet to tell, so use this check + !(jsMath.document.URL && jsMath.document.URL.match(/^file:\/\/.*\\/))) { + try {this.request = new XMLHttpRequest} catch (err) {} + } + if (!this.request && window.ActiveXObject) { + var xml = ["MSXML2.XMLHTTP.5.0","MSXML2.XMLHTTP.4.0","MSXML2.XMLHTTP.3.0", + "MSXML2.XMLHTTP","Microsoft.XMLHTTP"]; + for (var i = 0; i < xml.length && !this.request; i++) { + try {this.request = new ActiveXObject(xml[i])} catch (err) {} + } } } // @@ -336,23 +462,32 @@ jsMath.Script = { * Load a URL and run the contents of the file */ xmlRequest: function (url) { - this.debug('xmlRequest: '+url); + this.blocking = 1; +// this.debug('xmlRequest: '+url); try { this.request.open("GET",url,false); this.request.send(null); } catch (err) { + this.blocking = 0; + if (jsMath.Translate.restart && jsMath.Translate.asynchronous) {return ""} throw "jsMath can't load the file '"+url+"'\n" + "Message: "+err.message; } if (this.request.status && this.request.status >= 400) { // Do we need to deal with redirected links? + this.blocking = 0; + if (jsMath.Translate.restart && jsMath.Translate.asynchronous) {return ""} throw "jsMath can't load the file '"+url+"'\n" + "Error status: "+this.request.status; } - this.Start(); this.blocking = 1; + if (!url.match(/\.js$/)) {return(this.request.responseText)} + var tmpQueue = this.queue; this.queue = []; +// this.debug('xml Eval ['+tmpQueue.length+']'); jsMath.window.eval(this.request.responseText); - this.End(); this.blocking = 0; +// this.debug('xml Done ['+this.queue.length+' + '+tmpQueue.length+']'); + this.blocking = 0; this.queue = this.queue.concat(tmpQueue); this.Process(); + return ""; }, /******************************************************************** @@ -371,7 +506,6 @@ jsMath.Script = { needsBody: 0, // true if loading files requires BODY to be present queue: [], // the stack of pending actions - queueAt: 0, /* * Provide mechanism for synchronizing with the asynchronous jsMath @@ -387,9 +521,8 @@ jsMath.Script = { * If nothing is being loaded, do the pending commands. */ Push: function (object,method,data) { - this.debug('Pushing: '+method+' at '+this.queueAt); - this.queue = [].concat(this.queue.slice(0,this.queueAt),[[object,method,data]],this.queue.slice(this.queueAt)); - this.queueAt++; +// this.debug('Pushing: '+method+' at '+this.queue.length); // debug + this.queue[this.queue.length] = [object,method,data]; if (!(this.blocking || (this.needsBody && !jsMath.document.body))) this.Process(); }, @@ -398,24 +531,35 @@ jsMath.Script = { */ Process: function () { while (this.queue.length && !this.blocking) { - this.Start(); var call = this.queue[0]; this.queue = this.queue.slice(1); + var savedQueue = this.SaveQueue(); var object = call[0]; var method = call[1]; var data = call[2]; - this.debug('Calling: '+method); +// this.debug('Calling: '+method+' ['+savedQueue.length+']'); // debug if (object) {object[method](data)} else if (method) {method(data)} - this.debug('Done: '+method); +// this.debug('Done: '+method+' ['+this.queue.length+' + '+savedQueue.length+'] ('+this.blocking+')'); // debug + this.RestoreQueue(savedQueue); } - this.End(); }, - Start: function () {this.queueAt = 0}, - End: function () {this.queueAt = this.queue.length}, - + /* + * Allows pushes to occur at the FRONT of the queue + * (so a command acts as a single unit, including anything + * that it pushes on to the command stack) + */ + SaveQueue: function () { + var queue = this.queue; + this.queue = []; + return queue; + }, + RestoreQueue: function (queue) { + this.queue = this.queue.concat(queue); + }, + /* * Handle loading of scripts that run asynchronously */ delayedLoad: function (url) { - this.debug('Loading: '+url); +// this.debug('Loading: '+url); this.Push(this,'startLoad',url); }, startLoad: function (url) { @@ -435,15 +579,22 @@ jsMath.Script = { if (url.substr(0,jsMath.root.length) == jsMath.root) {url = url.substr(jsMath.root.length)} jsMath.Message.Set("Loading "+url); - this.debug('Starting: '+url); this.cancelTimer = setTimeout('jsMath.Script.cancelLoad()',this.cancelTimeout); }, endLoad: function (action) { - this.debug('Ending: '+this.url); if (this.cancelTimer) {clearTimeout(this.cancelTimer); this.cancelTimer = null;} jsMath.Message.Clear(); if (action != 'cancel') {this.blocking = 0; this.Process()} }, + + Start: function () { +// this.debug('Starting: ['+this.queue.length+'] '+this.url); + this.tmpQueue = this.queue; this.queue = []; + }, + End: function () { +// this.debug('Ending: ['+this.queue.length+' + '+this.tmpQueue.length+'] '+this.url); + this.queue = this.queue.concat(this.tmpQueue); delete this.tmpQueue; + }, /* * If the loading takes too long, cancel it and end the load. @@ -461,16 +612,22 @@ jsMath.Script = { this.blocking = 1; setTimeout('jsMath.Script.endDelay()',time); }, - endDelay: function () {this.debug('endDelay'); this.blocking = 0; this.Process()}, + endDelay: function () { +// this.debug('endDelay'); + this.blocking = 0; + this.Process(); + }, /* * Load an image and wait for it * (so MSIE won't load extra copies of it) */ + imageCount: 0, WaitForImage: function (file) { - this.blocking = 1; if (this.img == null) {this.img = []} + this.blocking = 1; this.imageCount++; + if (this.img == null) {this.img = []} var img = new Image(); this.img[this.img.length] = img; - img.onload = function () {jsMath.Script.endDelay()} + img.onload = function () {if (--jsMath.Script.imageCount == 0) jsMath.Script.endDelay()} img.onerror = img.onload; img.onabort = img.onload; img.src = file; }, @@ -485,15 +642,17 @@ jsMath.Script = { data[k] = d.join(''); } window.eval(data.join('')); - }, + } /* * for debugging the event queue */ - debug: function (message) { -// if (jsMath.document.body && jsMath.window.debug) {jsMath.window.debug(message)} -// else {alert(message)} - } + /* + * ,debug: function (message) { + * if (jsMath.document.body && jsMath.window.debug) {jsMath.window.debug(message)} + * else {alert(message)} + * } + */ }; @@ -545,7 +704,7 @@ jsMath.Message = { if (!this.message.style.cursor) {this.message.style.cursor = 'hand'} this.message.title = ' Cancel Processing of Math '; } else { - this.message.style.cursor; + this.message.style.cursor = ''; this.message.title = ''; } } else { @@ -622,7 +781,7 @@ jsMath.Setup = { */ Script: function (file,show) { if (this.loaded[file]) {return} else {this.loaded[file] = 1} - if (!file.match('^([a-zA-Z]+:/)?/')) {file = jsMath.root + file} + if (!file.match('^([a-zA-Z]+:/?)?/')) {file = jsMath.root + file} jsMath.Script.Load(file,show); }, @@ -651,23 +810,28 @@ jsMath.Setup = { if (script) { for (var i = 0; i < script.length; i++) { var src = script[i].src; - if (src && src.match('(^|/)jsMath.js$')) { + if (src && src.match('(^|/|\\\\)jsMath.js$')) { jsMath.root = src.replace(/jsMath.js$/,''); - if (jsMath.root.charAt(0) == '/') { - jsMath.root = jsMath.document.location.protocol + '//' - + jsMath.document.location.host + jsMath.root; - } else if (!jsMath.root.match(/^[a-z]+:/i)) { - src = new String(jsMath.document.location); - jsMath.root = src.replace(new RegExp('[^/]*$'),'') + jsMath.root; - while (jsMath.root.match('/[^/]*/\\.\\./')) { - jsMath.root = jsMath.root.replace(new RegExp('/[^/]*/\\.\\./'),'/'); - } - } - i = script.length; + break; } } } } + if (jsMath.root.charAt(0) == '\\') {jsMath.root = jsMath.root.replace(/\\/g,'/')} + if (jsMath.root.charAt(0) == '/') { + if (jsMath.root.charAt(1) != '/') { + if (jsMath.document.location.port) + {jsMath.root = ':' + jsMath.document.location.port + jsMath.root} + jsMath.root = '//' + jsMath.document.location.host + jsMath.root; + } + jsMath.root = jsMath.document.location.protocol + jsMath.root; + } else if (!jsMath.root.match(/^[a-z]+:/i)) { + var src = new String(jsMath.document.location); + var pattern = new RegExp('/[^/]*/\\.\\./') + jsMath.root = src.replace(new RegExp('[^/]*$'),'') + jsMath.root; + while (jsMath.root.match(pattern)) + {jsMath.root = jsMath.root.replace(pattern,'/')} + } jsMath.Img.root = jsMath.root + "fonts/"; jsMath.blank = jsMath.root + "blank.gif"; this.Domain(); @@ -679,6 +843,7 @@ jsMath.Setup = { * the domain of the calling page. */ Domain: function () { + try {jsMath.document.domain} catch (err) {return} var jsDomain = ''; var pageDomain = jsMath.document.domain; if (jsMath.root.match('://([^/]*)/')) {jsDomain = RegExp.$1} jsDomain = jsDomain.replace(/:\d+$/,''); @@ -688,7 +853,7 @@ jsMath.Setup = { // catch the error (Grrr!), so exit for them. // if (navigator.appName == 'Microsoft Internet Explorer' && - navigator.platform == 'MacPPC' && navigator.onLine && + jsMath.platform == 'mac' && navigator.onLine && navigator.userProfile && jsMath.document.all) return; jsDomain = jsDomain.split(/\./); pageDomain = pageDomain.split(/\./); if (jsDomain.length < 2 || pageDomain.length < 2 || @@ -766,11 +931,11 @@ jsMath.Setup = { * Compute font parameters for various sizes */ Sizes: function () { - jsMath.TeXparams = []; - for (var j=0; j < jsMath.sizes.length; j++) {jsMath.TeXparams[j] = {}} - for (var i in jsMath.TeX) { + jsMath.TeXparams = []; var i; var j; + for (j=0; j < jsMath.sizes.length; j++) {jsMath.TeXparams[j] = {}} + for (i in jsMath.TeX) { if (typeof(jsMath.TeX[i]) != 'object') { - for (var j=0; j < jsMath.sizes.length; j++) { + for (j=0; j < jsMath.sizes.length; j++) { jsMath.TeXparams[j][i] = jsMath.sizes[j]*jsMath.TeX[i]/100; } } @@ -796,7 +961,8 @@ jsMath.Setup = { var string = ''; for (var id in styles) {string += id + ' {'+styles[id]+"}\n"} if (jsMath.document.createStyleSheet) {// check for MSIE head.insertAdjacentHTML('beforeEnd', - 'x'); + 'x' // MSIE needs this for some reason + + ''); } else { var style = jsMath.document.createElement('style'); style.type = "text/css"; style.appendChild(jsMath.document.createTextNode(string)); @@ -809,7 +975,7 @@ jsMath.Setup = { */ Body: function () { if (this.inited) return; - + this.inited = -1; jsMath.Setup.Hidden(); this.inited = -2; @@ -826,16 +992,25 @@ jsMath.Setup = { // make sure browser-specific loads are done before this jsMath.Script.Push(jsMath.Font,'Check'); - + if (jsMath.Font.register.length) + {jsMath.Script.Push(jsMath.Font,'LoadRegistered')} + this.inited = 1; }, /* - * Web page author can override this to do initialization - * that must be done before the font check is performed, or - * at other times (as indicated by the value of the parameter). + * Web page author can override the entries to the UserEvent hash + * functions that will be run at various times during jsMath's setup + * process. */ - User: function (when) {} + User: function (when) { + if (jsMath.Setup.UserEvent[when]) {(jsMath.Setup.UserEvent[when])()} + }, + + UserEvent: { + "pre-font": null, // after browser is set up but before fonts are tested + "onload": null // after jsMath.js is loaded and finished running + } }; @@ -886,6 +1061,7 @@ jsMath.Browser = { operaHiddenFix: '', // for Opera to fix bug with math in tables msieCenterBugFix: '', // for MSIE centering bug with image fonts msieInlineBlockFix: '', // for MSIE alignment bug in non-quirks mode + msieSpaceFix: '', // for MSIE to avoid dropping empty spans imgScale: 1, // MSI scales images for 120dpi screens, so compensate renameOK: 1, // tells if brower will find a tag whose name @@ -915,13 +1091,15 @@ jsMath.Browser = { * and decide whether to use spans or images for spacing */ TestInlineBlock: function () { - this.block = "display:inline-block"; + this.block = "display:-moz-inline-box"; this.hasInlineBlock = jsMath.BBoxFor('').w > 0; - if (!this.hasInlineBlock) { - this.block = "display:-moz-inline-box"; + if (this.hasInlineBlock) { + jsMath.styles['.typeset .blank'] = jsMath.styles['.typeset .blank'].replace(/display:inline-block/,this.block); + jsMath.styles['.typeset .spacer'] = jsMath.styles['.typeset .spacer'].replace(/display:inline-block/,''); + } else { + this.block = "display:inline-block"; this.hasInlineBlock = jsMath.BBoxFor('').w > 0; if (!this.hasInlineBlock) return; - jsMath.styles['.typeset .blank'] = jsMath.styles['.typeset .blank'].replace(/display:inline-block/,this.block); } this.block += ';overflow:hidden'; var h = jsMath.BBoxFor('x').h; @@ -1013,27 +1191,44 @@ jsMath.Browser = { MSIE: function () { if (this.spanHeightVaries && !this.spanHeightTooBig) { jsMath.browser = 'MSIE'; - if (navigator.platform == 'Win32') { + if (jsMath.platform == 'pc') { + this.IE7 = (window.XMLHttpRequest != null); + this.quirks = (jsMath.document.compatMode == "BackCompat"); + this.msieStandard6 = !this.quirks && !this.IE7; this.allowAbsoluteDelim = 1; this.separateSkips = 1; this.buttonCheck = 1; this.msieBlankBug = 1; + this.msieAccentBug = 1; this.msieRelativeClipBug = 1; this.msieDivWidthBug = 1; this.msiePositionFixedBug = 1; this.msieIntegralBug = 1; this.waitForImages = 1; - this.msieAlphaBug = 1; this.alphaPrintBug = 1; + this.msieAlphaBug = !this.IE7; this.alphaPrintBug = !this.IE7; this.msieCenterBugFix = 'position:relative; '; this.msieInlineBlockFix = ' display:inline-block;'; + this.msieTeXfontBaselineBug = !jsMath.Browser.quirks; + if (!this.IE7) {this.msieSpaceFix = ''} jsMath.Macro('joinrel','\\mathrel{\\kern-5mu}'), + jsMath.Parser.prototype.mathchardef.mapstocharOrig = jsMath.Parser.prototype.mathchardef.mapstochar; + delete jsMath.Parser.prototype.mathchardef.mapstochar; + jsMath.Macro('mapstochar','\\rlap{\\mapstocharOrig\\,}\\kern1mu'), jsMath.styles['.typeset .arial'] = "font-family: 'Arial unicode MS'"; - // MSIE doesn't implement fixed positioning, so use absolute - jsMath.styles['#jsMath_message'] = + if (!this.IE7 || this.quirks) { + // MSIE doesn't implement fixed positioning, so use absolute + jsMath.styles['#jsMath_message'] = jsMath.styles['#jsMath_message'].replace(/position:fixed/,"position:absolute").replace(/width:auto/,""); - jsMath.styles['#jsMath_panel'] = + jsMath.styles['#jsMath_panel'] = jsMath.styles['#jsMath_panel'].replace(/position:fixed/,"position:absolute").replace(/width:auto/,""); - jsMath.styles['#jsMath_button'] = 'width:1px; ' + jsMath.styles['#jsMath_button'] = 'width:1px; ' + jsMath.styles['#jsMath_button'].replace(/position:fixed/,"position:absolute").replace(/width:auto/,""); - jsMath.window.onscroll = jsMath.Controls.MoveButton; + jsMath.window.attachEvent("onscroll",jsMath.Controls.MoveButton); + if (this.IE7) jsMath.window.attachEvent("onresize",jsMath.Controls.MoveButton); + this.msieMoveButtonHack = this.IE7; + } + // Make MSIE put borders around the whole button + jsMath.styles['#jsMath_noFont .link'] += " display: inline-block;"; // MSIE needs this NOT to be inline-block jsMath.styles['.typeset .spacer'] = jsMath.styles['.typeset .spacer'].replace(/display:inline-block/,''); + // MSIE can't insert DIV's into text nodes, so tex2math must use SPAN's to fake DIV's + jsMath.styles['.tex2math_div'] = jsMath.styles['div.typeset'] + '; width: 100%; display: inline-block'; // MSIE will rescale images if the DPIs differ if (screen.deviceXDPI && screen.logicalXDPI && screen.deviceXDPI != screen.logicalXDPI) { @@ -1043,13 +1238,14 @@ jsMath.Browser = { // Handle bug with getting width of italic text this.italicString = 'x'; jsMath.EmBoxFor = jsMath.EmBoxForItalics; - } else if (navigator.platform == 'MacPPC') { + } else if (jsMath.platform == 'mac') { this.msieAbsoluteBug = 1; this.msieButtonBug = 1; this.msieDivWidthBug = 1; this.msieBlankBug = 1; + this.quirks = 1; jsMath.Setup.Script('jsMath-msie-mac.js'); jsMath.Parser.prototype.macros.angle = ['Replace','ord','','normal']; - jsMath.styles['#jsMath_panel'] = 'width:25em; ' + jsMath.styles['#jsMath_panel'].replace(/width:auto/,""); - jsMath.styles['#jsMath_button'] = 'width:1px; ' + jsMath.styles['#jsMath_button'].replace(/width:auto/,""); + jsMath.styles['#jsMath_panel'] = 'width:42em; ' + jsMath.styles['#jsMath_panel'].replace(/width:auto/,""); + jsMath.Controls.cookie.printwarn = 0; // MSIE/Mac doesn't handle '@media screen' } jsMath.Macro('not','\\mathrel{\\rlap{\\kern3mu/}}'); } @@ -1061,13 +1257,15 @@ jsMath.Browser = { Mozilla: function () { if (jsMath.hidden.ATTRIBUTE_NODE) { jsMath.browser = 'Mozilla'; - if (navigator.platform == 'Win32') {this.alphaPrintBug = 1} - this.allowAbsoluteDelim = 1; // this.separateSkips = 1; // no longer needed? + if (jsMath.platform == 'pc') {this.alphaPrintBug = 1} + this.allowAbsoluteDelim = 1; + jsMath.styles['#jsMath_button'] = jsMath.styles['#jsMath_button'].replace(/cursor:hand/,'cursor:pointer'); + jsMath.styles['#jsMath_noFont .link'] = jsMath.styles['#jsMath_noFont .link'].replace(/cursor:hand/,'cursor:pointer'); jsMath.Macro('not','\\mathrel{\\rlap{\\kern3mu/}}'); if (navigator.vendor == 'Firefox') { - jsMath.Browser.version = navigator.vendorSub; + this.version = navigator.vendorSub; } else if (navigator.userAgent.match(' Firefox/([0-9.]+)( |$)')) { - jsMath.Browser.version = RegExp.$1; + this.version = RegExp.$1; } } }, @@ -1080,8 +1278,9 @@ jsMath.Browser = { jsMath.browser = 'OmniWeb'; this.allowAbsolute = this.hasInlineBlock; this.allowAbsoluteDelim = this.allowAbsolute; - this.valignBug = this.allowAbsolute; + this.valignBug = !this.allowAbsolute; this.buttonCheck = 1; this.textNodeBug = 1; + jsMath.noChangeGlobal = 1; // OmniWeb craches on GoGlobal if (!this.hasInlineBlock) {jsMath.Setup.Script('jsMath-old-browsers.js')} } }, @@ -1108,11 +1307,15 @@ jsMath.Browser = { jsMath.browser = 'Safari'; var version = navigator.userAgent.match("Safari/([0-9]+)"); version = (version)? version[1] : 400; - for (var i = 0; i < jsMath.TeX.fam.length; i++) - {if (jsMath.TeX.fam[i]) {jsMath.TeX[jsMath.TeX.fam[i]].dh = .1}} + for (var i = 0; i < jsMath.TeX.fam.length; i++) { + if (jsMath.TeX.fam[i] && jsMath.TeX[jsMath.TeX.fam[i]]) + {jsMath.TeX[jsMath.TeX.fam[i]].dh = .1} + } jsMath.TeX.axis_height += .05; + jsMath.TeX.default_rule_thickness += .025; this.allowAbsoluteDelim = version >= 125; this.safariIFRAMEbug = version >= 312 && version < 412; + this.safariButtonBug = version < 412; this.safariImgBug = 1; this.textNodeBug = 1; this.buttonCheck = 1; this.styleChangeDelay = 1; @@ -1134,6 +1337,16 @@ jsMath.Browser = { jsMath.Setup.Script('jsMath-old-browsers.js'); } } + // Apparently, Konqueror wants the names without the hyphen + jsMath.Add(jsMath.styles,{ + '.typeset .cmr10': 'font-family: jsMath-cmr10, jsMath cmr10, serif', + '.typeset .cmbx10': 'font-family: jsMath-cmbx10, jsMath cmbx10, jsMath-cmr10, jsMath cmr10', + '.typeset .cmti10': 'font-family: jsMath-cmti10, jsMath cmti10, jsMath-cmr10, jsMath cmr10', + '.typeset .cmmi10': 'font-family: jsMath-cmmi10, jsMath cmmi10', + '.typeset .cmsy10': 'font-family: jsMath-cmsy10, jsMath cmsy10', + '.typeset .cmex10': 'font-family: jsMath-cmex10, jsMath cmex10' + }); + jsMath.Font.testFont = "jsMath-cmex10, jsMath cmex10"; } } @@ -1146,7 +1359,9 @@ jsMath.Browser = { */ jsMath.Font = { + testFont: "jsMath-cmex10", fallback: "symbol", // the default fallback method + register: [], // list of fonts registered before jsMath.Init() // the HTML for the missing font message message: @@ -1158,6 +1373,14 @@ jsMath.Font = { 'Extra TeX fonts not found:
' + 'Using image fonts instead. This may be slow and might not print well.
\n' + 'Use the jsMath control panel to get additional information.', + + print_message: + 'To print higher-resolution math symbols, click the
\n' + + 'Hi-Res Fonts for Printing button on the jsMath control panel.
\n', + + alpha_message: + 'If the math symbols print as black boxes, turn off image alpha channels
\n' + + 'using the Options pane of the jsMath control panel.
\n', /* * Look to see if a font is found. @@ -1186,9 +1409,9 @@ jsMath.Font = { * If they are found, load the BaKoMa encoding information. */ CheckTeX: function () { - var wh = jsMath.BBoxFor(''+jsMath.TeX.cmex10[1].c+''); + var wh = jsMath.BBoxFor(''+jsMath.TeX.cmex10[1].c+''); jsMath.nofonts = ((wh.w*3 > wh.h || wh.h == 0) && !this.Test1('cmr10',null,null,'jsMath-')); - if (jsMath.nofonts && (navigator.platform != "MacPPC" || + if (jsMath.nofonts && (jsMath.platform != "mac" || jsMath.browser != 'Mozilla' || !jsMath.Browser.VersionAtLeast(1.5))) { wh = jsMath.BBoxFor(''+jsMath.TeX.cmex10[1].c+''); jsMath.nofonts = ((wh.w*3 > wh.h || wh.h == 0) && !this.Test1('cmr10')); @@ -1228,12 +1451,16 @@ jsMath.Font = { } if (jsMath.noImgFonts) {cookie.font = 'unicode'} if (cookie.font == 'unicode') { - var platform = ({Win32: 'pc', MacPPC: 'mac'})[navigator.platform] || 'unix'; - jsMath.Setup.Script('jsMath-fallback-'+platform+'.js'); + jsMath.Setup.Script('jsMath-fallback-'+jsMath.platform+'.js'); jsMath.Box.TeXnonfallback = jsMath.Box.TeX; jsMath.Box.TeX = jsMath.Box.TeXfallback; return; } + if (!cookie.print && cookie.printwarn) { + this.PrintMessage( + (jsMath.Browser.alphaPrintBug && jsMath.Controls.cookie.alpha) ? + this.print_message + this.alpha_message : this.print_message); + } if (jsMath.Browser.waitForImages) { jsMath.Script.Push(jsMath.Script,"WaitForImage",jsMath.blank); } @@ -1261,16 +1488,16 @@ jsMath.Font = { * of your page. */ Message: function (message) { - if(jsMath.Element("Warning")) return; + if (jsMath.Element("Warning")) return; var div = jsMath.Setup.DIV("Warning",{}); div.innerHTML = '
' - + '
' + message + + '
' + message + '
' + 'jsMath Control Panel' + '' + 'Hide this Message' - + '

' + + '

' + '
' + '

'; }, @@ -1280,12 +1507,25 @@ jsMath.Font = { if (message) {message.style.display = "none"} }, + PrintMessage: function (message) { + if (jsMath.Element("PrintWarning")) return; + var div = jsMath.Setup.DIV("PrintWarning",{}); + div.innerHTML = + '
' + + '
' + message + '
' + + '
' + + '

'; + }, + /* * Register an extra font so jsMath knows about it */ - Register: function (data) { - jsMath.Script.Start(); + Register: function (data,force) { if (typeof(data) == 'string') {data = {name: data}} + if (!jsMath.Setup.inited && !force) { + this.register[this.register.length] = data; + return; + } var fontname = data.name; var name = fontname.replace(/10$/,''); var fontfam = jsMath.TeX.fam.length; if (data.prefix == null) {data.prefix = ""} @@ -1304,38 +1544,49 @@ jsMath.Font = { */ data.styles['.typeset .'+fontname] = data.style; jsMath.Setup.Styles(data.styles); - jsMath.Script.Push(jsMath.Setup,'TeXfont',fontname); + if (jsMath.initialized) {jsMath.Script.Push(jsMath.Setup,'TeXfont',fontname)} /* * Check for font and give message if missing */ + var cookie = jsMath.Controls.cookie; var hasTeXfont = !jsMath.nofonts && data.test(fontname,data.testChar,data.testFactor,data.prefix); - if (hasTeXfont && jsMath.Controls.cookie.font == 'tex') { + if (hasTeXfont && cookie.font == 'tex') { if (data.tex) {data.tex(fontname,fontfam,data)} - jsMath.Script.End(); return; } - if (!hasTeXfont && jsMath.Controls.cookie.warn && - jsMath.Controls.cookie.font == 'tex' && !jsMath.nofonts) { - if (!jsMath.Element("Warning")) this.Message(this.extra_message); - var extra = jsMath.Element("ExtraFonts"); - if (extra) { - if (extra.innerHTML != "") {extra.innerHTML += ','} - extra.innerHTML += " " + data.prefix+fontname; + if (!hasTeXfont && cookie.warn && cookie.font == 'tex' && !jsMath.nofonts) { + if (!cookie.fonts.match("/"+fontname+"/")) { + cookie.fonts += fontname + "/"; jsMath.Controls.SetCookie(0); + if (!jsMath.Element("Warning")) this.Message(this.extra_message); + var extra = jsMath.Element("ExtraFonts"); + if (extra) { + if (extra.innerHTML != "") {extra.innerHTML += ','} + extra.innerHTML += " " + data.prefix+fontname; + } } } - if (jsMath.Controls.cookie.font == 'unicode') { + if (cookie.font == 'unicode' || jsMath.noImgFonts) { if (data.fallback) {data.fallback(fontname,fontfam,data)} - jsMath.Script.End(); return; } // Image fonts var font = {}; font[fontname] = ['all']; jsMath.Img.SetFont(font); jsMath.Img.LoadFont(fontname); - jsMath.Script.Push(jsMath.Img,'Scale'); - jsMath.Script.Push(jsMath.Img,'UpdateFonts'); - jsMath.Script.End(); + if (jsMath.initialized) { + jsMath.Script.Push(jsMath.Img,'Scale'); + jsMath.Script.Push(jsMath.Img,'UpdateFonts'); + } + }, + /* + * If fonts are registered before jsMath.Init() is called, jsMath.em + * will not be available, so they need to be delayed. + */ + LoadRegistered: function () { + var i = 0; + while (i < this.register.length) {this.Register(this.register[i++],1)} + this.register = []; }, /* @@ -1359,11 +1610,13 @@ jsMath.Controls = { cookie: { scale: 100, font: 'tex', autofont: 1, scaleImg: 0, alpha: 1, - warn: 1, button: 1, progress: 1, asynch: 0, blank: 0, - print: 0, keep: '0D' + warn: 1, fonts: '/', printwarn: 1, stayhires: 0, + button: 1, progress: 1, asynch: 0, blank: 0, + print: 0, keep: '0D', global: 'auto', hiddenGlobal: 1 }, cookiePath: '/', // can also set cookieDomain + noCookiePattern: /^(file|mk):$/, // pattern for handling cookies locally /* @@ -1390,19 +1643,48 @@ jsMath.Controls = { Button: function () { var button = jsMath.Setup.DIV("button",{}); button.title = ' Open jsMath Control Panel '; - button.innerHTML = 'jsMath'; - if (button.offsetWidth < 2*jsMath.em) {button.style.width = "auto"} - button.onclick = new Function("jsMath.Controls.Panel()"); + button.innerHTML = + 'jsMath'; + if (!jsMath.Global.isLocal && !jsMath.noShowGlobal) { + button.innerHTML += + 'Global '; + } + if (button.offsetWidth < 30) {button.style.width = "auto"} if (!this.cookie.button) {button.style.display = "none"} }, - /* - * MSIE doesn't implement position:fixed, so redraw the button on scrolls. - */ + /* + * Since MSIE doesn't handle position:float, we need to have the + * window repositioned every time the window scrolls. We do that + * by hiding then showing the window, which apparently causes MSIE + * to recompute its location. In MSIE7, that doesn't work anymore, + * so we have to move the window by hand. + */ MoveButton: function () { - if (!this.button) {this.button = jsMath.Element("button")} - this.button.style.visibility = "hidden"; - this.button.style.visibility = "visible"; + var controls = jsMath.Controls; + if (!controls.button) {controls.button = jsMath.Element("button")} + if (controls.button) controls.MoveElement(controls.button,3,2); + var dx = 20; var dy = 20; + if (controls.button) {dy = controls.button.offsetHeight + 6; dx = dy + 5} + if (controls.panel) controls.MoveElement(controls.panel,dx,dy); + }, + MoveElement: function (obj,dx,dy) { + if (jsMath.Browser.IE7) { + var body = document.body; + obj.style.right = "auto"; + obj.style.bottom = "auto"; + // + // This position can't be overridden by CSS (grr) + // (Perhaps we can look up the current position and which sides it's + // attached to and use those. What a pain.) + // + obj.style.left = body.clientWidth + body.scrollLeft - obj.offsetWidth - dx + "px"; + obj.style.top = body.clientHeight + body.scrollTop - obj.offsetHeight - dy + "px"; + } else { + obj.style.visibility = "hidden"; + obj.style.visibility = "visible"; + } }, /* @@ -1410,18 +1692,28 @@ jsMath.Controls = { * (for file: references, use url '?' syntax) */ GetCookie: function () { + // save the current cookie settings as the defaults + if (this.defaults == null) {this.defaults = {}} + jsMath.Add(this.defaults,this.cookie); this.userSet = {}; + // get the browser's cookie data var cookies = jsMath.document.cookie; - if (jsMath.window.location.protocol == 'file:') - {cookies = unescape(jsMath.window.location.search.substr(1))} - if (cookies.match(/jsMath=([^;]*)/)) { - var data = RegExp.$1.split(/,/); + if (jsMath.window.location.protocol.match(this.noCookiePattern)) { + cookies = this.localGetCookie(); + this.isLocalCookie = 1; + } + if (cookies.match(/jsMath=([^;]+)/)) { + var data = unescape(RegExp.$1).split(/,/); for (var i = 0; i < data.length; i++) { var x = data[i].match(/(.*):(.*)/); if (x[2].match(/^\d+$/)) {x[2] = 1*x[2]} // convert from string this.cookie[x[1]] = x[2]; + this.userSet[x[1]] = 1; } } }, + localGetCookie: function () { + return jsMath.window.location.search.substr(1); + }, /* * Save the cookie data in the browser @@ -1429,15 +1721,17 @@ jsMath.Controls = { */ SetCookie: function (warn) { var cookie = []; - for (var id in this.cookie) {cookie[cookie.length] = id + ':' + this.cookie[id]} + for (var id in this.cookie) { + if (this.defaults[id] == null || this.cookie[id] != this.defaults[id]) + {cookie[cookie.length] = id + ':' + this.cookie[id]} + } cookie = cookie.join(','); - if (jsMath.window.location.protocol == 'file:') { - if (!warn) return; - this.loaded = 0; - var href = jsMath.window.location.href; - href = href.replace(/\?.*/,"") + '?jsMath=' + escape(cookie); - if (href != jsMath.window.location.href) {jsMath.window.location.replace(href)} + if (this.isLocalCookie) { + if (warn == 2) {return 'jsMath='+escape(cookie)} + this.localSetCookie(cookie,warn); } else { + cookie = escape(cookie); + if (cookie == '') {warn = 0} if (this.cookiePath) {cookie += '; path='+this.cookiePath} if (this.cookieDomain) {cookie += '; domain='+this.cookieDomain} if (this.cookie.keep != '0D') { @@ -1452,13 +1746,33 @@ jsMath.Controls = { this.cookie.keep.substr(0,1) * ms[this.cookie.keep.substr(1,1)]); cookie += '; expires=' + exp.toGMTString(); } - jsMath.document.cookie = 'jsMath='+cookie; - var cookies = jsMath.document.cookie; - if (warn && !cookies.match(/jsMath=/)) - {alert("Cookies must be enabled in order to save jsMath options")} + if (cookie != '') { + jsMath.document.cookie = 'jsMath='+cookie; + var cookies = jsMath.document.cookie; + if (warn && !cookies.match(/jsMath=/)) + {alert("Cookies must be enabled in order to save jsMath options")} + } } + return null; + }, + localSetCookie: function (cookie,warn) { + if (!warn) return; + var href = String(jsMath.window.location).replace(/\?.*/,""); + if (cookie != '') {href += '?jsMath=' + escape(cookie)} + if (href != jsMath.window.location.href) {this.Reload(href)} + }, + + /* + * Reload the page (with the given URL) + */ + Reload: function (url) { + if (!this.loaded) return; + this.loaded = 0; jsMath.Setup.inited = -100; + jsMath.Global.ClearCache(); + if (url) {jsMath.window.location.replace(url)} + else {jsMath.window.location.reload()} } - + }; /***************************************************************************/ @@ -1525,7 +1839,7 @@ jsMath.TeX = { delim1: 2.39, delim2: 1.0, axis_height: .25, - default_rule_thickness: .04, + default_rule_thickness: .06, big_op_spacing1: .111111, big_op_spacing2: .166666, big_op_spacing3: .2, @@ -2124,7 +2438,6 @@ jsMath.Img = { */ UpdateFonts: function () { var change = this.update; if (!this.loaded) return; - var best = this[jsMath.Img.fonts[this.best]]; for (var font in change) { for (var i = 0; i < change[font].length; i++) { var c = change[font][i]; @@ -2184,10 +2497,10 @@ jsMath.Img = { * Setup for print mode, and create the hex code table */ Init: function () { - if (jsMath.Controls.cookie.print) { - jsMath.Controls.cookie.print = 0; + if (jsMath.Controls.cookie.print || jsMath.Controls.cookie.stayhires) { + jsMath.Controls.cookie.print = jsMath.Controls.cookie.stayhires; this.factor *= 3; - if (jsMath.window.location.protocol != 'file:') {jsMath.Controls.SetCookie(0)} + if (!jsMath.Controls.isLocalCookie || !jsMath.Global.isLocal) {jsMath.Controls.SetCookie(0)} if (jsMath.Browser.alphaPrintBug) {jsMath.Controls.cookie.alpha = 0} } var codes = '0123456789ABCDEF'; @@ -2227,7 +2540,7 @@ jsMath.HTML = { */ Spacer: function (w) { if (w == 0) {return ''}; - return ''; + return jsMath.Browser.msieSpaceFix+''; }, /* @@ -2251,7 +2564,7 @@ jsMath.HTML = { if (d == null) {d = 0} if (h) { var H = this.Em(h+d); - if (isRule && h > 0 && h*jsMath.em < 1.5) {H = "1px"; h = 1/jsMath.em} + if (isRule && h*jsMath.em < 1.5) {H = "1px"; h = 1/jsMath.em} style += 'height:'+H+';'; } if (jsMath.Browser.mozInlineBlockBug) {d = -h} @@ -2298,11 +2611,26 @@ jsMath.HTML = { * also doesn't combine vertical and horizontal spacing well. * Here the x and y positioning are done in separate tags */ - PlaceSeparateSkips: function (html,x,y) { + PlaceSeparateSkips: function (html,x,y,mw,Mw,w) { if (Math.abs(x) < .0001) {x = 0} if (Math.abs(y) < .0001) {y = 0} - if (y) {html = '' + html + ''} + if (y) { + var lw = 0; var rw = 0; var width = ""; + if (mw != null) { + rw = Mw - w; lw = mw; + width = ' width:'+this.Em(Mw-mw)+';'; + } + html = + this.Spacer(lw-rw) + + '' + + this.Spacer(-lw) + + html + + this.Spacer(rw) + + '' + } if (x) {html = this.Spacer(x) + html} return html; }, @@ -2310,12 +2638,20 @@ jsMath.HTML = { /* * Place a SPAN with absolute coordinates */ - PlaceAbsolute: function (html,x,y) { + PlaceAbsolute: function (html,x,y,mw,Mw,w) { if (Math.abs(x) < .0001) {x = 0} if (Math.abs(y) < .0001) {y = 0} - html = '' + html + ' '; - // space normalizes line height in script styles + var leftSpace = ""; var rightSpace = ""; + if (jsMath.Browser.msieRelativeClipBug && mw != null) { + leftSpace = this.Spacer(-mw); x += mw; + rightSpace = this.Spacer(Mw-w); + } + html = + '' + + leftSpace + html + rightSpace + + ' ' + // space normalizes line height in script styles + ''; return html; }, @@ -2332,13 +2668,17 @@ jsMath.HTML = { if (jsMath.Browser.msieAbsoluteBug) { // for MSIE (Mac) html = '' + html + ''; } - html = '' + if (jsMath.Browser.spanHeightVaries) { + html = '' + html + ''; + } else { + html = '' + html + ''; + } return html; } @@ -2355,7 +2695,7 @@ jsMath.Box = function (format,text,w,h,d if (d == null) {d = jsMath.d} this.type = 'typeset'; this.w = w; this.h = h; this.d = d; this.bh = h; this.bd = d; - this.x = 0; this.y = 0; + this.x = 0; this.y = 0; this.mw = 0; this.Mw = w; this.html = text; this.format = format; }; @@ -2367,7 +2707,7 @@ jsMath.Add(jsMath.Box,{ /* * An empty box */ - Null: new jsMath.Box('null','',0,0,0), + Null: function () {return new jsMath.Box('null','',0,0,0)}, /* * A box containing only text whose class and style haven't been added @@ -2413,7 +2753,7 @@ jsMath.Add(jsMath.Box,{ // hack to avoid font changing back to the default // font when a unicode reference is not followed // by a letter or number - box.html += 'x'; + box.html += 'x'; } } return box; @@ -2424,10 +2764,11 @@ jsMath.Add(jsMath.Box,{ * sizes of the characters precomputed */ TeXfallback: function (C,font,style,size) { - c = jsMath.TeX[font][C]; if (!c.tclass) {c.tclass = font} + var c = jsMath.TeX[font][C]; if (!c.tclass) {c.tclass = font} if (c.img != null) {return this.TeXnonfallback(C,font,style,size)} if (c.h != null && c.a == null) {c.a = c.h-1.1*jsMath.TeX.x_height} - var box = this.Text(c.c,c.tclass,style,size,c.a,c.d); + var a = c.a; var d = c.d; // avoid Firefox warnings + var box = this.Text(c.c,c.tclass,style,size,a,d); var scale = jsMath.Typeset.TeX(style,size).scale; if (c.bh != null) { box.bh = c.bh*scale; @@ -2565,32 +2906,32 @@ jsMath.Add(jsMath.Box,{ var bot = this.GetChar(C.delim.bot? C.delim.bot: C.delim.rep,font); var ext = jsMath.Typeset.AddClass(rep.tclass,rep.c); var w = rep.w; var h = rep.h+rep.d - var y; var dx; + var y; var Y; var html; var dx; var i; var n; if (C.delim.mid) {// braces var mid = this.GetChar(C.delim.mid,font); - var n = Math.ceil((H-(top.h+top.d)-(mid.h+mid.d)-(bot.h+bot.d))/(2*(rep.h+rep.d))); + n = Math.ceil((H-(top.h+top.d)-(mid.h+mid.d)-(bot.h+bot.d))/(2*(rep.h+rep.d))); H = 2*n*(rep.h+rep.d) + (top.h+top.d) + (mid.h+mid.d) + (bot.h+bot.d); - if (nocenter) {y = 0} else {y = H/2+a}; var Y = y; - var html = jsMath.HTML.Place(jsMath.Typeset.AddClass(top.tclass,top.c),0,y-top.h) - + jsMath.HTML.Place(jsMath.Typeset.AddClass(bot.tclass,bot.c),-(top.w+bot.w)/2,y-(H-bot.d)) - + jsMath.HTML.Place(jsMath.Typeset.AddClass(mid.tclass,mid.c),-(bot.w+mid.w)/2,y-(H+mid.h-mid.d)/2); + if (nocenter) {y = 0} else {y = H/2+a}; Y = y; + html = jsMath.HTML.Place(jsMath.Typeset.AddClass(top.tclass,top.c),0,y-top.h) + + jsMath.HTML.Place(jsMath.Typeset.AddClass(bot.tclass,bot.c),-(top.w+bot.w)/2,y-(H-bot.d)) + + jsMath.HTML.Place(jsMath.Typeset.AddClass(mid.tclass,mid.c),-(bot.w+mid.w)/2,y-(H+mid.h-mid.d)/2); dx = (w-mid.w)/2; if (Math.abs(dx) < .0001) {dx = 0} if (dx) {html += jsMath.HTML.Spacer(dx)} y -= top.h+top.d + rep.h; - for (var i = 0; i < n; i++) {html += jsMath.HTML.Place(ext,-w,y-i*h)} + for (i = 0; i < n; i++) {html += jsMath.HTML.Place(ext,-w,y-i*h)} y -= H/2 - rep.h/2; - for (var i = 0; i < n; i++) {html += jsMath.HTML.Place(ext,-w,y-i*h)} + for (i = 0; i < n; i++) {html += jsMath.HTML.Place(ext,-w,y-i*h)} } else {// everything else - var n = Math.ceil((H - (top.h+top.d) - (bot.h+bot.d))/(rep.h+rep.d)); + n = Math.ceil((H - (top.h+top.d) - (bot.h+bot.d))/(rep.h+rep.d)); // make sure two-headed arrows have an extender if (top.h+top.d < .9*(rep.h+rep.d)) {n = Math.max(1,n)} H = n*(rep.h+rep.d) + (top.h+top.d) + (bot.h+bot.d); - if (nocenter) {y = 0} else {y = H/2+a}; var Y = y; - var html = jsMath.HTML.Place(jsMath.Typeset.AddClass(top.tclass,top.c),0,y-top.h) + if (nocenter) {y = 0} else {y = H/2+a}; Y = y; + html = jsMath.HTML.Place(jsMath.Typeset.AddClass(top.tclass,top.c),0,y-top.h) dx = (w-top.w)/2; if (Math.abs(dx) < .0001) {dx = 0} if (dx) {html += jsMath.HTML.Spacer(dx)} y -= top.h+top.d + rep.h; - for (var i = 0; i < n; i++) {html += jsMath.HTML.Place(ext,-w,y-i*h)} + for (i = 0; i < n; i++) {html += jsMath.HTML.Place(ext,-w,y-i*h)} html += jsMath.HTML.Place(jsMath.Typeset.AddClass(bot.tclass,bot.c),-(w+bot.w)/2,Y-(H-bot.d)); } if (nocenter) {h = top.h} else {h = H/2+a} @@ -2607,38 +2948,40 @@ jsMath.Add(jsMath.Box,{ */ DelimExtendAbsolute: function (H,c,font,a,nocenter) { var Font = jsMath.TeX[font]; - var C = Font[c]; + var C = Font[c]; var html; var top = this.GetChar(C.delim.top? C.delim.top: C.delim.rep,font); var rep = this.GetChar(C.delim.rep,font); var bot = this.GetChar(C.delim.bot? C.delim.bot: C.delim.rep,font); + var n; var h; var y; var ext; var i; if (C.delim.mid) {// braces var mid = this.GetChar(C.delim.mid,font); - var n = Math.ceil((H-(top.h+top.d)-(mid.h+mid.d-.05)-(bot.h+bot.d-.05))/(2*(rep.h+rep.d-.05))); + n = Math.ceil((H-(top.h+top.d)-(mid.h+mid.d-.05)-(bot.h+bot.d-.05))/(2*(rep.h+rep.d-.05))); H = 2*n*(rep.h+rep.d-.05) + (top.h+top.d) + (mid.h+mid.d-.05) + (bot.h+bot.d-.05); html = jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(top.tclass,top.c),0,0); - var h = rep.h+rep.d - .05; var y = top.d-.05 + rep.h; - var ext = jsMath.Typeset.AddClass(font,rep.c) - for (var i = 0; i < n; i++) {html += jsMath.HTML.PlaceAbsolute(ext,0,y+i*h)} + h = rep.h+rep.d - .05; y = top.d-.05 + rep.h; + ext = jsMath.Typeset.AddClass(font,rep.c) + for (i = 0; i < n; i++) {html += jsMath.HTML.PlaceAbsolute(ext,0,y+i*h)} html += jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(mid.tclass,mid.c),0,y+n*h-rep.h+mid.h); y += n*h + mid.h+mid.d - .05; - for (var i = 0; i < n; i++) {html += jsMath.HTML.PlaceAbsolute(ext,0,y+i*h)} + for (i = 0; i < n; i++) {html += jsMath.HTML.PlaceAbsolute(ext,0,y+i*h)} html += jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(bot.tclass,bot.c),0,y+n*h-rep.h+bot.h); } else {// all others - var n = Math.ceil((H - (top.h+top.d) - (bot.h+bot.d-.05))/(rep.h+rep.d-.05)); + n = Math.ceil((H - (top.h+top.d) - (bot.h+bot.d-.05))/(rep.h+rep.d-.05)); H = n*(rep.h+rep.d-.05) + (top.h+top.d) + (bot.h+bot.d-.05); html = jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(top.tclass,top.c),0,0); - var h = rep.h+rep.d-.05; var y = top.d-.05 + rep.h; - var ext = jsMath.Typeset.AddClass(rep.tclass,rep.c); - for (var i = 0; i < n; i++) {html += jsMath.HTML.PlaceAbsolute(ext,0,y+i*h)} + h = rep.h+rep.d-.05; y = top.d-.05 + rep.h; + ext = jsMath.Typeset.AddClass(rep.tclass,rep.c); + for (i = 0; i < n; i++) {html += jsMath.HTML.PlaceAbsolute(ext,0,y+i*h)} html += jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(bot.tclass,bot.c),0,y+n*h-rep.h+bot.h); } var w = top.w; if (nocenter) {h = top.h; y = 0} else {h = H/2 + a; y = h - top.h} - html = jsMath.HTML.Absolute(html,w,Font.h,"none",-y,top.h); +// html = jsMath.HTML.Absolute(html,w,Font.h,"none",-y,top.h); + html = jsMath.HTML.Absolute(html,w,Font.h,"none",-y,jsMath.h); var box = new jsMath.Box('html',html,rep.w,h,H-h); box.bh = jsMath.TeX[font].h; box.bd = jsMath.TeX[font].d; return box; @@ -2659,7 +3002,7 @@ jsMath.Add(jsMath.Box,{ if (CFSH == null) {return this.Space(TeX.nulldelimiterspace)} if (CFSH[2] == '') {return this.DelimExtend(H,CFSH[0],CFSH[1],TeX.axis_height,nocenter)} - box = jsMath.Box.TeX(CFSH[0],CFSH[1],CFSH[2],size).Styled(); + var box = jsMath.Box.TeX(CFSH[0],CFSH[1],CFSH[2],size).Styled(); if (nocenter) {box.y = -jsMath.TeX[CFSH[1]].dh*TeX.scale} else {box.y = -((box.h+box.d)/2 - box.d - TeX.axis_height)} if (Math.abs(box.y) < .0001) {box.y = 0} @@ -2701,9 +3044,12 @@ jsMath.Add(jsMath.Box,{ * ### still need to allow users to specify row and column attributes, * and do things like \span and \multispan ### */ - LayoutRelative: function (size,table,align,cspacing) { + LayoutRelative: function (size,table,align,cspacing,rspacing,vspace,useStrut,addWidth) { if (align == null) {align = []} if (cspacing == null) {cspacing = []} + if (rspacing == null) {rspacing = []} + if (useStrut == null) {useStrut = 1} + if (addWidth == null) {addWidth = 1} // get row and column maximum dimensions var scale = jsMath.sizes[size]/100; @@ -2711,7 +3057,9 @@ jsMath.Add(jsMath.Box,{ var unset = -1000; var bh = unset; var bd = unset; var i; var j; var row; for (i = 0; i < table.length; i++) { - row = table[i]; H[i] = jsMath.h*scale; D[i] = jsMath.d*scale; + if (rspacing[i] == null) {rspacing[i] = 0} + row = table[i]; + H[i] = useStrut*jsMath.h*scale; D[i] = useStrut*jsMath.d*scale; for (j = 0; j < row.length; j++) { row[j] = row[j].Remeasured(); if (row[j].h > H[i]) {H[i] = row[j].h} @@ -2722,15 +3070,17 @@ jsMath.Add(jsMath.Box,{ if (row[j].bd > bd) {bd = row[j].bd} } } + if (rspacing[table.length] == null) {rspacing[table.length] = 0} if (bh == unset) {bh = 0}; if (bd == unset) {bd = 0} // lay out the columns - var HD = (jsMath.hd-.01)*scale; + var HD = useStrut*(jsMath.hd-.01)*scale; + var dy = (vspace || 1) * scale/6; var html = ''; var pW = 0; var cW = 0; var w; var h; var y; var box; var mlist; var entry; for (j = 0; j < W.length; j++) { - mlist = []; y = -H[0]; pW = 0; + mlist = []; y = -H[0]-rspacing[0]; pW = 0; for (i = 0; i < table.length; i++) { entry = table[i][j]; if (entry && entry.format != 'null') { @@ -2740,8 +3090,7 @@ jsMath.Add(jsMath.Box,{ entry.x = w - pW; pW = entry.w + w; entry.y = y; mlist[mlist.length] = entry; } - if (i == table.length-1) {y -= D[i]} - else {y -= Math.max(HD,D[i]+H[i+1]) + scale/10} + if (i+1 < table.length) {y -= Math.max(HD,D[i]+H[i+1]) + dy + rspacing[i+1]} } if (cspacing[j] == null) cspacing[j] = scale; if (mlist.length > 0) { @@ -2752,16 +3101,16 @@ jsMath.Add(jsMath.Box,{ } // get the full width and height - w = -cspacing[W.length-1]; y = (H.length-1)*scale/10; + w = -cspacing[W.length-1]; y = (H.length-1)*dy + rspacing[0]; for (i = 0; i < W.length; i++) {w += W[i] + cspacing[i]} - for (i = 0; i < H.length; i++) {y += Math.max(HD,H[i]+D[i])} + for (i = 0; i < H.length; i++) {y += Math.max(HD,H[i]+D[i]) + rspacing[i+1]} h = y/2 + jsMath.TeX.axis_height; var d = y-h; // adjust the final row width, and vcenter the table // (add 1/6em at each side for the \,) - html += jsMath.HTML.Spacer(cW-cspacing[W.length-1] + scale/6); - html = jsMath.HTML.Place(html,scale/6,h); - box = new jsMath.Box('html',html,w+scale/3,h,d); + html += jsMath.HTML.Spacer(cW-cspacing[W.length-1] + addWidth*scale/6); + html = jsMath.HTML.Place(html,addWidth*scale/6,h); + box = new jsMath.Box('html',html,w+addWidth*scale/3,h,d); box.bh = bh; box.bd = bd; return box; }, @@ -2773,19 +3122,24 @@ jsMath.Add(jsMath.Box,{ * ### still need to allow users to specify row and column attributes, * and do things like \span and \multispan ### */ - LayoutAbsolute: function (size,table,align,cspacing) { + LayoutAbsolute: function (size,table,align,cspacing,rspacing,vspace,useStrut,addWidth) { if (align == null) {align = []} if (cspacing == null) {cspacing = []} + if (rspacing == null) {rspacing = []} + if (useStrut == null) {useStrut = 1} + if (addWidth == null) {addWidth = 1} // get row and column maximum dimensions var scale = jsMath.sizes[size]/100; - var HD = (jsMath.hd-.01)*scale; + var HD = useStrut*(jsMath.hd-.01)*scale; + var dy = (vspace || 1) * scale/6; var W = []; var H = []; var D = []; var w = 0; var h; var x; var y; var i; var j; var row; for (i = 0; i < table.length; i++) { + if (rspacing[i] == null) {rspacing[i] = 0} row = table[i]; - H[i] = jsMath.h*scale; D[i] = jsMath.d*scale; + H[i] = useStrut*jsMath.h*scale; D[i] = useStrut*jsMath.d*scale; for (j = 0; j < row.length; j++) { row[j] = row[j].Remeasured(); if (row[j].h > H[i]) {H[i] = row[j].h} @@ -2794,40 +3148,42 @@ jsMath.Add(jsMath.Box,{ else if (row[j].w > W[j]) {W[j] = row[j].w} } } + if (rspacing[table.length] == null) {rspacing[table.length] = 0} // get the height and depth of the centered table - y = (H.length-1)*scale/6; - for (i = 0; i < H.length; i++) {y += Math.max(HD,H[i]+D[i])} + y = (H.length-1)*dy + rspacing[0]; + for (i = 0; i < H.length; i++) {y += Math.max(HD,H[i]+D[i]) + rspacing[i+1]} h = y/2 + jsMath.TeX.axis_height; var d = y - h; // lay out the columns - var html = ''; var entry; w = scale/6; + var html = ''; var entry; w = addWidth*scale/6; for (j = 0; j < W.length; j++) { - y = H[0]-h; + y = H[0]-h + rspacing[0]; for (i = 0; i < table.length; i++) { entry = table[i][j]; if (entry && entry.format != 'null') { - if (align[j] == 'l') {x = 0} else - if (align[j] == 'r') {x = W[j] - entry.w} else + if (align[j] && align[j] == 'l') {x = 0} else + if (align[j] && align[j] == 'r') {x = W[j] - entry.w} else {x = (W[j] - entry.w)/2} html += jsMath.HTML.PlaceAbsolute(entry.html,w+x, - y-Math.max(0,entry.bh-jsMath.h*scale)); + y-Math.max(0,entry.bh-jsMath.h*scale), + entry.mw,entry.Mw,entry.w); } - if (i == table.length-1) {y += D[i]} - else {y += Math.max(HD,D[i]+H[i+1]) + scale/6} + if (i+1 < table.length) {y += Math.max(HD,D[i]+H[i+1]) + dy + rspacing[i+1]} } if (cspacing[j] == null) cspacing[j] = scale; w += W[j] + cspacing[j]; } // get the full width - w = -cspacing[W.length-1]+scale/3; + w = -cspacing[W.length-1]+addWidth*scale/3; for (i = 0; i < W.length; i++) {w += W[i] + cspacing[i]} - html = jsMath.HTML.Spacer(scale/6)+html+jsMath.HTML.Spacer(scale/6); + html = jsMath.HTML.Spacer(addWidth*scale/6)+html+jsMath.HTML.Spacer(addWidth*scale/6); if (jsMath.Browser.spanHeightVaries) {y = h-jsMath.h} else {y = 0} - html = jsMath.HTML.Absolute(html,w,h+d,d,y,H[0]); - var box = new jsMath.Box('html',html,w+scale/3,h,d); +// html = jsMath.HTML.Absolute(html,w,h+d,d,y,H[0]); + html = jsMath.HTML.Absolute(html,w,h+d,d,y,h); + var box = new jsMath.Box('html',html,w+addWidth*scale/3,h,d); return box; }, @@ -2835,10 +3191,11 @@ jsMath.Add(jsMath.Box,{ * Look for math within \hbox and other non-math text */ InternalMath: function (text,size) { + text = text.replace(/@\(([^)]*)\)/g,'<$1>'); if (!text.match(/\$|\\\(/)) {return this.Text(text,'normal','T',size).Styled()} var i = 0; var k = 0; var c; var match = ''; - var mlist = []; var parse; var html; var box; + var mlist = []; var parse; while (i < text.length) { c = text.charAt(i++); if (c == '$') { @@ -2889,7 +3246,7 @@ jsMath.Add(jsMath.Box,{ return box.mlist.Typeset(style,size); } if (box.type == 'text') { - box = this.Text(box.text,box.tclass,style,size,box.ascend,box.descend); + box = this.Text(box.text,box.tclass,style,size,box.ascend||null,box.descend||null); if (addstyle != 0) {box.Styled()} return box; } @@ -2897,7 +3254,7 @@ jsMath.Add(jsMath.Box,{ if (addstyle != 0) {box.Styled()} return box; } - return jsMath.Box.Null; + return jsMath.Box.Null(); }, /* @@ -2938,8 +3295,7 @@ jsMath.Package(jsMath.Box,{ * Recompute the box width to make it more accurate. */ Remeasured: function () { - if (this.w > 0 && !this.html.match(/position: ?absolute/)) - {this.w = jsMath.EmBoxFor(this.html).w} + if (this.w > 0) {this.w = jsMath.EmBoxFor(this.html).w} return this; } @@ -3183,7 +3539,7 @@ jsMath.Package(jsMath.mList,{ AddDelimiters: function(style,size) { var unset = -10000; var h = unset; var d = unset; for (var i = 0; i < this.mlist.length; i++) { - mitem = this.mlist[i]; + var mitem = this.mlist[i]; if (mitem.atom || mitem.type == 'box') { h = Math.max(h,mitem.nuc.h+mitem.nuc.y); d = Math.max(d,mitem.nuc.d-mitem.nuc.y); @@ -3239,7 +3595,7 @@ jsMath.Add(jsMath.mList.prototype.Atomiz phantom: function (style,size,mitem) { var box = mitem.nuc = jsMath.Box.Set(mitem.phantom,style,size); if (mitem.h) {box.Remeasured(); box.html = jsMath.HTML.Spacer(box.w)} - else {box.html = '', box.w = 0} + else {box.html = '', box.w = box.Mw = box.mw = 0;} if (!mitem.v) {box.h = box.d = 0} box.bd = box.bh = 0; delete mitem.phantom; @@ -3252,7 +3608,7 @@ jsMath.Add(jsMath.mList.prototype.Atomiz */ smash: function (style,size,mitem) { var box = mitem.nuc = jsMath.Box.Set(mitem.smash,style,size).Remeasured(); - box.h = box.d = box.bd = box.bh = 0; + box.h = box.d = 0; delete mitem.smash; mitem.type = 'box'; }, @@ -3263,7 +3619,8 @@ jsMath.Add(jsMath.mList.prototype.Atomiz raise: function (style,size,mitem) { mitem.nuc = jsMath.Box.Set(mitem.nuc,style,size); var y = mitem.raise; - mitem.nuc.html = jsMath.HTML.Place(mitem.nuc.html,0,y); + mitem.nuc.html = + jsMath.HTML.Place(mitem.nuc.html,0,y,mitem.nuc.mw,mitem.nuc.Mw,mitem.nuc.w); mitem.nuc.h += y; mitem.nuc.d -= y; mitem.type = 'ord'; mitem.atom = 1; }, @@ -3288,7 +3645,7 @@ jsMath.Add(jsMath.mList.prototype.Atomiz * Handle a Bin atom. (Rule 5) */ bin: function (style,size,mitem,prev) { - if (prev) { + if (prev && prev.type) { var type = prev.type; if (type == 'bin' || type == 'op' || type == 'rel' || type == 'open' || type == 'punct' || type == '' || @@ -3301,7 +3658,7 @@ jsMath.Add(jsMath.mList.prototype.Atomiz * Handle a Rel atom. (Rule 6) */ rel: function (style,size,mitem,prev) { - if (prev.type == 'bin') {prev.type = 'ord'} + if (prev.type && prev.type == 'bin') {prev.type = 'ord'} jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); }, @@ -3309,7 +3666,7 @@ jsMath.Add(jsMath.mList.prototype.Atomiz * Handle a Close atom. (Rule 6) */ close: function (style,size,mitem,prev) { - if (prev.type == 'bin') {prev.type = 'ord'} + if (prev.type && prev.type == 'bin') {prev.type = 'ord'} jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); }, @@ -3317,7 +3674,7 @@ jsMath.Add(jsMath.mList.prototype.Atomiz * Handle a Punct atom. (Rule 6) */ punct: function (style,size,mitem,prev) { - if (prev.type == 'bin') {prev.type = 'ord'} + if (prev.type && prev.type == 'bin') {prev.type = 'ord'} jsMath.mList.prototype.Atomize.SupSub(style,size,mitem); }, @@ -3387,13 +3744,13 @@ jsMath.Add(jsMath.mList.prototype.Atomiz var p = t; if (style == 'D' || style == "D'") {p = TeX.x_height} var r = t + p/4; var surd = jsMath.Box.Delimiter(box.h+box.d+r+t,[0,2,0x70,3,0x70],style,1); - t = surd.h; // thickness of rule is height of surd character +// if (surd.h > 0) {t = surd.h} // thickness of rule is height of surd character if (surd.d > box.h+box.d+r) {r = (r+surd.d-box.h-box.d)/2} surd.y = box.h+r; var rule = jsMath.Box.Rule(box.w,t); rule.y = surd.y-t/2; rule.h += 3*t/2; box.x = -box.w; var Cr = jsMath.Typeset.UpStyle(jsMath.Typeset.UpStyle(style)); - var root = jsMath.Box.Set(mitem.root,Cr,size).Remeasured(); + var root = jsMath.Box.Set(mitem.root || null,Cr,size).Remeasured(); if (mitem.root) { root.y = .55*(box.h+box.d+3*t+r)-box.d; surd.x = Math.max(root.w-(11/18)*surd.w,0); @@ -3412,11 +3769,12 @@ jsMath.Add(jsMath.mList.prototype.Atomiz var TeX = jsMath.Typeset.TeX(style,size); var Cp = jsMath.Typeset.PrimeStyle(style); var box = jsMath.Box.Set(mitem.nuc,Cp,size); - var u = box.w; var s; var Font; + var u = box.w; var s; var Font; var ic = 0; if (mitem.nuc.type == 'TeX') { Font = jsMath.TeX[mitem.nuc.font]; if (Font[mitem.nuc.c].krn && Font.skewchar) {s = Font[mitem.nuc.c].krn[Font.skewchar]} + ic = Font[mitem.nuc.c].ic; if (ic == null) {ic = 0} } if (s == null) {s = 0} @@ -3435,7 +3793,9 @@ jsMath.Add(jsMath.mList.prototype.Atomiz } var acc = jsMath.Box.TeX(c,font,style,size); acc.y = box.h - delta; acc.x = -box.w + s + (u-acc.w)/2; - if (Font[c].ic) {acc.x -= Font[c].ic * TeX.scale} + if (jsMath.Browser.msieAccentBug) + {acc.html += jsMath.HTML.Spacer(.1); acc.w += .1; acc.Mw += .1} + if (Font[c].ic || ic) {acc.x += (ic - (Font[c].ic||0)) * TeX.scale} mitem.nuc = jsMath.Box.SetList([box,acc],style,size); if (mitem.nuc.w != box.w) { @@ -3457,17 +3817,18 @@ jsMath.Add(jsMath.mList.prototype.Atomiz if (mitem.nuc.type == 'TeX') { var C = jsMath.TeX[mitem.nuc.font][mitem.nuc.c]; if (isD && C.n) {mitem.nuc.c = C.n; C = jsMath.TeX[mitem.nuc.font][C.n]} - box = jsMath.Box.Set(mitem.nuc,style,size); + box = mitem.nuc = jsMath.Box.Set(mitem.nuc,style,size); if (C.ic) { mitem.delta = C.ic * TeX.scale; - if (mitem.limits || !mitem.sub || jsMath.Browser.msieIntegralBug) - {box = jsMath.Box.SetList([box,jsMath.mItem.Space(mitem.delta)],style,size)} + if (mitem.limits || !mitem.sub || jsMath.Browser.msieIntegralBug) { + box = mitem.nuc = jsMath.Box.SetList([box,jsMath.mItem.Space(mitem.delta)],style,size); + } } box.y = -((box.h+box.d)/2 - box.d - TeX.axis_height); if (Math.abs(box.y) < .0001) {box.y = 0} } - - if (!box) {box = jsMath.Box.Set(mitem.nuc,style,size).Remeasured()} + + if (!box) {box = mitem.nuc = jsMath.Box.Set(mitem.nuc,style,size).Remeasured()} if (mitem.limits) { var W = box.w; var x = box.w; var mlist = [box]; var dh = 0; var dd = 0; @@ -3537,7 +3898,7 @@ jsMath.Add(jsMath.mList.prototype.Atomiz var num = jsMath.Box.Set(mitem.num,Cn,size).Remeasured(); var den = jsMath.Box.Set(mitem.den,Cd,size).Remeasured(); - var u; var v; var w; + var u; var v; var w; var p; var r; var H = (isD)? TeX.delim1 : TeX.delim2; var mlist = [jsMath.Box.Delimiter(H,mitem.left,style)] var right = jsMath.Box.Delimiter(H,mitem.right,style); @@ -3556,13 +3917,13 @@ jsMath.Add(jsMath.mList.prototype.Atomiz v = TeX.denom2; } if (t == 0) {// atop - var p = (isD)? 7*TeX.default_rule_thickness: 3*TeX.default_rule_thickness; - var r = (u - num.d) - (den.h - v); + p = (isD)? 7*TeX.default_rule_thickness: 3*TeX.default_rule_thickness; + r = (u - num.d) - (den.h - v); if (r < p) {u += (p-r)/2; v += (p-r)/2} } else {// over - var p = (isD)? 3*t: t; var a = TeX.axis_height; - var r = (u-num.d)-(a+t/2); if (r < p) {u += p-r} - r = (a-t/2)-(den.h-v); if (r < p) {v += p-r} + p = (isD)? 3*t: t; var a = TeX.axis_height; + r = (u-num.d)-(a+t/2); if (r < p) {u += p-r} + r = (a-t/2)-(den.h-v); if (r < p) {v += p-r} var rule = jsMath.Box.Rule(w,t); rule.x = -w; rule.y = a - t/2; mlist[mlist.length] = rule; } @@ -3801,7 +4162,8 @@ jsMath.Package(jsMath.Typeset,{ */ Typeset: function (style,size) { this.style = style; this.size = size; var unset = -10000 - this.w = 0; this.h = unset; this.d = unset; + this.w = 0; this.mw = 0; this.Mw = 0; + this.h = unset; this.d = unset; this.bh = this.h; this.bd = this.d; this.tbuf = ''; this.tx = 0; this.tclass = ''; this.cbuf = ''; this.hbuf = ''; this.hx = 0; @@ -3844,8 +4206,12 @@ jsMath.Package(jsMath.Typeset,{ default: // atom if (!mitem.atom && mitem.type != 'box') break; mitem.nuc.x += this.dx + this.GetSeparation(prev,mitem,this.style); - if (mitem.nuc.y || mitem.nuc.x) mitem.nuc.Styled(); + if (mitem.nuc.x || mitem.nuc.y) mitem.nuc.Styled(); this.dx = 0; this.x = this.x + this.w; + if (this.x + mitem.nuc.x + mitem.nuc.mw < this.mw) + {this.mw = this.x + mitem.nuc.x + mitem.nuc.mw} + if (this.w + mitem.nuc.x + mitem.nuc.Mw > this.Mw) + {this.Mw = this.w + mitem.nuc.x + mitem.nuc.Mw} this.w += mitem.nuc.w + mitem.nuc.x; if (mitem.nuc.format == 'text') { if (this.tclass != mitem.nuc.tclass && this.tclass != '') this.FlushText(); @@ -3862,14 +4228,19 @@ jsMath.Package(jsMath.Typeset,{ break; } } - + this.FlushClassed(); // make sure scaling is included - if (this.dx) {this.hbuf += jsMath.HTML.Spacer(this.dx); this.w += this.dx} - if (this.hbuf == '') {return jsMath.Box.Null} + if (this.dx) { + this.hbuf += jsMath.HTML.Spacer(this.dx); this.w += this.dx; + if (this.w > this.Mw) {this.Mw = this.w} + if (this.w < this.mw) {this.mw = this.w} + } + if (this.hbuf == '') {return jsMath.Box.Null()} if (this.h == unset) {this.h = 0} if (this.d == unset) {this.d = 0} var box = new jsMath.Box('html',this.hbuf,this.w,this.h,this.d); box.bh = this.bh; box.bd = this.bd; + box.mw = this.mw; box.Mw = this.Mw; return box; }, @@ -3916,17 +4287,26 @@ jsMath.Package(jsMath.Typeset,{ * also doesn't combine vertical and horizontal spacing well. * Here, the horizontal and vertical spacing are done separately. */ + PlaceSeparateSkips: function (item) { if (item.y) { - item.html = '' + item.html + '' + var rw = item.Mw - item.w; var lw = item.mw; + var W = item.Mw - item.mw; + item.html = + jsMath.HTML.Spacer(lw-rw) + + '' + + jsMath.HTML.Spacer(-lw) + + item.html + + jsMath.HTML.Spacer(rw) + + '' } if (item.x) {item.html = jsMath.HTML.Spacer(item.x) + item.html} item.h += item.y; item.d -= item.y; item.x = 0; item.y = 0; } - + }); @@ -3960,7 +4340,7 @@ jsMath.Package(jsMath.Parser,{ letter: /[a-z]/i, number: /[0-9]/, // pattern for macros to ^ and _ that should be read with arguments - scriptargs: /^((math|text)..|mathcal)$/, + scriptargs: /^((math|text)..|mathcal|[hm]box)$/, // the \mathchar definitions (see Appendix B of the TeXbook). mathchar: { @@ -3998,7 +4378,8 @@ jsMath.Package(jsMath.Parser,{ "\n": 'Space', "'": 'Prime', '%': 'HandleComment', - '&': 'HandleEntry' + '&': 'HandleEntry', + '#': 'Hash' }, // the \mathchardef table (see Appendix B of the TeXbook). @@ -4146,6 +4527,8 @@ jsMath.Package(jsMath.Parser,{ le: [3,2,0x14], geq: [3,2,0x15], ge: [3,2,0x15], + lt: [3,1,0x3C], // extra since < and > are hard + gt: [3,1,0x3E], // to get in HTML succ: [3,2,0x1F], prec: [3,2,0x1E], approx: [3,2,0x19], @@ -4188,6 +4571,7 @@ jsMath.Package(jsMath.Parser,{ nwarrow: [3,2,0x2D], swarrow: [3,2,0x2E], + minuschar: [3,2,0x00], // for longmapsto hbarchar: [0,0,0x16], // for \hbar lhook: [3,1,0x2C], rhook: [3,1,0x2D], @@ -4210,6 +4594,8 @@ jsMath.Package(jsMath.Parser,{ ']': [0,0,0x5D,3,0x03], '<': [0,2,0x68,3,0x0A], '>': [0,2,0x69,3,0x0B], + '\\lt': [0,2,0x68,3,0x0A], // extra since < and > are + '\\gt': [0,2,0x69,3,0x0B], // hard to get in HTML '/': [0,0,0x2F,3,0x0E], '|': [0,2,0x6A,3,0x0C], '.': [0,0,0x00,0,0x00], @@ -4273,6 +4659,8 @@ jsMath.Package(jsMath.Parser,{ it: ['HandleFont',4], bf: ['HandleFont',6], + font: ['Extension','font'], + left: 'HandleLeft', right: 'HandleRight', @@ -4325,7 +4713,11 @@ jsMath.Package(jsMath.Parser,{ overbrace: ['Extension','leaders'], underbrace: ['Extension','leaders'], overrightarrow: ['Extension','leaders'], + underrightarrow: ['Extension','leaders'], overleftarrow: ['Extension','leaders'], + underleftarrow: ['Extension','leaders'], + overleftrightarrow: ['Extension','leaders'], + underleftrightarrow: ['Extension','leaders'], overset: ['Extension','underset-overset'], underset: ['Extension','underset-overset'], @@ -4362,7 +4754,7 @@ jsMath.Package(jsMath.Parser,{ Relbar: ['Macro','\\mathrel='], bowtie: ['Macro','\\mathrel\\triangleright\\joinrel\\mathrel\\triangleleft'], models: ['Macro','\\mathrel|\\joinrel='], - mapsto: ['Macro','\\mapstochar\\rightarrow'], + mapsto: ['Macro','\\mathrel{\\mapstochar\\rightarrow}'], rightleftharpoons: ['Macro','\\vcenter{\\mathrel{\\rlap{\\raise3mu{\\rightharpoonup}}}\\leftharpoondown}'], hookrightarrow: ['Macro','\\lhook\\joinrel\\rightarrow'], hookleftarrow: ['Macro','\\leftarrow\\joinrel\\rhook'], @@ -4370,7 +4762,7 @@ jsMath.Package(jsMath.Parser,{ longrightarrow: ['Macro','\\relbar\\joinrel\\rightarrow'], longleftarrow: ['Macro','\\leftarrow\\joinrel\\relbar'], Longleftarrow: ['Macro','\\Leftarrow\\joinrel\\Relbar'], - longmapsto: ['Macro','\\mapstochar\\char{cmsy10}{0}\\joinrel\\rightarrow'], + longmapsto: ['Macro','\\mathrel{\\mapstochar\\minuschar\\joinrel\\rightarrow}'], longleftrightarrow: ['Macro','\\leftarrow\\joinrel\\rightarrow'], Longleftrightarrow: ['Macro','\\Leftarrow\\joinrel\\Rightarrow'], iff: ['Macro','\\;\\Longleftrightarrow\\;'], @@ -4382,6 +4774,7 @@ jsMath.Package(jsMath.Parser,{ textrm: ['Macro','\\mathord{\\hbox{#1}}',1], textit: ['Macro','\\mathord{\\class{textit}{\\hbox{#1}}}',1], textbf: ['Macro','\\mathord{\\class{textbf}{\\hbox{#1}}}',1], + pmb: ['Macro','\\rlap{#1}\\kern1px{#1}',1], TeX: ['Macro','T\\kern-.1667em\\lower.5ex{E}\\kern-.125em X'], @@ -4465,9 +4858,15 @@ jsMath.Package(jsMath.Parser,{ matrix: 'Matrix', array: 'Matrix', // ### still need to do alignment options ### pmatrix: ['Matrix','(',')','c'], - cases: ['Matrix','\\{','.',['l','l']], + cases: ['Matrix','\\{','.',['l','l'],null,2], + eqalign: ['Matrix',null,null,['r','l'],[5/18],3,'D'], + displaylines: ['Matrix',null,null,['c'],null,3,'D'], cr: 'HandleRow', '\\': 'HandleRow', + newline: 'HandleRow', + noalign: 'HandleNoAlign', + eqalignno: ['Matrix',null,null,['r','l','r'],[5/8,3],3,'D'], + leqalignno: ['Matrix',null,null,['r','l','r'],[5/8,3],3,'D'], // LaTeX begin: 'Begin', @@ -4484,8 +4883,9 @@ jsMath.Package(jsMath.Parser,{ Huge: ['HandleSize',9], dots: ['Macro','\\ldots'], - newcommand: ['Extension','newcommand'], - def: ['Extension','newcommand'], + newcommand: ['Extension','newcommand'], + newenvironment: ['Extension','newcommand'], + def: ['Extension','newcommand'], // Extensions to TeX color: ['Extension','HTML'], @@ -4494,6 +4894,7 @@ jsMath.Package(jsMath.Parser,{ style: ['Extension','HTML'], cssId: ['Extension','HTML'], unicode: ['Extension','HTML'], + bbox: ['Extension','bbox'], require: 'Require', @@ -4505,15 +4906,23 @@ jsMath.Package(jsMath.Parser,{ * LaTeX environments */ environments: { - array: 'Array', - matrix: ['Array',null,null,'c'], - pmatrix: ['Array','(',')','c'], - bmatrix: ['Array','[',']','c'], - Bmatrix: ['Array','\\{','\\}','c'], - vmatrix: ['Array','\\vert','\\vert','c'], - Vmatrix: ['Array','\\Vert','\\Vert','c'], - cases: ['Array','\\{','.','ll'], - eqnarray: ['Array',null,null,'rcl',[5/18,5/18],'D'] + array: 'Array', + matrix: ['Array',null,null,'c'], + pmatrix: ['Array','(',')','c'], + bmatrix: ['Array','[',']','c'], + Bmatrix: ['Array','\\{','\\}','c'], + vmatrix: ['Array','\\vert','\\vert','c'], + Vmatrix: ['Array','\\Vert','\\Vert','c'], + cases: ['Array','\\{','.','ll',null,2], + eqnarray: ['Array',null,null,'rcl',[5/18,5/18],3,'D'], + + align: ['Extension','AMSmath'], + 'align*': ['Extension','AMSmath'], + multline: ['Extension','AMSmath'], + 'multline*': ['Extension','AMSmath'], + split: ['Extension','AMSmath'], + gather: ['Extension','AMSmath'], + 'gather*': ['Extension','AMSmath'] }, @@ -4581,8 +4990,7 @@ jsMath.Package(jsMath.Parser,{ var letter = /^([a-z]+|.) ?/i; var cmd = letter.exec(this.string.slice(this.i)); if (cmd) {this.i += cmd[1].length; return cmd[1]} - this.Error("Missing control sequnece name at end of string or argument"); - return null; + this.i++; return " "; }, /* @@ -4627,7 +5035,7 @@ jsMath.Package(jsMath.Parser,{ ProcessScriptArg: function (name) { var arg = this.GetArgument(name); if (this.error) {return null} if (arg.charAt(0) == this.cmd) { - csname = arg.substr(1); + var csname = arg.substr(1); if (csname == "frac") { arg += '{'+this.GetArgument(csname)+'}'; if (this.error) {return null} arg += '{'+this.GetArgument(csname)+'}'; if (this.error) {return null} @@ -4670,7 +5078,11 @@ jsMath.Package(jsMath.Parser,{ rest = this.string.slice(this.i); advance = 1; } - var match = rest.match(/^\s*([-+]?(\.\d+|\d+(\.\d*)?))(pt|em|ex|mu|px)/); + return this.ParseDimen(rest,name,advance,nomu); + }, + + ParseDimen: function (dimen,name,advance,nomu) { + var match = dimen.match(/^\s*([-+]?(\.\d+|\d+(\.\d*)?))(pt|em|ex|mu|px)/); if (!match) {this.Error("Missing dimension or its units for "+name); return null} if (advance) { this.i += match[0].length; @@ -4699,7 +5111,7 @@ jsMath.Package(jsMath.Parser,{ var c = this.GetNext(); if (c != '[') return ''; var start = ++this.i; var pcount = 0; while (this.i < this.string.length) { - var c = this.string.charAt(this.i++); + c = this.string.charAt(this.i++); if (c == '{') {pcount++} else if (c == '}') { if (pcount == 0) @@ -4803,7 +5215,7 @@ jsMath.Package(jsMath.Parser,{ */ RaiseLower: function (name) { var h = this.GetDimen(this.cmd+name,1); if (this.error) return; - var box = this.ProcessArg(this.cmd+name); if (this.error) return; + var box = this.ProcessScriptArg(this.cmd+name); if (this.error) return; if (name == 'lower') {h = -h} this.mlist.Add(new jsMath.mItem('raise',{nuc: box, raise: h})); }, @@ -4838,7 +5250,6 @@ jsMath.Package(jsMath.Parser,{ Extension: function (name,data) { jsMath.Translate.restart = 1; if (name != null) {delete jsMath.Parser.prototype[data[1]||'macros'][name]} - jsMath.Script.Start(); jsMath.Extension.Require(data[0],jsMath.Translate.asynchronous); throw "restart"; }, @@ -4858,8 +5269,8 @@ jsMath.Package(jsMath.Parser,{ Sqrt: function (name) { var n = this.GetBrackets(this.cmd+name); if (this.error) return; var arg = this.ProcessArg(this.cmd+name); if (this.error) return; - box = jsMath.mItem.Atom('radical',arg); - if (this.n != '') {box.root = this.Process(n); if (this.error) return} + var box = jsMath.mItem.Atom('radical',arg); + if (n != '') {box.root = this.Process(n); if (this.error) return} this.mlist.Add(box); }, @@ -4869,7 +5280,7 @@ jsMath.Package(jsMath.Parser,{ Root: function (name) { var n = this.ProcessUpto(this.cmd+name,'of'); if (this.error) return; var arg = this.ProcessArg(this.cmd+name); if (this.error) return; - box = jsMath.mItem.Atom('radical',arg); + var box = jsMath.mItem.Atom('radical',arg); box.root = n; this.mlist.Add(box); }, @@ -4915,15 +5326,15 @@ jsMath.Package(jsMath.Parser,{ Matrix: function (name,delim) { var data = this.mlist.data; var arg = this.GetArgument(this.cmd+name); if (this.error) return; - var parse = new jsMath.Parser(arg+'\\\\',null,data.size); - parse.matrix = name; parse.row = []; parse.table = []; + var parse = new jsMath.Parser(arg+this.cmd+'\\',null,data.size,delim[5] || 'T'); + parse.matrix = name; parse.row = []; parse.table = []; parse.rspacing = []; parse.Parse(); if (parse.error) {this.Error(parse); return} parse.HandleRow(name,1); // be sure the last row is recorded - var box = jsMath.Box.Layout(data.size,parse.table,delim[2]); + var box = jsMath.Box.Layout(data.size,parse.table,delim[2]||null,delim[3]||null,parse.rspacing,delim[4]||null); // Add parentheses, if needed if (delim[0] && delim[1]) { - var left = jsMath.Box.Delimiter(box.h+box.d,this.delimiter[delim[0]],'T'); - var right = jsMath.Box.Delimiter(box.h+box.d,this.delimiter[delim[1]],'T'); + var left = jsMath.Box.Delimiter(box.h+box.d-jsMath.hd/4,this.delimiter[delim[0]],'T'); + var right = jsMath.Box.Delimiter(box.h+box.d-jsMath.hd/4,this.delimiter[delim[1]],'T'); box = jsMath.Box.SetList([left,box,right],data.style,data.size); } this.mlist.Add(jsMath.mItem.Atom((delim[0]? 'inner': 'ord'),box)); @@ -4945,6 +5356,7 @@ jsMath.Package(jsMath.Parser,{ var data = this.mlist.data; this.mlist.Atomize(data.style,data.size); var box = this.mlist.Typeset(data.style,data.size); + box.entry = data.entry; delete data.entry; if (!box.entry) {box.entry = {}}; this.row[this.row.length] = box; this.mlist = new jsMath.mList(null,null,data.size,data.style); }, @@ -4953,15 +5365,31 @@ jsMath.Package(jsMath.Parser,{ * When we see a \cr or \\, try to add a row to the table */ HandleRow: function (name,last) { - if (!this.matrix) - {this.Error(this.cmd+name+" can only appear in a matrix or array"); return} + var dimen; + if (!this.matrix) {this.Error(this.cmd+name+" can only appear in a matrix or array"); return} + if (name == "\\") { + dimen = this.GetBrackets(this.cmd+name); if (this.error) return; + if (dimen) {dimen = this.ParseDimen(dimen,this.cmd+name,0,1)} + } this.HandleEntry(name); if (!last || this.row.length > 1 || this.row[0].format != 'null') {this.table[this.table.length] = this.row} + if (dimen) {this.rspacing[this.table.length] = dimen} this.row = []; }, /* + * Look for \vskip or \vspace in \noalign parameters + */ + HandleNoAlign: function (name) { + var arg = this.GetArgument(this.cmd+name); if (this.error) return; + var skip = arg.replace(/^.*(vskip|vspace)([^a-z])/i,'$2'); + if (skip.length == arg.length) return; + var d = this.ParseDimen(skip,this.cmd+RegExp.$1,0,1); if (this.error) return; + this.rspacing[this.table.length] = (this.rspacing[this.table.length] || 0) + d; + }, + + /* * LaTeX array environment */ Array: function (name,delim) { @@ -4972,17 +5400,17 @@ jsMath.Package(jsMath.Parser,{ } columns = columns.replace(/[^clr]/g,''); columns = columns.split(''); - var data = this.mlist.data; var style = delim[4] || 'T'; + var data = this.mlist.data; var style = delim[5] || 'T'; var arg = this.GetEnd(name); if (this.error) return; var parse = new jsMath.Parser(arg+this.cmd+'\\',null,data.size,style); - parse.matrix = name; parse.row = []; parse.table = []; + parse.matrix = name; parse.row = []; parse.table = []; parse.rspacing = []; parse.Parse(); if (parse.error) {this.Error(parse); return} parse.HandleRow(name,1); // be sure the last row is recorded - var box = jsMath.Box.Layout(data.size,parse.table,columns,cspacing); + var box = jsMath.Box.Layout(data.size,parse.table,columns,cspacing,parse.rspacing,delim[4],delim[6],delim[7]); // Add parentheses, if needed if (delim[0] && delim[1]) { - var left = jsMath.Box.Delimiter(box.h+box.d,this.delimiter[delim[0]],'T'); - var right = jsMath.Box.Delimiter(box.h+box.d,this.delimiter[delim[1]],'T'); + var left = jsMath.Box.Delimiter(box.h+box.d-jsMath.hd/4,this.delimiter[delim[0]],'T'); + var right = jsMath.Box.Delimiter(box.h+box.d-jsMath.hd/4,this.delimiter[delim[1]],'T'); box = jsMath.Box.SetList([left,box,right],data.style,data.size); } this.mlist.Add(jsMath.mItem.Atom((delim[0]? 'inner': 'ord'),box)); @@ -5058,7 +5486,7 @@ jsMath.Package(jsMath.Parser,{ Strut: function () { var size = this.mlist.data.size; var box = jsMath.Box.Text('','normal','T',size).Styled(); - box.bh = box.bd = 0; box.h = .8; box.d = .3; box.w = 0; + box.bh = box.bd = 0; box.h = .8; box.d = .3; box.w = box.Mw = 0; this.mlist.Add(jsMath.mItem.Typeset(box)); }, @@ -5144,7 +5572,7 @@ jsMath.Package(jsMath.Parser,{ c = string.charAt(i++); if (c == "#") {text += c} else { if (!c.match(/[1-9]/) || c > args.length) - {this.Error("Illegal macro parameter reference"); return} + {this.Error("Illegal macro parameter reference"); return null} newstring = this.AddArgs(this.AddArgs(newstring,text),args[c-1]); text = ''; } @@ -5170,6 +5598,13 @@ jsMath.Package(jsMath.Parser,{ }, /* + * Error for # (must use \#) + */ + Hash: function (name) { + this.Error("You can't use 'macro parameter character #' in math mode"); + }, + + /* * Insert space for ~ */ Tilde: function (name) { @@ -5190,7 +5625,7 @@ jsMath.Package(jsMath.Parser,{ */ HandleAtom: function (name,data) { var arg = this.ProcessArg(this.cmd+name); if (this.error) return; - this.mlist.Add(jsMath.mItem.Atom(data,arg)); + this.mlist.Add(jsMath.mItem.Atom(data[0],arg)); }, @@ -5336,7 +5771,7 @@ jsMath.Package(jsMath.Parser,{ this.mlist.data.overF.right = null; } if (name.match(/^above/)) { - this.mlist.data.overF.thickness = this.GetDimen(this.cmd.name,1); + this.mlist.data.overF.thickness = this.GetDimen(this.cmd+name,1); if (this.error) return; } else { this.mlist.data.overF.thickness = null; @@ -5348,6 +5783,7 @@ jsMath.Package(jsMath.Parser,{ */ HandleSuperscript: function () { var base = this.mlist.Last(); + if (this.mlist.data.overI == this.mlist.Length()) {base = null} if (base == null || (!base.atom && base.type != 'box' && base.type != 'frac')) {base = this.mlist.Add(jsMath.mItem.Atom('ord',{type:null}))} if (base.sup) { @@ -5362,6 +5798,7 @@ jsMath.Package(jsMath.Parser,{ */ HandleSubscript: function () { var base = this.mlist.Last(); + if (this.mlist.data.overI == this.mlist.Length()) {base = null} if (base == null || (!base.atom && base.type != 'box' && base.type != 'frac')) {base = this.mlist.Add(jsMath.mItem.Atom('ord',{type:null}))} if (base.sub) {this.Error("Double subscripts: use braces to clarify"); return} @@ -5422,11 +5859,17 @@ jsMath.Package(jsMath.Parser,{ if (jsMath.Browser.allowAbsolute) { var y = 0; if (box.bh > jsMath.h+.001) {y = jsMath.h - box.bh} + if (jsMath.Browser.msieTeXfontBaselineBug && + jsMath.Controls.cookie.font == 'tex') {y -= jsMath.d} html = jsMath.HTML.Absolute(html,box.w,jsMath.h,0,y,jsMath.h); - } else if (!jsMath.Browser.valignBug) { + } else if (jsMath.Browser.valignBug) { + // remove line height + html = '' + + html + ''; + } else { // remove line height and try to hide the depth var dy = jsMath.HTML.Em(Math.max(0,box.bd-jsMath.hd)/3); - html = '' + html + ''; } @@ -5574,26 +6017,25 @@ jsMath.Translate = { element: [], // the list of math elements on the page cancel: 0, // set to 1 to cancel asynchronous processing - + /* - * Typeset a string in \textstyle and return the HTML for it + * Parse a TeX string in Text or Display mode and return + * the HTML for it (taking it from the cache, if available) */ - TextMode: function (s) { - var parse = jsMath.Parse(s,null,null,'T'); - parse.Atomize(); - var html = parse.Typeset(); - return html; + Parse: function (style,s,noCache) { + var cache = jsMath.Global.cache[style]; + if (!cache[jsMath.em]) {cache[jsMath.em] = {}} + var HTML = cache[jsMath.em][s]; + if (!HTML || noCache) { + var parse = jsMath.Parse(s,null,null,style); + parse.Atomize(); HTML = parse.Typeset(); + if (!noCache) {cache[jsMath.em][s] = HTML} + } + return HTML; }, - /* - * Typeset a string in \displaystyle and return the HTML for it - */ - DisplayMode: function (s) { - var parse = jsMath.Parse(s,null,null,'D'); - parse.Atomize(); - var html = parse.Typeset(); - return html; - }, + TextMode: function (s,noCache) {this.Parse('T',s,noCache)}, + DisplayMode: function (s,noCache) {this.Parse('D',s,noCache)}, /* * Return the text of a given DOM element @@ -5624,9 +6066,9 @@ jsMath.Translate = { */ ResetHidden: function (element) { element.innerHTML = - '' + '' + jsMath.Browser.operaHiddenFix; // needed by Opera in tables - element.className=''; + element.className = ''; jsMath.hidden = element.firstChild; if (!jsMath.BBoxFor("x").w) {jsMath.hidden = jsMath.hiddenTop} jsMath.ReInit(); @@ -5636,10 +6078,12 @@ jsMath.Translate = { /* * Typeset the contents of an element in \textstyle */ - ConvertText: function (element) { + ConvertText: function (element,noCache) { var text = this.GetElementText(element); this.ResetHidden(element); - text = this.TextMode(text); + if (text.match(/^\s*\\nocache([^a-zA-Z])/)) + {noCache = true; text = text.replace(/\s*\\nocache/,'')} + text = this.Parse('T',text,noCache); element.className = 'typeset'; element.innerHTML = text; }, @@ -5647,10 +6091,12 @@ jsMath.Translate = { /* * Typeset the contents of an element in \displaystyle */ - ConvertDisplay: function (element) { + ConvertDisplay: function (element,noCache) { var text = this.GetElementText(element); this.ResetHidden(element); - text = this.DisplayMode(text); + if (text.match(/^\s*\\nocache([^a-zA-Z])/)) + {noCache = true; text = text.replace(/\s*\\nocache/,'')} + text = this.Parse('D',text,noCache); element.className = 'typeset'; element.innerHTML = text; }, @@ -5660,13 +6106,15 @@ jsMath.Translate = { */ ProcessElement: function (element) { this.restart = 0; + if (!element.className.match(/(^| )math( |$)/)) return; // don't reprocess elements + var noCache = (element.className.toLowerCase().match(/(^| )nocache( |$)/) != null); try { if (element.tagName.toLowerCase() == 'div') { - this.ConvertDisplay(element); + this.ConvertDisplay(element,noCache); element.onclick = jsMath.Click.CheckClick; element.ondblclick = jsMath.Click.CheckDblClick; } else if (element.tagName.toLowerCase() == 'span') { - this.ConvertText(element); + this.ConvertText(element,noCache); element.onclick = jsMath.Click.CheckClick; element.ondblclick = jsMath.Click.CheckDblClick; } @@ -5677,6 +6125,8 @@ jsMath.Translate = { tex = tex.replace(//g,'>'); element.innerHTML = tex; + element.className = 'math'; + if (noCache) {element.className += ' nocache'} } jsMath.hidden = jsMath.hiddenTop; } @@ -5697,7 +6147,9 @@ jsMath.Translate = { jsMath.Script.blocking = 0; jsMath.Script.Process(); } else { + var savedQueue = jsMath.Script.SaveQueue(); this.ProcessElement(this.element[k]); + jsMath.Script.RestoreQueue(savedQueue); if (this.restart) { jsMath.Script.Push(this,'ProcessElements',k); jsMath.Script.blocking = 0; @@ -5716,8 +6168,8 @@ jsMath.Translate = { Asynchronous: function (obj) { if (!jsMath.initialized) {jsMath.Init()} this.element = this.GetMathElements(obj); - this.cancel = 0; this.asynchronous = 1; jsMath.Script.blocking = 1; + this.cancel = 0; this.asynchronous = 1; jsMath.Message.Set('Processing Math: 0%',1); setTimeout('jsMath.Translate.ProcessElements(0)',jsMath.Browser.delay); }, @@ -5749,21 +6201,21 @@ jsMath.Translate = { * put them in a list sorted from top to bottom of the page */ GetMathElements: function (obj) { - var element = []; + var element = []; var k; if (!obj) {obj = jsMath.document} if (typeof(obj) == 'string') {obj = jsMath.document.getElementById(obj)} if (!obj.getElementsByTagName) return null; var math = obj.getElementsByTagName('div'); - for (var k = 0; k < math.length; k++) { - if (math[k].className == 'math') { + for (k = 0; k < math.length; k++) { + if (math[k].className && math[k].className.match(/(^| )math( |$)/)) { if (jsMath.Browser.renameOK && obj.getElementsByName) {math[k].setAttribute('name','_jsMath_')} else {element[element.length] = math[k]} } } math = obj.getElementsByTagName('span'); - for (var k = 0; k < math.length; k++) { - if (math[k].className == 'math') { + for (k = 0; k < math.length; k++) { + if (math[k].className && math[k].className.match(/(^| )math( |$)/)) { if (jsMath.Browser.renameOK && obj.getElementsByName) {math[k].setAttribute('name','_jsMath_')} else {element[element.length] = math[k]} @@ -5790,7 +6242,7 @@ jsMath.Translate = { } } jsMath.hidden = jsMath.hiddenTop; - this.element = []; + this.element = []; this.restart = null; if (!noMessage) { jsMath.Message.Set('Processing Math: Done'); jsMath.Message.Clear(); @@ -5842,19 +6294,26 @@ jsMath.Synchronize = jsMath.Script.Synch /***************************************************************************/ + /* * Initialize things */ -if (window.parent != window) { - window.parent.jsMath = jsMath; - jsMath.document = window.parent.document; - jsMath.window = window.parent; -} +try { + if (window.parent != window && window.jsMathAutoload) { + window.parent.jsMath = jsMath; + jsMath.document = window.parent.document; + jsMath.window = window.parent; + } +} catch (err) {} + +jsMath.Global.Register(); jsMath.Loaded(); jsMath.Controls.GetCookie(); jsMath.Setup.Source(); +jsMath.Global.Init(); jsMath.Script.Init(); jsMath.Setup.Fonts(); if (jsMath.document.body) {jsMath.Setup.Body()} +jsMath.Setup.User("onload"); }}