by Han, Jeanine, and Mary (maintainers@mathquill.com)
Good news! We've resumed active development and we're committed to getting
things running smoothly.
Find a dusty corner? Let us know!
Just load MathQuill and call our constructors on some HTML element DOM objects, for example:
<link rel="stylesheet" href="https://github.com/mathquill/mathquill/raw/v0.10.1/path/to/mathquill.css"/>
<script src="https://github.com/mathquill/mathquill/raw/v0.10.1/ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="https://github.com/mathquill/mathquill/raw/v0.10.1/path/to/mathquill.js"></script>
Solve <span id="problem">ax^2 + bx + c = 0</span>:
<span id="answer">x=</span>
<script>
var MQ = MathQuill.getInterface(2);
MQ.StaticMath($('#problem')[0]);
var answer = MQ.MathField($('#answer')[0], {
handlers: {
edit: function() {
checkAnswer(answer.latex());
}
}
});
</script>
To load MathQuill,
- jQuery 1.4.3+ has to be loaded before mathquill.js
(Google CDN-hosted copy recommended)
- the fonts should be served from the font/ directory relative to
mathquill.css (unless you'd rather change where your copy of mathquill.css
includes them from), which is already the case if you just:
- download and serve the latest release.
To use the MathQuill API, first get the latest version of the interface:
var MQ = MathQuill.getInterface(2);
Now you can call MQ.StaticMath() or MQ.MathField(), which MathQuill-ify
an HTML element and return an API object. If the element had already been
MathQuill-ified into the same kind, return that kind of API object (if
different kind or not an HTML element, null). Note that it always returns
either an instance of itself, or null.
var staticMath = MQ.StaticMath(staticMathSpan);
mathField instanceof MQ.StaticMath // => true
mathField instanceof MQ // => true
mathField instanceof MathQuill // => true
var mathField = MQ.MathField(mathFieldSpan);
mathField instanceof MQ.MathField // => true
mathField instanceof MQ.EditableField // => true
mathField instanceof MQ // => true
mathField instanceof MathQuill // => true
MQ itself is a function that takes an HTML element and, if it's the root
HTML element of a static math or math field, returns an API object for it
(if not, null):
MQ(mathFieldSpan) instanceof MQ.MathField // => true
MQ(otherSpan) // => null
API objects for the same MathQuill instance have the same .id, which will
always be a unique truthy primitive value that can be used as an object key
(like an ad hoc [Map][] or [Set][]):
MQ(mathFieldSpan).id === mathField.id // => true
var setOfMathFields = {};
setOfMathFields[mathField.id] = mathField;
MQ(mathFieldSpan).id in setOfMathFields // => true
staticMath.id in setOfMathFields // => false
Similarly, API objects for the same MathQuill instance share a .data object
(which can be used like an ad hoc [WeakMap][] or [WeakSet][]):
MQ(mathFieldSpan).data === mathField.data // => true
mathField.data.foo = 'bar';
MQ(mathFieldSpan).data.foo // => 'bar'
Any element that has been MathQuill-ified can be reverted:
<span id="revert-me" class="mathquill-static-math">
some <code>HTML</code>
</span>
MQ($('#revert-me')[0]).revert().html(); // => 'some <code>HTML</code>'
MathQuill uses computed dimensions, so if they change (because an element was mathquill-ified before it was in the visible HTML DOM, or the font size changed), then you'll need to tell MathQuill to recompute:
var mathFieldSpan = $('<span>\\sqrt{2}</span>');
var mathField = MQ.MathField(mathFieldSpan[0]);
mathFieldSpan.appendTo(document.body);
mathField.reflow();
MathQuill API objects further expose the following public methods:
.el() returns the root HTML element.html() returns the contents as static HTML.latex() returns the contents as LaTeX.latex('a_n x^n') will render the argument as LaTeXAdditionally, descendants of MQ.EditableField (currently only MQ.MathField)
expose:
.write(' - 1') will write some LaTeX at the current cursor position.cmd('\\sqrt') will enter a LaTeX command at the current cursor position or
with the current selection.select() selects the contents (just like [on textareas][] and [on
inputs][]).clearSelection() clears the current selection.moveTo{Left,Right,Dir}End() move the cursor to the left/right end of the
editable field, respectively. (The first two are implemented in terms of
.moveToDirEnd(dir) where dir is one of MQ.L or MQ.R, constants that
obey the contract that MQ.L === -MQ.R and vice versa.).keystroke(keys) simulates keystrokes given a string like "Ctrl-Home Del",
a whitespace-delimited list of key values with optional prefixes.typedText(text) simulates typing text, one character at a timeᴇxᴘᴇʀɪᴍᴇɴᴛᴀʟ .dropEmbedded(pageX, pageY, options) insert a custom
embedded element at the given coordinates, where options is an object like:js
{
htmlString: '<span class="custom-embed"></span>',
text: function() { return 'custom_embed'; },
latex: function() { return '\customEmbed'; }
}
* ᴇxᴘᴇʀɪᴍᴇɴᴛᴀʟ .registerEmbed('name', function(id){return options}) allows MathQuill to parse custom embedded objects from latex, where options is an object like the one defined above in .dropEmbedded. This will parse the following latex into the embedded object you defined: \embed{name}[id]}
MathQuill overwrites the global MathQuill variable when loaded. You can undo
that with .noConflict() (similar to [jQuery.noConflict()]
(http://api.jquery.com/jQuery.noConflict)):
<script src="https://github.com/mathquill/mathquill/raw/v0.10.1/path/to/first-mathquill.js"></script>
<script src="https://github.com/mathquill/mathquill/raw/v0.10.1/path/to/second-mathquill.js"></script>
<script>
var secondMQ = MathQuill.noConflict().getInterface(2);
secondMQ.MathField(...);
var firstMQ = MathQuill.getInterface(2);
firstMQ.MathField(...);
</script>
(Warning: This lets different copies of MathQuill each power their own math fields, but using different copies on the same DOM element won't work. Anyway, .noConflict() is primarily to help you reduce globals.)
MQ.MathField() can also take an options object:
var el = $('<span>x^2</span>').appendTo('body');
var mathField = MQ.MathField(el[0], {
spaceBehavesLikeTab: true,
leftRightIntoCmdGoes: 'up',
restrictMismatchedBrackets: true,
sumStartsWithNEquals: true,
supSubsRequireOperand: true,
charsThatBreakOutOfSupSub: '+-=<>',
autoSubscriptNumerals: true,
autoCommands: 'pi theta sqrt sum',
autoOperatorNames: 'sin cos etc',
substituteTextarea: function() {
return document.createElement('textarea');
},
handlers: {
edit: function(mathField) { ... },
upOutOf: function(mathField) { ... },
moveOutOf: function(dir, mathField) { if (dir === MQ.L) ... else ... }
}
});
To change mathField's options, the .config({ ... }) method takes an options
object in the same format.
Global defaults for a page may be set with MQ.config({ ... }).
If spaceBehavesLikeTab is true the keystrokes {Shift-,}Spacebar will behave
like {Shift-,}Tab escaping from the current block (as opposed to the default
behavior of inserting a Space character).
By default, the Left and Right keys move the cursor through all possible cursor
positions in a particular order: right into a fraction puts the cursor at the
left end of the numerator, right out of the numerator puts the cursor at the
left end of the denominator, right out of the denominator puts the cursor to the
right of the fraction; symmetrically, left into a fraction puts the cursor at
the right end of the denominator, etc. Note that right out of the numerator to
the left end of the denominator is actually leftwards (and downwards, it's
basically wrapped). If instead you want right to always go right, and left to
always go left, you can set leftRightIntoCmdGoes to 'up' or 'down' so that
left and right go up or down (respectively) into commands, e.g. 'up' means
that left into a fraction goes up into the numerator, skipping the denominator;
symmetrically, right out of the numerator skips the denominator and puts the
cursor to the right of the fraction, which unlike the default behavior is
actually rightwards (the drawback is the denominator is always skipped, you
can't get to it with just Left and Right, you have to press Down); which is
the same behavior as the Desmos calculator. 'down' instead means it is the
numerator that is always skipped, which is the same behavior as the Mac OS X
built-in app Grapher.
If restrictMismatchedBrackets is true then you can type [a,b) and [a,b), but
if you try typing [x} or \langle x|, you'll get [{x}] or
\langle|x|\rangle instead. This lets you type (|x|+1) normally; otherwise,
you'd get \left( \right| x \left| + 1 \right).
If sumStartsWithNEquals is true then when you type \sum, \prod, or
\coprod, the lower limit starts out with n=, e.g. you get the LaTeX
\sum_{n=}^{ }, rather than empty by default.
supSubsRequireOperand disables typing of superscripts and subscripts when
there's nothing to the left of the cursor to be exponentiated or subscripted.
Averts the especially confusing typo x^^2, which looks much like x^2.
charsThatBreakOutOfSupSub sets the chars that when typed, "break out" of
superscripts and subscripts: for example, typing x^2n+y normally results in
the LaTeX x^{2n+y}, you have to hit Down or Tab (or Space if
spaceBehavesLikeTab is true) to move the cursor out of the exponent and get
the LaTeX x^{2n}+y; this option makes + "break out" of the exponent and
type what you expect. Problem is, now you can't just type x^n+m to get the
LaTeX x^{n+m}, you have to type x^(n+m and delete the paren or something.
(Doesn't apply to the first character in a superscript or subscript, so typing
x^-6 still results in x^{-6}.)
autoCommands, a space-delimited list of LaTeX control words (no backslash,
letters only, min length 2), defines the (default empty) set of "auto-commands",
commands automatically rendered by just typing the letters without typing a
backslash first.
autoOperatorNames, a list of the same form (space-delimited letters-only each
length>=2), and overrides the set of operator names that automatically become
non-italicized when typing the letters without typing a backslash first, like
sin, log, etc. (Defaults to the LaTeX built-in operator names, but
with additional trig operators like sech, arcsec, arsinh, etc.)
substituteTextarea, a function that creates a focusable DOM element, called
when setting up a math field. It defaults to <textarea autocorrect=off .../>,
but for example, Desmos substitutes <span tabindex=0></span> on iOS to
suppress the built-in virtual keyboard in favor of a custom math keypad that
calls the MathQuill API. Unfortunately there's no universal check for a virtual
keyboard, you can't even detect a touchscreen (notably
Modernizr gave up) and even if you could, Windows 8 and ChromeOS
devices have both physical keyboards and touchscreens and you can connect
physical keyboards to iOS and Android devices with Bluetooth, so touchscreen !=
virtual keyboard. Desmos currently sniffs the user agent for iOS, so Bluetooth
keyboards just don't work in Desmos on iOS, the tradeoffs are up to you.
Supported handlers:
- moveOutOf, deleteOutOf, and selectOutOf are called with dir and the
math field API object as arguments
- upOutOf, downOutOf, enter, and edit are called with just the API
object as the argument
The *OutOf handlers are called when Left/Right/Up/Down/Backspace/Del/
Shift-Left/Shift-Right is pressed but the cursor is at the left/right/top/bottom
edge and so nothing happens within the math field. For example, when the cursor
is at the left edge, pressing the Left key causes the moveOutOf handler (if
provided) to be called with MQ.L and the math field API object as arguments,
and Backspace causes deleteOutOf (if provided) to be called with MQ.L and
the API object as arguments, etc.
The enter handler is called whenever Enter is pressed.
The edit handler is called when the contents of the field might have been
changed by stuff being typed, or deleted, or written with the API, etc.
(Deprecated aliases: edited, reflow.)
Hand
$ claude mcp add mathquill \
-- python -m otcore.mcp_server <graph>