tag
+ //
+ data = this.processString(parts[i+4].replace(/^\s/,"").replace(/\s$/,""),args,domain);
+ if (!MathJax.Object.isArray(data)) {data = [data]}
+ data = ["code",{},data];
+ } else if (parts[i+5]) { // hyperlink
+ //
+ // Process the link text, and make an tag with the URL
+ //
+ data = this.processString(parts[i+5],args,domain);
+ if (!MathJax.Object.isArray(data)) {data = [data]}
+ data = ["a",{href:this.processString(parts[i+6],args),target:"_blank"},data];
+ } else {
+ //
+ // Escaped character (%c) gets added into the string.
+ //
+ string += parts[i]; data = null;
+ }
+ //
+ // If there is a tag to insert,
+ // Add any pending string, then push the tag
+ //
+ if (data) {
+ result = this.concatString(result,string,args,domain);
+ result.push(data); string = "";
+ }
+ //
+ // Process the string that follows matches pattern
+ //
+ if (parts[i+7] !== "") {string += parts[i+7]}
+ };
+ //
+ // Add any pending string and return the resulting snippet
+ //
+ result = this.concatString(result,string,args,domain);
+ return result;
+ },
+ concatString: function (result,string,args,domain) {
+ if (string != "") {
+ //
+ // Process the substutions.
+ // If the result is not a snippet, turn it into one.
+ // Then concatenate the snippet to the current one
+ //
+ string = this.processString(string,args,domain);
+ if (!MathJax.Object.isArray(string)) {string = [string]}
+ result = result.concat(string);
+ }
+ return result;
+ },
+
+ lookupPhrase: function (id,phrase,domain) {
+ //
+ // Get the domain and messageID
+ //
+ if (!domain) {domain = "_"}
+ if (MathJax.Object.isArray(id)) {domain = (id[0] || "_"); id = (id[1] || "")}
+ //
+ // Check if the data is available and if not,
+ // load it and throw a restart error so the calling
+ // code can wait for the load and try again.
+ //
+ var load = this.loadDomain(domain);
+ if (load) {MathJax.Hub.RestartAfter(load)}
+ //
+ // Look up the message in the localization data
+ // (if not found, the original English is used)
+ //
+ var localeData = this.strings[this.locale];
+ if (localeData) {
+ if (localeData.domains && domain in localeData.domains) {
+ var domainData = localeData.domains[domain];
+ if (domainData.strings && id in domainData.strings)
+ {phrase = domainData.strings[id]}
+ }
+ }
+ //
+ // return the translated phrase
+ //
+ return phrase;
+ },
+
+ //
+ // Load a langauge data file from the proper
+ // directory and file.
+ //
+ loadFile: function (file,data,callback) {
+ callback = MathJax.Callback(callback);
+ file = (data.file || file); // the data's file name or the default name
+ if (!file.match(/\.js$/)) {file += ".js"} // add .js if needed
+ //
+ // Add the directory if the file doesn't
+ // contain a full URL already.
+ //
+ if (!file.match(/^([a-z]+:|\[MathJax\])/)) {
+ var dir = (this.strings[this.locale].directory ||
+ this.directory + "/" + this.locale ||
+ "[MathJax]/localization/" + this.locale);
+ file = dir + "/" + file;
+ }
+ //
+ // Load the file and mark the data as loaded (even if it
+ // failed to load, so we don't continue to try to load it
+ // over and over).
+ //
+ var load = MathJax.Ajax.Require(file,function () {data.isLoaded = true; return callback()});
+ //
+ // Return the callback if needed, otherwise null.
+ //
+ return (load.called ? null : load);
+ },
+
+ //
+ // Check to see if the localization data are loaded
+ // for the given domain; if not, load the data file,
+ // and return a callback for the loading operation.
+ // Otherwise return null (data are loaded).
+ //
+ loadDomain: function (domain,callback) {
+ var load, localeData = this.strings[this.locale];
+ if (localeData) {
+ if (!localeData.isLoaded) {
+ load = this.loadFile(this.locale,localeData);
+ if (load) {
+ return MathJax.Callback.Queue(
+ load,["loadDomain",this,domain] // call again to load domain
+ ).Push(callback||{});
+ }
+ }
+ if (localeData.domains && domain in localeData.domains) {
+ var domainData = localeData.domains[domain];
+ if (!domainData.isLoaded) {
+ load = this.loadFile(domain,domainData);
+ if (load) {return MathJax.Callback.Queue(load).Push(callback)}
+ }
+ }
+ }
+ // localization data are loaded, so just do the callback
+ return MathJax.Callback(callback)();
+ },
+
+ //
+ // Perform a function, properly handling
+ // restarts due to localization file loads.
+ //
+ // Note that this may return before the function
+ // has been called successfully, so you should
+ // consider fn as running asynchronously. (Callbacks
+ // can be used to synchronize it with other actions.)
+ //
+ Try: function (fn) {
+ fn = MathJax.Callback(fn); fn.autoReset = true;
+ try {fn()} catch (err) {
+ if (!err.restart) {throw err}
+ MathJax.Callback.After(["Try",this,fn],err.restart);
+ }
+ },
+
+ //
+ // Reset the current language
+ //
+ resetLocale: function(locale) {
+ // Selection algorithm:
+ // 1) Downcase locale name (e.g. "en-US" => "en-us")
+ // 2) Try a parent language (e.g. "en-us" => "en")
+ // 3) Try the fallback specified in the data (e.g. "pt" => "pt-br")
+ // 4) Otherwise don't change the locale.
+ if (!locale) return;
+ locale = locale.toLowerCase();
+ while (!this.strings[locale]) {
+ var dashPos = locale.lastIndexOf("-");
+ if (dashPos === -1) return;
+ locale = locale.substring(0, dashPos);
+ }
+ var remap = this.strings[locale].remap;
+ this.locale = remap ? remap : locale;
+ },
+
+ //
+ // Set the current language
+ //
+ setLocale: function(locale) {
+ this.resetLocale(locale);
+ if (MathJax.Menu) {this.loadDomain("MathMenu")}
+ },
+
+ //
+ // Add or update a language or domain
+ //
+ addTranslation: function (locale,domain,definition) {
+ var data = this.strings[locale], isNew = false;
+ if (!data) {data = this.strings[locale] = {}; isNew = true}
+ if (!data.domains) {data.domains = {}}
+ if (domain) {
+ if (!data.domains[domain]) {data.domains[domain] = {}}
+ data = data.domains[domain];
+ }
+ MathJax.Hub.Insert(data,definition);
+ if (isNew && MathJax.Menu.menu) {MathJax.Menu.CreateLocaleMenu()}
+ },
+
+ //
+ // Set CSS for an element based on font requirements
+ //
+ setCSS: function (div) {
+ var locale = this.strings[this.locale];
+ if (locale) {
+ if (locale.fontFamily) {div.style.fontFamily = locale.fontFamily}
+ if (locale.fontDirection) {
+ div.style.direction = locale.fontDirection;
+ if (locale.fontDirection === "rtl") {div.style.textAlign = "right"}
+ }
+ }
+ return div;
+ },
+
+ //
+ // Get the language's font family or direction
+ //
+ fontFamily: function () {
+ var locale = this.strings[this.locale];
+ return (locale ? locale.fontFamily : null);
+ },
+ fontDirection: function () {
+ var locale = this.strings[this.locale];
+ return (locale ? locale.fontDirection : null);
+ },
+
+ //
+ // Get the language's plural index for a number
+ //
+ plural: function (n) {
+ var locale = this.strings[this.locale];
+ if (locale && locale.plural) {return locale.plural(n)}
+ // default
+ if (n == 1) {return 1} // one
+ return 2; // other
+ },
+
+ //
+ // Convert a number to language-specific form
+ //
+ number: function(n) {
+ var locale = this.strings[this.locale];
+ if (locale && locale.number) {return locale.number(n)}
+ // default
+ return n;
+ }
+};
+
+
+/**********************************************************/
+
+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.Message.msieFixedPositionBug = ((document.documentMode||0) < 7);
+ if (MathJax.Message.msieFixedPositionBug)
+ {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 (this.msieFixedPositionBug && window.attachEvent) {
+ 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';
+ },
+
+ localize: function (message) {
+ return MathJax.Localization._(message,message);
+ },
+
+ filterText: function (text,n,id) {
+ if (MathJax.Hub.config.messageStyle === "simple") {
+ if (id === "LoadFile") {
+ if (!this.loading) {this.loading = this.localize("Loading") + " "}
+ text = this.loading; this.loading += ".";
+ } else if (id === "ProcessMath") {
+ if (!this.processing) {this.processing = this.localize("Processing") + " "}
+ text = this.processing; this.processing += ".";
+ } else if (id === "TypesetMath") {
+ if (!this.typesetting) {this.typesetting = this.localize("Typesetting") + " "}
+ text = this.typesetting; this.typesetting += ".";
+ }
+ }
+ return text;
+ },
+
+ clearCounts: function () {
+ delete this.loading;
+ delete this.processing;
+ delete this.typesetting;
+ },
+
+ Set: function (text,n,clearDelay) {
+ if (n == null) {n = this.log.length; this.log[n] = {}}
+ //
+ // Translate message if it is [id,message,arguments]
+ //
+ var id = "";
+ if (MathJax.Object.isArray(text)) {
+ id = text[0]; if (MathJax.Object.isArray(id)) {id = id[1]}
+ //
+ // Localization._() will throw a restart error if a localization file
+ // needs to be loaded, so trap that and redo the Set() call
+ // after it is loaded.
+ //
+ try {
+ text = MathJax.Localization._.apply(MathJax.Localization,text);
+ } catch (err) {
+ if (!err.restart) {throw err}
+ if (!err.restart.called) {
+ //
+ // Mark it so we can tell if the Clear() comes before the message is displayed
+ //
+ if (this.log[n].restarted == null) {this.log[n].restarted = 0}
+ this.log[n].restarted++; delete this.log[n].cleared;
+ MathJax.Callback.After(["Set",this,text,n,clearDelay],err.restart);
+ return n;
+ }
+ }
+ }
+ //
+ // Clear the timout timer.
+ //
+ if (this.timer) {clearTimeout(this.timer); delete this.timer}
+ //
+ // Save the message and filtered message.
+ //
+ this.log[n].text = text; this.log[n].filteredText = text = this.filterText(text,n,id);
+ //
+ // Hook the message into the message list so we can tell
+ // what message to put up when this one is removed.
+ //
+ 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;
+ }
+ //
+ // Show the message if it is the currently active one.
+ //
+ 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;
+ }
+ }
+ //
+ // Check if the message was resetarted to load a localization file
+ // and if it has been cleared in the meanwhile.
+ //
+ if (this.log[n].restarted) {
+ if (this.log[n].cleared) {clearDelay = 0}
+ if (--this.log[n].restarted === 0) {delete this.log[n].cleared}
+ }
+ //
+ // Check if we need to clear the message automatically.
+ //
+ if (clearDelay) {setTimeout(MathJax.Callback(["Clear",this,n]),clearDelay)}
+ else if (clearDelay == 0) {this.Clear(n,0)}
+ //
+ // Return the message number.
+ //
+ return n;
+ },
+
+ Clear: function (n,delay) {
+ //
+ // Detatch the message from the active list.
+ //
+ 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 it is the current message, get the next one to show.
+ //
+ 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 there are no more messages, remove the message box.
+ //
+ 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 there is an old message, put it in place
+ //
+ 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);
+ }
+ }
+ //
+ // Clean up the log data no longer needed
+ //
+ delete this.log[n].next; delete this.log[n].prev;
+ delete this.log[n].filteredText;
+ //
+ // If this is a restarted localization message, mark that it has been cleared
+ // while waiting for the file to load.
+ //
+ if (this.log[n].restarted) {this.log[n].cleared = true}
+ },
+
+ Remove: function () {
+ // FIXME: do a fade out or something else interesting?
+ this.text.nodeValue = "";
+ this.div.style.display = "none";
+ },
+
+ File: function (file) {
+ return this.Set(["LoadFile","Loading %1",file],null,null);
+ },
+
+ 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
+ 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: null, // set when Jax are loaded
+ font: "Auto", // what font HTML-CSS should use
+ context: "MathJax", // or "Browser" for pass-through to browser menu
+ locale: null, // the language to use for messages
+ 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
+ FastPreview: null, // use PreviewHTML output as preview?
+ assistiveMML: null, // include hidden MathML for screen readers?
+ inTabOrder: true, // set to false if math elements should be included in the tabindex
+ semantics: false // add semantics tag with original form in MathML output
+ },
+
+ errorSettings: {
+ // localized HTML snippet structure for message to use
+ message: ["[",["MathProcessingError","Math Processing Error"],"]"],
+ style: {color: "#CC0000", "font-style":"italic"} // style for message
+ },
+
+ ignoreMMLattributes: {} // attributes not to copy to HTML-CSS or SVG output
+ // from MathML input (in addition to the ones in MML.nocopyAttributes).
+ // An id set to true will be ignored, one set to false will
+ // be allowed (even if other criteria normally would prevent
+ // it from being copied); use false carefully!
+ },
+
+ 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)
+
+ processSectionDelay: 50, // pause between input and output phases of processing
+ 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 () {return 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)}
+ },
+ UnRegister: {
+ PreProcessor: function (hook) {MathJax.Hub.preProcessors.Remove(hook)},
+ MessageHook: function (hook) {MathJax.Hub.signal.RemoveHook(hook)},
+ StartupHook: function (hook) {MathJax.Hub.Startup.signal.RemoveHook(hook)},
+ LoadHook: function (hook) {MathJax.Ajax.removeHook(hook)}
+ },
+
+ 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) === 'string') {element = document.getElementById(element)}
+ if (element && element.MathJax) {return element.MathJax.elementJax}
+ if (this.isMathJaxNode(element)) {
+ if (!element.isMathJax) {element = element.firstChild} // for NativeMML output
+ while (element && !element.jaxID) {element = element.parentNode}
+ if (element) {return MathJax.OutputJax[element.jaxID].getJaxFromMath(element)}
+ }
+ return null;
+ },
+
+ isJax: function (element) {
+ if (typeof(element) === 'string') {element = document.getElementById(element)}
+ if (this.isMathJaxNode(element)) {return 1}
+ if (element && (element.tagName||"").toLowerCase() === 'script') {
+ if (element.MathJax)
+ {return (element.MathJax.state === MathJax.ElementJax.STATE.PROCESSED ? 1 : -1)}
+ if (element.type && this.inputJax[element.type.replace(/ *;(.|\s)*/,"")]) {return -1}
+ }
+ return 0;
+ },
+ isMathJaxNode: function (element) {
+ return !!element && (element.isMathJax || (element.className||"") === "MathJax_MathML");
+ },
+
+ setRenderer: function (renderer,type) {
+ if (!renderer) return;
+ if (!MathJax.OutputJax[renderer]) {
+ this.config.menuSettings.renderer = "";
+ var file = "[MathJax]/jax/output/"+renderer+"/config.js";
+ return MathJax.Ajax.Require(file,["setRenderer",this,renderer,type]);
+ } else {
+ this.config.menuSettings.renderer = renderer;
+ if (type == null) {type = "jax/mml"}
+ var jax = this.outputJax;
+ if (jax[type] && jax[type].length) {
+ if (renderer !== jax[type][0].id) {
+ jax[type].unshift(MathJax.OutputJax[renderer]);
+ return this.signal.Post(["Renderer Selected",renderer]);
+ }
+ }
+ return null;
+ }
+ },
+
+ Queue: function () {
+ return this.queue.Push.apply(this.queue,arguments);
+ },
+
+ Typeset: function (element,callback) {
+ if (!MathJax.isReady) return null;
+ var ec = this.elementCallback(element,callback);
+ if (ec.count) {
+ var queue = MathJax.Callback.Queue(
+ ["PreProcess",this,ec.elements],
+ ["Process",this,ec.elements]
+ );
+ }
+ return queue.Push(ec.callback);
+ },
+
+ PreProcess: function (element,callback) {
+ var ec = this.elementCallback(element,callback);
+ var queue = MathJax.Callback.Queue();
+ if (ec.count) {
+ var elements = (ec.count === 1 ? [ec.elements] : ec.elements);
+ queue.Push(["Post",this.signal,["Begin PreProcess",ec.elements]]);
+ for (var i = 0, m = elements.length; i < m; i++) {
+ if (elements[i]) {queue.Push(["Execute",this.preProcessors,elements[i]])}
+ }
+ queue.Push(["Post",this.signal,["End PreProcess",ec.elements]]);
+ }
+ return queue.Push(ec.callback);
+ },
+
+ Process: function (element,callback) {return this.takeAction("Process",element,callback)},
+ Update: function (element,callback) {return this.takeAction("Update",element,callback)},
+ Reprocess: function (element,callback) {return this.takeAction("Reprocess",element,callback)},
+ Rerender: function (element,callback) {return this.takeAction("Rerender",element,callback)},
+
+ takeAction: function (action,element,callback) {
+ var ec = this.elementCallback(element,callback);
+ var elements = ec.elements;
+ var queue = MathJax.Callback.Queue(["Clear",this.signal]);
+ var state = {
+ scripts: [], // filled in by prepareScripts
+ start: new Date().getTime(), // timer for processing messages
+ i: 0, j: 0, // current script, current jax
+ jax: {}, // scripts grouped by output jax
+ jaxIDs: [] // id's of jax used
+ };
+ if (ec.count) {
+ var delay = ["Delay",MathJax.Callback,this.processSectionDelay];
+ if (!delay[2]) {delay = {}}
+ queue.Push(
+ ["clearCounts",MathJax.Message],
+ ["Post",this.signal,["Begin "+action,elements]],
+ ["Post",this.signal,["Begin Math",elements,action]],
+ ["prepareScripts",this,action,elements,state],
+ ["Post",this.signal,["Begin Math Input",elements,action]],
+ ["processInput",this,state],
+ ["Post",this.signal,["End Math Input",elements,action]],
+ delay,
+ ["prepareOutput",this,state,"preProcess"],
+ delay,
+ ["Post",this.signal,["Begin Math Output",elements,action]],
+ ["processOutput",this,state],
+ ["Post",this.signal,["End Math Output",elements,action]],
+ delay,
+ ["prepareOutput",this,state,"postProcess"],
+ delay,
+ ["Post",this.signal,["End Math",elements,action]],
+ ["Post",this.signal,["End "+action,elements]],
+ ["clearCounts",MathJax.Message]
+ );
+ }
+ return queue.Push(ec.callback);
+ },
+
+ scriptAction: {
+ Process: function (script) {},
+ Update: function (script) {
+ var jax = script.MathJax.elementJax;
+ if (jax && jax.needsUpdate()) {jax.Remove(true); script.MathJax.state = jax.STATE.UPDATE}
+ else {script.MathJax.state = jax.STATE.PROCESSED}
+ },
+ Reprocess: function (script) {
+ var jax = script.MathJax.elementJax;
+ if (jax) {jax.Remove(true); script.MathJax.state = jax.STATE.UPDATE}
+ },
+ Rerender: function (script) {
+ var jax = script.MathJax.elementJax;
+ if (jax) {jax.Remove(true); script.MathJax.state = jax.STATE.OUTPUT}
+ }
+ },
+
+ prepareScripts: function (action,element,state) {
+ if (arguments.callee.disabled) return;
+ var scripts = this.elementScripts(element);
+ var STATE = MathJax.ElementJax.STATE;
+ for (var i = 0, m = scripts.length; i < m; i++) {
+ var script = scripts[i];
+ if (script.type && this.inputJax[script.type.replace(/ *;(.|\n)*/,"")]) {
+ if (script.MathJax) {
+ if (script.MathJax.elementJax && script.MathJax.elementJax.hover) {
+ MathJax.Extension.MathEvents.Hover.ClearHover(script.MathJax.elementJax);
+ }
+ if (script.MathJax.state !== STATE.PENDING) {this.scriptAction[action](script)}
+ }
+ if (!script.MathJax) {script.MathJax = {state: STATE.PENDING}}
+ if (script.MathJax.error) delete script.MathJax.error;
+ if (script.MathJax.state !== STATE.PROCESSED) {state.scripts.push(script)}
+ }
+ }
+ },
+
+ checkScriptSiblings: function (script) {
+ if (script.MathJax.checked) return;
+ var config = this.config, pre = script.previousSibling;
+ if (pre && pre.nodeName === "#text") {
+ var preJax,postJax, post = script.nextSibling;
+ if (post && post.nodeName !== "#text") {post = null}
+ if (config.preJax) {
+ if (typeof(config.preJax) === "string") {config.preJax = new RegExp(config.preJax+"$")}
+ preJax = pre.nodeValue.match(config.preJax);
+ }
+ if (config.postJax && post) {
+ if (typeof(config.postJax) === "string") {config.postJax = new RegExp("^"+config.postJax)}
+ postJax = post.nodeValue.match(config.postJax);
+ }
+ if (preJax && (!config.postJax || postJax)) {
+ pre.nodeValue = pre.nodeValue.replace
+ (config.preJax,(preJax.length > 1? preJax[1] : ""));
+ pre = null;
+ }
+ if (postJax && (!config.preJax || preJax)) {
+ post.nodeValue = post.nodeValue.replace
+ (config.postJax,(postJax.length > 1? postJax[1] : ""));
+ }
+ if (pre && !pre.nodeValue.match(/\S/)) {pre = pre.previousSibling}
+ }
+ if (config.preRemoveClass && pre && pre.className === config.preRemoveClass)
+ {script.MathJax.preview = pre}
+ script.MathJax.checked = 1;
+ },
+
+ processInput: function (state) {
+ var jax, STATE = MathJax.ElementJax.STATE;
+ var script, prev, m = state.scripts.length;
+ try {
+ //
+ // Loop through the scripts
+ //
+ while (state.i < m) {
+ script = state.scripts[state.i]; if (!script) {state.i++; continue}
+ //
+ // Remove previous error marker, if any
+ //
+ prev = script.previousSibling;
+ if (prev && prev.className === "MathJax_Error") {prev.parentNode.removeChild(prev)}
+ //
+ // Check if already processed or needs processing
+ //
+ if (!script.parentNode || !script.MathJax || script.MathJax.state === STATE.PROCESSED) {state.i++; continue};
+ if (!script.MathJax.elementJax || script.MathJax.state === STATE.UPDATE) {
+ this.checkScriptSiblings(script); // remove preJax/postJax etc.
+ var type = script.type.replace(/ *;(.|\s)*/,""); // the input jax type
+ var input = this.inputJax[type]; // the input jax itself
+ jax = input.Process(script,state); // run the input jax
+ if (typeof jax === 'function') { // if a callback was returned
+ if (jax.called) continue; // go back and call Process() again
+ this.RestartAfter(jax); // wait for the callback
+ }
+ jax = jax.Attach(script,input.id); // register the jax on the script
+ this.saveScript(jax,state,script,STATE); // add script to state
+ this.postInputHooks.Execute(jax,input.id,script); // run global jax filters
+ } else if (script.MathJax.state === STATE.OUTPUT) {
+ this.saveScript(script.MathJax.elementJax,state,script,STATE); // add script to state
+ }
+ //
+ // Go on to the next script, and check if we need to update the processing message
+ //
+ state.i++; var now = new Date().getTime();
+ if (now - state.start > this.processUpdateTime && state.i < state.scripts.length)
+ {state.start = now; this.RestartAfter(MathJax.Callback.Delay(1))}
+ }
+ } catch (err) {return this.processError(err,state,"Input")}
+ //
+ // Put up final message, reset the state and return
+ //
+ if (state.scripts.length && this.config.showProcessingMessages)
+ {MathJax.Message.Set(["ProcessMath","Processing math: %1%%",100],0)}
+ state.start = new Date().getTime(); state.i = state.j = 0;
+ return null;
+ },
+ postInputHooks: MathJax.Callback.Hooks(true), // hooks to run after element jax is created
+ saveScript: function (jax,state,script,STATE) {
+ //
+ // Check that output jax exists
+ //
+ if (!this.outputJax[jax.mimeType]) {
+ script.MathJax.state = STATE.UPDATE;
+ throw Error("No output jax registered for "+jax.mimeType);
+ }
+ //
+ // Record the output jax
+ // and put this script in the queue for that jax
+ //
+ jax.outputJax = this.outputJax[jax.mimeType][0].id;
+ if (!state.jax[jax.outputJax]) {
+ if (state.jaxIDs.length === 0) {
+ // use original array until we know there are more (rather than two copies)
+ state.jax[jax.outputJax] = state.scripts;
+ } else {
+ if (state.jaxIDs.length === 1) // get the script so far for the existing jax
+ {state.jax[state.jaxIDs[0]] = state.scripts.slice(0,state.i)}
+ state.jax[jax.outputJax] = []; // start a new array for the new jax
+ }
+ state.jaxIDs.push(jax.outputJax); // save the ID of the jax
+ }
+ if (state.jaxIDs.length > 1) {state.jax[jax.outputJax].push(script)}
+ //
+ // Mark script as needing output
+ //
+ script.MathJax.state = STATE.OUTPUT;
+ },
+
+ //
+ // Pre- and post-process scripts by jax
+ // (to get scaling factors, hide/show output, and so on)
+ // Since this can cause the jax to load, we need to trap restarts
+ //
+ prepareOutput: function (state,method) {
+ while (state.j < state.jaxIDs.length) {
+ var id = state.jaxIDs[state.j], JAX = MathJax.OutputJax[id];
+ if (JAX[method]) {
+ try {
+ var result = JAX[method](state);
+ if (typeof result === 'function') {
+ if (result.called) continue; // go back and try again
+ this.RestartAfter(result);
+ }
+ } catch (err) {
+ if (!err.restart) {
+ MathJax.Message.Set(["PrepError","Error preparing %1 output (%2)",id,method],null,600);
+ MathJax.Hub.lastPrepError = err;
+ state.j++;
+ }
+ return MathJax.Callback.After(["prepareOutput",this,state,method],err.restart);
+ }
+ }
+ state.j++;
+ }
+ return null;
+ },
+
+ processOutput: function (state) {
+ var result, STATE = MathJax.ElementJax.STATE, script, m = state.scripts.length;
+ try {
+ //
+ // Loop through the scripts
+ //
+ while (state.i < m) {
+ //
+ // Check that there is an element jax
+ //
+ script = state.scripts[state.i];
+ if (!script || !script.parentNode || !script.MathJax || script.MathJax.error) {state.i++; continue}
+ var jax = script.MathJax.elementJax; if (!jax) {state.i++; continue}
+ //
+ // Call the output Jax's Process method (which will be its Translate()
+ // method once loaded). Mark it as complete and remove the preview unless
+ // the Process() call returns an explicit false value (in which case, it will
+ // handle this later during the postProcess phase, as HTML-CSS does).
+ //
+ result = MathJax.OutputJax[jax.outputJax].Process(script,state);
+ if (result !== false) {
+ script.MathJax.state = STATE.PROCESSED;
+ if (script.MathJax.preview) {
+ script.MathJax.preview.innerHTML = "";
+ script.MathJax.preview.style.display = "none";
+ }
+ //
+ // Signal that new math is available
+ //
+ this.signal.Post(["New Math",jax.inputID]); // FIXME: wait for this? (i.e., restart if returns uncalled callback)
+ }
+ //
+ // Go on to next math expression
+ //
+ state.i++;
+ //
+ // Update the processing message, if needed
+ //
+ var now = new Date().getTime();
+ if (now - state.start > this.processUpdateTime && state.i < state.scripts.length)
+ {state.start = now; this.RestartAfter(MathJax.Callback.Delay(this.processUpdateDelay))}
+ }
+ } catch (err) {return this.processError(err,state,"Output")}
+ //
+ // Put up the typesetting-complete message
+ //
+ if (state.scripts.length && this.config.showProcessingMessages) {
+ MathJax.Message.Set(["TypesetMath","Typesetting math: %1%%",100],0);
+ MathJax.Message.Clear(0);
+ }
+ state.i = state.j = 0;
+ return null;
+ },
+
+ processMessage: function (state,type) {
+ var m = Math.floor(state.i/(state.scripts.length)*100);
+ var message = (type === "Output" ? ["TypesetMath","Typesetting math: %1%%"] :
+ ["ProcessMath","Processing math: %1%%"]);
+ if (this.config.showProcessingMessages) {MathJax.Message.Set(message.concat(m),0)}
+ },
+
+ processError: function (err,state,type) {
+ if (!err.restart) {
+ if (!this.config.errorSettings.message) {throw err}
+ this.formatError(state.scripts[state.i],err); state.i++;
+ }
+ this.processMessage(state,type);
+ return MathJax.Callback.After(["process"+type,this,state],err.restart);
+ },
+
+ formatError: function (script,err) {
+ var LOCALIZE = function (id,text,arg1,arg2) {return MathJax.Localization._(id,text,arg1,arg2)};
+ //
+ // Get the error message, URL, and line, and save it for
+ // reporting in the Show Math As Error menu
+ //
+ var message = LOCALIZE("ErrorMessage","Error: %1",err.message)+"\n";
+ if (err.sourceURL||err.fileName) message += "\n"+LOCALIZE("ErrorFile","file: %1",err.sourceURL||err.fileName);
+ if (err.line||err.lineNumber) message += "\n"+LOCALIZE("ErrorLine","line: %1",err.line||err.lineNumber);
+ message += "\n\n"+LOCALIZE("ErrorTips","Debugging tips: use %1, inspect %2 in the browser console","'unpacked/MathJax.js'","'MathJax.Hub.lastError'");
+ script.MathJax.error = MathJax.OutputJax.Error.Jax(message,script);
+ if (script.MathJax.elementJax)
+ script.MathJax.error.inputID = script.MathJax.elementJax.inputID;
+ //
+ // Create the [Math Processing Error] span
+ //
+ var errorSettings = this.config.errorSettings;
+ var errorText = LOCALIZE(errorSettings.messageId,errorSettings.message);
+ var error = MathJax.HTML.Element("span", {
+ className:"MathJax_Error", jaxID:"Error", isMathJax:true,
+ id: script.MathJax.error.inputID+"-Frame"
+ },[["span",null,errorText]]);
+ //
+ // Attach the menu events
+ //
+ MathJax.Ajax.Require("[MathJax]/extensions/MathEvents.js",function () {
+ var EVENT = MathJax.Extension.MathEvents.Event,
+ HUB = MathJax.Hub;
+ error.oncontextmenu = EVENT.Menu;
+ error.onmousedown = EVENT.Mousedown;
+ error.onkeydown = EVENT.Keydown;
+ error.tabIndex = HUB.getTabOrder(HUB.getJaxFor(script));
+ });
+ //
+ // Insert the error into the page and remove any preview
+ //
+ var node = document.getElementById(error.id);
+ if (node) node.parentNode.removeChild(node);
+ if (script.parentNode) script.parentNode.insertBefore(error,script);
+ if (script.MathJax.preview) {
+ script.MathJax.preview.innerHTML = "";
+ script.MathJax.preview.style.display = "none";
+ }
+ //
+ // Save the error for debugging purposes
+ // Report the error as a signal
+ //
+ this.lastError = err;
+ this.signal.Post(["Math Processing Error",script,err]);
+ },
+
+ RestartAfter: function (callback) {
+ throw this.Insert(Error("restart"),{restart: MathJax.Callback(callback)});
+ },
+
+ elementCallback: function (element,callback) {
+ if (callback == null && (MathJax.Object.isArray(element) || typeof element === 'function'))
+ {try {MathJax.Callback(element); callback = element; element = null} catch(e) {}}
+ if (element == null) {element = this.config.elements || []}
+ if (this.isHTMLCollection(element)) {element = this.HTMLCollection2Array(element)}
+ if (!MathJax.Object.isArray(element)) {element = [element]}
+ element = [].concat(element); // make a copy so the original isn't changed
+ for (var i = 0, m = element.length; i < m; i++)
+ {if (typeof(element[i]) === 'string') {element[i] = document.getElementById(element[i])}}
+ if (!document.body) {document.body = document.getElementsByTagName("body")[0]}
+ if (element.length == 0) {element.push(document.body)}
+ if (!callback) {callback = {}}
+ return {
+ count: element.length,
+ elements: (element.length === 1 ? element[0] : element),
+ callback: callback
+ };
+ },
+
+ elementScripts: function (element) {
+ var scripts = [];
+ if (MathJax.Object.isArray(element) || this.isHTMLCollection(element)) {
+ for (var i = 0, m = element.length; i < m; i++) {
+ var alreadyDone = 0;
+ for (var j = 0; j < i && !alreadyDone; j++)
+ {alreadyDone = element[j].contains(element[i])}
+ if (!alreadyDone) scripts.push.apply(scripts,this.elementScripts(element[i]));
+ }
+ return scripts;
+ }
+ if (typeof(element) === 'string') {element = document.getElementById(element)}
+ if (!document.body) {document.body = document.getElementsByTagName("body")[0]}
+ if (element == null) {element = document.body}
+ if (element.tagName != null && element.tagName.toLowerCase() === "script") {return [element]}
+ scripts = element.getElementsByTagName("script");
+ if (this.msieHTMLCollectionBug) {scripts = this.HTMLCollection2Array(scripts)}
+ return scripts;
+ },
+
+ //
+ // IE8 fails to check "obj instanceof HTMLCollection" for some values of obj.
+ //
+ isHTMLCollection: function (obj) {
+ return ("HTMLCollection" in window && typeof(obj) === "object" && obj instanceof HTMLCollection);
+ },
+ //
+ // IE8 doesn't deal with HTMLCollection as an array, so convert to array
+ //
+ HTMLCollection2Array: function (nodes) {
+ if (!this.msieHTMLCollectionBug) {return [].slice.call(nodes)}
+ var NODES = [];
+ for (var i = 0, m = nodes.length; i < m; i++) {NODES[i] = nodes[i]}
+ return NODES;
+ },
+
+ Insert: function (dst,src) {
+ for (var id in src) {if (src.hasOwnProperty(id)) {
+ // allow for concatenation of arrays?
+ if (typeof src[id] === 'object' && !(MathJax.Object.isArray(src[id])) &&
+ (typeof dst[id] === 'object' || typeof dst[id] === 'function')) {
+ this.Insert(dst[id],src[id]);
+ } else {
+ dst[id] = src[id];
+ }
+ }}
+ return dst;
+ },
+
+ getTabOrder: function(script) {
+ return this.config.menuSettings.inTabOrder ? 0 : -1;
+ },
+
+ // Old browsers (e.g. Internet Explorer <= 8) do not support trim().
+ SplitList: ("trim" in String.prototype ?
+ function (list) {return list.trim().split(/\s+/)} :
+ function (list) {return list.replace(/^\s+/,'').
+ replace(/\s+$/,'').split(/\s+/)})
+};
+MathJax.Hub.Insert(MathJax.Hub.config.styles,MathJax.Message.styles);
+MathJax.Hub.Insert(MathJax.Hub.config.styles,{".MathJax_Error":MathJax.Hub.config.errorSettings.style});
+
+//
+// Storage area for extensions and preprocessors
+//
+MathJax.Extension = {};
+
+//
+// Hub Startup code
+//
+MathJax.Hub.Configured = MathJax.Callback({}); // called when configuration is complete
+MathJax.Hub.Startup = {
+ script: "", // the startup script from the SCRIPT call that loads MathJax.js
+ queue: MathJax.Callback.Queue(), // Queue used for startup actions
+ signal: MathJax.Callback.Signal("Startup"), // Signal used for startup events
+ params: {},
+
+ //
+ // Load the configuration files
+ //
+ Config: function () {
+ this.queue.Push(["Post",this.signal,"Begin Config"]);
+ //
+ // Make sure root is set before loading any files
+ //
+ if (MathJax.AuthorConfig && MathJax.AuthorConfig.root)
+ MathJax.Ajax.config.root = MathJax.AuthorConfig.root;
+ //
+ // If a locale is given as a parameter,
+ // set the locale and the default menu value for the locale
+ //
+ if (this.params.locale) {
+ MathJax.Localization.resetLocale(this.params.locale);
+ MathJax.Hub.config.menuSettings.locale = this.params.locale;
+ }
+ //
+ // Run the config files, if any are given in the parameter list
+ //
+ if (this.params.config) {
+ var files = this.params.config.split(/,/);
+ for (var i = 0, m = files.length; i < m; i++) {
+ if (!files[i].match(/\.js$/)) {files[i] += ".js"}
+ this.queue.Push(["Require",MathJax.Ajax,this.URL("config",files[i])]);
+ }
+ }
+ //
+ // Perform author configuration from in-line MathJax = {...}
+ //
+ this.queue.Push(["Config",MathJax.Hub,MathJax.AuthorConfig]);
+ //
+ // Run the deprecated configuration script, if any (ignoring return value)
+ // Wait for the startup delay signal
+ // Run the mathjax-config blocks
+ // Load the files in the configuration's config array
+ //
+ if (this.script.match(/\S/)) {this.queue.Push(this.script+";\n1;")}
+ this.queue.Push(
+ ["ConfigDelay",this],
+ ["ConfigBlocks",this],
+ [function (THIS) {return THIS.loadArray(MathJax.Hub.config.config,"config",null,true)},this],
+ ["Post",this.signal,"End Config"]
+ );
+ },
+ //
+ // Return the delay callback
+ //
+ ConfigDelay: function () {
+ var delay = this.params.delayStartupUntil || MathJax.Hub.config.delayStartupUntil;
+ if (delay === "onload") {return this.onload}
+ if (delay === "configured") {return MathJax.Hub.Configured}
+ return delay;
+ },
+ //
+ // Run the scripts of type=text/x-mathjax-config
+ //
+ ConfigBlocks: function () {
+ var scripts = document.getElementsByTagName("script");
+ var queue = MathJax.Callback.Queue();
+ for (var i = 0, m = scripts.length; i < m; i++) {
+ var type = String(scripts[i].type).replace(/ /g,"");
+ if (type.match(/^text\/x-mathjax-config(;.*)?$/) && !type.match(/;executed=true/)) {
+ scripts[i].type += ";executed=true";
+ queue.Push(scripts[i].innerHTML+";\n1;");
+ }
+ }
+ return queue.Push(function () {MathJax.Ajax.config.root = MathJax.Hub.config.root});
+ },
+
+ //
+ // Read cookie and set up menu defaults
+ // (set the locale according to the cookie)
+ // (adjust the jax to accommodate renderer preferences)
+ //
+ Cookie: function () {
+ return this.queue.Push(
+ ["Post",this.signal,"Begin Cookie"],
+ ["Get",MathJax.HTML.Cookie,"menu",MathJax.Hub.config.menuSettings],
+ [function (config) {
+ var SETTINGS = config.menuSettings;
+ if (SETTINGS.locale) MathJax.Localization.resetLocale(SETTINGS.locale);
+ var renderer = config.menuSettings.renderer, jax = config.jax;
+ if (renderer) {
+ var name = "output/"+renderer; jax.sort();
+ for (var i = 0, m = jax.length; i < m; i++) {
+ if (jax[i].substr(0,7) === "output/") break;
+ }
+ if (i == m-1) {jax.pop()} else {
+ while (i < m) {if (jax[i] === name) {jax.splice(i,1); break}; i++}
+ }
+ jax.unshift(name);
+ }
+ if (SETTINGS.CHTMLpreview != null) {
+ if (SETTINGS.FastPreview == null) SETTINGS.FastPreview = SETTINGS.CHTMLpreview;
+ delete SETTINGS.CHTMLpreview;
+ }
+ if (SETTINGS.FastPreview && !MathJax.Extension["fast-preview"])
+ MathJax.Hub.config.extensions.push("fast-preview.js");
+ if (config.menuSettings.assistiveMML && !MathJax.Extension.AssistiveMML)
+ MathJax.Hub.config.extensions.push("AssistiveMML.js");
+ },MathJax.Hub.config],
+ ["Post",this.signal,"End Cookie"]
+ );
+ },
+ //
+ // Setup stylesheets and extra styles
+ //
+ Styles: function () {
+ return this.queue.Push(
+ ["Post",this.signal,"Begin Styles"],
+ ["loadArray",this,MathJax.Hub.config.styleSheets,"config"],
+ ["Styles",MathJax.Ajax,MathJax.Hub.config.styles],
+ ["Post",this.signal,"End Styles"]
+ );
+ },
+ //
+ // Load the input and output jax
+ //
+ Jax: function () {
+ var config = MathJax.Hub.config, jax = MathJax.Hub.outputJax;
+ // Save the order of the output jax since they are loading asynchronously
+ for (var i = 0, m = config.jax.length, k = 0; i < m; i++) {
+ var name = config.jax[i].substr(7);
+ if (config.jax[i].substr(0,7) === "output/" && jax.order[name] == null)
+ {jax.order[name] = k; k++}
+ }
+ var queue = MathJax.Callback.Queue();
+ return queue.Push(
+ ["Post",this.signal,"Begin Jax"],
+ ["loadArray",this,config.jax,"jax","config.js"],
+ ["Post",this.signal,"End Jax"]
+ );
+ },
+ //
+ // Load the extensions
+ //
+ Extensions: function () {
+ var queue = MathJax.Callback.Queue();
+ return queue.Push(
+ ["Post",this.signal,"Begin Extensions"],
+ ["loadArray",this,MathJax.Hub.config.extensions,"extensions"],
+ ["Post",this.signal,"End Extensions"]
+ );
+ },
+
+ //
+ // Initialize the Message system
+ //
+ Message: function () {
+ MathJax.Message.Init(true);
+ },
+
+ //
+ // Set the math menu renderer, if it isn't already
+ // (this must come after the jax are loaded)
+ //
+ Menu: function () {
+ var menu = MathJax.Hub.config.menuSettings, jax = MathJax.Hub.outputJax, registered;
+ for (var id in jax) {if (jax.hasOwnProperty(id)) {
+ if (jax[id].length) {registered = jax[id]; break}
+ }}
+ if (registered && registered.length) {
+ if (menu.renderer && menu.renderer !== registered[0].id)
+ {registered.unshift(MathJax.OutputJax[menu.renderer])}
+ menu.renderer = registered[0].id;
+ }
+ },
+
+ //
+ // Set the location to the designated hash position
+ //
+ Hash: function () {
+ if (MathJax.Hub.config.positionToHash && document.location.hash &&
+ document.body && document.body.scrollIntoView) {
+ var name = document.location.hash.substr(1);
+ var target = document.getElementById(name);
+ if (!target) {
+ var a = document.getElementsByTagName("a");
+ for (var i = 0, m = a.length; i < m; i++)
+ {if (a[i].name === name) {target = a[i]; break}}
+ }
+ if (target) {
+ while (!target.scrollIntoView) {target = target.parentNode}
+ target = this.HashCheck(target);
+ if (target && target.scrollIntoView)
+ {setTimeout(function () {target.scrollIntoView(true)},1)}
+ }
+ }
+ },
+ HashCheck: function (target) {
+ var jax = MathJax.Hub.getJaxFor(target);
+ if (jax && MathJax.OutputJax[jax.outputJax].hashCheck)
+ {target = MathJax.OutputJax[jax.outputJax].hashCheck(target)}
+ return target;
+ },
+
+ //
+ // Load the Menu and Zoom code, if it hasn't already been loaded.
+ // This is called after the initial typeset, so should no longer be
+ // competing with other page loads, but will make these available
+ // if needed later on.
+ //
+ MenuZoom: function () {
+ if (MathJax.Hub.config.showMathMenu) {
+ if (!MathJax.Extension.MathMenu) {
+ setTimeout(
+ function () {
+ MathJax.Callback.Queue(
+ ["Require",MathJax.Ajax,"[MathJax]/extensions/MathMenu.js",{}],
+ ["loadDomain",MathJax.Localization,"MathMenu"]
+ )
+ },1000
+ );
+ } else {
+ setTimeout(
+ MathJax.Callback(["loadDomain",MathJax.Localization,"MathMenu"]),
+ 1000
+ );
+ }
+ if (!MathJax.Extension.MathZoom) {
+ setTimeout(
+ MathJax.Callback(["Require",MathJax.Ajax,"[MathJax]/extensions/MathZoom.js",{}]),
+ 2000
+ );
+ }
+ }
+ },
+
+ //
+ // Setup the onload callback
+ //
+ onLoad: function () {
+ var onload = this.onload =
+ MathJax.Callback(function () {MathJax.Hub.Startup.signal.Post("onLoad")});
+ if (document.body && document.readyState)
+ if (MathJax.Hub.Browser.isMSIE) {
+ // IE can change from loading to interactive before
+ // full page is ready, so go with complete (even though
+ // that means we may have to wait longer).
+ if (document.readyState === "complete") {return [onload]}
+ } else if (document.readyState !== "loading") {return [onload]}
+ if (window.addEventListener) {
+ window.addEventListener("load",onload,false);
+ if (!this.params.noDOMContentEvent)
+ {window.addEventListener("DOMContentLoaded",onload,false)}
+ }
+ else if (window.attachEvent) {window.attachEvent("onload",onload)}
+ else {window.onload = onload}
+ return onload;
+ },
+
+ //
+ // Perform the initial typesetting (or skip if configuration says to)
+ //
+ Typeset: function (element,callback) {
+ if (MathJax.Hub.config.skipStartupTypeset) {return function () {}}
+ return this.queue.Push(
+ ["Post",this.signal,"Begin Typeset"],
+ ["Typeset",MathJax.Hub,element,callback],
+ ["Post",this.signal,"End Typeset"]
+ );
+ },
+
+ //
+ // Create a URL in the MathJax hierarchy
+ //
+ URL: function (dir,name) {
+ if (!name.match(/^([a-z]+:\/\/|\[|\/)/)) {name = "[MathJax]/"+dir+"/"+name}
+ return name;
+ },
+
+ //
+ // Load an array of files, waiting for all of them
+ // to be loaded before going on
+ //
+ loadArray: function (files,dir,name,synchronous) {
+ if (files) {
+ if (!MathJax.Object.isArray(files)) {files = [files]}
+ if (files.length) {
+ var queue = MathJax.Callback.Queue(), callback = {}, file;
+ for (var i = 0, m = files.length; i < m; i++) {
+ file = this.URL(dir,files[i]);
+ if (name) {file += "/" + name}
+ if (synchronous) {queue.Push(["Require",MathJax.Ajax,file,callback])}
+ else {queue.Push(MathJax.Ajax.Require(file,callback))}
+ }
+ return queue.Push({}); // wait for everything to finish
+ }
+ }
+ return null;
+ }
+
+};
+
+
+/**********************************************************/
+
+(function (BASENAME) {
+ var BASE = window[BASENAME], ROOT = "["+BASENAME+"]";
+ var HUB = BASE.Hub, AJAX = BASE.Ajax, CALLBACK = BASE.Callback;
+
+ var JAX = MathJax.Object.Subclass({
+ JAXFILE: "jax.js",
+ require: null, // array of files to load before jax.js is complete
+ config: {},
+ //
+ // Make a subclass and return an instance of it.
+ // (FIXME: should we replace config with a copy of the constructor's
+ // config? Otherwise all subclasses share the same config structure.)
+ //
+ Init: function (def,cdef) {
+ if (arguments.length === 0) {return this}
+ return (this.constructor.Subclass(def,cdef))();
+ },
+ //
+ // Augment by merging with class definition (not replacing)
+ //
+ Augment: function (def,cdef) {
+ var cObject = this.constructor, ndef = {};
+ if (def != null) {
+ for (var id in def) {if (def.hasOwnProperty(id)) {
+ if (typeof def[id] === "function")
+ {cObject.protoFunction(id,def[id])} else {ndef[id] = def[id]}
+ }}
+ // MSIE doesn't list toString even if it is not native so handle it separately
+ if (def.toString !== cObject.prototype.toString && def.toString !== {}.toString)
+ {cObject.protoFunction('toString',def.toString)}
+ }
+ HUB.Insert(cObject.prototype,ndef);
+ cObject.Augment(null,cdef);
+ return this;
+ },
+ Translate: function (script,state) {
+ throw Error(this.directory+"/"+this.JAXFILE+" failed to define the Translate() method");
+ },
+ Register: function (mimetype) {},
+ Config: function () {
+ this.config = HUB.CombineConfig(this.id,this.config);
+ if (this.config.Augment) {this.Augment(this.config.Augment)}
+ },
+ Startup: function () {},
+ loadComplete: function (file) {
+ if (file === "config.js") {
+ return AJAX.loadComplete(this.directory+"/"+file);
+ } else {
+ var queue = CALLBACK.Queue();
+ queue.Push(
+ HUB.Register.StartupHook("End Config",{}), // wait until config complete
+ ["Post",HUB.Startup.signal,this.id+" Jax Config"],
+ ["Config",this],
+ ["Post",HUB.Startup.signal,this.id+" Jax Require"],
+ // Config may set the required and extensions array,
+ // so use functions to delay making the reference until needed
+ [function (THIS) {return MathJax.Hub.Startup.loadArray(THIS.require,this.directory)},this],
+ [function (config,id) {return MathJax.Hub.Startup.loadArray(config.extensions,"extensions/"+id)},this.config||{},this.id],
+ ["Post",HUB.Startup.signal,this.id+" Jax Startup"],
+ ["Startup",this],
+ ["Post",HUB.Startup.signal,this.id+" Jax Ready"]
+ );
+ if (this.copyTranslate) {
+ queue.Push(
+ [function (THIS) {
+ THIS.preProcess = THIS.preTranslate;
+ THIS.Process = THIS.Translate;
+ THIS.postProcess = THIS.postTranslate;
+ },this.constructor.prototype]
+ );
+ }
+ return queue.Push(["loadComplete",AJAX,this.directory+"/"+file]);
+ }
+ }
+ },{
+ id: "Jax",
+ version: "2.7.1",
+ directory: ROOT+"/jax",
+ extensionDir: ROOT+"/extensions"
+ });
+
+ /***********************************/
+
+ BASE.InputJax = JAX.Subclass({
+ elementJax: "mml", // the element jax to load for this input jax
+ sourceMenuTitle: /*_(MathMenu)*/ ["Original","Original Form"],
+ copyTranslate: true,
+ Process: function (script,state) {
+ var queue = CALLBACK.Queue(), file;
+ // Load any needed element jax
+ var jax = this.elementJax; if (!BASE.Object.isArray(jax)) {jax = [jax]}
+ for (var i = 0, m = jax.length; i < m; i++) {
+ file = BASE.ElementJax.directory+"/"+jax[i]+"/"+this.JAXFILE;
+ if (!this.require) {this.require = []}
+ else if (!BASE.Object.isArray(this.require)) {this.require = [this.require]};
+ this.require.push(file); // so Startup will wait for it to be loaded
+ queue.Push(AJAX.Require(file));
+ }
+ // Load the input jax
+ file = this.directory+"/"+this.JAXFILE;
+ var load = queue.Push(AJAX.Require(file));
+ if (!load.called) {
+ this.constructor.prototype.Process = function () {
+ if (!load.called) {return load}
+ throw Error(file+" failed to load properly");
+ }
+ }
+ // Load the associated output jax
+ jax = HUB.outputJax["jax/"+jax[0]];
+ if (jax) {queue.Push(AJAX.Require(jax[0].directory+"/"+this.JAXFILE))}
+ return queue.Push({});
+ },
+ needsUpdate: function (jax) {
+ var script = jax.SourceElement();
+ return (jax.originalText !== BASE.HTML.getScript(script));
+ },
+ Register: function (mimetype) {
+ if (!HUB.inputJax) {HUB.inputJax = {}}
+ HUB.inputJax[mimetype] = this;
+ }
+ },{
+ id: "InputJax",
+ version: "2.7.1",
+ directory: JAX.directory+"/input",
+ extensionDir: JAX.extensionDir
+ });
+
+ /***********************************/
+
+ BASE.OutputJax = JAX.Subclass({
+ copyTranslate: true,
+ preProcess: function (state) {
+ var load, file = this.directory+"/"+this.JAXFILE;
+ this.constructor.prototype.preProcess = function (state) {
+ if (!load.called) {return load}
+ throw Error(file+" failed to load properly");
+ }
+ load = AJAX.Require(file);
+ return load;
+ },
+ Register: function (mimetype) {
+ var jax = HUB.outputJax;
+ if (!jax[mimetype]) {jax[mimetype] = []}
+ // If the output jax is earlier in the original configuration list, put it first here
+ if (jax[mimetype].length && (this.id === HUB.config.menuSettings.renderer ||
+ (jax.order[this.id]||0) < (jax.order[jax[mimetype][0].id]||0)))
+ {jax[mimetype].unshift(this)} else {jax[mimetype].push(this)}
+ // Make sure the element jax is loaded before Startup is called
+ if (!this.require) {this.require = []}
+ else if (!BASE.Object.isArray(this.require)) {this.require = [this.require]};
+ this.require.push(BASE.ElementJax.directory+"/"+(mimetype.split(/\//)[1])+"/"+this.JAXFILE);
+ },
+ Remove: function (jax) {}
+ },{
+ id: "OutputJax",
+ version: "2.7.1",
+ directory: JAX.directory+"/output",
+ extensionDir: JAX.extensionDir,
+ fontDir: ROOT+(BASE.isPacked?"":"/..")+"/fonts",
+ imageDir: ROOT+(BASE.isPacked?"":"/..")+"/images"
+ });
+
+ /***********************************/
+
+ BASE.ElementJax = JAX.Subclass({
+ // make a subclass, not an instance
+ Init: function (def,cdef) {return this.constructor.Subclass(def,cdef)},
+
+ inputJax: null,
+ outputJax: null,
+ inputID: null,
+ originalText: "",
+ mimeType: "",
+ sourceMenuTitle: /*_(MathMenu)*/ ["MathMLcode","MathML Code"],
+
+ Text: function (text,callback) {
+ var script = this.SourceElement();
+ BASE.HTML.setScript(script,text);
+ script.MathJax.state = this.STATE.UPDATE;
+ return HUB.Update(script,callback);
+ },
+ Reprocess: function (callback) {
+ var script = this.SourceElement();
+ script.MathJax.state = this.STATE.UPDATE;
+ return HUB.Reprocess(script,callback);
+ },
+ Update: function (callback) {return this.Rerender(callback)},
+ Rerender: function (callback) {
+ var script = this.SourceElement();
+ script.MathJax.state = this.STATE.OUTPUT;
+ return HUB.Process(script,callback);
+ },
+ Remove: function (keep) {
+ if (this.hover) {this.hover.clear(this)}
+ BASE.OutputJax[this.outputJax].Remove(this);
+ if (!keep) {
+ HUB.signal.Post(["Remove Math",this.inputID]); // wait for this to finish?
+ this.Detach();
+ }
+ },
+ needsUpdate: function () {
+ return BASE.InputJax[this.inputJax].needsUpdate(this);
+ },
+
+ SourceElement: function () {return document.getElementById(this.inputID)},
+
+ Attach: function (script,inputJax) {
+ var jax = script.MathJax.elementJax;
+ if (script.MathJax.state === this.STATE.UPDATE) {
+ jax.Clone(this);
+ } else {
+ jax = script.MathJax.elementJax = this;
+ if (script.id) {this.inputID = script.id}
+ else {script.id = this.inputID = BASE.ElementJax.GetID(); this.newID = 1}
+ }
+ jax.originalText = BASE.HTML.getScript(script);
+ jax.inputJax = inputJax;
+ if (jax.root) {jax.root.inputID = jax.inputID}
+ return jax;
+ },
+ Detach: function () {
+ var script = this.SourceElement(); if (!script) return;
+ try {delete script.MathJax} catch(err) {script.MathJax = null}
+ if (this.newID) {script.id = ""}
+ },
+ Clone: function (jax) {
+ var id;
+ for (id in this) {
+ if (!this.hasOwnProperty(id)) continue;
+ if (typeof(jax[id]) === 'undefined' && id !== 'newID') {delete this[id]}
+ }
+ for (id in jax) {
+ if (!jax.hasOwnProperty(id)) continue;
+ if (typeof(this[id]) === 'undefined' || (this[id] !== jax[id] && id !== 'inputID'))
+ {this[id] = jax[id]}
+ }
+ }
+ },{
+ id: "ElementJax",
+ version: "2.7.1",
+ directory: JAX.directory+"/element",
+ extensionDir: JAX.extensionDir,
+ ID: 0, // jax counter (for IDs)
+ STATE: {
+ PENDING: 1, // script is identified as math but not yet processed
+ PROCESSED: 2, // script has been processed
+ UPDATE: 3, // elementJax should be updated
+ OUTPUT: 4 // output should be updated (input is OK)
+ },
+
+ GetID: function () {this.ID++; return "MathJax-Element-"+this.ID},
+ Subclass: function () {
+ var obj = JAX.Subclass.apply(this,arguments);
+ obj.loadComplete = this.prototype.loadComplete;
+ return obj;
+ }
+ });
+ BASE.ElementJax.prototype.STATE = BASE.ElementJax.STATE;
+
+ //
+ // Some "Fake" jax used to allow menu access for "Math Processing Error" messages
+ //
+ BASE.OutputJax.Error = {
+ id: "Error", version: "2.7.1", config: {}, errors: 0,
+ ContextMenu: function () {return BASE.Extension.MathEvents.Event.ContextMenu.apply(BASE.Extension.MathEvents.Event,arguments)},
+ Mousedown: function () {return BASE.Extension.MathEvents.Event.AltContextMenu.apply(BASE.Extension.MathEvents.Event,arguments)},
+ getJaxFromMath: function (math) {return (math.nextSibling.MathJax||{}).error},
+ Jax: function (text,script) {
+ var jax = MathJax.Hub.inputJax[script.type.replace(/ *;(.|\s)*/,"")];
+ this.errors++;
+ return {
+ inputJax: (jax||{id:"Error"}).id, // Use Error InputJax as fallback
+ outputJax: "Error",
+ inputID: "MathJax-Error-"+this.errors,
+ sourceMenuTitle: /*_(MathMenu)*/ ["ErrorMessage","Error Message"],
+ sourceMenuFormat: "Error",
+ originalText: MathJax.HTML.getScript(script),
+ errorText: text
+ }
+ }
+ };
+ BASE.InputJax.Error = {
+ id: "Error", version: "2.7.1", config: {},
+ sourceMenuTitle: /*_(MathMenu)*/ ["Original","Original Form"]
+ };
+
+})("MathJax");
+
+/**********************************************************/
+
+(function (BASENAME) {
+ var BASE = window[BASENAME];
+ if (!BASE) {BASE = window[BASENAME] = {}}
+
+ var HUB = BASE.Hub; var STARTUP = HUB.Startup; var CONFIG = HUB.config;
+ var HEAD = document.head || (document.getElementsByTagName("head")[0]);
+ if (!HEAD) {HEAD = document.childNodes[0]};
+ var scripts = (document.documentElement || document).getElementsByTagName("script");
+ if (scripts.length === 0 && HEAD.namespaceURI)
+ scripts = document.getElementsByTagNameNS(HEAD.namespaceURI,"script");
+ var namePattern = new RegExp("(^|/)"+BASENAME+"\\.js(\\?.*)?$");
+ for (var i = scripts.length-1; i >= 0; i--) {
+ if ((scripts[i].src||"").match(namePattern)) {
+ STARTUP.script = scripts[i].innerHTML;
+ if (RegExp.$2) {
+ var params = RegExp.$2.substr(1).split(/\&/);
+ for (var j = 0, m = params.length; j < m; j++) {
+ var KV = params[j].match(/(.*)=(.*)/);
+ if (KV) {STARTUP.params[unescape(KV[1])] = unescape(KV[2])}
+ else {STARTUP.params[params[j]] = true}
+ }
+ }
+ CONFIG.root = scripts[i].src.replace(/(^|\/)[^\/]*(\?.*)?$/,'');
+ BASE.Ajax.config.root = CONFIG.root;
+ BASE.Ajax.params = STARTUP.params;
+ break;
+ }
+ }
+
+ var AGENT = navigator.userAgent;
+ var BROWSERS = {
+ isMac: (navigator.platform.substr(0,3) === "Mac"),
+ isPC: (navigator.platform.substr(0,3) === "Win"),
+ isMSIE: ("ActiveXObject" in window && "clipboardData" in window),
+ isEdge: ("MSGestureEvent" in window && "chrome" in window &&
+ window.chrome.loadTimes == null),
+ isFirefox: (!!AGENT.match(/Gecko\//) && !AGENT.match(/like Gecko/)),
+ isSafari: (!!AGENT.match(/ (Apple)?WebKit\//) && !AGENT.match(/ like iPhone /) &&
+ (!window.chrome || window.chrome.app == null)),
+ isChrome: ("chrome" in window && window.chrome.loadTimes != null),
+ isOpera: ("opera" in window && window.opera.version != null),
+ isKonqueror: ("konqueror" in window && navigator.vendor == "KDE"),
+ versionAtLeast: function (v) {
+ var bv = (this.version).split('.'); v = (new String(v)).split('.');
+ for (var i = 0, m = v.length; i < m; i++)
+ {if (bv[i] != v[i]) {return parseInt(bv[i]||"0") >= parseInt(v[i])}}
+ return true;
+ },
+ Select: function (choices) {
+ var browser = choices[HUB.Browser];
+ if (browser) {return browser(HUB.Browser)}
+ return null;
+ }
+ };
+
+ var xAGENT = AGENT
+ .replace(/^Mozilla\/(\d+\.)+\d+ /,"") // remove initial Mozilla, which is never right
+ .replace(/[a-z][-a-z0-9._: ]+\/\d+[^ ]*-[^ ]*\.([a-z][a-z])?\d+ /i,"") // remove linux version
+ .replace(/Gentoo |Ubuntu\/(\d+\.)*\d+ (\([^)]*\) )?/,""); // special case for these
+
+ HUB.Browser = HUB.Insert(HUB.Insert(new String("Unknown"),{version: "0.0"}),BROWSERS);
+ for (var browser in BROWSERS) {if (BROWSERS.hasOwnProperty(browser)) {
+ if (BROWSERS[browser] && browser.substr(0,2) === "is") {
+ browser = browser.slice(2);
+ if (browser === "Mac" || browser === "PC") continue;
+ HUB.Browser = HUB.Insert(new String(browser),BROWSERS);
+ var VERSION = new RegExp(
+ ".*(Version/| Trident/.*; rv:)((?:\\d+\\.)+\\d+)|" + // for Safari, Opera10, and IE11+
+ ".*("+browser+")"+(browser == "MSIE" ? " " : "/")+"((?:\\d+\\.)*\\d+)|"+ // for one of the main browsers
+ "(?:^|\\(| )([a-z][-a-z0-9._: ]+|(?:Apple)?WebKit)/((?:\\d+\\.)+\\d+)"); // for unrecognized browser
+ var MATCH = VERSION.exec(xAGENT) || ["","","","unknown","0.0"];
+ HUB.Browser.name = (MATCH[1] != "" ? browser : (MATCH[3] || MATCH[5]));
+ HUB.Browser.version = MATCH[2] || MATCH[4] || MATCH[6];
+ break;
+ }
+ }};
+
+ //
+ // Initial browser-specific info (e.g., touch up version or name, check for MathPlayer, etc.)
+ // Wrap in try/catch just in case of error (see issue #1155).
+ //
+ try {HUB.Browser.Select({
+ Safari: function (browser) {
+ var v = parseInt((String(browser.version).split("."))[0]);
+ if (v > 85) {browser.webkit = browser.version}
+ if (v >= 538) {browser.version = "8.0"}
+ else if (v >= 537) {browser.version = "7.0"}
+ else if (v >= 536) {browser.version = "6.0"}
+ else if (v >= 534) {browser.version = "5.1"}
+ else if (v >= 533) {browser.version = "5.0"}
+ else if (v >= 526) {browser.version = "4.0"}
+ else if (v >= 525) {browser.version = "3.1"}
+ else if (v > 500) {browser.version = "3.0"}
+ else if (v > 400) {browser.version = "2.0"}
+ else if (v > 85) {browser.version = "1.0"}
+ browser.webkit = (navigator.appVersion.match(/WebKit\/(\d+)\./))[1];
+ browser.isMobile = (navigator.appVersion.match(/Mobile/i) != null);
+ browser.noContextMenu = browser.isMobile;
+ },
+ Firefox: function (browser) {
+ if ((browser.version === "0.0" || AGENT.match(/Firefox/) == null) &&
+ navigator.product === "Gecko") {
+ var rv = AGENT.match(/[\/ ]rv:(\d+\.\d.*?)[\) ]/);
+ if (rv) {browser.version = rv[1]}
+ else {
+ var date = (navigator.buildID||navigator.productSub||"0").substr(0,8);
+ if (date >= "20111220") {browser.version = "9.0"}
+ else if (date >= "20111120") {browser.version = "8.0"}
+ else if (date >= "20110927") {browser.version = "7.0"}
+ else if (date >= "20110816") {browser.version = "6.0"}
+ else if (date >= "20110621") {browser.version = "5.0"}
+ else if (date >= "20110320") {browser.version = "4.0"}
+ else if (date >= "20100121") {browser.version = "3.6"}
+ else if (date >= "20090630") {browser.version = "3.5"}
+ else if (date >= "20080617") {browser.version = "3.0"}
+ else if (date >= "20061024") {browser.version = "2.0"}
+ }
+ }
+ browser.isMobile = (navigator.appVersion.match(/Android/i) != null ||
+ AGENT.match(/ Fennec\//) != null ||
+ AGENT.match(/Mobile/) != null);
+ },
+ Chrome: function (browser) {
+ browser.noContextMenu = browser.isMobile = !!navigator.userAgent.match(/ Mobile[ \/]/);
+ },
+ Opera: function (browser) {browser.version = opera.version()},
+ Edge: function (browser) {
+ browser.isMobile = !!navigator.userAgent.match(/ Phone/);
+ },
+ MSIE: function (browser) {
+ browser.isMobile = !!navigator.userAgent.match(/ Phone/);
+ browser.isIE9 = !!(document.documentMode && (window.performance || window.msPerformance));
+ MathJax.HTML.setScriptBug = !browser.isIE9 || document.documentMode < 9;
+ MathJax.Hub.msieHTMLCollectionBug = (document.documentMode < 9);
+ //
+ // MathPlayer doesn't function properly in IE10, and not at all in IE11,
+ // so don't even try to load it.
+ //
+ if (document.documentMode < 10 && !STARTUP.params.NoMathPlayer) {
+ try {
+ new ActiveXObject("MathPlayer.Factory.1");
+ browser.hasMathPlayer = true;
+ } catch (err) {}
+ try {
+ if (browser.hasMathPlayer) {
+ var mathplayer = document.createElement("object");
+ mathplayer.id = "mathplayer"; mathplayer.classid = "clsid:32F66A20-7614-11D4-BD11-00104BD3F987";
+ HEAD.appendChild(mathplayer);
+ document.namespaces.add("m","http://www.w3.org/1998/Math/MathML");
+ browser.mpNamespace = true;
+ if (document.readyState && (document.readyState === "loading" ||
+ document.readyState === "interactive")) {
+ document.write('');
+ browser.mpImported = true;
+ }
+ } else {
+ // Adding any namespace avoids a crash in IE9 in IE9-standards mode
+ // (any reference to document.namespaces before document.readyState is
+ // "complete" causes an "unspecified error" to be thrown)
+ document.namespaces.add("mjx_IE_fix","http://www.w3.org/1999/xlink");
+ }
+ } catch (err) {}
+ }
+ }
+ });} catch (err) {
+ console.error(err.message);
+ }
+ HUB.Browser.Select(MathJax.Message.browsers);
+
+ if (BASE.AuthorConfig && typeof BASE.AuthorConfig.AuthorInit === "function") {BASE.AuthorConfig.AuthorInit()}
+ HUB.queue = BASE.Callback.Queue();
+ HUB.queue.Push(
+ ["Post",STARTUP.signal,"Begin"],
+ ["Config",STARTUP],
+ ["Cookie",STARTUP],
+ ["Styles",STARTUP],
+ ["Message",STARTUP],
+ function () {
+ // Do Jax and Extensions in parallel, but wait for them all to complete
+ var queue = BASE.Callback.Queue(
+ STARTUP.Jax(),
+ STARTUP.Extensions()
+ );
+ return queue.Push({});
+ },
+ ["Menu",STARTUP],
+ STARTUP.onLoad(),
+ function () {MathJax.isReady = true}, // indicates that MathJax is ready to process math
+ ["Typeset",STARTUP],
+ ["Hash",STARTUP],
+ ["MenuZoom",STARTUP],
+ ["Post",STARTUP.signal,"End"]
+ );
+
+})("MathJax");
+
+}}
diff --git a/_static/scipy-mathjax/README.md b/_static/scipy-mathjax/README.md
new file mode 100644
index 000000000..749d885ca
--- /dev/null
+++ b/_static/scipy-mathjax/README.md
@@ -0,0 +1,11 @@
+# scipy-mathjax
+
+Scipy-variant of stripped-down Mathjax.
+
+Only keep TeX-AMS input with SVG + stix-web output.
+
+Run rebuild.sh to rebuild the files.
+
+Note that this requires node.js npm being available.
+
+Based on https://github.com/mathjax/MathJax-grunt-cleaner.git
diff --git a/_static/scipy-mathjax/config/scipy-mathjax.js b/_static/scipy-mathjax/config/scipy-mathjax.js
new file mode 100644
index 000000000..cfe5df781
--- /dev/null
+++ b/_static/scipy-mathjax/config/scipy-mathjax.js
@@ -0,0 +1,24 @@
+/*************************************************************
+ *
+ * /MathJax/unpacked/config/TeX-AMS_SVG.js
+ *
+ * Copyright (c) 2010-2017 The MathJax Consortium
+ *
+ * Part of the MathJax library.
+ * See http://www.mathjax.org for details.
+ *
+ * Licensed under the Apache License, Version 2.0;
+ * you may not use this file except in compliance with the License.
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+MathJax.Hub.Config({
+ extensions: ["tex2jax.js","toMathML.js","TeX/noErrors.js","TeX/noUndefined.js","TeX/AMSmath.js","TeX/AMSsymbols.js","fast-preview.js","AssistiveMML.js","[a11y]/accessibility-menu.js"],
+ jax: ["input/TeX","output/SVG","output/PreviewHTML"],
+ showProcessingMessages: false,
+ showMathMenu: false,
+ messageStyle: "none"
+});
+
+MathJax.Ajax.loadComplete("[MathJax]/config/scipy-mathjax.js");
diff --git a/_static/scipy-mathjax/extensions/AssistiveMML.js b/_static/scipy-mathjax/extensions/AssistiveMML.js
new file mode 100644
index 000000000..266dd2b52
--- /dev/null
+++ b/_static/scipy-mathjax/extensions/AssistiveMML.js
@@ -0,0 +1,161 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/AssistiveMML.js
+ *
+ * Implements an extension that inserts hidden MathML into the
+ * page for screen readers or other asistive technology.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2015-2017 The MathJax Consortium
+ *
+ * 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.
+ */
+
+(function (AJAX,CALLBACK,HUB,HTML) {
+ var SETTINGS = HUB.config.menuSettings;
+
+ var AssistiveMML = MathJax.Extension["AssistiveMML"] = {
+ version: "2.7.1",
+
+ config: HUB.CombineConfig("AssistiveMML",{
+ disabled: false,
+ styles: {
+ ".MJX_Assistive_MathML": {
+ position:"absolute!important",
+ top: 0, left: 0,
+ clip: (HUB.Browser.isMSIE && (document.documentMode||0) < 8 ?
+ "rect(1px 1px 1px 1px)" : "rect(1px, 1px, 1px, 1px)"),
+ padding: "1px 0 0 0!important",
+ border: "0!important",
+ height: "1px!important",
+ width: "1px!important",
+ overflow: "hidden!important",
+ display:"block!important",
+ //
+ // Don't allow the assistive MathML become part of the selection
+ //
+ "-webkit-touch-callout": "none",
+ "-webkit-user-select": "none",
+ "-khtml-user-select": "none",
+ "-moz-user-select": "none",
+ "-ms-user-select": "none",
+ "user-select": "none"
+ },
+ ".MJX_Assistive_MathML.MJX_Assistive_MathML_Block": {
+ width: "100%!important"
+ }
+ }
+ }),
+
+ Config: function () {
+ if (!this.config.disabled && SETTINGS.assistiveMML == null)
+ HUB.Config({menuSettings:{assistiveMML:true}});
+ AJAX.Styles(this.config.styles);
+ HUB.Register.MessageHook("End Math",function (msg) {
+ if (SETTINGS.assistiveMML) return AssistiveMML.AddAssistiveMathML(msg[1])
+ });
+ },
+
+ //
+ // This sets up a state object that lists the jax and index into the jax,
+ // and a dummy callback that is used to synchronizing with MathJax.
+ // It will be called when the jax are all processed, and that will
+ // let the MathJax queue continue (it will block until then).
+ //
+ AddAssistiveMathML: function (node) {
+ var state = {
+ jax: HUB.getAllJax(node), i: 0,
+ callback: MathJax.Callback({})
+ };
+ this.HandleMML(state);
+ return state.callback;
+ },
+
+ //
+ // This removes the data-mathml attribute and the assistive MathML from
+ // all the jax.
+ //
+ RemoveAssistiveMathML: function (node) {
+ var jax = HUB.getAllJax(node), frame;
+ for (var i = 0, m = jax.length; i < m; i++) {
+ frame = document.getElementById(jax[i].inputID+"-Frame");
+ if (frame && frame.getAttribute("data-mathml")) {
+ frame.removeAttribute("data-mathml");
+ if (frame.lastChild && frame.lastChild.className.match(/MJX_Assistive_MathML/))
+ frame.removeChild(frame.lastChild);
+ }
+ }
+ },
+
+ //
+ // For each jax in the state, look up the frame.
+ // If the jax doesn't use NativeMML and hasn't already been handled:
+ // Get the MathML for the jax, taking resets into account.
+ // Add a data-mathml attribute to the frame, and
+ // Create a span that is not visible on screen and put the MathML in it,
+ // and add it to the frame.
+ // When all the jax are processed, call the callback.
+ //
+ HandleMML: function (state) {
+ var m = state.jax.length, jax, mml, frame, span;
+ while (state.i < m) {
+ jax = state.jax[state.i];
+ frame = document.getElementById(jax.inputID+"-Frame");
+ if (jax.outputJax !== "NativeMML" && jax.outputJax !== "PlainSource" &&
+ frame && !frame.getAttribute("data-mathml")) {
+ try {
+ mml = jax.root.toMathML("").replace(/\n */g,"").replace(//g,"");
+ } catch (err) {
+ if (!err.restart) throw err; // an actual error
+ return MathJax.Callback.After(["HandleMML",this,state],err.restart);
+ }
+ frame.setAttribute("data-mathml",mml);
+ span = HTML.addElement(frame,"span",{
+ isMathJax: true, unselectable: "on",
+ className: "MJX_Assistive_MathML"
+ + (jax.root.Get("display") === "block" ? " MJX_Assistive_MathML_Block" : "")
+ });
+ try {span.innerHTML = mml} catch (err) {}
+ frame.style.position = "relative";
+ frame.setAttribute("role","presentation");
+ frame.firstChild.setAttribute("aria-hidden","true");
+ span.setAttribute("role","presentation");
+ }
+ state.i++;
+ }
+ state.callback();
+ }
+
+ };
+
+ HUB.Startup.signal.Post("AssistiveMML Ready");
+
+})(MathJax.Ajax,MathJax.Callback,MathJax.Hub,MathJax.HTML);
+
+//
+// Make sure the toMathML extension is loaded before we signal
+// the load complete for this extension. Then wait for the end
+// of the user configuration before configuring this extension.
+//
+MathJax.Callback.Queue(
+ ["Require",MathJax.Ajax,"[MathJax]/extensions/toMathML.js"],
+ ["loadComplete",MathJax.Ajax,"[MathJax]/extensions/AssistiveMML.js"],
+ function () {
+ MathJax.Hub.Register.StartupHook("End Config",["Config",MathJax.Extension.AssistiveMML]);
+ }
+);
+
diff --git a/_static/scipy-mathjax/extensions/CHTML-preview.js b/_static/scipy-mathjax/extensions/CHTML-preview.js
new file mode 100644
index 000000000..84d555170
--- /dev/null
+++ b/_static/scipy-mathjax/extensions/CHTML-preview.js
@@ -0,0 +1,30 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/CHTML-preview.js
+ *
+ * Backward compatibility with old CHTML-preview extension.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2014-2017 The MathJax Consortium
+ *
+ * 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.
+ */
+
+MathJax.Callback.Queue(
+ ["Require",MathJax.Ajax,"[MathJax]/extensions/fast-preview.js"],
+ ["loadComplete",MathJax.Ajax,"[MathJax]/extensions/CHTML-preview.js"]
+);
diff --git a/_static/scipy-mathjax/extensions/FontWarnings.js b/_static/scipy-mathjax/extensions/FontWarnings.js
new file mode 100644
index 000000000..e531dcd6b
--- /dev/null
+++ b/_static/scipy-mathjax/extensions/FontWarnings.js
@@ -0,0 +1,313 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/FontWarnings.js
+ *
+ * Implements a font warning message window that appears when
+ * the image fonts, no fonts, or web fonts are used, informing
+ * the user where to download the fonts, or to update to a more
+ * modern browser. The window will fade out automatically after
+ * a time, and the user can dismiss it by a close box.
+ *
+ * To include font warning messages, add "FontWarnings.js" to the
+ * extensions array in your MathJax configuration.
+ *
+ * You can customize the warning messages in a number of ways. Use the
+ * FontWarnings section of the configuration to specify any of the items
+ * shown in the CONFIG variable below. These include
+ *
+ * messageStyle the style to apply to the warning box that is
+ * displayed when MathJax uses one of its fallback
+ * methods.
+ *
+ * removeAfter the amount of time to show the warning message (in ms)
+ * fadeoutTime how long the message should take to fade out
+ * fadeoutSteps how many separate steps to use during the fade out
+ * (set to 0 to use no fadeout and simply remove the window)
+ *
+ * Messages stores the descriptions of the messages to use for the
+ * various warnings (webFonts, imageFonts, and noFonts).
+ * These are arrays of strings to be inserted into the window,
+ * or identifiers within brackets, which refer to the HTML
+ * snippets in the HTML section described below. To disable a
+ * specific message, set its value to null (see example below).
+ *
+ * HTML stores snippets of HTML descriptions for various
+ * common parts of the error messages. These include
+ * the closeBox, the message about web fonts being available
+ * in modern browser, and messages about downloadable fonts.
+ * The STIX and TeX font messages are used when only one
+ * of these is in the availableFonts list. The data for these
+ * are arrays of either strings to include or a description of
+ * an HTML item enclosed in square brackets. That description
+ * has (up to) three parts: the name of the tag to be included,
+ * a list (enclosed in braces) of attributes and their values
+ * to be set on the tag (optional), and an array of the contents
+ * of the tag (optional). See the definitions below for examples.
+ *
+ * For example,
+ *
+ * MathJax.Hub.Config({
+ * ...
+ * extensions: ["FontWarnings.js"],
+ * FontWarnings: {
+ * removeAfter: 20*1000, // 20 seconds
+ * messageStyle: {
+ * border: "2px solid black",
+ * padding: "2em"
+ * },
+ * Message: {
+ * webFont: null // no webfont messages (only image and no fonts)
+ * }
+ * }
+ * });
+ *
+ * would extend the time the message is displayed from 12 seconds to 20,
+ * and changes the border to a solid black one, with 2em of padding
+ * rather than the default of 1em.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2010-2017 The MathJax Consortium
+ *
+ * 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.
+ */
+
+(function (HUB,HTML) {
+ var VERSION = "2.7.1";
+
+ var STIXURL = "http://www.stixfonts.org/";
+ var MATHJAXURL = "https://github.com/mathjax/MathJax/tree/master/fonts/HTML-CSS/TeX/otf";
+
+ var CONFIG = HUB.CombineConfig("FontWarnings",{
+ //
+ // The CSS for the message window
+ //
+ messageStyle: {
+ position:"fixed", bottom:"4em", left:"3em", width:"40em",
+ border: "3px solid #880000", "background-color": "#E0E0E0", color: "black",
+ padding: "1em", "font-size":"small", "white-space":"normal",
+
+ "border-radius": ".75em", // Opera 10.5 and IE9
+ "-webkit-border-radius": ".75em", // Safari and Chrome
+ "-moz-border-radius": ".75em", // Firefox
+ "-khtml-border-radius": ".75em", // Konqueror
+
+ "box-shadow": "4px 4px 10px #AAAAAA", // Opera 10.5 and IE9
+ "-webkit-box-shadow": "4px 4px 10px #AAAAAA", // Safari 3 and Chrome
+ "-moz-box-shadow": "4px 4px 10px #AAAAAA", // Forefox 3.5
+ "-khtml-box-shadow": "4px 4px 10px #AAAAAA", // Konqueror
+ filter: "progid:DXImageTransform.Microsoft.dropshadow(OffX=3, OffY=3, Color='gray', Positive='true')" // IE
+ },
+
+ //
+ // The messages for the various situations
+ //
+ Message: {
+
+ webFont: [
+ ["closeBox"],
+ ["webFont",
+ "MathJax is using web-based fonts to display the mathematics "+
+ "on this page. These take time to download, so the page would "+
+ "render faster if you installed math fonts directly in your "+
+ "system's font folder."],
+ ["fonts"]
+ ],
+
+ imageFonts: [
+ ["closeBox"],
+ ["imageFonts",
+ "MathJax is using its image fonts rather than local or web-based fonts. "+
+ "This will render slower than usual, and the mathematics may not print "+
+ "at the full resolution of your printer."],
+ ["fonts"],
+ ["webFonts"]
+ ],
+
+ noFonts: [
+ ["closeBox"],
+ ["noFonts",
+ "MathJax is unable to locate a font to use to display "+
+ "its mathematics, and image fonts are not available, so it "+
+ "is falling back on generic unicode characters in hopes that "+
+ "your browser will be able to display them. Some characters "+
+ "may not show up properly, or possibly not at all."],
+ ["fonts"],
+ ["webFonts"]
+ ]
+ },
+
+ //
+ // HTML objects that can be referred to in the message definitions
+ //
+ HTML: {
+ //
+ // The definition of the close box
+ //
+ closeBox: [[
+ "div",{
+ style: {
+ position:"absolute", overflow:"hidden", top:".1em", right:".1em",
+ border: "1px outset", width:"1em", height:"1em",
+ "text-align": "center", cursor: "pointer",
+ "background-color": "#EEEEEE", color:"#606060",
+
+ "border-radius": ".5em", // Opera 10.5
+ "-webkit-border-radius": ".5em", // Safari and Chrome
+ "-moz-border-radius": ".5em", // Firefox
+ "-khtml-border-radius": ".5em" // Konqueror
+ },
+ onclick: function () {
+ if (DATA.div && DATA.fade === 0)
+ {if (DATA.timer) {clearTimeout(DATA.timer)}; DATA.div.style.display = "none"}
+ }
+ },
+ [["span",{style:{position:"relative", bottom:".2em"}},["x"]]]
+ ]],
+
+ webFonts: [
+ ["p"],
+ ["webFonts",
+ "Most modern browsers allow for fonts to be downloaded over the web. "+
+ "Updating to a more recent version of your browser (or changing "+
+ "browsers) could improve the quality of the mathematics on this page."
+ ]
+ ],
+
+ fonts: [
+ ["p"],
+ ["fonts",
+ "MathJax can use either the [STIX fonts](%1) or the [MathJax TeX fonts](%2). " +
+ "Download and install one of those fonts to improve your MathJax experience.",
+ STIXURL,MATHJAXURL
+ ]
+ ],
+
+ STIXfonts: [
+ ["p"],
+ ["STIXPage",
+ "This page is designed to use the [STIX fonts](%1). " +
+ "Download and install those fonts to improve your MathJax experience.",
+ STIXURL
+ ]
+ ],
+
+ TeXfonts: [
+ ["p"],
+ ["TeXPage",
+ "This page is designed to use the [MathJax TeX fonts](%1). " +
+ "Download and install those fonts to improve your MathJax experience.",
+ MATHJAXURL
+ ]
+ ]
+
+ },
+
+ removeAfter: 12*1000, // time to show message (in ms)
+ fadeoutSteps: 10, // fade-out steps
+ fadeoutTime: 1.5*1000 // fadeout over this amount of time (in ms)
+
+ });
+ if (MathJax.Hub.Browser.isIE9 && document.documentMode >= 9)
+ {delete CONFIG.messageStyle.filter}
+
+ //
+ // Data for the window
+ //
+ var DATA = {
+ div: null, // the message window, when displayed
+ fade: 0 // number of fade-out steps so far
+ };
+
+ //
+ // Create the message window and start the fade-out timer
+ //
+ var CREATEMESSAGE = function (data) {
+ if (DATA.div) return;
+ var HTMLCSS = MathJax.OutputJax["HTML-CSS"], frame = document.body;
+ if (HUB.Browser.isMSIE) {
+ if (CONFIG.messageStyle.position === "fixed") {
+ MathJax.Message.Init(); // make sure MathJax_MSIE_frame exists
+ frame = document.getElementById("MathJax_MSIE_Frame") || frame;
+ if (frame !== document.body) {CONFIG.messageStyle.position = "absolute"}
+ }
+ } else {delete CONFIG.messageStyle.filter}
+ CONFIG.messageStyle.maxWidth = (document.body.clientWidth-75) + "px";
+ var i = 0; while (i < data.length) {
+ if (MathJax.Object.isArray(data[i])) {
+ if (data[i].length === 1 && CONFIG.HTML[data[i][0]]) {
+ data.splice.apply(data,[i,1].concat(CONFIG.HTML[data[i][0]]));
+ } else if (typeof data[i][1] === "string") {
+ var message = MathJax.Localization.lookupPhrase(["FontWarnings",data[i][0]],data[i][1]);
+ message = MathJax.Localization.processMarkdown(message,data[i].slice(2),"FontWarnings");
+ data.splice.apply(data,[i,1].concat(message));
+ i += message.length;
+ } else {i++}
+ } else {i++}
+ }
+ DATA.div = HTMLCSS.addElement(frame,"div",
+ {id:"MathJax_FontWarning",style:CONFIG.messageStyle},data);
+ MathJax.Localization.setCSS(DATA.div);
+ if (CONFIG.removeAfter) {
+ HUB.Register.StartupHook("End",function ()
+ {DATA.timer = setTimeout(FADEOUT,CONFIG.removeAfter)});
+ }
+ HTML.Cookie.Set("fontWarn",{warned:true});
+ };
+
+ //
+ // Set the opacity based on the number of steps taken so far
+ // and remove the window when it gets to 0
+ //
+ var FADEOUT = function () {
+ DATA.fade++; if (DATA.timer) {delete DATA.timer}
+ if (DATA.fade < CONFIG.fadeoutSteps) {
+ var opacity = 1 - DATA.fade/CONFIG.fadeoutSteps;
+ DATA.div.style.opacity = opacity;
+ DATA.div.style.filter = "alpha(opacity="+Math.floor(100*opacity)+")";
+ setTimeout(FADEOUT,CONFIG.fadeoutTime/CONFIG.fadeoutSteps);
+ } else {
+ DATA.div.style.display = "none";
+ }
+ };
+
+ //
+ // Check that we haven't already issued a warning
+ //
+ if (!HTML.Cookie.Get("fontWarn").warned) {
+ //
+ // Hook into the Startup signal and look for font warning messages.
+ // When one comes, issue the correct message.
+ //
+ HUB.Startup.signal.Interest(function (message) {
+ if (message.match(/HTML-CSS Jax - /) && !DATA.div) {
+ var HTMLCSS = MathJax.OutputJax["HTML-CSS"], FONTS = HTMLCSS.config.availableFonts, MSG;
+ var localFonts = (FONTS && FONTS.length);
+ if (!localFonts) {CONFIG.HTML.fonts = [""]}
+ else if (FONTS.length === 1) {CONFIG.HTML.fonts = CONFIG.HTML[FONTS[0]+"fonts"]}
+ if (HTMLCSS.allowWebFonts) {CONFIG.HTML.webfonts = [""]}
+ if (message.match(/- Web-Font/)) {if (localFonts) {MSG = "webFont"}}
+ else if (message.match(/- using image fonts/)) {MSG = "imageFonts"}
+ else if (message.match(/- no valid font/)) {MSG = "noFonts"}
+ if (MSG && CONFIG.Message[MSG])
+ {MathJax.Localization.loadDomain("FontWarnings",[CREATEMESSAGE,CONFIG.Message[MSG]])}
+ }
+ });
+ }
+
+})(MathJax.Hub,MathJax.HTML);
+
+MathJax.Ajax.loadComplete("[MathJax]/extensions/FontWarnings.js");
diff --git a/_static/scipy-mathjax/extensions/HelpDialog.js b/_static/scipy-mathjax/extensions/HelpDialog.js
new file mode 100644
index 000000000..e0680f097
--- /dev/null
+++ b/_static/scipy-mathjax/extensions/HelpDialog.js
@@ -0,0 +1,203 @@
+/*************************************************************
+ *
+ * MathJax/extensions/HelpDialog.js
+ *
+ * Implements the MathJax Help dialog box.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2013-2017 The MathJax Consortium
+ *
+ * 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.
+ */
+
+(function (HUB,HTML,AJAX,OUTPUT,LOCALE) {
+
+ var HELP = MathJax.Extension.Help = {
+ version: "2.7.1"
+ };
+
+ var STIXURL = "http://www.stixfonts.org/";
+ var MENU = MathJax.Menu;
+ var FALSE, KEY;
+ HUB.Register.StartupHook("MathEvents Ready",function () {
+ FALSE = MathJax.Extension.MathEvents.Event.False;
+ KEY = MathJax.Extension.MathEvents.Event.KEY;
+ });
+
+
+ var CONFIG = HUB.CombineConfig("HelpDialog",{
+
+ styles: {
+ "#MathJax_Help": {
+ position:"fixed", left:"50%", width:"auto", "max-width": "90%", "text-align":"center",
+ border:"3px outset", padding:"1em 2em", "background-color":"#DDDDDD", color:"black",
+ cursor: "default", "font-family":"message-box", "font-size":"120%",
+ "font-style":"normal", "text-indent":0, "text-transform":"none",
+ "line-height":"normal", "letter-spacing":"normal", "word-spacing":"normal",
+ "word-wrap":"normal", "white-space":"wrap", "float":"none", "z-index":201,
+
+ "border-radius": "15px", // Opera 10.5 and IE9
+ "-webkit-border-radius": "15px", // Safari and Chrome
+ "-moz-border-radius": "15px", // Firefox
+ "-khtml-border-radius": "15px", // Konqueror
+
+ "box-shadow":"0px 10px 20px #808080", // Opera 10.5 and IE9
+ "-webkit-box-shadow":"0px 10px 20px #808080", // Safari 3 and Chrome
+ "-moz-box-shadow":"0px 10px 20px #808080", // Forefox 3.5
+ "-khtml-box-shadow":"0px 10px 20px #808080", // Konqueror
+ filter: "progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color='gray', Positive='true')" // IE
+ },
+ "#MathJax_Help.MathJax_MousePost": {
+ outline:"none"
+ },
+
+ "#MathJax_HelpContent": {
+ overflow:"auto", "text-align":"left", "font-size":"80%",
+ padding:".4em .6em", border:"1px inset", margin:"1em 0px",
+ "max-height":"20em", "max-width":"30em", "background-color":"#EEEEEE"
+ },
+
+ "#MathJax_HelpClose": {
+ position:"absolute", top:".2em", right:".2em",
+ cursor:"pointer",
+ display:"inline-block",
+ border:"2px solid #AAA",
+ "border-radius":"18px",
+ "-webkit-border-radius": "18px", // Safari and Chrome
+ "-moz-border-radius": "18px", // Firefox
+ "-khtml-border-radius": "18px", // Konqueror
+ "font-family":"'Courier New',Courier",
+ "font-size":"24px",
+ color:"#F0F0F0"
+ },
+ "#MathJax_HelpClose span": {
+ display:"block", "background-color":"#AAA", border:"1.5px solid",
+ "border-radius":"18px",
+ "-webkit-border-radius": "18px", // Safari and Chrome
+ "-moz-border-radius": "18px", // Firefox
+ "-khtml-border-radius": "18px", // Konqueror
+ "line-height":0,
+ padding:"8px 0 6px" // may need to be browser-specific
+ },
+ "#MathJax_HelpClose:hover": {
+ color:"white!important",
+ border:"2px solid #CCC!important"
+ },
+ "#MathJax_HelpClose:hover span": {
+ "background-color":"#CCC!important"
+ },
+ "#MathJax_HelpClose:hover:focus": {
+ outline:"none"
+ }
+ }
+ });
+
+ /*
+ * Handle the Help Dialog box
+ */
+ HELP.Dialog = function (event) {
+ LOCALE.loadDomain("HelpDialog",["Post",HELP,event]);
+ };
+
+ HELP.Post = function (event) {
+ this.div = MENU.Background(this);
+ var help = HTML.addElement(this.div,"div",{
+ id: "MathJax_Help", tabIndex: 0, onkeydown: HELP.Keydown
+ },LOCALE._("HelpDialog",[
+ ["b",{style:{fontSize:"120%"}},[["Help","MathJax Help"]]],
+ ["div",{id: "MathJax_HelpContent", tabIndex: 0},[
+ ["p",{},[["MathJax",
+ "*MathJax* is a JavaScript library that allows page authors to include " +
+ "mathematics within their web pages. As a reader, you don't need to do " +
+ "anything to make that happen."]]
+ ],
+ ["p",{},[["Browsers",
+ "*Browsers*: MathJax works with all modern browsers including IE6+, Firefox 3+, " +
+ "Chrome 0.2+, Safari 2+, Opera 9.6+ and most mobile browsers."]]
+ ],
+ ["p",{},[["Menu",
+ "*Math Menu*: MathJax adds a contextual menu to equations. Right-click or " +
+ "CTRL-click on any mathematics to access the menu."]]
+ ],
+ ["div",{style:{"margin-left":"1em"}},[
+ ["p",{},[["ShowMath",
+ "*Show Math As* allows you to view the formula's source markup " +
+ "for copy & paste (as MathML or in its original format)."]]
+ ],
+ ["p",{},[["Settings",
+ "*Settings* gives you control over features of MathJax, such as the " +
+ "size of the mathematics, and the mechanism used to display equations."]]
+ ],
+ ["p",{},[["Language",
+ "*Language* lets you select the language used by MathJax for its menus " +
+ "and warning messages."]]
+ ],
+ ]],
+ ["p",{},[["Zoom",
+ "*Math Zoom*: If you are having difficulty reading an equation, MathJax can " +
+ "enlarge it to help you see it better."]]
+ ],
+ ["p",{},[["Accessibilty",
+ "*Accessibility*: MathJax will automatically work with screen readers to make " +
+ "mathematics accessible to the visually impaired."]]
+ ],
+ ["p",{},[["Fonts",
+ "*Fonts*: MathJax will use certain math fonts if they are installed on your " +
+ "computer; otherwise, it will use web-based fonts. Although not required, " +
+ "locally installed fonts will speed up typesetting. We suggest installing " +
+ "the [STIX fonts](%1).",STIXURL]]
+ ]
+ ]],
+ ["a",{href:"http://www.mathjax.org/"},["www.mathjax.org"]],
+ ["span",{id: "MathJax_HelpClose", onclick: HELP.Remove,
+ onkeydown: HELP.Keydown, tabIndex: 0, role: "button",
+ "aria-label": LOCALE._(["HelpDialog","CloseDialog"],"Close help dialog")},
+ [["span",{},["\u00D7"]]]
+ ]
+ ]));
+ if (event.type === "mouseup") help.className += " MathJax_MousePost";
+ help.focus();
+ LOCALE.setCSS(help);
+ var doc = (document.documentElement||{});
+ var H = window.innerHeight || doc.clientHeight || doc.scrollHeight || 0;
+ if (MENU.prototype.msieAboutBug) {
+ help.style.width = "20em"; help.style.position = "absolute";
+ help.style.left = Math.floor((document.documentElement.scrollWidth - help.offsetWidth)/2)+"px";
+ help.style.top = (Math.floor((H-help.offsetHeight)/3)+document.body.scrollTop)+"px";
+ } else {
+ help.style.marginLeft = Math.floor(-help.offsetWidth/2)+"px";
+ help.style.top = Math.floor((H-help.offsetHeight)/3)+"px";
+ }
+ };
+ HELP.Remove = function (event) {
+ if (HELP.div) {document.body.removeChild(HELP.div); delete HELP.div}
+ };
+ HELP.Keydown = function(event) {
+ if (event.keyCode === KEY.ESCAPE ||
+ (this.id === "MathJax_HelpClose" &&
+ (event.keyCode === KEY.SPACE || event.keyCode === KEY.RETURN))) {
+ HELP.Remove(event);
+ MENU.CurrentNode().focus();
+ FALSE(event);
+ }
+ },
+
+ MathJax.Callback.Queue(
+ HUB.Register.StartupHook("End Config",{}), // wait until config is complete
+ ["Styles",AJAX,CONFIG.styles],
+ ["Post",HUB.Startup.signal,"HelpDialig Ready"],
+ ["loadComplete",AJAX,"[MathJax]/extensions/HelpDialog.js"]
+ );
+
+})(MathJax.Hub,MathJax.HTML,MathJax.Ajax,MathJax.OutputJax,MathJax.Localization);
diff --git a/_static/scipy-mathjax/extensions/MatchWebFonts.js b/_static/scipy-mathjax/extensions/MatchWebFonts.js
new file mode 100644
index 000000000..13853af48
--- /dev/null
+++ b/_static/scipy-mathjax/extensions/MatchWebFonts.js
@@ -0,0 +1,309 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/MatchWebFonts.js
+ *
+ * Adds code to the output jax so that if web fonts are used on the page,
+ * MathJax will be able to detect their arrival and update the math to
+ * accommodate the change in font. For the NativeMML output, this works
+ * both for web fonts in main text, and for web fonts in the math as well.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2013-2017 The MathJax Consortium
+ *
+ * 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.
+ */
+
+(function (HUB,AJAX) {
+ var VERSION = "2.7.1";
+
+ var CONFIG = MathJax.Hub.CombineConfig("MatchWebFonts",{
+ matchFor: {
+ "HTML-CSS": true,
+ NativeMML: true,
+ SVG: true
+ },
+ fontCheckDelay: 500, // initial delay for the first check for web fonts
+ fontCheckTimeout: 15 * 1000, // how long to keep looking for fonts (15 seconds)
+ });
+
+ MathJax.Extension.MatchWebFonts = {
+ version: VERSION,
+ config: CONFIG
+ };
+
+ HUB.Register.StartupHook("HTML-CSS Jax Ready",function () {
+ var HTMLCSS = MathJax.OutputJax["HTML-CSS"];
+ var POSTTRANSLATE = HTMLCSS.postTranslate;
+
+ HTMLCSS.Augment({
+ postTranslate: function (state,partial) {
+ if (!partial && CONFIG.matchFor["HTML-CSS"] && this.config.matchFontHeight) {
+ //
+ // Check for changes in the web fonts that might affect the font
+ // size for math elements. This is a periodic check that goes on
+ // until a timeout is reached.
+ //
+ AJAX.timer.start(AJAX,["checkFonts",this,state.jax[this.id]],
+ CONFIG.fontCheckDelay,CONFIG.fontCheckTimeout);
+ }
+ return POSTTRANSLATE.apply(this,arguments); // do the original function
+ },
+
+ checkFonts: function (check,scripts) {
+ if (check.time(function () {})) return;
+ var size = [], i, m, retry = false;
+ //
+ // Add the elements used for testing ex and em sizes
+ //
+ for (i = 0, m = scripts.length; i < m; i++) {
+ script = scripts[i];
+ if (script.parentNode && script.MathJax.elementJax) {
+ script.parentNode.insertBefore(this.EmExSpan.cloneNode(true),script);
+ }
+ }
+ //
+ // Check to see if anything has changed
+ //
+ for (i = 0, m = scripts.length; i < m; i++) {
+ script = scripts[i]; if (!script.parentNode) continue; retry = true;
+ var jax = script.MathJax.elementJax; if (!jax) continue;
+ //
+ // Check if ex or mex has changed
+ //
+ var test = script.previousSibling;
+ var ex = test.firstChild.offsetHeight/60;
+ var em = test.lastChild.lastChild.offsetHeight/60;
+ if (ex === 0 || ex === "NaN") {ex = this.defaultEx; em = this.defaultEm}
+ if (ex !== jax.HTMLCSS.ex || em !== jax.HTMLCSS.em) {
+ var scale = ex/this.TeX.x_height/em;
+ scale = Math.floor(Math.max(this.config.minScaleAdjust/100,scale)*this.config.scale);
+ if (scale/100 !== jax.scale) {size.push(script); scripts[i] = {}}
+ }
+ }
+ //
+ // Remove markers
+ //
+ scripts = scripts.concat(size); // some scripts have been moved to the size array
+ for (i = 0, m = scripts.length; i < m; i++) {
+ script = scripts[i];
+ if (script && script.parentNode && script.MathJax.elementJax) {
+ script.parentNode.removeChild(script.previousSibling);
+ }
+ }
+ //
+ // Rerender the changed items
+ //
+ if (size.length) {HUB.Queue(["Rerender",HUB,[size],{}])}
+ //
+ // Try again later
+ //
+ if (retry) {setTimeout(check,check.delay)}
+ }
+ });
+ });
+
+ HUB.Register.StartupHook("SVG Jax Ready",function () {
+ var SVG = MathJax.OutputJax.SVG;
+ var POSTTRANSLATE = SVG.postTranslate;
+
+ SVG.Augment({
+ postTranslate: function (state,partial) {
+ if (!partial && CONFIG.matchFor.SVG) {
+ //
+ // Check for changes in the web fonts that might affect the font
+ // size for math elements. This is a periodic check that goes on
+ // until a timeout is reached.
+ //
+ AJAX.timer.start(AJAX,["checkFonts",this,state.jax[this.id]],
+ CONFIG.fontCheckDelay,CONFIG.fontCheckTimeout);
+ }
+ return POSTTRANSLATE.apply(this,arguments); // do the original function
+ },
+
+ checkFonts: function (check,scripts) {
+ if (check.time(function () {})) return;
+ var size = [], i, m, retry = false;
+ //
+ // Add the elements used for testing ex and em sizes
+ //
+ for (i = 0, m = scripts.length; i < m; i++) {
+ script = scripts[i];
+ if (script.parentNode && script.MathJax.elementJax) {
+ script.parentNode.insertBefore(this.ExSpan.cloneNode(true),script);
+ }
+ }
+ //
+ // Check to see if anything has changed
+ //
+ for (i = 0, m = scripts.length; i < m; i++) {
+ script = scripts[i]; if (!script.parentNode) continue; retry = true;
+ var jax = script.MathJax.elementJax; if (!jax) continue;
+ //
+ // Check if ex or mex has changed
+ //
+ var test = script.previousSibling;
+ var ex = test.firstChild.offsetHeight/60;
+ if (ex === 0 || ex === "NaN") {ex = this.defaultEx}
+ if (ex !== jax.SVG.ex) {size.push(script); scripts[i] = {}}
+ }
+ //
+ // Remove markers
+ //
+ scripts = scripts.concat(size); // some scripts have been moved to the size array
+ for (i = 0, m = scripts.length; i < m; i++) {
+ script = scripts[i];
+ if (script.parentNode && script.MathJax.elementJax) {
+ script.parentNode.removeChild(script.previousSibling);
+ }
+ }
+ //
+ // Rerender the changed items
+ //
+ if (size.length) {HUB.Queue(["Rerender",HUB,[size],{}])}
+ //
+ // Try again later (if not all the scripts are null)
+ //
+
+ if (retry) setTimeout(check,check.delay);
+ }
+ });
+ });
+
+ HUB.Register.StartupHook("NativeMML Jax Ready",function () {
+ var nMML = MathJax.OutputJax.NativeMML;
+ var POSTTRANSLATE = nMML.postTranslate;
+
+ nMML.Augment({
+ postTranslate: function (state) {
+ if (!HUB.Browser.isMSIE && CONFIG.matchFor.NativeMML) {
+ //
+ // Check for changes in the web fonts that might affect the sizes
+ // of math elements. This is a periodic check that goes on until
+ // a timeout is reached.
+ //
+ AJAX.timer.start(AJAX,["checkFonts",this,state.jax[this.id]],
+ CONFIG.fontCheckDelay,CONFIG.fontCheckTimeout);
+ }
+ POSTTRANSLATE.apply(this,arguments); // do the original routine
+ },
+
+ //
+ // Check to see if web fonts have been loaded that change the ex size
+ // of the surrounding font, the ex size within the math, or the widths
+ // of math elements. We do this by rechecking the ex and mex sizes
+ // (to see if the font scaling needs adjusting) and by checking the
+ // size of the inner mrow of math elements and mtd elements. The
+ // sizes of these have been stored in the NativeMML object of the
+ // element jax so that we can check for them here.
+ //
+ checkFonts: function (check,scripts) {
+ if (check.time(function () {})) return;
+ var adjust = [], mtd = [], size = [], i, m, script;
+ //
+ // Add the elements used for testing ex and em sizes
+ //
+ for (i = 0, m = scripts.length; i < m; i++) {
+ script = scripts[i];
+ if (script.parentNode && script.MathJax.elementJax) {
+ script.parentNode.insertBefore(this.EmExSpan.cloneNode(true),script);
+ }
+ }
+ //
+ // Check to see if anything has changed
+ //
+ for (i = 0, m = scripts.length; i < m; i++) {
+ script = scripts[i]; if (!script.parentNode) continue;
+ var jax = script.MathJax.elementJax; if (!jax) continue;
+ var span = document.getElementById(jax.inputID+"-Frame");
+ var math = span.getElementsByTagName("math")[0]; if (!math) continue;
+ jax = jax.NativeMML;
+ //
+ // Check if ex or mex has changed
+ //
+ var test = script.previousSibling;
+ var ex = test.firstChild.offsetWidth/60;
+ var mex = test.lastChild.offsetWidth/60;
+ if (ex === 0 || ex === "NaN") {ex = this.defaultEx; mex = this.defaultMEx}
+ var newEx = (ex !== jax.ex);
+ if (newEx || mex != jax.mex) {
+ var scale = (this.config.matchFontHeight && mex > 1 ? ex/mex : 1);
+ scale = Math.floor(Math.max(this.config.minScaleAdjust/100,scale) * this.config.scale);
+ if (scale/100 !== jax.scale) {size.push([span.style,scale])}
+ jax.scale = scale/100; jax.fontScale = scale+"%"; jax.ex = ex; jax.mex = mex;
+ }
+
+ //
+ // Check width of math elements
+ //
+ if ("scrollWidth" in jax && (newEx || jax.scrollWidth !== math.firstChild.scrollWidth)) {
+ jax.scrollWidth = math.firstChild.scrollWidth;
+ adjust.push([math.parentNode.style,jax.scrollWidth/jax.ex/jax.scale]);
+ }
+ //
+ // Check widths of mtd elements
+ //
+ if (math.MathJaxMtds) {
+ for (var j = 0, n = math.MathJaxMtds.length; j < n; j++) {
+ if (!math.MathJaxMtds[j].parentNode) continue;
+ if (newEx || math.MathJaxMtds[j].firstChild.scrollWidth !== jax.mtds[j]) {
+ jax.mtds[j] = math.MathJaxMtds[j].firstChild.scrollWidth;
+ mtd.push([math.MathJaxMtds[j],jax.mtds[j]/jax.ex]);
+ }
+ }
+ }
+ }
+ //
+ // Remove markers
+ //
+ for (i = 0, m = scripts.length; i < m; i++) {
+ script = scripts[i];
+ if (script.parentNode && script.MathJax.elementJax) {
+ script.parentNode.removeChild(script.previousSibling);
+ }
+ }
+ //
+ // Adjust scaling factor
+ //
+ for (i = 0, m = size.length; i < m; i++) {
+ size[i][0].fontSize = size[i][1] + "%";
+ }
+ //
+ // Adjust width of spans containing math elements that have changed
+ //
+ for (i = 0, m = adjust.length; i < m; i++) {
+ adjust[i][0].width = adjust[i][1].toFixed(3)+"ex";
+ }
+ //
+ // Adjust widths of mtd elements that have changed
+ //
+ for (i = 0, m = mtd.length; i < m; i++) {
+ var style = mtd[i][0].getAttribute("style");
+ style = style.replace(/(($|;)\s*min-width:).*?ex/,"$1 "+mtd[i][1].toFixed(3)+"ex");
+ mtd[i][0].setAttribute("style",style);
+ }
+ //
+ // Try again later
+ //
+ setTimeout(check,check.delay);
+ }
+ });
+ });
+
+ HUB.Startup.signal.Post("MatchWebFonts Extension Ready");
+ AJAX.loadComplete("[MathJax]/extensions/MatchWebFonts.js");
+
+})(MathJax.Hub,MathJax.Ajax);
diff --git a/_static/scipy-mathjax/extensions/MathEvents.js b/_static/scipy-mathjax/extensions/MathEvents.js
new file mode 100644
index 000000000..52e3c9120
--- /dev/null
+++ b/_static/scipy-mathjax/extensions/MathEvents.js
@@ -0,0 +1,619 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/MathEvents.js
+ *
+ * Implements the event handlers needed by the output jax to perform
+ * menu, hover, and other events.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2011-2017 The MathJax Consortium
+ *
+ * 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.
+ */
+
+(function (HUB,HTML,AJAX,CALLBACK,LOCALE,OUTPUT,INPUT) {
+ var VERSION = "2.7.1";
+
+ var EXTENSION = MathJax.Extension;
+ var ME = EXTENSION.MathEvents = {version: VERSION};
+
+ var SETTINGS = HUB.config.menuSettings;
+
+ var CONFIG = {
+ hover: 500, // time required to be considered a hover
+ frame: {
+ x: 3.5, y: 5, // frame padding and
+ bwidth: 1, // frame border width (in pixels)
+ bcolor: "#A6D", // frame border color
+ hwidth: "15px", // haze width
+ hcolor: "#83A" // haze color
+ },
+ button: {
+ x: -6, y: -3, // menu button offsets
+ wx: -2 // button offset for full-width equations
+ },
+ fadeinInc: .2, // increment for fade-in
+ fadeoutInc: .05, // increment for fade-out
+ fadeDelay: 50, // delay between fade-in or fade-out steps
+ fadeoutStart: 400, // delay before fade-out after mouseout
+ fadeoutDelay: 15*1000, // delay before automatic fade-out
+
+ styles: {
+ ".MathJax_Hover_Frame": {
+ "border-radius": ".25em", // Opera 10.5 and IE9
+ "-webkit-border-radius": ".25em", // Safari and Chrome
+ "-moz-border-radius": ".25em", // Firefox
+ "-khtml-border-radius": ".25em", // Konqueror
+
+ "box-shadow": "0px 0px 15px #83A", // Opera 10.5 and IE9
+ "-webkit-box-shadow": "0px 0px 15px #83A", // Safari and Chrome
+ "-moz-box-shadow": "0px 0px 15px #83A", // Forefox
+ "-khtml-box-shadow": "0px 0px 15px #83A", // Konqueror
+
+ border: "1px solid #A6D ! important",
+ display: "inline-block", position:"absolute"
+ },
+
+ ".MathJax_Menu_Button .MathJax_Hover_Arrow": {
+ position:"absolute",
+ cursor:"pointer",
+ display:"inline-block",
+ border:"2px solid #AAA",
+ "border-radius":"4px",
+ "-webkit-border-radius": "4px", // Safari and Chrome
+ "-moz-border-radius": "4px", // Firefox
+ "-khtml-border-radius": "4px", // Konqueror
+ "font-family":"'Courier New',Courier",
+ "font-size":"9px",
+ color:"#F0F0F0"
+ },
+ ".MathJax_Menu_Button .MathJax_Hover_Arrow span": {
+ display:"block",
+ "background-color":"#AAA",
+ border:"1px solid",
+ "border-radius":"3px",
+ "line-height":0,
+ padding:"4px"
+ },
+ ".MathJax_Hover_Arrow:hover": {
+ color:"white!important",
+ border:"2px solid #CCC!important"
+ },
+ ".MathJax_Hover_Arrow:hover span": {
+ "background-color":"#CCC!important"
+ }
+ }
+ };
+
+
+ //
+ // Common event-handling code
+ //
+ var EVENT = ME.Event = {
+
+ LEFTBUTTON: 0, // the event.button value for left button
+ RIGHTBUTTON: 2, // the event.button value for right button
+ MENUKEY: "altKey", // the event value for alternate context menu
+
+ /*************************************************************/
+ /*
+ * Enum element for key codes.
+ */
+ KEY: {
+ RETURN: 13,
+ ESCAPE: 27,
+ SPACE: 32,
+ LEFT: 37,
+ UP: 38,
+ RIGHT: 39,
+ DOWN: 40
+ },
+
+ Mousedown: function (event) {return EVENT.Handler(event,"Mousedown",this)},
+ Mouseup: function (event) {return EVENT.Handler(event,"Mouseup",this)},
+ Mousemove: function (event) {return EVENT.Handler(event,"Mousemove",this)},
+ Mouseover: function (event) {return EVENT.Handler(event,"Mouseover",this)},
+ Mouseout: function (event) {return EVENT.Handler(event,"Mouseout",this)},
+ Click: function (event) {return EVENT.Handler(event,"Click",this)},
+ DblClick: function (event) {return EVENT.Handler(event,"DblClick",this)},
+ Menu: function (event) {return EVENT.Handler(event,"ContextMenu",this)},
+
+ //
+ // Call the output jax's event handler or the zoom handler
+ //
+ Handler: function (event,type,math) {
+ if (AJAX.loadingMathMenu) {return EVENT.False(event)}
+ var jax = OUTPUT[math.jaxID];
+ if (!event) {event = window.event}
+ event.isContextMenu = (type === "ContextMenu");
+ if (jax[type]) {return jax[type](event,math)}
+ if (EXTENSION.MathZoom) {return EXTENSION.MathZoom.HandleEvent(event,type,math)}
+ },
+
+ //
+ // Try to cancel the event in every way we can
+ //
+ False: function (event) {
+ if (!event) {event = window.event}
+ if (event) {
+ if (event.preventDefault) {event.preventDefault()} else {event.returnValue = false}
+ if (event.stopPropagation) {event.stopPropagation()}
+ event.cancelBubble = true;
+ }
+ return false;
+ },
+
+ //
+ // Keydown event handler. Should only fire on Space key.
+ //
+ Keydown: function (event, math) {
+ if (!event) event = window.event;
+ if (event.keyCode === EVENT.KEY.SPACE) {
+ EVENT.ContextMenu(event, this);
+ };
+ },
+
+ //
+ // Load the contextual menu code, if needed, and post the menu
+ //
+ ContextMenu: function (event,math,force) {
+ //
+ // Check if we are showing menus
+ //
+ var JAX = OUTPUT[math.jaxID], jax = JAX.getJaxFromMath(math);
+ var show = (JAX.config.showMathMenu != null ? JAX : HUB).config.showMathMenu;
+ if (!show || (SETTINGS.context !== "MathJax" && !force)) return;
+
+ //
+ // Remove selections, remove hover fades
+ //
+ if (ME.msieEventBug) {event = window.event || event}
+ EVENT.ClearSelection(); HOVER.ClearHoverTimer();
+ if (jax.hover) {
+ if (jax.hover.remove) {clearTimeout(jax.hover.remove); delete jax.hover.remove}
+ jax.hover.nofade = true;
+ }
+
+ //
+ // If the menu code is loaded,
+ // Check if localization needs loading;
+ // If not, post the menu, and return.
+ // Otherwise wait for the localization to load
+ // Otherwse load the menu code.
+ // Try again after the file is loaded.
+ //
+ var MENU = MathJax.Menu; var load, fn;
+ if (MENU) {
+ if (MENU.loadingDomain) {return EVENT.False(event)}
+ load = LOCALE.loadDomain("MathMenu");
+ if (!load) {
+ MENU.jax = jax;
+ var source = MENU.menu.Find("Show Math As").submenu;
+ source.items[0].name = jax.sourceMenuTitle;
+ source.items[0].format = (jax.sourceMenuFormat||"MathML");
+ source.items[1].name = INPUT[jax.inputJax].sourceMenuTitle;
+ source.items[5].disabled = !INPUT[jax.inputJax].annotationEncoding;
+
+ //
+ // Try and find each known annotation format and enable the menu
+ // items accordingly.
+ //
+ var annotations = source.items[2]; annotations.disabled = true;
+ var annotationItems = annotations.submenu.items;
+ annotationList = MathJax.Hub.Config.semanticsAnnotations;
+ for (var i = 0, m = annotationItems.length; i < m; i++) {
+ var name = annotationItems[i].name[1]
+ if (jax.root && jax.root.getAnnotation(name) !== null) {
+ annotations.disabled = false;
+ annotationItems[i].hidden = false;
+ } else {
+ annotationItems[i].hidden = true;
+ }
+ }
+
+ var MathPlayer = MENU.menu.Find("Math Settings","MathPlayer");
+ MathPlayer.hidden = !(jax.outputJax === "NativeMML" && HUB.Browser.hasMathPlayer);
+ return MENU.menu.Post(event);
+ }
+ MENU.loadingDomain = true;
+ fn = function () {delete MENU.loadingDomain};
+ } else {
+ if (AJAX.loadingMathMenu) {return EVENT.False(event)}
+ AJAX.loadingMathMenu = true;
+ load = AJAX.Require("[MathJax]/extensions/MathMenu.js");
+ fn = function () {
+ delete AJAX.loadingMathMenu;
+ if (!MathJax.Menu) {MathJax.Menu = {}}
+ }
+ }
+ var ev = {
+ pageX:event.pageX, pageY:event.pageY,
+ clientX:event.clientX, clientY:event.clientY
+ };
+ CALLBACK.Queue(
+ load, fn, // load the file and delete the marker when done
+ ["ContextMenu",EVENT,ev,math,force] // call this function again
+ );
+ return EVENT.False(event);
+ },
+
+ //
+ // Mousedown handler for alternate means of accessing menu
+ //
+ AltContextMenu: function (event,math) {
+ var JAX = OUTPUT[math.jaxID];
+ var show = (JAX.config.showMathMenu != null ? JAX : HUB).config.showMathMenu;
+ if (show) {
+ show = (JAX.config.showMathMenuMSIE != null ? JAX : HUB).config.showMathMenuMSIE;
+ if (SETTINGS.context === "MathJax" && !SETTINGS.mpContext && show) {
+ if (!ME.noContextMenuBug || event.button !== EVENT.RIGHTBUTTON) return;
+ } else {
+ if (!event[EVENT.MENUKEY] || event.button !== EVENT.LEFTBUTTON) return;
+ }
+ return JAX.ContextMenu(event,math,true);
+ }
+ },
+
+ ClearSelection: function () {
+ if (ME.safariContextMenuBug) {setTimeout("window.getSelection().empty()",0)}
+ if (document.selection) {setTimeout("document.selection.empty()",0)}
+ },
+
+ getBBox: function (span) {
+ span.appendChild(ME.topImg);
+ var h = ME.topImg.offsetTop, d = span.offsetHeight-h, w = span.offsetWidth;
+ span.removeChild(ME.topImg);
+ return {w:w, h:h, d:d};
+ }
+
+ };
+
+ //
+ // Handle hover "discoverability"
+ //
+ var HOVER = ME.Hover = {
+
+ //
+ // Check if we are moving from a non-MathJax element to a MathJax one
+ // and either start fading in again (if it is fading out) or start the
+ // timer for the hover
+ //
+ Mouseover: function (event,math) {
+ if (SETTINGS.discoverable || SETTINGS.zoom === "Hover") {
+ var from = event.fromElement || event.relatedTarget,
+ to = event.toElement || event.target;
+ if (from && to && (HUB.isMathJaxNode(from) !== HUB.isMathJaxNode(to) ||
+ HUB.getJaxFor(from) !== HUB.getJaxFor(to))) {
+ var jax = this.getJaxFromMath(math);
+ if (jax.hover) {HOVER.ReHover(jax)} else {HOVER.HoverTimer(jax,math)}
+ return EVENT.False(event);
+ }
+ }
+ },
+ //
+ // Check if we are moving from a MathJax element to a non-MathJax one
+ // and either start fading out, or clear the timer if we haven't
+ // hovered yet
+ //
+ Mouseout: function (event,math) {
+ if (SETTINGS.discoverable || SETTINGS.zoom === "Hover") {
+ var from = event.fromElement || event.relatedTarget,
+ to = event.toElement || event.target;
+ if (from && to && (HUB.isMathJaxNode(from) !== HUB.isMathJaxNode(to) ||
+ HUB.getJaxFor(from) !== HUB.getJaxFor(to))) {
+ var jax = this.getJaxFromMath(math);
+ if (jax.hover) {HOVER.UnHover(jax)} else {HOVER.ClearHoverTimer()}
+ return EVENT.False(event);
+ }
+ }
+ },
+ //
+ // Restart hover timer if the mouse moves
+ //
+ Mousemove: function (event,math) {
+ if (SETTINGS.discoverable || SETTINGS.zoom === "Hover") {
+ var jax = this.getJaxFromMath(math); if (jax.hover) return;
+ if (HOVER.lastX == event.clientX && HOVER.lastY == event.clientY) return;
+ HOVER.lastX = event.clientX; HOVER.lastY = event.clientY;
+ HOVER.HoverTimer(jax,math);
+ return EVENT.False(event);
+ }
+ },
+
+ //
+ // Clear the old timer and start a new one
+ //
+ HoverTimer: function (jax,math) {
+ this.ClearHoverTimer();
+ this.hoverTimer = setTimeout(CALLBACK(["Hover",this,jax,math]),CONFIG.hover);
+ },
+ ClearHoverTimer: function () {
+ if (this.hoverTimer) {clearTimeout(this.hoverTimer); delete this.hoverTimer}
+ },
+
+ //
+ // Handle putting up the hover frame
+ //
+ Hover: function (jax,math) {
+ //
+ // Check if Zoom handles the hover event
+ //
+ if (EXTENSION.MathZoom && EXTENSION.MathZoom.Hover({},math)) return;
+ //
+ // Get the hover data
+ //
+ var JAX = OUTPUT[jax.outputJax],
+ span = JAX.getHoverSpan(jax,math),
+ bbox = JAX.getHoverBBox(jax,span,math),
+ show = (JAX.config.showMathMenu != null ? JAX : HUB).config.showMathMenu;
+ var dx = CONFIG.frame.x, dy = CONFIG.frame.y, dd = CONFIG.frame.bwidth; // frame size
+ if (ME.msieBorderWidthBug) {dd = 0}
+ jax.hover = {opacity:0, id:jax.inputID+"-Hover"};
+ //
+ // The frame and menu button
+ //
+ var frame = HTML.Element("span",{
+ id:jax.hover.id, isMathJax: true,
+ style:{display:"inline-block", width:0, height:0, position:"relative"}
+ },[["span",{
+ className:"MathJax_Hover_Frame", isMathJax: true,
+ style:{
+ display:"inline-block", position:"absolute",
+ top:this.Px(-bbox.h-dy-dd-(bbox.y||0)), left:this.Px(-dx-dd+(bbox.x||0)),
+ width:this.Px(bbox.w+2*dx), height:this.Px(bbox.h+bbox.d+2*dy),
+ opacity:0, filter:"alpha(opacity=0)"
+ }}
+ ]]
+ );
+ var button = HTML.Element("span",{
+ isMathJax: true, id:jax.hover.id+"Menu", className:"MathJax_Menu_Button",
+ style:{display:"inline-block", "z-index": 1, width:0, height:0, position:"relative"}
+ },[["span",{
+ className: "MathJax_Hover_Arrow", isMathJax: true, math: math,
+ onclick: this.HoverMenu, jax:JAX.id,
+ style: {
+ left:this.Px(bbox.w+dx+dd+(bbox.x||0)+CONFIG.button.x),
+ top:this.Px(-bbox.h-dy-dd-(bbox.y||0)-CONFIG.button.y),
+ opacity:0, filter:"alpha(opacity=0)"
+ }
+ },[["span",{isMathJax:true},"\u25BC"]]]]
+ );
+ if (bbox.width) {
+ frame.style.width = button.style.width = bbox.width;
+ frame.style.marginRight = button.style.marginRight = "-"+bbox.width;
+ frame.firstChild.style.width = bbox.width;
+ button.firstChild.style.left = "";
+ button.firstChild.style.right = this.Px(CONFIG.button.wx);
+ }
+ //
+ // Add the frame and button
+ //
+ span.parentNode.insertBefore(frame,span);
+ if (show) {span.parentNode.insertBefore(button,span)}
+ if (span.style) {span.style.position = "relative"} // so math is on top of hover frame
+ //
+ // Start the hover fade-in
+ //
+ this.ReHover(jax);
+ },
+ //
+ // Restart the hover fade in and fade-out timers
+ //
+ ReHover: function (jax) {
+ if (jax.hover.remove) {clearTimeout(jax.hover.remove)}
+ jax.hover.remove = setTimeout(CALLBACK(["UnHover",this,jax]),CONFIG.fadeoutDelay);
+ this.HoverFadeTimer(jax,CONFIG.fadeinInc);
+ },
+ //
+ // Start the fade-out
+ //
+ UnHover: function (jax) {
+ if (!jax.hover.nofade) {this.HoverFadeTimer(jax,-CONFIG.fadeoutInc,CONFIG.fadeoutStart)}
+ },
+ //
+ // Handle the fade-in and fade-out
+ //
+ HoverFade: function (jax) {
+ delete jax.hover.timer;
+ jax.hover.opacity = Math.max(0,Math.min(1,jax.hover.opacity + jax.hover.inc));
+ jax.hover.opacity = Math.floor(1000*jax.hover.opacity)/1000;
+ var frame = document.getElementById(jax.hover.id),
+ button = document.getElementById(jax.hover.id+"Menu");
+ frame.firstChild.style.opacity = jax.hover.opacity;
+ frame.firstChild.style.filter = "alpha(opacity="+Math.floor(100*jax.hover.opacity)+")";
+ if (button) {
+ button.firstChild.style.opacity = jax.hover.opacity;
+ button.firstChild.style.filter = frame.style.filter;
+ }
+ if (jax.hover.opacity === 1) {return}
+ if (jax.hover.opacity > 0) {this.HoverFadeTimer(jax,jax.hover.inc); return}
+ frame.parentNode.removeChild(frame);
+ if (button) {button.parentNode.removeChild(button)}
+ if (jax.hover.remove) {clearTimeout(jax.hover.remove)}
+ delete jax.hover;
+ },
+ //
+ // Set the fade to in or out (via inc) and start the timer, if needed
+ //
+ HoverFadeTimer: function (jax,inc,delay) {
+ jax.hover.inc = inc;
+ if (!jax.hover.timer) {
+ jax.hover.timer = setTimeout(CALLBACK(["HoverFade",this,jax]),(delay||CONFIG.fadeDelay));
+ }
+ },
+
+ //
+ // Handle a click on the menu button
+ //
+ HoverMenu: function (event) {
+ if (!event) {event = window.event}
+ return OUTPUT[this.jax].ContextMenu(event,this.math,true);
+ },
+
+ //
+ // Clear all hover timers
+ //
+ ClearHover: function (jax) {
+ if (jax.hover.remove) {clearTimeout(jax.hover.remove)}
+ if (jax.hover.timer) {clearTimeout(jax.hover.timer)}
+ HOVER.ClearHoverTimer();
+ delete jax.hover;
+ },
+
+ //
+ // Make a measurement in pixels
+ //
+ Px: function (m) {
+ if (Math.abs(m) < .006) {return "0px"}
+ return m.toFixed(2).replace(/\.?0+$/,"") + "px";
+ },
+
+ //
+ // Preload images so they show up with the menu
+ //
+ getImages: function () {
+ if (SETTINGS.discoverable) {
+ var menu = new Image();
+ menu.src = CONFIG.button.src;
+ }
+ }
+
+ };
+
+ //
+ // Handle touch events.
+ //
+ // Use double-tap-and-hold as a replacement for context menu event.
+ // Use double-tap as a replacement for double click.
+ //
+ var TOUCH = ME.Touch = {
+
+ last: 0, // time of last tap event
+ delay: 500, // delay time for double-click
+
+ //
+ // Check if this is a double-tap, and if so, start the timer
+ // for the double-tap and hold (to trigger the contextual menu)
+ //
+ start: function (event) {
+ var now = new Date().getTime();
+ var dblTap = (now - TOUCH.last < TOUCH.delay && TOUCH.up);
+ TOUCH.last = now; TOUCH.up = false;
+ if (dblTap) {
+ TOUCH.timeout = setTimeout(TOUCH.menu,TOUCH.delay,event,this);
+ event.preventDefault();
+ }
+ },
+
+ //
+ // Check if there is a timeout pending, i.e., we have a
+ // double-tap and were waiting to see if it is held long
+ // enough for the menu. Since we got the end before the
+ // timeout, it is a double-click, not a double-tap-and-hold.
+ // Prevent the default action and issue a double click.
+ //
+ end: function (event) {
+ var now = new Date().getTime();
+ TOUCH.up = (now - TOUCH.last < TOUCH.delay);
+ if (TOUCH.timeout) {
+ clearTimeout(TOUCH.timeout);
+ delete TOUCH.timeout; TOUCH.last = 0; TOUCH.up = false;
+ event.preventDefault();
+ return EVENT.Handler((event.touches[0]||event.touch),"DblClick",this);
+ }
+ },
+
+ //
+ // If the timeout passes without an end event, we issue
+ // the contextual menu event.
+ //
+ menu: function (event,math) {
+ delete TOUCH.timeout; TOUCH.last = 0; TOUCH.up = false;
+ return EVENT.Handler((event.touches[0]||event.touch),"ContextMenu",math);
+ }
+
+ };
+
+ /*
+ * //
+ * // Mobile screens are small, so use larger version of arrow
+ * //
+ * if (HUB.Browser.isMobile) {
+ * var arrow = CONFIG.styles[".MathJax_Hover_Arrow"];
+ * arrow.width = "25px"; arrow.height = "18px";
+ * CONFIG.button.x = -6;
+ * }
+ */
+
+ //
+ // Set up browser-specific values
+ //
+ HUB.Browser.Select({
+ MSIE: function (browser) {
+ var mode = (document.documentMode || 0);
+ var isIE8 = browser.versionAtLeast("8.0");
+ ME.msieBorderWidthBug = (document.compatMode === "BackCompat"); // borders are inside offsetWidth/Height
+ ME.msieEventBug = browser.isIE9; // must get event from window even though event is passed
+ ME.msieAlignBug = (!isIE8 || mode < 8); // inline-block spans don't rest on baseline
+ if (mode < 9) {EVENT.LEFTBUTTON = 1} // IE < 9 has wrong event.button values
+ },
+ Safari: function (browser) {
+ ME.safariContextMenuBug = true; // selection can be started by contextmenu event
+ },
+ Opera: function (browser) {
+ ME.operaPositionBug = true; // position is wrong unless border is used
+ },
+ Konqueror: function (browser) {
+ ME.noContextMenuBug = true; // doesn't produce contextmenu event
+ }
+ });
+
+ //
+ // Used in measuring zoom and hover positions
+ //
+ ME.topImg = (ME.msieAlignBug ?
+ HTML.Element("img",{style:{width:0,height:0,position:"relative"},src:"about:blank"}) :
+ HTML.Element("span",{style:{width:0,height:0,display:"inline-block"}})
+ );
+ if (ME.operaPositionBug) {ME.topImg.style.border="1px solid"}
+
+ //
+ // Get configuration from user
+ //
+ ME.config = CONFIG = HUB.CombineConfig("MathEvents",CONFIG);
+ var SETFRAME = function () {
+ var haze = CONFIG.styles[".MathJax_Hover_Frame"];
+ haze.border = CONFIG.frame.bwidth+"px solid "+CONFIG.frame.bcolor+" ! important";
+ haze["box-shadow"] = haze["-webkit-box-shadow"] =
+ haze["-moz-box-shadow"] = haze["-khtml-box-shadow"] =
+ "0px 0px "+CONFIG.frame.hwidth+" "+CONFIG.frame.hcolor;
+ };
+
+ //
+ // Queue the events needed for startup
+ //
+ CALLBACK.Queue(
+ HUB.Register.StartupHook("End Config",{}), // wait until config is complete
+ [SETFRAME],
+ ["getImages",HOVER],
+ ["Styles",AJAX,CONFIG.styles],
+ ["Post",HUB.Startup.signal,"MathEvents Ready"],
+ ["loadComplete",AJAX,"[MathJax]/extensions/MathEvents.js"]
+ );
+
+})(MathJax.Hub,MathJax.HTML,MathJax.Ajax,MathJax.Callback,
+ MathJax.Localization,MathJax.OutputJax,MathJax.InputJax);
diff --git a/_static/scipy-mathjax/extensions/MathMenu.js b/_static/scipy-mathjax/extensions/MathMenu.js
new file mode 100644
index 000000000..6352adaa3
--- /dev/null
+++ b/_static/scipy-mathjax/extensions/MathMenu.js
@@ -0,0 +1,1664 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/MathMenu.js
+ *
+ * Implements a right-mouse (or CTRL-click) menu over mathematics
+ * elements that gives the user the ability to copy the source,
+ * change the math size, and zoom settings.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2010-2017 The MathJax Consortium
+ *
+ * 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.
+ */
+
+(function (HUB,HTML,AJAX,CALLBACK,OUTPUT) {
+ var VERSION = "2.7.1";
+
+ var SIGNAL = MathJax.Callback.Signal("menu"); // signal for menu events
+
+ MathJax.Extension.MathMenu = {
+ version: VERSION,
+ signal: SIGNAL
+ };
+
+ var _ = function (id) {
+ return MathJax.Localization._.apply(
+ MathJax.Localization,
+ [["MathMenu",id]].concat([].slice.call(arguments,1))
+ );
+ };
+
+ var isArray = MathJax.Object.isArray;
+
+ var isPC = HUB.Browser.isPC, isMSIE = HUB.Browser.isMSIE, isIE9 = ((document.documentMode||0) > 8);
+ var ROUND = (isPC ? null : "5px");
+
+ var CONFIG = HUB.CombineConfig("MathMenu",{
+ delay: 150, // the delay for submenus
+
+ showRenderer: true, // show the "Math Renderer" menu?
+ showMathPlayer: true, // show the "MathPlayer" menu?
+ showFontMenu: false, // show the "Font Preference" menu?
+ showContext: false, // show the "Context Menu" menu?
+ showDiscoverable: false, // show the "Discoverable" menu?
+ showLocale: true, // show the "Locale" menu?
+ showLocaleURL: false, // show the "Load from URL" menu?
+
+ semanticsAnnotations: {
+ "TeX": ["TeX", "LaTeX", "application/x-tex"],
+ "StarMath": ["StarMath 5.0"],
+ "Maple": ["Maple"],
+ "ContentMathML": ["MathML-Content", "application/mathml-content+xml"],
+ "OpenMath": ["OpenMath"]
+ },
+
+ windowSettings: { // for source window
+ status: "no", toolbar: "no", locationbar: "no", menubar: "no",
+ directories: "no", personalbar: "no", resizable: "yes", scrollbars: "yes",
+ width: 400, height: 300,
+ left: Math.round((screen.width - 400)/2),
+ top: Math.round((screen.height - 300)/3)
+ },
+
+ styles: {
+ "#MathJax_About": {
+ position:"fixed", left:"50%", width:"auto", "text-align":"center",
+ border:"3px outset", padding:"1em 2em", "background-color":"#DDDDDD", color:"black",
+ cursor: "default", "font-family":"message-box", "font-size":"120%",
+ "font-style":"normal", "text-indent":0, "text-transform":"none",
+ "line-height":"normal", "letter-spacing":"normal", "word-spacing":"normal",
+ "word-wrap":"normal", "white-space":"nowrap", "float":"none", "z-index":201,
+
+ "border-radius": "15px", // Opera 10.5 and IE9
+ "-webkit-border-radius": "15px", // Safari and Chrome
+ "-moz-border-radius": "15px", // Firefox
+ "-khtml-border-radius": "15px", // Konqueror
+
+ "box-shadow":"0px 10px 20px #808080", // Opera 10.5 and IE9
+ "-webkit-box-shadow":"0px 10px 20px #808080", // Safari 3 and Chrome
+ "-moz-box-shadow":"0px 10px 20px #808080", // Forefox 3.5
+ "-khtml-box-shadow":"0px 10px 20px #808080", // Konqueror
+ filter: "progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color='gray', Positive='true')" // IE
+ },
+ "#MathJax_About.MathJax_MousePost": {
+ outline:"none"
+ },
+
+ ".MathJax_Menu": {
+ position:"absolute", "background-color":"white", color:"black",
+ width:"auto", padding:(isPC ? "2px" : "5px 0px"),
+ border:"1px solid #CCCCCC", margin:0, cursor:"default",
+ font: "menu", "text-align":"left", "text-indent":0, "text-transform":"none",
+ "line-height":"normal", "letter-spacing":"normal", "word-spacing":"normal",
+ "word-wrap":"normal", "white-space":"nowrap", "float":"none", "z-index":201,
+
+ "border-radius": ROUND, // Opera 10.5 and IE9
+ "-webkit-border-radius": ROUND, // Safari and Chrome
+ "-moz-border-radius": ROUND, // Firefox
+ "-khtml-border-radius": ROUND, // Konqueror
+
+ "box-shadow":"0px 10px 20px #808080", // Opera 10.5 and IE9
+ "-webkit-box-shadow":"0px 10px 20px #808080", // Safari 3 and Chrome
+ "-moz-box-shadow":"0px 10px 20px #808080", // Forefox 3.5
+ "-khtml-box-shadow":"0px 10px 20px #808080", // Konqueror
+ filter: "progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color='gray', Positive='true')" // IE
+ },
+
+ ".MathJax_MenuItem": {
+ padding: (isPC ? "2px 2em" : "1px 2em"),
+ background:"transparent"
+ },
+
+ ".MathJax_MenuArrow": {
+ position:"absolute", right:".5em", "padding-top":".25em", color:"#666666",
+ "font-family": (isMSIE ? "'Arial unicode MS'" : null), "font-size": ".75em"
+ },
+ ".MathJax_MenuActive .MathJax_MenuArrow": {color:"white"},
+ ".MathJax_MenuArrow.RTL": {left:".5em", right:"auto"},
+
+ ".MathJax_MenuCheck": {
+ position:"absolute", left:".7em",
+ "font-family": (isMSIE ? "'Arial unicode MS'" : null)
+ },
+ ".MathJax_MenuCheck.RTL": {right:".7em", left:"auto"},
+
+ ".MathJax_MenuRadioCheck": {
+ position:"absolute", left: (isPC ? "1em" : ".7em")
+ },
+ ".MathJax_MenuRadioCheck.RTL": {
+ right: (isPC ? "1em" : ".7em"), left:"auto"
+ },
+
+ ".MathJax_MenuLabel": {
+ padding: (isPC ? "2px 2em 4px 1.33em" : "1px 2em 3px 1.33em"),
+ "font-style":"italic"
+ },
+
+ ".MathJax_MenuRule": {
+ "border-top": (isPC ? "1px solid #CCCCCC" : "1px solid #DDDDDD"),
+ margin: (isPC ? "4px 1px 0px" : "4px 3px")
+ },
+
+ ".MathJax_MenuDisabled": {
+ color:"GrayText"
+ },
+ ".MathJax_MenuActive": {
+ "background-color": (isPC ? "Highlight" : "#606872"),
+ color: (isPC ? "HighlightText" : "white")
+ },
+
+ ".MathJax_MenuDisabled:focus, .MathJax_MenuLabel:focus": {
+ "background-color": "#E8E8E8"
+ },
+ ".MathJax_ContextMenu:focus": {
+ outline:"none"
+ },
+ ".MathJax_ContextMenu .MathJax_MenuItem:focus": {
+ outline:"none"
+ },
+
+ "#MathJax_AboutClose": {
+ top:".2em", right:".2em"
+ },
+ ".MathJax_Menu .MathJax_MenuClose": {
+ top:"-10px", left:"-10px"
+ },
+
+ ".MathJax_MenuClose": {
+ position:"absolute",
+ cursor:"pointer",
+ display:"inline-block",
+ border:"2px solid #AAA",
+ "border-radius":"18px",
+ "-webkit-border-radius": "18px", // Safari and Chrome
+ "-moz-border-radius": "18px", // Firefox
+ "-khtml-border-radius": "18px", // Konqueror
+ "font-family":"'Courier New',Courier",
+ "font-size":"24px",
+ color:"#F0F0F0"
+ },
+ ".MathJax_MenuClose span": {
+ display:"block", "background-color":"#AAA", border:"1.5px solid",
+ "border-radius":"18px",
+ "-webkit-border-radius": "18px", // Safari and Chrome
+ "-moz-border-radius": "18px", // Firefox
+ "-khtml-border-radius": "18px", // Konqueror
+ "line-height":0,
+ padding:"8px 0 6px" // may need to be browser-specific
+ },
+ ".MathJax_MenuClose:hover": {
+ color:"white!important",
+ border:"2px solid #CCC!important"
+ },
+ ".MathJax_MenuClose:hover span": {
+ "background-color":"#CCC!important"
+ },
+ ".MathJax_MenuClose:hover:focus": {
+ outline:"none"
+ }
+ }
+ });
+
+ var FALSE, HOVER, KEY;
+ HUB.Register.StartupHook("MathEvents Ready",function () {
+ FALSE = MathJax.Extension.MathEvents.Event.False;
+ HOVER = MathJax.Extension.MathEvents.Hover;
+ KEY = MathJax.Extension.MathEvents.Event.KEY;
+ });
+
+
+ /*************************************************************/
+ /*
+ * Abstract class of all keyboard navigatable objects.
+ */
+ var NAV = MathJax.Object.Subclass({
+ /*
+ * Moving in the list of items.
+ */
+ Keydown: function(event, menu) {
+ switch (event.keyCode) {
+ case KEY.ESCAPE:
+ this.Remove(event, menu);
+ break;
+ case KEY.RIGHT:
+ this.Right(event, menu);
+ break;
+ case KEY.LEFT:
+ this.Left(event, menu);
+ break;
+ case KEY.UP:
+ this.Up(event, menu);
+ break;
+ case KEY.DOWN:
+ this.Down(event, menu);
+ break;
+ case KEY.RETURN:
+ case KEY.SPACE:
+ this.Space(event, menu);
+ break;
+ default:
+ return;
+ break;
+ }
+ return FALSE(event);
+ },
+ Escape: function(event, menu) { },
+ Right: function(event, menu) { },
+ Left: function(event, menu) { },
+ Up: function(event, menu) { },
+ Down: function(event, menu) { },
+ Space: function(event, menu) { }
+ }, {});
+
+
+ /*************************************************************/
+ /*
+ * The main menu class
+ */
+ var MENU = MathJax.Menu = NAV.Subclass({
+ version: VERSION,
+ items: [],
+ posted: false,
+ title: null,
+ margin: 5,
+
+ Init: function (def) {this.items = [].slice.call(arguments,0)},
+ With: function (def) {if (def) {HUB.Insert(this,def)}; return this},
+
+ /*
+ * Display the menu
+ */
+ Post: function (event,parent,forceLTR) {
+ if (!event) {event = window.event||{}}
+ var div = document.getElementById("MathJax_MenuFrame");
+ if (!div) {
+ div = MENU.Background(this);
+ delete ITEM.lastItem; delete ITEM.lastMenu;
+ delete MENU.skipUp;
+ SIGNAL.Post(["post",MENU.jax]);
+ MENU.isRTL = (MathJax.Localization.fontDirection() === "rtl");
+ }
+ var menu = HTML.Element("div",{
+ onmouseup: MENU.Mouseup, ondblclick: FALSE,
+ ondragstart: FALSE, onselectstart: FALSE, oncontextmenu: FALSE,
+ menuItem: this, className: "MathJax_Menu", onkeydown: MENU.Keydown,
+ role: "menu"
+ });
+ if (event.type === "contextmenu" || event.type === "mouseover")
+ menu.className += " MathJax_ContextMenu";
+ if (!forceLTR) {MathJax.Localization.setCSS(menu)}
+
+ for (var i = 0, m = this.items.length; i < m; i++) {this.items[i].Create(menu)}
+ if (MENU.isMobile) {
+ HTML.addElement(menu,"span",{
+ className: "MathJax_MenuClose", menu: parent,
+ ontouchstart: MENU.Close, ontouchend: FALSE, onmousedown: MENU.Close, onmouseup: FALSE
+ },[["span",{},"\u00D7"]]);
+ }
+
+ div.appendChild(menu);
+ this.posted = true;
+ if (menu.offsetWidth) menu.style.width = (menu.offsetWidth+2) + "px";
+ var x = event.pageX, y = event.pageY;
+ var bbox = document.body.getBoundingClientRect();
+ var styles = (window.getComputedStyle ? window.getComputedStyle(document.body) : {marginLeft: "0px"});
+ var bodyRight = bbox.right - Math.min(0,bbox.left) + parseFloat(styles.marginLeft);
+ if (!x && !y && "clientX" in event) {
+ x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
+ y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop;
+ }
+ if (!parent) {
+ var node = MENU.CurrentNode() || event.target;
+ if ((event.type === "keydown" || (!x && !y)) && node) {
+ var offsetX = window.pageXOffset || document.documentElement.scrollLeft;
+ var offsetY = window.pageYOffset || document.documentElement.scrollTop;
+ var rect = node.getBoundingClientRect();
+ x = (rect.right + rect.left) / 2 + offsetX;
+ y = (rect.bottom + rect.top) / 2 + offsetY;
+ }
+ if (x + menu.offsetWidth > bodyRight - this.margin)
+ {x = bodyRight - menu.offsetWidth - this.margin}
+ if (MENU.isMobile) {x = Math.max(5,x-Math.floor(menu.offsetWidth/2)); y -= 20}
+ MENU.skipUp = event.isContextMenu;
+ } else {
+ var side = "left", mw = parent.offsetWidth;
+ x = (MENU.isMobile ? 30 : mw - 2); y = 0;
+ while (parent && parent !== div) {
+ x += parent.offsetLeft; y += parent.offsetTop;
+ parent = parent.parentNode;
+ }
+ if (!MENU.isMobile) {
+ if ((MENU.isRTL && x - mw - menu.offsetWidth > this.margin) ||
+ (!MENU.isRTL && x + menu.offsetWidth > bodyRight - this.margin))
+ {side = "right"; x = Math.max(this.margin,x - mw - menu.offsetWidth + 6)}
+ }
+ if (!isPC) {
+ // in case these ever get implemented
+ menu.style["borderRadiusTop"+side] = 0; // Opera 10.5
+ menu.style["WebkitBorderRadiusTop"+side] = 0; // Safari and Chrome
+ menu.style["MozBorderRadiusTop"+side] = 0; // Firefox
+ menu.style["KhtmlBorderRadiusTop"+side] = 0; // Konqueror
+ }
+ }
+
+ menu.style.left = x+"px"; menu.style.top = y+"px";
+ if (document.selection && document.selection.empty) {document.selection.empty()}
+
+ // Focusing while keeping the scroll position.
+ var oldX = window.pageXOffset || document.documentElement.scrollLeft;
+ var oldY = window.pageYOffset || document.documentElement.scrollTop;
+ MENU.Focus(menu);
+ if (event.type === "keydown") {
+ MENU.skipMouseoverFromKey = true;
+ setTimeout(function() {delete MENU.skipMouseoverFromKey;}, CONFIG.delay);
+ }
+ window.scrollTo(oldX, oldY);
+ return FALSE(event);
+ },
+
+ /*
+ * Remove the menu from the screen
+ */
+ Remove: function (event,menu) {
+ SIGNAL.Post(["unpost",MENU.jax]);
+ var div = document.getElementById("MathJax_MenuFrame");
+ if (div) {
+ div.parentNode.removeChild(div);
+ if (this.msieFixedPositionBug) {detachEvent("onresize",MENU.Resize)}
+ }
+ if (MENU.jax.hover) {
+ delete MENU.jax.hover.nofade;
+ HOVER.UnHover(MENU.jax);
+ }
+ MENU.Unfocus(menu);
+ if (event.type === "mousedown") MENU.CurrentNode().blur();
+ return FALSE(event);
+ },
+
+ /*
+ * Find an item in a menu (or submenu) by name (Find) or ID (FindID).
+ * A list of names or IDs means descend into submenus.
+ */
+ Find: function (name) {return this.FindN(1,name,[].slice.call(arguments,1))},
+ FindId: function (name) {return this.FindN(0,name,[].slice.call(arguments,1))},
+ FindN: function (n,name,names) {
+ for (var i = 0, m = this.items.length; i < m; i++) {
+ if (this.items[i].name[n] === name) {
+ if (names.length) {
+ if (!this.items[i].submenu) {return null}
+ return this.items[i].submenu.FindN(n,names[0],names.slice(1));
+ }
+ return this.items[i];
+ }
+ }
+ return null;
+ },
+
+ /*
+ * Find the index of a menu item (so we can insert before or after it)
+ */
+ IndexOf: function (name) {return this.IndexOfN(1,name)},
+ IndexOfId: function (name) {return this.IndexOfN(0,name)},
+ IndexOfN: function (n,name) {
+ for (var i = 0, m = this.items.length; i < m; i++)
+ {if (this.items[i].name[n] === name) {return i}}
+ return null;
+ },
+
+ Right: function(event, menu) {
+ MENU.Right(event, menu);
+ },
+ Left: function(event, menu) {
+ MENU.Left(event, menu);
+ },
+ Up: function(event, menu) {
+ var node = menu.lastChild;
+ node.menuItem.Activate(event, node);
+ },
+ Down: function(event, menu) {
+ var node = menu.firstChild;
+ node.menuItem.Activate(event, node);
+ },
+ Space: function(event, menu) {
+ this.Remove(event, menu);
+ }
+ },{
+
+ config: CONFIG,
+
+ Remove: function (event) {return MENU.Event(event,this,"Remove")},
+ Mouseover: function (event) {return MENU.Event(event,this,"Mouseover")},
+ Mouseout: function (event) {return MENU.Event(event,this,"Mouseout")},
+ Mousedown: function (event) {return MENU.Event(event,this,"Mousedown")},
+ Mouseup: function (event) {return MENU.Event(event,this,"Mouseup")},
+ Keydown: function (event) {return MENU.Event(event,this,"Keydown")},
+ /*
+ * Events for mobile devices.
+ */
+ Touchstart: function (event) {return MENU.Event(event,this,"Touchstart")},
+ Touchend: function (event) {return MENU.Event(event,this,"Touchend")},
+ Close: function (event) {
+ return MENU.Event(event,this.menu||this.parentNode,(this.menu?"Touchend":"Remove"));
+ },
+ Event: function (event,menu,type,force) {
+ if (MENU.skipMouseover && type === "Mouseover" && !force) {return FALSE(event)}
+ if (MENU.skipMouseoverFromKey && type === "Mouseover") {
+ delete MENU.skipMouseoverFromKey;
+ return FALSE(event);
+ }
+ if (MENU.skipUp) {
+ if (type.match(/Mouseup|Touchend/)) {delete MENU.skipUp; return FALSE(event)}
+ if (type === "Touchstart" ||
+ (type === "Mousedown" && !MENU.skipMousedown)) {delete MENU.skipUp}
+ }
+ if (!event) {event = window.event}
+ var item = menu.menuItem;
+ if (item && item[type]) {return item[type](event,menu)}
+ return null;
+ },
+ /*
+ * Style for the background DIV
+ */
+ BGSTYLE: {
+ position:"absolute", left:0, top:0, "z-index":200,
+ width:"100%", height:"100%", border:0, padding:0, margin:0
+ },
+
+ Background: function (menu) {
+ var div = HTML.addElement(document.body,"div",
+ {style:this.BGSTYLE, id:"MathJax_MenuFrame"},
+ [["div",{style: this.BGSTYLE, menuItem: menu, onmousedown: this.Remove}]]);
+ var bg = div.firstChild;
+ if (MENU.msieBackgroundBug) {
+ // MSIE doesn't allow transparent background to be hit boxes, so
+ // fake it using opacity with solid background color
+ bg.style.backgroundColor = "white"; bg.style.filter = "alpha(opacity=0)";
+ }
+ if (MENU.msieFixedPositionBug) {
+ // MSIE can't do fixed position, so use a full-sized background
+ // and an onresize handler to update it (stupid, but necessary)
+ div.width = div.height = 0; this.Resize();
+ attachEvent("onresize",this.Resize);
+ } else {
+ // otherwise, use a fixed position DIV to cover the viewport
+ bg.style.position = "fixed";
+ }
+ return div;
+ },
+ Resize: function () {setTimeout(MENU.SetWH,0)},
+ SetWH: function () {
+ var bg = document.getElementById("MathJax_MenuFrame");
+ if (bg) {
+ bg = bg.firstChild;
+ bg.style.width = bg.style.height = "1px"; // so scrollWidth/Height will be right below
+ bg.style.width = document.body.scrollWidth + "px";
+ bg.style.height = document.body.scrollHeight + "px";
+ }
+ },
+
+ /*************************************************************/
+ /*
+ * Keyboard navigation of menu.
+ */
+ posted: false, // Is a menu open?
+ active: null, // The focused in HTML node in the menu.
+
+ GetNode: function(jax) {
+ var node = document.getElementById(jax.inputID + "-Frame");
+ return node.isMathJax ? node : node.firstChild;
+ },
+ CurrentNode: function() {
+ return MENU.GetNode(MENU.jax);
+ },
+ AllNodes: function() {
+ var jaxs = MathJax.Hub.getAllJax();
+ var nodes = [];
+ for (var i = 0, jax; jax = jaxs[i]; i++) {
+ nodes.push(MENU.GetNode(jax));
+ }
+ return nodes;
+ },
+ ActiveNode: function() {
+ return MENU.active;
+ },
+ FocusNode: function(node) {
+ MENU.active = node;
+ node.focus();
+ },
+ //
+ // Focus is a global affair, since we only ever want a single focused item.
+ //
+ Focus: function(menu) {
+ !MENU.posted ? MENU.Activate(menu) : MENU.ActiveNode().tabIndex = -1;
+ menu.tabIndex = 0;
+ MENU.FocusNode(menu);
+ },
+ Activate: function(event, menu) {
+ MENU.UnsetTabIndex();
+ MENU.posted = true;
+ },
+ Unfocus: function() {
+ MENU.ActiveNode().tabIndex = -1;
+ MENU.SetTabIndex();
+ MENU.FocusNode(MENU.CurrentNode());
+ MENU.posted = false;
+ },
+ MoveHorizontal: function(event, menu, move) {
+ if (!event.shiftKey) return;
+ var jaxs = MENU.AllNodes();
+ var len = jaxs.length;
+ if (len === 0) return;
+ var next = jaxs[MENU.Mod(move(MENU.IndexOf(jaxs, MENU.CurrentNode())), len)];
+ if (next === MENU.CurrentNode()) return;
+ MENU.menu.Remove(event, menu);
+ MENU.jax = MathJax.Hub.getJaxFor(next);
+ MENU.FocusNode(next);
+ MENU.menu.Post(null);
+ },
+ Right: function(event, menu) {
+ MENU.MoveHorizontal(event, menu, function(x) {return x + 1;});
+ },
+ Left: function(event, menu) {
+ MENU.MoveHorizontal(event, menu, function(x) {return x - 1;});
+ },
+ UnsetTabIndex: function () {
+ var jaxs = MENU.AllNodes();
+ for (var j = 0, jax; jax = jaxs[j]; j++) {
+ if (jax.tabIndex > 0) {
+ jax.oldTabIndex = jax.tabIndex;
+ }
+ jax.tabIndex = -1;
+ }
+ },
+ SetTabIndex: function () {
+ var jaxs = MENU.AllNodes();
+ for (var j = 0, jax; jax = jaxs[j]; j++) {
+ if (jax.oldTabIndex !== undefined) {
+ jax.tabIndex = jax.oldTabIndex
+ delete jax.oldTabIndex;
+ } else {
+ jax.tabIndex = HUB.getTabOrder(jax);
+ }
+ }
+ },
+
+ //TODO: Move to utility class.
+ // Computes a mod n.
+ Mod: function(a, n) {
+ return ((a % n) + n) % n;
+ },
+ IndexOf: (Array.prototype.indexOf ?
+ function (A, item, start) {return A.indexOf(item, start);} :
+ function (A, item, start) {
+ for (var i = (start || 0), j = A.length; i < j; i++) {
+ if (item === A[i]) return i;
+ }
+ return -1;
+ }),
+
+ saveCookie: function () {HTML.Cookie.Set("menu",this.cookie)},
+ getCookie: function () {this.cookie = HTML.Cookie.Get("menu")}
+
+ });
+
+ MathJax.Menu.NAV = NAV;
+
+ /*************************************************************/
+ /*
+ * Abstract class of menu items.
+ */
+ var ITEM = MENU.ITEM = NAV.Subclass({
+
+ name: "", // The menu item's label as [id,label] pair.
+ node: null, // The HTML node of the item.
+ menu: null, // The parent menu containing that item. HTML node.
+
+ Attributes: function(def) {
+ return HUB.Insert(
+ {onmouseup: MENU.Mouseup,
+ ondragstart: FALSE, onselectstart: FALSE, onselectend: FALSE,
+ ontouchstart: MENU.Touchstart, ontouchend: MENU.Touchend,
+ className: "MathJax_MenuItem", role: this.role,
+ menuItem: this},
+ def);
+ },
+
+ Create: function (menu) {
+ if (!this.hidden) {
+ var def = this.Attributes();
+ var label = this.Label(def,menu);
+ HTML.addElement(menu, "div", def, label);
+ }
+ },
+ Name: function () {return _(this.name[0],this.name[1])},
+
+ Mouseover: function (event,menu) {
+ if (menu.parentNode === MENU.ActiveNode().parentNode) {
+ this.Deactivate(MENU.ActiveNode());
+ }
+ this.Activate(event, menu);
+ },
+ Mouseout: function (event,menu) {
+ this.Deactivate(menu);
+ },
+ Mouseup: function (event,menu) {return this.Remove(event,menu)},
+
+
+ DeactivateSubmenus: function(menu) {
+ var menus = document.getElementById("MathJax_MenuFrame").childNodes,
+ items = ITEM.GetMenuNode(menu).childNodes;
+ for (var i = 0, m = items.length; i < m; i++) {
+ var item = items[i].menuItem;
+ // Deactivates submenu items.
+ if (item && item.submenu && item.submenu.posted &&
+ item !== menu.menuItem) {
+ item.Deactivate(items[i]);
+ }
+ }
+ this.RemoveSubmenus(menu, menus);
+ },
+ RemoveSubmenus: function(menu, menus) {
+ menus = menus || document.getElementById("MathJax_MenuFrame").childNodes;
+ var m = menus.length-1;
+ while (m >= 0 && ITEM.GetMenuNode(menu).menuItem !== menus[m].menuItem) {
+ menus[m].menuItem.posted = false;
+ menus[m].parentNode.removeChild(menus[m]);
+ m--;
+ }
+ },
+
+ Touchstart: function (event,menu) {return this.TouchEvent(event,menu,"Mousedown")},
+ Touchend: function (event,menu) {return this.TouchEvent(event,menu,"Mouseup")},
+ TouchEvent: function (event,menu,type) {
+ if (this !== ITEM.lastItem) {
+ if (ITEM.lastMenu) {MENU.Event(event,ITEM.lastMenu,"Mouseout")}
+ MENU.Event(event,menu,"Mouseover",true);
+ ITEM.lastItem = this; ITEM.lastMenu = menu;
+ }
+ if (this.nativeTouch) {return null}
+ MENU.Event(event,menu,type);
+ return false;
+ },
+
+ Remove: function (event,menu) {
+ menu = menu.parentNode.menuItem;
+ return menu.Remove(event,menu);
+ },
+
+ With: function (def) {if (def) {HUB.Insert(this,def)}; return this},
+
+ isRTL: function () {return MENU.isRTL},
+ rtlClass: function () {return (this.isRTL() ? " RTL" : "")}
+ }, {
+ GetMenuNode: function(item) {
+ return item.parentNode;
+ }
+ });
+
+ /*************************************************************/
+ /*
+ * Abstract class of menu items that are focusable and perform some action
+ */
+ MENU.ENTRY = MENU.ITEM.Subclass({
+ role: "menuitem", // Aria role.
+
+ Attributes: function(def) {
+ def = HUB.Insert(
+ {onmouseover: MENU.Mouseover, onmouseout: MENU.Mouseout,
+ onmousedown: MENU.Mousedown, onkeydown: MENU.Keydown,
+ "aria-disabled": !!this.disabled},
+ def);
+ def = this.SUPER(arguments).Attributes.call(this, def);
+ if (this.disabled) {
+ def.className += " MathJax_MenuDisabled";
+ }
+ return def;
+ },
+ MoveVertical: function(event, item, move) {
+ var menuNode = ITEM.GetMenuNode(item);
+ var items = [];
+ for (var i = 0, allItems = menuNode.menuItem.items, it;
+ it = allItems[i]; i++) {
+ if (!it.hidden) {
+ items.push(it);
+ }
+ }
+ var index = MENU.IndexOf(items, this);
+ if (index === -1) return;
+ var len = items.length;
+ var children = menuNode.childNodes;
+ do {
+ index = MENU.Mod(move(index), len);
+ } while (items[index].hidden || !children[index].role ||
+ children[index].role === "separator");
+ this.Deactivate(item);
+ items[index].Activate(event, children[index]);
+ },
+ Up: function(event, item) {
+ this.MoveVertical(event, item, function(x) { return x - 1; });
+ },
+ Down: function(event, item) {
+ this.MoveVertical(event, item, function(x) { return x + 1; });
+ },
+ Right: function(event, item) {
+ this.MoveHorizontal(event, item, MENU.Right, !this.isRTL());
+ },
+ Left: function(event, item) {
+ this.MoveHorizontal(event, item, MENU.Left, this.isRTL());
+ },
+ MoveHorizontal: function(event, item, move, rtl) {
+ var menuNode = ITEM.GetMenuNode(item);
+ if (menuNode.menuItem === MENU.menu && event.shiftKey) {
+ move(event, item);
+ }
+ if (rtl) return;
+ if (menuNode.menuItem !== MENU.menu) {
+ this.Deactivate(item);
+ }
+ var parentNodes = menuNode.previousSibling.childNodes;
+ var length = parentNodes.length;
+ while (length--) {
+ var parent = parentNodes[length];
+ if (parent.menuItem.submenu &&
+ parent.menuItem.submenu === menuNode.menuItem) {
+ MENU.Focus(parent);
+ break;
+ }
+ }
+ this.RemoveSubmenus(item);
+ },
+ Space: function (event, menu) {
+ this.Mouseup(event, menu);
+ },
+
+ Activate: function (event, menu) {
+ this.Deactivate(menu);
+ if (!this.disabled) {
+ menu.className += " MathJax_MenuActive";
+ }
+ this.DeactivateSubmenus(menu);
+ MENU.Focus(menu);
+ },
+ Deactivate: function (menu) {
+ menu.className = menu.className.replace(/ MathJax_MenuActive/,"");
+ }
+
+ });
+
+ /*************************************************************/
+ /*
+ * A menu item that performs a command when selected
+ */
+ MENU.ITEM.COMMAND = MENU.ENTRY.Subclass({
+ action: function () {},
+
+ Init: function (name,action,def) {
+ if (!isArray(name)) {name = [name,name]} // make [id,label] pair
+ this.name = name; this.action = action;
+ this.With(def);
+ },
+
+ Label: function (def,menu) {return [this.Name()]},
+ Mouseup: function (event,menu) {
+ if (!this.disabled) {
+ this.Remove(event,menu);
+ SIGNAL.Post(["command",this]);
+ this.action.call(this,event);
+ }
+ return FALSE(event);
+ }
+ });
+
+ /*************************************************************/
+ /*
+ * A menu item that posts a submenu
+ */
+ MENU.ITEM.SUBMENU = MENU.ENTRY.Subclass({
+ submenu: null, // the submenu
+ marker: "\u25BA", // the submenu arrow
+ markerRTL: "\u25C4", // the submenu arrow for RTL
+
+ Attributes: function(def) {
+ def = HUB.Insert({"aria-haspopup": "true"}, def);
+ def = this.SUPER(arguments).Attributes.call(this, def);
+ return def;
+ },
+ Init: function (name,def) {
+ if (!isArray(name)) {name = [name,name]} // make [id,label] pair
+ this.name = name; var i = 1;
+ if (!(def instanceof MENU.ITEM)) {this.With(def), i++}
+ this.submenu = MENU.apply(MENU,[].slice.call(arguments,i));
+ },
+ Label: function (def,menu) {
+ this.submenu.posted = false;
+ return [this.Name()+" ",["span",{
+ className:"MathJax_MenuArrow" + this.rtlClass()
+ },[this.isRTL() ? this.markerRTL : this.marker]]];
+ },
+ Timer: function (event,menu) {
+ this.ClearTimer();
+ event = {type: event.type,
+ clientX: event.clientX, clientY: event.clientY}; // MSIE can't pass the event below
+ this.timer = setTimeout(CALLBACK(["Mouseup",this,event,menu]),CONFIG.delay);
+ },
+ ClearTimer: function() {
+ if (this.timer) {
+ clearTimeout(this.timer);
+ }
+ },
+ Touchend: function (event,menu) {
+ var forceout = this.submenu.posted;
+ var result = this.SUPER(arguments).Touchend.apply(this,arguments);
+ if (forceout) {this.Deactivate(menu); delete ITEM.lastItem; delete ITEM.lastMenu}
+ return result;
+ },
+ Mouseout: function(event, menu) {
+ if (!this.submenu.posted) {
+ this.Deactivate(menu);
+ }
+ this.ClearTimer();
+ },
+ Mouseover: function(event, menu) {
+ this.Activate(event, menu);
+ },
+ Mouseup: function (event,menu) {
+ if (!this.disabled) {
+ if (!this.submenu.posted) {
+ this.ClearTimer();
+ this.submenu.Post(event, menu, this.ltr);
+ MENU.Focus(menu);
+ } else {
+ this.DeactivateSubmenus(menu);
+ }
+ }
+ return FALSE(event);
+ },
+ Activate: function (event, menu) {
+ if (!this.disabled) {
+ this.Deactivate(menu);
+ menu.className += " MathJax_MenuActive";
+ }
+ if (!this.submenu.posted) {
+ this.DeactivateSubmenus(menu);
+ if (!MENU.isMobile) {
+ this.Timer(event,menu);
+ }
+ }
+ MENU.Focus(menu);
+ },
+ MoveVertical: function(event, item, move) {
+ this.ClearTimer();
+ this.SUPER(arguments).MoveVertical.apply(this, arguments);
+ },
+ MoveHorizontal: function(event, menu, move, rtl) {
+ if (!rtl) {
+ this.SUPER(arguments).MoveHorizontal.apply(this, arguments);
+ return;
+ }
+ if (this.disabled) return;
+ if (!this.submenu.posted) {
+ this.Activate(event, menu);
+ return;
+ }
+ var submenuNodes = ITEM.GetMenuNode(menu).nextSibling.childNodes;
+ if (submenuNodes.length > 0) {
+ this.submenu.items[0].Activate(event, submenuNodes[0]);
+ }
+ }
+ });
+
+ /*************************************************************/
+ /*
+ * A menu item that is one of several radio buttons
+ */
+ MENU.ITEM.RADIO = MENU.ENTRY.Subclass({
+ variable: null, // the variable name
+ marker: (isPC ? "\u25CF" : "\u2713"), // the checkmark
+ role: "menuitemradio",
+
+ Attributes: function(def) {
+ var checked = CONFIG.settings[this.variable] === this.value ? "true" : "false";
+ def = HUB.Insert({"aria-checked": checked}, def);
+ def = this.SUPER(arguments).Attributes.call(this, def);
+ return def;
+ },
+ Init: function (name,variable,def) {
+ if (!isArray(name)) {name = [name,name]} // make [id,label] pair
+ this.name = name; this.variable = variable; this.With(def);
+ if (this.value == null) {this.value = this.name[0]}
+ },
+ Label: function (def,menu) {
+ var span = {className:"MathJax_MenuRadioCheck" + this.rtlClass()};
+ if (CONFIG.settings[this.variable] !== this.value) {
+ span = {style:{display:"none"}};
+ }
+ return [["span",span,[this.marker]]," "+this.Name()];
+ },
+ Mouseup: function (event,menu) {
+ if (!this.disabled) {
+ var child = menu.parentNode.childNodes;
+ for (var i = 0, m = child.length; i < m; i++) {
+ var item = child[i].menuItem;
+ if (item && item.variable === this.variable) {
+ child[i].firstChild.style.display = "none";
+ }
+ }
+ menu.firstChild.display = "";
+ CONFIG.settings[this.variable] = this.value;
+ MENU.cookie[this.variable] = CONFIG.settings[this.variable]; MENU.saveCookie();
+ SIGNAL.Post(["radio button",this]);
+ }
+ this.Remove(event,menu);
+ if (this.action && !this.disabled) {this.action.call(MENU,this)}
+ return FALSE(event);
+ }
+ });
+
+ /*************************************************************/
+ /*
+ * A menu item that is checkable
+ */
+ MENU.ITEM.CHECKBOX = MENU.ENTRY.Subclass({
+ variable: null, // the variable name
+ marker: "\u2713", // the checkmark
+ role: "menuitemcheckbox",
+
+ Attributes: function(def) {
+ var checked = CONFIG.settings[this.variable] ? "true" : "false";
+ def = HUB.Insert({"aria-checked": checked}, def);
+ def = this.SUPER(arguments).Attributes.call(this, def);
+ return def;
+ },
+ Init: function (name,variable,def) {
+ if (!isArray(name)) {name = [name,name]} // make [id,label] pair
+ this.name = name; this.variable = variable; this.With(def);
+ },
+ Label: function (def,menu) {
+ var span = {className:"MathJax_MenuCheck" + this.rtlClass()};
+ if (!CONFIG.settings[this.variable]) {span = {style:{display:"none"}}}
+ return [["span",span,[this.marker]]," "+this.Name()];
+ },
+ Mouseup: function (event,menu) {
+ if (!this.disabled) {
+ menu.firstChild.display = (CONFIG.settings[this.variable] ? "none" : "");
+ CONFIG.settings[this.variable] = !CONFIG.settings[this.variable];
+ MENU.cookie[this.variable] = CONFIG.settings[this.variable]; MENU.saveCookie();
+ SIGNAL.Post(["checkbox",this]);
+ }
+ this.Remove(event,menu);
+ if (this.action && !this.disabled) {this.action.call(MENU,this)}
+ return FALSE(event);
+ }
+ });
+
+ /*************************************************************/
+ /*
+ * A menu item that is a label
+ */
+ MENU.ITEM.LABEL = MENU.ENTRY.Subclass({
+ role: "menuitem", // Aria role.
+
+ Init: function (name,def) {
+ if (!isArray(name)) {name = [name,name]} // make [id,label] pair
+ this.name = name; this.With(def);
+ },
+ Label: function (def,menu) {
+ def.className += " MathJax_MenuLabel";
+ return [this.Name()];
+ },
+ Activate: function(event, menu) {
+ this.Deactivate(menu);
+ MENU.Focus(menu);
+ },
+ Mouseup: function (event,menu) { }
+ });
+
+ /*************************************************************/
+ /*
+ * A rule in a menu
+ */
+ MENU.ITEM.RULE = MENU.ITEM.Subclass({
+ role: "separator",
+
+ Attributes: function(def) {
+ def = HUB.Insert({"aria-orientation": "vertical"}, def);
+ def = this.SUPER(arguments).Attributes.call(this, def);
+ return def;
+ },
+ Label: function (def,menu) {
+ def.className += " MathJax_MenuRule";
+ return null;
+ }
+ });
+
+ /*************************************************************/
+ /*************************************************************/
+
+ /*
+ * Handle the ABOUT box
+ */
+ MENU.About = function (event) {
+ var font = MENU.About.GetFont();
+ var format = MENU.About.GetFormat();
+ var jax = ["MathJax.js v"+MathJax.fileversion,["br"]];
+ jax.push(["div",{style:{"border-top":"groove 2px",margin:".25em 0"}}]);
+ MENU.About.GetJax(jax,MathJax.InputJax,["InputJax","%1 Input Jax v%2"]);
+ MENU.About.GetJax(jax,MathJax.OutputJax,["OutputJax","%1 Output Jax v%2"]);
+ MENU.About.GetJax(jax,MathJax.ElementJax,["ElementJax","%1 Element Jax v%2"]);
+ jax.push(["div",{style:{"border-top":"groove 2px",margin:".25em 0"}}]);
+ MENU.About.GetJax(jax,MathJax.Extension,["Extension","%1 Extension v%2"],true);
+ jax.push(["div",{style:{"border-top":"groove 2px",margin:".25em 0"}}],["center",{},[
+ HUB.Browser + " v"+HUB.Browser.version + (format ?
+ " \u2014 " + _(format.replace(/ /g,""),format) : "")
+ ]]);
+ MENU.About.div = MENU.Background(MENU.About);
+ var about = HTML.addElement(MENU.About.div,"div",{
+ id: "MathJax_About", tabIndex: 0, onkeydown: MENU.About.Keydown
+ },[
+ ["b",{style:{fontSize:"120%"}},["MathJax"]]," v"+MathJax.version,["br"],
+ _(font.replace(/ /g,""),"using "+font),["br"],["br"],
+ ["span",{style:{
+ display:"inline-block", "text-align":"left", "font-size":"80%",
+ "max-height":"20em", overflow:"auto",
+ "background-color":"#E4E4E4", padding:".4em .6em", border:"1px inset"
+ }, tabIndex: 0},jax],["br"],["br"],
+ ["a",{href:"http://www.mathjax.org/"},["www.mathjax.org"]],
+ ["span",{className:"MathJax_MenuClose",id:"MathJax_AboutClose",
+ onclick:MENU.About.Remove,
+ onkeydown: MENU.About.Keydown, tabIndex: 0, role: "button",
+ "aria-label": _("CloseAboutDialog","Close about MathJax dialog")},
+ [["span",{},"\u00D7"]]]
+ ]);
+ if (event.type === "mouseup") about.className += " MathJax_MousePost";
+ about.focus();
+ MathJax.Localization.setCSS(about);
+ var doc = (document.documentElement||{});
+ var H = window.innerHeight || doc.clientHeight || doc.scrollHeight || 0;
+ if (MENU.prototype.msieAboutBug) {
+ about.style.width = "20em"; about.style.position = "absolute";
+ about.style.left = Math.floor((document.documentElement.scrollWidth - about.offsetWidth)/2)+"px";
+ about.style.top = (Math.floor((H-about.offsetHeight)/3)+document.body.scrollTop)+"px";
+ } else {
+ about.style.marginLeft = Math.floor(-about.offsetWidth/2)+"px";
+ about.style.top = Math.floor((H-about.offsetHeight)/3)+"px";
+ }
+ };
+ MENU.About.Remove = function (event) {
+ if (MENU.About.div) {document.body.removeChild(MENU.About.div); delete MENU.About.div}
+ };
+ MENU.About.Keydown = function(event) {
+ if (event.keyCode === KEY.ESCAPE ||
+ (this.id === "MathJax_AboutClose" &&
+ (event.keyCode === KEY.SPACE || event.keyCode === KEY.RETURN))) {
+ MENU.About.Remove(event);
+ MENU.CurrentNode().focus();
+ FALSE(event);
+ }
+ },
+ MENU.About.GetJax = function (jax,JAX,type,noTypeCheck) {
+ var info = [];
+ for (var id in JAX) {if (JAX.hasOwnProperty(id) && JAX[id]) {
+ if ((noTypeCheck && JAX[id].version) || (JAX[id].isa && JAX[id].isa(JAX)))
+ {info.push(_(type[0],type[1],(JAX[id].id||id),JAX[id].version))}
+ }}
+ info.sort();
+ for (var i = 0, m = info.length; i < m; i++) {jax.push(info[i],["br"])}
+ return jax;
+ };
+ MENU.About.GetFont = function () {
+ var jax = MathJax.Hub.outputJax["jax/mml"][0] || {};
+ var font = {
+ SVG: "web SVG",
+ CommonHTML: "web TeX",
+ "HTML-CSS": (jax.imgFonts ? "image" : (jax.webFonts ? "web" : "local")+" "+jax.fontInUse)
+ }[jax.id] || "generic";
+ return font + " fonts";
+ };
+ MENU.About.GetFormat = function () {
+ var jax = MathJax.Hub.outputJax["jax/mml"][0] || {};
+ if (jax.id !== "HTML-CSS"|| !jax.webFonts || jax.imgFonts) return;
+ return jax.allowWebFonts.replace(/otf/,"woff or otf") + " fonts";
+ };
+
+
+ /*
+ * Handle the MathJax HELP menu
+ */
+ MENU.Help = function (event) {
+ AJAX.Require("[MathJax]/extensions/HelpDialog.js",
+ function () {MathJax.Extension.Help.Dialog({type:event.type})});
+ };
+
+ /*
+ * Handle showing of element's source
+ */
+ MENU.ShowSource = function (event) {
+ if (!event) {event = window.event}
+ var EVENT = {screenX:event.screenX, screenY:event.screenY};
+ if (!MENU.jax) return;
+ if (this.format === "MathML") {
+ var MML = MathJax.ElementJax.mml;
+ if (MML && typeof(MML.mbase.prototype.toMathML) !== "undefined") {
+ // toMathML() can call MathJax.Hub.RestartAfter, so trap errors and check
+ try {MENU.ShowSource.Text(MENU.jax.root.toMathML("",MENU.jax),event)} catch (err) {
+ if (!err.restart) {throw err}
+ CALLBACK.After([this,MENU.ShowSource,EVENT],err.restart);
+ }
+ } else if (!AJAX.loadingToMathML) {
+ AJAX.loadingToMathML = true;
+ MENU.ShowSource.Window(event); // WeBKit needs to open window on click event
+ CALLBACK.Queue(
+ AJAX.Require("[MathJax]/extensions/toMathML.js"),
+ function () {
+ delete AJAX.loadingToMathML;
+ if (!MML.mbase.prototype.toMathML) {MML.mbase.prototype.toMathML = function () {}}
+ },
+ [this,MENU.ShowSource,EVENT] // call this function again
+ );
+ return;
+ }
+ } else if (this.format === "Error") {
+ MENU.ShowSource.Text(MENU.jax.errorText,event);
+ } else if (CONFIG.semanticsAnnotations[this.format]) {
+ var annotation = MENU.jax.root.getAnnotation(this.format);
+ if (annotation.data[0]) MENU.ShowSource.Text(annotation.data[0].toString());
+ } else {
+ if (MENU.jax.originalText == null) {
+ alert(_("NoOriginalForm","No original form available"));
+ return;
+ }
+ MENU.ShowSource.Text(MENU.jax.originalText,event);
+ }
+ };
+ MENU.ShowSource.Window = function (event) {
+ if (!MENU.ShowSource.w) {
+ var def = [], DEF = CONFIG.windowSettings;
+ for (var id in DEF) {if (DEF.hasOwnProperty(id)) {def.push(id+"="+DEF[id])}}
+ MENU.ShowSource.w = window.open("","_blank",def.join(","));
+ }
+ return MENU.ShowSource.w;
+ };
+ MENU.ShowSource.Text = function (text,event) {
+ var w = MENU.ShowSource.Window(event); delete MENU.ShowSource.w;
+ text = text.replace(/^\s*/,"").replace(/\s*$/,"");
+ text = text.replace(/&/g,"&").replace(//g,">");
+ var title = _("EqSource","MathJax Equation Source");
+ if (MENU.isMobile) {
+ w.document.open();
+ w.document.write(""+title+" ");
+ w.document.write(""+text+"
");
+ w.document.write("
");
+ w.document.write("");
+ w.document.close();
+ } else {
+ w.document.open();
+ w.document.write(""+title+" ");
+ w.document.write(""+text+"
");
+ w.document.write("");
+ w.document.close();
+ var table = w.document.body.firstChild;
+ setTimeout(function () {
+ var H = (w.outerHeight-w.innerHeight)||30, W = (w.outerWidth-w.innerWidth)||30, x, y;
+ W = Math.max(140,Math.min(Math.floor(.5*screen.width),table.offsetWidth+W+25));
+ H = Math.max(40,Math.min(Math.floor(.5*screen.height),table.offsetHeight+H+25));
+ if (MENU.prototype.msieHeightBug) {H += 35}; // for title bar in XP
+ w.resizeTo(W,H);
+ var X; try {X = event.screenX} catch (e) {}; // IE8 throws an error accessing screenX
+ if (event && X != null) {
+ x = Math.max(0,Math.min(event.screenX-Math.floor(W/2), screen.width-W-20));
+ y = Math.max(0,Math.min(event.screenY-Math.floor(H/2), screen.height-H-20));
+ w.moveTo(x,y);
+ }
+ },50);
+ }
+ };
+
+ /*
+ * Handle rescaling all the math
+ */
+ MENU.Scale = function () {
+ var JAX = ["CommonHTML","HTML-CSS","SVG","NativeMML","PreviewHTML"], m = JAX.length,
+ SCALE = 100, i, jax;
+ for (i = 0; i < m; i++) {
+ jax = OUTPUT[JAX[i]];
+ if (jax) {SCALE = jax.config.scale; break}
+ }
+ var scale = prompt(_("ScaleMath","Scale all mathematics (compared to surrounding text) by"),SCALE+"%");
+ if (scale) {
+ if (scale.match(/^\s*\d+(\.\d*)?\s*%?\s*$/)) {
+ scale = parseFloat(scale);
+ if (scale) {
+ if (scale !== SCALE) {
+ for (i = 0; i < m; i++) {
+ jax = OUTPUT[JAX[i]];
+ if (jax) jax.config.scale = scale;
+ }
+ MENU.cookie.scale = HUB.config.scale = scale;
+ MENU.saveCookie();
+ HUB.Queue(["Rerender",HUB]);
+ }
+ } else {alert(_("NonZeroScale","The scale should not be zero"))}
+ } else {alert(_("PercentScale",
+ "The scale should be a percentage (e.g., 120%%)"))}
+ }
+ };
+
+ /*
+ * Handle loading the zoom code
+ */
+ MENU.Zoom = function () {
+ if (!MathJax.Extension.MathZoom) {AJAX.Require("[MathJax]/extensions/MathZoom.js")}
+ };
+
+ /*
+ * Handle changing the renderer
+ */
+ MENU.Renderer = function () {
+ var jax = HUB.outputJax["jax/mml"];
+ if (jax[0] !== CONFIG.settings.renderer) {
+ var BROWSER = HUB.Browser, message, MESSAGE = MENU.Renderer.Messages, warned;
+ //
+ // Check that the new renderer is appropriate for the browser
+ //
+ switch (CONFIG.settings.renderer) {
+ case "NativeMML":
+ if (!CONFIG.settings.warnedMML) {
+ if (BROWSER.isChrome && BROWSER.version.substr(0,3) !== "24.") {message = MESSAGE.MML.WebKit}
+ else if (BROWSER.isSafari && !BROWSER.versionAtLeast("5.0")) {message = MESSAGE.MML.WebKit}
+ else if (BROWSER.isMSIE) {if (!BROWSER.hasMathPlayer) {message = MESSAGE.MML.MSIE}}
+ else if (BROWSER.isEdge) {message = MESSAGE.MML.WebKit}
+ else {message = MESSAGE.MML[BROWSER]}
+ warned = "warnedMML";
+ }
+ break;
+
+ case "SVG":
+ if (!CONFIG.settings.warnedSVG) {
+ if (BROWSER.isMSIE && !isIE9) {message = MESSAGE.SVG.MSIE}
+ }
+ break;
+ }
+ if (message) {
+ message = _(message[0],message[1]);
+ message += "\n\n";
+ message += _("SwitchAnyway",
+ "Switch the renderer anyway?\n\n" +
+ "(Press OK to switch, CANCEL to continue with the current renderer)");
+ MENU.cookie.renderer = jax[0].id; MENU.saveCookie();
+ if (!confirm(message)) {
+ MENU.cookie.renderer = CONFIG.settings.renderer = HTML.Cookie.Get("menu").renderer;
+ MENU.saveCookie();
+ return;
+ }
+ if (warned) {MENU.cookie.warned = CONFIG.settings.warned = true}
+ MENU.cookie.renderer = CONFIG.settings.renderer; MENU.saveCookie();
+ }
+ HUB.Queue(
+ ["setRenderer",HUB,CONFIG.settings.renderer,"jax/mml"],
+ ["Rerender",HUB]
+ );
+ }
+ };
+ MENU.Renderer.Messages = {
+ MML: {
+ WebKit: ["WebkitNativeMMLWarning",
+ "Your browser doesn't seem to support MathML natively, " +
+ "so switching to MathML output may cause the mathematics " +
+ "on the page to become unreadable."],
+
+ MSIE: ["MSIENativeMMLWarning",
+ "Internet Explorer requires the MathPlayer plugin " +
+ "in order to process MathML output."],
+
+ Opera: ["OperaNativeMMLWarning",
+ "Opera's support for MathML is limited, so switching to " +
+ "MathML output may cause some expressions to render poorly."],
+
+ Safari: ["SafariNativeMMLWarning",
+ "Your browser's native MathML does not implement all the features " +
+ "used by MathJax, so some expressions may not render properly."],
+
+ Firefox: ["FirefoxNativeMMLWarning",
+ "Your browser's native MathML does not implement all the features " +
+ "used by MathJax, so some expressions may not render properly."]
+ },
+
+ SVG: {
+ MSIE: ["MSIESVGWarning",
+ "SVG is not implemented in Internet Explorer prior to " +
+ "IE9 or when it is emulating IE8 or below. " +
+ "Switching to SVG output will cause the mathematics to " +
+ "not display properly."]
+ }
+ };
+
+ /*
+ * Toggle assistive MML settings
+ */
+ MENU.AssistiveMML = function (item,restart) {
+ var AMML = MathJax.Extension.AssistiveMML;
+ if (!AMML) {
+ // Try to load the extension, but only try once.
+ if (!restart)
+ AJAX.Require("[MathJax]/extensions/AssistiveMML.js",["AssistiveMML",MENU,item,true]);
+ return;
+ }
+ MathJax.Hub.Queue([(CONFIG.settings.assistiveMML ? "Add" : "Remove")+"AssistiveMathML",AMML]);
+ };
+
+ /*
+ * Handle setting the HTMLCSS fonts
+ */
+ MENU.Font = function () {
+ var HTMLCSS = OUTPUT["HTML-CSS"]; if (!HTMLCSS) return;
+ document.location.reload();
+ };
+
+ /*
+ * Handle selection of locale and rerender the page
+ */
+ MENU.Locale = function () {
+ MathJax.Localization.setLocale(CONFIG.settings.locale);
+ MathJax.Hub.Queue(["Reprocess",MathJax.Hub]); // FIXME: Just reprocess error messages?
+ };
+ MENU.LoadLocale = function () {
+ var url = prompt(_("LoadURL","Load translation data from this URL:"));
+ if (url) {
+ if (!url.match(/\.js$/)) {
+ alert(_("BadURL",
+ "The URL should be for a javascript file that defines MathJax translation data. " +
+ "Javascript file names should end with '.js'"
+ ));
+ }
+ AJAX.Require(url,function (status) {
+ if (status != AJAX.STATUS.OK) {alert(_("BadData","Failed to load translation data from %1",url))}
+ });
+ }
+ };
+
+ /*
+ * Handle setting MathPlayer events
+ */
+ MENU.MPEvents = function (item) {
+ var discoverable = CONFIG.settings.discoverable,
+ MESSAGE = MENU.MPEvents.Messages;
+ if (!isIE9) {
+ if (CONFIG.settings.mpMouse && !confirm(_.apply(_,MESSAGE.IE8warning))) {
+ delete MENU.cookie.mpContext; delete CONFIG.settings.mpContext;
+ delete MENU.cookie.mpMouse; delete CONFIG.settings.mpMouse;
+ MENU.saveCookie();
+ return;
+ }
+ CONFIG.settings.mpContext = CONFIG.settings.mpMouse;
+ MENU.cookie.mpContext = MENU.cookie.mpMouse = CONFIG.settings.mpMouse;
+ MENU.saveCookie();
+ MathJax.Hub.Queue(["Rerender",MathJax.Hub])
+ } else if (!discoverable && item.name[1] === "Menu Events" && CONFIG.settings.mpContext) {
+ alert(_.apply(_,MESSAGE.IE9warning));
+ }
+ };
+
+ MENU.MPEvents.Messages = {
+ IE8warning: ["IE8warning",
+ "This will disable the MathJax menu and zoom features, " +
+ "but you can Alt-Click on an expression to obtain the MathJax " +
+ "menu instead.\n\nReally change the MathPlayer settings?"],
+
+ IE9warning: ["IE9warning",
+ "The MathJax contextual menu will be disabled, but you can " +
+ "Alt-Click on an expression to obtain the MathJax menu instead."]
+ };
+
+ /*************************************************************/
+ /*************************************************************/
+
+ HUB.Browser.Select({
+ MSIE: function (browser) {
+ var quirks = (document.compatMode === "BackCompat");
+ var isIE8 = browser.versionAtLeast("8.0") && document.documentMode > 7;
+ MENU.Augment({
+ margin: 20,
+ msieBackgroundBug: ((document.documentMode||0) < 9),
+ msieFixedPositionBug: (quirks || !isIE8),
+ msieAboutBug: quirks,
+ msieHeightBug: ((document.documentMode||0) < 9)
+ // height of window doesn't include title bar in XP
+ });
+ if (isIE9) {
+ delete CONFIG.styles["#MathJax_About"].filter;
+ delete CONFIG.styles[".MathJax_Menu"].filter;
+ }
+ },
+ Firefox: function (browser) {
+ MENU.skipMouseover = browser.isMobile && browser.versionAtLeast("6.0");
+ MENU.skipMousedown = browser.isMobile;
+ }
+ });
+ MENU.isMobile = HUB.Browser.isMobile;
+ MENU.noContextMenu = HUB.Browser.noContextMenu;
+
+ /*************************************************************/
+
+ //
+ // Creates the locale menu from the list of locales in MathJax.Localization.strings
+ //
+ MENU.CreateLocaleMenu = function () {
+ if (!MENU.menu) return;
+ var menu = MENU.menu.Find("Language").submenu, items = menu.items;
+ //
+ // Get the names of the languages and sort them
+ //
+ var locales = [], LOCALE = MathJax.Localization.strings;
+ for (var id in LOCALE) {if (LOCALE.hasOwnProperty(id)) {locales.push(id)}}
+ locales = locales.sort(); menu.items = [];
+ //
+ // Add a menu item for each
+ //
+ for (var i = 0, m = locales.length; i < m; i++) {
+ var title = LOCALE[locales[i]].menuTitle;
+ if (title) {title += " ("+locales[i]+")"} else {title = locales[i]}
+ menu.items.push(ITEM.RADIO([locales[i],title],"locale",{action:MENU.Locale}));
+ }
+ //
+ // Add the rule and "Load from URL" items
+ //
+ menu.items.push(items[items.length-2],items[items.length-1]);
+ };
+
+ //
+ // Create the annotation menu from MathJax.Hub.config.semanticsAnnotations
+ //
+ MENU.CreateAnnotationMenu = function () {
+ if (!MENU.menu) return;
+ var menu = MENU.menu.Find("Show Math As","Annotation").submenu;
+ var annotations = CONFIG.semanticsAnnotations;
+ for (var a in annotations) {
+ if (annotations.hasOwnProperty(a)) {
+ menu.items.push(ITEM.COMMAND([a,a], MENU.ShowSource, {hidden: true, nativeTouch: true, format: a}));
+ }
+ }
+ };
+
+ /*************************************************************/
+
+ HUB.Register.StartupHook("End Config",function () {
+
+ /*
+ * Get the menu settings from the HUB (which includes the
+ * data from the cookie already), and add the format, if
+ * it wasn't set in the cookie.
+ */
+ CONFIG.settings = HUB.config.menuSettings;
+ if (typeof(CONFIG.settings.showRenderer) !== "undefined") {CONFIG.showRenderer = CONFIG.settings.showRenderer}
+ if (typeof(CONFIG.settings.showFontMenu) !== "undefined") {CONFIG.showFontMenu = CONFIG.settings.showFontMenu}
+ if (typeof(CONFIG.settings.showContext) !== "undefined") {CONFIG.showContext = CONFIG.settings.showContext}
+ MENU.getCookie();
+
+ /*
+ * The main menu
+ */
+ // Localization: items used as key, should be refactored.
+ MENU.menu = MENU(
+ ITEM.SUBMENU(["Show","Show Math As"],
+ ITEM.COMMAND(["MathMLcode","MathML Code"], MENU.ShowSource, {nativeTouch: true, format: "MathML"}),
+ ITEM.COMMAND(["Original","Original Form"], MENU.ShowSource, {nativeTouch: true}),
+ ITEM.SUBMENU(["Annotation","Annotation"], {disabled:true}),
+ ITEM.RULE(),
+ ITEM.CHECKBOX(["texHints","Show TeX hints in MathML"], "texHints"),
+ ITEM.CHECKBOX(["semantics","Add original form as annotation"], "semantics")
+ ),
+ ITEM.RULE(),
+ ITEM.SUBMENU(["Settings","Math Settings"],
+ ITEM.SUBMENU(["ZoomTrigger","Zoom Trigger"],
+ ITEM.RADIO(["Hover","Hover"], "zoom", {action: MENU.Zoom}),
+ ITEM.RADIO(["Click","Click"], "zoom", {action: MENU.Zoom}),
+ ITEM.RADIO(["DoubleClick","Double-Click"], "zoom", {action: MENU.Zoom}),
+ ITEM.RADIO(["NoZoom","No Zoom"], "zoom", {value: "None"}),
+ ITEM.RULE(),
+ ITEM.LABEL(["TriggerRequires","Trigger Requires:"]),
+ ITEM.CHECKBOX((HUB.Browser.isMac ? ["Option","Option"] : ["Alt","Alt"]), "ALT"),
+ ITEM.CHECKBOX(["Command","Command"], "CMD", {hidden: !HUB.Browser.isMac}),
+ ITEM.CHECKBOX(["Control","Control"], "CTRL", {hidden: HUB.Browser.isMac}),
+ ITEM.CHECKBOX(["Shift","Shift"], "Shift")
+ ),
+ ITEM.SUBMENU(["ZoomFactor","Zoom Factor"],
+ ITEM.RADIO("125%", "zscale"),
+ ITEM.RADIO("133%", "zscale"),
+ ITEM.RADIO("150%", "zscale"),
+ ITEM.RADIO("175%", "zscale"),
+ ITEM.RADIO("200%", "zscale"),
+ ITEM.RADIO("250%", "zscale"),
+ ITEM.RADIO("300%", "zscale"),
+ ITEM.RADIO("400%", "zscale")
+ ),
+ ITEM.RULE(),
+ ITEM.SUBMENU(["Renderer","Math Renderer"], {hidden:!CONFIG.showRenderer},
+ ITEM.RADIO(["HTML-CSS","HTML-CSS"], "renderer", {action: MENU.Renderer}),
+ ITEM.RADIO(["CommonHTML","Common HTML"], "renderer", {action: MENU.Renderer, value:"CommonHTML"}),
+ ITEM.RADIO(["PreviewHTML","Preview HTML"],"renderer", {action: MENU.Renderer, value:"PreviewHTML"}),
+ ITEM.RADIO(["MathML","MathML"], "renderer", {action: MENU.Renderer, value:"NativeMML"}),
+ ITEM.RADIO(["SVG","SVG"], "renderer", {action: MENU.Renderer}),
+ ITEM.RADIO(["PlainSource","Plain Source"],"renderer", {action: MENU.Renderer, value:"PlainSource"}),
+ ITEM.RULE(),
+ ITEM.CHECKBOX(["FastPreview","Fast Preview"], "FastPreview")
+ ),
+ ITEM.SUBMENU("MathPlayer", {hidden:!HUB.Browser.isMSIE || !CONFIG.showMathPlayer,
+ disabled:!HUB.Browser.hasMathPlayer},
+ ITEM.LABEL(["MPHandles","Let MathPlayer Handle:"]),
+ ITEM.CHECKBOX(["MenuEvents","Menu Events"], "mpContext", {action: MENU.MPEvents, hidden:!isIE9}),
+ ITEM.CHECKBOX(["MouseEvents","Mouse Events"], "mpMouse", {action: MENU.MPEvents, hidden:!isIE9}),
+ ITEM.CHECKBOX(["MenuAndMouse","Mouse and Menu Events"], "mpMouse", {action: MENU.MPEvents, hidden:isIE9})
+ ),
+ ITEM.SUBMENU(["FontPrefs","Font Preference"], {hidden:!CONFIG.showFontMenu},
+ ITEM.LABEL(["ForHTMLCSS","For HTML-CSS:"]),
+ ITEM.RADIO(["Auto","Auto"], "font", {action: MENU.Font}),
+ ITEM.RULE(),
+ ITEM.RADIO(["TeXLocal","TeX (local)"], "font", {action: MENU.Font}),
+ ITEM.RADIO(["TeXWeb","TeX (web)"], "font", {action: MENU.Font}),
+ ITEM.RADIO(["TeXImage","TeX (image)"], "font", {action: MENU.Font}),
+ ITEM.RULE(),
+ ITEM.RADIO(["STIXLocal","STIX (local)"], "font", {action: MENU.Font}),
+ ITEM.RADIO(["STIXWeb","STIX (web)"], "font", {action: MENU.Font}),
+ ITEM.RULE(),
+ ITEM.RADIO(["AsanaMathWeb","Asana Math (web)"], "font", {action: MENU.Font}),
+ ITEM.RADIO(["GyrePagellaWeb","Gyre Pagella (web)"], "font", {action: MENU.Font}),
+ ITEM.RADIO(["GyreTermesWeb","Gyre Termes (web)"], "font", {action: MENU.Font}),
+ ITEM.RADIO(["LatinModernWeb","Latin Modern (web)"], "font", {action: MENU.Font}),
+ ITEM.RADIO(["NeoEulerWeb","Neo Euler (web)"], "font", {action: MENU.Font})
+ ),
+ ITEM.SUBMENU(["ContextMenu","Contextual Menu"], {hidden:!CONFIG.showContext},
+ ITEM.RADIO(["MathJax","MathJax"], "context"),
+ ITEM.RADIO(["Browser","Browser"], "context")
+ ),
+ ITEM.COMMAND(["Scale","Scale All Math ..."],MENU.Scale),
+ ITEM.RULE().With({hidden:!CONFIG.showDiscoverable, name:["","discover_rule"]}),
+ ITEM.CHECKBOX(["Discoverable","Highlight on Hover"], "discoverable", {hidden:!CONFIG.showDiscoverable})
+ ),
+ ITEM.SUBMENU(["Accessibility","Accessibility"],
+ ITEM.CHECKBOX(["AssistiveMML","Assistive MathML"], "assistiveMML", {action:MENU.AssistiveMML}),
+ ITEM.CHECKBOX(["InTabOrder","Include in Tab Order"], "inTabOrder")
+ ),
+ ITEM.SUBMENU(["Locale","Language"], {hidden:!CONFIG.showLocale, ltr:true},
+ ITEM.RADIO("en", "locale", {action: MENU.Locale}),
+ ITEM.RULE().With({hidden:!CONFIG.showLocaleURL, name:["","localURL_rule"]}),
+ ITEM.COMMAND(["LoadLocale","Load from URL ..."], MENU.LoadLocale, {hidden:!CONFIG.showLocaleURL})
+ ),
+ ITEM.RULE(),
+ ITEM.COMMAND(["About","About MathJax"],MENU.About),
+ ITEM.COMMAND(["Help","MathJax Help"],MENU.Help)
+ );
+
+ if (MENU.isMobile) {
+ (function () {
+ var settings = CONFIG.settings;
+ var trigger = MENU.menu.Find("Math Settings","Zoom Trigger").submenu;
+ trigger.items[0].disabled = trigger.items[1].disabled = true;
+ if (settings.zoom === "Hover" || settings.zoom == "Click") {settings.zoom = "None"}
+ trigger.items = trigger.items.slice(0,4);
+
+ if (navigator.appVersion.match(/[ (]Android[) ]/)) {
+ MENU.ITEM.SUBMENU.Augment({marker: "\u00BB"});
+ }
+ })();
+ }
+
+ MENU.CreateLocaleMenu();
+ MENU.CreateAnnotationMenu();
+ });
+
+ MENU.showRenderer = function (show) {
+ MENU.cookie.showRenderer = CONFIG.showRenderer = show; MENU.saveCookie();
+ MENU.menu.Find("Math Settings","Math Renderer").hidden = !show;
+ };
+ MENU.showMathPlayer = function (show) {
+ MENU.cookie.showMathPlayer = CONFIG.showMathPlayer = show; MENU.saveCookie();
+ MENU.menu.Find("Math Settings","MathPlayer").hidden = !show;
+ };
+ MENU.showFontMenu = function (show) {
+ MENU.cookie.showFontMenu = CONFIG.showFontMenu = show; MENU.saveCookie();
+ MENU.menu.Find("Math Settings","Font Preference").hidden = !show;
+ };
+ MENU.showContext = function (show) {
+ MENU.cookie.showContext = CONFIG.showContext = show; MENU.saveCookie();
+ MENU.menu.Find("Math Settings","Contextual Menu").hidden = !show;
+ };
+ MENU.showDiscoverable = function (show) {
+ MENU.cookie.showDiscoverable = CONFIG.showDiscoverable = show; MENU.saveCookie();
+ MENU.menu.Find("Math Settings","Highlight on Hover").hidden = !show;
+ MENU.menu.Find("Math Settings","discover_rule").hidden = !show;
+ };
+ MENU.showLocale = function (show) {
+ MENU.cookie.showLocale = CONFIG.showLocale = show; MENU.saveCookie();
+ MENU.menu.Find("Language").hidden = !show;
+ };
+
+ MathJax.Hub.Register.StartupHook("HTML-CSS Jax Ready",function () {
+ if (!MathJax.OutputJax["HTML-CSS"].config.imageFont)
+ {MENU.menu.Find("Math Settings","Font Preference","TeX (image)").disabled = true}
+ });
+
+ /*************************************************************/
+
+ CALLBACK.Queue(
+ HUB.Register.StartupHook("End Config",{}), // wait until config is complete
+ ["Styles",AJAX,CONFIG.styles],
+ ["Post",HUB.Startup.signal,"MathMenu Ready"],
+ ["loadComplete",AJAX,"[MathJax]/extensions/MathMenu.js"]
+ );
+
+})(MathJax.Hub,MathJax.HTML,MathJax.Ajax,MathJax.CallBack,MathJax.OutputJax);
diff --git a/_static/scipy-mathjax/extensions/MathZoom.js b/_static/scipy-mathjax/extensions/MathZoom.js
new file mode 100644
index 000000000..64a71411b
--- /dev/null
+++ b/_static/scipy-mathjax/extensions/MathZoom.js
@@ -0,0 +1,366 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/MathZoom.js
+ *
+ * Implements the zoom feature for enlarging math expressions. It is
+ * loaded automatically when the Zoom menu selection changes from "None".
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2010-2017 The MathJax Consortium
+ *
+ * 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.
+ */
+
+(function (HUB,HTML,AJAX,HTMLCSS,nMML) {
+ var VERSION = "2.7.1";
+
+ var CONFIG = HUB.CombineConfig("MathZoom",{
+ styles: {
+ //
+ // The styles for the MathZoom display box
+ //
+ "#MathJax_Zoom": {
+ position:"absolute", "background-color":"#F0F0F0", overflow:"auto",
+ display:"block", "z-index":301, padding:".5em", border:"1px solid black", margin:0,
+ "font-weight":"normal", "font-style":"normal",
+ "text-align":"left", "text-indent":0, "text-transform":"none",
+ "line-height":"normal", "letter-spacing":"normal", "word-spacing":"normal",
+ "word-wrap":"normal", "white-space":"nowrap", "float":"none",
+ "-webkit-box-sizing":"content-box", // Android ≤ 2.3, iOS ≤ 4
+ "-moz-box-sizing":"content-box", // Firefox ≤ 28
+ "box-sizing":"content-box", // Chrome, Firefox 29+, IE 8+, Opera, Safari 5.1
+ "box-shadow":"5px 5px 15px #AAAAAA", // Opera 10.5 and IE9
+ "-webkit-box-shadow":"5px 5px 15px #AAAAAA", // Safari 3 and Chrome
+ "-moz-box-shadow":"5px 5px 15px #AAAAAA", // Forefox 3.5
+ "-khtml-box-shadow":"5px 5px 15px #AAAAAA", // Konqueror
+ filter: "progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color='gray', Positive='true')" // IE
+ },
+
+ //
+ // The styles for the hidden overlay (should not need to be adjusted by the page author)
+ //
+ "#MathJax_ZoomOverlay": {
+ position:"absolute", left:0, top:0, "z-index":300, display:"inline-block",
+ width:"100%", height:"100%", border:0, padding:0, margin:0,
+ "background-color":"white", opacity:0, filter:"alpha(opacity=0)"
+ },
+
+ "#MathJax_ZoomFrame": {
+ position:"relative", display:"inline-block",
+ height:0, width:0
+ },
+
+ "#MathJax_ZoomEventTrap": {
+ position:"absolute", left:0, top:0, "z-index":302,
+ display:"inline-block", border:0, padding:0, margin:0,
+ "background-color":"white", opacity:0, filter:"alpha(opacity=0)"
+ }
+ }
+ });
+
+ var FALSE, HOVER, EVENT;
+ MathJax.Hub.Register.StartupHook("MathEvents Ready",function () {
+ EVENT = MathJax.Extension.MathEvents.Event;
+ FALSE = MathJax.Extension.MathEvents.Event.False;
+ HOVER = MathJax.Extension.MathEvents.Hover;
+ });
+
+ /*************************************************************/
+
+ var ZOOM = MathJax.Extension.MathZoom = {
+ version: VERSION,
+ settings: HUB.config.menuSettings,
+ scrollSize: 18, // width of scrool bars
+
+ //
+ // Process events passed from output jax
+ //
+ HandleEvent: function (event,type,math) {
+ if (ZOOM.settings.CTRL && !event.ctrlKey) return true;
+ if (ZOOM.settings.ALT && !event.altKey) return true;
+ if (ZOOM.settings.CMD && !event.metaKey) return true;
+ if (ZOOM.settings.Shift && !event.shiftKey) return true;
+ if (!ZOOM[type]) return true;
+ return ZOOM[type](event,math);
+ },
+
+ //
+ // Zoom on click
+ //
+ Click: function (event,math) {
+ if (this.settings.zoom === "Click") {return this.Zoom(event,math)}
+ },
+
+ //
+ // Zoom on double click
+ //
+ DblClick: function (event,math) {
+ if (this.settings.zoom === "Double-Click" || this.settings.zoom === "DoubleClick") {return this.Zoom(event,math)}
+ },
+
+ //
+ // Zoom on hover (called by MathEvents.Hover)
+ //
+ Hover: function (event,math) {
+ if (this.settings.zoom === "Hover") {this.Zoom(event,math); return true}
+ return false;
+ },
+
+
+ //
+ // Handle the actual zooming
+ //
+ Zoom: function (event,math) {
+ //
+ // Remove any other zoom and clear timers
+ //
+ this.Remove(); HOVER.ClearHoverTimer(); EVENT.ClearSelection();
+
+ //
+ // Find the jax
+ //
+ var JAX = MathJax.OutputJax[math.jaxID];
+ var jax = JAX.getJaxFromMath(math);
+ if (jax.hover) {HOVER.UnHover(jax)}
+
+ //
+ // Create the DOM elements for the zoom box
+ //
+ var container = this.findContainer(math);
+ var Mw = Math.floor(.85*container.clientWidth),
+ Mh = Math.max(document.body.clientHeight,document.documentElement.clientHeight);
+ if (this.getOverflow(container) !== "visible") {Mh = Math.min(container.clientHeight,Mh)}
+ Mh = Math.floor(.85*Mh);
+ var div = HTML.Element(
+ "span",{id:"MathJax_ZoomFrame"},[
+ ["span",{id:"MathJax_ZoomOverlay", onmousedown:this.Remove}],
+ ["span",{
+ id:"MathJax_Zoom", onclick:this.Remove,
+ style:{visibility:"hidden", fontSize:this.settings.zscale}
+ },[["span",{style:{display:"inline-block", "white-space":"nowrap"}}]]
+ ]]
+ );
+ var zoom = div.lastChild, span = zoom.firstChild, overlay = div.firstChild;
+ math.parentNode.insertBefore(div,math); math.parentNode.insertBefore(math,div); // put div after math
+ if (span.addEventListener) {span.addEventListener("mousedown",this.Remove,true)}
+ var eW = zoom.offsetWidth || zoom.clientWidth; Mw -= eW; Mh -= eW;
+ zoom.style.maxWidth = Mw+"px"; zoom.style.maxHeight = Mh+"px";
+
+ if (this.msieTrapEventBug) {
+ var trap = HTML.Element("span",{id:"MathJax_ZoomEventTrap", onmousedown:this.Remove});
+ div.insertBefore(trap,zoom);
+ }
+
+ //
+ // Display the zoomed math
+ //
+ if (this.msieZIndexBug) {
+ // MSIE doesn't do z-index properly, so move the div to the document.body,
+ // and use an image as a tracker for the usual position
+ var tracker = HTML.addElement(document.body,"img",{
+ src:"about:blank", id:"MathJax_ZoomTracker", width:0, height:0,
+ style:{width:0, height:0, position:"relative"}
+ });
+ div.style.position = "relative";
+ div.style.zIndex = CONFIG.styles["#MathJax_ZoomOverlay"]["z-index"];
+ div = tracker;
+ }
+
+ var bbox = JAX.Zoom(jax,span,math,Mw,Mh);
+
+ //
+ // Fix up size and position for browsers with bugs (IE)
+ //
+ if (this.msiePositionBug) {
+ if (this.msieSizeBug)
+ {zoom.style.height = bbox.zH+"px"; zoom.style.width = bbox.zW+"px"} // IE8 gets the dimensions completely wrong
+ if (zoom.offsetHeight > Mh) {zoom.style.height = Mh+"px"; zoom.style.width = (bbox.zW+this.scrollSize)+"px"} // IE doesn't do max-height?
+ if (zoom.offsetWidth > Mw) {zoom.style.width = Mw+"px"; zoom.style.height = (bbox.zH+this.scrollSize)+"px"}
+ }
+ if (this.operaPositionBug) {zoom.style.width = Math.min(Mw,bbox.zW)+"px"} // Opera gets width as 0?
+ if (zoom.offsetWidth > eW && zoom.offsetWidth-eW < Mw && zoom.offsetHeight-eW < Mh)
+ {zoom.style.overflow = "visible"} // don't show scroll bars if we don't need to
+ this.Position(zoom,bbox);
+ if (this.msieTrapEventBug) {
+ trap.style.height = zoom.clientHeight+"px"; trap.style.width = zoom.clientWidth+"px";
+ trap.style.left = (parseFloat(zoom.style.left)+zoom.clientLeft)+"px";
+ trap.style.top = (parseFloat(zoom.style.top)+zoom.clientTop)+"px";
+ }
+ zoom.style.visibility = "";
+
+ //
+ // Add event handlers
+ //
+ if (this.settings.zoom === "Hover") {overlay.onmouseover = this.Remove}
+ if (window.addEventListener) {addEventListener("resize",this.Resize,false)}
+ else if (window.attachEvent) {attachEvent("onresize",this.Resize)}
+ else {this.onresize = window.onresize; window.onresize = this.Resize}
+
+ //
+ // Let others know about the zoomed math
+ //
+ HUB.signal.Post(["math zoomed",jax]);
+
+ //
+ // Canel further actions
+ //
+ return FALSE(event);
+ },
+
+ //
+ // Set the position of the zoom box and overlay
+ //
+ Position: function (zoom,bbox) {
+ zoom.style.display = "none"; // avoids getting excessive width in Resize()
+ var XY = this.Resize(), x = XY.x, y = XY.y, W = bbox.mW;
+ zoom.style.display = "";
+ var dx = -W-Math.floor((zoom.offsetWidth-W)/2), dy = bbox.Y;
+ zoom.style.left = Math.max(dx,10-x)+"px"; zoom.style.top = Math.max(dy,10-y)+"px";
+ if (!ZOOM.msiePositionBug) {ZOOM.SetWH()} // refigure overlay width/height
+ },
+
+ //
+ // Handle resizing of overlay while zoom is displayed
+ //
+ Resize: function (event) {
+ if (ZOOM.onresize) {ZOOM.onresize(event)}
+ var div = document.getElementById("MathJax_ZoomFrame"),
+ overlay = document.getElementById("MathJax_ZoomOverlay");
+ var xy = ZOOM.getXY(div), obj = ZOOM.findContainer(div);
+ if (ZOOM.getOverflow(obj) !== "visible") {
+ overlay.scroll_parent = obj; // Save this for future reference.
+ var XY = ZOOM.getXY(obj); // Remove container position
+ xy.x -= XY.x; xy.y -= XY.y;
+ XY = ZOOM.getBorder(obj); // Remove container border
+ xy.x -= XY.x; xy.y -= XY.y;
+ }
+ overlay.style.left = (-xy.x)+"px"; overlay.style.top = (-xy.y)+"px";
+ if (ZOOM.msiePositionBug) {setTimeout(ZOOM.SetWH,0)} else {ZOOM.SetWH()}
+ return xy;
+ },
+ SetWH: function () {
+ var overlay = document.getElementById("MathJax_ZoomOverlay");
+ if (!overlay) return;
+ overlay.style.display = "none"; // so scrollWidth/Height will be right below
+ var doc = overlay.scroll_parent || document.documentElement || document.body;
+ overlay.style.width = doc.scrollWidth + "px";
+ overlay.style.height = Math.max(doc.clientHeight,doc.scrollHeight) + "px";
+ overlay.style.display = "";
+ },
+ findContainer: function (obj) {
+ obj = obj.parentNode;
+ while (obj.parentNode && obj !== document.body && ZOOM.getOverflow(obj) === "visible")
+ {obj = obj.parentNode}
+ return obj;
+ },
+ //
+ // Look up CSS properties (use getComputeStyle if available, or currentStyle if not)
+ //
+ getOverflow: (window.getComputedStyle ?
+ function (obj) {return getComputedStyle(obj).overflow} :
+ function (obj) {return (obj.currentStyle||{overflow:"visible"}).overflow}),
+ getBorder: function (obj) {
+ var size = {thin: 1, medium: 2, thick: 3};
+ var style = (window.getComputedStyle ? getComputedStyle(obj) :
+ (obj.currentStyle || {borderLeftWidth:0,borderTopWidth:0}));
+ var x = style.borderLeftWidth, y = style.borderTopWidth;
+ if (size[x]) {x = size[x]} else {x = parseInt(x)}
+ if (size[y]) {y = size[y]} else {y = parseInt(y)}
+ return {x:x, y:y};
+ },
+ //
+ // Get the position of an element on the page
+ //
+ getXY: function (div) {
+ var x = 0, y = 0, obj;
+ obj = div; while (obj.offsetParent) {x += obj.offsetLeft; obj = obj.offsetParent}
+ if (ZOOM.operaPositionBug) {div.style.border = "1px solid"} // to get vertical position right
+ obj = div; while (obj.offsetParent) {y += obj.offsetTop; obj = obj.offsetParent}
+ if (ZOOM.operaPositionBug) {div.style.border = ""}
+ return {x:x, y:y};
+ },
+
+ //
+ // Remove zoom display and event handlers
+ //
+ Remove: function (event) {
+ var div = document.getElementById("MathJax_ZoomFrame");
+ if (div) {
+ var JAX = MathJax.OutputJax[div.previousSibling.jaxID];
+ var jax = JAX.getJaxFromMath(div.previousSibling);
+ HUB.signal.Post(["math unzoomed",jax]);
+ div.parentNode.removeChild(div);
+ div = document.getElementById("MathJax_ZoomTracker");
+ if (div) {div.parentNode.removeChild(div)}
+ if (ZOOM.operaRefreshBug) {
+ // force a redisplay of the page
+ // (Opera doesn't refresh properly after the zoom is removed)
+ var overlay = HTML.addElement(document.body,"div",{
+ style:{position:"fixed", left:0, top:0, width:"100%", height:"100%",
+ backgroundColor:"white", opacity:0},
+ id: "MathJax_OperaDiv"
+ });
+ document.body.removeChild(overlay);
+ }
+ if (window.removeEventListener) {removeEventListener("resize",ZOOM.Resize,false)}
+ else if (window.detachEvent) {detachEvent("onresize",ZOOM.Resize)}
+ else {window.onresize = ZOOM.onresize; delete ZOOM.onresize}
+ }
+ return FALSE(event);
+ }
+
+ };
+
+
+ /*************************************************************/
+
+ HUB.Browser.Select({
+ MSIE: function (browser) {
+ var mode = (document.documentMode || 0);
+ var isIE9 = (mode >= 9);
+ ZOOM.msiePositionBug = !isIE9;
+ ZOOM.msieSizeBug = browser.versionAtLeast("7.0") &&
+ (!document.documentMode || mode === 7 || mode === 8);
+ ZOOM.msieZIndexBug = (mode <= 7);
+ ZOOM.msieInlineBlockAlignBug = (mode <= 7);
+ ZOOM.msieTrapEventBug = !window.addEventListener;
+ if (document.compatMode === "BackCompat") {ZOOM.scrollSize = 52} // don't know why this is so far off
+ if (isIE9) {delete CONFIG.styles["#MathJax_Zoom"].filter}
+ },
+
+ Opera: function (browser) {
+ ZOOM.operaPositionBug = true;
+ ZOOM.operaRefreshBug = true;
+ }
+ });
+
+ ZOOM.topImg = (ZOOM.msieInlineBlockAlignBug ?
+ HTML.Element("img",{style:{width:0,height:0,position:"relative"},src:"about:blank"}) :
+ HTML.Element("span",{style:{width:0,height:0,display:"inline-block"}})
+ );
+ if (ZOOM.operaPositionBug || ZOOM.msieTopBug) {ZOOM.topImg.style.border="1px solid"}
+
+ /*************************************************************/
+
+ MathJax.Callback.Queue(
+ ["StartupHook",MathJax.Hub.Register,"Begin Styles",{}],
+ ["Styles",AJAX,CONFIG.styles],
+ ["Post",HUB.Startup.signal,"MathZoom Ready"],
+ ["loadComplete",AJAX,"[MathJax]/extensions/MathZoom.js"]
+ );
+
+})(MathJax.Hub,MathJax.HTML,MathJax.Ajax,MathJax.OutputJax["HTML-CSS"],MathJax.OutputJax.NativeMML);
diff --git a/_static/scipy-mathjax/extensions/Safe.js b/_static/scipy-mathjax/extensions/Safe.js
new file mode 100644
index 000000000..68e8f6949
--- /dev/null
+++ b/_static/scipy-mathjax/extensions/Safe.js
@@ -0,0 +1,428 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/Safe.js
+ *
+ * Implements a "Safe" mode that disables features that could be
+ * misused in a shared environment (such as href's to javascript URL's).
+ * See the CONFIG variable below for configuration options.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2013-2017 The MathJax Consortium
+ *
+ * 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.
+ */
+
+(function (HUB,AJAX) {
+ var VERSION = "2.7.1";
+
+ var CONFIG = MathJax.Hub.CombineConfig("Safe",{
+ allow: {
+ //
+ // Values can be "all", "safe", or "none"
+ //
+ URLs: "safe", // safe are in safeProtocols below
+ classes: "safe", // safe start with MJX-
+ cssIDs: "safe", // safe start with MJX-
+ styles: "safe", // safe are in safeStyles below
+ fontsize: "all", // safe are between sizeMin and sizeMax em's
+ require: "safe" // safe are in safeRequire below
+ },
+ sizeMin: .7, // \scriptsize
+ sizeMax: 1.44, // \large
+ lengthMax: 3, // largest padding/border/margin, etc. in em's
+ safeProtocols: {
+ http: true,
+ https: true,
+ file: true,
+ javascript: false
+ },
+ safeStyles: {
+ color: true,
+ backgroundColor: true,
+ border: true,
+ cursor: true,
+ margin: true,
+ padding: true,
+ textShadow: true,
+ fontFamily: true,
+ fontSize: true,
+ fontStyle: true,
+ fontWeight: true,
+ opacity: true,
+ outline: true
+ },
+ safeRequire: {
+ action: true,
+ amscd: true,
+ amsmath: true,
+ amssymbols: true,
+ autobold: false,
+ "autoload-all": false,
+ bbox: true,
+ begingroup: true,
+ boldsymbol: true,
+ cancel: true,
+ color: true,
+ enclose: true,
+ extpfeil: true,
+ HTML: true,
+ mathchoice: true,
+ mhchem: true,
+ newcommand: true,
+ noErrors: false,
+ noUndefined: false,
+ unicode: true,
+ verb: true
+ },
+ //
+ // CSS styles that have Top/Right/Bottom/Left versions
+ //
+ styleParts: {
+ border: true,
+ padding: true,
+ margin: true,
+ outline: true
+ },
+ //
+ // CSS styles that are lengths needing max/min testing
+ // A string value means test that style value;
+ // An array gives [min,max] in em's
+ // Otherwise use [-lengthMax,lengthMax] from above
+ //
+ styleLengths: {
+ borderTop: "borderTopWidth",
+ borderRight: "borderRightWidth",
+ borderBottom: "borderBottomWidth",
+ borderLeft: "borderLeftWidth",
+ paddingTop: true,
+ paddingRight: true,
+ paddingBottom: true,
+ paddingLeft: true,
+ marginTop: true,
+ marginRight: true,
+ marginBottom: true,
+ marginLeft: true,
+ outlineTop: true,
+ outlineRight: true,
+ outlineBottom: true,
+ outlineLeft: true,
+ fontSize: [.7,1.44]
+ }
+ });
+
+ var ALLOW = CONFIG.allow;
+ if (ALLOW.fontsize !== "all") {CONFIG.safeStyles.fontSize = false}
+
+ var SAFE = MathJax.Extension.Safe = {
+ version: VERSION,
+ config: CONFIG,
+ div1: document.createElement("div"), // for CSS processing
+ div2: document.createElement("div"),
+
+ //
+ // Methods called for MathML attribute processing
+ //
+ filter: {
+ href: "filterURL",
+ src: "filterURL",
+ altimg: "filterURL",
+ "class": "filterClass",
+ style: "filterStyles",
+ id: "filterID",
+ fontsize: "filterFontSize",
+ mathsize: "filterFontSize",
+ scriptminsize: "filterFontSize",
+ scriptsizemultiplier: "filterSizeMultiplier",
+ scriptlevel: "filterScriptLevel"
+ },
+
+ //
+ // Filter HREF URL's
+ //
+ filterURL: function (url) {
+ var protocol = (url.match(/^\s*([a-z]+):/i)||[null,""])[1].toLowerCase();
+ if (ALLOW.URLs === "none" ||
+ (ALLOW.URLs !== "all" && !CONFIG.safeProtocols[protocol])) {url = null}
+ return url;
+ },
+
+ //
+ // Filter class names and css ID's
+ //
+ filterClass: function (CLASS) {
+ if (ALLOW.classes === "none" ||
+ (ALLOW.classes !== "all" && !CLASS.match(/^MJX-[-a-zA-Z0-9_.]+$/))) {CLASS = null}
+ return CLASS;
+ },
+ filterID: function (id) {
+ if (ALLOW.cssIDs === "none" ||
+ (ALLOW.cssIDs !== "all" && !id.match(/^MJX-[-a-zA-Z0-9_.]+$/))) {id = null}
+ return id;
+ },
+
+ //
+ // Filter style strings
+ //
+ filterStyles: function (styles) {
+ if (ALLOW.styles === "all") {return styles}
+ if (ALLOW.styles === "none") {return null}
+ try {
+ //
+ // Set the div1 styles to the given styles, and clear div2
+ //
+ var STYLE1 = this.div1.style, STYLE2 = this.div2.style, value;
+ STYLE1.cssText = styles; STYLE2.cssText = "";
+ //
+ // Check each allowed style and transfer OK ones to div2
+ // If the style has Top/Right/Bottom/Left, look at all four separately
+ //
+ for (var name in CONFIG.safeStyles) {if (CONFIG.safeStyles.hasOwnProperty(name)) {
+ if (CONFIG.styleParts[name]) {
+ for (var i = 0; i < 4; i++) {
+ var NAME = name+["Top","Right","Bottom","Left"][i]
+ value = this.filterStyle(NAME,STYLE1);
+ if (value) {STYLE2[NAME] = value}
+ }
+ } else {
+ value = this.filterStyle(name,STYLE1);
+ if (value) {STYLE2[name] = value}
+ }
+ }}
+ //
+ // Return the div2 style string
+ //
+ styles = STYLE2.cssText;
+ } catch (e) {styles = null}
+ return styles;
+ },
+ //
+ // Filter an individual name:value style pair
+ //
+ filterStyle: function (name,styles) {
+ var value = styles[name];
+ if (typeof value !== "string" || value === "") {return null}
+ if (value.match(/^\s*expression/)) {return null}
+ if (value.match(/javascript:/)) {return null}
+ var NAME = name.replace(/Top|Right|Left|Bottom/,"");
+ if (!CONFIG.safeStyles[name] && !CONFIG.safeStyles[NAME]) {return null}
+ if (!CONFIG.styleLengths[name]) {return value}
+ return (this.filterStyleLength(name,value,styles) ? value : null);
+ },
+ filterStyleLength: function (name,value,styles) {
+ if (typeof CONFIG.styleLengths[name] === "string") value = styles[CONFIG.styleLengths[name]];
+ value = this.length2em(value);
+ if (value == null) return false;
+ var mM = [-CONFIG.lengthMax,CONFIG.lengthMax];
+ if (MathJax.Object.isArray(CONFIG.styleLengths[name])) mM = CONFIG.styleLengths[name];
+ return (value >= mM[0] && value <= mM[1]);
+ },
+ //
+ // Conversion of units to em's
+ //
+ unit2em: {
+ em: 1,
+ ex: .5, // assume 1ex = .5em
+ ch: .5, // assume 1ch = .5em
+ rem: 1, // assume 1rem = 1em
+ px: 1/16, // assume 1em = 16px
+ mm: 96/25.4/16, // 25.4mm = 96px
+ cm: 96/2.54/16, // 2.54cm = 96px
+ 'in': 96/16, // 1in = 96px
+ pt: 96/72/16, // 72pt = 1in
+ pc: 96/6/16 // 1pc = 12pt
+ },
+ length2em: function (value) {
+ var match = value.match(/(.+)(em|ex|ch|rem|px|mm|cm|in|pt|pc)/);
+ if (!match) return null;
+ return parseFloat(match[1])*this.unit2em[match[2]];
+ },
+
+ //
+ // Filter TeX font size values (in em's)
+ //
+ filterSize: function (size) {
+ if (ALLOW.fontsize === "none") {return null}
+ if (ALLOW.fontsize !== "all")
+ {size = Math.min(Math.max(size,CONFIG.sizeMin),CONFIG.sizeMax)}
+ return size;
+ },
+ filterFontSize: function (size) {
+ return (ALLOW.fontsize === "all" ? size: null);
+ },
+
+ //
+ // Filter scriptsizemultiplier
+ //
+ filterSizeMultiplier: function (size) {
+ if (ALLOW.fontsize === "none") {size = null}
+ else if (ALLOW.fontsize !== "all") {size = Math.min(1,Math.max(.6,size)).toString()}
+ return size;
+ },
+ //
+ // Filter scriptLevel
+ //
+ filterScriptLevel: function (level) {
+ if (ALLOW.fontsize === "none") {level = null}
+ else if (ALLOW.fontsize !== "all") {level = Math.max(0,level).toString()}
+ return level;
+ },
+
+ //
+ // Filter TeX extension names
+ //
+ filterRequire: function (name) {
+ if (ALLOW.require === "none" ||
+ (ALLOW.require !== "all" && !CONFIG.safeRequire[name.toLowerCase()]))
+ {name = null}
+ return name;
+ }
+
+ };
+
+ HUB.Register.StartupHook("TeX HTML Ready",function () {
+ var TEX = MathJax.InputJax.TeX;
+
+ TEX.Parse.Augment({
+
+ //
+ // Implements \href{url}{math} with URL filter
+ //
+ HREF_attribute: function (name) {
+ var url = SAFE.filterURL(this.GetArgument(name)),
+ arg = this.GetArgumentMML(name);
+ if (url) {arg.With({href:url})}
+ this.Push(arg);
+ },
+
+ //
+ // Implements \class{name}{math} with class-name filter
+ //
+ CLASS_attribute: function (name) {
+ var CLASS = SAFE.filterClass(this.GetArgument(name)),
+ arg = this.GetArgumentMML(name);
+ if (CLASS) {
+ if (arg["class"] != null) {CLASS = arg["class"] + " " + CLASS}
+ arg.With({"class":CLASS});
+ }
+ this.Push(arg);
+ },
+
+ //
+ // Implements \style{style-string}{math} with style filter
+ //
+ STYLE_attribute: function (name) {
+ var style = SAFE.filterStyles(this.GetArgument(name)),
+ arg = this.GetArgumentMML(name);
+ if (style) {
+ if (arg.style != null) {
+ if (style.charAt(style.length-1) !== ";") {style += ";"}
+ style = arg.style + " " + style;
+ }
+ arg.With({style: style});
+ }
+ this.Push(arg);
+ },
+
+ //
+ // Implements \cssId{id}{math} with ID filter
+ //
+ ID_attribute: function (name) {
+ var ID = SAFE.filterID(this.GetArgument(name)),
+ arg = this.GetArgumentMML(name);
+ if (ID) {arg.With({id:ID})}
+ this.Push(arg);
+ }
+
+ });
+
+ });
+
+ HUB.Register.StartupHook("TeX Jax Ready",function () {
+ var TEX = MathJax.InputJax.TeX,
+ PARSE = TEX.Parse, METHOD = SAFE.filter;
+
+ PARSE.Augment({
+
+ //
+ // Implements \require{name} with filtering
+ //
+ Require: function (name) {
+ var file = this.GetArgument(name).replace(/.*\//,"").replace(/[^a-z0-9_.-]/ig,"");
+ file = SAFE.filterRequire(file);
+ if (file) {this.Extension(null,file)}
+ },
+
+ //
+ // Controls \mmlToken attributes
+ //
+ MmlFilterAttribute: function (name,value) {
+ if (METHOD[name]) {value = SAFE[METHOD[name]](value)}
+ return value;
+ },
+
+ //
+ // Handles font size macros with filtering
+ //
+ SetSize: function (name,size) {
+ size = SAFE.filterSize(size);
+ if (size) {
+ this.stack.env.size = size;
+ this.Push(TEX.Stack.Item.style().With({styles: {mathsize: size+"em"}}));
+ }
+ }
+
+ });
+ });
+
+ HUB.Register.StartupHook("TeX bbox Ready",function () {
+ var TEX = MathJax.InputJax.TeX;
+
+ //
+ // Filter the styles for \bbox
+ //
+ TEX.Parse.Augment({
+ BBoxStyle: function (styles) {return SAFE.filterStyles(styles)},
+ BBoxPadding: function (pad) {
+ var styles = SAFE.filterStyles("padding: "+pad);
+ return (styles ? pad : 0);
+ }
+ });
+
+ });
+
+ HUB.Register.StartupHook("MathML Jax Ready",function () {
+ var PARSE = MathJax.InputJax.MathML.Parse,
+ METHOD = SAFE.filter;
+
+ //
+ // Filter MathML attributes
+ //
+ PARSE.Augment({
+ filterAttribute: function (name,value) {
+ if (METHOD[name]) {value = SAFE[METHOD[name]](value)}
+ return value;
+ }
+ });
+
+ });
+
+ // MathML input (href, style, fontsize, class, id)
+
+ HUB.Startup.signal.Post("Safe Extension Ready");
+ AJAX.loadComplete("[MathJax]/extensions/Safe.js");
+
+})(MathJax.Hub,MathJax.Ajax);
diff --git a/_static/scipy-mathjax/extensions/TeX/AMScd.js b/_static/scipy-mathjax/extensions/TeX/AMScd.js
new file mode 100644
index 000000000..86c8f1e27
--- /dev/null
+++ b/_static/scipy-mathjax/extensions/TeX/AMScd.js
@@ -0,0 +1,158 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/TeX/AMScd.js
+ *
+ * Implements the CD environment for commutative diagrams.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2013-2017 The MathJax Consortium
+ *
+ * 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.
+ */
+
+MathJax.Extension["TeX/AMScd"] = {
+ version: "2.7.1",
+ config: MathJax.Hub.CombineConfig("TeX.CD",{
+ colspace: "5pt",
+ rowspace: "5pt",
+ harrowsize: "2.75em",
+ varrowsize: "1.75em",
+ hideHorizontalLabels: false
+ })
+};
+
+MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
+ var MML = MathJax.ElementJax.mml,
+ TEX = MathJax.InputJax.TeX,
+ STACKITEM = TEX.Stack.Item,
+ TEXDEF = TEX.Definitions,
+ CONFIG = MathJax.Extension["TeX/AMScd"].config;
+
+ TEXDEF.environment.CD = "CD_env";
+ TEXDEF.special["@"] = "CD_arrow";
+ TEXDEF.macros.minCDarrowwidth = "CD_minwidth";
+ TEXDEF.macros.minCDarrowheight = "CD_minheight";
+
+ TEX.Parse.Augment({
+ //
+ // Implements \begin{CD}...\end{CD}
+ //
+ CD_env: function (begin) {
+ this.Push(begin);
+ return STACKITEM.array().With({
+ arraydef: {
+ columnalign: "center",
+ columnspacing: CONFIG.colspace,
+ rowspacing: CONFIG.rowspace,
+ displaystyle: true
+ },
+ minw: this.stack.env.CD_minw || CONFIG.harrowsize,
+ minh: this.stack.env.CD_minh || CONFIG.varrowsize
+ });
+ },
+
+ CD_arrow: function (name) {
+ var c = this.string.charAt(this.i);
+ if (!c.match(/[>>> @<<< @VVV and @AAA, get the arrow and labels
+ //
+ var arrow = {">":"\u2192", "<":"\u2190", V:"\u2193", A:"\u2191"}[c];
+ var a = this.GetUpTo(name+c,c),
+ b = this.GetUpTo(name+c,c);
+
+ if (c === ">" || c === "<") {
+ //
+ // Lay out horizontal arrows with munderover if it has labels
+ //
+ mml = MML.mo(arrow).With(hdef);
+ if (!a) {a = "\\kern "+top.minw} // minsize needs work
+ if (a || b) {
+ var pad = {width:"+11mu", lspace:"6mu"};
+ mml = MML.munderover(this.mmlToken(mml));
+ if (a) {
+ a = TEX.Parse(a,this.stack.env).mml();
+ mml.SetData(mml.over,MML.mpadded(a).With(pad).With({voffset:".1em"}));
+ }
+ if (b) {
+ b = TEX.Parse(b,this.stack.env).mml();
+ mml.SetData(mml.under,MML.mpadded(b).With(pad));
+ }
+ if (CONFIG.hideHorizontalLabels)
+ {mml = MML.mpadded(mml).With({depth:0, height:".67em"})}
+ }
+ } else {
+ //
+ // Lay out vertical arrows with mrow if there are labels
+ //
+ mml = arrow = this.mmlToken(MML.mo(arrow).With(vdef));
+ if (a || b) {
+ mml = MML.mrow();
+ if (a) {mml.Append(TEX.Parse("\\scriptstyle\\llap{"+a+"}",this.stack.env).mml())}
+ mml.Append(arrow.With({texClass: MML.TEXCLASS.ORD}));
+ if (b) {mml.Append(TEX.Parse("\\scriptstyle\\rlap{"+b+"}",this.stack.env).mml())}
+ }
+ }
+ }
+ if (mml) {this.Push(mml)};
+ this.CD_cell(name);
+ },
+ CD_cell: function (name) {
+ var top = this.stack.Top();
+ if ((top.table||[]).length % 2 === 0 && (top.row||[]).length === 0) {
+ //
+ // Add a strut to the first cell in even rows to get
+ // better spacing of arrow rows.
+ //
+ this.Push(MML.mpadded().With({height:"8.5pt",depth:"2pt"}));
+ }
+ this.Push(STACKITEM.cell().With({isEntry:true, name:name}));
+ },
+
+ CD_minwidth: function (name) {
+ this.stack.env.CD_minw = this.GetDimen(name);
+ },
+ CD_minheight: function (name) {
+ this.stack.env.CD_minh = this.GetDimen(name);
+ }
+
+ });
+
+});
+
+MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/AMScd.js");
diff --git a/_static/scipy-mathjax/extensions/TeX/AMSmath.js b/_static/scipy-mathjax/extensions/TeX/AMSmath.js
new file mode 100644
index 000000000..59ad81c64
--- /dev/null
+++ b/_static/scipy-mathjax/extensions/TeX/AMSmath.js
@@ -0,0 +1,654 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/TeX/AMSmath.js
+ *
+ * Implements AMS math environments and macros.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2009-2017 The MathJax Consortium
+ *
+ * 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.
+ */
+
+MathJax.Extension["TeX/AMSmath"] = {
+ version: "2.7.1",
+
+ number: 0, // current equation number
+ startNumber: 0, // current starting equation number (for when equation is restarted)
+ IDs: {}, // IDs used in previous equations
+ eqIDs: {}, // IDs used in this equation
+ labels: {}, // the set of labels
+ eqlabels: {}, // labels in the current equation
+ refs: [] // array of jax with unresolved references
+};
+
+MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
+
+ var MML = MathJax.ElementJax.mml,
+ TEX = MathJax.InputJax.TeX,
+ AMS = MathJax.Extension["TeX/AMSmath"];
+
+ var TEXDEF = TEX.Definitions,
+ STACKITEM = TEX.Stack.Item,
+ CONFIG = TEX.config.equationNumbers;
+
+ var COLS = function (W) {
+ var WW = [];
+ for (var i = 0, m = W.length; i < m; i++)
+ {WW[i] = TEX.Parse.prototype.Em(W[i])}
+ return WW.join(" ");
+ };
+
+ //
+ // Get the URL of the page (for use with formatURL) when there
+ // is a element on the page.
+ //
+ var baseURL = (document.getElementsByTagName("base").length === 0) ? "" :
+ String(document.location).replace(/#.*$/,"");
+
+
+ /******************************************************************************/
+
+ TEXDEF.Add({
+ mathchar0mo: {
+ iiiint: ['2A0C',{texClass: MML.TEXCLASS.OP}]
+ },
+
+ macros: {
+ mathring: ['Accent','2DA'], // or 0x30A
+
+ nobreakspace: 'Tilde',
+ negmedspace: ['Spacer',MML.LENGTH.NEGATIVEMEDIUMMATHSPACE],
+ negthickspace: ['Spacer',MML.LENGTH.NEGATIVETHICKMATHSPACE],
+
+// intI: ['Macro','\\mathchoice{\\!}{}{}{}\\!\\!\\int'],
+// iint: ['MultiIntegral','\\int\\intI'], // now in core TeX input jax
+// iiint: ['MultiIntegral','\\int\\intI\\intI'], // now in core TeX input jax
+// iiiint: ['MultiIntegral','\\int\\intI\\intI\\intI'], // now in mathchar0mo above
+ idotsint: ['MultiIntegral','\\int\\cdots\\int'],
+
+// dddot: ['Macro','\\mathop{#1}\\limits^{\\textstyle \\mathord{.}\\mathord{.}\\mathord{.}}',1],
+// ddddot: ['Macro','\\mathop{#1}\\limits^{\\textstyle \\mathord{.}\\mathord{.}\\mathord{.}\\mathord{.}}',1],
+ dddot: ['Accent','20DB'],
+ ddddot: ['Accent','20DC'],
+
+ sideset: ['Macro','\\mathop{\\mathop{\\rlap{\\phantom{#3}}}\\nolimits#1\\!\\mathop{#3}\\nolimits#2}',3],
+
+ boxed: ['Macro','\\fbox{$\\displaystyle{#1}$}',1],
+
+ tag: 'HandleTag',
+ notag: 'HandleNoTag',
+ label: 'HandleLabel',
+ ref: 'HandleRef',
+ eqref: ['HandleRef',true],
+
+ substack: ['Macro','\\begin{subarray}{c}#1\\end{subarray}',1],
+
+ injlim: ['NamedOp','inj lim'],
+ projlim: ['NamedOp','proj lim'],
+ varliminf: ['Macro','\\mathop{\\underline{\\mmlToken{mi}{lim}}}'],
+ varlimsup: ['Macro','\\mathop{\\overline{\\mmlToken{mi}{lim}}}'],
+ varinjlim: ['Macro','\\mathop{\\underrightarrow{\\mmlToken{mi}{lim}}}'],
+ varprojlim: ['Macro','\\mathop{\\underleftarrow{\\mmlToken{mi}{lim}}}'],
+
+ DeclareMathOperator: 'HandleDeclareOp',
+ operatorname: 'HandleOperatorName',
+ SkipLimits: 'SkipLimits',
+
+ genfrac: 'Genfrac',
+ frac: ['Genfrac',"","","",""],
+ tfrac: ['Genfrac',"","","",1],
+ dfrac: ['Genfrac',"","","",0],
+ binom: ['Genfrac',"(",")","0",""],
+ tbinom: ['Genfrac',"(",")","0",1],
+ dbinom: ['Genfrac',"(",")","0",0],
+
+ cfrac: 'CFrac',
+
+ shoveleft: ['HandleShove',MML.ALIGN.LEFT],
+ shoveright: ['HandleShove',MML.ALIGN.RIGHT],
+
+ xrightarrow: ['xArrow',0x2192,5,6],
+ xleftarrow: ['xArrow',0x2190,7,3]
+ },
+
+ environment: {
+ align: ['AMSarray',null,true,true, 'rlrlrlrlrlrl',COLS([0,2,0,2,0,2,0,2,0,2,0])],
+ 'align*': ['AMSarray',null,false,true, 'rlrlrlrlrlrl',COLS([0,2,0,2,0,2,0,2,0,2,0])],
+ multline: ['Multline',null,true],
+ 'multline*': ['Multline',null,false],
+ split: ['AMSarray',null,false,false,'rl',COLS([0])],
+ gather: ['AMSarray',null,true,true, 'c'],
+ 'gather*': ['AMSarray',null,false,true, 'c'],
+
+ alignat: ['AlignAt',null,true,true],
+ 'alignat*': ['AlignAt',null,false,true],
+ alignedat: ['AlignAt',null,false,false],
+
+ aligned: ['AlignedAMSArray',null,null,null,'rlrlrlrlrlrl',COLS([0,2,0,2,0,2,0,2,0,2,0]),".5em",'D'],
+ gathered: ['AlignedAMSArray',null,null,null,'c',null,".5em",'D'],
+
+ subarray: ['Array',null,null,null,null,COLS([0]),"0.1em",'S',1],
+ smallmatrix: ['Array',null,null,null,'c',COLS([1/3]),".2em",'S',1],
+
+ 'equation': ['EquationBegin','Equation',true],
+ 'equation*': ['EquationBegin','EquationStar',false],
+
+ eqnarray: ['AMSarray',null,true,true, 'rcl',"0 "+MML.LENGTH.THICKMATHSPACE,".5em"],
+ 'eqnarray*': ['AMSarray',null,false,true,'rcl',"0 "+MML.LENGTH.THICKMATHSPACE,".5em"]
+ },
+
+ delimiter: {
+ '\\lvert': ['007C',{texClass:MML.TEXCLASS.OPEN}],
+ '\\rvert': ['007C',{texClass:MML.TEXCLASS.CLOSE}],
+ '\\lVert': ['2016',{texClass:MML.TEXCLASS.OPEN}],
+ '\\rVert': ['2016',{texClass:MML.TEXCLASS.CLOSE}]
+ }
+ },null,true);
+
+
+ /******************************************************************************/
+
+ TEX.Parse.Augment({
+
+ /*
+ * Add the tag to the environment (to be added to the table row later)
+ */
+ HandleTag: function (name) {
+ var star = this.GetStar();
+ var arg = this.trimSpaces(this.GetArgument(name)), tag = arg;
+ if (!star) {arg = CONFIG.formatTag(arg)}
+ var global = this.stack.global; global.tagID = tag;
+ if (global.notags) {
+ TEX.Error(["CommandNotAllowedInEnv",
+ "%1 not allowed in %2 environment",
+ name,global.notags]
+ );
+ }
+ if (global.tag) {TEX.Error(["MultipleCommand","Multiple %1",name])}
+ global.tag = MML.mtd.apply(MML,this.InternalMath(arg)).With({id:CONFIG.formatID(tag)});
+ },
+ HandleNoTag: function (name) {
+ if (this.stack.global.tag) {delete this.stack.global.tag}
+ this.stack.global.notag = true; // prevent auto-tagging
+ },
+
+ /*
+ * Record a label name for a tag
+ */
+ HandleLabel: function (name) {
+ var global = this.stack.global, label = this.GetArgument(name);
+ if (label === "") return;
+ if (!AMS.refUpdate) {
+ if (global.label) {TEX.Error(["MultipleCommand","Multiple %1",name])}
+ global.label = label;
+ if (AMS.labels[label] || AMS.eqlabels[label])
+ {TEX.Error(["MultipleLabel","Label '%1' multiply defined",label])}
+ AMS.eqlabels[label] = {tag:"???", id:""}; // will be replaced by tag value later
+ }
+ },
+
+ /*
+ * Handle a label reference
+ */
+ HandleRef: function (name,eqref) {
+ var label = this.GetArgument(name);
+ var ref = AMS.labels[label] || AMS.eqlabels[label];
+ if (!ref) {ref = {tag:"???",id:""}; AMS.badref = !AMS.refUpdate}
+ var tag = ref.tag; if (eqref) {tag = CONFIG.formatTag(tag)}
+ this.Push(MML.mrow.apply(MML,this.InternalMath(tag)).With({
+ href:CONFIG.formatURL(ref.id,baseURL), "class":"MathJax_ref"
+ }));
+ },
+
+ /*
+ * Handle \DeclareMathOperator
+ */
+ HandleDeclareOp: function (name) {
+ var limits = (this.GetStar() ? "" : "\\nolimits\\SkipLimits");
+ var cs = this.trimSpaces(this.GetArgument(name));
+ if (cs.charAt(0) == "\\") {cs = cs.substr(1)}
+ var op = this.GetArgument(name);
+ op = op.replace(/\*/g,'\\text{*}').replace(/-/g,'\\text{-}');
+ TEX.Definitions.macros[cs] = ['Macro','\\mathop{\\rm '+op+'}'+limits];
+ },
+
+ HandleOperatorName: function (name) {
+ var limits = (this.GetStar() ? "" : "\\nolimits\\SkipLimits");
+ var op = this.trimSpaces(this.GetArgument(name));
+ op = op.replace(/\*/g,'\\text{*}').replace(/-/g,'\\text{-}');
+ this.string = '\\mathop{\\rm '+op+'}'+limits+" "+this.string.slice(this.i);
+ this.i = 0;
+ },
+
+ SkipLimits: function (name) {
+ var c = this.GetNext(), i = this.i;
+ if (c === "\\" && ++this.i && this.GetCS() !== "limits") this.i = i;
+ },
+
+ /*
+ * Record presence of \shoveleft and \shoveright
+ */
+ HandleShove: function (name,shove) {
+ var top = this.stack.Top();
+ if (top.type !== "multline" || top.data.length) {
+ TEX.Error(["CommandAtTheBeginingOfLine",
+ "%1 must come at the beginning of the line",name]);
+ }
+ top.data.shove = shove;
+ },
+
+ /*
+ * Handle \cfrac
+ */
+ CFrac: function (name) {
+ var lr = this.trimSpaces(this.GetBrackets(name,"")),
+ num = this.GetArgument(name),
+ den = this.GetArgument(name);
+ var frac = MML.mfrac(TEX.Parse('\\strut\\textstyle{'+num+'}',this.stack.env).mml(),
+ TEX.Parse('\\strut\\textstyle{'+den+'}',this.stack.env).mml());
+ lr = ({l:MML.ALIGN.LEFT, r:MML.ALIGN.RIGHT,"":""})[lr];
+ if (lr == null)
+ {TEX.Error(["IllegalAlign","Illegal alignment specified in %1",name])}
+ if (lr) {frac.numalign = frac.denomalign = lr}
+ this.Push(frac);
+ },
+
+ /*
+ * Implement AMS generalized fraction
+ */
+ Genfrac: function (name,left,right,thick,style) {
+ if (left == null) {left = this.GetDelimiterArg(name)}
+ if (right == null) {right = this.GetDelimiterArg(name)}
+ if (thick == null) {thick = this.GetArgument(name)}
+ if (style == null) {style = this.trimSpaces(this.GetArgument(name))}
+ var num = this.ParseArg(name);
+ var den = this.ParseArg(name);
+ var frac = MML.mfrac(num,den);
+ if (thick !== "") {frac.linethickness = thick}
+ if (left || right) {frac = TEX.fixedFence(left,frac.With({texWithDelims:true}),right)}
+ if (style !== "") {
+ var STYLE = (["D","T","S","SS"])[style];
+ if (STYLE == null)
+ {TEX.Error(["BadMathStyleFor","Bad math style for %1",name])}
+ frac = MML.mstyle(frac);
+ if (STYLE === "D") {frac.displaystyle = true; frac.scriptlevel = 0}
+ else {frac.displaystyle = false; frac.scriptlevel = style - 1}
+ }
+ this.Push(frac);
+ },
+
+ /*
+ * Implements multline environment (mostly handled through STACKITEM below)
+ */
+ Multline: function (begin,numbered) {
+ this.Push(begin); this.checkEqnEnv();
+ return STACKITEM.multline(numbered,this.stack).With({
+ arraydef: {
+ displaystyle: true,
+ rowspacing: ".5em",
+ width: TEX.config.MultLineWidth, columnwidth:"100%",
+ side: TEX.config.TagSide,
+ minlabelspacing: TEX.config.TagIndent
+ }
+ });
+ },
+
+ /*
+ * Handle AMS aligned environments
+ */
+ AMSarray: function (begin,numbered,taggable,align,spacing) {
+ this.Push(begin); if (taggable) {this.checkEqnEnv()}
+ align = align.replace(/[^clr]/g,'').split('').join(' ');
+ align = align.replace(/l/g,'left').replace(/r/g,'right').replace(/c/g,'center');
+ return STACKITEM.AMSarray(begin.name,numbered,taggable,this.stack).With({
+ arraydef: {
+ displaystyle: true,
+ rowspacing: ".5em",
+ columnalign: align,
+ columnspacing: (spacing||"1em"),
+ rowspacing: "3pt",
+ side: TEX.config.TagSide,
+ minlabelspacing: TEX.config.TagIndent
+ }
+ });
+ },
+
+ AlignedAMSArray: function (begin) {
+ var align = this.GetBrackets("\\begin{"+begin.name+"}");
+ return this.setArrayAlign(this.AMSarray.apply(this,arguments),align);
+ },
+
+ /*
+ * Handle alignat environments
+ */
+ AlignAt: function (begin,numbered,taggable) {
+ var n, valign, align = "", spacing = [];
+ if (!taggable) {valign = this.GetBrackets("\\begin{"+begin.name+"}")}
+ n = this.GetArgument("\\begin{"+begin.name+"}");
+ if (n.match(/[^0-9]/)) {
+ TEX.Error(["PositiveIntegerArg","Argument to %1 must me a positive integer",
+ "\\begin{"+begin.name+"}"]);
+ }
+ while (n > 0) {align += "rl"; spacing.push("0em 0em"); n--}
+ spacing = spacing.join(" ");
+ if (taggable) {return this.AMSarray(begin,numbered,taggable,align,spacing)}
+ var array = this.AMSarray(begin,numbered,taggable,align,spacing);
+ return this.setArrayAlign(array,valign);
+ },
+
+ /*
+ * Handle equation environment
+ */
+ EquationBegin: function (begin,force) {
+ this.checkEqnEnv();
+ this.stack.global.forcetag = (force && CONFIG.autoNumber !== "none");
+ return begin;
+ },
+ EquationStar: function (begin,row) {
+ this.stack.global.tagged = true; // prevent automatic tagging
+ return row;
+ },
+
+ /*
+ * Check for bad nesting of equation environments
+ */
+ checkEqnEnv: function () {
+ if (this.stack.global.eqnenv)
+ {TEX.Error(["ErroneousNestingEq","Erroneous nesting of equation structures"])}
+ this.stack.global.eqnenv = true;
+ },
+
+ /*
+ * Handle multiple integrals (make a mathop if followed by limits)
+ */
+ MultiIntegral: function (name,integral) {
+ var next = this.GetNext();
+ if (next === "\\") {
+ var i = this.i; next = this.GetArgument(name); this.i = i;
+ if (next === "\\limits") {
+ if (name === "\\idotsint") {integral = "\\!\\!\\mathop{\\,\\,"+integral+"}"}
+ else {integral = "\\!\\!\\!\\mathop{\\,\\,\\,"+integral+"}"}
+ }
+ }
+ this.string = integral + " " + this.string.slice(this.i);
+ this.i = 0;
+ },
+
+ /*
+ * Handle stretchable arrows
+ */
+ xArrow: function (name,chr,l,r) {
+ var def = {width: "+"+(l+r)+"mu", lspace: l+"mu"};
+ var bot = this.GetBrackets(name),
+ top = this.ParseArg(name);
+ var arrow = MML.mo(MML.chars(String.fromCharCode(chr))).With({
+ stretchy: true, texClass: MML.TEXCLASS.REL
+ });
+ var mml = MML.munderover(arrow);
+ mml.SetData(mml.over,MML.mpadded(top).With(def).With({voffset:".15em"}));
+ if (bot) {
+ bot = TEX.Parse(bot,this.stack.env).mml()
+ mml.SetData(mml.under,MML.mpadded(bot).With(def).With({voffset:"-.24em"}));
+ }
+ this.Push(mml.With({subsupOK:true}));
+ },
+
+ /*
+ * Get a delimiter or empty argument
+ */
+ GetDelimiterArg: function (name) {
+ var c = this.trimSpaces(this.GetArgument(name));
+ if (c == "") return null;
+ if (c in TEXDEF.delimiter) return c;
+ TEX.Error(["MissingOrUnrecognizedDelim","Missing or unrecognized delimiter for %1",name]);
+ },
+
+ /*
+ * Get a star following a control sequence name, if any
+ */
+ GetStar: function () {
+ var star = (this.GetNext() === "*");
+ if (star) {this.i++}
+ return star;
+ }
+
+ });
+
+ /******************************************************************************/
+
+ STACKITEM.Augment({
+ /*
+ * Increment equation number and form tag mtd element
+ */
+ autoTag: function () {
+ var global = this.global;
+ if (!global.notag) {
+ AMS.number++; global.tagID = CONFIG.formatNumber(AMS.number.toString());
+ var mml = TEX.Parse("\\text{"+CONFIG.formatTag(global.tagID)+"}",{}).mml();
+ global.tag = MML.mtd(mml).With({id:CONFIG.formatID(global.tagID)});
+ }
+ },
+
+ /*
+ * Get the tag and record the label, if any
+ */
+ getTag: function () {
+ var global = this.global, tag = global.tag; global.tagged = true;
+ if (global.label) {
+ if (CONFIG.useLabelIds) {tag.id = CONFIG.formatID(global.label)}
+ AMS.eqlabels[global.label] = {tag:global.tagID, id:tag.id};
+ }
+ //
+ // Check for repeated ID's (either in the document or as
+ // a previous tag) and find a unique related one. (#240)
+ //
+ if (document.getElementById(tag.id) || AMS.IDs[tag.id] || AMS.eqIDs[tag.id]) {
+ var i = 0, ID;
+ do {i++; ID = tag.id+"_"+i}
+ while (document.getElementById(ID) || AMS.IDs[ID] || AMS.eqIDs[ID]);
+ tag.id = ID; if (global.label) {AMS.eqlabels[global.label].id = ID}
+ }
+ AMS.eqIDs[tag.id] = 1;
+ this.clearTag();
+ return tag;
+ },
+ clearTag: function () {
+ var global = this.global;
+ delete global.tag; delete global.tagID; delete global.label;
+ },
+
+ /*
+ * If the initial child, skipping any initial space or
+ * empty braces (TeXAtom with child being an empty inferred row),
+ * is an , preceed it by an empty to force the to
+ * be infix.
+ */
+ fixInitialMO: function (data) {
+ for (var i = 0, m = data.length; i < m; i++) {
+ if (data[i] && (data[i].type !== "mspace" &&
+ (data[i].type !== "texatom" || (data[i].data[0] && data[i].data[0].data.length)))) {
+ if (data[i].isEmbellished()) data.unshift(MML.mi());
+ break;
+ }
+ }
+ }
+ });
+
+ /*
+ * Implement multline environment via a STACKITEM
+ */
+ STACKITEM.multline = STACKITEM.array.Subclass({
+ type: "multline",
+ Init: function (numbered,stack) {
+ this.SUPER(arguments).Init.apply(this);
+ this.numbered = (numbered && CONFIG.autoNumber !== "none");
+ this.save = {notag: stack.global.notag};
+ stack.global.tagged = !numbered && !stack.global.forcetag; // prevent automatic tagging in starred environments
+ },
+ EndEntry: function () {
+ if (this.table.length) {this.fixInitialMO(this.data)}
+ var mtd = MML.mtd.apply(MML,this.data);
+ if (this.data.shove) {mtd.columnalign = this.data.shove}
+ this.row.push(mtd);
+ this.data = [];
+ },
+ EndRow: function () {
+ if (this.row.length != 1) {
+ TEX.Error(["MultlineRowsOneCol",
+ "The rows within the %1 environment must have exactly one column",
+ "multline"]);
+ }
+ this.table.push(this.row); this.row = [];
+ },
+ EndTable: function () {
+ this.SUPER(arguments).EndTable.call(this);
+ if (this.table.length) {
+ var m = this.table.length-1, i, label = -1;
+ if (!this.table[0][0].columnalign) {this.table[0][0].columnalign = MML.ALIGN.LEFT}
+ if (!this.table[m][0].columnalign) {this.table[m][0].columnalign = MML.ALIGN.RIGHT}
+ if (!this.global.tag && this.numbered) {this.autoTag()}
+ if (this.global.tag && !this.global.notags) {
+ label = (this.arraydef.side === "left" ? 0 : this.table.length - 1);
+ this.table[label] = [this.getTag()].concat(this.table[label]);
+ }
+ for (i = 0, m = this.table.length; i < m; i++) {
+ var mtr = (i === label ? MML.mlabeledtr : MML.mtr);
+ this.table[i] = mtr.apply(MML,this.table[i]);
+ }
+ }
+ this.global.notag = this.save.notag;
+ }
+ });
+
+ /*
+ * Save data about numbering and taging equations, and add
+ * tags at the ends of rows.
+ */
+ STACKITEM.AMSarray = STACKITEM.array.Subclass({
+ type: "AMSarray",
+ Init: function (name,numbered,taggable,stack) {
+ this.SUPER(arguments).Init.apply(this);
+ this.numbered = (numbered && CONFIG.autoNumber !== "none");
+ this.save = {notags: stack.global.notags, notag: stack.global.notag};
+ stack.global.notags = (taggable ? null : name);
+ stack.global.tagged = !numbered && !stack.global.forcetag; // prevent automatic tagging in starred environments
+ },
+ EndEntry: function () {
+ if (this.row.length) {this.fixInitialMO(this.data)}
+ this.row.push(MML.mtd.apply(MML,this.data));
+ this.data = [];
+ },
+ EndRow: function () {
+ var mtr = MML.mtr;
+ if (!this.global.tag && this.numbered) {this.autoTag()}
+ if (this.global.tag && !this.global.notags) {
+ this.row = [this.getTag()].concat(this.row);
+ mtr = MML.mlabeledtr;
+ } else {this.clearTag()}
+ if (this.numbered) {delete this.global.notag}
+ this.table.push(mtr.apply(MML,this.row)); this.row = [];
+ },
+ EndTable: function () {
+ this.SUPER(arguments).EndTable.call(this);
+ this.global.notags = this.save.notags;
+ this.global.notag = this.save.notag;
+ }
+ });
+
+ //
+ // Look for \tag on a formula and make an mtable to include it
+ //
+ STACKITEM.start.Augment({
+ oldCheckItem: STACKITEM.start.prototype.checkItem,
+ checkItem: function (item) {
+ if (item.type === "stop") {
+ var mml = this.mmlData(), global = this.global;
+ if (AMS.display && !global.tag && !global.tagged && !global.isInner &&
+ (CONFIG.autoNumber === "all" || global.forcetag)) {this.autoTag()}
+ if (global.tag) {
+ var row = [this.getTag(),MML.mtd(mml)];
+ var def = {
+ side: TEX.config.TagSide,
+ minlabelspacing: TEX.config.TagIndent,
+ displaystyle: "inherit" // replaced by TeX input jax Translate() function with actual value
+ };
+ mml = MML.mtable(MML.mlabeledtr.apply(MML,row)).With(def);
+ }
+ return STACKITEM.mml(mml);
+ }
+ return this.oldCheckItem.call(this,item);
+ }
+ });
+
+ /******************************************************************************/
+
+ /*
+ * Add pre- and post-filters to handle the equation number maintainance.
+ */
+ TEX.prefilterHooks.Add(function (data) {
+ AMS.display = data.display;
+ AMS.number = AMS.startNumber; // reset equation numbers (in case the equation restarted)
+ AMS.eqlabels = {};
+ AMS.eqIDs = {};
+ AMS.badref = false;
+ if (AMS.refUpdate) {AMS.number = data.script.MathJax.startNumber}
+ });
+ TEX.postfilterHooks.Add(function (data) {
+ data.script.MathJax.startNumber = AMS.startNumber;
+ AMS.startNumber = AMS.number; // equation numbers for next equation
+ MathJax.Hub.Insert(AMS.IDs,AMS.eqIDs); // save IDs from this equation
+ MathJax.Hub.Insert(AMS.labels,AMS.eqlabels); // save labels from this equation
+ if (AMS.badref && !data.math.texError) {AMS.refs.push(data.script)} // reprocess later
+ },100);
+
+ MathJax.Hub.Register.MessageHook("Begin Math Input",function () {
+ AMS.refs = []; // array of jax with bad references
+ AMS.refUpdate = false;
+ });
+ MathJax.Hub.Register.MessageHook("End Math Input",function (message) {
+ if (AMS.refs.length) {
+ AMS.refUpdate = true;
+ for (var i = 0, m = AMS.refs.length; i < m; i++)
+ {AMS.refs[i].MathJax.state = MathJax.ElementJax.STATE.UPDATE}
+ return MathJax.Hub.processInput({
+ scripts:AMS.refs,
+ start: new Date().getTime(),
+ i:0, j:0, jax:{}, jaxIDs:[]
+ });
+ }
+ return null;
+ });
+
+ //
+ // Clear the equation numbers and labels
+ //
+ TEX.resetEquationNumbers = function (n,keepLabels) {
+ AMS.startNumber = (n || 0);
+ if (!keepLabels) {
+ AMS.labels = {};
+ AMS.IDs = {};
+ }
+ }
+
+ /******************************************************************************/
+
+ MathJax.Hub.Startup.signal.Post("TeX AMSmath Ready");
+
+});
+
+MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/AMSmath.js");
diff --git a/_static/scipy-mathjax/extensions/TeX/AMSsymbols.js b/_static/scipy-mathjax/extensions/TeX/AMSsymbols.js
new file mode 100644
index 000000000..5b1b6d292
--- /dev/null
+++ b/_static/scipy-mathjax/extensions/TeX/AMSsymbols.js
@@ -0,0 +1,349 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/TeX/AMSsymbols.js
+ *
+ * Implements macros for accessing the AMS symbol fonts.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2009-2017 The MathJax Consortium
+ *
+ * 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.
+ */
+
+MathJax.Extension["TeX/AMSsymbols"] = {
+ version: "2.7.1"
+};
+
+MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
+ var MML = MathJax.ElementJax.mml,
+ TEXDEF = MathJax.InputJax.TeX.Definitions;
+
+ TEXDEF.Add({
+
+ mathchar0mi: {
+ // Lowercase Greek letters
+ digamma: '03DD',
+ varkappa: '03F0',
+
+ // Uppercase Greek letters
+ varGamma: ['0393',{mathvariant: MML.VARIANT.ITALIC}],
+ varDelta: ['0394',{mathvariant: MML.VARIANT.ITALIC}],
+ varTheta: ['0398',{mathvariant: MML.VARIANT.ITALIC}],
+ varLambda: ['039B',{mathvariant: MML.VARIANT.ITALIC}],
+ varXi: ['039E',{mathvariant: MML.VARIANT.ITALIC}],
+ varPi: ['03A0',{mathvariant: MML.VARIANT.ITALIC}],
+ varSigma: ['03A3',{mathvariant: MML.VARIANT.ITALIC}],
+ varUpsilon: ['03A5',{mathvariant: MML.VARIANT.ITALIC}],
+ varPhi: ['03A6',{mathvariant: MML.VARIANT.ITALIC}],
+ varPsi: ['03A8',{mathvariant: MML.VARIANT.ITALIC}],
+ varOmega: ['03A9',{mathvariant: MML.VARIANT.ITALIC}],
+
+ // Hebrew letters
+ beth: '2136',
+ gimel: '2137',
+ daleth: '2138',
+
+ // Miscellaneous symbols
+// hbar: '0127', // in TeX/jax.js
+ backprime: ['2035',{variantForm: true}],
+ hslash: '210F',
+ varnothing: ['2205',{variantForm: true}],
+ blacktriangle: '25B4',
+ triangledown: ['25BD',{variantForm: true}],
+ blacktriangledown: '25BE',
+ square: '25FB',
+ Box: '25FB',
+ blacksquare: '25FC',
+ lozenge: '25CA',
+ Diamond: '25CA',
+ blacklozenge: '29EB',
+ circledS: ['24C8',{mathvariant: MML.VARIANT.NORMAL}],
+ bigstar: '2605',
+// angle: '2220', // in TeX/jax.js
+ sphericalangle: '2222',
+ measuredangle: '2221',
+ nexists: '2204',
+ complement: '2201',
+ mho: '2127',
+ eth: ['00F0',{mathvariant: MML.VARIANT.NORMAL}],
+ Finv: '2132',
+ diagup: '2571',
+ Game: '2141',
+ diagdown: '2572',
+ Bbbk: ['006B',{mathvariant: MML.VARIANT.DOUBLESTRUCK}],
+
+ yen: '00A5',
+ circledR: '00AE',
+ checkmark: '2713',
+ maltese: '2720'
+ },
+
+ mathchar0mo: {
+ // Binary operators
+ dotplus: '2214',
+ ltimes: '22C9',
+ smallsetminus: '2216',
+ rtimes: '22CA',
+ Cap: '22D2',
+ doublecap: '22D2',
+ leftthreetimes: '22CB',
+ Cup: '22D3',
+ doublecup: '22D3',
+ rightthreetimes: '22CC',
+ barwedge: '22BC',
+ curlywedge: '22CF',
+ veebar: '22BB',
+ curlyvee: '22CE',
+ doublebarwedge: '2A5E',
+ boxminus: '229F',
+ circleddash: '229D',
+ boxtimes: '22A0',
+ circledast: '229B',
+ boxdot: '22A1',
+ circledcirc: '229A',
+ boxplus: '229E',
+ centerdot: ['22C5',{variantForm: true}],
+ divideontimes: '22C7',
+ intercal: '22BA',
+
+ // Binary relations
+ leqq: '2266',
+ geqq: '2267',
+ leqslant: '2A7D',
+ geqslant: '2A7E',
+ eqslantless: '2A95',
+ eqslantgtr: '2A96',
+ lesssim: '2272',
+ gtrsim: '2273',
+ lessapprox: '2A85',
+ gtrapprox: '2A86',
+ approxeq: '224A',
+ lessdot: '22D6',
+ gtrdot: '22D7',
+ lll: '22D8',
+ llless: '22D8',
+ ggg: '22D9',
+ gggtr: '22D9',
+ lessgtr: '2276',
+ gtrless: '2277',
+ lesseqgtr: '22DA',
+ gtreqless: '22DB',
+ lesseqqgtr: '2A8B',
+ gtreqqless: '2A8C',
+ doteqdot: '2251',
+ Doteq: '2251',
+ eqcirc: '2256',
+ risingdotseq: '2253',
+ circeq: '2257',
+ fallingdotseq: '2252',
+ triangleq: '225C',
+ backsim: '223D',
+ thicksim: ['223C',{variantForm: true}],
+ backsimeq: '22CD',
+ thickapprox: ['2248',{variantForm: true}],
+ subseteqq: '2AC5',
+ supseteqq: '2AC6',
+ Subset: '22D0',
+ Supset: '22D1',
+ sqsubset: '228F',
+ sqsupset: '2290',
+ preccurlyeq: '227C',
+ succcurlyeq: '227D',
+ curlyeqprec: '22DE',
+ curlyeqsucc: '22DF',
+ precsim: '227E',
+ succsim: '227F',
+ precapprox: '2AB7',
+ succapprox: '2AB8',
+ vartriangleleft: '22B2',
+ lhd: '22B2',
+ vartriangleright: '22B3',
+ rhd: '22B3',
+ trianglelefteq: '22B4',
+ unlhd: '22B4',
+ trianglerighteq: '22B5',
+ unrhd: '22B5',
+ vDash: '22A8',
+ Vdash: '22A9',
+ Vvdash: '22AA',
+ smallsmile: ['2323',{variantForm: true}],
+ shortmid: ['2223',{variantForm: true}],
+ smallfrown: ['2322',{variantForm: true}],
+ shortparallel: ['2225',{variantForm: true}],
+ bumpeq: '224F',
+ between: '226C',
+ Bumpeq: '224E',
+ pitchfork: '22D4',
+ varpropto: '221D',
+ backepsilon: '220D',
+ blacktriangleleft: '25C2',
+ blacktriangleright: '25B8',
+ therefore: '2234',
+ because: '2235',
+ eqsim: '2242',
+ vartriangle: ['25B3',{variantForm: true}],
+ Join: '22C8',
+
+ // Negated relations
+ nless: '226E',
+ ngtr: '226F',
+ nleq: '2270',
+ ngeq: '2271',
+ nleqslant: ['2A87',{variantForm: true}],
+ ngeqslant: ['2A88',{variantForm: true}],
+ nleqq: ['2270',{variantForm: true}],
+ ngeqq: ['2271',{variantForm: true}],
+ lneq: '2A87',
+ gneq: '2A88',
+ lneqq: '2268',
+ gneqq: '2269',
+ lvertneqq: ['2268',{variantForm: true}],
+ gvertneqq: ['2269',{variantForm: true}],
+ lnsim: '22E6',
+ gnsim: '22E7',
+ lnapprox: '2A89',
+ gnapprox: '2A8A',
+ nprec: '2280',
+ nsucc: '2281',
+ npreceq: ['22E0',{variantForm: true}],
+ nsucceq: ['22E1',{variantForm: true}],
+ precneqq: '2AB5',
+ succneqq: '2AB6',
+ precnsim: '22E8',
+ succnsim: '22E9',
+ precnapprox: '2AB9',
+ succnapprox: '2ABA',
+ nsim: '2241',
+ ncong: '2246',
+ nshortmid: ['2224',{variantForm: true}],
+ nshortparallel: ['2226',{variantForm: true}],
+ nmid: '2224',
+ nparallel: '2226',
+ nvdash: '22AC',
+ nvDash: '22AD',
+ nVdash: '22AE',
+ nVDash: '22AF',
+ ntriangleleft: '22EA',
+ ntriangleright: '22EB',
+ ntrianglelefteq: '22EC',
+ ntrianglerighteq: '22ED',
+ nsubseteq: '2288',
+ nsupseteq: '2289',
+ nsubseteqq: ['2288',{variantForm: true}],
+ nsupseteqq: ['2289',{variantForm: true}],
+ subsetneq: '228A',
+ supsetneq: '228B',
+ varsubsetneq: ['228A',{variantForm: true}],
+ varsupsetneq: ['228B',{variantForm: true}],
+ subsetneqq: '2ACB',
+ supsetneqq: '2ACC',
+ varsubsetneqq: ['2ACB',{variantForm: true}],
+ varsupsetneqq: ['2ACC',{variantForm: true}],
+
+
+ // Arrows
+ leftleftarrows: '21C7',
+ rightrightarrows: '21C9',
+ leftrightarrows: '21C6',
+ rightleftarrows: '21C4',
+ Lleftarrow: '21DA',
+ Rrightarrow: '21DB',
+ twoheadleftarrow: '219E',
+ twoheadrightarrow: '21A0',
+ leftarrowtail: '21A2',
+ rightarrowtail: '21A3',
+ looparrowleft: '21AB',
+ looparrowright: '21AC',
+ leftrightharpoons: '21CB',
+ rightleftharpoons: ['21CC',{variantForm: true}],
+ curvearrowleft: '21B6',
+ curvearrowright: '21B7',
+ circlearrowleft: '21BA',
+ circlearrowright: '21BB',
+ Lsh: '21B0',
+ Rsh: '21B1',
+ upuparrows: '21C8',
+ downdownarrows: '21CA',
+ upharpoonleft: '21BF',
+ upharpoonright: '21BE',
+ downharpoonleft: '21C3',
+ restriction: '21BE',
+ multimap: '22B8',
+ downharpoonright: '21C2',
+ leftrightsquigarrow: '21AD',
+ rightsquigarrow: '21DD',
+ leadsto: '21DD',
+ dashrightarrow: '21E2',
+ dashleftarrow: '21E0',
+
+ // Negated arrows
+ nleftarrow: '219A',
+ nrightarrow: '219B',
+ nLeftarrow: '21CD',
+ nRightarrow: '21CF',
+ nleftrightarrow: '21AE',
+ nLeftrightarrow: '21CE'
+ },
+
+ delimiter: {
+ // corners
+ "\\ulcorner": '231C',
+ "\\urcorner": '231D',
+ "\\llcorner": '231E',
+ "\\lrcorner": '231F'
+ },
+
+ macros: {
+ implies: ['Macro','\\;\\Longrightarrow\\;'],
+ impliedby: ['Macro','\\;\\Longleftarrow\\;']
+ }
+
+ },null,true);
+
+ var REL = MML.mo.OPTYPES.REL;
+
+ MathJax.Hub.Insert(MML.mo.prototype,{
+ OPTABLE: {
+ infix: {
+ '\u2322': REL, // smallfrown
+ '\u2323': REL, // smallsmile
+ '\u25B3': REL, // vartriangle
+ '\uE006': REL, // nshortmid
+ '\uE007': REL, // nshortparallel
+ '\uE00C': REL, // lvertneqq
+ '\uE00D': REL, // gvertneqq
+ '\uE00E': REL, // ngeqq
+ '\uE00F': REL, // ngeqslant
+ '\uE010': REL, // nleqslant
+ '\uE011': REL, // nleqq
+ '\uE016': REL, // nsubseteqq
+ '\uE017': REL, // varsubsetneqq
+ '\uE018': REL, // nsupseteqq
+ '\uE019': REL, // varsupsetneqq
+ '\uE01A': REL, // varsubsetneq
+ '\uE01B': REL, // varsupsetneq
+ '\uE04B': REL, // npreceq
+ '\uE04F': REL // nsucceq
+ }
+ }
+ });
+
+ MathJax.Hub.Startup.signal.Post("TeX AMSsymbols Ready");
+
+});
+
+MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/AMSsymbols.js");
diff --git a/_static/scipy-mathjax/extensions/TeX/HTML.js b/_static/scipy-mathjax/extensions/TeX/HTML.js
new file mode 100644
index 000000000..65b1d8752
--- /dev/null
+++ b/_static/scipy-mathjax/extensions/TeX/HTML.js
@@ -0,0 +1,106 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/TeX/HTML.js
+ *
+ * Implements the \href, \class, \style, \cssId macros.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2010-2017 The MathJax Consortium
+ *
+ * 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.
+ */
+
+MathJax.Extension["TeX/HTML"] = {
+ version: "2.7.1"
+};
+
+MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
+
+ var TEX = MathJax.InputJax.TeX;
+ var TEXDEF = TEX.Definitions;
+
+ TEXDEF.Add({
+ macros: {
+ href: 'HREF_attribute',
+ "class": 'CLASS_attribute',
+ style: 'STYLE_attribute',
+ cssId: 'ID_attribute'
+ }
+ },null,true);
+
+ TEX.Parse.Augment({
+
+ //
+ // Implements \href{url}{math}
+ //
+ HREF_attribute: function (name) {
+ var url = this.GetArgument(name),
+ arg = this.GetArgumentMML(name);
+ this.Push(arg.With({href:url}));
+ },
+
+ //
+ // Implements \class{name}{math}
+ //
+ CLASS_attribute: function (name) {
+ var CLASS = this.GetArgument(name),
+ arg = this.GetArgumentMML(name);
+ if (arg["class"] != null) {CLASS = arg["class"] + " " + CLASS}
+ this.Push(arg.With({"class":CLASS}));
+ },
+
+ //
+ // Implements \style{style-string}{math}
+ //
+ STYLE_attribute: function (name) {
+ var style = this.GetArgument(name),
+ arg = this.GetArgumentMML(name);
+ // check that it looks like a style string
+ if (arg.style != null) {
+ if (style.charAt(style.length-1) !== ";") {style += ";"}
+ style = arg.style + " " + style;
+ }
+ this.Push(arg.With({style: style}));
+ },
+
+ //
+ // Implements \cssId{id}{math}
+ //
+ ID_attribute: function (name) {
+ var ID = this.GetArgument(name),
+ arg = this.GetArgumentMML(name);
+ this.Push(arg.With({id:ID}));
+ },
+
+ //
+ // returns an argument that is a single MathML element
+ // (in an mrow if necessary)
+ //
+ GetArgumentMML: function (name) {
+ var arg = this.ParseArg(name);
+ if (arg.inferred && arg.data.length == 1)
+ {arg = arg.data[0]} else {delete arg.inferred}
+ return arg;
+ }
+
+ });
+
+ MathJax.Hub.Startup.signal.Post("TeX HTML Ready");
+
+});
+
+MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/HTML.js");
diff --git a/_static/scipy-mathjax/extensions/TeX/action.js b/_static/scipy-mathjax/extensions/TeX/action.js
new file mode 100644
index 000000000..e12230d9e
--- /dev/null
+++ b/_static/scipy-mathjax/extensions/TeX/action.js
@@ -0,0 +1,83 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/TeX/action.js
+ *
+ * Implements the \mathtip, \texttip, and \toggle macros, which give
+ * access from TeX to the tag in the MathML that underlies
+ * MathJax's internal format.
+ *
+ * Usage:
+ *
+ * \mathtip{math}{tip} % use "tip" (in math mode) as tooltip for "math"
+ * \texttip{math}{tip} % use "tip" (in text mode) as tooltip for "math"
+ * \toggle{math1}{math2}...\endtoggle
+ * % show math1, and when clicked, show math2, and so on.
+ * % When the last one is clicked, go back to math1.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2011-2017 The MathJax Consortium
+ *
+ * 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.
+ */
+
+MathJax.Extension["TeX/action"] = {
+ version: "2.7.1"
+};
+
+MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
+ var TEX = MathJax.InputJax.TeX,
+ MML = MathJax.ElementJax.mml;
+
+ //
+ // Set up control sequenecs
+ //
+ TEX.Definitions.Add({
+ macros: {
+ toggle: 'Toggle',
+ mathtip: 'Mathtip',
+ texttip: ['Macro','\\mathtip{#1}{\\text{#2}}',2]
+ }
+ },null,true);
+
+ TEX.Parse.Augment({
+
+ //
+ // Implement \toggle {math1} {math2} ... \endtoggle
+ // (as an )
+ //
+ Toggle: function (name) {
+ var data = [], arg;
+ while ((arg = this.GetArgument(name)) !== "\\endtoggle")
+ {data.push(TEX.Parse(arg,this.stack.env).mml())}
+ this.Push(MML.maction.apply(MML,data).With({actiontype: MML.ACTIONTYPE.TOGGLE}));
+ },
+
+ //
+ // Implement \mathtip{math}{tip}
+ // (an an )
+ //
+ Mathtip: function(name) {
+ var arg = this.ParseArg(name), tip = this.ParseArg(name);
+ this.Push(MML.maction(arg,tip).With({actiontype: MML.ACTIONTYPE.TOOLTIP}));
+ }
+ });
+
+ MathJax.Hub.Startup.signal.Post("TeX action Ready");
+
+});
+
+MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/action.js");
diff --git a/_static/scipy-mathjax/extensions/TeX/autobold.js b/_static/scipy-mathjax/extensions/TeX/autobold.js
new file mode 100644
index 000000000..c0a3febfc
--- /dev/null
+++ b/_static/scipy-mathjax/extensions/TeX/autobold.js
@@ -0,0 +1,50 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/TeX/autobold.js
+ *
+ * Adds \boldsymbol around mathematics that appears in a section
+ * of an HTML page that is in bold.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2009-2017 The MathJax Consortium
+ *
+ * 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.
+ */
+
+MathJax.Extension["TeX/autobold"] = {
+ version: "2.7.1"
+};
+
+MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
+ var TEX = MathJax.InputJax.TeX;
+
+ TEX.prefilterHooks.Add(function (data) {
+ var span = data.script.parentNode.insertBefore(document.createElement("span"),data.script);
+ span.visibility = "hidden";
+ span.style.fontFamily = "Times, serif";
+ span.appendChild(document.createTextNode("ABCXYZabcxyz"));
+ var W = span.offsetWidth;
+ span.style.fontWeight = "bold";
+ if (W && span.offsetWidth === W) {data.math = "\\boldsymbol{"+data.math+"}"}
+ span.parentNode.removeChild(span);
+ });
+
+ MathJax.Hub.Startup.signal.Post("TeX autobold Ready");
+
+});
+
+MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/autobold.js");
diff --git a/_static/scipy-mathjax/extensions/TeX/autoload-all.js b/_static/scipy-mathjax/extensions/TeX/autoload-all.js
new file mode 100644
index 000000000..9522cb80b
--- /dev/null
+++ b/_static/scipy-mathjax/extensions/TeX/autoload-all.js
@@ -0,0 +1,83 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/TeX/autoload-all.js
+ *
+ * Provides pre-defined macros to autoload all the extensions
+ * so that all macros that MathJax knows about are available.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2013-2017 The MathJax Consortium
+ *
+ * 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.
+ */
+
+MathJax.Extension["TeX/autoload-all"] = {
+ version: "2.7.1"
+};
+
+MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
+
+ var EXTENSIONS = {
+ action: ["mathtip","texttip","toggle"],
+ AMSmath: ["mathring","nobreakspace","negmedspace","negthickspace","intI",
+ "iiiint","idotsint","dddot","ddddot","sideset","boxed",
+ "substack","injlim","projlim","varliminf","varlimsup",
+ "varinjlim","varprojlim","DeclareMathOperator","operatorname",
+ "genfrac","tfrac","dfrac","binom","tbinom","dbinom","cfrac",
+ "shoveleft","shoveright","xrightarrow","xleftarrow"],
+ begingroup: ["begingroup","endgroup","gdef","global"],
+ cancel: ["cancel","bcancel","xcancel","cancelto"],
+ color: ["color","textcolor","colorbox","fcolorbox","definecolor"],
+ enclose: ["enclose"],
+ extpfeil: ["Newextarrow","xlongequal","xmapsto","xtofrom",
+ "xtwoheadleftarrow","xtwoheadrightarrow"],
+ mhchem: ["ce","cee","cf"]
+ };
+
+ var ENVIRONMENTS = {
+ AMSmath: ["subarray","smallmatrix","equation","equation*"],
+ AMScd: ["CD"]
+ };
+
+ var name, i, m, defs = {macros:{}, environment:{}};
+
+ for (name in EXTENSIONS) {if (EXTENSIONS.hasOwnProperty(name)) {
+ if (!MathJax.Extension["TeX/"+name]) {
+ var macros = EXTENSIONS[name];
+ for (i = 0, m = macros.length; i < m; i++)
+ {defs.macros[macros[i]] = ["Extension",name]}
+ }
+ }}
+
+ for (name in ENVIRONMENTS) {if (ENVIRONMENTS.hasOwnProperty(name)) {
+ if (!MathJax.Extension["TeX/"+name]) {
+ var envs = ENVIRONMENTS[name];
+ for (i = 0, m = envs.length; i < m; i++)
+ {defs.environment[envs[i]] = ["ExtensionEnv",null,name]}
+ }
+ }}
+
+ MathJax.InputJax.TeX.Definitions.Add(defs);
+
+ MathJax.Hub.Startup.signal.Post("TeX autoload-all Ready");
+
+});
+
+MathJax.Callback.Queue(
+ ["Require",MathJax.Ajax,"[MathJax]/extensions/TeX/AMSsymbols.js"],
+ ["loadComplete",MathJax.Ajax,"[MathJax]/extensions/TeX/autoload-all.js"]
+);
diff --git a/_static/scipy-mathjax/extensions/TeX/bbox.js b/_static/scipy-mathjax/extensions/TeX/bbox.js
new file mode 100644
index 000000000..97a8ed5dd
--- /dev/null
+++ b/_static/scipy-mathjax/extensions/TeX/bbox.js
@@ -0,0 +1,102 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/TeX/bbox.js
+ *
+ * This file implements the \bbox macro, which creates an box that
+ * can be styled (for background colors, and so on). You can include
+ * an optional dimension that tells how much extra padding to include
+ * around the bounding box for the mathematics, or a color specification
+ * for the background color to use, or both. E.g.,
+ *
+ * \bbox[2pt]{x+y} % an invisible box around x+y with 2pt of extra space
+ * \bbox[green]{x+y} % a green box around x+y
+ * \bbox[green,2pt]{x+y} % a green box with 2pt of extra space
+ *
+ * You can also specify style attributes, for example
+ *
+ * \bbox[red,border:3px solid blue,5px]{x+y}
+ *
+ * would give a red background with a 3px solid blue border that has 5px
+ * of padding between the border and the mathematics. Note that not all
+ * output formats support the style specifications. In particular, the
+ * NativeMML output depends on the browser to render the attributes, and
+ * not all MathML renderers will honor them (e.g., MathPlayer2 doesn't
+ * render border styles).
+ *
+ * This file will be loaded automatically when \bbox is first used.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2011-2017 The MathJax Consortium
+ *
+ * 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.
+ */
+
+MathJax.Extension["TeX/bbox"] = {
+ version: "2.7.1"
+};
+
+MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
+
+ var TEX = MathJax.InputJax.TeX,
+ MML = MathJax.ElementJax.mml;
+
+ TEX.Definitions.Add({macros: {bbox: "BBox"}},null,true);
+
+ TEX.Parse.Augment({
+ BBox: function (name) {
+ var bbox = this.GetBrackets(name,""),
+ math = this.ParseArg(name);
+ var parts = bbox.split(/,/), def, background, style;
+ for (var i = 0, m = parts.length; i < m; i++) {
+ var part = parts[i].replace(/^\s+/,'').replace(/\s+$/,'');
+ var match = part.match(/^(\.\d+|\d+(\.\d*)?)(pt|em|ex|mu|px|in|cm|mm)$/);
+ if (match) {
+ if (def)
+ {TEX.Error(["MultipleBBoxProperty","%1 specified twice in %2","Padding",name])}
+ var pad = this.BBoxPadding(match[1]+match[3]);
+ if (pad) def = {height:"+"+pad, depth:"+"+pad, lspace:pad, width:"+"+(2*match[1])+match[3]};
+ } else if (part.match(/^([a-z0-9]+|\#[0-9a-f]{6}|\#[0-9a-f]{3})$/i)) {
+ if (background)
+ {TEX.Error(["MultipleBBoxProperty","%1 specified twice in %2","Background",name])}
+ background = part;
+ } else if (part.match(/^[-a-z]+:/i)) {
+ if (style)
+ {TEX.Error(["MultipleBBoxProperty","%1 specified twice in %2", "Style",name])}
+ style = this.BBoxStyle(part);
+ } else if (part !== "") {
+ TEX.Error(
+ ["InvalidBBoxProperty",
+ "'%1' doesn't look like a color, a padding dimension, or a style",
+ part]
+ );
+ }
+ }
+ if (def) {math = MML.mpadded(math).With(def)}
+ if (background || style) {
+ math = MML.mstyle(math).With({mathbackground:background, style:style});
+ }
+ this.Push(math);
+ },
+ BBoxStyle: function (styles) {return styles},
+ BBoxPadding: function (pad) {return pad}
+ });
+
+ MathJax.Hub.Startup.signal.Post("TeX bbox Ready");
+
+});
+
+MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/bbox.js");
diff --git a/_static/scipy-mathjax/extensions/TeX/begingroup.js b/_static/scipy-mathjax/extensions/TeX/begingroup.js
new file mode 100644
index 000000000..c9cead324
--- /dev/null
+++ b/_static/scipy-mathjax/extensions/TeX/begingroup.js
@@ -0,0 +1,309 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/TeX/begingroup.js
+ *
+ * Implements \begingroup and \endgroup commands that make local
+ * definitions possible and are removed when the \endgroup occurs.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2011-2017 The MathJax Consortium
+ *
+ * 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.
+ */
+
+MathJax.Extension["TeX/begingroup"] = {
+ version: "2.7.1"
+};
+
+MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
+
+ var TEX = MathJax.InputJax.TeX,
+ TEXDEF = TEX.Definitions;
+
+ /****************************************************/
+
+ //
+ // A namespace for localizing macros and environments
+ // (\begingroup and \endgroup create and destroy these)
+ //
+ var NSFRAME = MathJax.Object.Subclass({
+ macros: null, // the local macro definitions
+ environments: null, // the local environments
+ Init: function (macros,environments) {
+ this.macros = (macros || {});
+ this.environments = (environments || {});
+ },
+ //
+ // Find a macro or environment by name
+ //
+ Find: function (name,type) {if (this[type][name]) {return this[type][name]}},
+ //
+ // Define or remove a macro or environment
+ //
+ Def: function (name,value,type) {this[type][name] = value},
+ Undef: function (name,type) {delete this[type][name]},
+ //
+ // Merge two namespaces (used when the equation namespace is combined with the root one)
+ //
+ Merge: function (frame) {
+ MathJax.Hub.Insert(this.macros,frame.macros);
+ MathJax.Hub.Insert(this.environments,frame.environments);
+ },
+ //
+ // Move global macros to the stack (globally) and remove from the frame
+ //
+ MergeGlobals: function (stack) {
+ var macros = this.macros;
+ for (var cs in macros) {if (macros.hasOwnProperty(cs) && macros[cs].global) {
+ stack.Def(cs,macros[cs],"macros",true);
+ delete macros[cs].global; delete macros[cs];
+ }}
+ },
+ //
+ // Clear the macro and environment lists
+ // (but not global macros unless "all" is true)
+ //
+ Clear: function (all) {
+ this.environments = {};
+ if (all) {this.macros = {}} else {
+ var macros = this.macros;
+ for (var cs in macros) {
+ if (macros.hasOwnProperty(cs) && !macros[cs].global) {delete macros[cs]}
+ }
+ }
+ return this;
+ }
+ });
+
+ /****************************************************/
+
+ //
+ // A Stack of namespace frames
+ //
+ var NSSTACK = TEX.nsStack = MathJax.Object.Subclass({
+ stack: null, // the namespace frames
+ top: 0, // the current top one (we don't pop for real until the equation completes)
+ isEqn: false, // true if this is the equation stack (not the global one)
+ //
+ // Set up the initial stack frame
+ //
+ Init: function (eqn) {
+ this.isEqn = eqn; this.stack = [];
+ if (!eqn) {this.Push(NSFRAME(TEXDEF.macros,TEXDEF.environment))}
+ else {this.Push(NSFRAME())}
+ },
+ //
+ // Define a macro or environment in the top frame
+ //
+ Def: function (name,value,type,global) {
+ var n = this.top-1;
+ if (global) {
+ //
+ // Define global macros in the base frame and remove that cs
+ // from all other frames. Mark the global ones in equations
+ // so they can be made global when merged with the root stack.
+ //
+ while (n > 0) {this.stack[n].Undef(name,type); n--}
+ if (!MathJax.Object.isArray(value)) {value = [value]}
+ if (this.isEqn) {value.global = true}
+ }
+ this.stack[n].Def(name,value,type);
+ },
+ //
+ // Push a new namespace frame on the stack
+ //
+ Push: function (frame) {
+ this.stack.push(frame);
+ this.top = this.stack.length;
+ },
+ //
+ // Pop the top stack frame
+ // (if it is the root, just keep track of the pop so we can
+ // reset it if the equation is reprocessed)
+ //
+ Pop: function () {
+ var top;
+ if (this.top > 1) {
+ top = this.stack[--this.top];
+ if (this.isEqn) {this.stack.pop()}
+ } else if (this.isEqn) {
+ this.Clear();
+ }
+ return top;
+ },
+ //
+ // Search the stack from top to bottom for the first
+ // definition of the given control sequence in the given type
+ //
+ Find: function (name,type) {
+ for (var i = this.top-1; i >= 0; i--) {
+ var def = this.stack[i].Find(name,type);
+ if (def) {return def}
+ }
+ return null;
+ },
+ //
+ // Combine the equation stack with the global one
+ // (The bottom frame of the equation goes with the top frame of the global one,
+ // and the remainder are pushed on the global stack, truncated to the
+ // position where items were poped from it.)
+ //
+ Merge: function (stack) {
+ stack.stack[0].MergeGlobals(this);
+ this.stack[this.top-1].Merge(stack.stack[0]);
+ var data = [this.top,this.stack.length-this.top].concat(stack.stack.slice(1));
+ this.stack.splice.apply(this.stack,data);
+ this.top = this.stack.length;
+ },
+ //
+ // Put back the temporarily poped items
+ //
+ Reset: function () {this.top = this.stack.length},
+ //
+ // Clear the stack and start with a blank frame
+ //
+ Clear: function (all) {
+ this.stack = [this.stack[0].Clear()];
+ this.top = this.stack.length;
+ }
+ },{
+ nsFrame: NSFRAME
+ });
+
+ /****************************************************/
+
+ //
+ // Define the new macros
+ //
+ TEXDEF.Add({
+ macros: {
+ begingroup: "BeginGroup",
+ endgroup: "EndGroup",
+ global: ["Extension","newcommand"],
+ gdef: ["Extension","newcommand"]
+ }
+ },null,true);
+
+ TEX.Parse.Augment({
+ //
+ // Implement \begingroup
+ //
+ BeginGroup: function (name) {
+ TEX.eqnStack.Push(NSFRAME());
+ },
+ //
+ // Implements \endgroup
+ //
+ EndGroup: function (name) {
+ //
+ // If the equation has pushed frames, pop one,
+ // Otherwise clear the equation stack and pop the top global one
+ //
+ if (TEX.eqnStack.top > 1) {
+ TEX.eqnStack.Pop();
+ } else if (TEX.rootStack.top === 1) {
+ TEX.Error(["ExtraEndMissingBegin","Extra %1 or missing \\begingroup",name]);
+ } else {
+ TEX.eqnStack.Clear();
+ TEX.rootStack.Pop();
+ }
+ },
+
+ //
+ // Replace the original routines with ones that looks through the
+ // equation and root stacks for the given name
+ //
+ csFindMacro: function (name) {
+ return (TEX.eqnStack.Find(name,"macros") || TEX.rootStack.Find(name,"macros"));
+ },
+ envFindName: function (name) {
+ return (TEX.eqnStack.Find(name,"environments") || TEX.rootStack.Find(name,"environments"));
+ }
+
+ });
+
+ /****************************************************/
+
+ TEX.rootStack = NSSTACK(); // the global namespace stack
+ TEX.eqnStack = NSSTACK(true); // the equation stack
+
+ //
+ // Reset the global stack and clear the equation stack
+ // (this gets us back to the initial stack state as it was
+ // before the equation was first processed, in case the equation
+ // get restarted due to an autoloaded file)
+ //
+ TEX.prefilterHooks.Add(function () {TEX.rootStack.Reset(); TEX.eqnStack.Clear(true)});
+
+ //
+ // We only get here if there were no errors and the equation is fully
+ // processed (all restarts are complete). So we merge the equation
+ // stack into the global stack, thus making the changes from this
+ // equation permanent.
+ //
+ TEX.postfilterHooks.Add(function () {TEX.rootStack.Merge(TEX.eqnStack)});
+
+ /*********************************************************/
+
+ MathJax.Hub.Register.StartupHook("TeX newcommand Ready",function () {
+
+ //
+ // Add the commands that depend on the newcommand code
+ //
+ TEXDEF.Add({
+ macros: {
+ global: "Global",
+ gdef: ["Macro","\\global\\def"]
+ }
+ },null,true);
+
+ TEX.Parse.Augment({
+ //
+ // Modify the way macros and environments are defined
+ // to make them go into the equation namespace stack
+ //
+ setDef: function (name,value) {
+ value.isUser = true;
+ TEX.eqnStack.Def(name,value,"macros",this.stack.env.isGlobal);
+ delete this.stack.env.isGlobal;
+ },
+ setEnv: function (name,value) {
+ value.isUser = true;
+ TEX.eqnStack.Def(name,value,"environments")
+ },
+
+ //
+ // Implement \global (for \global\let, \global\def and \global\newcommand)
+ //
+ Global: function (name) {
+ var i = this.i; var cs = this.GetCSname(name); this.i = i;
+ if (cs !== "let" && cs !== "def" && cs !== "newcommand") {
+ TEX.Error(["GlobalNotFollowedBy",
+ "%1 not followed by \\let, \\def, or \\newcommand",name]);
+ }
+ this.stack.env.isGlobal = true;
+ }
+
+ });
+
+ });
+
+ MathJax.Hub.Startup.signal.Post("TeX begingroup Ready");
+
+});
+
+MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/begingroup.js");
diff --git a/_static/scipy-mathjax/extensions/TeX/boldsymbol.js b/_static/scipy-mathjax/extensions/TeX/boldsymbol.js
new file mode 100644
index 000000000..70f0979d3
--- /dev/null
+++ b/_static/scipy-mathjax/extensions/TeX/boldsymbol.js
@@ -0,0 +1,75 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/TeX/boldsymbol.js
+ *
+ * Implements the \boldsymbol{...} command to make bold
+ * versions of all math characters (not just variables).
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2009-2017 The MathJax Consortium
+ *
+ * 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.
+ */
+
+MathJax.Extension["TeX/boldsymbol"] = {
+ version: "2.7.1"
+};
+
+MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
+
+ var MML = MathJax.ElementJax.mml;
+ var TEX = MathJax.InputJax.TeX;
+ var TEXDEF = TEX.Definitions;
+
+ var BOLDVARIANT = {};
+ BOLDVARIANT[MML.VARIANT.NORMAL] = MML.VARIANT.BOLD;
+ BOLDVARIANT[MML.VARIANT.ITALIC] = MML.VARIANT.BOLDITALIC;
+ BOLDVARIANT[MML.VARIANT.FRAKTUR] = MML.VARIANT.BOLDFRAKTUR;
+ BOLDVARIANT[MML.VARIANT.SCRIPT] = MML.VARIANT.BOLDSCRIPT;
+ BOLDVARIANT[MML.VARIANT.SANSSERIF] = MML.VARIANT.BOLDSANSSERIF;
+ BOLDVARIANT["-tex-caligraphic"] = "-tex-caligraphic-bold";
+ BOLDVARIANT["-tex-oldstyle"] = "-tex-oldstyle-bold";
+
+ TEXDEF.Add({macros: {boldsymbol: 'Boldsymbol'}},null,true);
+
+ TEX.Parse.Augment({
+ mmlToken: function (token) {
+ if (this.stack.env.boldsymbol) {
+ var variant = token.Get("mathvariant");
+ if (variant == null) {token.mathvariant = MML.VARIANT.BOLD}
+ else {token.mathvariant = (BOLDVARIANT[variant]||variant)}
+ }
+ return token;
+ },
+
+ Boldsymbol: function (name) {
+ var boldsymbol = this.stack.env.boldsymbol,
+ font = this.stack.env.font;
+ this.stack.env.boldsymbol = true;
+ this.stack.env.font = null;
+ var mml = this.ParseArg(name);
+ this.stack.env.font = font;
+ this.stack.env.boldsymbol = boldsymbol;
+ this.Push(mml);
+ }
+ });
+
+ MathJax.Hub.Startup.signal.Post("TeX boldsymbol Ready");
+
+});
+
+MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/boldsymbol.js");
diff --git a/_static/scipy-mathjax/extensions/TeX/cancel.js b/_static/scipy-mathjax/extensions/TeX/cancel.js
new file mode 100644
index 000000000..8f8387375
--- /dev/null
+++ b/_static/scipy-mathjax/extensions/TeX/cancel.js
@@ -0,0 +1,110 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/TeX/cancel.js
+ *
+ * Implements the \cancel, \bcancel, \xcancel, and \cancelto macros.
+ *
+ * Usage:
+ *
+ * \cancel{math} % strikeout math from lower left to upper right
+ * \bcancel{math} % strikeout from upper left to lower right
+ * \xcancel{math} % strikeout with an X
+ * \cancelto{value}{math} % strikeout with arrow going to value
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2011-2017 The MathJax Consortium
+ *
+ * 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.
+ */
+
+MathJax.Extension["TeX/cancel"] = {
+ version: "2.7.1",
+
+ //
+ // The attributes allowed in \enclose{notation}[attributes]{math}
+ //
+ ALLOWED: {
+ color: 1, mathcolor: 1,
+ background: 1, mathbackground: 1,
+ padding: 1,
+ thickness: 1
+ }
+};
+
+MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
+ var TEX = MathJax.InputJax.TeX,
+ MML = MathJax.ElementJax.mml,
+ CANCEL = MathJax.Extension["TeX/cancel"];
+
+ CANCEL.setAttributes = function (def,attr) {
+ if (attr !== "") {
+ attr = attr.replace(/ /g,"").split(/,/);
+ for (var i = 0, m = attr.length; i < m; i++) {
+ var keyvalue = attr[i].split(/[:=]/);
+ if (CANCEL.ALLOWED[keyvalue[0]]) {
+ if (keyvalue[1] === "true") {keyvalue[1] = true}
+ if (keyvalue[1] === "false") {keyvalue[1] = false}
+ def[keyvalue[0]] = keyvalue[1];
+ }
+ }
+ }
+ return def;
+ };
+
+ //
+ // Set up macros
+ //
+ TEX.Definitions.Add({
+ macros: {
+ cancel: ['Cancel',MML.NOTATION.UPDIAGONALSTRIKE],
+ bcancel: ['Cancel',MML.NOTATION.DOWNDIAGONALSTRIKE],
+ xcancel: ['Cancel',MML.NOTATION.UPDIAGONALSTRIKE+" "+MML.NOTATION.DOWNDIAGONALSTRIKE],
+ cancelto: 'CancelTo'
+ }
+ },null,true);
+
+ TEX.Parse.Augment({
+ //
+ // Implement \cancel[attributes]{math},
+ // \bcancel[attributes]{math}, and
+ // \xcancel[attributes]{math}
+ //
+ Cancel: function(name,notation) {
+ var attr = this.GetBrackets(name,""), math = this.ParseArg(name);
+ var def = CANCEL.setAttributes({notation: notation},attr);
+ this.Push(MML.menclose(math).With(def));
+ },
+
+ //
+ // Implement \cancelto{value}[attributes]{math}
+ //
+ CancelTo: function(name,notation) {
+ var value = this.ParseArg(name),
+ attr = this.GetBrackets(name,""),
+ math = this.ParseArg(name);
+ var def = CANCEL.setAttributes({notation: MML.NOTATION.UPDIAGONALSTRIKE+" "+MML.NOTATION.UPDIAGONALARROW},attr);
+ value = MML.mpadded(value).With({depth:"-.1em",height:"+.1em",voffset:".1em"});
+ this.Push(MML.msup(MML.menclose(math).With(def),value));
+ }
+
+ });
+
+ MathJax.Hub.Startup.signal.Post("TeX cancel Ready");
+
+});
+
+MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/cancel.js");
diff --git a/_static/scipy-mathjax/extensions/TeX/color.js b/_static/scipy-mathjax/extensions/TeX/color.js
new file mode 100644
index 000000000..f3b749495
--- /dev/null
+++ b/_static/scipy-mathjax/extensions/TeX/color.js
@@ -0,0 +1,281 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/TeX/color.js
+ *
+ * Implements LaTeX-compatible \color macro rather than MathJax's original
+ * (non-standard) version. It includes the rgb, RGB, gray, and named color
+ * models, and the \textcolor, \definecolor, \colorbox, and \fcolorbox
+ * macros.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2011-2017 The MathJax Consortium
+ *
+ * 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.
+ */
+
+//
+// The configuration defaults, augmented by the user settings
+//
+MathJax.Extension["TeX/color"] = {
+ version: "2.7.1",
+
+ config: MathJax.Hub.CombineConfig("TeX.color",{
+ padding: "5px",
+ border: "2px"
+ }),
+
+ colors: {
+ Apricot: "#FBB982",
+ Aquamarine: "#00B5BE",
+ Bittersweet: "#C04F17",
+ Black: "#221E1F",
+ Blue: "#2D2F92",
+ BlueGreen: "#00B3B8",
+ BlueViolet: "#473992",
+ BrickRed: "#B6321C",
+ Brown: "#792500",
+ BurntOrange: "#F7921D",
+ CadetBlue: "#74729A",
+ CarnationPink: "#F282B4",
+ Cerulean: "#00A2E3",
+ CornflowerBlue: "#41B0E4",
+ Cyan: "#00AEEF",
+ Dandelion: "#FDBC42",
+ DarkOrchid: "#A4538A",
+ Emerald: "#00A99D",
+ ForestGreen: "#009B55",
+ Fuchsia: "#8C368C",
+ Goldenrod: "#FFDF42",
+ Gray: "#949698",
+ Green: "#00A64F",
+ GreenYellow: "#DFE674",
+ JungleGreen: "#00A99A",
+ Lavender: "#F49EC4",
+ LimeGreen: "#8DC73E",
+ Magenta: "#EC008C",
+ Mahogany: "#A9341F",
+ Maroon: "#AF3235",
+ Melon: "#F89E7B",
+ MidnightBlue: "#006795",
+ Mulberry: "#A93C93",
+ NavyBlue: "#006EB8",
+ OliveGreen: "#3C8031",
+ Orange: "#F58137",
+ OrangeRed: "#ED135A",
+ Orchid: "#AF72B0",
+ Peach: "#F7965A",
+ Periwinkle: "#7977B8",
+ PineGreen: "#008B72",
+ Plum: "#92268F",
+ ProcessBlue: "#00B0F0",
+ Purple: "#99479B",
+ RawSienna: "#974006",
+ Red: "#ED1B23",
+ RedOrange: "#F26035",
+ RedViolet: "#A1246B",
+ Rhodamine: "#EF559F",
+ RoyalBlue: "#0071BC",
+ RoyalPurple: "#613F99",
+ RubineRed: "#ED017D",
+ Salmon: "#F69289",
+ SeaGreen: "#3FBC9D",
+ Sepia: "#671800",
+ SkyBlue: "#46C5DD",
+ SpringGreen: "#C6DC67",
+ Tan: "#DA9D76",
+ TealBlue: "#00AEB3",
+ Thistle: "#D883B7",
+ Turquoise: "#00B4CE",
+ Violet: "#58429B",
+ VioletRed: "#EF58A0",
+ White: "#FFFFFF",
+ WildStrawberry: "#EE2967",
+ Yellow: "#FFF200",
+ YellowGreen: "#98CC70",
+ YellowOrange: "#FAA21A"
+ },
+
+ /*
+ * Look up a color based on its model and definition
+ */
+ getColor: function (model,def) {
+ if (!model) {model = "named"}
+ var fn = this["get_"+model];
+ if (!fn) {this.TEX.Error(["UndefinedColorModel","Color model '%1' not defined",model])}
+ return fn.call(this,def);
+ },
+
+ /*
+ * Get an rgb color
+ */
+ get_rgb: function (rgb) {
+ rgb = rgb.replace(/^\s+/,"").replace(/\s+$/,"").split(/\s*,\s*/); var RGB = "#";
+ if (rgb.length !== 3)
+ {this.TEX.Error(["ModelArg1","Color values for the %1 model require 3 numbers","rgb"])}
+ for (var i = 0; i < 3; i++) {
+ if (!rgb[i].match(/^(\d+(\.\d*)?|\.\d+)$/))
+ {this.TEX.Error(["InvalidDecimalNumber","Invalid decimal number"])}
+ var n = parseFloat(rgb[i]);
+ if (n < 0 || n > 1) {
+ this.TEX.Error(["ModelArg2",
+ "Color values for the %1 model must be between %2 and %3",
+ "rgb",0,1]);
+ }
+ n = Math.floor(n*255).toString(16); if (n.length < 2) {n = "0"+n}
+ RGB += n;
+ }
+ return RGB;
+ },
+
+ /*
+ * Get an RGB color
+ */
+ get_RGB: function (rgb) {
+ rgb = rgb.replace(/^\s+/,"").replace(/\s+$/,"").split(/\s*,\s*/); var RGB = "#";
+ if (rgb.length !== 3)
+ {this.TEX.Error(["ModelArg1","Color values for the %1 model require 3 numbers","RGB"])}
+ for (var i = 0; i < 3; i++) {
+ if (!rgb[i].match(/^\d+$/))
+ {this.TEX.Error(["InvalidNumber","Invalid number"])}
+ var n = parseInt(rgb[i]);
+ if (n > 255) {
+ this.TEX.Error(["ModelArg2",
+ "Color values for the %1 model must be between %2 and %3",
+ "RGB",0,255]);
+ }
+ n = n.toString(16); if (n.length < 2) {n = "0"+n}
+ RGB += n;
+ }
+ return RGB;
+ },
+
+ /*
+ * Get a gray-scale value
+ */
+ get_gray: function (gray) {
+ if (!gray.match(/^\s*(\d+(\.\d*)?|\.\d+)\s*$/))
+ {this.TEX.Error(["InvalidDecimalNumber","Invalid decimal number"])}
+ var n = parseFloat(gray);
+ if (n < 0 || n > 1) {
+ this.TEX.Error(["ModelArg2",
+ "Color values for the %1 model must be between %2 and %3",
+ "gray",0,1]);
+ }
+ n = Math.floor(n*255).toString(16); if (n.length < 2) {n = "0"+n}
+ return "#"+n+n+n;
+ },
+
+ /*
+ * Get a named value
+ */
+ get_named: function (name) {
+ if (this.colors[name]) {return this.colors[name]}
+ return name;
+ },
+
+ padding: function () {
+ var pad = "+"+this.config.padding;
+ var unit = this.config.padding.replace(/^.*?([a-z]*)$/,"$1");
+ var pad2 = "+"+(2*parseFloat(pad))+unit;
+ return {width:pad2, height:pad, depth:pad, lspace:this.config.padding};
+ }
+
+};
+
+MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
+ var TEX = MathJax.InputJax.TeX,
+ MML = MathJax.ElementJax.mml;
+ var STACKITEM = TEX.Stack.Item;
+ var COLOR = MathJax.Extension["TeX/color"];
+
+ COLOR.TEX = TEX; // for reference in getColor above
+
+ TEX.Definitions.Add({
+ macros: {
+ color: "Color",
+ textcolor: "TextColor",
+ definecolor: "DefineColor",
+ colorbox: "ColorBox",
+ fcolorbox: "fColorBox"
+ }
+ },null,true);
+
+ TEX.Parse.Augment({
+
+ //
+ // Override \color macro definition
+ //
+ Color: function (name) {
+ var model = this.GetBrackets(name),
+ color = this.GetArgument(name);
+ color = COLOR.getColor(model,color);
+ var mml = STACKITEM.style().With({styles:{mathcolor:color}});
+ this.stack.env.color = color;
+ this.Push(mml);
+ },
+
+ TextColor: function (name) {
+ var model = this.GetBrackets(name),
+ color = this.GetArgument(name);
+ color = COLOR.getColor(model,color);
+ var old = this.stack.env.color; this.stack.env.color = color;
+ var math = this.ParseArg(name);
+ if (old) {this.stack.env.color} else {delete this.stack.env.color}
+ this.Push(MML.mstyle(math).With({mathcolor: color}));
+ },
+
+ //
+ // Define the \definecolor macro
+ //
+ DefineColor: function (name) {
+ var cname = this.GetArgument(name),
+ model = this.GetArgument(name),
+ def = this.GetArgument(name);
+ COLOR.colors[cname] = COLOR.getColor(model,def);
+ },
+
+ //
+ // Produce a text box with a colored background
+ //
+ ColorBox: function (name) {
+ var cname = this.GetArgument(name),
+ arg = this.InternalMath(this.GetArgument(name));
+ this.Push(MML.mpadded.apply(MML,arg).With({
+ mathbackground:COLOR.getColor("named",cname)
+ }).With(COLOR.padding()));
+ },
+
+ //
+ // Procude a framed text box with a colored background
+ //
+ fColorBox: function (name) {
+ var fname = this.GetArgument(name),
+ cname = this.GetArgument(name),
+ arg = this.InternalMath(this.GetArgument(name));
+ this.Push(MML.mpadded.apply(MML,arg).With({
+ mathbackground: COLOR.getColor("named",cname),
+ style: "border: "+COLOR.config.border+" solid "+COLOR.getColor("named",fname)
+ }).With(COLOR.padding()));
+ }
+
+ });
+
+ MathJax.Hub.Startup.signal.Post("TeX color Ready");
+
+});
+
+MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/color.js");
diff --git a/_static/scipy-mathjax/extensions/TeX/enclose.js b/_static/scipy-mathjax/extensions/TeX/enclose.js
new file mode 100644
index 000000000..384c71cd5
--- /dev/null
+++ b/_static/scipy-mathjax/extensions/TeX/enclose.js
@@ -0,0 +1,91 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/TeX/enclose.js
+ *
+ * Implements the \enclose macros, which give access from TeX to the
+ * tag in the MathML that underlies MathJax's internal format.
+ *
+ * Usage:
+ *
+ * \enclose{notation}{math} % enclose math using given notation
+ * \enclose{notation,notation,...}{math} % enclose with several notations
+ * \enclose{notation}[attributes]{math} % enclose with attributes
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2011-2017 The MathJax Consortium
+ *
+ * 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.
+ */
+
+MathJax.Extension["TeX/enclose"] = {
+ version: "2.7.1",
+
+ //
+ // The attributes allowed in \enclose{notation}[attributes]{math}
+ //
+ ALLOWED: {
+ arrow: 1,
+ color: 1, mathcolor: 1,
+ background: 1, mathbackground: 1,
+ padding: 1,
+ thickness: 1
+ }
+};
+
+MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
+ var TEX = MathJax.InputJax.TeX,
+ MML = MathJax.ElementJax.mml,
+ ALLOW = MathJax.Extension["TeX/enclose"].ALLOWED;
+
+ //
+ // Set up macro
+ //
+ TEX.Definitions.Add({macros: {enclose: 'Enclose'}},null,true);
+
+ TEX.Parse.Augment({
+ //
+ // Implement \enclose{notation}[attr]{math}
+ // (create math )
+ //
+ Enclose: function(name) {
+ var notation = this.GetArgument(name),
+ attr = this.GetBrackets(name),
+ math = this.ParseArg(name);
+ var def = {notation: notation.replace(/,/g," ")};
+ if (attr) {
+ attr = attr.replace(/ /g,"").split(/,/);
+ for (var i = 0, m = attr.length; i < m; i++) {
+ var keyvalue = attr[i].split(/[:=]/);
+ if (ALLOW[keyvalue[0]]) {
+ keyvalue[1] = keyvalue[1].replace(/^"(.*)"$/,"$1");
+ if (keyvalue[1] === "true") {keyvalue[1] = true}
+ if (keyvalue[1] === "false") {keyvalue[1] = false}
+ if (keyvalue[0] === "arrow" && keyvalue[1])
+ {def.notation = def.notation + " updiagonalarrow"} else
+ {def[keyvalue[0]] = keyvalue[1]}
+ }
+ }
+ }
+ this.Push(MML.menclose(math).With(def));
+ }
+ });
+
+ MathJax.Hub.Startup.signal.Post("TeX enclose Ready");
+
+});
+
+MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/enclose.js");
diff --git a/_static/scipy-mathjax/extensions/TeX/extpfeil.js b/_static/scipy-mathjax/extensions/TeX/extpfeil.js
new file mode 100644
index 000000000..cece5903f
--- /dev/null
+++ b/_static/scipy-mathjax/extensions/TeX/extpfeil.js
@@ -0,0 +1,102 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/TeX/extpfeil.js
+ *
+ * Implements additional stretchy arrow macros.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2011-2017 The MathJax Consortium
+ *
+ * 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.
+ */
+
+MathJax.Extension["TeX/extpfeil"] = {
+ version: "2.7.1"
+};
+
+MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
+
+ var TEX = MathJax.InputJax.TeX,
+ TEXDEF = TEX.Definitions;
+
+ //
+ // Define the arrows to load the AMSmath extension
+ // (since they need its xArrow method)
+ //
+ TEXDEF.Add({
+ macros: {
+ xtwoheadrightarrow: ['Extension','AMSmath'],
+ xtwoheadleftarrow: ['Extension','AMSmath'],
+ xmapsto: ['Extension','AMSmath'],
+ xlongequal: ['Extension','AMSmath'],
+ xtofrom: ['Extension','AMSmath'],
+ Newextarrow: ['Extension','AMSmath']
+ }
+ },null,true);
+
+ //
+ // Redefine the macros when AMSmath is loaded
+ //
+ MathJax.Hub.Register.StartupHook("TeX AMSmath Ready",function () {
+ MathJax.Hub.Insert(TEXDEF,{
+ macros: {
+ xtwoheadrightarrow: ['xArrow',0x21A0,12,16],
+ xtwoheadleftarrow: ['xArrow',0x219E,17,13],
+ xmapsto: ['xArrow',0x21A6,6,7],
+ xlongequal: ['xArrow',0x003D,7,7],
+ xtofrom: ['xArrow',0x21C4,12,12],
+ Newextarrow: 'NewExtArrow'
+ }
+ });
+ });
+
+ //
+ // Implements \Newextarrow to define a new arrow (not compatible with \newextarrow, but
+ // the equivalent for MathJax)
+ //
+ TEX.Parse.Augment({
+ NewExtArrow: function (name) {
+ var cs = this.GetArgument(name),
+ space = this.GetArgument(name),
+ chr = this.GetArgument(name);
+ if (!cs.match(/^\\([a-z]+|.)$/i)) {
+ TEX.Error(["NewextarrowArg1",
+ "First argument to %1 must be a control sequence name",name]);
+ }
+ if (!space.match(/^(\d+),(\d+)$/)) {
+ TEX.Error(
+ ["NewextarrowArg2",
+ "Second argument to %1 must be two integers separated by a comma",
+ name]
+ );
+ }
+ if (!chr.match(/^(\d+|0x[0-9A-F]+)$/i)) {
+ TEX.Error(
+ ["NewextarrowArg3",
+ "Third argument to %1 must be a unicode character number",
+ name]
+ );
+ }
+ cs = cs.substr(1); space = space.split(","); chr = parseInt(chr);
+ TEXDEF.macros[cs] = ['xArrow',chr,parseInt(space[0]),parseInt(space[1])];
+ }
+ });
+
+ MathJax.Hub.Startup.signal.Post("TeX extpfeil Ready");
+});
+
+MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/extpfeil.js");
diff --git a/_static/scipy-mathjax/extensions/TeX/mathchoice.js b/_static/scipy-mathjax/extensions/TeX/mathchoice.js
new file mode 100644
index 000000000..c43b3b2c4
--- /dev/null
+++ b/_static/scipy-mathjax/extensions/TeX/mathchoice.js
@@ -0,0 +1,107 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/TeX/mathchoice.js
+ *
+ * Implements the \mathchoice macro (rarely used)
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2009-2017 The MathJax Consortium
+ *
+ * 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.
+ */
+
+MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
+ var VERSION = "2.7.1";
+
+ var MML = MathJax.ElementJax.mml;
+ var TEX = MathJax.InputJax.TeX;
+ var TEXDEF = TEX.Definitions;
+
+ TEXDEF.Add({macros: {mathchoice: 'MathChoice'}},null,true);
+
+ TEX.Parse.Augment({
+ MathChoice: function (name) {
+ var D = this.ParseArg(name),
+ T = this.ParseArg(name),
+ S = this.ParseArg(name),
+ SS = this.ParseArg(name);
+ this.Push(MML.TeXmathchoice(D,T,S,SS));
+ }
+ });
+
+ MML.TeXmathchoice = MML.mbase.Subclass({
+ type: "TeXmathchoice", notParent: true,
+ choice: function () {
+ if (this.selection != null) return this.selection;
+ if (this.choosing) return 2; // prevent infinite loops: see issue #1151
+ this.choosing = true;
+ var selection = 0, values = this.getValues("displaystyle","scriptlevel");
+ if (values.scriptlevel > 0) {selection = Math.min(3,values.scriptlevel+1)}
+ else {selection = (values.displaystyle ? 0 : 1)}
+ // only cache the result if we are actually in place in a