views:

276

answers:

2

Scenario: I have a standard dropdown list and when the value in that dropdownlist changes I want to update another dropdownlist that exists in a tinyMCE control.

Currently it does what I want when I open the page (i.e. the first time)...

function changeParent() {

    }

tinymce.create('tinymce.plugins.MoePlugin', {
            createControl: function(n, cm) {
                switch (n) {
                    case 'mylistbox':
                        var mlb = cm.createListBox('mylistbox', {
                            title: 'Inserts',
                            onselect: function(v) {
                                tinyMCE.execCommand("mceInsertContent",false,v);                                                                
                            }
                        });

                        <% foreach (var insert in (ViewData["Inserts"] as List<String>)) { %> // This is .NET 
                            yourobject = '<%= insert %>'; // This is JS AND .NET
                            mlb.add(yourobject, yourobject); // This is JavaScript
                        <% } %>                       

                        // Return the new listbox instance
                        return mlb;
                }
                return null;
            }
        });             


<%= Html.DropDownList(Model.Record[184].ModelEntity.ModelEntityId.ToString(), ViewData["Containers"] as SelectList, new { onchange = "changeParent(); return false;" })%>

I am thinking the way to accomplish this (in the ChangeParentFunction) is to call a controller action to get a new list, then grab the 'mylistbox' object and reassign it, but am unsure how to put it all together.

+1  A: 

As far as updating the TinyMCE listbox goes, you can try using a tinymce.ui.NativeListBox instead of the standard tinymce.ui.ListBox. You can do this by setting the last argument to cm.createListBox to tinymce.ui.NativeListBox. This way, you'll have a regular old <select> that you can update as you normally would.

The downside is that it looks like you'll need to manually hook up your own onchange listener since NativeListBox maintains its own list of items internally.

EDIT:

I played around a bit with this last night and here's what I've come up with.

First, here's how to use a native list box and wire up our own onChange handler, the TinyMCE way:

// Create a NativeListBox so we can easily modify the contents of the list.
var mlb = cm.createListBox('mylistbox', {
    title: 'Inserts'
}, tinymce.ui.NativeListBox);

// Set our own change handler.
mlb.onPostRender.add(function(t) {
    tinymce.dom.Event.add(t.id, 'change', function(e) {
        var v = e.target.options[e.target.selectedIndex].value;
        tinyMCE.activeEditor.execCommand("mceInsertContent", false, v);
        e.target.selectedIndex = 0;
    });
});

As far as updating the list box at runtime, your idea of calling a controller action to get the new items is sound; I'm not familiar with ASP.NET, so I can't really help you there.

The ID of the <select> that TinyMCE creates takes the form editorId_*controlId*, where in your case controlId is "mylistbox". Firebug in Firefox is the easiest way to find the ID of the <select> :)

Here's the test button I added to my page to check if the above code was working:

<script type="text/javascript">
function doFoo() {
    // Change "myEditor" below to the ID of your TinyMCE instance.
    var insertsElem = document.getElementById("myEditor_mylistbox");

    insertsElem.options.length = 1;  // Remove all but the first option.

    var optElem = document.createElement("option");
    optElem.value = "1";
    optElem.text = "Foo";
    insertsElem.add(optElem, null);

    optElem = document.createElement("option");
    optElem.value = "2";
    optElem.text = "Bar";
    insertsElem.add(optElem, null);
}
</script>
<button onclick="doFoo();">FOO</button>

Hope this helps, or at least gets you started.

ZoogieZork
Sounds intreging, I a a bit of a javascript noob, however. Can you give me an example please.
Grayson Mitchell
Thanks ZoogieZork, I will have another coffee and give it a go!
Grayson Mitchell
I get an error: htmlfile: Type mismatch. on the "insertsElem.add(optElem, null);" statement
Grayson Mitchell
Stepping through to that point I can see all of the original list items, then see all but the first one being deleted (length = 1), so its good up until that point.
Grayson Mitchell
Ah, looks like IE handles `add()` on a select element slightly differently than other browser. http://www.coderanch.com/t/119339/HTML-JavaScript/What-s-Wrong-With-My
ZoogieZork
Great, that worked, thanks for the help
Grayson Mitchell
+1  A: 

Step 1 - Provide a JsonResult in your controller

    public JsonResult GetInserts(int containerId)
    {
        //some code to get list of inserts here 
        List<string> somedata = doSomeStuff();

        return Json(somedata);
    }

Step 2 - Create javascript function to get Json results

function getInserts() {
    var params = {};
    params.containerId = $("#184").val();
    $.getJSON("GetInserts", params, updateInserts);
};

updateInserts = function(data) {
    var insertsElem = document.getElementById("183_mylistbox");

    insertsElem.options.length = 1;  // Remove all but the first option.

    var optElem = document.createElement("option");
    for (var item in data) {
        optElem = document.createElement("option");
        optElem.value = item;
        optElem.text = data[item];

        try {  
            insertsElem.add(optElem, null); // standards compliant browsers  
        }  
        catch(ex) {  
            insertsElem.add(optElem, item+1); // IE only (second paramater is the items position in the list) 
        }
    }
};

Step 3 - Create NativeListBox (code above provided by ZoogieZork above)

var mlb = cm.createListBox('mylistbox', {
    title: 'Inserts'
}, tinymce.ui.NativeListBox);

// Set our own change handler.
mlb.onPostRender.add(function(t) {
    tinymce.dom.Event.add(t.id, 'change', function(e) {
        var v = e.target.options[e.target.selectedIndex].value;
        tinyMCE.activeEditor.execCommand("mceInsertContent", false, v);
        e.target.selectedIndex = 0;
    });
});

//populate inserts on listbox create
getInserts();  
Grayson Mitchell