views:

56

answers:

2

So I have a TinyMCE form on my page and it is pre-filled with "sections" (divs with specific class names).

I have a couple of plugins that will add to TinyMCE with more "sections".

I need it so when I push the plugin button it will test to make sure the cursor is not inside a "section" and paste a "section" inside another "section".

Not sure the direction I need to take to accomplish this. Any help would be great.

more info: So below is an example of a plugin that adds a button that just inserts a simple dov into the editor at the selection/cursor.

ed.addButton('pluginbutton', {
    title : 'MyPlugin',
    image : 'img/test.png',
    onclick : function() {
        ed.selection.setContent('<div>test</div>');
    }
});

I am currently thinking that onBeforeSetContent is the API event handler I need to set to process whether or not I am in another section and if so send a message to the screen. If not just do the setContent method. I am not sure exactly how to set that up though so I am still figuring that out. Any help here?

+1  A: 

I don't know TinyMCE specifically, but it should be possible to extract the current DOM element from ed.selection. If that is possible (I'm sure it is using some sort of getter function or property), you should be able to do the following:

  • Mark a "forbidden" area using an id or class ("<div class='protected'> ")
  • traverse through the selection's ancestry (using the parentNode property of the element) and check whether one of the parent elements has the "protected" class or ID.
  • If the ID was found, do not execute setContent(); otherwise execute it.
Pekka
+1 Great outline. You are right, the `selection.getNode()` returns the context DOM element.
Doug Neiner
+3  A: 

Since it seems like you have control over the plugin, here is how I would edit it to work.

Note: I am using the jQuery method closest. I figured since you are on the jQuery core team, you are probably using it for this project. If not, just refactor that line as needed. The important part is that selection.getNode() returns the DOM element that is the parent of both the start and end selection points.:

ed.addButton('pluginbutton', {
    title : 'MyPlugin',
    image : 'img/test.png',
    onclick : function() {
        if( !$(ed.selection.getNode()).closest('div.section').length ){
            ed.selection.setContent('<div class="section">test</div>'); 
        }
    }
});

Additional thoughts

Also, to make your plugin aware enough so it won't put a div as the child of a p tag, you could do something like this:

Replace onclick above with this:

onclick: function(){
    var $node = $(ed.selection.getNode());
    if( !$node.closest('div.section').length ){
       // Get highest element that is a direct child of the `body` tag:
       var $parent = $node.closest('body > *');
       // Wrap with our special section div
       if($parent.length) $parent.wrap('<div class="section"></div>');
    }
}
Doug Neiner
Sneaky JQuery implementation! Nice. And another case for that co-authoring function.
Pekka
@Pekka Totally... we really need to suggest that. Maybe I'll type it up this week.
Doug Neiner
HA I already had something like you had in the first example.
RedWolves
that second example is useful as well...Thanks.
RedWolves
@RedWolves great! Good luck on your project!
Doug Neiner
I was using parents instead of closest but I like this approach better.
RedWolves