7

Every time I type a character in an input field, I parse the expression so that I get:

  1. An array of tokens, i.e., tokenArray=[2, *, COS, (, 4, )]
  2. A corresponding array of token types, i.e., tokenType=[NUMBER, OPERATOR, FUNCTION, (, NUMBER, )]

I need to style each token (for instance assigning a different color to each token) based on its respective token type.

I have been able to easily style a dynamic copy of the input text in a different <div> (not the input text itself, which is what I am asking for help) as follows:

JavaScript:

function processExpression() {
    var userInput = document.getElementById('inputText').value;

        var resultOutput =  parse(userInput); //this generates the two arrays described above

        for (i in tokenArray) 
          newHTML += "<span style='color: " + colorMap[ tokenType[i] ] + " '>" +  tokenArray[i] + "</span>";

          document.getElementById('styledExpression').innerHTML = newHTML; 
}

HTML:

<input type="text" id="inputText" value="" placeholder="Type expression" size="40"
        onKeyDown="processExpression();" 
        onKeyUp="processExpression();"/>

<div id="styledExpression" value=""></div>

How can I style the input text directly in the input field where I type? Any JavaScript solution?

UPDATE

Tim's answer to the question replace innerHTML in contenteditable div provides some good help.

How would you modify http://jsfiddle.net/2rTA5/2/ to solve for when at every keydown, one reparses the entire editable? For example, imagine you type "=if(AND(3=2,A1:A4,OR(0,1)),5,6)" and, at every keydown the editable gets programmatically re-written (see token description above) and I lose the cursor.

How can this solution ignore the type of token or character or node and simply save and restore the absolute cursor (from the beginning of the ) position that was before the keydown?

Community
  • 1
  • 1
Gian
  • 549
  • 3
  • 7
  • 18
  • 2
    I actually just started working on something like this a couple hours ago! It's not easy, but what I have so far might help you get started: https://github.com/minitech/OpenEdit – Ry- May 05 '12 at 20:27
  • Alternatively, you can also try making the `` transparent and styling things behind it. This works best for background colors, but you can also make the text transparent to get simple styling effects. – Ry- May 05 '12 at 20:32

3 Answers3

6

Text inputs do not support styled content. End of story.

A common solution is to use contenteditable instead.

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
4

as Matt said, <input>s don't support styling content. However, one possible solution could be to use a second <span> that will contain the input's value, and show the styled content here. If that's not acceptable, then use contenteditable as Matt suggested.

Ry-
  • 218,210
  • 55
  • 464
  • 476
Luka Ramishvili
  • 889
  • 1
  • 11
  • 20
2

You can sort of hack styling behind it if it's just for unimportant aesthetics.

  • Make the background and the text of the <input> transparent
  • Have another <span> behind it
  • Update the content of the <span> (with appropriate styling) when the <input>'s contents change

Here's a quick demo.

Ry-
  • 218,210
  • 55
  • 464
  • 476
  • Simple and effective solution. Is there a way to see the cursor and avoid the blue border? Thanks – Gian May 07 '12 at 05:51
  • @Gian: Blue border? I'm not sure what you mean there... as for the cursor, there's no cross-browser solution, I'm afraid. If you only need it for WebKit, use `-webkit-text-fill-color: transparent;`; otherwise, you'll pretty much have to style it using background colors and nothing else. – Ry- May 07 '12 at 13:50
  • I meant the blue sky around the div field (the standard border showing focus on the element) – Gian May 07 '12 at 20:22
  • @Gian: Sure, just set `outline: none` on the ``. – Ry- May 08 '12 at 00:33