Basj
Basj

Reputation: 46463

Convert innerHTML of a contenteditable text to normal string

I use a content-editable element :

<span id="myinput" contenteditable="true">This is editable.</span>

and

document.getElementById('myinput').innerHTML

to read its content from Javascript.

But the result is :

How to convert innerHTML into normal text?

(i.e. in my 2 examples : "blah " and "bonjour\n bonsoir")

Upvotes: 10

Views: 38039

Answers (3)

jstaab
jstaab

Reputation: 3855

Here's my answer — it's not perfect, sometimes line breaks get dropped, but I found so little information on this maybe it'll help someone.

  const parseNode = node => {
    let content = ""

    for (const child of node.childNodes) {
      if (child.tagName === "BR") {
        content += "\n"
      }

      if (child.tagName === "DIV" && !child.querySelector("br")) {
        content += "\n"
      }

      if (child instanceof Text) {
        content += child.textContent
      } else {
        content += parseNode(child)
      }
    }

    return content
  }

Upvotes: 0

EvilEpidemic
EvilEpidemic

Reputation: 469

Try using;

// for IE
document.getElementById('myinput').innerText

// for everyone else
document.getElementById('myinput').textContent

In terms of finding linebreaks, etc, consider;

el = document.getElementById('myinput');
var nodes = el.childNodes;
var text = '';

for(var i = 0; i < nodes.length; i++) {                        
    switch(nodes[i].nodeName) {
        case '#text'    : text = text + nodes[i].nodeValue;   break;
        case 'BR'       : text = text + '\n';      break;
    }
}
console.log(text);

Upvotes: 9

Bart
Bart

Reputation: 27205

Due to the fact this behaviour is not consistent in different browsers, you have to implement this yourself:

var convert = (function() {
    var convertElement = function(element) {
        switch(element.tagName) {
            case "BR": 
                return "\n";
            case "P": // fall through to DIV
            case "DIV": 
                return (element.previousSibling ? "\n" : "") 
                    + [].map.call(element.childNodes, convertElement).join("");
            default: 
                return element.textContent;
        }
    };

    return function(element) {
        return [].map.call(element.childNodes, convertElement).join("");
    };
})();

In action: http://jsfiddle.net/koyd8h59/1/

Of course you'll need to add your own code if you want to use <h1> and other block-level tags.

Upvotes: 1

Related Questions