/**
 * Copyleft 2010-2011 Jay and Han (laughinghan@gmail.com)
 *   under the GNU Lesser General Public License
 *     http://www.gnu.org/licenses/lgpl.html
 * Project Website: http://mathquill.com
 */ /**
 * Copyleft 2010-2011 Jay and Han (laughinghan@gmail.com)
 *   under the GNU Lesser General Public License
 *     http://www.gnu.org/licenses/lgpl.html
 * Project Website: http://mathquill.com
 */ ( function ( ) { var jQuery = window . jQuery , undefined , _ , mqCmdId = 'mathquill-command-id' , mqBlockId = 'mathquill-block-id' , min = Math . min , max = Math . max ; var __slice = [ ] . slice ; function noop ( ) { } /**
     * sugar to make defining lots of commands easier.
     * TODO: rethink this.
     */ function bind ( cons ) { var args = __slice . call ( arguments , 1 ) ; return function ( ) { return cons . apply ( this , args ) ; } ; } /**
     * a development-only debug method.  This definition and all
     * calls to `pray` will be stripped from the minified
     * build of mathquill.
     *
     * This function must be called by name to be removed
     * at compile time.  Do not define another function
     * with the same name, and only call this function by
     * name.
     */ function pray ( message , cond ) { if ( ! cond ) throw new Error ( 'prayer failed: ' + message ) ; } var P = ( function ( prototype , ownProperty , undefined ) { function isObject ( o ) { return typeof o === 'object' ; } function isFunction ( f ) { return typeof f === 'function' ; } function BareConstructor ( ) { } function P ( _superclass , definition ) { if ( definition === undefined ) { definition = _superclass ; _superclass = Object ; } function C ( ) { var self = new Bare ; if ( isFunction ( self . init ) ) self . init . apply ( self , arguments ) ; return self ; } function Bare ( ) { } C . Bare = Bare ; var _super = BareConstructor [ prototype ] = _superclass [ prototype ] ; var proto = Bare [ prototype ] = C [ prototype ] = new BareConstructor ; var extensions ; proto . constructor = C ; C . mixin = function ( def ) { Bare [ prototype ] = C [ prototype ] = P ( C , def ) [ prototype ] ; return C ; } ; return ( C . open = function ( def ) { extensions = { } ; if ( isFunction ( def ) ) { extensions = def . call ( C , proto , _super , C , _superclass ) ; } else if ( isObject ( def ) ) { extensions = def ; } if ( isObject ( extensions ) ) { for ( var ext in extensions ) { if ( ownProperty . call ( extensions , ext ) ) { proto [ ext ] = extensions [ ext ] ; } } } if ( ! isFunction ( proto . init ) ) { proto . init = _superclass ; } return C ; } ) ( definition ) ; } return P ; } ) ( 'prototype' , ( { } ) . hasOwnProperty ) ; /*************************************************
     * Textarea Manager
     *
     * An abstraction layer wrapping the textarea in
     * an object with methods to manipulate and listen
     * to events on, that hides all the nasty cross-
     * browser incompatibilities behind a uniform API.
     *
     * Design goal: This is a *HARD* internal
     * abstraction barrier. Cross-browser
     * inconsistencies are not allowed to leak through
     * and be dealt with by event handlers. All future
     * cross-browser issues that arise must be dealt
     * with here, and if necessary, the API updated.
     *
     * Organization:
     * - key values map and stringify()
     * - manageTextarea()
     *    + defer() and flush()
     *    + event handler logic
     *    + attach event handlers and export methods
     ************************************************/ var manageTextarea = ( function ( ) { var KEY_VALUES = { 8 : 'Backspace' , 9 : 'Tab' , 10 : 'Enter' , 13 : 'Enter' , 16 : 'Shift' , 17 : 'Control' , 18 : 'Alt' , 20 : 'CapsLock' , 27 : 'Esc' , 32 : 'Spacebar' , 33 : 'PageUp' , 34 : 'PageDown' , 35 : 'End' , 36 : 'Home' , 37 : 'Left' , 38 : 'Up' , 39 : 'Right' , 40 : 'Down' , 45 : 'Insert' , 46 : 'Del' , 144 : 'NumLock' } ; function stringify ( evt ) { var which = evt . which || evt . keyCode ; var keyVal = KEY_VALUES [ which ] ; var key ; var modifiers = [ ] ; if ( evt . ctrlKey ) modifiers . push ( 'Ctrl' ) ; if ( evt . originalEvent && evt . originalEvent . metaKey ) modifiers . push ( 'Meta' ) ; if ( evt . altKey ) modifiers . push ( 'Alt' ) ; if ( evt . shiftKey ) modifiers . push ( 'Shift' ) ; key = keyVal || String . fromCharCode ( which ) ; if ( ! modifiers . length && ! keyVal ) return key ; modifiers . push ( key ) ; return modifiers . join ( '-' ) ; } return function manageTextarea ( el , opts ) { var keydown = null ; var keypress = null ; if ( ! opts ) opts = { } ; var textCallback = opts . text || noop ; var keyCallback = opts . key || noop ; var pasteCallback = opts . paste || noop ; var onCut = opts . cut || noop ; var textarea = jQuery ( el ) ; var target = jQuery ( opts . container || textarea ) ; var checkTextarea = noop , timeoutId ; function checkTextareaFor ( checker ) { checkTextarea = checker ; clearTimeout ( timeoutId ) ; timeoutId = setTimeout ( checker ) ; } target . bind ( 'keydown keypress input keyup focusout paste' , function ( ) { checkTextarea ( ) ; } ) ; function select ( text ) { checkTextarea ( ) ; checkTextarea = noop ; clearTimeout ( timeoutId ) ; textarea . val ( text ) ; if ( text ) textarea [ 0 ] . select ( ) ; } function hasSelection ( ) { var dom = textarea [ 0 ] ; if ( ! ( 'selectionStart' in dom ) ) return false ; return dom . selectionStart !== dom . selectionEnd ; } function popText ( callback ) { var text = textarea . val ( ) ; textarea . val ( '' ) ; if ( text ) callback ( text ) ; } function handleKey ( ) { keyCallback ( stringify ( keydown ) , keydown ) ; } function onKeydown ( e ) { keydown = e ; keypress = null ; handleKey ( ) ; } function onKeypress ( e ) { if ( keydown && keypress ) handleKey ( ) ; keypress = e ; checkTextareaFor ( typedText ) ; } function typedText ( ) { if ( hasSelection ( ) ) return ; popText ( textCallback ) ; } function onBlur ( ) { keydown = keypress = null ; } function onPaste ( e ) { textarea . focus ( ) ; checkTextareaFor ( pastedText ) ; } function pastedText ( ) { popText ( pasteCallback ) ; } target . bind ( { keydown : onKeydown , keypress : onKeypress , focusout : onBlur , cut : onCut , paste : onPaste } ) ; return { select : select } ; } ; } ( ) ) ; var Parser = P ( function ( _ , _super , Parser ) { function parseError ( stream , message ) { if ( stream ) { stream = "'" + stream + "'" ; } else { stream = 'EOF' ; } throw 'Parse Error: ' + message + ' at ' + stream ; } _ . init = function ( body ) { this . _ = body ; } ; _ . parse = function ( stream ) { return this . skip ( eof ) . _ ( stream , success , parseError ) ; function success ( stream , result ) { return result ; } } ; _ . or = function ( alternative ) { pray ( 'or is passed a parser' , alternative instanceof Parser ) ; var self = this ; return Parser ( function ( stream , onSuccess , onFailure ) { return self . _ ( stream , onSuccess , failure ) ; function failure ( newStream ) { return alternative . _ ( stream , onSuccess , onFailure ) ; } } ) ; } ; _ . then = function ( next ) { var self = this ; return Parser ( function ( stream , onSuccess , onFailure ) { return self . _ ( stream , success , onFailure ) ; function success ( newStream , result ) { var nextParser = ( next instanceof Parser ? next : next ( result ) ) ; pray ( 'a parser is returned' , nextParser instanceof Parser ) ; return nextParser . _ ( newStream , onSuccess , onFailure ) ; } } ) ; } ; _ . many = function ( ) { var self = this ; return Parser ( function ( stream , onSuccess , onFailure ) { var xs = [ ] ; while ( self . _ ( stream , success , failure ) ) ; return onSuccess ( stream , xs ) ; function success ( newStream , x ) { stream = newStream ; xs . push ( x ) ; return true ; } function failure ( ) { return false ; } } ) ; } ; _ . times = function ( min , max ) { if ( arguments . length < 2 ) max = min ; var self = this ; return Parser ( function ( stream , onSuccess , onFailure ) { var xs = [ ] ; var result = true ; var failure ; for ( var i = 0 ; i < min ; i += 1 ) { result = self . _ ( stream , success , firstFailure ) ; if ( ! result ) return onFailure ( stream , failure ) ; } for ( ; i < max && result ; i += 1 ) { result = self . _ ( stream , success , secondFailure ) ; } return onSuccess ( stream , xs ) ; function success ( newStream , x ) { xs . push ( x ) ; stream = newStream ; return true ; } function firstFailure ( newStream , msg ) { failure = msg ; stream = newStream ; return false ; } function secondFailure ( newStream , msg ) { return false ; } } ) ; } ; _ . result = function ( res ) { return this . then ( succeed ( res ) ) ; } ; _ . atMost = function ( n ) { return this . times ( 0 , n ) ; } ; _ . atLeast = function ( n ) { var self = this ; return self . times ( n ) . then ( function ( start ) { return self . many ( ) . map ( function ( end ) { return start . concat ( end ) ; } ) ; } ) ; } ; _ . map = function ( fn ) { return this . then ( function ( result ) { return succeed ( fn ( result ) ) ; } ) ; } ; _ . skip = function ( two ) { return this . then ( function ( result ) { return two . result ( result ) ; } ) ; } ; var string = this . string = function ( str ) { var len = str . length ; var expected = "expected '" + str + "'" ; return Parser ( function ( stream , onSuccess , onFailure ) { var head = stream . slice ( 0 , len ) ; if ( head === str ) { return onSuccess ( stream . slice ( len ) , head ) ; } else { return onFailure ( stream , expected ) ; } } ) ; } ; var regex = this . regex = function ( re ) { pray ( 'regexp parser is anchored' , re . toString ( ) . charAt ( 1 ) === '^' ) ; var expected = 'expected ' + re ; return Parser ( function ( stream , onSuccess , onFailure ) { var match = re . exec ( stream ) ; if ( match ) { var result = match [ 0 ] ; return onSuccess ( stream . slice ( result . length ) , result ) ; } else { return onFailure ( stream , expected ) ; } } ) ; } ; var succeed = Parser . succeed = function ( result ) { return Parser ( function ( stream , onSuccess ) { return onSuccess ( stream , result ) ; } ) ; } ; var fail = Parser . fail = function ( msg ) { return Parser ( function ( stream , _ , onFailure ) { return onFailure ( stream , msg ) ; } ) ; } ; var letter = Parser . letter = regex ( /^[a-z]/i ) ; var letters = Parser . letters = regex ( /^[a-z]*/i ) ; var digit = Parser . digit = regex ( /^[0-9]/ ) ; var digits = Parser . digits = regex ( /^[0-9]*/ ) ; var whitespace = Parser . whitespace = regex ( /^\s+/ ) ; var optWhitespace = Parser . optWhitespace = regex ( /^\s*/ ) ; var any = Parser . any = Parser ( function ( stream , onSuccess , onFailure ) { if ( ! stream ) return onFailure ( stream , 'expected any character' ) ; return onSuccess ( stream . slice ( 1 ) , stream . charAt ( 0 ) ) ; } ) ; var all = Parser . all = Parser ( function ( stream , onSuccess , onFailure ) { return onSuccess ( '' , stream ) ; } ) ; var eof = Parser . eof = Parser ( function ( stream , onSuccess , onFailure ) { if ( stream ) return onFailure ( stream , 'expected EOF' ) ; return onSuccess ( stream , stream ) ; } ) ; } ) ; /*************************************************
     * Base classes of the MathQuill virtual DOM tree
     *
     * Only doing tree node manipulation via these
     * adopt/ disown methods guarantees well-formedness
     * of the tree.
     ************************************************/ var L = - 1 ; var R = 1 ; function prayDirection ( dir ) { pray ( 'a direction was passed' , dir === L || dir === R ) ; } /**
     * Tiny extension of jQuery adding directionalized DOM manipulation methods.
     *
     * Funny how Pjs v3 almost just works with `jQuery.fn.init`.
     *
     * jQuery features that don't work on $:
     *   - jQuery.*, like jQuery.ajax, obviously (Pjs doesn't and shouldn't
     *                                            copy constructor properties)
     *
     *   - jQuery(function), the shortcut for `jQuery(document).ready(function)`,
     *     because `jQuery.fn.init` is idiosyncratic and Pjs doing, essentially,
     *     `jQuery.fn.init.apply(this, arguments)` isn't quite right, you need:
     *
     *       _.init = function(s, c) { jQuery.fn.init.call(this, s, c, $(document)); };
     *
     *     if you actually give a shit (really, don't bother),
     *     see https://github.com/jquery/jquery/blob/1.7.2/src/core.js#L889
     *
     *   - jQuery(selector), because jQuery translates that to
     *     `jQuery(document).find(selector)`, but Pjs doesn't (should it?) let
     *     you override the result of a constructor call
     *       + note that because of the jQuery(document) shortcut-ness, there's also
     *         the 3rd-argument-needs-to-be-`$(document)` thing above, but the fix
     *         for that (as can be seen above) is really easy. This problem requires
     *         a way more intrusive fix
     *
     * And that's it! Everything else just magically works because jQuery internally
     * uses `this.constructor()` everywhere (hence calling `$`), but never ever does
     * `this.constructor.find` or anything like that, always doing `jQuery.find`.
     */ var $ = P ( jQuery , function ( _ ) { _ . insDirOf = function ( dir , el ) { return dir === L ? this . insertBefore ( el . first ( ) ) : this . insertAfter ( el . last ( ) ) ; } ; _ . insAtDirEnd = function ( dir , el ) { return dir === L ? this . prependTo ( el ) : this . appendTo ( el ) ; } ; } ) ; var Point = P ( function ( _ ) { _ . parent = 0 ; _ [ L ] = 0 ; _ [ R ] = 0 ; _ . init = function ( parent , leftward , rightward ) { this . parent = parent ; this [ L ] = leftward ; this [ R ] = rightward ; } ; } ) ; /**
     * MathQuill virtual-DOM tree-node abstract base class
     */ var Node = P ( function ( _ ) { _ [ L ] = 0 ; _ [ R ] = 0 ; _ . parent = 0 ; _ . init = function ( ) { this . ends = { } ; this . ends [ L ] = 0 ; this . ends [ R ] = 0 ; } ; _ . children = function ( ) { return Fragment ( this . ends [ L ] , this . ends [ R ] ) ; } ; _ . eachChild = function ( fn ) { return this . children ( ) . each ( fn ) ; } ; _ . foldChildren = function ( fold , fn ) { return this . children ( ) . fold ( fold , fn ) ; } ; _ . adopt = function ( parent , leftward , rightward ) { Fragment ( this , this ) . adopt ( parent , leftward , rightward ) ; return this ; } ; _ . disown = function ( ) { Fragment ( this , this ) . disown ( ) ; return this ; } ; } ) ; /**
     * An entity outside the virtual tree with one-way pointers (so it's only a
     * "view" of part of the tree, not an actual node/entity in the tree) that
     * delimits a doubly-linked list of sibling nodes.
     * It's like a fanfic love-child between HTML DOM DocumentFragment and the Range
     * classes: like DocumentFragment, its contents must be sibling nodes
     * (unlike Range, whose contents are arbitrary contiguous pieces of subtrees),
     * but like Range, it has only one-way pointers to its contents, its contents
     * have no reference to it and in fact may still be in the visible tree (unlike
     * DocumentFragment, whose contents must be detached from the visible tree
     * and have their 'parent' pointers set to the DocumentFragment).
     */ var Fragment = P ( function ( _ ) { _ . init = function ( leftEnd , rightEnd ) { pray ( 'no half-empty fragments' , ! leftEnd === ! rightEnd ) ; this . ends = { } ; if ( ! leftEnd ) return ; pray ( 'left end node is passed to Fragment' , leftEnd instanceof Node ) ; pray ( 'right end node is passed to Fragment' , rightEnd instanceof Node ) ; pray ( 'leftEnd and rightEnd have the same parent' , leftEnd . parent === rightEnd . parent ) ; this . ends [ L ] = leftEnd ; this . ends [ R ] = rightEnd ; } ; function prayWellFormed ( parent , leftward , rightward ) { pray ( 'a parent is always present' , parent ) ; pray ( 'leftward is properly set up' , ( function ( ) { if ( ! leftward ) return parent . ends [ L ] === rightward ; return leftward [ R ] === rightward && leftward . parent === parent ; } ) ( ) ) ; pray ( 'rightward is properly set up' , ( function ( ) { if ( ! rightward ) return parent . ends [ R ] === leftward ; return rightward [ L ] === leftward && rightward . parent === parent ; } ) ( ) ) ; } _ . adopt = function ( parent , leftward , rightward ) { prayWellFormed ( parent , leftward , rightward ) ; var self = this ; self . disowned = false ; var leftEnd = self . ends [ L ] ; if ( ! leftEnd ) return this ; var rightEnd = self . ends [ R ] ; if ( leftward ) { } else { parent . ends [ L ] = leftEnd ; } if ( rightward ) { rightward [ L ] = rightEnd ; } else { parent . ends [ R ] = rightEnd ; } self . ends [ R ] [ R ] = rightward ; self . each ( function ( el ) { el [ L ] = leftward ; el . parent = parent ; if ( leftward ) leftward [ R ] = el ; leftward = el ; } ) ; return self ; } ; _ . disown = function ( ) { var self = this ; var leftEnd = self . ends [ L ] ; if ( ! leftEnd || self . disowned ) return self ; self . disowned = true ; var rightEnd = self . ends [ R ] ; var parent = leftEnd . parent ; prayWellFormed ( parent , leftEnd [ L ] , leftEnd ) ; prayWellFormed ( parent , rightEnd , rightEnd [ R ] ) ; if ( leftEnd [ L ] ) { leftEnd [ L ] [ R ] = rightEnd [ R ] ; } else { parent . ends [ L ] = rightEnd [ R ] ; } if ( rightEnd [ R ] ) { rightEnd [ R ] [ L ] = leftEnd [ L ] ; } else { parent . ends [ R ] = leftEnd [ L ] ; } return self ; } ; _ . each = function ( fn ) { var self = this ; var el = self . ends [ L ] ; if ( ! el ) return self ; for ( ; el !== self . ends [ R ] [ R ] ; el = el [ R ] ) { if ( fn . call ( self , el ) === false ) break ; } return self ; } ; _ . fold = function ( fold , fn ) { this . each ( function ( el ) { fold = fn . call ( this , fold , el ) ; } ) ; return fold ; } ; } ) ; /*************************************************
     * Abstract classes of math blocks and commands.
     ************************************************/ var uuid = ( function ( ) { var id = 0 ; return function ( ) { return id += 1 ; } ; } ) ( ) ; /**
     * Math tree node base class.
     * Some math-tree-specific extensions to Node.
     * Both MathBlock's and MathCommand's descend from it.
     */ var MathElement = P ( Node , function ( _ , _super ) { _ . init = function ( obj ) { _super . init . call ( this ) ; this . id = uuid ( ) ; MathElement [ this . id ] = this ; } ; _ . toString = function ( ) { return '[MathElement ' + this . id + ']' ; } ; _ . bubble = function ( event ) { var args = __slice . call ( arguments , 1 ) ; for ( var ancestor = this ; ancestor ; ancestor = ancestor . parent ) { var res = ancestor [ event ] && ancestor [ event ] . apply ( ancestor , args ) ; if ( res === false ) break ; } return this ; } ; _ . postOrder = function ( fn ) { var args = __slice . call ( arguments , 1 ) ; if ( typeof fn === 'string' ) { var methodName = fn ; fn = function ( el ) { if ( methodName in el ) el [ methodName ] . apply ( el , args ) ; } ; } ( function recurse ( desc ) { desc . eachChild ( recurse ) ; fn ( desc ) ; } ) ( this ) ; } ; _ . jQ = $ ( ) ; _ . jQadd = function ( jQ ) { this . jQ = this . jQ . add ( jQ ) ; } ; this . jQize = function ( html ) { var jQ = $ ( html ) ; jQ . find ( '*' ) . andSelf ( ) . each ( function ( ) { var jQ = $ ( this ) , cmdId = jQ . attr ( 'mathquill-command-id' ) , blockId = jQ . attr ( 'mathquill-block-id' ) ; if ( cmdId ) MathElement [ cmdId ] . jQadd ( jQ ) ; if ( blockId ) MathElement [ blockId ] . jQadd ( jQ ) ; } ) ; return jQ ; } ; _ . finalizeInsert = function ( ) { var self = this ; self . postOrder ( 'finalizeTree' ) ; self . postOrder ( 'blur' ) ; self . postOrder ( 'respace' ) ; if ( self [ R ] . respace ) self [ R ] . respace ( ) ; if ( self [ L ] . respace ) self [ L ] . respace ( ) ; self . postOrder ( 'redraw' ) ; self . bubble ( 'redraw' ) ; } ; } ) ; /**
     * Commands and operators, like subscripts, exponents, or fractions.
     * Descendant commands are organized into blocks.
     */ var MathCommand = P ( MathElement , function ( _ , _super ) { _ . init = function ( ctrlSeq , htmlTemplate , textTemplate ) { var cmd = this ; _super . init . call ( cmd ) ; if ( ! cmd . ctrlSeq ) cmd . ctrlSeq = ctrlSeq ; if ( htmlTemplate ) cmd . htmlTemplate = htmlTemplate ; if ( textTemplate ) cmd . textTemplate = textTemplate ; } ; _ . replaces = function ( replacedFragment ) { replacedFragment . disown ( ) ; this . replacedFragment = replacedFragment ; } ; _ . isEmpty = function ( ) { return this . foldChildren ( true , function ( isEmpty , child ) { return isEmpty && child . isEmpty ( ) ; } ) ; } ; _ . parser = function ( ) { var block = latexMathParser . block ; var self = this ; return block . times ( self . numBlocks ( ) ) . map ( function ( blocks ) { self . blocks = blocks ; for ( var i = 0 ; i < blocks . length ; i += 1 ) { blocks [ i ] . adopt ( self , self . ends [ R ] , 0 ) ; } return self ; } ) ; } ; _ . createLeftOf = function ( cursor ) { var cmd = this ; var replacedFragment = cmd . replacedFragment ; cmd . createBlocks ( ) ; MathElement . jQize ( cmd . html ( ) ) ; if ( replacedFragment ) { replacedFragment . adopt ( cmd . ends [ L ] , 0 , 0 ) ; replacedFragment . jQ . appendTo ( cmd . ends [ L ] . jQ ) ; } cursor . jQ . before ( cmd . jQ ) ; cursor [ L ] = cmd . adopt ( cursor . parent , cursor [ L ] , cursor [ R ] ) ; cmd . finalizeInsert ( cursor ) ; cmd . placeCursor ( cursor ) ; } ; _ . createBlocks = function ( ) { var cmd = this , numBlocks = cmd . numBlocks ( ) , blocks = cmd . blocks = Array ( numBlocks ) ; for ( var i = 0 ; i < numBlocks ; i += 1 ) { var newBlock = blocks [ i ] = MathBlock ( ) ; newBlock . adopt ( cmd , cmd . ends [ R ] , 0 ) ; } } ; _ . respace = noop ; _ . placeCursor = function ( cursor ) { cursor . insAtRightEnd ( this . foldChildren ( this . ends [ L ] , function ( leftward , child ) { return leftward . isEmpty ( ) ? leftward : child ; } ) ) ; } ; _ . remove = function ( ) { this . disown ( ) ; this . jQ . remove ( ) ; this . postOrder ( function ( el ) { delete MathElement [ el . id ] ; } ) ; return this ; } ; _ . numBlocks = function ( ) { var matches = this . htmlTemplate . match ( /&\d+/g ) ; return matches ? matches . length : 0 ; } ; _ . html = function ( ) { var cmd = this ; var blocks = cmd . blocks ; var cmdId = ' mathquill-command-id=' + cmd . id ; var tokens = cmd . htmlTemplate . match ( /<[^<>]+>|[^<>]+/g ) ; pray ( 'no unmatched angle brackets' , tokens . join ( '' ) === this . htmlTemplate ) ; for ( var i = 0 , token = tokens [ 0 ] ; token ; i += 1 , token = tokens [ i ] ) { if ( token . slice ( - 2 ) === '/>' ) { tokens [ i ] = token . slice ( 0 , - 2 ) + cmdId + '/>' ; } else if ( token . charAt ( 0 ) === '<' ) { pray ( 'not an unmatched top-level close tag' , token . charAt ( 1 ) !== '/' ) ; tokens [ i ] = token . slice ( 0 , - 1 ) + cmdId + '>' ; var nesting = 1 ; do { i += 1 , token = tokens [ i ] ; pray ( 'no missing close tags' , token ) ; if ( token . slice ( 0 , 2 ) === '</' ) { nesting -= 1 ; } else if ( token . charAt ( 0 ) === '<' && token . slice ( - 2 ) !== '/>' ) { nesting += 1 ; } } while ( nesting > 0 ) ; } } return tokens . join ( '' ) . replace ( />&(\d+)/g , function ( $0 , $1 ) { return ' mathquill-block-id=' + blocks [ $1 ] . id + '>' + blocks [ $1 ] . join ( 'html' ) ; } ) ; } ; _ . latex = function ( ) { return this . foldChildren ( this . ctrlSeq , function ( latex , child ) { return latex + '{' + ( child . latex ( ) || ' ' ) + '}' ; } ) ; } ; _ . textTemplate = [ '' ] ; _ . text = function ( ) { var cmd = this , i = 0 ; return cmd . foldChildren ( cmd . textTemplate [ i ] , function ( text , child ) { i += 1 ; var child_text = child . text ( ) ; if ( text && cmd . textTemplate [ i ] === '(' && child_text [ 0 ] === '(' && child_text . slice ( - 1 ) === ')' ) return text + child_text . slice ( 1 , - 1 ) + cmd . textTemplate [ i ] ; return text + child . text ( ) + ( cmd . textTemplate [ i ] || '' ) ; } ) ; } ; } ) ; /**
     * Lightweight command without blocks or children.
     */ var Symbol = P ( MathCommand , function ( _ , _super ) { _ . init = function ( ctrlSeq , html , text ) { if ( ! text ) text = ctrlSeq && ctrlSeq . length > 1 ? ctrlSeq . slice ( 1 ) : ctrlSeq ; _super . init . call ( this , ctrlSeq , html , [ text ] ) ; } ; _ . parser = function ( ) { return Parser . succeed ( this ) ; } ; _ . numBlocks = function ( ) { return 0 ; } ; _ . replaces = function ( replacedFragment ) { replacedFragment . remove ( ) ; } ; _ . createBlocks = noop ; _ . latex = function ( ) { return this . ctrlSeq ; } ; _ . text = function ( ) { return this . textTemplate ; } ; _ . placeCursor = noop ; _ . isEmpty = function ( ) { return true ; } ; } ) ; /**
     * Children and parent of MathCommand's. Basically partitions all the
     * symbols and operators that descend (in the Math DOM tree) from
     * ancestor operators.
     */ var MathBlock = P ( MathElement , function ( _ ) { _ . join = function ( methodName ) { return this . foldChildren ( '' , function ( fold , child ) { return fold + child [ methodName ] ( ) ; } ) ; } ; _ . latex = function ( ) { return this . join ( 'latex' ) ; } ; _ . text = function ( ) { return this . ends [ L ] === this . ends [ R ] ? this . ends [ L ] . text ( ) : '(' + this . join ( 'text' ) + ')' ; } ; _ . isEmpty = function ( ) { return this . ends [ L ] === 0 && this . ends [ R ] === 0 ; } ; _ . write = function ( cursor , ch , replacedFragment ) { var cmd ; if ( ch . match ( /^[a-eg-zA-Z]$/ ) ) cmd = Variable ( ch ) ; else if ( cmd = CharCmds [ ch ] || LatexCmds [ ch ] ) cmd = cmd ( ch ) ; else cmd = VanillaSymbol ( ch ) ; if ( replacedFragment ) cmd . replaces ( replacedFragment ) ; cmd . createLeftOf ( cursor ) ; } ; _ . focus = function ( ) { this . jQ . addClass ( 'hasCursor' ) ; this . jQ . removeClass ( 'empty' ) ; return this ; } ; _ . blur = function ( ) { this . jQ . removeClass ( 'hasCursor' ) ; if ( this . isEmpty ( ) ) this . jQ . addClass ( 'empty' ) ; return this ; } ; } ) ; /**
     * Math tree fragment base class.
     * Some math-tree-specific extensions to Fragment.
     */ var MathFragment = P ( Fragment , function ( _ , _super ) { _ . init = function ( leftEnd , rightEnd ) { _super . init . call ( this , leftEnd , rightEnd || leftEnd ) ; this . jQ = this . fold ( $ ( ) , function ( jQ , child ) { return child . jQ . add ( jQ ) ; } ) ; } ; _ . latex = function ( ) { return this . fold ( '' , function ( latex , el ) { return latex + el . latex ( ) ; } ) ; } ; _ . remove = function ( ) { this . jQ . remove ( ) ; this . each ( function ( el ) { el . postOrder ( function ( desc ) { delete MathElement [ desc . id ] ; } ) ; } ) ; return this . disown ( ) ; } ; } ) ; /*********************************************
     * Root math elements with event delegation.
     ********************************************/ function createRoot ( jQ , root , textbox , editable ) { var contents = jQ . contents ( ) . detach ( ) ; if ( ! textbox ) { jQ . addClass ( 'mathquill-rendered-math' ) ; } root . jQ = jQ . attr ( mqBlockId , root . id ) ; root . revert = function ( ) { jQ . empty ( ) . unbind ( '.mathquill' ) . removeClass ( 'mathquill-rendered-math mathquill-editable mathquill-textbox' ) . append ( contents ) ; } ; var cursor = root . cursor = Cursor ( root ) ; root . renderLatex ( contents . text ( ) ) ; var textareaSpan = root . textarea = $ ( '<span class="textarea"><textarea></textarea></span>' ) , textarea = textareaSpan . children ( ) ; /******
         * TODO [Han]: Document this
         */ var textareaSelectionTimeout ; root . selectionChanged = function ( ) { if ( textareaSelectionTimeout === undefined ) { textareaSelectionTimeout = setTimeout ( setTextareaSelection ) ; } forceIERedraw ( jQ [ 0 ] ) ; } ; function setTextareaSelection ( ) { textareaSelectionTimeout = undefined ; var latex = cursor . selection ? '$' + cursor . selection . latex ( ) + '$' : '' ; textareaManager . select ( latex ) ; } jQ . bind ( 'selectstart.mathquill' , function ( e ) { if ( e . target !== textarea [ 0 ] ) e . preventDefault ( ) ; e . stopPropagation ( ) ; } ) ; var anticursor , blink = cursor . blink ; jQ . bind ( 'mousedown.mathquill' , function ( e ) { function mousemove ( e ) { cursor . seek ( $ ( e . target ) , e . pageX , e . pageY ) ; if ( cursor [ L ] !== anticursor [ L ] || cursor . parent !== anticursor . parent ) { cursor . selectFrom ( anticursor ) ; } return false ; } function docmousemove ( e ) { delete e . target ; return mousemove ( e ) ; } function mouseup ( e ) { anticursor = undefined ; cursor . blink = blink ; if ( ! cursor . selection ) { if ( editable ) { cursor . show ( ) ; } else { textareaSpan . detach ( ) ; } } jQ . unbind ( 'mousemove' , mousemove ) ; $ ( e . target . ownerDocument ) . unbind ( 'mousemove' , docmousemove ) . unbind ( 'mouseup' , mouseup ) ; } setTimeout ( function ( ) { textarea . focus ( ) ; } ) ; cursor . blink = noop ; cursor . seek ( $ ( e . target ) , e . pageX , e . pageY ) ; anticursor = Point ( cursor . parent , cursor [ L ] , cursor [ R ] ) ; if ( ! editable ) jQ . prepend ( textareaSpan ) ; jQ . mousemove ( mousemove ) ; $ ( e . target . ownerDocument ) . mousemove ( docmousemove ) . mouseup ( mouseup ) ; return false ; } ) ; if ( ! editable ) { var textareaManager = manageTextarea ( textarea , { container : jQ } ) ; jQ . bind ( 'cut paste' , false ) . bind ( 'copy' , setTextareaSelection ) . prepend ( '<span class="selectable">$' + root . latex ( ) + '$</span>' ) ; textarea . blur ( function ( ) { cursor . clearSelection ( ) ; setTimeout ( detach ) ; } ) ; function detach ( ) { textareaSpan . detach ( ) ; } return ; } var textareaManager = manageTextarea ( textarea , { container : jQ , key : function ( key , evt ) { cursor . parent . bubble ( 'onKey' , key , evt ) ; } , text : function ( text ) { cursor . parent . bubble ( 'onText' , text ) ; } , cut : function ( e ) { if ( cursor . selection ) { setTimeout ( function ( ) { cursor . prepareEdit ( ) ; cursor . parent . bubble ( 'redraw' ) ; } ) ; } e . stopPropagation ( ) ; } , paste : function ( text ) { if ( text . slice ( 0 , 1 ) === '$' && text . slice ( - 1 ) === '$' ) { text = text . slice ( 1 , - 1 ) ; } else { text = '\\text{' + text + '}' ; } cursor . writeLatex ( text ) . show ( ) ; } } ) ; jQ . prepend ( textareaSpan ) ; jQ . addClass ( 'mathquill-editable' ) ; if ( textbox ) jQ . addClass ( 'mathquill-textbox' ) ; textarea . focus ( function ( e ) { if ( ! cursor . parent ) cursor . insAtRightEnd ( root ) ; cursor . parent . jQ . addClass ( 'hasCursor' ) ; if ( cursor . selection ) { cursor . selection . jQ . removeClass ( 'blur' ) ; setTimeout ( root . selectionChanged ) ; } else cursor . show ( ) ; e . stopPropagation ( ) ; } ) . blur ( function ( e ) { cursor . hide ( ) . parent . blur ( ) ; if ( cursor . selection ) cursor . selection . jQ . addClass ( 'blur' ) ; e . stopPropagation ( ) ; } ) ; jQ . bind ( 'focus.mathquill blur.mathquill' , function ( e ) { textarea . trigger ( e ) ; } ) . blur ( ) ; } var RootMathBlock = P ( MathBlock , function ( _ , _super ) { _ . latex = function ( ) { return _super . latex . call ( this ) . replace ( /(\\[a-z]+) (?![a-z])/ig , '$1' ) ; } ; _ . text = function ( ) { return this . foldChildren ( '' , function ( text , child ) { return text + child . text ( ) ; } ) ; } ; _ . renderLatex = function ( latex ) { var jQ = this . jQ ; jQ . children ( ) . slice ( 1 ) . remove ( ) ; this . ends [ L ] = this . ends [ R ] = 0 ; delete this . cursor . selection ; this . cursor . insAtRightEnd ( this ) . writeLatex ( latex ) ; } ; _ . onKey = function ( key , e ) { switch ( key ) { case 'Ctrl-Shift-Backspace' : case 'Ctrl-Backspace' : while ( this . cursor [ L ] || this . cursor . selection ) { this . cursor . backspace ( ) ; } break ; case 'Shift-Backspace' : case 'Backspace' : this . cursor . backspace ( ) ; break ; case 'Esc' : case 'Tab' : case 'Spacebar' : var parent = this . cursor . parent ; if ( parent === this . cursor . root ) { if ( key === 'Spacebar' ) e . preventDefault ( ) ; return ; } this . cursor . prepareMove ( ) ; if ( parent [ R ] ) { this . cursor . insAtLeftEnd ( parent [ R ] ) ; } else { this . cursor . insRightOf ( parent . parent ) ; } break ; case 'Shift-Tab' : case 'Shift-Esc' : case 'Shift-Spacebar' : var parent = this . cursor . parent ; if ( parent === this . cursor . root ) { if ( key === 'Shift-Spacebar' ) e . preventDefault ( ) ; return ; } this . cursor . prepareMove ( ) ; if ( parent [ L ] ) { this . cursor . insAtRightEnd ( parent [ L ] ) ; } else { this . cursor . insLeftOf ( parent . parent ) ; } break ; case 'Enter' : break ; case 'End' : this . cursor . prepareMove ( ) . insAtRightEnd ( this . cursor . parent ) ; break ; case 'Ctrl-End' : this . cursor . prepareMove ( ) . insAtRightEnd ( this ) ; break ; case 'Shift-End' : while ( this . cursor [ R ] ) { this . cursor . selectRight ( ) ; } break ; case 'Ctrl-Shift-End' : while ( this . cursor [ R ] || this . cursor . parent !== this ) { this . cursor . selectRight ( ) ; } break ; case 'Home' : this . cursor . prepareMove ( ) . insAtLeftEnd ( this . cursor . parent ) ; break ; case 'Ctrl-Home' : this . cursor . prepareMove ( ) . insAtLeftEnd ( this ) ; break ; case 'Shift-Home' : while ( this . cursor [ L ] ) { this . cursor . selectLeft ( ) ; } break ; case 'Ctrl-Shift-Home' : while ( this . cursor [ L ] || this . cursor . parent !== this ) { this . cursor . selectLeft ( ) ; } break ; case 'Left' : this . cursor . moveLeft ( ) ; break ; case 'Shift-Left' : this . cursor . selectLeft ( ) ; break ; case 'Ctrl-Left' : break ; case 'Right' : this . cursor . moveRight ( ) ; break ; case 'Shift-Right' : this . cursor . selectRight ( ) ; break ; case 'Ctrl-Right' : break ; case 'Up' : this . cursor . moveUp ( ) ; break ; case 'Down' : this . cursor . moveDown ( ) ; break ; case 'Shift-Up' : if ( this . cursor [ L ] ) { while ( this . cursor [ L ] ) this . cursor . selectLeft ( ) ; } else { this . cursor . selectLeft ( ) ; } case 'Shift-Down' : if ( this . cursor [ R ] ) { while ( this . cursor [ R ] ) this . cursor . selectRight ( ) ; } else { this . cursor . selectRight ( ) ; } case 'Ctrl-Up' : break ; case 'Ctrl-Down' : break ; case 'Ctrl-Shift-Del' : case 'Ctrl-Del' : while ( this . cursor [ R ] || this . cursor . selection ) { this . cursor . deleteForward ( ) ; } break ; case 'Shift-Del' : case 'Del' : this . cursor . deleteForward ( ) ; break ; case 'Meta-A' : case 'Ctrl-A' : if ( this !== this . cursor . root ) return ; this . cursor . prepareMove ( ) . insAtRightEnd ( this ) ; while ( this . cursor [ L ] ) this . cursor . selectLeft ( ) ; break ; default : return false ; } e . preventDefault ( ) ; return false ; } ; _ . onText = function ( ch ) { this . cursor . write ( ch ) ; return false ; } ; } ) ; var RootMathCommand = P ( MathCommand , function ( _ , _super ) { _ . init = function ( cursor ) { _super . init . call ( this , '$' ) ; this . cursor = cursor ; } ; _ . htmlTemplate = '<span class="mathquill-rendered-math">&0</span>' ; _ . createBlocks = function ( ) { this . ends [ L ] = this . ends [ R ] = RootMathBlock ( ) ; this . blocks = [ this . ends [ L ] ] ; this . ends [ L ] . parent = this ; this . ends [ L ] . cursor = this . cursor ; this . ends [ L ] . write = function ( cursor , ch , replacedFragment ) { if ( ch !== '$' ) MathBlock . prototype . write . call ( this , cursor , ch , replacedFragment ) ; else if ( this . isEmpty ( ) ) { cursor . insRightOf ( this . parent ) . backspace ( ) . show ( ) ; VanillaSymbol ( '\\$' , '$' ) . createLeftOf ( cursor ) ; } else if ( ! cursor [ R ] ) cursor . insRightOf ( this . parent ) ; else if ( ! cursor [ L ] ) cursor . insLeftOf ( this . parent ) ; else MathBlock . prototype . write . call ( this , cursor , ch , replacedFragment ) ; } ; } ; _ . latex = function ( ) { return '$' + this . ends [ L ] . latex ( ) + '$' ; } ; } ) ; var RootTextBlock = P ( MathBlock , function ( _ ) { _ . renderLatex = function ( latex ) { var self = this ; var cursor = self . cursor ; self . jQ . children ( ) . slice ( 1 ) . remove ( ) ; self . ends [ L ] = self . ends [ R ] = 0 ; delete cursor . selection ; cursor . show ( ) . insAtRightEnd ( self ) ; var regex = Parser . regex ; var string = Parser . string ; var eof = Parser . eof ; var all = Parser . all ; var mathMode = string ( '$' ) . then ( latexMathParser ) . skip ( string ( '$' ) . or ( eof ) ) . map ( function ( block ) { var rootMathCommand = RootMathCommand ( cursor ) ; rootMathCommand . createBlocks ( ) ; var rootMathBlock = rootMathCommand . ends [ L ] ; block . children ( ) . adopt ( rootMathBlock , 0 , 0 ) ; return rootMathCommand ; } ) ; var escapedDollar = string ( '\\$' ) . result ( '$' ) ; var textChar = escapedDollar . or ( regex ( /^[^$]/ ) ) . map ( VanillaSymbol ) ; var latexText = mathMode . or ( textChar ) . many ( ) ; var commands = latexText . skip ( eof ) . or ( all . result ( false ) ) . parse ( latex ) ; if ( commands ) { for ( var i = 0 ; i < commands . length ; i += 1 ) { commands [ i ] . adopt ( self , self . ends [ R ] , 0 ) ; } var html = self . join ( 'html' ) ; MathElement . jQize ( html ) . appendTo ( self . jQ ) ; this . finalizeInsert ( ) ; } } ; _ . onKey = function ( key ) { if ( key === 'Spacebar' || key === 'Shift-Spacebar' ) return ; RootMathBlock . prototype . onKey . apply ( this , arguments ) ; } ; _ . onText = RootMathBlock . prototype . onText ; _ . write = function ( cursor , ch , replacedFragment ) { if ( replacedFragment ) replacedFragment . remove ( ) ; if ( ch === '$' ) RootMathCommand ( cursor ) . createLeftOf ( cursor ) ; else { var html ; if ( ch === '<' ) html = '&lt;' ; else if ( ch === '>' ) html = '&gt;' ; VanillaSymbol ( ch , html ) . createLeftOf ( cursor ) ; } } ; } ) ; /***************************
     * Commands and Operators.
     **************************/ var CharCmds = { } , LatexCmds = { } ; var scale , forceIERedraw = noop , div = document . createElement ( 'div' ) , div_style = div . style , transformPropNames = { transform : 1 , WebkitTransform : 1 , MozTransform : 1 , OTransform : 1 , msTransform : 1 } , transformPropName ; for ( var prop in transformPropNames ) { if ( prop in div_style ) { transformPropName = prop ; break ; } } if ( transformPropName ) { scale = function ( jQ , x , y ) { jQ . css ( transformPropName , 'scale(' + x + ',' + y + ')' ) ; } ; } else if ( 'filter' in div_style ) { forceIERedraw = function ( el ) { el . className = el . className ; } ; scale = function ( jQ , x , y ) { x /= ( 1 + ( y - 1 ) / 2 ) ; jQ . css ( 'fontSize' , y + 'em' ) ; if ( ! jQ . hasClass ( 'matrixed-container' ) ) { jQ . addClass ( 'matrixed-container' ) . wrapInner ( '<span class="matrixed"></span>' ) ; } var innerjQ = jQ . children ( ) . css ( 'filter' , 'progid:DXImageTransform.Microsoft' + '.Matrix(M11=' + x + ",SizingMethod='auto expand')" ) ; function calculateMarginRight ( ) { jQ . css ( 'marginRight' , ( innerjQ . width ( ) - 1 ) * ( x - 1 ) / x + 'px' ) ; } calculateMarginRight ( ) ; var intervalId = setInterval ( calculateMarginRight ) ; $ ( window ) . load ( function ( ) { clearTimeout ( intervalId ) ; calculateMarginRight ( ) ; } ) ; } ; } else { scale = function ( jQ , x , y ) { jQ . css ( 'fontSize' , y + 'em' ) ; } ; } var Style = P ( MathCommand , function ( _ , _super ) { _ . init = function ( ctrlSeq , tagName , attrs ) { _super . init . call ( this , ctrlSeq , '<' + tagName + ' ' + attrs + '>&0</' + tagName + '>' ) ; } ; } ) ; LatexCmds . mathrm = bind ( Style , '\\mathrm' , 'span' , 'class="roman font"' ) ; LatexCmds . mathit = bind ( Style , '\\mathit' , 'i' , 'class="font"' ) ; LatexCmds . mathbf = bind ( Style , '\\mathbf' , 'b' , 'class="font"' ) ; LatexCmds . mathsf = bind ( Style , '\\mathsf' , 'span' , 'class="sans-serif font"' ) ; LatexCmds . mathtt = bind ( Style , '\\mathtt' , 'span' , 'class="monospace font"' ) ; LatexCmds . underline = bind ( Style , '\\underline' , 'span' , 'class="non-leaf underline"' ) ; LatexCmds . overline = LatexCmds . bar = bind ( Style , '\\overline' , 'span' , 'class="non-leaf overline"' ) ; var SupSub = P ( MathCommand , function ( _ , _super ) { _ . init = function ( ctrlSeq , tag , text ) { _super . init . call ( this , ctrlSeq , '<' + tag + ' class="non-leaf">&0</' + tag + '>' , [ text ] ) ; } ; _ . finalizeTree = function ( ) { pray ( 'SupSub is only _ and ^' , this . ctrlSeq === '^' || this . ctrlSeq === '_' ) ; if ( this . ctrlSeq === '_' ) { this . down = this . ends [ L ] ; this . ends [ L ] . up = insLeftOfMeUnlessAtEnd ; } else { this . up = this . ends [ L ] ; this . ends [ L ] . down = insLeftOfMeUnlessAtEnd ; } function insLeftOfMeUnlessAtEnd ( cursor ) { var cmd = this . parent , ancestorCmd = cursor ; do { if ( ancestorCmd [ R ] ) { cursor . insLeftOf ( cmd ) ; return false ; } ancestorCmd = ancestorCmd . parent . parent ; } while ( ancestorCmd !== cmd ) ; cursor . insRightOf ( cmd ) ; return false ; } } ; _ . latex = function ( ) { var latex = this . ends [ L ] . latex ( ) ; if ( latex . length === 1 ) return this . ctrlSeq + latex ; else return this . ctrlSeq + '{' + ( latex || ' ' ) + '}' ; } ; _ . redraw = function ( ) { if ( this [ L ] ) this [ L ] . respace ( ) ; if ( ! ( this [ L ] instanceof SupSub ) ) { this . respace ( ) ; if ( this [ R ] && ! ( this [ R ] instanceof SupSub ) ) this [ R ] . respace ( ) ; } } ; _ . respace = function ( ) { if ( this [ L ] . ctrlSeq === '\\int ' || ( this [ L ] instanceof SupSub && this [ L ] . ctrlSeq != this . ctrlSeq && this [ L ] [ L ] && this [ L ] [ L ] . ctrlSeq === '\\int ' ) ) { if ( ! this . limit ) { this . limit = true ; this . jQ . addClass ( 'limit' ) ; } } else { if ( this . limit ) { this . limit = false ; this . jQ . removeClass ( 'limit' ) ; } } this . respaced = this [ L ] instanceof SupSub && this [ L ] . ctrlSeq != this . ctrlSeq && ! this [ L ] . respaced ; if ( this . respaced ) { var fontSize = + this . jQ . css ( 'fontSize' ) . slice ( 0 , - 2 ) , leftWidth = this [ L ] . jQ . outerWidth ( ) , thisWidth = this . jQ . outerWidth ( ) ; this . jQ . css ( { left : ( this . limit && this . ctrlSeq === '_' ? - .25 : 0 ) - leftWidth / fontSize + 'em' , marginRight : .1 - min ( thisWidth , leftWidth ) / fontSize + 'em' } ) ; } else if ( this . limit && this . ctrlSeq === '_' ) { this . jQ . css ( { left : '-.25em' , marginRight : '' } ) ; } else { this . jQ . css ( { left : '' , marginRight : '' } ) ; } if ( this [ R ] instanceof SupSub ) this [ R ] . respace ( ) ; return this ; } ; } ) ; LatexCmds . subscript = LatexCmds . _ = bind ( SupSub , '_' , 'sub' , '_' ) ; LatexCmds . superscript = LatexCmds . supscript = LatexCmds [ '^' ] = bind ( SupSub , '^' , 'sup' , '**' ) ; var Fraction = LatexCmds . frac = LatexCmds . dfrac = LatexCmds . cfrac = LatexCmds . fraction = P ( MathCommand , function ( _ , _super ) { _ . ctrlSeq = '\\frac' ; _ . htmlTemplate = '<span class="fraction non-leaf">' + '<span class="numerator">&0</span>' + '<span class="denominator">&1</span>' + '<span style="display:inline-block;width:0">&nbsp;</span>' + '</span>' ; _ . textTemplate = [ '(' , '/' , ')' ] ; _ . finalizeTree = function ( ) { this . up = this . ends [ R ] . up = this . ends [ L ] ; this . down = this . ends [ L ] . down = this . ends [ R ] ; } ; } ) ; var LiveFraction = LatexCmds . over = CharCmds [ '/' ] = P ( Fraction , function ( _ , _super ) { _ . createLeftOf = function ( cursor ) { if ( ! this . replacedFragment ) { var leftward = cursor [ L ] ; while ( leftward && ! ( leftward instanceof BinaryOperator || leftward instanceof TextBlock || leftward instanceof BigSymbol || ',;:' . split ( '' ) . indexOf ( leftward . ctrlSeq ) > - 1 ) ) leftward = leftward [ L ] ; if ( leftward instanceof BigSymbol && leftward [ R ] instanceof SupSub ) { leftward = leftward [ R ] ; if ( leftward [ R ] instanceof SupSub && leftward [ R ] . ctrlSeq != leftward . ctrlSeq ) leftward = leftward [ R ] ; } if ( leftward !== cursor [ L ] ) { this . replaces ( MathFragment ( leftward [ R ] || cursor . parent . ends [ L ] , cursor [ L ] ) ) ; cursor [ L ] = leftward ; } } _super . createLeftOf . call ( this , cursor ) ; } ; } ) ; var SquareRoot = LatexCmds . sqrt = LatexCmds [ '√' ] = P ( MathCommand , function ( _ , _super ) { _ . ctrlSeq = '\\sqrt' ; _ . htmlTemplate = '<span class="non-leaf">' + '<span class="scaled sqrt-prefix">&radic;</span>' + '<span class="non-leaf sqrt-stem">&0</span>' + '</span>' ; _ . textTemplate = [ 'sqrt(' , ')' ] ; _ . parser = function ( ) { return latexMathParser . optBlock . then ( function ( optBlock ) { return latexMathParser . block . map ( function ( block ) { var nthroot = NthRoot ( ) ; nthroot . blocks = [ optBlock , block ] ; optBlock . adopt ( nthroot , 0 , 0 ) ; block . adopt ( nthroot , optBlock , 0 ) ; return nthroot ; } ) ; } ) . or ( _super . parser . call ( this ) ) ; } ; _ . redraw = function ( ) { var block = this . ends [ R ] . jQ ; scale ( block . prev ( ) , 1 , block . innerHeight ( ) / + block . css ( 'fontSize' ) . slice ( 0 , - 2 ) - .1 ) ; } ; } ) ; var Vec = LatexCmds . vec = P ( MathCommand , function ( _ , _super ) { _ . ctrlSeq = '\\vec' ; _ . htmlTemplate = '<span class="non-leaf">' + '<span class="vector-prefix">&rarr;</span>' + '<span class="vector-stem">&0</span>' + '</span>' ; _ . textTemplate = [ 'vec(' , ')' ] ; } ) ; var NthRoot = LatexCmds . nthroot = P ( SquareRoot , function ( _ , _super ) { _ . htmlTemplate = '<sup class="nthroot non-leaf">&0</sup>' + '<span class="scaled">' + '<span class="sqrt-prefix scaled">&radic;</span>' + '<span class="sqrt-stem non-leaf">&1</span>' + '</span>' ; _ . textTemplate = [ 'sqrt[' , '](' , ')' ] ; _ . latex = function ( ) { return '\\sqrt[' + this . ends [ L ] . latex ( ) + ']{' + this . ends [ R ] . latex ( ) + '}' ; } ; } ) ; var Bracket = P ( MathCommand , function ( _ , _super ) { _ . init = function ( open , close , ctrlSeq , end ) { _super . init . call ( this , '\\left' + ctrlSeq , '<span class="non-leaf">' + '<span class="scaled paren">' + open + '</span>' + '<span class="non-leaf">&0</span>' + '<span class="scaled paren">' + close + '</span>' + '</span>' , [ open , close ] ) ; this . end = '\\right' + end ; } ; _ . jQadd = function ( ) { _super . jQadd . apply ( this , arguments ) ; var jQ = this . jQ ; this . bracketjQs = jQ . children ( ':first' ) . add ( jQ . children ( ':last' ) ) ; } ; _ . latex = function ( ) { return this . ctrlSeq + this . ends [ L ] . latex ( ) + this . end ; } ; _ . redraw = function ( ) { var blockjQ = this . ends [ L ] . jQ ; var height = blockjQ . outerHeight ( ) / + blockjQ . css ( 'fontSize' ) . slice ( 0 , - 2 ) ; scale ( this . bracketjQs , min ( 1 + .2 * ( height - 1 ) , 1.2 ) , 1.05 * height ) ; } ; } ) ; LatexCmds . left = P ( MathCommand , function ( _ ) { _ . parser = function ( ) { var regex = Parser . regex ; var string = Parser . string ; var succeed = Parser . succeed ; var optWhitespace = Parser . optWhitespace ; return optWhitespace . then ( regex ( /^(?:[([|]|\\\{)/ ) ) . then ( function ( open ) { if ( open . charAt ( 0 ) === '\\' ) open = open . slice ( 1 ) ; var cmd = CharCmds [ open ] ( ) ; return latexMathParser . map ( function ( block ) { cmd . blocks = [ block ] ; block . adopt ( cmd , 0 , 0 ) ; } ) . then ( string ( '\\right' ) ) . skip ( optWhitespace ) . then ( regex ( /^(?:[\])|]|\\\})/ ) ) . then ( function ( close ) { if ( close . slice ( - 1 ) !== cmd . end . slice ( - 1 ) ) { return Parser . fail ( 'open doesn\'t match close' ) ; } return succeed ( cmd ) ; } ) ; } ) ; } ; } ) ; LatexCmds . right = P ( MathCommand , function ( _ ) { _ . parser = function ( ) { return Parser . fail ( 'unmatched \\right' ) ; } ; } ) ; LatexCmds . lbrace = CharCmds [ '{' ] = bind ( Bracket , '{' , '}' , '\\{' , '\\}' ) ; LatexCmds . langle = LatexCmds . lang = bind ( Bracket , '&lang;' , '&rang;' , '\\langle ' , '\\rangle ' ) ; var CloseBracket = P ( Bracket , function ( _ , _super ) { _ . createLeftOf = function ( cursor ) { if ( ! cursor [ R ] && cursor . parent . parent && cursor . parent . parent . end === this . end && ! this . replacedFragment ) cursor . insRightOf ( cursor . parent . parent ) ; else _super . createLeftOf . call ( this , cursor ) ; } ; _ . placeCursor = function ( cursor ) { this . ends [ L ] . blur ( ) ; cursor . insRightOf ( this ) ; } ; } ) ; LatexCmds . rbrace = CharCmds [ '}' ] = bind ( CloseBracket , '{' , '}' , '\\{' , '\\}' ) ; LatexCmds . rangle = LatexCmds . rang = bind ( CloseBracket , '&lang;' , '&rang;' , '\\langle ' , '\\rangle ' ) ; var parenMixin = function ( _ , _super ) { _ . init = function ( open , close ) { _super . init . call ( this , open , close , open , close ) ; } ; } ; var Paren = P ( Bracket , parenMixin ) ; LatexCmds . lparen = CharCmds [ '(' ] = bind ( Paren , '(' , ')' ) ; LatexCmds . lbrack = LatexCmds . lbracket = CharCmds [ '[' ] = bind ( Paren , '[' , ']' ) ; var CloseParen = P ( CloseBracket , parenMixin ) ; LatexCmds . rparen = CharCmds [ ')' ] = bind ( CloseParen , '(' , ')' ) ; LatexCmds . rbrack = LatexCmds . rbracket = CharCmds [ ']' ] = bind ( CloseParen , '[' , ']' ) ; var Pipes = LatexCmds . lpipe = LatexCmds . rpipe = CharCmds [ '|' ] = P ( Paren , function ( _ , _super ) { _ . init = function ( ) { _super . init . call ( this , '|' , '|' ) ; } ; _ . createLeftOf = CloseBracket . prototype . createLeftOf ; } ) ; var TextBlock = CharCmds . $ = LatexCmds . text = LatexCmds . textnormal = LatexCmds . textrm = LatexCmds . textup = LatexCmds . textmd = P ( MathCommand , function ( _ , _super ) { _ . ctrlSeq = '\\text' ; _ . htmlTemplate = '<span class="text">&0</span>' ; _ . replaces = function ( replacedText ) { if ( replacedText instanceof MathFragment ) this . replacedText = replacedText . remove ( ) . jQ . text ( ) ; else if ( typeof replacedText === 'string' ) this . replacedText = replacedText ; } ; _ . textTemplate = [ '"' , '"' ] ; _ . parser = function ( ) { var self = this ; var string = Parser . string ; var regex = Parser . regex ; var optWhitespace = Parser . optWhitespace ; return optWhitespace . then ( string ( '{' ) ) . then ( regex ( /^[^}]*/ ) ) . skip ( string ( '}' ) ) . map ( function ( text ) { self . createBlocks ( ) ; var block = self . ends [ L ] ; for ( var i = 0 ; i < text . length ; i += 1 ) { var ch = VanillaSymbol ( text . charAt ( i ) ) ; ch . adopt ( block , block . ends [ R ] , 0 ) ; } return self ; } ) ; } ; _ . createBlocks = function ( ) { this . ends [ L ] = this . ends [ R ] = InnerTextBlock ( ) ; this . blocks = [ this . ends [ L ] ] ; this . ends [ L ] . parent = this ; } ; _ . finalizeInsert = function ( ) { this . ends [ L ] . blur = function ( ) { delete this . blur ; return this ; } ; _super . finalizeInsert . call ( this ) ; } ; _ . createLeftOf = function ( cursor ) { _super . createLeftOf . call ( this , this . cursor = cursor ) ; if ( this . replacedText ) for ( var i = 0 ; i < this . replacedText . length ; i += 1 ) this . ends [ L ] . write ( cursor , this . replacedText . charAt ( i ) ) ; } ; } ) ; var InnerTextBlock = P ( MathBlock , function ( _ , _super ) { _ . onKey = function ( key , e ) { if ( key === 'Spacebar' || key === 'Shift-Spacebar' ) return false ; } ; _ . deleteOutOf = function ( dir , cursor ) { if ( this . isEmpty ( ) ) cursor . insRightOf ( this . parent ) ; } ; _ . write = function ( cursor , ch , replacedFragment ) { if ( replacedFragment ) replacedFragment . remove ( ) ; if ( ch !== '$' ) { var html ; if ( ch === '<' ) html = '&lt;' ; else if ( ch === '>' ) html = '&gt;' ; VanillaSymbol ( ch , html ) . createLeftOf ( cursor ) ; } else if ( this . isEmpty ( ) ) { cursor . insRightOf ( this . parent ) . backspace ( ) ; VanillaSymbol ( '\\$' , '$' ) . createLeftOf ( cursor ) ; } else if ( ! cursor [ R ] ) cursor . insRightOf ( this . parent ) ; else if ( ! cursor [ L ] ) cursor . insLeftOf ( this . parent ) ; else { var rightward = TextBlock ( ) ; rightward . replaces ( MathFragment ( cursor [ R ] , this . ends [ R ] ) ) ; cursor . insRightOf ( this . parent ) ; rightward . adopt = function ( ) { delete this . adopt ; this . adopt . apply ( this , arguments ) ; this [ L ] = 0 ; } ; rightward . createLeftOf ( cursor ) ; rightward [ L ] = this . parent ; cursor . insLeftOf ( rightward ) ; } return false ; } ; _ . blur = function ( ) { this . jQ . removeClass ( 'hasCursor' ) ; if ( this . isEmpty ( ) ) { var textblock = this . parent , cursor = textblock . cursor ; if ( cursor . parent === this ) this . jQ . addClass ( 'empty' ) ; else { cursor . hide ( ) ; textblock . remove ( ) ; if ( cursor [ R ] === textblock ) cursor [ R ] = textblock [ R ] ; else if ( cursor [ L ] === textblock ) cursor [ L ] = textblock [ L ] ; cursor . show ( ) . parent . bubble ( 'redraw' ) ; } } return this ; } ; _ . focus = function ( ) { _super . focus . call ( this ) ; var textblock = this . parent ; if ( textblock [ R ] . ctrlSeq === textblock . ctrlSeq ) { var innerblock = this , cursor = textblock . cursor , rightward = textblock [ R ] . ends [ L ] ; rightward . eachChild ( function ( child ) { child . parent = innerblock ; child . jQ . appendTo ( innerblock . jQ ) ; } ) ; if ( this . ends [ R ] ) this . ends [ R ] [ R ] = rightward . ends [ L ] ; else this . ends [ L ] = rightward . ends [ L ] ; rightward . ends [ L ] [ L ] = this . ends [ R ] ; this . ends [ R ] = rightward . ends [ R ] ; rightward . parent . remove ( ) ; if ( cursor [ L ] ) cursor . insRightOf ( cursor [ L ] ) ; else cursor . insAtLeftEnd ( this ) ; cursor . parent . bubble ( 'redraw' ) ; } else if ( textblock [ L ] . ctrlSeq === textblock . ctrlSeq ) { var cursor = textblock . cursor ; if ( cursor [ L ] ) textblock [ L ] . ends [ L ] . focus ( ) ; else cursor . insAtRightEnd ( textblock [ L ] . ends [ L ] ) ; } return this ; } ; } ) ; function makeTextBlock ( latex , tagName , attrs ) { return P ( TextBlock , { ctrlSeq : latex , htmlTemplate : '<' + tagName + ' ' + attrs + '>&0</' + tagName + '>' } ) ; } LatexCmds . em = LatexCmds . italic = LatexCmds . italics = LatexCmds . emph = LatexCmds . textit = LatexCmds . textsl = makeTextBlock ( '\\textit' , 'i' , 'class="text"' ) ; LatexCmds . strong = LatexCmds . bold = LatexCmds . textbf = makeTextBlock ( '\\textbf' , 'b' , 'class="text"' ) ; LatexCmds . sf = LatexCmds . textsf = makeTextBlock ( '\\textsf' , 'span' , 'class="sans-serif text"' ) ; LatexCmds . tt = LatexCmds . texttt = makeTextBlock ( '\\texttt' , 'span' , 'class="monospace text"' ) ; LatexCmds . textsc = makeTextBlock ( '\\textsc' , 'span' , 'style="font-variant:small-caps" class="text"' ) ; LatexCmds . uppercase = makeTextBlock ( '\\uppercase' , 'span' , 'style="text-transform:uppercase" class="text"' ) ; LatexCmds . lowercase = makeTextBlock ( '\\lowercase' , 'span' , 'style="text-transform:lowercase" class="text"' ) ; var LatexCommandInput = CharCmds [ '\\' ] = P ( MathCommand , function ( _ , _super ) { _ . ctrlSeq = '\\' ; _ . replaces = function ( replacedFragment ) { this . _replacedFragment = replacedFragment . disown ( ) ; this . isEmpty = function ( ) { return false ; } ; } ; _ . htmlTemplate = '<span class="latex-command-input non-leaf">\\<span>&0</span></span>' ; _ . textTemplate = [ '\\' ] ; _ . createBlocks = function ( ) { _super . createBlocks . call ( this ) ; this . ends [ L ] . focus = function ( ) { this . parent . jQ . addClass ( 'hasCursor' ) ; if ( this . isEmpty ( ) ) this . parent . jQ . removeClass ( 'empty' ) ; return this ; } ; this . ends [ L ] . blur = function ( ) { this . parent . jQ . removeClass ( 'hasCursor' ) ; if ( this . isEmpty ( ) ) this . parent . jQ . addClass ( 'empty' ) ; return this ; } ; } ; _ . createLeftOf = function ( cursor ) { _super . createLeftOf . call ( this , cursor ) ; this . cursor = cursor . insAtRightEnd ( this . ends [ L ] ) ; if ( this . _replacedFragment ) { var el = this . jQ [ 0 ] ; this . jQ = this . _replacedFragment . jQ . addClass ( 'blur' ) . bind ( 'mousedown mousemove' , function ( e ) { $ ( e . target = el ) . trigger ( e ) ; return false ; } ) . insertBefore ( this . jQ ) . add ( this . jQ ) ; } this . ends [ L ] . write = function ( cursor , ch , replacedFragment ) { if ( replacedFragment ) replacedFragment . remove ( ) ; if ( ch . match ( /[a-z]/i ) ) VanillaSymbol ( ch ) . createLeftOf ( cursor ) ; else { this . parent . renderCommand ( ) ; if ( ch !== '\\' || ! this . isEmpty ( ) ) this . parent . parent . write ( cursor , ch ) ; } } ; } ; _ . latex = function ( ) { return '\\' + this . ends [ L ] . latex ( ) + ' ' ; } ; _ . onKey = function ( key , e ) { if ( key === 'Tab' || key === 'Enter' || key === 'Spacebar' ) { this . renderCommand ( ) ; e . preventDefault ( ) ; return false ; } } ; _ . renderCommand = function ( ) { this . jQ = this . jQ . last ( ) ; this . remove ( ) ; if ( this [ R ] ) { this . cursor . insLeftOf ( this [ R ] ) ; } else { this . cursor . insAtRightEnd ( this . parent ) ; } var latex = this . ends [ L ] . latex ( ) , cmd ; if ( ! latex ) latex = 'backslash' ; this . cursor . insertCmd ( latex , this . _replacedFragment ) ; } ; } ) ; var Binomial = LatexCmds . binom = LatexCmds . binomial = P ( MathCommand , function ( _ , _super ) { _ . ctrlSeq = '\\binom' ; _ . htmlTemplate = '<span class="paren scaled">(</span>' + '<span class="non-leaf">' + '<span class="array non-leaf">' + '<span>&0</span>' + '<span>&1</span>' + '</span>' + '</span>' + '<span class="paren scaled">)</span>' ; _ . textTemplate = [ 'choose(' , ',' , ')' ] ; _ . redraw = function ( ) { var blockjQ = this . jQ . eq ( 1 ) ; var height = blockjQ . outerHeight ( ) / + blockjQ . css ( 'fontSize' ) . slice ( 0 , - 2 ) ; var parens = this . jQ . filter ( '.paren' ) ; scale ( parens , min ( 1 + .2 * ( height - 1 ) , 1.2 ) , 1.05 * height ) ; } ; } ) ; var Choose = LatexCmds . choose = P ( Binomial , function ( _ ) { _ . createLeftOf = LiveFraction . prototype . createLeftOf ; } ) ; var Vector = LatexCmds . vector = P ( MathCommand , function ( _ , _super ) { _ . ctrlSeq = '\\vector' ; _ . htmlTemplate = '<span class="array"><span>&0</span></span>' ; _ . latex = function ( ) { return '\\begin{matrix}' + this . foldChildren ( [ ] , function ( latex , child ) { latex . push ( child . latex ( ) ) ; return latex ; } ) . join ( '\\\\' ) + '\\end{matrix}' ; } ; _ . text = function ( ) { return '[' + this . foldChildren ( [ ] , function ( text , child ) { text . push ( child . text ( ) ) ; return text ; } ) . join ( ) + ']' ; } ; _ . createLeftOf = function ( cursor ) { _super . createLeftOf . call ( this , this . cursor = cursor ) ; } ; _ . onKey = function ( key , e ) { var currentBlock = this . cursor . parent ; if ( currentBlock . parent === this ) { if ( key === 'Enter' ) { var newBlock = MathBlock ( ) ; newBlock . parent = this ; newBlock . jQ = $ ( '<span></span>' ) . attr ( mqBlockId , newBlock . id ) . insertAfter ( currentBlock . jQ ) ; if ( currentBlock [ R ] ) currentBlock [ R ] [ L ] = newBlock ; else this . ends [ R ] = newBlock ; newBlock [ R ] = currentBlock [ R ] ; currentBlock [ R ] = newBlock ; newBlock [ L ] = currentBlock ; this . bubble ( 'redraw' ) . cursor . insAtRightEnd ( newBlock ) ; e . preventDefault ( ) ; return false ; } else if ( key === 'Tab' && ! currentBlock [ R ] ) { if ( currentBlock . isEmpty ( ) ) { if ( currentBlock [ L ] ) { this . cursor . insRightOf ( this ) ; delete currentBlock [ L ] [ R ] ; this . ends [ R ] = currentBlock [ L ] ; currentBlock . jQ . remove ( ) ; this . bubble ( 'redraw' ) ; e . preventDefault ( ) ; return false ; } else return ; } var newBlock = MathBlock ( ) ; newBlock . parent = this ; newBlock . jQ = $ ( '<span></span>' ) . attr ( mqBlockId , newBlock . id ) . appendTo ( this . jQ ) ; this . ends [ R ] = newBlock ; currentBlock [ R ] = newBlock ; newBlock [ L ] = currentBlock ; this . bubble ( 'redraw' ) . cursor . insAtRightEnd ( newBlock ) ; e . preventDefault ( ) ; return false ; } else if ( e . which === 8 ) { if ( currentBlock . isEmpty ( ) ) { if ( currentBlock [ L ] ) { this . cursor . insAtRightEnd ( currentBlock [ L ] ) ; currentBlock [ L ] [ R ] = currentBlock [ R ] ; } else { this . cursor . insLeftOf ( this ) ; this . ends [ L ] = currentBlock [ R ] ; } if ( currentBlock [ R ] ) currentBlock [ R ] [ L ] = currentBlock [ L ] ; else this . ends [ R ] = currentBlock [ L ] ; currentBlock . jQ . remove ( ) ; if ( this . isEmpty ( ) ) this . cursor . deleteForward ( ) ; else this . bubble ( 'redraw' ) ; e . preventDefault ( ) ; return false ; } else if ( ! this . cursor [ L ] ) { e . preventDefault ( ) ; return false ; } } } } ; } ) ; LatexCmds . editable = P ( RootMathCommand , function ( _ , _super ) { _ . init = function ( ) { MathCommand . prototype . init . call ( this , '\\editable' ) ; } ; _ . jQadd = function ( ) { var self = this ; _super . jQadd . apply ( self , arguments ) ; var block = self . ends [ L ] . disown ( ) ; var blockjQ = self . jQ . children ( ) . detach ( ) ; self . ends [ L ] = self . ends [ R ] = RootMathBlock ( ) ; self . blocks = [ self . ends [ L ] ] ; self . ends [ L ] . parent = self ; createRoot ( self . jQ , self . ends [ L ] , false , true ) ; self . cursor = self . ends [ L ] . cursor ; block . children ( ) . adopt ( self . ends [ L ] , 0 , 0 ) ; blockjQ . appendTo ( self . ends [ L ] . jQ ) ; self . ends [ L ] . cursor . insAtRightEnd ( self . ends [ L ] ) ; } ; _ . latex = function ( ) { return this . ends [ L ] . latex ( ) ; } ; _ . text = function ( ) { return this . ends [ L ] . text ( ) ; } ; } ) ; /**********************************
     * Symbols and Special Characters
     *********************************/ LatexCmds . f = bind ( Symbol , 'f' , '<var class="florin">&fnof;</var><span style="display:inline-block;width:0">&nbsp;</span>' ) ; var Variable = P ( Symbol , function ( _ , _super ) { _ . init = function ( ch , html ) { _super . init . call ( this , ch , '<var>' + ( html || ch ) + '</var>' ) ; } ; _ . text = function ( ) { var text = this . ctrlSeq ; if ( this [ L ] && ! ( this [ L ] instanceof Variable ) && ! ( this [ L ] instanceof BinaryOperator ) ) text = '*' + text ; if ( this [ R ] && ! ( this [ R ] instanceof BinaryOperator ) && ! ( this [ R ] . ctrlSeq === '^' ) ) text += '*' ; return text ; } ; } ) ; var VanillaSymbol = P ( Symbol , function ( _ , _super ) { _ . init = function ( ch , html ) { _super . init . call ( this , ch , '<span>' + ( html || ch ) + '</span>' ) ; } ; } ) ; CharCmds [ ' ' ] = bind ( VanillaSymbol , '\\:' , ' ' ) ; LatexCmds . prime = CharCmds [ "'" ] = bind ( VanillaSymbol , "'" , '&prime;' ) ; var NonSymbolaSymbol = P ( Symbol , function ( _ , _super ) { _ . init = function ( ch , html ) { _super . init . call ( this , ch , '<span class="nonSymbola">' + ( html || ch ) + '</span>' ) ; } ; } ) ; LatexCmds [ '@' ] = NonSymbolaSymbol ; LatexCmds [ '&' ] = bind ( NonSymbolaSymbol , '\\&' , '&amp;' ) ; LatexCmds [ '%' ] = bind ( NonSymbolaSymbol , '\\%' , '%' ) ; LatexCmds . alpha = LatexCmds . beta = LatexCmds . gamma = LatexCmds . delta = LatexCmds . zeta = LatexCmds . eta = LatexCmds . theta = LatexCmds . iota = LatexCmds . kappa = LatexCmds . mu = LatexCmds . nu = LatexCmds . xi = LatexCmds . rho = LatexCmds . sigma = LatexCmds . tau = LatexCmds . chi = LatexCmds . psi = LatexCmds . omega = P ( Variable , function ( _ , _super ) { _ . init = function ( latex ) { _super . init . call ( this , '\\' + latex + ' ' , '&' + latex + ';' ) ; } ; } ) ; LatexCmds . phi = bind ( Variable , '\\phi ' , '&#981;' ) ; LatexCmds . phiv = LatexCmds . varphi = bind ( Variable , '\\varphi ' , '&phi;' ) ; LatexCmds . epsilon = bind ( Variable , '\\epsilon ' , '&#1013;' ) ; LatexCmds . epsiv = LatexCmds . varepsilon = bind ( Variable , '\\varepsilon ' , '&epsilon;' ) ; LatexCmds . piv = LatexCmds . varpi = bind ( Variable , '\\varpi ' , '&piv;' ) ; LatexCmds . sigmaf = LatexCmds . sigmav = LatexCmds . varsigma = bind ( Variable , '\\varsigma ' , '&sigmaf;' ) ; LatexCmds . thetav = LatexCmds . vartheta = LatexCmds . thetasym = bind ( Variable , '\\vartheta ' , '&thetasym;' ) ; LatexCmds . upsilon = LatexCmds . upsi = bind ( Variable , '\\upsilon ' , '&upsilon;' ) ; LatexCmds . gammad = LatexCmds . Gammad = LatexCmds . digamma = bind ( Variable , '\\digamma ' , '&#989;' ) ; LatexCmds . kappav = LatexCmds . varkappa = bind ( Variable , '\\varkappa ' , '&#1008;' ) ; LatexCmds . rhov = LatexCmds . varrho = bind ( Variable , '\\varrho ' , '&#1009;' ) ; LatexCmds . pi = LatexCmds [ 'π' ] = bind ( NonSymbolaSymbol , '\\pi ' , '&pi;' ) ; LatexCmds . lambda = bind ( NonSymbolaSymbol , '\\lambda ' , '&lambda;' ) ; LatexCmds . Upsilon = LatexCmds . Upsi = LatexCmds . upsih = LatexCmds . Upsih = bind ( Symbol , '\\Upsilon ' , '<var style="font-family: serif">&upsih;</var>' ) ; LatexCmds . Gamma = LatexCmds . Delta = LatexCmds . Theta = LatexCmds . Lambda = LatexCmds . Xi = LatexCmds . Pi = LatexCmds . Sigma = LatexCmds . Phi = LatexCmds . Psi = LatexCmds . Omega = LatexCmds . forall = P ( VanillaSymbol , function ( _ , _super ) { _ . init = function ( latex ) { _super . init . call ( this , '\\' + latex + ' ' , '&' + latex + ';' ) ; } ; } ) ; var LatexFragment = P ( MathCommand , function ( _ ) { _ . init = function ( latex ) { this . latex = latex ; } ; _ . createLeftOf = function ( cursor ) { cursor . writeLatex ( this . latex ) ; } ; _ . parser = function ( ) { var frag = latexMathParser . parse ( this . latex ) . children ( ) ; return Parser . succeed ( frag ) ; } ; } ) ; LatexCmds [ '¹' ] = bind ( LatexFragment , '^1' ) ; LatexCmds [ '²' ] = bind ( LatexFragment , '^2' ) ; LatexCmds [ '³' ] = bind ( LatexFragment , '^3' ) ; LatexCmds [ '¼' ] = bind ( LatexFragment , '\\frac14' ) ; LatexCmds [ '½' ] = bind ( LatexFragment , '\\frac12' ) ; LatexCmds [ '¾' ] = bind ( LatexFragment , '\\frac34' ) ; var BinaryOperator = P ( Symbol , function ( _ , _super ) { _ . init = function ( ctrlSeq , html , text ) { _super . init . call ( this , ctrlSeq , '<span class="binary-operator">' + html + '</span>' , text ) ; } ; } ) ; var PlusMinus = P ( BinaryOperator , function ( _ ) { _ . init = VanillaSymbol . prototype . init ; _ . respace = function ( ) { if ( ! this [ L ] ) { this . jQ [ 0 ] . className = '' ; } else if ( this [ L ] instanceof BinaryOperator && this [ R ] && ! ( this [ R ] instanceof BinaryOperator ) ) { this . jQ [ 0 ] . className = 'unary-operator' ; } else { this . jQ [ 0 ] . className = 'binary-operator' ; } return this ; } ; } ) ; LatexCmds [ '+' ] = bind ( PlusMinus , '+' , '+' ) ; LatexCmds [ '–' ] = LatexCmds [ '-' ] = bind ( PlusMinus , '-' , '&minus;' ) ; LatexCmds [ '±' ] = LatexCmds . pm = LatexCmds . plusmn = LatexCmds . plusminus = bind ( PlusMinus , '\\pm ' , '&plusmn;' ) ; LatexCmds . mp = LatexCmds . mnplus = LatexCmds . minusplus = bind ( PlusMinus , '\\mp ' , '&#8723;' ) ; CharCmds [ '*' ] = LatexCmds . sdot = LatexCmds . cdot = bind ( BinaryOperator , '\\cdot ' , '&middot;' ) ; LatexCmds [ '=' ] = bind ( BinaryOperator , '=' , '=' ) ; LatexCmds [ '<' ] = bind ( BinaryOperator , '<' , '&lt;' ) ; LatexCmds [ '>' ] = bind ( BinaryOperator , '>' , '&gt;' ) ; LatexCmds . notin = LatexCmds . sim = LatexCmds . cong = LatexCmds . equiv = LatexCmds . oplus = LatexCmds . otimes = P ( BinaryOperator , function ( _ , _super ) { _ . init = function ( latex ) { _super . init . call ( this , '\\' + latex + ' ' , '&' + latex + ';' ) ; } ; } ) ; LatexCmds . times = bind ( BinaryOperator , '\\times ' , '&times;' , '[x]' ) ; LatexCmds [ '÷' ] = LatexCmds . div = LatexCmds . divide = LatexCmds . divides = bind ( BinaryOperator , '\\div ' , '&divide;' , '[/]' ) ; LatexCmds [ '≠' ] = LatexCmds . ne = LatexCmds . neq = bind ( BinaryOperator , '\\ne ' , '&ne;' ) ; LatexCmds . ast = LatexCmds . star = LatexCmds . loast = LatexCmds . lowast = bind ( BinaryOperator , '\\ast ' , '&lowast;' ) ; LatexCmds . therefor = LatexCmds . therefore = bind ( BinaryOperator , '\\therefore ' , '&there4;' ) ; LatexCmds . cuz = LatexCmds . because = bind ( BinaryOperator , '\\because ' , '&#8757;' ) ; LatexCmds . prop = LatexCmds . propto = bind ( BinaryOperator , '\\propto ' , '&prop;' ) ; LatexCmds [ '≈' ] = LatexCmds . asymp = LatexCmds . approx = bind ( BinaryOperator , '\\approx ' , '&asymp;' ) ; LatexCmds . lt = bind ( BinaryOperator , '<' , '&lt;' ) ; LatexCmds . gt = bind ( BinaryOperator , '>' , '&gt;' ) ; LatexCmds [ '≤' ] = LatexCmds . le = LatexCmds . leq = bind ( BinaryOperator , '\\le ' , '&le;' ) ; LatexCmds [ '≥' ] = LatexCmds . ge = LatexCmds . geq = bind ( BinaryOperator , '\\ge ' , '&ge;' ) ; LatexCmds . isin = LatexCmds [ 'in' ] = bind ( BinaryOperator , '\\in ' , '&isin;' ) ; LatexCmds . ni = LatexCmds . contains = bind ( BinaryOperator , '\\ni ' , '&ni;' ) ; LatexCmds . notni = LatexCmds . niton = LatexCmds . notcontains = LatexCmds . doesnotcontain = bind ( BinaryOperator , '\\not\\ni ' , '&#8716;' ) ; LatexCmds . sub = LatexCmds . subset = bind ( BinaryOperator , '\\subset ' , '&sub;' ) ; LatexCmds . sup = LatexCmds . supset = LatexCmds . superset = bind ( BinaryOperator , '\\supset ' , '&sup;' ) ; LatexCmds . nsub = LatexCmds . notsub = LatexCmds . nsubset = LatexCmds . notsubset = bind ( BinaryOperator , '\\not\\subset ' , '&#8836;' ) ; LatexCmds . nsup = LatexCmds . notsup = LatexCmds . nsupset = LatexCmds . notsupset = LatexCmds . nsuperset = LatexCmds . notsuperset = bind ( BinaryOperator , '\\not\\supset ' , '&#8837;' ) ; LatexCmds . sube = LatexCmds . subeq = LatexCmds . subsete = LatexCmds . subseteq = bind ( BinaryOperator , '\\subseteq ' , '&sube;' ) ; LatexCmds . supe = LatexCmds . supeq = LatexCmds . supsete = LatexCmds . supseteq = LatexCmds . supersete = LatexCmds . superseteq = bind ( BinaryOperator , '\\supseteq ' , '&supe;' ) ; LatexCmds . nsube = LatexCmds . nsubeq = LatexCmds . notsube = LatexCmds . notsubeq = LatexCmds . nsubsete = LatexCmds . nsubseteq = LatexCmds . notsubsete = LatexCmds . notsubseteq = bind ( BinaryOperator , '\\not\\subseteq ' , '&#8840;' ) ; LatexCmds . nsupe = LatexCmds . nsupeq = LatexCmds . notsupe = LatexCmds . notsupeq = LatexCmds . nsupsete = LatexCmds . nsupseteq = LatexCmds . notsupsete = LatexCmds . notsupseteq = LatexCmds . nsupersete = LatexCmds . nsuperseteq = LatexCmds . notsupersete = LatexCmds . notsuperseteq = bind ( BinaryOperator , '\\not\\supseteq ' , '&#8841;' ) ; var BigSymbol = P ( Symbol , function ( _ , _super ) { _ . init = function ( ch , html ) { _super . init . call ( this , ch , '<big>' + html + '</big>' ) ; } ; } ) ; LatexCmds [ '∑' ] = LatexCmds . sum = LatexCmds . summation = bind ( BigSymbol , '\\sum ' , '&sum;' ) ; LatexCmds [ '∏' ] = LatexCmds . prod = LatexCmds . product = bind ( BigSymbol , '\\prod ' , '&prod;' ) ; LatexCmds . coprod = LatexCmds . coproduct = bind ( BigSymbol , '\\coprod ' , '&#8720;' ) ; LatexCmds [ '∫' ] = LatexCmds [ 'int' ] = LatexCmds . integral = bind ( BigSymbol , '\\int ' , '&int;' ) ; LatexCmds . N = LatexCmds . naturals = LatexCmds . Naturals = bind ( VanillaSymbol , '\\mathbb{N}' , '&#8469;' ) ; LatexCmds . P = LatexCmds . primes = LatexCmds . Primes = LatexCmds . projective = LatexCmds . Projective = LatexCmds . probability = LatexCmds . Probability = bind ( VanillaSymbol , '\\mathbb{P}' , '&#8473;' ) ; LatexCmds . Z = LatexCmds . integers = LatexCmds . Integers = bind ( VanillaSymbol , '\\mathbb{Z}' , '&#8484;' ) ; LatexCmds . Q = LatexCmds . rationals = LatexCmds . Rationals = bind ( VanillaSymbol , '\\mathbb{Q}' , '&#8474;' ) ; LatexCmds . R = LatexCmds . reals = LatexCmds . Reals = bind ( VanillaSymbol , '\\mathbb{R}' , '&#8477;' ) ; LatexCmds . C = LatexCmds . complex = LatexCmds . Complex = LatexCmds . complexes = LatexCmds . Complexes = LatexCmds . complexplane = LatexCmds . Complexplane = LatexCmds . ComplexPlane = bind ( VanillaSymbol , '\\mathbb{C}' , '&#8450;' ) ; LatexCmds . H = LatexCmds . Hamiltonian = LatexCmds . quaternions = LatexCmds . Quaternions = bind ( VanillaSymbol , '\\mathbb{H}' , '&#8461;' ) ; LatexCmds . quad = LatexCmds . emsp = bind ( VanillaSymbol , '\\quad ' , '    ' ) ; LatexCmds . qquad = bind ( VanillaSymbol , '\\qquad ' , '        ' ) ; LatexCmds . diamond = bind ( VanillaSymbol , '\\diamond ' , '&#9671;' ) ; LatexCmds . bigtriangleup = bind ( VanillaSymbol , '\\bigtriangleup ' , '&#9651;' ) ; LatexCmds . ominus = bind ( VanillaSymbol , '\\ominus ' , '&#8854;' ) ; LatexCmds . uplus = bind ( VanillaSymbol , '\\uplus ' , '&#8846;' ) ; LatexCmds . bigtriangledown = bind ( VanillaSymbol , '\\bigtriangledown ' , '&#9661;' ) ; LatexCmds . sqcap = bind ( VanillaSymbol , '\\sqcap ' , '&#8851;' ) ; LatexCmds . triangleleft = bind ( VanillaSymbol , '\\triangleleft ' , '&#8882;' ) ; LatexCmds . sqcup = bind ( VanillaSymbol , '\\sqcup ' , '&#8852;' ) ; LatexCmds . triangleright = bind ( VanillaSymbol , '\\triangleright ' , '&#8883;' ) ; LatexCmds . odot = bind ( VanillaSymbol , '\\odot ' , '&#8857;' ) ; LatexCmds . bigcirc = bind ( VanillaSymbol , '\\bigcirc ' , '&#9711;' ) ; LatexCmds . dagger = bind ( VanillaSymbol , '\\dagger ' , '&#0134;' ) ; LatexCmds . ddagger = bind ( VanillaSymbol , '\\ddagger ' , '&#135;' ) ; LatexCmds . wr = bind ( VanillaSymbol , '\\wr ' , '&#8768;' ) ; LatexCmds . amalg = bind ( VanillaSymbol , '\\amalg ' , '&#8720;' ) ; LatexCmds . models = bind ( VanillaSymbol , '\\models ' , '&#8872;' ) ; LatexCmds . prec = bind ( VanillaSymbol , '\\prec ' , '&#8826;' ) ; LatexCmds . succ = bind ( VanillaSymbol , '\\succ ' , '&#8827;' ) ; LatexCmds . preceq = bind ( VanillaSymbol , '\\preceq ' , '&#8828;' ) ; LatexCmds . succeq = bind ( VanillaSymbol , '\\succeq ' , '&#8829;' ) ; LatexCmds . simeq = bind ( VanillaSymbol , '\\simeq ' , '&#8771;' ) ; LatexCmds . mid = bind ( VanillaSymbol , '\\mid ' , '&#8739;' ) ; LatexCmds . ll = bind ( VanillaSymbol , '\\ll ' , '&#8810;' ) ; LatexCmds . gg = bind ( VanillaSymbol , '\\gg ' , '&#8811;' ) ; LatexCmds . parallel = bind ( VanillaSymbol , '\\parallel ' , '&#8741;' ) ; LatexCmds . bowtie = bind ( VanillaSymbol , '\\bowtie ' , '&#8904;' ) ; LatexCmds . sqsubset = bind ( VanillaSymbol , '\\sqsubset ' , '&#8847;' ) ; LatexCmds . sqsupset = bind ( VanillaSymbol , '\\sqsupset ' , '&#8848;' ) ; LatexCmds . smile = bind ( VanillaSymbol , '\\smile ' , '&#8995;' ) ; LatexCmds . sqsubseteq = bind ( VanillaSymbol , '\\sqsubseteq ' , '&#8849;' ) ; LatexCmds . sqsupseteq = bind ( VanillaSymbol , '\\sqsupseteq ' , '&#8850;' ) ; LatexCmds . doteq = bind ( VanillaSymbol , '\\doteq ' , '&#8784;' ) ; LatexCmds . frown = bind ( VanillaSymbol , '\\frown ' , '&#8994;' ) ; LatexCmds . vdash = bind ( VanillaSymbol , '\\vdash ' , '&#8870;' ) ; LatexCmds . dashv = bind ( VanillaSymbol , '\\dashv ' , '&#8867;' ) ; LatexCmds . longleftarrow = bind ( VanillaSymbol , '\\longleftarrow ' , '&#8592;' ) ; LatexCmds . longrightarrow = bind ( VanillaSymbol , '\\longrightarrow ' , '&#8594;' ) ; LatexCmds . Longleftarrow = bind ( VanillaSymbol , '\\Longleftarrow ' , '&#8656;' ) ; LatexCmds . Longrightarrow = bind ( VanillaSymbol , '\\Longrightarrow ' , '&#8658;' ) ; LatexCmds . longleftrightarrow = bind ( VanillaSymbol , '\\longleftrightarrow ' , '&#8596;' ) ; LatexCmds . updownarrow = bind ( VanillaSymbol , '\\updownarrow ' , '&#8597;' ) ; LatexCmds . Longleftrightarrow = bind ( VanillaSymbol , '\\Longleftrightarrow ' , '&#8660;' ) ; LatexCmds . Updownarrow = bind ( VanillaSymbol , '\\Updownarrow ' , '&#8661;' ) ; LatexCmds . mapsto = bind ( VanillaSymbol , '\\mapsto ' , '&#8614;' ) ; LatexCmds . nearrow = bind ( VanillaSymbol , '\\nearrow ' , '&#8599;' ) ; LatexCmds . hookleftarrow = bind ( VanillaSymbol , '\\hookleftarrow ' , '&#8617;' ) ; LatexCmds . hookrightarrow = bind ( VanillaSymbol , '\\hookrightarrow ' , '&#8618;' ) ; LatexCmds . searrow = bind ( VanillaSymbol , '\\searrow ' , '&#8600;' ) ; LatexCmds . leftharpoonup = bind ( VanillaSymbol , '\\leftharpoonup ' , '&#8636;' ) ; LatexCmds . rightharpoonup = bind ( VanillaSymbol , '\\rightharpoonup ' , '&#8640;' ) ; LatexCmds . swarrow = bind ( VanillaSymbol , '\\swarrow ' , '&#8601;' ) ; LatexCmds . leftharpoondown = bind ( VanillaSymbol , '\\leftharpoondown ' , '&#8637;' ) ; LatexCmds . rightharpoondown = bind ( VanillaSymbol , '\\rightharpoondown ' , '&#8641;' ) ; LatexCmds . nwarrow = bind ( VanillaSymbol , '\\nwarrow ' , '&#8598;' ) ; LatexCmds . ldots = bind ( VanillaSymbol , '\\ldots ' , '&#8230;' ) ; LatexCmds . cdots = bind ( VanillaSymbol , '\\cdots ' , '&#8943;' ) ; LatexCmds . vdots = bind ( VanillaSymbol , '\\vdots ' , '&#8942;' ) ; LatexCmds . ddots = bind ( VanillaSymbol , '\\ddots ' , '&#8944;' ) ; LatexCmds . surd = bind ( VanillaSymbol , '\\surd ' , '&#8730;' ) ; LatexCmds . triangle = bind ( VanillaSymbol , '\\triangle ' , '&#9653;' ) ; LatexCmds . ell = bind ( VanillaSymbol , '\\ell ' , '&#8467;' ) ; LatexCmds . top = bind ( VanillaSymbol , '\\top ' , '&#8868;' ) ; LatexCmds . flat = bind ( VanillaSymbol , '\\flat ' , '&#9837;' ) ; LatexCmds . natural = bind ( VanillaSymbol , '\\natural ' , '&#9838;' ) ; LatexCmds . sharp = bind ( VanillaSymbol , '\\sharp ' , '&#9839;' ) ; LatexCmds . wp = bind ( VanillaSymbol , '\\wp ' , '&#8472;' ) ; LatexCmds . bot = bind ( VanillaSymbol , '\\bot ' , '&#8869;' ) ; LatexCmds . clubsuit = bind ( VanillaSymbol , '\\clubsuit ' , '&#9827;' ) ; LatexCmds . diamondsuit = bind ( VanillaSymbol , '\\diamondsuit ' , '&#9826;' ) ; LatexCmds . heartsuit = bind ( VanillaSymbol , '\\heartsuit ' , '&#9825;' ) ; LatexCmds . spadesuit = bind ( VanillaSymbol , '\\spadesuit ' , '&#9824;' ) ; LatexCmds . oint = bind ( VanillaSymbol , '\\oint ' , '&#8750;' ) ; LatexCmds . bigcap = bind ( VanillaSymbol , '\\bigcap ' , '&#8745;' ) ; LatexCmds . bigcup = bind ( VanillaSymbol , '\\bigcup ' , '&#8746;' ) ; LatexCmds . bigsqcup = bind ( VanillaSymbol , '\\bigsqcup ' , '&#8852;' ) ; LatexCmds . bigvee = bind ( VanillaSymbol , '\\bigvee ' , '&#8744;' ) ; LatexCmds . bigwedge = bind ( VanillaSymbol , '\\bigwedge ' , '&#8743;' ) ; LatexCmds . bigodot = bind ( VanillaSymbol , '\\bigodot ' , '&#8857;' ) ; LatexCmds . bigotimes = bind ( VanillaSymbol , '\\bigotimes ' , '&#8855;' ) ; LatexCmds . bigoplus = bind ( VanillaSymbol , '\\bigoplus ' , '&#8853;' ) ; LatexCmds . biguplus = bind ( VanillaSymbol , '\\biguplus ' , '&#8846;' ) ; LatexCmds . lfloor = bind ( VanillaSymbol , '\\lfloor ' , '&#8970;' ) ; LatexCmds . rfloor = bind ( VanillaSymbol , '\\rfloor ' , '&#8971;' ) ; LatexCmds . lceil = bind ( VanillaSymbol , '\\lceil ' , '&#8968;' ) ; LatexCmds . rceil = bind ( VanillaSymbol , '\\rceil ' , '&#8969;' ) ; LatexCmds . slash = bind ( VanillaSymbol , '\\slash ' , '&#47;' ) ; LatexCmds . opencurlybrace = bind ( VanillaSymbol , '\\opencurlybrace ' , '&#123;' ) ; LatexCmds . closecurlybrace = bind ( VanillaSymbol , '\\closecurlybrace ' , '&#125;' ) ; LatexCmds . caret = bind ( VanillaSymbol , '\\caret ' , '^' ) ; LatexCmds . underscore = bind ( VanillaSymbol , '\\underscore ' , '_' ) ; LatexCmds . backslash = bind ( VanillaSymbol , '\\backslash ' , '\\' ) ; LatexCmds . vert = bind ( VanillaSymbol , '|' ) ; LatexCmds . perp = LatexCmds . perpendicular = bind ( VanillaSymbol , '\\perp ' , '&perp;' ) ; LatexCmds . nabla = LatexCmds . del = bind ( VanillaSymbol , '\\nabla ' , '&nabla;' ) ; LatexCmds . hbar = bind ( VanillaSymbol , '\\hbar ' , '&#8463;' ) ; LatexCmds . AA = LatexCmds . Angstrom = LatexCmds . angstrom = bind ( VanillaSymbol , '\\text\\AA ' , '&#8491;' ) ; LatexCmds . ring = LatexCmds . circ = LatexCmds . circle = bind ( VanillaSymbol , '\\circ ' , '&#8728;' ) ; LatexCmds . bull = LatexCmds . bullet = bind ( VanillaSymbol , '\\bullet ' , '&bull;' ) ; LatexCmds . setminus = LatexCmds . smallsetminus = bind ( VanillaSymbol , '\\setminus ' , '&#8726;' ) ; LatexCmds . not = LatexCmds [ '¬' ] = LatexCmds . neg = bind ( VanillaSymbol , '\\neg ' , '&not;' ) ; LatexCmds [ '…' ] = LatexCmds . dots = LatexCmds . ellip = LatexCmds . hellip = LatexCmds . ellipsis = LatexCmds . hellipsis = bind ( VanillaSymbol , '\\dots ' , '&hellip;' ) ; LatexCmds . converges = LatexCmds . darr = LatexCmds . dnarr = LatexCmds . dnarrow = LatexCmds . downarrow = bind ( VanillaSymbol , '\\downarrow ' , '&darr;' ) ; LatexCmds . dArr = LatexCmds . dnArr = LatexCmds . dnArrow = LatexCmds . Downarrow = bind ( VanillaSymbol , '\\Downarrow ' , '&dArr;' ) ; LatexCmds . diverges = LatexCmds . uarr = LatexCmds . uparrow = bind ( VanillaSymbol , '\\uparrow ' , '&uarr;' ) ; LatexCmds . uArr = LatexCmds . Uparrow = bind ( VanillaSymbol , '\\Uparrow ' , '&uArr;' ) ; LatexCmds . to = bind ( BinaryOperator , '\\to ' , '&rarr;' ) ; LatexCmds . rarr = LatexCmds . rightarrow = bind ( VanillaSymbol , '\\rightarrow ' , '&rarr;' ) ; LatexCmds . implies = bind ( BinaryOperator , '\\Rightarrow ' , '&rArr;' ) ; LatexCmds . rArr = LatexCmds . Rightarrow = bind ( VanillaSymbol , '\\Rightarrow ' , '&rArr;' ) ; LatexCmds . gets = bind ( BinaryOperator , '\\gets ' , '&larr;' ) ; LatexCmds . larr = LatexCmds . leftarrow = bind ( VanillaSymbol , '\\leftarrow ' , '&larr;' ) ; LatexCmds . impliedby = bind ( BinaryOperator , '\\Leftarrow ' , '&lArr;' ) ; LatexCmds . lArr = LatexCmds . Leftarrow = bind ( VanillaSymbol , '\\Leftarrow ' , '&lArr;' ) ; LatexCmds . harr = LatexCmds . lrarr = LatexCmds . leftrightarrow = bind ( VanillaSymbol , '\\leftrightarrow ' , '&harr;' ) ; LatexCmds . iff = bind ( BinaryOperator , '\\Leftrightarrow ' , '&hArr;' ) ; LatexCmds . hArr = LatexCmds . lrArr = LatexCmds . Leftrightarrow = bind ( VanillaSymbol , '\\Leftrightarrow ' , '&hArr;' ) ; LatexCmds . Re = LatexCmds . Real = LatexCmds . real = bind ( VanillaSymbol , '\\Re ' , '&real;' ) ; LatexCmds . Im = LatexCmds . imag = LatexCmds . image = LatexCmds . imagin = LatexCmds . imaginary = LatexCmds . Imaginary = bind ( VanillaSymbol , '\\Im ' , '&image;' ) ; LatexCmds . part = LatexCmds . partial = bind ( VanillaSymbol , '\\partial ' , '&part;' ) ; LatexCmds . inf = LatexCmds . infin = LatexCmds . infty = LatexCmds . infinity = bind ( VanillaSymbol , '\\infty ' , '&infin;' ) ; LatexCmds . alef = LatexCmds . alefsym = LatexCmds . aleph = LatexCmds . alephsym = bind ( VanillaSymbol , '\\aleph ' , '&alefsym;' ) ; LatexCmds . xist = LatexCmds . xists = LatexCmds . exist = LatexCmds . exists = bind ( VanillaSymbol , '\\exists ' , '&exist;' ) ; LatexCmds . and = LatexCmds . land = LatexCmds . wedge = bind ( VanillaSymbol , '\\wedge ' , '&and;' ) ; LatexCmds . or = LatexCmds . lor = LatexCmds . vee = bind ( VanillaSymbol , '\\vee ' , '&or;' ) ; LatexCmds . o = LatexCmds . O = LatexCmds . empty = LatexCmds . emptyset = LatexCmds . oslash = LatexCmds . Oslash = LatexCmds . nothing = LatexCmds . varnothing = bind ( BinaryOperator , '\\varnothing ' , '&empty;' ) ; LatexCmds . cup = LatexCmds . union = bind ( BinaryOperator , '\\cup ' , '&cup;' ) ; LatexCmds . cap = LatexCmds . intersect = LatexCmds . intersection = bind ( BinaryOperator , '\\cap ' , '&cap;' ) ; LatexCmds . deg = LatexCmds . degree = bind ( VanillaSymbol , '^\\circ ' , '&deg;' ) ; LatexCmds . ang = LatexCmds . angle = bind ( VanillaSymbol , '\\angle ' , '&ang;' ) ; var NonItalicizedFunction = P ( Symbol , function ( _ , _super ) { _ . init = function ( fn ) { _super . init . call ( this , '\\' + fn + ' ' , '<span>' + fn + '</span>' ) ; } ; _ . respace = function ( ) { this . jQ [ 0 ] . className = ( this [ R ] instanceof SupSub || this [ R ] instanceof Bracket ) ? '' : 'non-italicized-function' ; } ; } ) ; LatexCmds . ln = LatexCmds . lg = LatexCmds . log = LatexCmds . span = LatexCmds . proj = LatexCmds . det = LatexCmds . dim = LatexCmds . min = LatexCmds . max = LatexCmds . mod = LatexCmds . lcm = LatexCmds . gcd = LatexCmds . gcf = LatexCmds . hcf = LatexCmds . lim = NonItalicizedFunction ; ( function ( ) { var trig = [ 'sin' , 'cos' , 'tan' , 'sec' , 'cosec' , 'csc' , 'cotan' , 'cot' ] ; for ( var i in trig ) { LatexCmds [ trig [ i ] ] = LatexCmds [ trig [ i ] + 'h' ] = LatexCmds [ 'a' + trig [ i ] ] = LatexCmds [ 'arc' + trig [ i ] ] = LatexCmds [ 'a' + trig [ i ] + 'h' ] = LatexCmds [ 'arc' + trig [ i ] + 'h' ] = NonItalicizedFunction ; } } ( ) ) ; var latexMathParser = ( function ( ) { function commandToBlock ( cmd ) { var block = MathBlock ( ) ; cmd . adopt ( block , 0 , 0 ) ; return block ; } function joinBlocks ( blocks ) { var firstBlock = blocks [ 0 ] || MathBlock ( ) ; for ( var i = 1 ; i < blocks . length ; i += 1 ) { blocks [ i ] . children ( ) . adopt ( firstBlock , firstBlock . ends [ R ] , 0 ) ; } return firstBlock ; } var string = Parser . string ; var regex = Parser . regex ; var letter = Parser . letter ; var any = Parser . any ; var optWhitespace = Parser . optWhitespace ; var succeed = Parser . succeed ; var fail = Parser . fail ; var variable = letter . map ( Variable ) ; var symbol = regex ( /^[^${}\\_^]/ ) . map ( VanillaSymbol ) ; var controlSequence = regex ( /^[^\\a-eg-zA-Z]/ ) . or ( string ( '\\' ) . then ( regex ( /^[a-z]+/i ) . or ( regex ( /^\s+/ ) . result ( ' ' ) ) . or ( any ) ) ) . then ( function ( ctrlSeq ) { var cmdKlass = LatexCmds [ ctrlSeq ] ; if ( cmdKlass ) { return cmdKlass ( ctrlSeq ) . parser ( ) ; } else { return fail ( 'unknown command: \\' + ctrlSeq ) ; } } ) ; var command = controlSequence . or ( variable ) . or ( symbol ) ; var mathGroup = string ( '{' ) . then ( function ( ) { return mathSequence ; } ) . skip ( string ( '}' ) ) ; var mathBlock = optWhitespace . then ( mathGroup . or ( command . map ( commandToBlock ) ) ) ; var mathSequence = mathBlock . many ( ) . map ( joinBlocks ) . skip ( optWhitespace ) ; var optMathBlock = string ( '[' ) . then ( mathBlock . then ( function ( block ) { return block . join ( 'latex' ) !== ']' ? succeed ( block ) : fail ( ) ; } ) . many ( ) . map ( joinBlocks ) . skip ( optWhitespace ) ) . skip ( string ( ']' ) ) ; var latexMath = mathSequence ; latexMath . block = mathBlock ; latexMath . optBlock = optMathBlock ; return latexMath ; } ) ( ) ; /********************************************
     * Cursor and Selection "singleton" classes
     *******************************************/ var Cursor = P ( Point , function ( _ ) { _ . init = function ( root ) { this . parent = this . root = root ; var jQ = this . jQ = this . _jQ = $ ( '<span class="cursor">&zwj;</span>' ) ; this . blink = function ( ) { jQ . toggleClass ( 'blink' ) ; } ; this . upDownCache = { } ; } ; _ . show = function ( ) { this . jQ = this . _jQ . removeClass ( 'blink' ) ; if ( 'intervalId' in this ) clearInterval ( this . intervalId ) ; else { if ( this [ R ] ) { if ( this . selection && this . selection . ends [ L ] [ L ] === this [ L ] ) this . jQ . insertBefore ( this . selection . jQ ) ; else this . jQ . insertBefore ( this [ R ] . jQ . first ( ) ) ; } else this . jQ . appendTo ( this . parent . jQ ) ; this . parent . focus ( ) ; } this . intervalId = setInterval ( this . blink , 500 ) ; return this ; } ; _ . hide = function ( ) { if ( 'intervalId' in this ) clearInterval ( this . intervalId ) ; delete this . intervalId ; this . jQ . detach ( ) ; this . jQ = $ ( ) ; return this ; } ; _ . withDirInsertAt = function ( dir , parent , withDir , oppDir ) { var oldParent = this . parent ; this . parent = parent ; this [ dir ] = withDir ; this [ - dir ] = oppDir ; oldParent . blur ( ) ; } ; _ . insDirOf = function ( dir , el ) { prayDirection ( dir ) ; this . withDirInsertAt ( dir , el . parent , el [ dir ] , el ) ; this . parent . jQ . addClass ( 'hasCursor' ) ; this . jQ . insDirOf ( dir , el . jQ ) ; return this ; } ; _ . insLeftOf = function ( el ) { return this . insDirOf ( L , el ) ; } ; _ . insRightOf = function ( el ) { return this . insDirOf ( R , el ) ; } ; _ . insAtDirEnd = function ( dir , el ) { prayDirection ( dir ) ; this . withDirInsertAt ( dir , el , 0 , el . ends [ dir ] ) ; if ( dir === L && el . textarea ) { this . jQ . insDirOf ( - dir , el . textarea ) ; } else { this . jQ . insAtDirEnd ( dir , el . jQ ) ; } el . focus ( ) ; return this ; } ; _ . insAtLeftEnd = function ( el ) { return this . insAtDirEnd ( L , el ) ; } ; _ . insAtRightEnd = function ( el ) { return this . insAtDirEnd ( R , el ) ; } ; _ . hopDir = function ( dir ) { prayDirection ( dir ) ; this . jQ . insDirOf ( dir , this [ dir ] . jQ ) ; this [ - dir ] = this [ dir ] ; this [ dir ] = this [ dir ] [ dir ] ; return this ; } ; _ . hopLeft = function ( ) { return this . hopDir ( L ) ; } ; _ . hopRight = function ( ) { return this . hopDir ( R ) ; } ; _ . moveDirWithin = function ( dir , block ) { prayDirection ( dir ) ; if ( this [ dir ] ) { if ( this [ dir ] . ends [ - dir ] ) this . insAtDirEnd ( - dir , this [ dir ] . ends [ - dir ] ) ; else this . hopDir ( dir ) ; } else { if ( this . parent === block ) return ; if ( this . parent [ dir ] ) this . insAtDirEnd ( - dir , this . parent [ dir ] ) ; else this . insDirOf ( dir , this . parent . parent ) ; } } ; _ . moveLeftWithin = function ( block ) { return this . moveDirWithin ( L , block ) ; } ; _ . moveRightWithin = function ( block ) { return this . moveDirWithin ( R , block ) ; } ; _ . moveDir = function ( dir ) { prayDirection ( dir ) ; clearUpDownCache ( this ) ; if ( this . selection ) { this . insDirOf ( dir , this . selection . ends [ dir ] ) . clearSelection ( ) ; } else { this . moveDirWithin ( dir , this . root ) ; } return this . show ( ) ; } ; _ . moveLeft = function ( ) { return this . moveDir ( L ) ; } ; _ . moveRight = function ( ) { return this . moveDir ( R ) ; } ; /**
         * moveUp and moveDown have almost identical algorithms:
         * - first check left and right, if so insAtLeft/RightEnd of them
         * - else check the parent's 'up'/'down' property - if it's a function,
         *   call it with the cursor as the sole argument and use the return value.
         *
         *   Given undefined, will bubble up to the next ancestor block.
         *   Given false, will stop bubbling.
         *   Given a MathBlock,
         *     + moveUp will insAtRightEnd of it
         *     + moveDown will insAtLeftEnd of it
         *
         */ _ . moveUp = function ( ) { return moveUpDown ( this , 'up' ) ; } ; _ . moveDown = function ( ) { return moveUpDown ( this , 'down' ) ; } ; function moveUpDown ( self , dir ) { if ( self [ R ] [ dir ] ) self . insAtLeftEnd ( self [ R ] [ dir ] ) ; else if ( self [ L ] [ dir ] ) self . insAtRightEnd ( self [ L ] [ dir ] ) ; else { var ancestorBlock = self . parent ; do { var prop = ancestorBlock [ dir ] ; if ( prop ) { if ( typeof prop === 'function' ) prop = ancestorBlock [ dir ] ( self ) ; if ( prop === false || prop instanceof MathBlock ) { self . upDownCache [ ancestorBlock . id ] = Point ( self . parent , self [ L ] , self [ R ] ) ; if ( prop instanceof MathBlock ) { var cached = self . upDownCache [ prop . id ] ; if ( cached ) { if ( cached [ R ] ) { self . insLeftOf ( cached [ R ] ) ; } else { self . insAtRightEnd ( cached . parent ) ; } } else { var pageX = offset ( self ) . left ; self . insAtRightEnd ( prop ) ; self . seekHoriz ( pageX , prop ) ; } } break ; } } ancestorBlock = ancestorBlock . parent . parent ; } while ( ancestorBlock ) ; } return self . clearSelection ( ) . show ( ) ; } _ . seek = function ( target , pageX , pageY ) { clearUpDownCache ( this ) ; var cmd , block , cursor = this . clearSelection ( ) . show ( ) ; if ( target . hasClass ( 'empty' ) ) { cursor . insAtLeftEnd ( MathElement [ target . attr ( mqBlockId ) ] ) ; return cursor ; } cmd = MathElement [ target . attr ( mqCmdId ) ] ; if ( cmd instanceof Symbol ) { if ( target . outerWidth ( ) > 2 * ( pageX - target . offset ( ) . left ) ) cursor . insLeftOf ( cmd ) ; else cursor . insRightOf ( cmd ) ; return cursor ; } if ( ! cmd ) { block = MathElement [ target . attr ( mqBlockId ) ] ; if ( ! block ) { target = target . parent ( ) ; cmd = MathElement [ target . attr ( mqCmdId ) ] ; if ( ! cmd ) { block = MathElement [ target . attr ( mqBlockId ) ] ; if ( ! block ) block = cursor . root ; } } } if ( cmd ) cursor . insRightOf ( cmd ) ; else cursor . insAtRightEnd ( block ) ; return cursor . seekHoriz ( pageX , cursor . root ) ; } ; _ . seekHoriz = function ( pageX , block ) { var cursor = this ; var dist = offset ( cursor ) . left - pageX ; var leftDist ; do { cursor . moveLeftWithin ( block ) ; leftDist = dist ; dist = offset ( cursor ) . left - pageX ; } while ( dist > 0 && ( cursor [ L ] || cursor . parent !== block ) ) ; if ( - dist > leftDist ) cursor . moveRightWithin ( block ) ; return cursor ; } ; function offset ( self ) { var offset = self . jQ . removeClass ( 'cursor' ) . offset ( ) ; self . jQ . addClass ( 'cursor' ) ; return offset ; } _ . writeLatex = function ( latex ) { var self = this ; clearUpDownCache ( self ) ; self . show ( ) . deleteSelection ( ) ; var all = Parser . all ; var eof = Parser . eof ; var block = latexMathParser . skip ( eof ) . or ( all . result ( false ) ) . parse ( latex ) ; if ( block ) { block . children ( ) . adopt ( self . parent , self [ L ] , self [ R ] ) ; MathElement . jQize ( block . join ( 'html' ) ) . insertBefore ( self . jQ ) ; self [ L ] = block . ends [ R ] ; block . finalizeInsert ( ) ; self . parent . bubble ( 'redraw' ) ; } return this . hide ( ) ; } ; _ . write = function ( ch ) { var seln = this . prepareWrite ( ) ; return this . insertCh ( ch , seln ) ; } ; _ . insertCh = function ( ch , replacedFragment ) { this . parent . write ( this , ch , replacedFragment ) ; return this ; } ; _ . insertCmd = function ( latexCmd , replacedFragment ) { var cmd = LatexCmds [ latexCmd ] ; if ( cmd ) { cmd = cmd ( latexCmd ) ; if ( replacedFragment ) cmd . replaces ( replacedFragment ) ; cmd . createLeftOf ( this ) ; } else { cmd = TextBlock ( ) ; cmd . replaces ( latexCmd ) ; cmd . ends [ L ] . focus = function ( ) { delete this . focus ; return this ; } ; cmd . createLeftOf ( this ) ; this . insRightOf ( cmd ) ; if ( replacedFragment ) replacedFragment . remove ( ) ; } return this ; } ; _ . unwrapGramp = function ( ) { var gramp = this . parent . parent ; var greatgramp = gramp . parent ; var rightward = gramp [ R ] ; var cursor = this ; var leftward = gramp [ L ] ; gramp . disown ( ) . eachChild ( function ( uncle ) { if ( uncle . isEmpty ( ) ) return ; uncle . children ( ) . adopt ( greatgramp , leftward , rightward ) . each ( function ( cousin ) { cousin . jQ . insertBefore ( gramp . jQ . first ( ) ) ; } ) ; leftward = uncle . ends [ R ] ; } ) ; if ( ! this [ R ] ) { if ( this [ L ] ) this [ R ] = this [ L ] [ R ] ; else { while ( ! this [ R ] ) { this . parent = this . parent [ R ] ; if ( this . parent ) this [ R ] = this . parent . ends [ L ] ; else { this [ R ] = gramp [ R ] ; this . parent = greatgramp ; break ; } } } } if ( this [ R ] ) this . insLeftOf ( this [ R ] ) ; else this . insAtRightEnd ( greatgramp ) ; gramp . jQ . remove ( ) ; if ( gramp [ L ] ) gramp [ L ] . respace ( ) ; if ( gramp [ R ] ) gramp [ R ] . respace ( ) ; } ; _ . deleteDir = function ( dir ) { prayDirection ( dir ) ; clearUpDownCache ( this ) ; this . show ( ) ; if ( this . deleteSelection ( ) ) ; else if ( this [ dir ] ) { if ( this [ dir ] . isEmpty ( ) ) this [ dir ] = this [ dir ] . remove ( ) [ dir ] ; else this . selectDir ( dir ) ; } else if ( this . parent !== this . root ) { if ( this . parent . parent . isEmpty ( ) ) return this . insDirOf ( - dir , this . parent . parent ) . deleteDir ( dir ) ; else this . unwrapGramp ( ) ; } if ( this [ L ] ) this [ L ] . respace ( ) ; if ( this [ R ] ) this [ R ] . respace ( ) ; this . parent . bubble ( 'redraw' ) ; return this ; } ; _ . backspace = function ( ) { return this . deleteDir ( L ) ; } ; _ . deleteForward = function ( ) { return this . deleteDir ( R ) ; } ; _ . selectFrom = function ( anticursor ) { var oneA = this , otherA = anticursor ; loopThroughAncestors : while ( true ) { for ( var oneI = this ; oneI !== oneA . parent . parent ; oneI = oneI . parent . parent ) if ( oneI . parent === otherA . parent ) { left = oneI ; right = otherA ; break loopThroughAncestors ; } for ( var otherI = anticursor ; otherI !== otherA . parent . parent ; otherI = otherI . parent . parent ) if ( oneA . parent === otherI . parent ) { left = oneA ; right = otherI ; break loopThroughAncestors ; } if ( oneA . parent . parent ) oneA = oneA . parent . parent ; if ( otherA . parent . parent ) otherA = otherA . parent . parent ; } var left , right , leftRight ; if ( left [ R ] !== right ) { for ( var rightward = left ; rightward ; rightward = rightward [ R ] ) { if ( rightward === right [ L ] ) { leftRight = true ; break ; } } if ( ! leftRight ) { leftRight = right ; right = left ; left = leftRight ; } } this . hide ( ) . selection = Selection ( left [ L ] [ R ] || left . parent . ends [ L ] , right [ R ] [ L ] || right . parent . ends [ R ] ) ; this . insRightOf ( right [ R ] [ L ] || right . parent . ends [ R ] ) ; this . root . selectionChanged ( ) ; } ; _ . selectDir = function ( dir ) { prayDirection ( dir ) ; clearUpDownCache ( this ) ; if ( this . selection ) { if ( this . selection . ends [ dir ] === this [ - dir ] ) { if ( this [ dir ] ) this . hopDir ( dir ) . selection . extendDir ( dir ) ; else if ( this . parent !== this . root ) { this . insDirOf ( dir , this . parent . parent ) . selection . levelUp ( ) ; } } else { this . hopDir ( dir ) ; if ( this . selection . ends [ dir ] === this . selection . ends [ - dir ] ) { this . clearSelection ( ) . show ( ) ; return ; } this . selection . retractDir ( dir ) ; } } else { if ( this [ dir ] ) this . hopDir ( dir ) ; else { if ( this . parent === this . root ) return ; this . insDirOf ( dir , this . parent . parent ) ; } this . hide ( ) . selection = Selection ( this [ - dir ] ) ; } this . root . selectionChanged ( ) ; } ; _ . selectLeft = function ( ) { return this . selectDir ( L ) ; } ; _ . selectRight = function ( ) { return this . selectDir ( R ) ; } ; function clearUpDownCache ( self ) { self . upDownCache = { } ; } _ . prepareMove = function ( ) { clearUpDownCache ( this ) ; return this . show ( ) . clearSelection ( ) ; } ; _ . prepareEdit = function ( ) { clearUpDownCache ( this ) ; return this . show ( ) . deleteSelection ( ) ; } ; _ . prepareWrite = function ( ) { clearUpDownCache ( this ) ; return this . show ( ) . replaceSelection ( ) ; } ; _ . clearSelection = function ( ) { if ( this . selection ) { this . selection . clear ( ) ; delete this . selection ; this . root . selectionChanged ( ) ; } return this ; } ; _ . deleteSelection = function ( ) { if ( ! this . selection ) return false ; this [ L ] = this . selection . ends [ L ] [ L ] ; this [ R ] = this . selection . ends [ R ] [ R ] ; this . selection . remove ( ) ; this . root . selectionChanged ( ) ; return delete this . selection ; } ; _ . replaceSelection = function ( ) { var seln = this . selection ; if ( seln ) { this [ L ] = seln . ends [ L ] [ L ] ; this [ R ] = seln . ends [ R ] [ R ] ; delete this . selection ; } return seln ; } ; } ) ; var Selection = P ( MathFragment , function ( _ , _super ) { _ . init = function ( ) { var frag = this ; _super . init . apply ( frag , arguments ) ; frag . jQwrap ( frag . jQ ) ; } ; _ . jQwrap = function ( children ) { this . jQ = children . wrapAll ( '<span class="selection"></span>' ) . parent ( ) ; } ; _ . adopt = function ( ) { this . jQ . replaceWith ( this . jQ = this . jQ . children ( ) ) ; return _super . adopt . apply ( this , arguments ) ; } ; _ . clear = function ( ) { this . jQ . replaceWith ( this . jQ . children ( ) ) ; return this ; } ; _ . levelUp = function ( ) { var seln = this , gramp = seln . ends [ L ] = seln . ends [ R ] = seln . ends [ R ] . parent . parent ; seln . clear ( ) . jQwrap ( gramp . jQ ) ; return seln ; } ; _ . extendDir = function ( dir ) { prayDirection ( dir ) ; this . ends [ dir ] = this . ends [ dir ] [ dir ] ; this . ends [ dir ] . jQ . insAtDirEnd ( dir , this . jQ ) ; return this ; } ; _ . extendLeft = function ( ) { return this . extendDir ( L ) ; } ; _ . extendRight = function ( ) { return this . extendDir ( R ) ; } ; _ . retractDir = function ( dir ) { prayDirection ( dir ) ; this . ends [ - dir ] . jQ . insDirOf ( - dir , this . jQ ) ; this . ends [ - dir ] = this . ends [ - dir ] [ dir ] ; } ; _ . retractRight = function ( ) { return this . retractDir ( R ) ; } ; _ . retractLeft = function ( ) { return this . retractDir ( L ) ; } ; } ) ; /*********************************************************
     * The actual jQuery plugin and document ready handlers.
     ********************************************************/ jQuery . fn . mathquill = function ( cmd , latex ) { switch ( cmd ) { case 'redraw' : return this . each ( function ( ) { var blockId = $ ( this ) . attr ( mqBlockId ) , rootBlock = blockId && MathElement [ blockId ] ; if ( rootBlock ) { ( function postOrderRedraw ( el ) { el . eachChild ( postOrderRedraw ) ; if ( el . redraw ) el . redraw ( ) ; } ( rootBlock ) ) ; } } ) ; case 'revert' : return this . each ( function ( ) { var blockId = $ ( this ) . attr ( mqBlockId ) , block = blockId && MathElement [ blockId ] ; if ( block && block . revert ) block . revert ( ) ; } ) ; case 'latex' : if ( arguments . length > 1 ) { return this . each ( function ( ) { var blockId = $ ( this ) . attr ( mqBlockId ) , block = blockId && MathElement [ blockId ] ; if ( block ) block . renderLatex ( latex ) ; } ) ; } var blockId = $ ( this ) . attr ( mqBlockId ) , block = blockId && MathElement [ blockId ] ; return block && block . latex ( ) ; case 'text' : var blockId = $ ( this ) . attr ( mqBlockId ) , block = blockId && MathElement [ blockId ] ; return block && block . text ( ) ; case 'html' : return this . html ( ) . replace ( / ?hasCursor|hasCursor / , '' ) . replace ( / class=(""|(?= |>))/g , '' ) . replace ( /<span class="?cursor( blink)?"?><\/span>/i , '' ) . replace ( /<span class="?textarea"?><textarea><\/textarea><\/span>/i , '' ) ; case 'write' : if ( arguments . length > 1 ) return this . each ( function ( ) { var blockId = $ ( this ) . attr ( mqBlockId ) , block = blockId && MathElement [ blockId ] , cursor = block && block . cursor ; if ( cursor ) cursor . writeLatex ( latex ) . parent . blur ( ) ; } ) ; case 'cmd' : if ( arguments . length > 1 ) return this . each ( function ( ) { var blockId = $ ( this ) . attr ( mqBlockId ) , block = blockId && MathElement [ blockId ] , cursor = block && block . cursor ; if ( cursor ) { var seln = cursor . prepareWrite ( ) ; if ( /^\\[a-z]+$/i . test ( latex ) ) cursor . insertCmd ( latex . slice ( 1 ) , seln ) ; else cursor . insertCh ( latex , seln ) ; cursor . hide ( ) . parent . blur ( ) ; } } ) ; default : var textbox = cmd === 'textbox' , editable = textbox || cmd === 'editable' , RootBlock = textbox ? RootTextBlock : RootMathBlock ; return this . each ( function ( ) { createRoot ( $ ( this ) , RootBlock ( ) , textbox , editable ) ; } ) ; } } ; jQuery ( function ( ) { jQuery ( '.mathquill-editable:not(.mathquill-rendered-math)' ) . mathquill ( 'editable' ) ; jQuery ( '.mathquill-textbox:not(.mathquill-rendered-math)' ) . mathquill ( 'textbox' ) ; jQuery ( '.mathquill-embedded-latex' ) . mathquill ( ) ; } ) ; } ( ) ) ;