/common/static/js/vendor/mathjax-MathJax-c9db6ac/unpacked/MathJax.js
JavaScript | 2436 lines | 1824 code | 157 blank | 455 comment | 629 complexity | 2f7d50cbe1cd26a37de9d639d0db031f MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0, LGPL-2.1
Large files files are truncated, but you can click here to view the full file
- /*************************************************************
- *
- * MathJax.js
- *
- * The main support code for the MathJax Hub, including the
- * Ajax, Callback, Messaging, and Object-Oriented Programming
- * libraries, as well as the base Jax classes, and startup
- * processing code.
- *
- * ---------------------------------------------------------------------
- *
- * Copyright (c) 2009-2012 Design Science, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- if (document.getElementById && document.childNodes && document.createElement) {
- if (!window.MathJax) {window.MathJax= {}}
- if (!MathJax.Hub) { // skip if already loaded
-
- MathJax.version = "2.0";
- MathJax.fileversion = "2.0";
- /**********************************************************/
- (function (BASENAME) {
- var BASE = window[BASENAME];
- if (!BASE) {BASE = window[BASENAME] = {}}
- var PROTO = []; // a static object used to indicate when a prototype is being created
- var OBJECT = function (def) {
- var obj = def.constructor; if (!obj) {obj = new Function("")}
- for (var id in def) {if (id !== 'constructor' && def.hasOwnProperty(id)) {obj[id] = def[id]}}
- return obj;
- };
- var CONSTRUCTOR = function () {
- return new Function ("return arguments.callee.Init.call(this,arguments)");
- };
- //
- // Test for Safari 2.x bug (can't replace prototype for result of new Function()).
- // (We don't use this version for everyone since it is a closure and we don't need that).
- //
- var BUGTEST = CONSTRUCTOR(); BUGTEST.prototype = {bug_test: 1};
- if (!BUGTEST.prototype.bug_test) {
- CONSTRUCTOR = function () {
- return function () {return arguments.callee.Init.call(this,arguments)};
- };
- };
- BASE.Object = OBJECT({
- constructor: CONSTRUCTOR(),
-
- Subclass: function (def,classdef) {
- var obj = CONSTRUCTOR();
- obj.SUPER = this; obj.Init = this.Init;
- obj.Subclass = this.Subclass; obj.Augment = this.Augment;
- obj.protoFunction = this.protoFunction;
- obj.can = this.can; obj.has = this.has; obj.isa = this.isa;
- obj.prototype = new this(PROTO);
- obj.prototype.constructor = obj; // the real constructor
- obj.Augment(def,classdef);
- return obj;
- },
-
- Init: function (args) {
- var obj = this;
- if (args.length === 1 && args[0] === PROTO) {return obj}
- if (!(obj instanceof args.callee)) {obj = new args.callee(PROTO)}
- return obj.Init.apply(obj,args) || obj;
- },
-
- Augment: function (def,classdef) {
- var id;
- if (def != null) {
- for (id in def) {if (def.hasOwnProperty(id)) {this.protoFunction(id,def[id])}}
- // MSIE doesn't list toString even if it is not native so handle it separately
- if (def.toString !== this.prototype.toString && def.toString !== {}.toString)
- {this.protoFunction('toString',def.toString)}
- }
- if (classdef != null) {
- for (id in classdef) {if (classdef.hasOwnProperty(id)) {this[id] = classdef[id]}}
- }
- return this;
- },
-
- protoFunction: function (id,def) {
- this.prototype[id] = def;
- if (typeof def === "function") {def.SUPER = this.SUPER.prototype}
- },
-
- prototype: {
- Init: function () {},
- SUPER: function (fn) {return fn.callee.SUPER},
- can: function (method) {return typeof(this[method]) === "function"},
- has: function (property) {return typeof(this[property]) !== "undefined"},
- isa: function (obj) {return (obj instanceof Object) && (this instanceof obj)}
- },
-
- can: function (method) {return this.prototype.can.call(this,method)},
- has: function (property) {return this.prototype.has.call(this,property)},
- isa: function (obj) {
- var constructor = this;
- while (constructor) {
- if (constructor === obj) {return true} else {constructor = constructor.SUPER}
- }
- return false;
- },
- SimpleSUPER: OBJECT({
- constructor: function (def) {return this.SimpleSUPER.define(def)},
- define: function (src) {
- var dst = {};
- if (src != null) {
- for (var id in src) {if (src.hasOwnProperty(id)) {dst[id] = this.wrap(id,src[id])}}
- // MSIE doesn't list toString even if it is not native so handle it separately
- if (src.toString !== this.prototype.toString && src.toString !== {}.toString)
- {dst.toString = this.wrap('toString',src.toString)}
- }
- return dst;
- },
- wrap: function (id,f) {
- if (typeof(f) === 'function' && f.toString().match(/\.\s*SUPER\s*\(/)) {
- var fn = new Function(this.wrapper);
- fn.label = id; fn.original = f; f = fn;
- fn.toString = this.stringify;
- }
- return f;
- },
- wrapper: function () {
- var fn = arguments.callee;
- this.SUPER = fn.SUPER[fn.label];
- try {var result = fn.original.apply(this,arguments)}
- catch (err) {delete this.SUPER; throw err}
- delete this.SUPER;
- return result;
- }.toString().replace(/^\s*function\s*\(\)\s*\{\s*/i,"").replace(/\s*\}\s*$/i,""),
- toString: function () {
- return this.original.toString.apply(this.original,arguments);
- }
- })
- });
- })("MathJax");
- /**********************************************************/
- /*
- * Create a callback function from various forms of data:
- *
- * MathJax.Callback(fn) -- callback to a function
- *
- * MathJax.Callback([fn]) -- callback to function
- * MathJax.Callback([fn,data...])
- * -- callback to function with given data as arguments
- * MathJax.Callback([object,fn])
- * -- call fn with object as "this"
- * MathJax.Callback([object,fn,data...])
- * -- call fn with object as "this" and data as arguments
- * MathJax.Callback(["method",object])
- * -- call method of object wth object as "this"
- * MathJax.Callback(["method",object,data...])
- * -- as above, but with data as arguments to method
- *
- * MathJax.Callback({hook: fn, data: [...], object: this})
- * -- give function, data, and object to act as "this" explicitly
- *
- * MathJax.Callback("code") -- callback that compiles and executes a string
- *
- * MathJax.Callback([...],i)
- * -- use slice of array starting at i and interpret
- * result as above. (Used for passing "arguments" array
- * and trimming initial arguments, if any.)
- */
- /*
- * MathJax.Callback.After([...],cb1,cb2,...)
- * -- make a callback that isn't called until all the other
- * ones are called first. I.e., wait for a union of
- * callbacks to occur before making the given callback.
- */
- /*
- * MathJax.Callback.Queue([callback,...])
- * -- make a synchronized queue of commands that process
- * sequentially, waiting for those that return uncalled
- * callbacks.
- */
- /*
- * MathJax.Callback.Signal(name)
- * -- finds or creates a names signal, to which listeners
- * can be attached and are signaled by messages posted
- * to the signal. Responses can be asynchronous.
- */
- (function (BASENAME) {
- var BASE = window[BASENAME];
- if (!BASE) {BASE = window[BASENAME] = {}}
- //
- // Create a callback from an associative array
- //
- var CALLBACK = function (data) {
- var cb = new Function("return arguments.callee.execute.apply(arguments.callee,arguments)");
- for (var id in CALLBACK.prototype) {
- if (CALLBACK.prototype.hasOwnProperty(id)) {
- if (typeof(data[id]) !== 'undefined') {cb[id] = data[id]}
- else {cb[id] = CALLBACK.prototype[id]}
- }
- }
- cb.toString = CALLBACK.prototype.toString;
- return cb;
- };
- CALLBACK.prototype = {
- isCallback: true,
- hook: function () {},
- data: [],
- object: window,
- execute: function () {
- if (!this.called || this.autoReset) {
- this.called = !this.autoReset;
- return this.hook.apply(this.object,this.data.concat([].slice.call(arguments,0)));
- }
- },
- reset: function () {delete this.called},
- toString: function () {return this.hook.toString.apply(this.hook,arguments)}
- };
- var ISCALLBACK = function (f) {
- return (typeof(f) === "function" && f.isCallback);
- }
- //
- // Evaluate a string in global context
- //
- var EVAL = function (code) {return eval.call(window,code)}
- EVAL("var __TeSt_VaR__ = 1"); // check if it works in global context
- if (window.__TeSt_VaR__) {
- try { delete window.__TeSt_VaR__; } // NOTE IE9 throws when in IE7 mode
- catch (error) { window.__TeSt_VaR__ = null; }
- } else {
- if (window.execScript) {
- // IE
- EVAL = function (code) {
- BASE.__code = code;
- code = "try {"+BASENAME+".__result = eval("+BASENAME+".__code)} catch(err) {"+BASENAME+".__result = err}";
- window.execScript(code);
- var result = BASE.__result; delete BASE.__result; delete BASE.__code;
- if (result instanceof Error) {throw result}
- return result;
- }
- } else {
- // Safari2
- EVAL = function (code) {
- BASE.__code = code;
- code = "try {"+BASENAME+".__result = eval("+BASENAME+".__code)} catch(err) {"+BASENAME+".__result = err}";
- var head = (document.getElementsByTagName("head"))[0]; if (!head) {head = document.body}
- var script = document.createElement("script");
- script.appendChild(document.createTextNode(code));
- head.appendChild(script); head.removeChild(script);
- var result = BASE.__result; delete BASE.__result; delete BASE.__code;
- if (result instanceof Error) {throw result}
- return result;
- }
- }
- }
- //
- // Create a callback from various types of data
- //
- var USING = function (args,i) {
- if (arguments.length > 1) {
- if (arguments.length === 2 && !(typeof arguments[0] === 'function') &&
- arguments[0] instanceof Object && typeof arguments[1] === 'number')
- {args = [].slice.call(args,i)}
- else {args = [].slice.call(arguments,0)}
- }
- if (args instanceof Array && args.length === 1) {args = args[0]}
- if (typeof args === 'function') {
- if (args.execute === CALLBACK.prototype.execute) {return args}
- return CALLBACK({hook: args});
- } else if (args instanceof Array) {
- if (typeof(args[0]) === 'string' && args[1] instanceof Object &&
- typeof args[1][args[0]] === 'function') {
- return CALLBACK({hook: args[1][args[0]], object: args[1], data: args.slice(2)});
- } else if (typeof args[0] === 'function') {
- return CALLBACK({hook: args[0], data: args.slice(1)});
- } else if (typeof args[1] === 'function') {
- return CALLBACK({hook: args[1], object: args[0], data: args.slice(2)});
- }
- } else if (typeof(args) === 'string') {
- return CALLBACK({hook: EVAL, data: [args]});
- } else if (args instanceof Object) {
- return CALLBACK(args);
- } else if (typeof(args) === 'undefined') {
- return CALLBACK({});
- }
- throw Error("Can't make callback from given data");
- };
-
- //
- // Wait for a given time to elapse and then perform the callback
- //
- var DELAY = function (time,callback) {
- callback = USING(callback);
- callback.timeout = setTimeout(callback,time);
- return callback;
- };
- //
- // Callback used by AFTER, QUEUE, and SIGNAL to check if calls have completed
- //
- var WAITFOR = function (callback,signal) {
- callback = USING(callback);
- if (!callback.called) {WAITSIGNAL(callback,signal); signal.pending++}
- };
- var WAITEXECUTE = function () {
- var signals = this.signal; delete this.signal;
- this.execute = this.oldExecute; delete this.oldExecute;
- var result = this.execute.apply(this,arguments);
- if (ISCALLBACK(result) && !result.called) {WAITSIGNAL(result,signals)} else {
- for (var i = 0, m = signals.length; i < m; i++) {
- signals[i].pending--;
- if (signals[i].pending <= 0) {signals[i].call()}
- }
- }
- };
- var WAITSIGNAL = function (callback,signals) {
- if (!(signals instanceof Array)) {signals = [signals]}
- if (!callback.signal) {
- callback.oldExecute = callback.execute;
- callback.execute = WAITEXECUTE;
- callback.signal = signals;
- } else if (signals.length === 1) {callback.signal.push(signals[0])}
- else {callback.signal = callback.signal.concat(signals)}
- };
- //
- // Create a callback that is called when a collection of other callbacks have
- // all been executed. If the callback gets called immediately (i.e., the
- // others are all already called), check if it returns another callback
- // and return that instead.
- //
- var AFTER = function (callback) {
- callback = USING(callback);
- callback.pending = 0;
- for (var i = 1, m = arguments.length; i < m; i++)
- {if (arguments[i]) {WAITFOR(arguments[i],callback)}}
- if (callback.pending === 0) {
- var result = callback();
- if (ISCALLBACK(result)) {callback = result}
- }
- return callback;
- };
- //
- // An array of prioritized hooks that are executed sequentially
- // with a given set of data.
- //
- var HOOKS = MathJax.Object.Subclass({
- //
- // Initialize the array and the auto-reset status
- //
- Init: function (reset) {
- this.hooks = [];
- this.reset = reset;
- },
- //
- // Add a callback to the list, in priority order (default priority is 10)
- //
- Add: function (hook,priority) {
- if (priority == null) {priority = 10}
- if (!ISCALLBACK(hook)) {hook = USING(hook)}
- hook.priority = priority;
- var i = this.hooks.length;
- while (i > 0 && priority < this.hooks[i-1].priority) {i--}
- this.hooks.splice(i,0,hook);
- return hook;
- },
- Remove: function (hook) {
- for (var i = 0, m = this.hooks.length; i < m; i++) {
- if (this.hooks[i] === hook) {this.hooks.splice(i,1); return}
- }
- },
- //
- // Execute the list of callbacks, resetting them if requested.
- // If any return callbacks, return a callback that will be
- // executed when they all have completed.
- //
- Execute: function () {
- var callbacks = [{}];
- for (var i = 0, m = this.hooks.length; i < m; i++) {
- if (this.reset) {this.hooks[i].reset()}
- var result = this.hooks[i].apply(window,arguments);
- if (ISCALLBACK(result) && !result.called) {callbacks.push(result)}
- }
- if (callbacks.length === 1) {return null}
- if (callbacks.length === 2) {return callbacks[1]}
- return AFTER.apply({},callbacks);
- }
- });
-
- //
- // Run an array of callbacks passing them the given data.
- // (Legacy function, since this has been replaced by the HOOKS object).
- //
- var EXECUTEHOOKS = function (hooks,data,reset) {
- if (!hooks) {return null}
- if (!(hooks instanceof Array)) {hooks = [hooks]}
- if (!(data instanceof Array)) {data = (data == null ? [] : [data])}
- var handler = HOOKS(reset);
- for (var i = 0, m = hooks.length; i < m; i++) {handler.Add(hooks[i])}
- return handler.Execute.apply(handler,data);
- };
-
- //
- // Command queue that performs commands in order, waiting when
- // necessary for commands to complete asynchronousely
- //
- var QUEUE = BASE.Object.Subclass({
- //
- // Create the queue and push any commands that are specified
- //
- Init: function () {
- this.pending = 0; this.running = 0;
- this.queue = [];
- this.Push.apply(this,arguments);
- },
- //
- // Add commands to the queue and run them. Adding a callback object
- // (rather than a callback specification) queues a wait for that callback.
- // Return the final callback for synchronization purposes.
- //
- Push: function () {
- var callback;
- for (var i = 0, m = arguments.length; i < m; i++) {
- callback = USING(arguments[i]);
- if (callback === arguments[i] && !callback.called)
- {callback = USING(["wait",this,callback])}
- this.queue.push(callback);
- }
- if (!this.running && !this.pending) {this.Process()}
- return callback;
- },
- //
- // Process the command queue if we aren't waiting on another command
- //
- Process: function (queue) {
- while (!this.running && !this.pending && this.queue.length) {
- var callback = this.queue[0];
- queue = this.queue.slice(1); this.queue = [];
- this.Suspend(); var result = callback(); this.Resume();
- if (queue.length) {this.queue = queue.concat(this.queue)}
- if (ISCALLBACK(result) && !result.called) {WAITFOR(result,this)}
- }
- },
- //
- // Suspend/Resume command processing on this queue
- //
- Suspend: function () {this.running++},
- Resume: function () {if (this.running) {this.running--}},
- //
- // Used by WAITFOR to restart the queue when an action completes
- //
- call: function () {this.Process.apply(this,arguments)},
- wait: function (callback) {return callback}
- });
-
- //
- // Create a named signal that listeners can attach to, to be signaled by
- // postings made to the signal. Posts are queued if they occur while one
- // is already in process.
- //
- var SIGNAL = QUEUE.Subclass({
- Init: function (name) {
- QUEUE.prototype.Init.call(this);
- this.name = name;
- this.posted = []; // the messages posted so far
- this.listeners = HOOKS(true); // those with interest in this signal
- },
- //
- // Post a message to the signal listeners, with callback for when complete
- //
- Post: function (message,callback,forget) {
- callback = USING(callback);
- if (this.posting || this.pending) {
- this.Push(["Post",this,message,callback,forget]);
- } else {
- this.callback = callback; callback.reset();
- if (!forget) {this.posted.push(message)}
- this.Suspend(); this.posting = true;
- var result = this.listeners.Execute(message);
- if (ISCALLBACK(result) && !result.called) {WAITFOR(result,this)}
- this.Resume(); delete this.posting;
- if (!this.pending) {this.call()}
- }
- return callback;
- },
- //
- // Clear the post history (so new listeners won't get old messages)
- //
- Clear: function (callback) {
- callback = USING(callback);
- if (this.posting || this.pending) {
- callback = this.Push(["Clear",this,callback]);
- } else {
- this.posted = [];
- callback();
- }
- return callback;
- },
- //
- // Call the callback (all replies are in) and process the command queue
- //
- call: function () {this.callback(this); this.Process()},
-
- //
- // A listener calls this to register intrest in the signal (so it will be called
- // when posts occur). If ignorePast is true, it will not be sent the post history.
- //
- Interest: function (callback,ignorePast,priority) {
- callback = USING(callback);
- this.listeners.Add(callback,priority);
- if (!ignorePast) {
- for (var i = 0, m = this.posted.length; i < m; i++) {
- callback.reset();
- var result = callback(this.posted[i]);
- if (ISCALLBACK(result) && i === this.posted.length-1) {WAITFOR(result,this)}
- }
- }
- return callback;
- },
- //
- // A listener calls this to remove itself from a signal
- //
- NoInterest: function (callback) {
- this.listeners.Remove(callback);
- },
-
- //
- // Hook a callback to a particular message on this signal
- //
- MessageHook: function (msg,callback,priority) {
- callback = USING(callback);
- if (!this.hooks) {this.hooks = {}; this.Interest(["ExecuteHooks",this])}
- if (!this.hooks[msg]) {this.hooks[msg] = HOOKS(true)}
- this.hooks[msg].Add(callback,priority);
- for (var i = 0, m = this.posted.length; i < m; i++)
- {if (this.posted[i] == msg) {callback.reset(); callback(this.posted[i])}}
- return callback;
- },
- //
- // Execute the message hooks for the given message
- //
- ExecuteHooks: function (msg,more) {
- var type = ((msg instanceof Array) ? msg[0] : msg);
- if (!this.hooks[type]) {return null}
- return this.hooks[type].Execute(msg);
- }
-
- },{
- signals: {}, // the named signals
- find: function (name) {
- if (!SIGNAL.signals[name]) {SIGNAL.signals[name] = new SIGNAL(name)}
- return SIGNAL.signals[name];
- }
- });
-
- //
- // The main entry-points
- //
- BASE.Callback = BASE.CallBack = USING;
- BASE.Callback.Delay = DELAY;
- BASE.Callback.After = AFTER;
- BASE.Callback.Queue = QUEUE;
- BASE.Callback.Signal = SIGNAL.find;
- BASE.Callback.Hooks = HOOKS;
- BASE.Callback.ExecuteHooks = EXECUTEHOOKS;
- })("MathJax");
- /**********************************************************/
- (function (BASENAME) {
- var BASE = window[BASENAME];
- if (!BASE) {BASE = window[BASENAME] = {}}
-
- var isSafari2 = (navigator.vendor === "Apple Computer, Inc." &&
- typeof navigator.vendorSub === "undefined");
- var sheets = 0; // used by Safari2
- //
- // Update sheets count and look up the head object
- //
- var HEAD = function (head) {
- if (document.styleSheets && document.styleSheets.length > sheets)
- {sheets = document.styleSheets.length}
- if (!head) {
- head = (document.getElementsByTagName("head"))[0];
- if (!head) {head = document.body}
- }
- return head;
- };
-
- //
- // Remove scripts that are completed so they don't clutter up the HEAD.
- // This runs via setTimeout since IE7 can't remove the script while it is running.
- //
- var SCRIPTS = []; // stores scripts to be removed after a delay
- var REMOVESCRIPTS = function () {
- for (var i = 0, m = SCRIPTS.length; i < m; i++) {BASE.Ajax.head.removeChild(SCRIPTS[i])}
- SCRIPTS = [];
- };
-
- BASE.Ajax = {
- loaded: {}, // files already loaded
- loading: {}, // files currently in process of loading
- loadHooks: {}, // hooks to call when files are loaded
- timeout: 15*1000, // timeout for loading of files (15 seconds)
- styleDelay: 1, // delay to use before styles are available
- config: {root: ""}, // URL of root directory to load from
- STATUS: {
- OK: 1, // file is loading or did load OK
- ERROR: -1 // file timed out during load
- },
-
- rootPattern: new RegExp("^\\["+BASENAME+"\\]"),
-
- //
- // Return a complete URL to a file (replacing the root pattern)
- //
- fileURL: function (file) {return file.replace(this.rootPattern,this.config.root)},
-
- //
- // Load a file if it hasn't been already.
- // Make sure the file URL is "safe"?
- //
- Require: function (file,callback) {
- callback = BASE.Callback(callback); var type;
- if (file instanceof Object) {for (var i in file) {}; type = i.toUpperCase(); file = file[i]}
- else {type = file.split(/\./).pop().toUpperCase()}
- file = this.fileURL(file);
- // FIXME: check that URL is OK
- if (this.loaded[file]) {
- callback(this.loaded[file]);
- } else {
- var FILE = {}; FILE[type] = file;
- this.Load(FILE,callback);
- }
- return callback;
- },
- //
- // Load a file regardless of where it is and whether it has
- // already been loaded.
- //
- Load: function (file,callback) {
- callback = BASE.Callback(callback); var type;
- if (file instanceof Object) {for (var i in file) {}; type = i.toUpperCase(); file = file[i]}
- else {type = file.split(/\./).pop().toUpperCase()}
- file = this.fileURL(file);
- if (this.loading[file]) {
- this.addHook(file,callback);
- } else {
- this.head = HEAD(this.head);
- if (this.loader[type]) {this.loader[type].call(this,file,callback)}
- else {throw Error("Can't load files of type "+type)}
- }
- return callback;
- },
-
- //
- // Register a load hook for a particular file (it will be called when
- // loadComplete() is called for that file)
- //
- LoadHook: function (file,callback,priority) {
- callback = BASE.Callback(callback);
- if (file instanceof Object) {for (var i in file) {file = file[i]}}
- file = this.fileURL(file);
- if (this.loaded[file]) {callback(this.loaded[file])}
- else {this.addHook(file,callback,priority)}
- return callback;
- },
- addHook: function (file,callback,priority) {
- if (!this.loadHooks[file]) {this.loadHooks[file] = MathJax.Callback.Hooks()}
- this.loadHooks[file].Add(callback,priority);
- },
-
- //
- // Used when files are combined in a preloading configuration file
- //
- Preloading: function () {
- for (var i = 0, m = arguments.length; i < m; i++) {
- var file = this.fileURL(arguments[i]);
- if (!this.loading[file]) {this.loading[file] = {preloaded: true}}
- }
- },
-
- //
- // Code used to load the various types of files
- // (JS for JavaScript, CSS for style sheets)
- //
- loader: {
- //
- // Create a SCRIPT tag to load the file
- //
- JS: function (file,callback) {
- var script = document.createElement("script");
- var timeout = BASE.Callback(["loadTimeout",this,file]);
- this.loading[file] = {
- callback: callback,
- message: BASE.Message.File(file),
- timeout: setTimeout(timeout,this.timeout),
- status: this.STATUS.OK,
- script: script
- };
- script.onerror = timeout; // doesn't work in IE and no apparent substitute
- script.type = "text/javascript";
- script.src = file;
- this.head.appendChild(script);
- },
- //
- // Create a LINK tag to load the style sheet
- //
- CSS: function (file,callback) {
- var link = document.createElement("link");
- link.rel = "stylesheet"; link.type = "text/css"; link.href = file;
- this.loading[file] = {
- callback: callback,
- message: BASE.Message.File(file),
- status: this.STATUS.OK
- };
- this.head.appendChild(link);
- this.timer.create.call(this,[this.timer.file,file],link);
- }
- },
-
- //
- // Timing code for checking when style sheets are available.
- //
- timer: {
- //
- // Create the timing callback and start the timing loop.
- // We use a delay because some browsers need it to allow the styles
- // to be processed.
- //
- create: function (callback,node) {
- callback = BASE.Callback(callback);
- if (node.nodeName === "STYLE" && node.styleSheet &&
- typeof(node.styleSheet.cssText) !== 'undefined') {
- callback(this.STATUS.OK); // MSIE processes style immediately, but doesn't set its styleSheet!
- } else if (window.chrome && typeof(window.sessionStorage) !== "undefined" &&
- node.nodeName === "STYLE") {
- callback(this.STATUS.OK); // Same for Chrome 5 (beta), Grrr.
- } else if (isSafari2) {
- this.timer.start(this,[this.timer.checkSafari2,sheets++,callback],this.styleDelay);
- } else {
- this.timer.start(this,[this.timer.checkLength,node,callback],this.styleDelay);
- }
- return callback;
- },
- //
- // Start the timer for the given callback checker
- //
- start: function (AJAX,check,delay,timeout) {
- check = BASE.Callback(check);
- check.execute = this.execute; check.time = this.time;
- check.STATUS = AJAX.STATUS; check.timeout = timeout || AJAX.timeout;
- check.delay = check.total = 0;
- if (delay) {setTimeout(check,delay)} else {check()}
- },
- //
- // Increment the time total, increase the delay
- // and test if we are past the timeout time.
- //
- time: function (callback) {
- this.total += this.delay;
- this.delay = Math.floor(this.delay * 1.05 + 5);
- if (this.total >= this.timeout) {callback(this.STATUS.ERROR); return 1}
- return 0;
- },
- //
- // For JS file loads, call the proper routine according to status
- //
- file: function (file,status) {
- if (status < 0) {BASE.Ajax.loadTimeout(file)} else {BASE.Ajax.loadComplete(file)}
- },
- //
- // Call the hook with the required data
- //
- execute: function () {this.hook.call(this.object,this,this.data[0],this.data[1])},
- //
- // Safari2 doesn't set the link's stylesheet, so we need to look in the
- // document.styleSheets array for the new sheet when it is created
- //
- checkSafari2: function (check,length,callback) {
- if (check.time(callback)) return;
- if (document.styleSheets.length > length &&
- document.styleSheets[length].cssRules &&
- document.styleSheets[length].cssRules.length)
- {callback(check.STATUS.OK)} else {setTimeout(check,check.delay)}
- },
- //
- // Look for the stylesheets rules and check when they are defined
- // and no longer of length zero. (This assumes there actually ARE
- // some rules in the stylesheet.)
- //
- checkLength: function (check,node,callback) {
- if (check.time(callback)) return;
- var isStyle = 0; var sheet = (node.sheet || node.styleSheet);
- try {if ((sheet.cssRules||sheet.rules||[]).length > 0) {isStyle = 1}} catch(err) {
- if (err.message.match(/protected variable|restricted URI/)) {isStyle = 1}
- else if (err.message.match(/Security error/)) {
- // Firefox3 gives "Security error" for missing files, so
- // can't distinguish that from OK files on remote servers.
- // or OK files in different directory from local files.
- isStyle = 1; // just say it is OK (can't really tell)
- }
- }
- if (isStyle) {
- // Opera 9.6 requires this setTimeout
- setTimeout(BASE.Callback([callback,check.STATUS.OK]),0);
- } else {
- setTimeout(check,check.delay);
- }
- }
- },
- //
- // JavaScript code must call this when they are completely initialized
- // (this allows them to perform asynchronous actions before indicating
- // that they are complete).
- //
- loadComplete: function (file) {
- file = this.fileURL(file);
- var loading = this.loading[file];
- if (loading && !loading.preloaded) {
- BASE.Message.Clear(loading.message);
- clearTimeout(loading.timeout);
- if (loading.script) {
- if (SCRIPTS.length === 0) {setTimeout(REMOVESCRIPTS,0)}
- SCRIPTS.push(loading.script);
- }
- this.loaded[file] = loading.status; delete this.loading[file];
- this.addHook(file,loading.callback);
- } else {
- if (loading) {delete this.loading[file]}
- this.loaded[file] = this.STATUS.OK;
- loading = {status: this.STATUS.OK}
- }
- if (!this.loadHooks[file]) {return null}
- return this.loadHooks[file].Execute(loading.status);
- },
-
- //
- // If a file fails to load within the timeout period (or the onerror handler
- // is called), this routine runs to signal the error condition.
- //
- loadTimeout: function (file) {
- if (this.loading[file].timeout) {clearTimeout(this.loading[file].timeout)}
- this.loading[file].status = this.STATUS.ERROR;
- this.loadError(file);
- this.loadComplete(file);
- },
-
- //
- // The default error hook for file load failures
- //
- loadError: function (file) {
- BASE.Message.Set("File failed to load: "+file,null,2000);
- BASE.Hub.signal.Post(["file load error",file]);
- },
- //
- // Defines a style sheet from a hash of style declarations (key:value pairs
- // where the key is the style selector and the value is a hash of CSS attributes
- // and values).
- //
- Styles: function (styles,callback) {
- var styleString = this.StyleString(styles);
- if (styleString === "") {
- callback = BASE.Callback(callback);
- callback();
- } else {
- var style = document.createElement("style"); style.type = "text/css";
- this.head = HEAD(this.head);
- this.head.appendChild(style);
- if (style.styleSheet && typeof(style.styleSheet.cssText) !== 'undefined') {
- style.styleSheet.cssText = styleString;
- } else {
- style.appendChild(document.createTextNode(styleString));
- }
- callback = this.timer.create.call(this,callback,style);
- }
- return callback;
- },
-
- //
- // Create a stylesheet string from a style declaration object
- //
- StyleString: function (styles) {
- if (typeof(styles) === 'string') {return styles}
- var string = "", id, style;
- for (id in styles) {if (styles.hasOwnProperty(id)) {
- if (typeof styles[id] === 'string') {
- string += id + " {"+styles[id]+"}\n";
- } else if (styles[id] instanceof Array) {
- for (var i = 0; i < styles[id].length; i++) {
- style = {}; style[id] = styles[id][i];
- string += this.StyleString(style);
- }
- } else if (id.substr(0,6) === '@media') {
- string += id + " {"+this.StyleString(styles[id])+"}\n";
- } else if (styles[id] != null) {
- style = [];
- for (var name in styles[id]) {if (styles[id].hasOwnProperty(name)) {
- if (styles[id][name] != null)
- {style[style.length] = name + ': ' + styles[id][name]}
- }}
- string += id +" {"+style.join('; ')+"}\n";
- }
- }}
- return string;
- }
- };
- })("MathJax");
- /**********************************************************/
- MathJax.HTML = {
- //
- // Create an HTML element with given attributes and content.
- // The def parameter is an (optional) object containing key:value pairs
- // of the attributes and their values, and contents is an (optional)
- // array of strings to be inserted as text, or arrays of the form
- // [type,def,contents] that describes an HTML element to be inserted
- // into the current element. Thus the contents can describe a complete
- // HTML snippet of arbitrary complexity. E.g.:
- //
- // MathJax.HTML.Element("span",{id:"mySpan",style{"font-style":"italic"}},[
- // "(See the ",["a",{href:"http://www.mathjax.org"},["MathJax home page"]],
- // " for more details.)"]);
- //
- Element: function (type,def,contents) {
- var obj = document.createElement(type);
- if (def) {
- if (def.style) {
- var style = def.style; def.style = {};
- for (var id in style) {if (style.hasOwnProperty(id))
- {def.style[id.replace(/-([a-z])/g,this.ucMatch)] = style[id]}}
- }
- MathJax.Hub.Insert(obj,def);
- }
- if (contents) {
- for (var i = 0; i < contents.length; i++) {
- if (contents[i] instanceof Array) {
- obj.appendChild(this.Element(contents[i][0],contents[i][1],contents[i][2]));
- } else {
- obj.appendChild(document.createTextNode(contents[i]));
- }
- }
- }
- return obj;
- },
- ucMatch: function (match,c) {return c.toUpperCase()},
- addElement: function (span,type,def,contents) {return span.appendChild(this.Element(type,def,contents))},
- TextNode: function (text) {return document.createTextNode(text)},
- addText: function (span,text) {return span.appendChild(this.TextNode(text))},
- //
- // Set and get the text of a script
- //
- setScript: function (script,text) {
- if (this.setScriptBug) {script.text = text} else {
- while (script.firstChild) {script.removeChild(script.firstChild)}
- this.addText(script,text);
- }
- },
- getScript: function (script) {
- var text = (script.text === "" ? script.innerHTML : script.text);
- return text.replace(/^\s+/,"").replace(/\s+$/,"");
- },
- //
- // Manage cookies
- //
- Cookie: {
- prefix: "mjx",
- expires: 365,
-
- //
- // Save an object as a named cookie
- //
- Set: function (name,def) {
- var keys = [];
- if (def) {
- for (var id in def) {if (def.hasOwnProperty(id)) {
- keys.push(id+":"+def[id].toString().replace(/&/g,"&&"));
- }}
- }
- var cookie = this.prefix+"."+name+"="+escape(keys.join('&;'));
- if (this.expires) {
- var time = new Date(); time.setDate(time.getDate() + this.expires);
- cookie += '; expires='+time.toGMTString();
- }
- document.cookie = cookie+"; path=/";
- },
-
- //
- // Get the contents of a named cookie and incorporate
- // it into the given object (or return a fresh one)
- //
- Get: function (name,obj) {
- if (!obj) {obj = {}}
- var pattern = new RegExp("(?:^|;\\s*)"+this.prefix+"\\."+name+"=([^;]*)(?:;|$)");
- var match = pattern.exec(document.cookie);
- if (match && match[1] !== "") {
- var keys = unescape(match[1]).split('&;');
- for (var i = 0, m = keys.length; i < m; i++) {
- match = keys[i].match(/([^:]+):(.*)/);
- var value = match[2].replace(/&&/g,'&');
- if (value === "true") {value = true} else if (value === "false") {value = false}
- else if (value.match(/^-?(\d+(\.\d+)?|\.\d+)$/)) {value = parseFloat(value)}
- obj[match[1]] = value;
- }
- }
- return obj;
- }
- }
-
- };
- /**********************************************************/
- MathJax.Message = {
- ready: false, // used to tell when the styles are available
- log: [{}], current: null,
- textNodeBug: (navigator.vendor === "Apple Computer, Inc." &&
- typeof navigator.vendorSub === "undefined") ||
- (window.hasOwnProperty && window.hasOwnProperty("konqueror")), // Konqueror displays some gibberish with text.nodeValue = "..."
-
- styles: {
- "#MathJax_Message": {
- position: "fixed", left: "1px", bottom: "2px",
- 'background-color': "#E6E6E6", border: "1px solid #959595",
- margin: "0px", padding: "2px 8px",
- 'z-index': "102", color: "black", 'font-size': "80%",
- width: "auto", 'white-space': "nowrap"
- },
-
- "#MathJax_MSIE_Frame": {
- position: "absolute",
- top:0, left: 0, width: "0px", 'z-index': 101,
- border: "0px", margin: "0px", padding: "0px"
- }
- },
-
- browsers: {
- MSIE: function (browser) {
- MathJax.Hub.config.styles["#MathJax_Message"].position = "absolute";
- MathJax.Message.quirks = (document.compatMode === "BackCompat");
- },
- Chrome: function (browser) {
- MathJax.Hub.config.styles["#MathJax_Message"].bottom = "1.5em";
- MathJax.Hub.config.styles["#MathJax_Message"].left = "1em";
- }
- },
-
- Init: function (styles) {
- if (styles) {this.ready = true}
- if (!document.body || !this.ready) {return false}
- //
- // ASCIIMathML replaces the entire page with a copy of itself (@#!#%@!!)
- // so check that this.div is still part of the page, otherwise look up
- // the copy and use that.
- //
- if (this.div && this.div.parentNode == null) {
- this.div = document.getElementById("MathJax_Message");
- if (this.div) {this.text = this.div.firstChild}
- }
- if (!this.div) {
- var frame = document.body;
- if (MathJax.Hub.Browser.isMSIE) {
- frame = this.frame = this.addDiv(document.body); frame.removeAttribute("id");
- frame.style.position = "absolute";
- frame.style.border = frame.style.margin = frame.style.padding = "0px";
- frame.style.zIndex = "101"; frame.style.height = "0px";
- frame = this.addDiv(frame);
- frame.id = "MathJax_MSIE_Frame";
- window.attachEvent("onscroll",this.MoveFrame);
- window.attachEvent("onresize",this.MoveFrame);
- this.MoveFrame();
- }
- this.div = this.addDiv(frame); this.div.style.display = "none";
- this.text = this.div.appendChild(document.createTextNode(""));
- }
- return true;
- },
-
- addDiv: function (parent) {
- var div = document.createElement("div");
- div.id = "MathJax_Message";
- if (parent.firstChild) {parent.insertBefore(div,parent.firstChild)}
- else {parent.appendChild(div)}
- return div;
- },
-
- MoveFrame: function () {
- var body = (MathJax.Message.quirks ? document.body : document.documentElement);
- var frame = MathJax.Message.frame;
- frame.style.left = body.scrollLeft + 'px';
- frame.style.top = body.scrollTop + 'px';
- frame.style.width = body.clientWidth + 'px';
- frame = frame.firstChild;
- frame.style.height = body.clientHeight + 'px';
- },
-
- filterText: function (text,n) {
- if (MathJax.Hub.config.messageStyle === "simple") {
- if (text.match(/^Loading /)) {
- if (!this.loading) {this.loading = "Loading "}
- text = this.loading; this.loading += ".";
- } else if (text.match(/^Processing /)) {
- if (!this.processing) {this.processing = "Processing "}
- text = this.processing; this.processing += ".";
- } else if (text.match(/^Typesetting /)) {
- if (!this.typesetting) {this.typesetting = "Typesetting "}
- text = this.typesetting; this.typesetting += ".";
- }
- }
- return text;
- },
-
- Set: function (text,n,clearDelay) {
- if (this.timer) {clearTimeout(this.timer); delete this.timeout}
- if (n == null) {n = this.log.length; this.log[n] = {}}
- this.log[n].text = text; this.log[n].filteredText = text = this.filterText(text,n);
- if (typeof(this.log[n].next) === "undefined") {
- this.log[n].next = this.current;
- if (this.current != null) {this.log[this.current].prev = n}
- this.current = n;
- }
- if (this.current === n && MathJax.Hub.config.messageStyle !== "none") {
- if (this.Init()) {
- if (this.textNodeBug) {this.div.innerHTML = text} else {this.text.nodeValue = text}
- this.div.style.display = "";
- if (this.status) {window.status = ""; delete this.status}
- } else {
- window.status = text;
- this.status = true;
- }
- }
- if (clearDelay) {setTimeout(MathJax.Callback(["Clear",this,n]),clearDelay)}
- else if (clearDelay == 0) {this.Clear(n,0)}
- return n;
- },
-
- Clear: function (n,delay) {
- if (this.log[n].prev != null) {this.log[this.log[n].prev].next = this.log[n].next}
- if (this.log[n].next != null) {this.log[this.log[n].next].prev = this.log[n].prev}
- if (this.current === n) {
- this.current = this.log[n].next;
- if (this.text) {
- if (this.div.parentNode == null) {this.Init()} // see ASCIIMathML comments above
- if (this.current == null) {
- if (this.timer) {clearTimeout(this.timer); delete this.timer}
- if (delay == null) {delay = 600}
- if (delay === 0) {this.Remove()}
- else {this.timer = setTimeout(MathJax.Callback(["Remove",this]),delay)}
- } else if (MathJax.Hub.config.messageStyle !== "none") {
- if (this.textNodeBug) {this.div.innerHTML = this.log[this.current].filteredText}
- else {this.text.nodeValue = this.log[this.current].filteredText}
- }
- if (this.status) {window.status = ""; delete this.status}
- } else if (this.status) {
- window.status = (this.current == null ? "" : this.log[this.current].text);
- }
- }
- delete this.log[n].next; delete this.log[n].prev;
- delete this.log[n].filteredText;
- },
-
- Remove: function () {
- // FIXME: do a fade out or something else interesting?
- this.text.nodeValue = "";
- this.div.style.display = "none";
- },
-
- File: function (file) {
- var root = MathJax.Ajax.config.root;
- if (file.substr(0,root.length) === root) {file = "[MathJax]"+file.substr(root.length)}
- return this.Set("Loading "+file);
- },
-
- Log: function () {
- var strings = [];
- for (var i = 1, m = this.log.length; i < m; i++) {strings[i] = this.log[i].text}
- return strings.join("\n");
- }
- };
- /**********************************************************/
- MathJax.Hub = {
- config: {
- root: "",
- config: [], // list of configuration files to load
- styleSheets: [], // list of CSS files to load
- styles: { // styles to generate in-line
- ".MathJax_Preview": {color: "#888"}
- },
- jax: [], // list of input and output jax to load
- extensions: [], // list of extensions to load
- preJax: null, // pattern to remove from before math script tag
- postJax: null, // pattern to remove from after math script tag
- displayAlign: 'center', // how to align displayed equations (left, center, right)
- displayIndent: '0', // indentation for displayed equations (when not centered)
- preRemoveClass: 'MathJax_Preview', // class of objects to remove preceeding math script
- showProcessingMessages: true, // display "Processing math: nn%" messages or not
- messageStyle: "normal", // set to "none" or "simple" (for "Loading..." and "Processing...")
- delayStartupUntil: "none", // set to "onload" to delay setup until the onload handler runs
- // set to "configured" to delay startup until MathJax.Hub.Configured() is called
- // set to a Callback to wait for before continuing with the startup
- skipStartupTypeset: false, // set to true to skip PreProcess and Process during startup
- "v1.0-compatible": true, // set to false to prevent message about configuration change
- elements: [], // array of elements to process when none is given explicitly
- positionToHash: true, // after initial typeset pass, position to #hash location?
-
- showMathMenu: true, // attach math context menu to typeset math?
- showMathMenuMSIE: true, // separtely determine if MSIE should have math menu
- // (since the code for that is a bit delicate)
- menuSettings: {
- zoom: "None", // when to do MathZoom
- CTRL: false, // require CTRL for MathZoom?
- ALT: false, // require Alt or Option?
- CMD: false, // require CMD?
- Shift: false, // require Shift?
- discoverable: false, // make math menu discoverable on hover?
- zscale: "200%", // the scaling factor for MathZoom
- renderer: "", // set when Jax are loaded
- font: "Auto", // what font HTML-CSS should use
- context: "MathJax", // or "Browser" for pass-through to browser menu
- mpContext: false, // true means pass menu events to MathPlayer in IE
- mpMouse: false, // true means pass mouse events to MathPlayer in IE
- texHints: true // include class names for TeXAtom elements
- },
-
- errorSettings: {
- message: ["[Math Processing Error]"], // HTML snippet structure for message to use
- style: {color: "#CC0000", "font-style":"italic"} // style for message
- }
- },
-
- preProcessors: MathJax.Callback.Hooks(true), // list of callbacks for preprocessing (initialized by extensions)
- inputJax: {}, // mime-type mapped to input jax (by registration)
- outputJax: {order:{}}, // mime-type mapped to output jax list (by registration)
- processUpdateTime: 250, // time between screen updates when processing math (milliseconds)
- processUpdateDelay: 10, // pause between screen updates to allow other processing (milliseconds)
- signal: MathJax.Callback.Signal("Hub"), // Signal used for Hub events
- Config: function (def) {
- this.Insert(this.config,def);
- if (this.config.Augment) {this.Augment(this.config.Augment)}
- },
- CombineConfig: function (name,def) {
- var config = this.config, id, parent; name = name.split(/\./);
- for (var i = 0, m = name.length; i < m; i++) {
- id = name[i]; if (!config[id]) {config[id] = {}}
- parent = config; config = config[id];
- }
- parent[id] = config = this.Insert(def,config);
- return config;
- },
-
- Register: {
- PreProcessor: function () {MathJax.Hub.preProcessors.Add.apply(MathJax.Hub.preProcessors,arguments)},
- MessageHook: function () {return MathJax.Hub.signal.MessageHook.apply(MathJax.Hub.signal,arguments)},
- StartupHook: function () {return MathJax.Hub.Startup.signal.MessageHook.apply(MathJax.Hub.Startup.signal,arguments)},
- LoadHook: function () {return MathJax.Ajax.LoadHook.apply(MathJax.Ajax,arguments)}
- },
-
- getAllJax: function (element) {
- var jax = [], scripts = this.elementScripts(element);
- for (var i = 0, m = scripts.length; i < m; i++) {
- if (scripts[i].MathJax && scripts[i].MathJax.elementJax)
- {jax.push(scripts[i].MathJax.elementJax)}
- }
- return jax;
- },
-
- getJaxByType: function (type,element) {
- var jax = [], scripts = this.elementScripts(element);
- for (var i = 0, m = scripts.length; i < m; i++) {
- if (scripts[i].MathJax && scripts[i].MathJax.elementJax &&
- scripts[i].MathJax.elementJax.mimeType === type)
- {jax.push(scripts[i].MathJax.elementJax)}
- }
- return jax;
- },
-
- getJaxByInputType: function (type,element) {
- var jax = [], scripts = this.elementScripts(element);
- for (var i = 0, m = scripts.length; i < m; i++) {
- if (scripts[i].MathJax && scripts[i].MathJax.elementJax &&
- scripts[i].type && scripts[i].type.replace(/ *;(.|\s)*/,"") === type)
- {jax.push(scripts[i].MathJax.elementJax)}
- }
- return jax;
- },
-
- getJaxFor: function (element) {
- if (typeof(element) …
Large files files are truncated, but you can click here to view the full file