Modify latex expression with Mathjax (HTMLcreateSpan)

1,009 views
Skip to first unread message

rodrigu...@gmail.com

unread,
Dec 28, 2011, 4:51:50 AM12/28/11
to mathja...@googlegroups.com
Hello,

I've got some ideas about how to edit math with MathJax without modifying a lot of codes...
Each element of an expression is translated to a <span />.

If we add on each span a javascript function which generates an event every time the mouse click on it, we can change the background of this span and we can add an indication which says where this expression is located in our latex expression.
If the user presses a key we can insert the new key at this location in the latex expression and update the display... If he presses "Backspace" we delete the latex expression at this location. If the expression is per example: \Omage \; \sqrt{a^2 + b^2} and the user has put his cursors at right of the expression we delete all the \sqrt{} block in the latex expression.

Any ideas how to do such a thing, please?

I think I have to modify the function HTMLcreateSpan.

Sorry I didn't find the way to insert code in this forum!


[code]
<div id="MathOutput">
You typed:
<span class="MathJax_Preview" style="display: none;"></span>
<div class="MathJax_Display" style="width: 100%; position: relative; text-align: center;" role="textbox" aria-readonly="true">
<span class="MathJax" style="">
<nobr>
<span id="MathJax-Span-193" class="math">
<span style="display: inline-block; position: relative; width: 2.295em; height: 0pt; font-size: 207%;">
<span style="position: absolute; top: -2.782em; left: 0em; clip: rect(2.026em, 1000em, 2.955em, -0.231em);">
<span id="MathJax-Span-194" class="mrow">
<span id="MathJax-Span-195" class="mrow">
<span id="MathJax-Span-196" class="texatom">
<span id="MathJax-Span-197" class="mrow">
<span id="MathJax-Span-198" class="mn" style="font-family: MathJax_Main;">3</span>
<span id="MathJax-Span-199" class="mo" style="font-family: MathJax_Main; padding-left: 0.222em;">+</span>
<span id="MathJax-Span-200" class="mi" style="font-family: MathJax_Math; font-style: italic; padding-left: 0.222em;">x</span>
</span>
</span>
</span>
</span>
<span style="display: inline-block; width: 0pt; height: 2.782em;"></span>
</span>
</span>
<span style="border-left: 0em solid; display: inline-block; overflow: hidden; width: 0pt; height: 1.548em; vertical-align: -0.172em;"></span>
</span>
</nobr>
</span>
</div>
<script id="MathJax-Element-1" type="math/tex; mode=display">
\displaystyle{3+x}
</script>
[/code]

If I look to the source code,

In jax.js (.\js\mathjax\unpacked\jax\output\HTML-CSS)

[code]
Translate: function (script) {
if (!script.parentNode) return;
var prev = script.previousSibling;
if (prev && String(prev.className).match(/^MathJax(_MathML|_Display)?$/))
{prev.parentNode.removeChild(prev)}
var math = script.MathJax.elementJax.root, span, div, frame;
span = div = frame = this.Element("span",{
className:"MathJax", oncontextmenu:this.ContextMenu, onmousedown: this.Mousedown,
onmouseover:this.Mouseover, onclick:this.Click, ondblclick:this.DblClick
});

...

try {math.toHTML(span,div)} catch (err) {
if (err.restart) {frame.parentNode.removeChild(frame)}
throw err;
}
if (isHidden) {script.parentNode.insertBefore(frame,script)}
if (this.useProcessingFrame) frame.parentNode.replaceChild(div,frame);
[/code]


jump to math.toHTML:

[code]
MML.math.Augment({
toHTML: function (span,node) {
var alttext = this.Get("alttext"); if (alttext) {node.setAttribute("aria-label",alttext)}
var nobr = HTMLCSS.addElement(span,"nobr");
span = this.HTMLcreateSpan(nobr);
var stack = HTMLCSS.createStack(span), box = HTMLCSS.createBox(stack), math;
// Move font-size from outer span to stack to avoid line separation
// problem in strict HTML mode
stack.style.fontSize = nobr.parentNode.style.fontSize; nobr.parentNode.style.fontSize = "";

...
[/code]

jump to HTMLcreateSpan:

[code]
HTMLcreateSpan: function (span) {
if (this.spanID) {
var SPAN = this.HTMLspanElement();
if (SPAN) {
while (SPAN.firstChild) {SPAN.removeChild(SPAN.firstChild)}
SPAN.bbox = {w:0, h:0, d:0, lw:0, rw:0};
SPAN.scale = 1; SPAN.isMultChar = null;
SPAN.style.cssText = "";
return SPAN;
}
}
if (this.href) {span = HTMLCSS.addElement(span,"a",{href:this.href})}
...
[/code]

Davide P. Cervone

unread,
Dec 29, 2011, 9:33:19 AM12/29/11
to mathja...@googlegroups.com
I think this is probably not the best approach.

First, you don't have to have event handlers on the individual spans, as you can have a single one on a container element and it will get fired when the event happens on any of the descendants.  That saves a lot of complication in terms of canceling events and so on, as you would have to do if you had handlers on each span (remember that events fire for all the children of an element, not just the element itself).

Second, the structure of the output is based on the underlying MathML (the TeX has been converted to MathML internally).  Many of the MathML elements are handled by producing multiple spans, so you would have to deal with elements that are not created by HTMLcreateSpan(), but could generate events anyway.

Third, because most of the elements used by MathJax's HTML-CSS output are spans, their heights will not necessarily correspond to the heights of their content (since spans typically have height and depth equal to that of a normal line of text regardless of their content).  So the span for a fraction, for instance, will not be as tall as the fraction itself, and if you set the background color, it likely will not cover the complete fraction.  (It also means the clickable regions may be a bit odd as well.)

Fourth, the routines you mention are in the deep internals of MathJax, and are not guaranteed to remain unchanged during updates.  Indeed, theses routines have been substantially updated in v2.0.  If you make modifications to them, you may have trouble upgrading to newer versions of MathJax, and may have to re-engineer your code.  There are some parts of MathJax that are designed to be overridden by user code, but this is not one of them.

Fifth, as mentioned above, the TeX output is first converted to MathML internally, and it is actually the MathML that is being displayed.  The mapping back to original TeX code is not always clear, especially if the TeX code includes macros.  The mouse clicks you receive will be within the MathML structure, not the TeX structure, and so you will have to deal with the reverse maping from MathML to TeX in some way.


It is not clear from your message exactly what you have in mind as an end result.  If you are trying to take an arbitrary TeX string and edit that visually, I think you are going to find that difficult.  If you are working on an equation editor that can produce TeX output, that is a different story, since you will be handling TeX that you generated, not arbitrary TeX code.

if it is the latter case, then I would recommend not using TeX as your internal format (that is, don't tie the editing to the TeX string itself).  I would suggest using a tree structure that more naturally represents the underlying mathematics (like MathML does), and generate the required TeX code from that (that is a pretty straight-forward process, in general).  Unless the user can see the TeX string and they see that they are editing that, then I don't see any reason why you should be thinking about editing TeX strings internally.  Edit the mathematical representation, and generate TeX strings from that.


In any case, the mouse click and background color changing can be done without modifying the MathJax code.  I have placed an example at


There you will see two displayed equations.  If you click in the first, the element you clicked on will have its background changed to red, and you will see the elements ID show up in the output area at the bottom of the page.  These are MathJax internal markers, so are not very meaningful.  The second equation, however, has been marked by custom ID's so that when you click on an element, a more descriptive ID is displayed.  This is one method that can be used to handle the reverse mapping from the MathML back to the TeX.  It uses the \cssID extension to mark each letter and operator with an identifier that you can use to map back to your internal mathematical representation.  Note that this can be done without any modification to MathJax itself, but it does require a more complicated TeX string.  That is another reason to not use TeX strings as your internal format.  You want to be able to produce this ID-tagged TeX string to send to MathJax while you are editing the equation, but you also want to be able to produce the untagged TeX string for display to the user and as the final output of your editor.

Anyway, those are my suggestions on the topic.

Davide

Chung-Yi

unread,
Feb 13, 2012, 12:16:23 AM2/13/12
to MathJax Users
Thanks! This is really helpful.

I'm trying to make a WYSIWYG equation editor. It looks like MathJax
only allows me to modify the entire math element, not individual
identifier, operator, and so on. So I guess I have to do it myself.
I'm wondering what the best way is to associate my internal
representation of the equation (like the tree structure you suggested)
with the html rendered by MathJax so that when a user modify a number
I can modify the internal structure accordingly.

Thanks in advance!
>        http://www.math.union.edu/locate/Cervone/transfer/mathjax/test-mousec...
>
> There you will see two displayed equations.  If you click in the
> first, the element you clicked on will have its background changed to
> red, and you will see the elements ID show up in the output area at
> the bottom of the page.  These are MathJax internal markers, so are
> not very meaningful.  The second equation, however, has been marked by
> custom ID's so that when you click on an element, a more descriptive
> ID is displayed.  This is one method that can be used to handle the
> reverse mapping from the MathML back to the TeX.  It uses the \cssID
> extension to mark each letter and operator with an identifier that you
> can use to map back to your internal mathematical representation.
> Note that this can be done without any modification to MathJax itself,
> but it does require a more complicated TeX string.  That is another
> reason to not use TeX strings as your internal format.  You want to be
> able to produce this ID-tagged TeX string to send to MathJax while you
> are editing the equation, but you also want to be able to produce the
> untagged TeX string for display to the user and as the final output of
> your editor.
>
> Anyway, those are my suggestions on the topic.
>
> Davide
>

Davide P. Cervone

unread,
Feb 13, 2012, 7:29:23 AM2/13/12
to mathja...@googlegroups.com
> I'm trying to make a WYSIWYG equation editor. It looks like MathJax
> only allows me to modify the entire math element, not individual
> identifier, operator, and so on.

That is correct.

> I'm wondering what the best way is to associate my internal
> representation of the equation (like the tree structure you suggested)
> with the html rendered by MathJax so that when a user modify a number
> I can modify the internal structure accordingly.

I already suggested one approach, which is to use \cssId{id}{math} to
mark the elements so that you can map back to your internal
structure. Your ID can be used as an index into a hash that points to
the math elements internally, or it could be a sequence of indices for
a tree structure (e.g. \cssId{1,2,0,1}{x}), or anything you can use to
identify your internal structure. The example I gave already shows
how to recover these id's from the clicks.

Davide

markd...@gmail.com

unread,
Apr 25, 2012, 7:18:37 AM4/25/12
to mathja...@googlegroups.com
I'm looking into this as well.  The demo is helpful.  Thanks.  However, the biggest hurdle I see is the "Third" item written by Davide.  This almost seems like a show stopper.  If you can't easily know the "border-box" of an element, for instance, a fraction, it will not be possible to show it has the focus or make a caret as tall as it.  I would have thought with the use of display:inline-block, this would not be an issue, but there seems to be something I'm missing.  I tried tweaking the CSS of your sample in chrome to see if I can get the fraction box to grow, but I haven't been successful yet.  

I tried a simple example using MathQuill "\sqrt x/y".  This produced mark-up, be it much simpler, that maintained the size.  I guess because MathJax is primarily concerned with making formulas look "really good", the mark-up becomes more complicated and will ultimately cause issues like this.

I was really hoping to write a WYSIWYG editor on top of MathJax, but I 'm starting to think, that it may not be a realistic goal. 

elvi...@gmail.com

unread,
Jan 21, 2015, 8:59:15 PM1/21/15
to mathja...@googlegroups.com
i need that example's code, can you give de code pls

Davide P. Cervone

unread,
Jan 22, 2015, 8:27:46 AM1/22/15
to mathja...@googlegroups.com
The example code is in the link given in the message that you quote:


View the document source to see the code (it is near the bottom of the page).

Davide


--
You received this message because you are subscribed to the Google Groups "MathJax Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mathjax-user...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Elvin Lazo

unread,
Jan 22, 2015, 11:07:01 AM1/22/15
to mathja...@googlegroups.com

I got it. Thanks

You received this message because you are subscribed to a topic in the Google Groups "MathJax Users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/mathjax-users/fRGv6pcCXiA/unsubscribe.
To unsubscribe from this group and all its topics, send an email to mathjax-user...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages