prevent contenteditable mode from creating tags

前端 未结 5 1257
别跟我提以往
别跟我提以往 2020-12-15 05:03

When I use the browser contenteditable=true on a div in order to let the user update the text in it, I run into this problem (using Chrome):

When using the delete

相关标签:
5条回答
  • 2020-12-15 05:30

    Here is how I solved this

    jquery remove <span> tags while preserving their contents (and replace <divs> and <p>:s with <br>)

    I preserve the text of all div, span and p tags, remove those tags, and substitute all div and p with a br. I do it on blur, optimal would be to do it on every keydown, but that is eating too much cpu since I have to loop through all these %#¤¤%& (you said it) nested elements.

    0 讨论(0)
  • 2020-12-15 05:43

    For now, I am using

            $(textObject).find('*').removeAttr('style');
    

    upon deselect of the editable region.

    It could also be used upon keyup.

    0 讨论(0)
  • 2020-12-15 05:45

    Add style display:inline-block; to contenteditable, it will not generate div, p, span automatic in chrome

    0 讨论(0)
  • 2020-12-15 05:47

    The problem is, actually, that not only it inserts span's and p's, but if you happen to copy a table it will insert the whole table with tbody and rows there. So, the only option to handle this that I've found working for me is this:

    $(document).on("DOMNodeInserted", $.proxy(function (e) {
            if (e.target.parentNode.getAttribute("contenteditable") === "true") {
                with (e.target.parentNode) {
                    replaceChild(e.target.firstChild, e.target);
                    normalize();
                }
            }
    }, this));
    

    Yes, it somewhat affects the overal page performance, but it blocks inserting tables and stuff into the contenteditables.

    UPDATE:
    The script above handles only basic cases, when the content you wish for is wrapped in one level of span/p tags. However, if you copy from, say, Word, you may end up copying even the whole tables. So, here is the code that handles everything i've thrown at it so far:

    $(document).on("DOMNodeInserted", $.proxy(function (e) {
        if (e.target.parentNode.getAttribute("contenteditable") === "true") {
            var newTextNode = document.createTextNode("");
            function antiChrome(node) {
                if (node.nodeType == 3) {
                    newTextNode.nodeValue += node.nodeValue.replace(/(\r\n|\n|\r)/gm, "")
                }
                else if (node.nodeType == 1 && node.childNodes) {
                        for (var i = 0; i < node.childNodes.length; ++i) {
                            antiChrome(node.childNodes[i]);
                        }
                }
            }
            antiChrome(e.target);
    
            e.target.parentNode.replaceChild(newTextNode, e.target);
        }
    }, this));
    

    Also, feel free to modify the regex in the middle any way you like to remove symbols that are particularly hazardous in your case.

    UPDATE 2
    After thinking for a little while and googling, I've just wrapped the code above into simple jQuery plugin to ease the usage. Here is the GitHub link

    0 讨论(0)
  • 2020-12-15 05:47

    Man, the timing on this question is crazy. What I'm doing with contenteditable is forcing all the content to be within paragraph tags, of the contenteditable div.

    So the way I handle this bullshit spans that get created is by flattening every <p> on every keystroke.

    Since .text() selects ALL the text of an element, including its subelements, I can just set (in coffeescript)

    t = $(element).text()
    $(element).children().remove()
    $(element).text(t)
    

    Which solves my problem. As an aside, these browser implementers really botched contenteditable pretty bad. There is a massive opportunity here to make this easy, because it really is the future of the web.

    0 讨论(0)
提交回复
热议问题