jantimon
jantimon

Reputation: 38140

tinyMCE - limit RemoveFormat to a list of formats

Current tinyMCE version (3.5.2).

Hi,

I am working on a custom plugin which adds and removes custom formats.

Adding a format to the current selection is simple however I couldn't find a fitting solution for removing multiple formats.

What I did find was the RemoveFormat command:

tinymce.activeEditor.execCommand('RemoveFormat');
// which is the same as 
tinymce.activeEditor.formatter.remove('removeformat');

This function does remove any formats of the current selection and that is definitely to much as I want to remove only some of the formats.

So I tried to call the remove method for every format

tinymce.activeEditor.formatter.remove('format_1');
tinymce.activeEditor.formatter.remove('format_2');
...

However this wasn't successful either as it doesn't remove nested formats. If you select the following paragraph and call tinymce.activeEditor.formatter.remove('format_2'); it will NOT remove the format as the paragraph doesn't use this format itself.

<p class="format_1">abcd<span class="format_2>ef</span>g</p>

Is there any way to remove a format of an element and also of all of its children like RemoveFormat?


Update (@Thariama)

All my formats are custom formats with the following structure:

  "demo_format_1" : { 
      "classes" : "demo_format_1",
      "deep" : true,
      "exact" : false,
      "inline" : "span",
      "selector" : "*",
      "title" : "Demo Format"
   }}

Update:

After implementing this again I found further cases. Here are examples of all special cases which came to my mind:

Text before removing the format:

<p>abc<span class=demo_format_1>def</span></p>

Case 1 (Covered with the so Jeffery To)

Selecting the whole paragraph should give you the following result

 <p>abcdef</p>

Case 2

Selecting only f should give you the following result

<p>abc<span class=demo_format_1>de</span>f</p>

Case 3

Selecting only cd should give you the following result

<p>abcd<span class=demo_format_1>ef</span></p>

Upvotes: 3

Views: 3427

Answers (2)

Jeffery To
Jeffery To

Reputation: 11936

tinymce.Formatter.remove can be called on a specific node, so:

var selection = ed.selection.getSel(),
    ancestor = ed.selection.getNode(),
    els = ancestor.getElementsByTagName('span'),
    l = els.length,
    i = 0;
if (selection.containsNode(ancestor, true) && ancestor.nodeName.toLowerCase() === 'span') {
    ed.formatter.remove('demo_format_2', null, ancestor);
}
for ( ; i < l; i++) {
    if (selection.containsNode(els[i], true)) {
        ed.formatter.remove('demo_format_2', null, els[i]);
    }
}

Demo


Update: Turns out the trouble is caused by including both inline and selector in the format, which marks it as "mixed" (inline + block level). If you define the format with only inline:

demo_format_1: {
    inline: "span",
    classes: "demo_format_1"
}

then formatter.remove('demo_format_1') works as you'd expect (demo).

Upvotes: 4

Thariama
Thariama

Reputation: 50832

You should do the following:

  1. get all paragaphs touched by the user selection
  2. get all nodes under those paragraphs
  3. check if a node is touched by the selection range
  4. if it is: remove the 'unwanted' class from its class element

I will provide some code for this later.

Upvotes: 1

Related Questions