itutor-mathlive
Version:
Beautifully typeset math made easy
661 lines (559 loc) • 122 kB
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"><title>editor/editor-editableMathlist.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-editableMathlist.js</h1>
<section>
<article>
<pre class="prettyprint source linenums">
<code>/**
* This module contains the definition of a data structure representing a list
* of math atoms that can be edited. It is an in-memory representation of a
* mathematical expression whose elements, math atoms, can be removed,
* inserted or re-arranged. In addition, the data structure keeps track
* of a selection, which can be either an insertion point — the selection is
* then said to be _collapsed_ — or a range of atoms.
*
* See {@linkcode EditableMathlist}
*
* @module editor/editableMathlist
* @private
*/
define([
'mathlive/core/definitions',
'mathlive/core/mathAtom',
'mathlive/core/lexer',
'mathlive/core/parser',
'mathlive/editor/editor-mathpath'],
function(Definitions, MathAtom, Lexer, ParserModule, MathPath) {
/**
*
* **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.
* They will be dispatched to an instance of `MathEditableList` as necessary.
* Note that the selector name does not include the underbar.
*
* For example:
* ```
* mf.perform('selectAll');
* ```
*
* @param {Object} config
* @param {function} announce - A callback invoked when there is some spoken
* feedback available.
* @property {Array.<MathAtom>} root - The root element of the math expression.
* @property {Array.<Object>} path - The path to the element that is the
* anchor for the selection.
* @property {number} extent - Number of atoms in the selection. `0` if the
* selection is collapsed.
* @property {Object} config
* @property {boolean} suppressSelectionChangeNotifications - If true,
* the handlers for notification change won't be called. @todo This is an
* inelegant solution to deal with iterating the expression, which has the
* side effect of temporarily changing the path. We should have an iterator
* that doesn't change the path instead.
* @class
* @global
* @memberof module:editor/editableMathlist
*/
function EditableMathlist(config, announce) {
this.root = MathAtom.makeRoot();
this.path = [{relation: 'body', offset: 0}];
this.extent = 0;
this.config = Object.assign({}, config);
this.announce = announce;
this.contentIsChanging = false;
this.suppressSelectionChangeNotifications = false;
}
function clone(mathlist) {
const result = Object.assign(new EditableMathlist(mathlist.config), mathlist);
result.path = MathPath.clone(mathlist.path);
return result;
}
EditableMathlist.prototype._announce = function(command, mathlist, atoms) {
if (typeof this.announce === 'function') {
this.announce(command, mathlist, atoms);
}
}
/**
* Iterate over each atom in the expression, starting with the focus.
*
* Return an array of all the paths for which the callback predicate
* returned true.
*
* @param {function} cb - A predicate being passed a path and the atom at this
* path. Return true to include the designated atom in the result.
* @param {number} dir - `+1` to iterate forward, `-1` to iterate backward.
* @return {MathAtom[]} The atoms for which the predicate is true
* @method EditableMathlist#filter
* @private
*/
EditableMathlist.prototype.filter = function(cb, dir) {
const suppressed = this.suppressSelectionChangeNotifications;
this.suppressSelectionChangeNotifications = true;
dir = dir < 0 ? -1 : +1;
const result = [];
const originalExtent = this.extent;
if (dir >= 0) {
this.collapseForward();
} else {
this.collapseBackward();
}
const initialPath = MathPath.pathToString(this.path);
do {
console.assert(this.anchor(), MathPath.pathToString(this.path));
if (cb.bind(this)(this.path, this.anchor())) {
result.push(this.toString());
}
if (dir >= 0) {
this.next({iterateAll: true});
} else {
this.previous({iterateAll: true});
}
} while (initialPath !== MathPath.pathToString(this.path));
this.extent = originalExtent;
this.suppressSelectionChangeNotifications = suppressed;
return result;
}
/**
* Return a string representation of the selection.
* @todo This is a bad name for this function, since it doesn't return
* a representation of the content, which one might expect...
*
* @return {string}
* @method EditableMathlist#toString
* @private
*/
EditableMathlist.prototype.toString = function() {
return MathPath.pathToString(this.path, this.extent);
}
/**
* When changing the selection, if the former selection is an empty list,
* insert a placeholder if necessary. For example, if in an empty numerator.
*/
EditableMathlist.prototype.adjustPlaceholder = function() {
// Should we insert a placeholder?
// Check if we're an empty list that is the child of a fraction
const siblings = this.siblings();
if (siblings && siblings.length <= 1) {
let placeholder;
const relation = this.relation();
if (relation === 'numer') {
placeholder = 'numerator';
} else if (relation === 'denom') {
placeholder = 'denominator';
} else if (this.parent().type === 'surd' && relation === 'body') {
// Surd (roots)
placeholder = 'radicand';
} else if (this.parent().type === 'overunder' && relation === 'body') {
placeholder = 'base';
} else if (relation === 'underscript' || relation === 'overscript') {
placeholder = 'annotation';
}
if (placeholder) {
// ◌ ⬚
const placeholderAtom = [new MathAtom.MathAtom('math', 'placeholder', '⬚')];
Array.prototype.splice.apply(siblings, [1, 0].concat(placeholderAtom));
}
}
}
EditableMathlist.prototype.selectionWillChange = function() {
if (!this.suppressSelectionChangeNotifications) {
if (this.config.onSelectionWillChange) this.config.onSelectionWillChange();
}
}
EditableMathlist.prototype.selectionDidChange = function() {
if (!this.suppressSelectionChangeNotifications) {
if (this.config.onSelectionDidChange) this.config.onSelectionDidChange();
}
}
/**
*
* @param {*} selection
* @param {number} extent the length of the selection
* @return {boolean} true if the path has actually changed
*/
EditableMathlist.prototype.setPath = function(selection, extent) {
// Convert to a path array if necessary
if (typeof selection === 'string') {
selection = MathPath.pathFromString(selection);
} else if (Array.isArray(selection)) {
// need to temporarily change the path of this to use 'sibling()'
const newPath = MathPath.clone(selection);
const oldPath = this.path;
this.path = newPath;
if (extent === 0 && this.anchor().type === 'placeholder') {
extent = 1; // select the placeholder
}
selection = {
path: newPath,
extent: extent || 0
};
this.path = oldPath;
}
const pathChanged = MathPath.pathDistance(this.path, selection.path) !== 0;
const extentChanged = selection.extent !== this.extent;
if (pathChanged || extentChanged) {
if (pathChanged) {
this.adjustPlaceholder();
}
this.selectionWillChange();
this.path = MathPath.clone(selection.path);
console.assert(this.siblings().length >= this.anchorOffset());
this.setExtent(selection.extent);
this.selectionDidChange();
}
return pathChanged || extentChanged;
}
/**
* Extend the selection between `from` and `to` nodes
*
* @param {string[]} from
* @param {string[]} to
* @method EditableMathlist#setRange
* @return {boolean} true if the range was actually changed
* @private
*/
EditableMathlist.prototype.setRange = function(from, to) {
// Measure the 'distance' between `from` and `to`
const distance = MathPath.pathDistance(from, to);
if (distance === 0) {
// `from` and `to` are equal.
// Set the path to a collapsed insertion point
return this.setPath(from, 0);
}
if (distance === 1) {
// They're siblings, set an extent
const extent = to[to.length - 1].offset - from[from.length - 1].offset;
const path = MathPath.clone(from);
path[path.length - 1] = {
relation : path[path.length - 1].relation,
offset : path[path.length - 1].offset + 1,
}
return this.setPath(path, extent);
}
// They're neither identical, not siblings.
// Find the common ancestor between the nodes
let commonAncestor = MathPath.pathCommonAncestor(from, to);
const ancestorDepth = commonAncestor.length;
if (from.length === ancestorDepth || to.length === ancestorDepth ||
from[ancestorDepth].relation !== to[ancestorDepth].relation) {
return this.setPath(commonAncestor, 1);
}
commonAncestor.push(from[ancestorDepth]);
commonAncestor = MathPath.clone(commonAncestor);
let extent = to[ancestorDepth].offset - from[ancestorDepth].offset;
if (extent <= 0) {
if (to.length > ancestorDepth + 1) {
commonAncestor[ancestorDepth].relation = to[ancestorDepth].relation;
commonAncestor[ancestorDepth].offset = to[ancestorDepth].offset;
extent = -extent;
} else {
commonAncestor[ancestorDepth].relation = to[ancestorDepth].relation;
commonAncestor[ancestorDepth].offset = to[ancestorDepth].offset + 1;
extent = -extent - 1;
}
} else if (to.length > from.length) {
commonAncestor = MathPath.clone(commonAncestor);
commonAncestor[commonAncestor.length - 1].offset += 1;
extent -= 1;
}
return this.setPath(commonAncestor, extent + 1);
}
/**
* Convert am array row/col into an array index.
* @param {MathAtom} atom
* @param {*} rowCol
* @return {number}
*/
function arrayIndex(atom, rowCol) {
let result = 0;
if (Array.isArray(atom.array)) {
for (let i = 0; i < rowCol.row; i++) {
for (let j = 0; j < atom.array[i].length; j++) {
result += 1;
}
}
result += rowCol.col;
}
return result;
}
/**
* Convert an array index (scalar) to an array row/col.
* @param {MathAtom} atom
* @param {number} index
*/
function arrayColRow(atom, index) {
const result = {row: 0, col: 0};
while (index > 0) {
result.col += 1;
if (!atom.array[result.row] || result.col >= atom.array[result.row].length) {
result.col = 0;
result.row += 1;
}
index -= 1;
}
return result;
}
/**
* Return the array cell corresponding to colrow or null (for example in
* a sparse array)
*
* @param {MathAtom} atom
* @param {*} colrow
*/
function arrayCell(atom, colrow) {
let result;
if (Array.isArray(atom.array)) {
if (typeof colrow === 'number') colrow = arrayColRow(atom, colrow);
if (Array.isArray(atom.array[colrow.row])) {
result = atom.array[colrow.row][colrow.col] || null;
}
}
return result;
}
/**
* Total numbers of cells (include sparse cells) in the array.
* @param {MathAtom} atom
*/
function arrayCellCount(atom) {
let result = 0;
if (Array.isArray(atom.array)) {
let numRows = 0;
let numCols = 1;
for (const row of atom.array) {
numRows += 1;
if (row.length > numCols) numCols = row.length;
}
result = numRows * numCols;
}
return result;
}
/**
* @param {number} ancestor distance from self to ancestor.
* - `ancestor` = 0: self
* - `ancestor` = 1: parent
* - `ancestor` = 2: grand-parent
* - etc...
* @return {MathAtom}
* @method EditableMathlist#ancestor
* @private
*/
EditableMathlist.prototype.ancestor = function(ancestor) {
// If the requested ancestor goes beyond what's available,
// return null
if (ancestor > this.path.length) return null;
// Start with the root
let result = this.root;
// Iterate over the path segments, selecting the appropriate
for (let i = 0; i < (this.path.length - ancestor); i++) {
const segment = this.path[i];
if (segment.relation.startsWith('cell')) {
const cellIndex = parseInt(segment.relation.match(/cell([0-9]*)$/)[1]);
result = arrayCell(result, cellIndex)[segment.offset];
} else if (!result[segment.relation]) {
// There is no such relation... (the path got out of sync with the tree)
return null;
} else {
// Make sure the 'first' atom has been inserted, otherwise
// the segment.offset might be invalid
if (result[segment.relation].length === 0 || result[segment.relation][0].type !== 'first') {
const firstAtom = new MathAtom.MathAtom(result.parseMode, 'first', null);
result[segment.relation].unshift(firstAtom);
}
const offset = Math.min(segment.offset, result[segment.relation].length - 1);
result = result[segment.relation][offset];
}
}
return result;
}
/**
* The atom where the selection starts. When the selection is extended
* the anchor remains fixed. The anchor could be either before or
* after the focus.
*
* @method EditableMathlist#anchor
* @private
*/
EditableMathlist.prototype.anchor = function() {
if (this.relation().startsWith('cell')) {
const cellIndex = parseInt(this.relation().match(/cell([0-9]*)$/)[1]);
return arrayCell(this.parent(), cellIndex)[this.anchorOffset()];
}
return this.siblings()[this.anchorOffset()];
}
EditableMathlist.prototype.parent = function() {
return this.ancestor(1);
}
EditableMathlist.prototype.relation = function() {
return this.path.length > 0 ? this.path[this.path.length - 1].relation : '';
}
EditableMathlist.prototype.anchorOffset = function() {
return this.path.length > 0 ? this.path[this.path.length - 1].offset : 0;
}
EditableMathlist.prototype.focusOffset = function() {
return this.path.length > 0 ?
this.path[this.path.length - 1].offset + this.extent : 0;
}
/**
* Offset of the first atom included in the selection
* i.e. `=1` => selection starts with and includes first atom
* With expression _x=_ and atoms :
* - 0: _<first>_
* - 1: _x_
* - 2: _=_
*
* - if caret is before _x_: `start` = 0, `end` = 0
* - if caret is after _x_: `start` = 1, `end` = 1
* - if _x_ is selected: `start` = 1, `end` = 2
* - if _x=_ is selected: `start` = 1, `end` = 3
* @method EditableMathlist#startOffset
* @private
*/
EditableMathlist.prototype.startOffset = function() {
return Math.min(this.path[this.path.length - 1].offset,
this.path[this.path.length - 1].offset + this.extent);
}
/**
* Offset of the first atom not included in the selection
* i.e. max value of `siblings.length`
* `endOffset - startOffset = extent`
* @method EditableMathlist#endOffset
* @private
*/
EditableMathlist.prototype.endOffset = function() {
return Math.max(this.path[this.path.length - 1].offset,
this.path[this.path.length - 1].offset + this.extent);
}
/**
* If necessary, insert a `first` atom in the sibling list.
* If there's already a `first` atom, do nothing.
* The `first` atom is used as a 'placeholder' to hold the blinking caret when
* the caret is positioned at the very beginning of the mathlist.
* @method EditableMathlist#insertFirstAtom
* @private
*/
EditableMathlist.prototype.insertFirstAtom = function() {
this.siblings();
}
/**
* @return {MathAtom[]} array of children of the parent
* @method EditableMathlist#siblings
* @private
*/
EditableMathlist.prototype.siblings = function() {
if (this.path.length === 0) return [];
let siblings;
if (this.relation().startsWith('cell')) {
const cellIndex = parseInt(this.relation().match(/cell([0-9]*)$/)[1]);
siblings = arrayCell(this.parent(), cellIndex);
} else {
siblings = this.parent()[this.relation()] || [];
if (typeof siblings === 'string') siblings = [];
}
// If the 'first' math atom is missing, insert it
if (siblings.length === 0 || siblings[0].type !== 'first') {
const firstAtom = new MathAtom.MathAtom(this.parent().parseMode, 'first', null);
siblings.unshift(firstAtom);
}
return siblings;
}
/**
* Sibling, relative to `anchor`
* `sibling(0)` = start of selection
* `sibling(-1)` = sibling immediately left of start offset
* @return {MathAtom}
* @method EditableMathlist#sibling
* @private
*/
EditableMathlist.prototype.sibling = function(offset) {
const siblingOffset = this.startOffset() + offset;
const siblings = this.siblings();
if (siblingOffset < 0 || siblingOffset > siblings.length) return null;
return siblings[siblingOffset]
}
/**
* @return {boolean} True if the selection is an insertion point.
* @method EditableMathlist#isCollapsed
*/
EditableMathlist.prototype.isCollapsed = function() {
return this.extent === 0;
}
/**
* @param {number} extent
* @method EditableMathlist#setExtent
* @private
*/
EditableMathlist.prototype.setExtent = function(extent) {
// const anchorOffset = this.anchorOffset();
// extent = Math.max(-anchorOffset,
// Math.min(extent, this.siblings().length - anchorOffset));
this.extent = extent;
}
EditableMathlist.prototype.collapseForward = function() {
if (this.isCollapsed()) return false;
// this.setSelection(
// Math.max(this.anchorOffset() - 2, this.focusOffset() - 2));
this.setSelection(
Math.max(this.anchorOffset(), this.focusOffset()) - 1);
return true;
}
EditableMathlist.prototype.collapseBackward = function() {
if (this.isCollapsed()) return false;
this.setSelection(
Math.min(this.anchorOffset(), this.focusOffset()));
return true;
}
/**
* Select all the atoms in the current group, that is all the siblings.
* When the selection is in a numerator, the group is the numerator. When
* the selection is a superscript or subscript, the group is the supsub.
* @method EditableMathlist#selectGroup_
*/
EditableMathlist.prototype.selectGroup_ = function() {
this.setSelection(1, 'end');
}
/**
* Select all the atoms in the math field.
* @method EditableMathlist#selectAll_
*/
EditableMathli