Search code examples
javascripthtmlmathjax

Right cursor position between MathJax formulas


I have some trouble with inserting MathJax formulas. I want that user can insert cursor between each formulas and therefore can insert formula between them.

My code:

function get(elem) 
{
    currentFormul = elem;
    var math = MathJax.Hub.getAllJax(elem)[0];
    var input = document.getElementById("MathInput");
    input.value = math.originalText;
}
function input()
{
    sel = window.getSelection();
    var range = sel.getRangeAt(0); 
    var input = document.getElementById("MathInput");
    var span = document.createElement("span");
    span.contentEditable="false";
    span.addEventListener('click', function() { get(this); }, true);
    span.innerHTML = "\\("+input.value+"\\)";
    range.insertNode(span); 
    MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
}  
</script>
   <body contenteditable="true" spellcheck="false"> 
        <span contenteditable="false">
            <button onclick="change()">Change!</button>
            <input id="MathInput" size="60" />
            <button onclick="input()">INPUT!</button>
            <button onclick="someChanges()">FONT!</button>
        </span>   
        <p>S</p>
        <span onclick="get(this)" contentEditable="false">\(\color{red}{x=ax^2}\)</span>
        <span onclick="get(this)" contentEditable="false">\(x=ax^2\)</span>
        <span onclick="get(this)" contentEditable="false">\(x=ax^2\)</span>
    </body>
</html>

Now i can't insert cursor between formula for new elements, but can for old. Can someone tell me how do this right?


Solution

  • There are white spaces between the spans in your html. These white spaces are in fact text node that are child of body, which has contenteditable set to true. So when you click on one of these text nodes, you click in a contenteditable node, hence you get a cursor.

    When you add spans dynamically, it adds it without white space. There's a text node created, but it's empty so you can't click it.

    One easy way to fix this would be to set the text node before your newly inserted spans to " ". It'll then have the same behavior as your old elements. Like this:

    function input()
    {
        sel = window.getSelection();
        var range = sel.getRangeAt(0); 
        var input = document.getElementById("MathInput");
        var span = document.createElement("span");
        span.contentEditable="false";
        span.addEventListener('click', function() { get(this); }, true);
        span.innerHTML = "\\("+input.value+"\\)";
        range.insertNode(span); 
        span.previousSibling.textContent = " ";
        MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
    }  
    

    http://jsfiddle.net/ox20a7oj/