Inline text editor

by Greg Bowler

HTML

<div class="editArea">
    <h1>This is a test title</h1>
    <p>
        This content is editable. Click edit below to start, and click Save to view the <b>ajax-returned</b> HTML.
    </p>
    <p>
        This is a second paragraph.
    </p>
</div>

<button id="btn_edit">Edit</button>
<button id="btn_save" disabled>Save</button>
<span id="status_save"></span>

CSS

.editArea{
    border: 3px double #aaa;
    min-height: 128px;
}
.editArea h1 {
    background: #ccf;
    padding: 8px;
}
.editArea p {
    padding: 8px;
}
.editArea[contenteditable] {
    background: #ffd;
    outline: 3px solid #fa5;
}
span#status_save {
    font-style: italic;
    color: #ccc;
}
span#status_save.saving {
    background: #f00;
    color: #fff;
    font-weight: bold;
}

.styleBox {
    overflow: hidden;
    height: 0;
    margin-bottom: 5px;
    background: #ddd;
    outline: 1px solid #aaa;
}

JavaScript

$(function() { TextEditor.init(); });

var TextEditor = new function() {
    var me = this;
    var currentEl = null;
    var styleEl = null;
    
    this.init = function() {
        styleEl = document.createElement("div");
        styleEl.className = "styleBox";

        $("#btn_edit").click(function() { edit(); });
        $("#btn_save").click(function() { save(); });
        $(".editArea").focus(function() {
            currentEl = this;
        });
        
        var boldButton = document.createElement("button");
        boldButton.className = "btn_bold";
        boldButton.innerHTML = "B";
        $(boldButton).appendTo(styleEl);
        
        var italicButton = document.createElement("button");
        italicButton.className = "btn_italic";
        italicButton.innerHTML = "I";
        $(italicButton).appendTo(styleEl);
        
        $(boldButton).click(function() { bold(); });
        $(italicButton).click(function() { italic(); });
    };
    
    var edit = function() {
        $(".editArea").attr("contenteditable", "true");
        $("#btn_edit").attr("disabled", "disabled");
        $("#btn_save").removeAttr("disabled");
        $("#status_save").text("");
        
        $(styleEl).insertBefore($(".editArea"));
        $(styleEl).animate(
            { height: "26px" },
            100);
    };
    
    var save = function() {
        $(".editArea").removeAttr("contenteditable");
        $("#btn_save").attr("disabled", "disabled");
        $("#status_save").text("SAVING...");
        $("#status_save").addClass("saving");
        
        $(styleEl).animate(
            { height: "0" },
            100);
        
        var editVal = $(".editArea").html();
        $.ajax({
            url: "/echo/html/",
            type: "POST",
            data: { html: editVal, delay: 0.5 },
            complete: function(data) {
                alert("Saved: \n" + data.responseText);
                $("#btn_edit").removeAttr("disabled");
               ...