itutor-mathlive
Version:
Beautifully typeset math made easy
687 lines (580 loc) • 59.7 kB
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"><title>core/span.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">core/span.js</h1>
<section>
<article>
<pre class="prettyprint source linenums">
<code>/*global require:false*/
/*global define:false*/
/**
* @module span
* @private
*/
define(['mathlive/core/fontMetrics'],
function(FontMetrics) {
const NUMBER_FORMATTER = new Intl.NumberFormat('en-US', {
useGrouping: false,
maximumSignificantDigits: 5
});
/**
* Return a string made up of the concatenated arguments.
* Each arguments can be either a string, which is unchanged,
* or a number, which is converted to a string with at most 5 fractional digits.
*
* @param {...string} args
* @return {string}
* @memberof module:span
* @private
*/
function toString() {
let result = '';
for (const arg of arguments) {
if (typeof arg === 'number') {
result += NUMBER_FORMATTER.format(arg);
} else if (typeof arg === 'string') {
result += arg;
} else if (Array.isArray(arg)) {
for (const elem of arg) {
result += toString(elem);
}
} else if (arg) {
result += arg.toString();
}
}
return result;
}
//----------------------------------------------------------------------------
// SPAN
//----------------------------------------------------------------------------
/**
* A span is the most elementary element that can be rendered.
* It is composed of an optional body of text and an optional list
* of children (other spans). Each span can be decorated with
* CSS classes and style attributes.
*
* @param {string|Span|Span[]} content the items 'contained' by this node
* @param {string} classes list of classes attributes associated with this node
* @return {void}
* @class
* @global
* @memberof module:span
* @property {string} type - For example, `'command'`, `'mrel'`, etc...
* @property {string} classes - A string of space separated CSS classes
* associated with this element
* @property {Span[]} children - An array, potentially empty, of spans which
* this span encloses
* @property {string} body - Content of this span. Can be empty.
* @property {Object} style - A set of key/value pairs specifying CSS properties
* associated with this element.
* @property {number} height - The measurement from baseline to top, in em.
* @property {number} depth - The measurement from baseline to bottom, in em.
* @private
*/
function Span(content, classes) {
// CLASSES
this.classes = classes || '';
console.assert(typeof this.classes === 'string');
// CONTENT
if (Array.isArray(content)) {
// Check if isArray first, since an array is also an object
// Flatten it (i.e. [[a1, a2], b1, b2] -> [a1, a2, b1, b2]
this.children = [].concat.apply([], content);
} else if (typeof content === 'string') {
this.body = content;
} else if (content && typeof content === 'object') {
this.children = [content];
}
// STYLE
// CSS style, as an array of key value pairs.
// Use this.setStyle() to modify it.
this.style = null;
// Calculate the dimensions of this span based on its children
this.updateDimensions();
}
/**
* Update the dimensions of this node based on its children:
* - height: distance from bottom to top
* - depth: distance from bottom to baseline
* - maxFontSize:
* @method module:span.Span#updateDimensions
* @private
*/
Span.prototype.updateDimensions = function() {
let height = 0;
let depth = 0;
let maxFontSize = 0;
if (this.children) {
for (const child of this.children) {
if (child) {
console.assert(!isNaN(child.height));
if (child.height > height) height = child.height;
if (child.depth > depth) depth = child.depth;
if (child.maxFontSize > maxFontSize) maxFontSize = child.maxFontSize;
}
}
}
this.height = height;
this.depth = depth;
this.maxFontSize = maxFontSize;
}
/**
* Set the value of a CSS property associated with this span.
* For example, setStyle('border-right', 5.6, 'em');
*
* @param {string} prop the CSS property to set
* @param {Object} value a series of strings and numbers that will be concatenated.
* @return {string}
* @method module:span.Span#setStyle
* @private
*/
Span.prototype.setStyle = function(prop, ...value) {
const v = toString(value);
if (v.length > 0) {
if (!this.style) this.style = {};
this.style[prop] = v;
}
}
Span.prototype.setTop = function(top) {
if (top && top !== 0) {
if (!this.style) this.style = {};
this.style['top'] = toString(top) + 'em';
this.height -= top;
this.depth += top;
}
}
Span.prototype.setLeft = function(left) {
if (left && left !== 0) {
if (!this.style) this.style = {};
this.style['margin-left'] = toString(left) + 'em';
}
}
Span.prototype.setRight = function(right) {
if (right && right !== 0) {
if (!this.style) this.style = {};
this.style['margin-right'] = toString(right) + 'em';
}
}
Span.prototype.setWidth = function(width) {
if (width && width !== 0) {
if (!this.style) this.style = {};
this.style['width'] = toString(width) + 'em';
}
}
Span.prototype.addMarginRight = function(margin) {
if (margin && margin !== 0) {
if (!this.style &&
!/qquad|quad|enspace|thickspace|mediumspace|thinspace|negativethinspace/.test(this.classes)) {
// Attempt to use a class instead of an explicit margin
const cls = {
'2': 'qquad',
'1': 'quad',
'.5': 'enspace',
'0.277778': 'thickspace',
'0.222222': 'mediumspace',
'0.166667': 'thinspace',
'-0.166667': 'negativethinspace'}[margin.toString()];
if (cls) {
this.classes += ' rspace ' + cls;
return;
}
}
if (!this.style) this.style = {};
const currentMargin = parseFloat(this.style['margin-right'] || '0');
this.style['margin-right'] = toString(currentMargin + margin) + 'em'
}
}
/**
* Return HTML markup representing this span, its style, classes and
* children.
*
* @param {number} [hskip] amount of whitespace to insert before this element
* This is used to adjust the inter-spacing between spans of different types,
* e.g. 'bin' and 'rel', according to the TeX rules.
* @alias module:span.INTER_ATOM_SPACING
* @private
*/
const INTER_ATOM_SPACING = {
'mord+mop': 3,
'mord+mbin': 4,
'mord+mrel': 5,
'mord+minner': 3,
'mop+mord': 3,
'mop+mop': 3,
'mop+mbin': 5,
'mop+minner': 3,
'mbin+mord': 4,
'mbin+mop': 4,
'mbin+mopen': 4,
'mbin+minner': 4,
'mrel+mord': 5,
'mrel+mop': 5,
'mrel+mopen': 5,
'mrel+minner': 5,
'mclose+mop': 3,
'mclose+mbin': 4,
'mclose+mrel': 5,
'mclose+minner': 3,
'mpunct+mord': 3,
'mpunct+mop': 3,
'mpunct+mbin': 4,
'mpunct+mrel': 5,
'mpunct+mopen': 3,
'mpunct+mpunct': 3,
'mpunct+minner': 3
}
/**
*
* @alias module:span.INTER_ATOM_TIGHT_SPACING
* @private
*/
const INTER_ATOM_TIGHT_SPACING = {
'mord+mop': 3,
'mop+mord': 3,
'mop+mop': 3,
'mclose+mop': 3,
'minner+mop': 3
}
function lastSpanType(span) {
let result = span.type;
if (span.classes.indexOf('ML__selected') !== -1) {
result = span.children[span.children.length - 1].type;
}
if (result === 'first') return 'none';
if (result === 'textord') return 'mord';
return result;
}
/**
* Generate the HTML markup to represent this span.
*
* @param {?number} hskip - If a value is provided, it will be added (in ems) to the
* left margin.
* @param {?number} hscale - If a value is provided, the margins are scaled by
* this factor.
* @return {string} HTML markup
* @method module:span.Span#toMarkup
* @private
*/
Span.prototype.toMarkup = function(hskip, hscale) {
hskip = hskip || 0;
let result = '';
let body = this.body || '';
if (this.children) {
let previousType = 'none';
for (const child of this.children) {
let spacing = 0;
if (previousType) {
let type = child.type;
if (type) {
if (type === 'textord') type = 'mord';
if (type === 'first') type = 'none';
if (child.isTight) {
spacing = (INTER_ATOM_TIGHT_SPACING[previousType + '+' + type] || 0) / 18;
} else {
spacing = (INTER_ATOM_SPACING[previousType + '+' + type] || 0) / 18;
}
if (hscale) spacing = hscale * spacing;
}
}
body += child.toMarkup(spacing, hscale);
previousType = lastSpanType(child);
}
}
const tag = this.tag || 'span';
if (tag.length === 0) {
result = body || '';
} else {
result = '<' + tag;
if (this.svgOverlay) {
if (!this.style) this.style = {};
this.style['position'] = 'relative';
}
if (this.attributes) {
for (const attribute in this.attributes) {
if (this.attributes.hasOwnProperty(attribute)) {
result += ' ' + attribute + '="' + this.attributes[attribute] + '"';
}
}
}
const classes = this.classes.split(' ');
// Add the type (mbin, mrel, etc...) if specified
if (this.type) {
classes.push({
'command': 'ML__command',
'placeholder': 'ML__placeholder',
'error': 'ML__error'
}[this.type] || '');
}
if (this.type === 'command' && this.hasCaret) {
classes.push('ML__caret');
}
// Remove duplicate and empty classes
// and 'mathrm' which is a no-op
const classList = classes.filter(function (x, e, a) {
return x.length > 0 && x !== 'mathrm' && a.indexOf(x) === e;
}).join(' ');
if (classList.length > 0) {
result += ' class="' + classList + '"';
}
// If a `hskip` value was provided, add it to the margin-left
if (hskip) {
if (!this.style) this.style = {};
if (!this.style['margin-left']) {
this.style['margin-left'] = toString(hskip, 'em');
} else {
this.style['margin-left'] = toString(
(parseInt(this.style['margin-left']) + hskip), 'em');
}
}
if (this.style) {
let styleString = ''
for (const style in this.style) {
if (this.style.hasOwnProperty(style)) {
styleString += style + ':' + this.style[style] + ';'
}
}
if (styleString.length > 0) {
result += ' style="' + styleString + '"';
}
}
result += '>';
// If there is some SVG markup associated with this span,
// include it now
if (this.svgOverlay) {
result += body; // @todo maybe safe encode here...? (< >)
result += '<svg ';
// result += ` width="${this.clientWidth()}px"`;
// result += ` height="${this.clientHeight()}px"`;
result += ' width="100%" height="100%"';
result += 'style="position:absolute;left:0;top:0;width:100%;height:100%;z-index:2;"';
if (this.svgStyle) {
result += ' style="filter: drop-shadow(0 0 .5px rgba(255, 255, 255, .7)) drop-shadow(1px 1px 2px #333);"';
}
result += '>';
result += this.svgOverlay;
result += '</svg>';
} else {
result += body; // @todo maybe safe encode here...? (< >)
}
result += '</' + tag + '>';
}
// Collapse 'empty' spans
if (result === '<span>\u200b</span>') {
result = '';
}
if (this.hasCaret && this.type !== 'command') {
result = '<span class="ML__caret">' + result + '</span>';
}
return result;
}
/**
* Can this span be coalesced with 'span'?
* This is used to 'coalesce' (i.e. group together) a series of spans that are
* identical except for their value, and to avoid generating redundant spans.
* That is: '12' ->
* "<span class='mord mathrm'>12</span>"
* rather than:
* "<span class='mord mathrm'>1</span><span class='mord mathrm'>2</span>"
* @param {Span} span
* @return {boolean}
* @method module:span.Span#tryCoalesceWith
* @private
*/
Span.prototype.tryCoalesceWith = function(span) {
if (this.tag !== span.tag) return false;
if (this.type !== span.type) return false;
// Don't coalesce consecutive errors or placeholders
if (this.type === 'error' || this.type === 'placeholder' ||
this.type === 'command') return false;
// If this span or the candidate span have children, we can't
// coalesce them, but we'll try to coalesce their children
const hasChildren = this.children && this.children.length > 0;
const spanHasChildren = span.children && span.children.length > 0;
if (hasChildren || spanHasChildren) return false;
// If they have a different number of styles, can't coalesce
const thisStyleCount = this.style ? this.style.length : 0;
const spanStyleCount = span.style ? span.style.length : 0;
if (thisStyleCount !== spanStyleCount) return false;
// For the purpose of our comparison,
// any 'empty' classes (whitespace)
const classes = this.classes.trim().replace(/\s+/g, ' ')
.split(' ');
const spanClasses = span.classes.trim().replace(/\s+/g, ' ')
.split(' ');
// If they have a different number of classes, can't coalesce
if (classes.length !== spanClasses.length) return false;
// OK, let's do the more expensive comparison now.
// If they have different classes, can't coalesce
classes.sort();
spanClasses.sort();
for (let i = 0; i < classes.length; i++) {
// Don't coalesce vertical separators
// (used in column formating with {l||r} for example
if (classes[i] === 'vertical-separator') return false;
if (classes[i] !== spanClasses[i]) return false;
}
// If the styles are different, can't coalesce
if (this.style && span.style) {
for (const style in this.style) {
if (this.style.hasOwnProperty(style) &&
span.style.hasOwnProperty(style)) {
if (this.style[style] !== span.style[style]) return false;
}
}
}
// OK, the attributes of those spans are compatible.
// Merge span into this
this.body += span.body;
this.height = Math.max(this.height, span.height);
this.depth = Math.max(this.depth, span.depth);
// The italic correction for the coalesced spans is the
// italic correction of the last span.
this.italic = span.italic;
return true;
}
/**
* Attempts to coalesce (merge) spans, for example consecutive text spans.
* Return a new tree with coalesced spans.
*
* @param {Span[]} spans
* @return {Span[]} coalesced tree
* @memberof module:span
* @private
*/
function coalesce(spans) {
if (!spans || spans.length === 0) return [];
spans[0].children = coalesce(spans[0].children);
const result = [spans[0]];
for (let i = 1; i < spans.length; i++) {
if (!result[result.length - 1].tryCoalesceWith(spans[i])) {
spans[i].children = coalesce(spans[i].children);
result.push(spans[i]);
}
}
return result;
}
//----------------------------------------------------------------------------
// UTILITY FUNCTIONS
//----------------------------------------------------------------------------
function height(spans) {
if (!spans) return 0;
if (Array.isArray(spans)) {
let result = 0;
for (const span of spans) {
result = Math.max(result, span.height);
}
return result;
}
return spans.height;
}
function depth(spans) {
if (!spans) return 0;
if (Array.isArray(spans)) {
let result = 0;
for (const span of spans) {
result = Math.max(result, span.depth);
}
return result;
}
return spans.depth;
}
function skew(spans) {
if (!spans) return 0;
if (Array.isArray(spans)) {
let result = 0;
for (const span of spans) {
result += span.skew || 0;
}
return result;
}
return spans.skew;
}
function italic(spans) {
if (!spans) return 0;
if (Array.isArray(spans)) {
return spans[spans.length - 1].italic;
}
return spans.italic;
}
/**
* Make an element made of a sequence of children with classes
* @param {(string|Span|Span[])} content the items 'contained' by this node
* @param {string} classes list of classes attributes associated with this node
* @memberof module:span
* @private
*/
function makeSpan(content, classes) {
if (Array.isArray(content)) {
const c = [];
for (const s of content) {
if (s) c.push(s);
}
if (c.length === 1) {
return makeSpan(c[0], classes);
}
}
return new Span(content, classes);
}
/**
*
* @param {string} fontFamily
* @param {string} symbol
* @param {string} classes
* @memberof module:span
* @private
*/
function makeSymbol(fontFamily, symbol, classes) {
const result = new Span(symbol, classes);
const metrics = FontMetrics.getCharacterMetrics(symbol, fontFamily);
result.height = metrics.height;
result.depth = metrics.depth;
result.skew = metrics.skew;
result.italic = metrics.italic;
result.setRight(result.italic);
return result;
}
/**
* Makes an element placed in each of the vlist elements to ensure that each
* element has the same max font size. To do this, we create a zero-width space
* with the correct font size.
// * Note: without this, even when fontSize = 0, the fraction bar is no
// * longer positioned correctly
* @return {Span}
* @memberof module