Louis Sherwood
Louis Sherwood

Reputation: 147

CKEditor SetData JQuery

I have a DropDownList where onChange sets the content of the TextArea which is my CKEditor control.

When the editor is not in use I run this bit of code for onChange:

$(".setBody").change(function() {
    //
    var className = "." + $(this).attr("sExternalId");
    var text = $(this).val();
    //
    $(className).val(text);
});

I'm not very experienced with Javascript/JQuery and I just can't figure out how to perform the same using CKEditor's setData() function. This is what I've tried:

$(".setCKBody").change(function() {
    //
    var className = "." + $(this).attr("sExternalId");
    var text = $(this).val();
    //
    var editor = $(className).ckeditorGet();
    editor.setData(text, function() {
        alert("The content was set");
    });
});

$(".setCKBody").change(function() {
    //
    var className = "." + $(this).attr("sExternalId");
    var text = $(this).val();
    //
    CKEDITOR.instances[$(className)].setData(text, function() {
        alert("The content was set");
    });
});

Am I close? I think one of the main limitations is that I have multiple editor controls with the same id and name, only the class can tell them apart which is why I'm using that with the JQuery. I've tried working through some examples online, but I'm not sure how to apply them to this scenario - that's probably my inexperience coming through there...

Thanks.

EDIT

This is how my textarea and dropdownlist appears in view source:

<textarea class="editArea M3" cols="20" id="Body" name="Body" rows="5">
    *some text*
</textarea>

<select class="setCKBody" id="Templates" name="Templates" sExternalId="M3">
    <option value="some value">Option 1</option>
    <option value="some value">Option 2</option>
</select>

The onChange event above is triggered from the dropDownList changing and is linked to the textArea via the "sExternalId" attribute. I realised I used "id" as the attribute name in the example above which was in error, so I changed that.

I use this to set it as a CKEditor control:

<script>CKEDITOR.replaceAll('editArea');</script>

I have between 2 to 6 textarea controls on the same page, created with razor like this:

@Html.TextAreaFor(m => m.Body, new { @class = "span12 editArea " + Model.ExternalId, rows = 5 })

They are contained within a partial view that is used like this:

@foreach (MailTemplateModel oTemplate in Model.Templates)
{
    @Html.Partial("_MailPartial", oTemplate)
}

This is why each text area has "Body" set as the id and name. I think this is the heart of the problem, with there being multiple elements with the same id and name CKEditor is not able to select the correct one. I've tried to do CKEDITOR.instances["className"] but that was undefined, whereas doing CKEDITOR.instances.Body did work, but would only ever return the same value.

I'm going to restructure the way the page is created to avoid this, hopefully my issues will be solved at the same time.

Upvotes: 1

Views: 9634

Answers (2)

Louis Sherwood
Louis Sherwood

Reputation: 147

My original approach to this scenario was all wrong, I had a model that contained multiple mail templates and so I rendered each one via a partial view within the same page so that the user could click to edit any one of them and the details would appear in a modal popup - within the same window. What I wanted to avoid was forcing the user to navigate to another window to edit a mail template, but this lead to multiple elements having the same id and name attributes which prevented me from accessing them correctly.

I've now added a list box where the user can select a template to edit, the selected template is rendered underneath and so avoids the multiple name and id issue. Now I know there is only ever 1 CKEditor control so I can access it in my js like this:

var editor = CKEDITOR.instances.SelectedTemplate_Body;

SelectedTemplate_Body is the name and id of the element I made into a CKEditor control. The onChange function I wrote for the dropdownlist is now written like this:

$(document).ready(function() {
    //
    $(".setBody").change(function() {
        //
        var templateId = $(this).val();
        //
        $.ajax({
            type: "GET",
            url: msHost + "MailTemplates/UpdateBody",
            data: { "templateId": templateId },
            cache: false,
            dataType: "text",
            success: function (data) {
                CKEDITOR.instances.SelectedTemplate_Body.setData(data);
            }
        })
    });
});

The tempalteId attribute is the value associated to the dropdownlist selection, this lets me know which template to use for setting the content of my editor control.

MailTemplates/UpdateBody points to a public method in my MailTemplates controller which runs a search on available mail templates and matches against the template Id passed in, the method then returns the body of the template as a string.

public string UpdateBody(string tempalteId)
{
    TemplateQuery oQuery;
    //
    oQuery = new TemplateQuery();
    oQuery.Execute();
    foreach (MailTemplate oTemplate in oQuery.Results)
        if (oTemplate.Id.Equals(templateId))
            return oTemplate.Body;
    //
    return string.Empty;
}

This line replaces the contents of the CKEditor control with the response from the controller method.

CKEDITOR.instances.SelectedTemplate_Body.setData(data);

Thanks @Nenotlep for trying to help out, you gave me a few things to think about there.

Upvotes: 0

Joel Peltonen
Joel Peltonen

Reputation: 13402

Here's a few pointers.

  1. Use class="foo" if you have many things that you refer to as a group, like like here it looks like you would have many setCKBody elements you listen to for change events.
  2. Use id="foo" if you have one single specific thing.
  3. Using the same id and class for one element usually is not the right thing to do.
  4. CKEDITOR.instances[xxx] <-- xxx should be a string, not a jquery object - so CKEDITOR.instances[className] might work better (I can't say not having seen your HTML).

It would help if we saw your HTML; textarea definitions and setCKBody definitions. Do you have many ckeditors and many setCKBody elements?

Upvotes: 2

Related Questions