itutor-mathlive
Version:
Beautifully typeset math made easy
530 lines (455 loc) • 120 kB
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"><title>editor/editor-mathfield.js - MathLive Docs</title><meta name="description" content="Beautifully typeset math made easy"><meta name="keywords" content="latex, tex, math, typesetting, documentation, docs">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="scripts/prettify/prettify.js"></script>
<script src="scripts/prettify/lang-css.js"></script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,700|Source+Sans+Pro:400,400i,700,900" rel="stylesheet">
<style>pre.prettyprint{background: #35434e;}</style>
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow-night.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
<link type="text/css" rel="stylesheet" href="styles/custom.css">
</head>
<body>
<div class="forkme"><a href="https://github.com/arnog/mathlive"><img style="position: absolute; top: 0; right: 0; border: 0; z-index:1;" src="https://camo.githubusercontent.com/52760788cde945287fbb584134c4cbc2bc36f904/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f77686974655f6666666666662e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_white_ffffff.png"></a></div>
<section role="navigation">
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
<label for="nav-trigger" class="navicon-button x">
<div class="navicon"></div>
</label>
<label for="nav-trigger" class="overlay"></label>
<nav id="nav">
<h3 class="group-title home"><a href="index.html">MathLive Docs</a></h3><input class="search" placeholder="Search" type="text"><div class="list"><h3 class="group-title">Tutorials</h3><ul><li><a href="tutorial-CONTRIBUTOR_GUIDE.html">Contributor Guide</a></li><li><a href="tutorial-MASTON.html">MASTON</a></li><li><a href="tutorial-USAGE_GUIDE.html">Usage Guide</a></li></ul><h3 class="group-title">Classes</h3><ul><li class="private"><a href="Context.html" class="className">Context</a><ul class='methods private'><li data-type='method' class='private'><a href="Context.html#clone" class="methodName">clone</a></li><li data-type='method' class='private'><a href="Context.html#cloneWith" class="methodName">cloneWith</a></li><li data-type='method' class='private'><a href="Context.html#getBackgroundColor" class="methodName">getBackgroundColor</a></li><li data-type='method' class='private'><a href="Context.html#getColor" class="methodName">getColor</a></li><li data-type='method' class='private'><a href="Context.html#setMathstyle" class="methodName">setMathstyle</a></li><li data-type='method' class='private'><a href="Context.html#withMathstyle" class="methodName">withMathstyle</a></li></ul></li><li><a href="EditableMathlist.html" class="className">EditableMathlist</a><ul class='methods'><li data-type='method'><a href="EditableMathlist.html#_addCell" class="methodName">_addCell</a></li><li data-type='method'><a href="EditableMathlist.html#_deleteAtoms" class="methodName">_deleteAtoms</a></li><li data-type='method'><a href="EditableMathlist.html#addColumnAfter_" class="methodName">addColumnAfter_</a></li><li data-type='method'><a href="EditableMathlist.html#addColumnBefore_" class="methodName">addColumnBefore_</a></li><li data-type='method'><a href="EditableMathlist.html#addRowAfter_" class="methodName">addRowAfter_</a></li><li data-type='method'><a href="EditableMathlist.html#addRowBefore_" class="methodName">addRowBefore_</a></li><li data-type='method' class='private'><a href="EditableMathlist.html#ancestor" class="methodName">ancestor</a></li><li data-type='method' class='private'><a href="EditableMathlist.html#anchor" class="methodName">anchor</a></li><li data-type='method'><a href="EditableMathlist.html#applyStyle" class="methodName">applyStyle</a></li><li data-type='method' class='private'><a href="EditableMathlist.html#commandOffsets" class="methodName">commandOffsets</a></li><li data-type='method' class='private'><a href="EditableMathlist.html#commitCommandStringBeforeInsertionPoint" class="methodName">commitCommandStringBeforeInsertionPoint</a></li><li data-type='method' class='private'><a href="EditableMathlist.html#contains" class="methodName">contains</a></li><li data-type='method' class='private'><a href="EditableMathlist.html#decorateCommandStringAroundInsertionPoint" class="methodName">decorateCommandStringAroundInsertionPoint</a></li><li data-type='method'><a href="EditableMathlist.html#delete" class="methodName">delete</a></li><li data-type='method'><a href="EditableMathlist.html#delete_" class="methodName">delete_</a></li><li data-type='method'><a href="EditableMathlist.html#deleteAll_" class="methodName">deleteAll_</a></li><li data-type='method'><a href="EditableMathlist.html#deleteNextChar_" class="methodName">deleteNextChar_</a></li><li data-type='method'><a href="EditableMathlist.html#deleteNextWord_" class="methodName">deleteNextWord_</a></li><li data-type='method'><a href="EditableMathlist.html#deletePreviousChar_" class="methodName">deletePreviousChar_</a></li><li data-type='method'><a href="EditableMathlist.html#deletePreviousWord_" class="methodName">deletePreviousWord_</a></li><li data-type='method'><a href="EditableMathlist.html#deleteToGroupEnd_" class="methodName">deleteToGroupEnd_</a></li><li data-type='method'><a href="EditableMathlist.html#deleteToGroupStart_" class="methodName">deleteToGroupStart_</a></li><li data-type='method'><a href="EditableMathlist.html#deleteToMathFieldEnd_" class="methodName">deleteToMathFieldEnd_</a></li><li data-type='method' class='private'><a href="EditableMathlist.html#endOffset" class="methodName">endOffset</a></li><li data-type='method' class='private'><a href="EditableMathlist.html#extend" class="methodName">extend</a></li><li data-type='method'><a href="EditableMathlist.html#extendDown_" class="methodName">extendDown_</a></li><li data-type='method'><a href="EditableMathlist.html#extendToGroupEnd_" class="methodName">extendToGroupEnd_</a></li><li data-type='method'><a href="EditableMathlist.html#extendToGroupStart_" class="methodName">extendToGroupStart_</a></li><li data-type='method'><a href="EditableMathlist.html#extendToMathFieldEnd_" class="methodName">extendToMathFieldEnd_</a></li><li data-type='method'><a href="EditableMathlist.html#extendToMathFieldStart_" class="methodName">extendToMathFieldStart_</a></li><li data-type='method'><a href="EditableMathlist.html#extendToNextBoundary_" class="methodName">extendToNextBoundary_</a></li><li data-type='method'><a href="EditableMathlist.html#extendToNextChar_" class="methodName">extendToNextChar_</a></li><li data-type='method'><a href="EditableMathlist.html#extendToNextWord_" class="methodName">extendToNextWord_</a></li><li data-type='method'><a href="EditableMathlist.html#extendToPreviousBoundary_" class="methodName">extendToPreviousBoundary_</a></li><li data-type='method'><a href="EditableMathlist.html#extendToPreviousChar_" class="methodName">extendToPreviousChar_</a></li><li data-type='method'><a href="EditableMathlist.html#extendToPreviousWord_" class="methodName">extendToPreviousWord_</a></li><li data-type='method'><a href="EditableMathlist.html#extendUp_" class="methodName">extendUp_</a></li><li data-type='method' class='private'><a href="EditableMathlist.html#extractCharactersBeforeInsertionPoint" class="methodName">extractCharactersBeforeInsertionPoint</a></li><li data-type='method' class='private'><a href="EditableMathlist.html#extractCommandStringAroundInsertionPoint" class="methodName">extractCommandStringAroundInsertionPoint</a></li><li data-type='method' class='private'><a href="EditableMathlist.html#extractContents" class="methodName">extractContents</a></li><li data-type='method' class='private'><a href="EditableMathlist.html#extractContentsOrdInGroupBeforeInsertionPoint" class="methodName">extractContentsOrdInGroupBeforeInsertionPoint</a></li><li data-type='method' class='private'><a href="EditableMathlist.html#filter" class="methodName">filter</a></li><li data-type='method'><a href="EditableMathlist.html#insert" class="methodName">insert</a></li><li data-type='method' class='private'><a href="EditableMathlist.html#insertFirstAtom" class="methodName">insertFirstAtom</a></li><li data-type='method'><a href="EditableMathlist.html#isCollapsed" class="methodName">isCollapsed</a></li><li data-type='method' class='private'><a href="EditableMathlist.html#jump" class="methodName">jump</a></li><li data-type='method' class='private'><a href="EditableMathlist.html#leap" class="methodName">leap</a></li><li data-type='method'><a href="EditableMathlist.html#moveAfterParent_" class="methodName">moveAfterParent_</a></li><li data-type='method'><a href="EditableMathlist.html#moveBeforeParent_" class="methodName">moveBeforeParent_</a></li><li data-type='method'><a href="EditableMathlist.html#moveDown_" class="methodName">moveDown_</a></li><li data-type='method'><a href="EditableMathlist.html#moveToGroupEnd_" class="methodName">moveToGroupEnd_</a></li><li data-type='method'><a href="EditableMathlist.html#moveToGroupStart_" class="methodName">moveToGroupStart_</a></li><li data-type='method'><a href="EditableMathlist.html#moveToMathFieldEnd_" class="methodName">moveToMathFieldEnd_</a></li><li data-type='method'><a href="EditableMathlist.html#moveToMathFieldStart_" class="methodName">moveToMathFieldStart_</a></li><li data-type='method'><a href="EditableMathlist.html#moveToNextChar_" class="methodName">moveToNextChar_</a></li><li data-type='method'><a href="EditableMathlist.html#moveToNextPlaceholder_" class="methodName">moveToNextPlaceholder_</a></li><li data-type='method'><a href="EditableMathlist.html#moveToNextWord_" class="methodName">moveToNextWord_</a></li><li data-type='method'><a href="EditableMathlist.html#moveToOpposite_" class="methodName">moveToOpposite_</a></li><li data-type='method'><a href="EditableMathlist.html#moveToPreviousChar_" class="methodName">moveToPreviousChar_</a></li><li data-type='method'><a href="EditableMathlist.html#moveToPreviousPlaceholder_" class="methodName">moveToPreviousPlaceholder_</a></li><li data-type='method'><a href="EditableMathlist.html#moveToPreviousWord_" class="methodName">moveToPreviousWord_</a></li><li data-type='method'><a href="EditableMathlist.html#moveToSubscript_" class="methodName">moveToSubscript_</a></li><li data-type='method'><a href="EditableMathlist.html#moveToSuperscript_" class="methodName">moveToSuperscript_</a></li><li data-type='method'><a href="EditableMathlist.html#moveUp_" class="methodName">moveUp_</a></li><li data-type='method' class='private'><a href="EditableMathlist.html#next" class="methodName">next</a></li><li data-type='method'><a href="EditableMathlist.html#selectAll_" class="methodName">selectAll_</a></li><li data-type='method'><a href="EditableMathlist.html#selectGroup_" class="methodName">selectGroup_</a></li><li data-type='method' class='private'><a href="EditableMathlist.html#setExtent" class="methodName">setExtent</a></li><li data-type='method' class='private'><a href="EditableMathlist.html#setRange" class="methodName">setRange</a></li><li data-type='method' class='private'><a href="EditableMathlist.html#setSelection" class="methodName">setSelection</a></li><li data-type='method' class='private'><a href="EditableMathlist.html#sibling" class="methodName">sibling</a></li><li data-type='method' class='private'><a href="EditableMathlist.html#siblings" class="methodName">siblings</a></li><li data-type='method' class='private'><a href="EditableMathlist.html#skip" class="methodName">skip</a></li><li data-type='method'><a href="EditableMathlist.html#speakAll_" class="methodName">speakAll_</a></li><li data-type='method'><a href="EditableMathlist.html#speakAllWithSynchronizedHighlighting_" class="methodName">speakAllWithSynchronizedHighlighting_</a></li><li data-type='method'><a href="EditableMathlist.html#speakGroup_" class="methodName">speakGroup_</a></li><li data-type='method'><a href="EditableMathlist.html#speakLeftSibling_" class="methodName">speakLeftSibling_</a></li><li data-type='method'><a href="EditableMathlist.html#speakParent_" class="methodName">speakParent_</a></li><li data-type='method'><a href="EditableMathlist.html#speakRightSibling_" class="methodName">speakRightSibling_</a></li><li data-type='method'><a href="EditableMathlist.html#speakSelection_" class="methodName">speakSelection_</a></li><li data-type='method'><a href="EditableMathlist.html#speakSelectionWithSynchronizedHighlighting_" class="methodName">speakSelectionWithSynchronizedHighlighting_</a></li><li data-type='method' class='private'><a href="EditableMathlist.html#startOffset" class="methodName">startOffset</a></li><li data-type='method' class='private'><a href="EditableMathlist.html#toString" class="methodName">toString</a></li><li data-type='method'><a href="EditableMathlist.html#transpose_" class="methodName">transpose_</a></li></ul></li><li class="private"><a href="Lexer.html" class="className">Lexer</a><ul class='methods private'><li data-type='method' class='private'><a href="Lexer.html#end" class="methodName">end</a></li><li data-type='method' class='private'><a href="Lexer.html#get" class="methodName">get</a></li><li data-type='method' class='private'><a href="Lexer.html#isWhiteSpace" class="methodName">isWhiteSpace</a></li><li data-type='method' class='private'><a href="Lexer.html#makeToken" class="methodName">makeToken</a></li><li data-type='method' class='private'><a href="Lexer.html#peek" class="methodName">peek</a></li><li data-type='method' class='private'><a href="Lexer.html#scan" class="methodName">scan</a></li></ul></li><li class="private"><a href="MathAtom.html" class="className">MathAtom</a><ul class='methods private'><li data-type='method' class='private'><a href="MathAtom.html#.toSpeakableText" class="methodName">toSpeakableText</a></li><li data-type='method' class='private'><a href="MathAtom.html#bind" class="methodName">bind</a></li><li data-type='method' class='private'><a href="MathAtom.html#decompose" class="methodName">decompose</a></li><li data-type='method' class='private'><a href="MathAtom.html#decomposeGenfrac" class="methodName">decomposeGenfrac</a></li><li data-type='method' class='private'><a href="MathAtom.html#decomposeLeftright" class="methodName">decomposeLeftright</a></li><li data-type='method' class='private'><a href="MathAtom.html#decomposeLine" class="methodName">decomposeLine</a></li><li data-type='method' class='private'><a href="MathAtom.html#decomposeRule" class="methodName">decomposeRule</a></li><li data-type='method' class='private'><a href="MathAtom.html#filter" class="methodName">filter</a></li><li data-type='method' class='private'><a href="MathAtom.html#makeSpan" class="methodName">makeSpan</a></li></ul></li><li><a href="MathField.html" class="className">MathField</a><ul class='methods'><li data-type='method' class='private'><a href="MathField.html#_getCaretPosition" class="methodName">_getCaretPosition</a></li><li data-type='method' class='private'><a href="MathField.html#_onKeystroke" class="methodName">_onKeystroke</a></li><li data-type='method' class='private'><a href="MathField.html#complete_" class="methodName">complete_</a></li><li data-type='method'><a href="MathField.html#el" class="methodName">el</a></li><li data-type='method' class='private'><a href="MathField.html#enterCommandMode_" class="methodName">enterCommandMode_</a></li><li data-type='method'><a href="MathField.html#insert" class="methodName">insert</a></li><li data-type='method'><a href="MathField.html#keystroke" class="methodName">keystroke</a></li><li data-type='method'><a href="MathField.html#latex" class="methodName">latex</a></li><li data-type='method'><a href="MathField.html#perform" class="methodName">perform</a></li><li data-type='method'><a href="MathField.html#perform" class="methodName">perform</a></li><li data-type='method' class='private'><a href="MathField.html#render" class="methodName">render</a></li><li data-type='method'><a href="MathField.html#revertToOriginalContent" class="methodName">revertToOriginalContent</a></li><li data-type='method'><a href="MathField.html#selectedText" class="methodName">selectedText</a></li><li data-type='method'><a href="MathField.html#selectionAtEnd" class="methodName">selectionAtEnd</a></li><li data-type='method'><a href="MathField.html#selectionAtStart" class="methodName">selectionAtStart</a></li><li data-type='method'><a href="MathField.html#selectionDepth" class="methodName">selectionDepth</a></li><li data-type='method'><a href="MathField.html#selectionIsCollapsed" class="methodName">selectionIsCollapsed</a></li><li data-type='method'><a href="MathField.html#setConfig" class="methodName">setConfig</a></li><li data-type='method'><a href="MathField.html#text" class="methodName">text</a></li><li data-type='method'><a href="MathField.html#typedText" class="methodName">typedText</a></li></ul></li><li class="private"><a href="module-mathstyle.Mathstyle.html" class="className">Mathstyle</a></li><li class="private"><a href="Parser.html" class="className">Parser</a><ul class='methods private'><li data-type='method' class='private'><a href="Parser.html#end" class="methodName">end</a></li><li data-type='method' class='private'><a href="Parser.html#hasLiteral" class="methodName">hasLiteral</a></li><li data-type='method' class='private'><a href="Parser.html#hasLiteralPattern" class="methodName">hasLiteralPattern</a></li><li data-type='method' class='private'><a href="Parser.html#hasToken" class="methodName">hasToken</a></li><li data-type='method' class='private'><a href="Parser.html#lastMathAtom" class="methodName">lastMathAtom</a></li><li data-type='method' class='private'><a href="Parser.html#parseAtom" class="methodName">parseAtom</a></li><li data-type='method' class='private'><a href="Parser.html#parseKeyword" class="methodName">parseKeyword</a></li><li data-type='method' class='private'><a href="Parser.html#parseLimits" class="methodName">parseLimits</a></li><li data-type='method' class='private'><a href="Parser.html#parseSupSub" class="methodName">parseSupSub</a></li><li data-type='method' class='private'><a href="Parser.html#parseToken" class="methodName">parseToken</a></li><li data-type='method' class='private'><a href="Parser.html#scanArg" class="methodName">scanArg</a></li><li data-type='method' class='private'><a href="Parser.html#scanColor" class="methodName">scanColor</a></li><li data-type='method' class='private'><a href="Parser.html#scanDelim" class="methodName">scanDelim</a></li><li data-type='method' class='private'><a href="Parser.html#scanDimen" class="methodName">scanDimen</a></li><li data-type='method' class='private'><a href="Parser.html#scanEnvironment" class="methodName">scanEnvironment</a></li><li data-type='method' class='private'><a href="Parser.html#scanGroup" class="methodName">scanGroup</a></li><li data-type='method' class='private'><a href="Parser.html#scanImplicitGroup" class="methodName">scanImplicitGroup</a></li><li data-type='method' class='private'><a href="Parser.html#scanLeftRight" class="methodName">scanLeftRight</a></li><li data-type='method' class='private'><a href="Parser.html#scanModeSet" class="methodName">scanModeSet</a></li><li data-type='method' class='private'><a href="Parser.html#scanModeShift" class="methodName">scanModeShift</a></li><li data-type='method' class='private'><a href="Parser.html#scanNumber" class="methodName">scanNumber</a></li><li data-type='method' class='private'><a href="Parser.html#scanString" class="methodName">scanString</a></li><li data-type='method' class='private'><a href="Parser.html#scanToken" class="methodName">scanToken</a></li></ul></li><li class="private"><a href="Span.html" class="className">Span</a></li><li class="private"><a href="Token.html" class="className">Token</a></li><li class="private"><a href="UndoManager.html" class="className">UndoManager</a><ul class='methods private'><li data-type='method' class='private'><a href="UndoManager.html#canRedo" class="methodName">canRedo</a></li><li data-type='method' class='private'><a href="UndoManager.html#canUndo" class="methodName">canUndo</a></li><li data-type='method' class='private'><a href="UndoManager.html#redo" class="methodName">redo</a></li><li data-type='method' class='private'><a href="UndoManager.html#snapshot" class="methodName">snapshot</a></li><li data-type='method' class='private'><a href="UndoManager.html#undo" class="methodName">undo</a></li></ul></li></ul><h3 class="group-title">Modules</h3><ul><li class="private"><a href="module-color.html" class="className">color</a><ul class='methods private'><li data-type='method' class='private'><a href="module-color.html#.stringToColor" class="methodName">stringToColor</a></li></ul></li><li class="private"><a href="module-definitions.html" class="className">definitions</a><ul class='methods private'><li data-type='method' class='private'><a href="module-definitions.html#.defineEnvironment" class="methodName">defineEnvironment</a></li><li data-type='method' class='private'><a href="module-definitions.html#.defineFunction" class="methodName">defineFunction</a></li><li data-type='method' class='private'><a href="module-definitions.html#.defineSymbol" class="methodName">defineSymbol</a></li><li data-type='method' class='private'><a href="module-definitions.html#.defineSymbolRange" class="methodName">defineSymbolRange</a></li><li data-type='method' class='private'><a href="module-definitions.html#.defineSymbols" class="methodName">defineSymbols</a></li><li data-type='method' class='private'><a href="module-definitions.html#.frequency" class="methodName">frequency</a></li><li data-type='method' class='private'><a href="module-definitions.html#.getInfo" class="methodName">getInfo</a></li><li data-type='method' class='private'><a href="module-definitions.html#.matchCodepoint" class="methodName">matchCodepoint</a></li><li data-type='method' class='private'><a href="module-definitions.html#.matchFunction" class="methodName">matchFunction</a></li><li data-type='method' class='private'><a href="module-definitions.html#.parseParamTemplateArgument" class="methodName">parseParamTemplateArgument</a></li><li data-type='method' class='private'><a href="module-definitions.html#.suggest" class="methodName">suggest</a></li></ul></li><li class="private"><a href="module-delimiters.html" class="className">delimiters</a><ul class='methods private'><li data-type='method' class='private'><a href="module-delimiters.html#.makeCustomSizedDelim" class="methodName">makeCustomSizedDelim</a></li><li data-type='method' class='private'><a href="module-delimiters.html#.makeInner" class="methodName">makeInner</a></li><li data-type='method' class='private'><a href="module-delimiters.html#.makeLargeDelim" class="methodName">makeLargeDelim</a></li><li data-type='method' class='private'><a href="module-delimiters.html#.makeLeftRightDelim" class="methodName">makeLeftRightDelim</a></li><li data-type='method' class='private'><a href="module-delimiters.html#.makeNullFence" class="methodName">makeNullFence</a></li><li data-type='method' class='private'><a href="module-delimiters.html#.makeSizedDelim" class="methodName">makeSizedDelim</a></li><li data-type='method' class='private'><a href="module-delimiters.html#.makeSmallDelim" class="methodName">makeSmallDelim</a></li><li data-type='method' class='private'><a href="module-delimiters.html#.makeStackedDelim" class="methodName">makeStackedDelim</a></li><li data-type='method' class='private'><a href="module-delimiters.html#.traverseSequence" class="methodName">traverseSequence</a></li></ul></li><li class="private"><a href="module-editor_editableMathlist.html" class="className">editor/editableMathlist</a><ul class='methods private'><li data-type='method' class='private'><a href="module-editor_editableMathlist.html#~atomContains" class="methodName">atomContains</a></li></ul></li><li class="private"><a href="module-editor_keyboard.html" class="className">editor/keyboard</a><ul class='methods private'><li data-type='method' class='private'><a href="module-editor_keyboard.html#.delegateKeyboardEvents" class="methodName">delegateKeyboardEvents</a></li><li data-type='method' class='private'><a href="module-editor_keyboard.html#.keyboardEventToString" class="methodName">keyboardEventToString</a></li></ul></li><li class="private"><a href="module-editor_mathfield.html" class="className">editor/mathfield</a><ul class='methods private'><li data-type='method' class='private'><a href="module-editor_mathfield.html#nearestElementFromPoint" class="methodName">nearestElementFromPoint</a></li></ul></li><li class="private"><a href="module-editor_mathpath.html" class="className">editor/mathpath</a><ul class='methods private'><li data-type='method' class='private'><a href="module-editor_mathpath.html#.pathCommonAncestor" class="methodName">pathCommonAncestor</a></li><li data-type='method' class='private'><a href="module-editor_mathpath.html#.pathDistance" class="methodName">pathDistance</a></li><li data-type='method' class='private'><a href="module-editor_mathpath.html#.pathFromString" class="methodName">pathFromString</a></li><li data-type='method' class='private'><a href="module-editor_mathpath.html#.pathToString" class="methodName">pathToString</a></li></ul></li><li class="private"><a href="module-editor_shortcuts.html" class="className">editor/shortcuts</a><ul class='methods private'><li data-type='method' class='private'><a href="module-editor_shortcuts.html#.match" class="methodName">match</a></li><li data-type='method' class='private'><a href="module-editor_shortcuts.html#.matchKeystroke" class="methodName">matchKeystroke</a></li><li data-type='method' class='private'><a href="module-editor_shortcuts.html#.platform" class="methodName">platform</a></li><li data-type='method' class='private'><a href="module-editor_shortcuts.html#.stringify" class="methodName">stringify</a></li></ul></li><li class="private"><a href="module-fontMetrics.html" class="className">fontMetrics</a><ul class='methods private'><li data-type='method' class='private'><a href="module-fontMetrics.html#.getCharacterMetrics" class="methodName">getCharacterMetrics</a></li></ul></li><li class="private"><a href="module-lexer.html" class="className">lexer</a><ul class='methods private'><li data-type='method' class='private'><a href="module-lexer.html#.tokenize" class="methodName">tokenize</a></li></ul></li><li class="private"><a href="module-mathAtom.html" class="className">mathAtom</a><ul class='methods private'><li data-type='method' class='private'><a href="module-mathAtom.html#.decompose" class="methodName">decompose</a></li><li data-type='method' class='private'><a href="module-mathAtom.html#.getFontName" class="methodName">getFontName</a></li><li data-type='method' class='private'><a href="module-mathAtom.html#.makeColGap" class="methodName">makeColGap</a></li><li data-type='method' class='private'><a href="module-mathAtom.html#.makeColOfRepeatingElements" class="methodName">makeColOfRepeatingElements</a></li><li data-type='method' class='private'><a href="module-mathAtom.html#.makeStack" class="methodName">makeStack</a></li></ul></li><li><a href="module-mathlive.html" class="className">mathlive</a><ul class='methods'><li data-type='method'><a href="module-mathlive.html#latexToAST" class="methodName">latexToAST</a></li><li data-type='method'><a href="module-mathlive.html#latexToMarkup" class="methodName">latexToMarkup</a></li><li data-type='method'><a href="module-mathlive.html#latexToMathML" class="methodName">latexToMathML</a></li><li data-type='method'><a href="module-mathlive.html#latexToSpeakableText" class="methodName">latexToSpeakableText</a></li><li data-type='method'><a href="module-mathlive.html#makeMathField" class="methodName">makeMathField</a></li><li data-type='method'><a href="module-mathlive.html#pauseReadAloud" class="methodName">pauseReadAloud</a></li><li data-type='method'><a href="module-mathlive.html#playReadAloud" class="methodName">playReadAloud</a></li><li data-type='method'><a href="module-mathlive.html#readAloud" class="methodName">readAloud</a></li><li data-type='method'><a href="module-mathlive.html#readAloudStatus" class="methodName">readAloudStatus</a></li><li data-type='method'><a href="module-mathlive.html#renderMathInDocument" class="methodName">renderMathInDocument</a></li><li data-type='method'><a href="module-mathlive.html#renderMathInElement" class="methodName">renderMathInElement</a></li><li data-type='method'><a href="module-mathlive.html#resumeReadAloud" class="methodName">resumeReadAloud</a></li><li data-type='method'><a href="module-mathlive.html#revertToOriginalContent" class="methodName">revertToOriginalContent</a></li><li data-type='method'><a href="module-mathlive.html#revertToOriginalContent" class="methodName">revertToOriginalContent</a></li></ul></li><li class="private"><a href="module-mathstyle.html" class="className">mathstyle</a><ul class='methods private'><li data-type='method' class='private'><a href="module-mathstyle.html#.toMathstyle" class="methodName">toMathstyle</a></li></ul></li><li class="private"><a href="module-span.html" class="className">span</a><ul class='methods private'><li data-type='method' class='private'><a href="module-span.html#.coalesce" class="methodName">coalesce</a></li><li data-type='method' class='private'><a href="module-span.html#.makeFontSizer" class="methodName">makeFontSizer</a></li><li data-type='method' class='private'><a href="module-span.html#.makeHlist" class="methodName">makeHlist</a></li><li data-type='method' class='private'><a href="module-span.html#.makeSpan" class="methodName">makeSpan</a></li><li data-type='method' class='private'><a href="module-span.html#.makeSpanOfType" class="methodName">makeSpanOfType</a></li><li data-type='method' class='private'><a href="module-span.html#.makeSymbol" class="methodName">makeSymbol</a></li><li data-type='method' class='private'><a href="module-span.html#.makeVlist" class="methodName">makeVlist</a></li><li data-type='method' class='private'><a href="module-span.html#.toString" class="methodName">toString</a></li></ul></li></ul><label class="checkbox"><input id="toggle-private" type="checkbox" onclick="
if (!document.getElementById('toggle-private').checked) {
document.documentElement.classList.add('no-private')
writeCookie('symbol-access', 'no-private')
} else {
document.documentElement.classList.remove('no-private')
writeCookie('symbol-access', 'private')
}
">Include Private Symbols</input></label></div>
<footer role="contentInfo">
Made with <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>.
</footer>
</nav>
</section>
<main id="main">
<h1 class="page-title">editor/editor-mathfield.js</h1>
<section>
<article>
<pre class="prettyprint source linenums">
<code>
/**
* See {@linkcode MathField}
* @module editor/mathfield
* @private
*/
define([
'mathlive/core/definitions',
'mathlive/core/mathAtom',
'mathlive/core/lexer',
'mathlive/core/parser',
'mathlive/core/span',
'mathlive/editor/editor-editableMathlist',
'mathlive/editor/editor-mathpath',
'mathlive/editor/editor-keyboard',
'mathlive/editor/editor-undo',
'mathlive/editor/editor-shortcuts',
'mathlive/editor/editor-popover',
'mathlive/editor/editor-virtualKeyboard',
'mathlive/core/grapheme-splitter',
'mathlive/addons/outputLatex',
'mathlive/addons/outputMathML',
'mathlive/addons/maston',
'mathlive/addons/outputSpokenText'],
function(Definitions, MathAtom, Lexer, ParserModule, Span,
EditableMathlist, MathPath, Keyboard, Undo, Shortcuts, Popover,
VirtualKeyboard, GraphemeSplitter,
// eslint-disable-next-line no-unused-vars
OutputLatex, OutputMathML, MASTON, OutputSpokenText) {
/*
Note:
The OutputLatex, OutputMathML, MASTON and OutputSpokenText modules are required,
even though they are not referenced directly.
They modify the MathAtom class, adding toLatex(), toMathML() and
toSpeakableText() respectively.
*/
const HAPTIC_FEEDBACK_DURATION = 3; // in ms
const AUDIO_FEEDBACK_VOLUME = 0.5; // from 0.0 to 1.0
function on(el, selectors, listener, options) {
selectors = selectors.split(' ');
for (const sel of selectors) {
el.addEventListener(sel, listener, options);
}
}
function off(el, selectors, listener, options) {
selectors = selectors.split(' ');
for (const sel of selectors) {
el.removeEventListener(sel, listener, options);
}
}
/**
* **Note**
* - Method names that _begin with_ an underbar `_` are private and meant
* to be used only by the implementation of the class.
* - Method names that _end with_ an underbar `_` are selectors. They can
* be invoked by calling the `perform()` function of a `MathField` object. Note
* that the selector name does not include the underbar.
*
* For example:
* ```
* mf.perform('selectAll');
* ```
*
* @param {Element} element
* @param {Object} config - See [`MathLive.makeMathField()`]{@link MathLive#makeMathField} for details
* @property {Element} element - The DOM element this mathfield is attached to.
* @property {Object} config - A key/value/pair object that includes options
* customizing the behavior of the mathfield
* @property {string} id - A unique ID identifying this mathfield
* @property {boolean} keystrokeCaptionVisible - True if the keystroke caption
* panel is visible
* @class
* @global
*/
function MathField(element, config) {
// Setup default config options
this.setConfig(config || {});
this.element = element;
// Save existing content
this.originalContent = element.innerHTML;
let elementText = this.element.textContent;
if (elementText) elementText = elementText.trim();
// Additional elements used for UI.
// They are retrieved in order a bit later, so they need to be kept in sync
// 1.0/ The field, where the math equation will be displayed
// 1.1/ The widget to activate the command bar
// 2/ The popover panel which displays info in command mode
// 3/ The keystroke caption panel (option+shift+K)
// 4/ The virtual keyboard
// 5.0/ The area to stick MathML for screen reading larger exprs (not used right now)
// The for the area is that focus would bounce their and then back triggering the
// screen reader to read it
// 5.1/ The aria-live region for announcements
let markup = ''
if (!this.config.substituteTextArea) {
if (/android|ipad|ipod|iphone/i.test(navigator.userAgent)) {
// On Android or iOS, don't use a textarea, which has the side effect of
// bringing up the OS virtual keyboard
markup += `<span class='ML__textarea'>
<span class='ML__textarea--textarea'
tabindex="0" role="textbox"
style='display:inline-block;height:1px;width:1px' >
</span>
</span>`;
} else {
markup += '<span class="ML__textarea">' +
'<textarea class="ML__textarea--textarea" autocapitalize="off" autocomplete="off" ' +
'autocorrect="off" spellcheck="false" aria-hidden="true" tabindex="-1">' +
'</textarea>' +
'</span>';
}
} else {
if (typeof this.config.substituteTextArea === 'string') {
markup += this.config.substituteTextArea;
} else {
// We don't really need this one, but we keep it here so that the
// indexes below remain the same whether a substituteTextArea is
// provided or not.
markup += '<span></span>';
}
}
markup += '<span class="ML__fieldcontainer">' +
'<span class="ML__fieldcontainer--field"></span>';
// Only display the virtual keyboard toggle if the virtual keyboard mode is
// 'manual'
if (this.config.virtualKeyboardMode === 'manual') {
markup += `<button class="ML__virtualKeyboardToggle" data-tooltip="Toggle Virtual Keyboard">`;
// data-tooltip='Toggle Virtual Keyboard'
if (this.config.virtualKeyboardToggleGlyph) {
markup += this.config.virtualKeyboardToggleGlyph;
} else {
markup += `<span style="width: 21px; margin-top: 5px;"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M528 64H48C21.49 64 0 85.49 0 112v288c0 26.51 21.49 48 48 48h480c26.51 0 48-21.49 48-48V112c0-26.51-21.49-48-48-48zm16 336c0 8.823-7.177 16-16 16H48c-8.823 0-16-7.177-16-16V112c0-8.823 7.177-16 16-16h480c8.823 0 16 7.177 16 16v288zM168 268v-24c0-6.627-5.373-12-12-12h-24c-6.627 0-12 5.373-12 12v24c0 6.627 5.373 12 12 12h24c6.627 0 12-5.373 12-12zm96 0v-24c0-6.627-5.373-12-12-12h-24c-6.627 0-12 5.373-12 12v24c0 6.627 5.373 12 12 12h24c6.627 0 12-5.373 12-12zm96 0v-24c0-6.627-5.373-12-12-12h-24c-6.627 0-12 5.373-12 12v24c0 6.627 5.373 12 12 12h24c6.627 0 12-5.373 12-12zm96 0v-24c0-6.627-5.373-12-12-12h-24c-6.627 0-12 5.373-12 12v24c0 6.627 5.373 12 12 12h24c6.627 0 12-5.373 12-12zm-336 80v-24c0-6.627-5.373-12-12-12H84c-6.627 0-12 5.373-12 12v24c0 6.627 5.373 12 12 12h24c6.627 0 12-5.373 12-12zm384 0v-24c0-6.627-5.373-12-12-12h-24c-6.627 0-12 5.373-12 12v24c0 6.627 5.373 12 12 12h24c6.627 0 12-5.373 12-12zM120 188v-24c0-6.627-5.373-12-12-12H84c-6.627 0-12 5.373-12 12v24c0 6.627 5.373 12 12 12h24c6.627 0 12-5.373 12-12zm96 0v-24c0-6.627-5.373-12-12-12h-24c-6.627 0-12 5.373-12 12v24c0 6.627 5.373 12 12 12h24c6.627 0 12-5.373 12-12zm96 0v-24c0-6.627-5.373-12-12-12h-24c-6.627 0-12 5.373-12 12v24c0 6.627 5.373 12 12 12h24c6.627 0 12-5.373 12-12zm96 0v-24c0-6.627-5.373-12-12-12h-24c-6.627 0-12 5.373-12 12v24c0 6.627 5.373 12 12 12h24c6.627 0 12-5.373 12-12zm96 0v-24c0-6.627-5.373-12-12-12h-24c-6.627 0-12 5.373-12 12v24c0 6.627 5.373 12 12 12h24c6.627 0 12-5.373 12-12zm-96 152v-8c0-6.627-5.373-12-12-12H180c-6.627 0-12 5.373-12 12v8c0 6.627 5.373 12 12 12h216c6.627 0 12-5.373 12-12z"/></svg></span>`;
}
markup += '</button>';
} else {
markup += '<span ></span>';
}
markup += '</span>';
markup += `
<div class="ML__popover" aria-hidden="true"></div>
<div class="ML__keystrokecaption" aria-hidden="true"></div>
<div class="ML__HiddenAccessibleMath">
<span aria-live="assertive" aria-atomic="true"></span>
<span></span>
</div>
`;
this.element.innerHTML = markup;
let iChild = 0; // index of child -- used to make changes below easier
if (typeof this.config.substituteTextArea === 'function') {
this.textarea = this.config.substituteTextArea();
} else {
this.textarea = this.element.children[iChild++].firstElementChild;
}
this.field = this.element.children[iChild].children[0];
this.virtualKeyboardToggleDOMNode = this.element.children[iChild++].children[1];
this._attachButtonHandlers(this.virtualKeyboardToggleDOMNode,
{
default: 'toggleVirtualKeyboard',
alt: 'toggleVirtualKeyboardAlt',
shift: 'toggleVirtualKeyboardShift'
}
);
this.popover = this.element.children[iChild++];
this.keystrokeCaption = this.element.children[iChild++];
this.ariaLiveText = this.element.children[iChild].children[0];
this.accessibleNode = this.element.children[iChild++].children[1];
// The keystroke caption panel and the command bar are
// initially hidden
this.keystrokeCaptionVisible = false;
this.virtualKeyboardVisible = false;
// This index indicates which of the suggestions available to
// display in the popover panel
this.suggestionIndex = 0;
// Focus/blur state
this.blurred = true;
on(window, 'focus', this._onFocus.bind(this));
on(window, 'blur', this._onBlur.bind(this));
on(this.element, 'focus', this._onFocus.bind(this));
on(this.element, 'blur', this._onBlur.bind(this));
// Capture clipboard events
on(this.textarea, 'cut', this._onCut.bind(this));
on(this.textarea, 'copy', this._onCopy.bind(this));
on(this.textarea, 'paste', this._onPaste.bind(this));
// Delegate keyboard events
Keyboard.delegateKeyboardEvents(this.textarea, {
container: this.element,
typedText: this._onTypedText.bind(this),
paste: this._onPaste.bind(this),
keystroke: this._onKeystroke.bind(this),
focus: this._onFocus.bind(this),
blur: this._onBlur.bind(this),
})
// Delegate mouse and touch events
on(this.element, 'touchstart mousedown', this._onPointerDown.bind(this),
{passive: false, capture: false});
// Request notification for when the window is resized (
// or the device switched from portrait to landscape) to adjust
// the UI (popover, etc...)
on(window, 'resize', this._onResize.bind(this));
// Override some handlers in the config
const localConfig = Object.assign({}, config);
localConfig.onSelectionDidChange =
MathField.prototype._onSelectionDidChange.bind(this);
localConfig.onSelectionWillChange =
MathField.prototype._onSelectionWillChange.bind(this);
localConfig.onContentWillChange =
MathField.prototype._onContentWillChange.bind(this);
localConfig.onContentDidChange =
MathField.prototype._onContentDidChange.bind(this);
localConfig.smartFence = this.config.smartFence;
localConfig.macros = this.config.macros;
this.mathlist = new EditableMathlist.EditableMathlist(localConfig, this._announce.bind(this));
// Prepare to manage undo/redo
this.undoManager = new Undo.UndoManager(this.mathlist);
// If there was some content in the element, use it for the initial
// value of the mathfield
if (elementText.length > 0) {
this.latex(elementText);
}
// If fonts get loaded (which could happen as a result of the first pass
// rendering done in .latex()), render again.
if (document && document.fonts) {
const that = this;
document.fonts.ready.then(() => that._render());
}
}
/**
* Revert this math field to its original content. After this method has been
* called, no other methods can be called on the MathField object. To turn the
* element back into a MathField, call `MathLive.makeMathField()` on the
* element again to get a new math field object.
*
* @method MathField#revertToOriginalContent
*/
MathField.prototype.revertToOriginalContent = function() {
this.element.innerHTML = this.originalContent;
delete this.accessibleNode;
delete this.ariaLiveText;
delete this.field;
this.textarea.remove();
delete this.textarea;
this.virtualKeyboardToggleDOMNode.remove()
delete this.virtualKeyboardToggleDOMNode;
this.popover.remove();
delete this.popover;
delete this.keystrokeCaption;
// this.virtualKeyboard.remove();
delete this.virtualKeyboard;
off(this.element, 'touchstart mousedown', this._onPointerDown.bind(this));
off(window, 'resize', this._onResize.bind(this));
}
/**
* Utility function that returns the element which has the caret
*
* @param {DomElement} el
* @private
*/
function _findElementWithCaret(el) {
if (el.classList.contains('ML__caret')) {
return el;
}
let result;
Array.from(el.children).forEach(function(child) {
result = result || _findElementWithCaret(child);
});
return result;
}
/**
* Return the (x,y) client coordinates of the caret
*
* @method MathField#_getCaretPosition
* @private
*/
MathField.prototype._getCaretPosition = function() {
const caret = _findElementWithCaret(this.field);
if (caret) {
const bounds = caret.getBoundingClientRect();
return {
x: bounds.right + window.scrollX,
y: bounds.bottom + window.scrollY };
}
return null;
}
/**
* Return a tuple of an element and a distance from point (x, y)
* @param {Element} el
* @param {number} x
* @param {number} y
* @function module:editor/mathfield#nearestElementFromPoint
* @private
*/
function nearestElementFromPoint(el, x, y) {
let result = { element: null };
let considerChildren = true;
if (!el.getAttribute('data-atom-id')) {
// This element may not have a matching atom, but its children might
result.distance = Number.POSITIVE_INFINITY;
} else {
result.element = el;
// Calculate the (square of the ) distance to the rectangle
const r = el.getBoundingClientRect();
const dx = Math.max(r.left - x, 0, x - r.right);
const dy = Math.max(r.top - y, 0, y - r.bottom);
result.distance = dx * dx + dy * dy;
// Only consider children if the target is inside the (horizontal) bounds of
// of the element.
// This avoid searching the numerator/denominator when a fraction
// is the last element in the formula.
considerChildren = x >= r.left && x <= r.right;
}
if (considerChildren && el.children) {
Array.from(el.children).forEach(function(child) {
const nearest = nearestElementFromPoint(child, x, y);
if (nearest.element && nearest.distance <= result.distance) {
result = nearest;
}
});
}
return result;
}
MathField.prototype._pathFromPoint = function(x, y) {
let result;
// Try to find the deepest element that is near the point that was
// clicked on (the point could be outside of the element)
const nearest = nearestElementFromPoint(this.field, x, y);
const el = nearest.element;
const id = el ? el.getAttribute('data-atom-id') : null;
if (id) {
// Let's find the atom that has a matching ID with the element that
// was clicked on (or near)
const atoms = this.mathlist.filter(function(path, atom) {
// If the atom allows children to be selected, match only if
// the ID of the atom matches the one we're looking for.
if (!atom.captureSelection) {
return atom.id === id;
}
// If the atom does not allow children to be selected
// (captureSelection === true), the element matches if any of
// its children has an ID that matches.
return atom.filter(function(childAtom) {
return childAtom.id === id;
}).length > 0;
});
if (atoms && atoms.length > 0) {
// (There should be exactly one atom that matches this ID...)
// Set the result to the path to this atom
// If the point clicked is to the left of the vertical midline,
// adjust the path to *before* the atom (i.e. after the
// preceding atom)
const bounds = el.getBoundingClientRect();
result = MathPath.pathFromString(atoms[0]).path;
if (x < bounds.left + bounds.width / 2 && !el.classList.contains('ML__placeholder')) {
result[result.length - 1].offset =
Math.max(0, result[result.length - 1].offset - 1);
}
}
}
return result;
}
let lastTouchEndTouch;
let lastTouchEndTimestamp;
let tapCount = 0;
MathField.prototype._onPointerDown = function(evt) {
let anchor;
function endPointerTracking(evt) {
off(that.field, 'touchmove', onPointerMove);
off(that.field, 'touchend touchleave', endPointerTracking);
off(window, 'mousemove', onPointerMove);
off(window, 'mouseup blur', endPointerTracking);
trackingPointer = false;
evt.preventDefault();
evt.stopPropagation();
}
function onPointerMove(moveEvt) {
const x = moveEvt.touches ? moveEvt.touches[0].clientX : moveEvt.clientX;
const y = moveEvt.touches ? moveEvt.touches[0].clientY : moveEvt.clientY;
const focus = that._pathFromPoint(x, y);
if (anchor && focus) {
if (that.mathlist.setRange(anchor, focus)) {
// Re-render if the range has actually changed
setTimeout(that._render.bind(that), 0);
}
}
// Prevent synthetic mouseMove event when this is a touch event
moveEvt.preventDefault();
moveEvt.stopPropagation();
}
const that = this;
let trackingPointer = false;
let dirty = false;
// Focus the math field
if (!this.hasFocus()) {
dirty = true;
if (this.textarea.focus) this.textarea.focus();
}
// Calculate the tap count (if this is a touch event)
if (evt.touches) {
if (lastTouchEndTouch && Math.abs(lastTouchEndTouch.pageX - evt.touches[0].pageX) < 5 &&
Math.abs(lastTouchEndTouch.pageY - evt.touches[0].pageY) < 5 &&
Date.now() < lastTouchEndTimestamp + 500) {
tapCount += 1;
} else {
lastTouchEndTouch = evt.touches[0];
tapCount = 1;
}
lastTouchEndTimestamp = Date.now();
}
const bounds = this.element.getBoundingClientRect();
const x = evt.touches ? evt.touches[0].clientX : evt.clientX;
const y = evt.touches ? evt.touches[0].clientY : evt.clientY;
if (x > bounds.left && x < bounds.right