Question

I use Google Chrome.

I need to have a very tiny HTML editor and I found Simple Edit. Very small editor, just for my needs. However... This and many other editors that are using Content Editable have one common problem.

Problem

After creating a list (hit enter twice on last list item), it creates a new div. Expected to me would be to create a new paragraph tag.

Links

Question

What is the correct way of prevent divs, and instead add paragraph tags after a list?

Was it helpful?

Solution

The answer posted by Bryan Allo did not take into account that you need to place the cursor at the end of the div. Otherwise upon every replace action the user would have to hit CTRL-End.

This is the solution I propose, also to be seen in action at http://jsfiddle.net/82dS6/:

function setEndOfContenteditable(contentEditableElement){
    // Taken from http://stackoverflow.com/a/3866442/1601088
    var range,selection;
    if(document.createRange){//Firefox, Chrome, Opera, Safari, IE 9+
        range = document.createRange();
        range.selectNodeContents(contentEditableElement);
        range.collapse(false);
        selection = window.getSelection();
        selection.removeAllRanges();
        selection.addRange(range);
    }
    else if(document.selection){//IE 8 and lower
        range = document.body.createTextRange();
        range.moveToElementText(contentEditableElement);
        range.collapse(false);
        range.select();
    }
}

function replaceDivWithP(el){

    $(el).find('div').each(function(){
        $(this).replaceWith($('<p>' + $(this).html() + '</p>'));
    });
}

$(function(){
    $(".text").simpleEdit();
});

$('.textarea').bind('keyup', function(){
    replaceDivWithP(this);
    setEndOfContenteditable(this);
});


​

OTHER TIPS

Instead of processing on-the-fly with every keyup event, you could consider post-processing:

$('.textarea').bind('blur', function(){
    $('.textarea div').contents().unwrap().wrap('<p/>');
});

Fiddle: http://jsfiddle.net/thNUS/4/

A quick solution is to simply replace any DIVs with Ps. Place this inside your content editable DIV.

onkeyup="this.innerHTML=this.innerHTML.replace('div','p')"

Hope it helps. Good luck.

The best I could come up with was to use formatblock which has compatibility issues. Basically you could add another link like so:

textcontainer.prepend("<button class='paragraph'>p</button>");

...

$(".paragraph").live("click", function(){
    document.execCommand('formatblock', false, "p");
});

This gives your users the option to insert a paragraph tag. Getting out of that tag is a bit tricky though, so it has some usability issues too. You can play with it on the provided demo:

Demo: http://jsbin.com/ovexiz/1
Source: http://jsbin.com/ovexiz/1/edit

*note that paragraphs are styled with green colored text.

Previous answers proposed a keyup or blur based solution. This one uses the click event of the list button to minimize the amount of function calls:

http://jsfiddle.net/9ZAL7/:

function replaceDivWithP(el){

    $(el).find('div').each(function(){
        $(this).replaceWith($('<p>' + $(this).html() + '</p>'));
    });
}

$(function(){
    $(".text").simpleEdit();
});

$('button.list').bind('click', function(){
    replaceDivWithP($('.textarea'));
});
​
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top