Question

I'm using TinyMCE 4.0.12 and I'm doing some dynamic inline editing. It's taken some research but I've got everything functioning now. My only issue is that it takes 2 clicks to get the TinyMCE toolbar to display. Here's what my simplified view (html looks like):

<script src="/Scripts/jquery-1.8.2.js"></script>
<script src="/Scripts/tinymce/tinymce.min.js"></script>
<script src="/Scripts/quantum.topics.js"></script>
<h1 id="title">@Model.Title</h1>
<div id="body">
    <p>@Model.Body</p>
    <p>@Model.Score</p>
    <p>@Model.CreatedBy</p>
    <p>@Model.CreatedDate</p>
</div>

My JQuery (quantum.topics.js):

var tinyMCEconfigs = [
{
    theme:                  "modern",
    mode:                   "none",
    language:               "en",
    inline:                 true,
    toolbar:                "undo redo",
    menubar:                false,
    browser_spellcheck:     true
},
{
    theme:                  "modern",
    mode:                   "none",
    language:               "en",
    inline:                 true,
    menubar:                false,
    browser_spellcheck:     true,
    plugins: [
                            "link"
    ],
    toolbar:                "undo redo | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link"
}
];

function addtinyMCE(type, selector) {
    //Only save and remove the current editor if we're active and we're switching controls
    if (tinymce.activeEditor && selector != tinymce.activeEditor.id) {
        tinymce.triggerSave();
        tinymce.execCommand('mceRemoveEditor', true, tinymce.activeEditor.id);
    }

    //Prevent adding the editor over and over
    if (!tinymce.activeEditor) {
        tinymce.settings = tinyMCEconfigs[type];
        tinymce.execCommand('mceAddEditor', false, selector);
        //tinymce.execCommand('mceFocus', false, selector);
        tinymce.activeEditor.execCommand('mceRepaint');
    }
}

$(function () {
    $('#title').click(function () {
        addtinyMCE(0, 'title');
    });
    $('#body').click(function () {
        addtinyMCE(1, 'body');
    });
});

I've tried using the mceFocus, I've tried passing 'true' for the mceAddEditor calls & I've tried using the mceRepaint. None seem to get the controls to appear, even though it is in edit mode. After the second click (even though none of the mce code is executed) the controls appear. It seems to be related to the cursor focus but I can't figure out how to fix it. If nothing else my example above may help someone who's stuck.

Was it helpful?

Solution

It seems my question has become a tumbleweed and I also don't need an answer anymore. I've solved this on my own by changing my approach. Instead of doing a direct inline edit when the user clicks on the #body or #title I've instead added an edit "button" (really a <span>) which toggles between edit/non-edit mode. Here's the new approach I took which ended up working really well:

On the page load I set up the edit "button":

$(function () {
    $('.edit').click(edit);
});

I set up the edit click event like this:

function edit() {
    //Make the title and header look editable
    $('#title').css({
        border: "1px dotted #333"
    });
    $('#body').css({
        border: "1px dotted #333"
    });

    //Detatch the 'edit' handler
    $('.edit').unbind();
    //Change it to a 'save' event
    $('.edit').html('Save').click(save);

    //Go into edit mode
    //Prevent adding the editor over and over
    if (!tinymce.activeEditor) {
        tinymce.init({
            selector: "#title",
            theme: "modern",
            language: "en",
            inline: true,
            toolbar: "undo redo",
            menubar: false,
            browser_spellcheck: true
        });

        tinymce.init({
            selector: "#body",
            theme: "modern",
            language: "en",
            inline: true,
            menubar: false,
            browser_spellcheck: true,
            plugins: [
                                "link"
            ],
            toolbar: "undo redo | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link"
        });
    }
}

While in edit mode the button becomes a 'save'. The save event sends an asyn Json response to the controller and is handled like this:

function save() {
    //Make the title and header look non-editable
    $('#title').css({
        border: "none"
    });
    $('#body').css({
        border: "none"
    });

    //Detatch the 'edit' handler
    $('.edit').unbind();
    //Change it to a 'edit' event
    $('.edit').html('Edit').click(edit);

    //Disable edit mode
    //Only remove the current editor if it's active
    if (tinymce.activeEditor) {
        tinymce.triggerSave();

        tinymce.execCommand('mceRemoveEditor', true, 'title');
        tinymce.execCommand('mceRemoveEditor', true, 'body');
    }

    //Persist to DB
    try {
        var title = $('#title').html();
        var body = $('#body').html();
        $.ajax({
            url: Routings.TopicSave,
            type: 'POST',
            contentType: 'application/json',
            data: JSON.stringify({
                ID: parseInt(TopicID, 10),
                Title: title,
                Body: body
            })
        });
    } catch (err) {
        alert(err);
    }
}

I've omitted the "cancel" functionality example as it doesn't add any value to this question, but if you're interested you can see an example here: Handle discard changes with TinyMCE

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top