W3Max
W3Max

Reputation: 3406

Prevent TinyMCE from removing span elements

Here is the problem demonstration

You can try it here: http://fiddle.tinymce.com/SLcaab

This is TinyMCE default configuration

1 - Open the Html Source Editor

2 - Paste this html into the Html Source Editor:

<p><span>Hello</span></p>
<p><a href="http://www.google.com">Google 1</a></p>
<p><a href="http://www.google.com">Google 2</a></p>

3 - Click update in the Html Source Editor to paste the html in the editor

4 - Remember there is a span around 'Hello'.

5 - Place your cursor just before Google 2 and press backspace (the two links should merge inside the same paragraph element).

6 - Look at the resulting html using the Html Source Editor.

Result (problem): No more span in the html document even though we added 'span' to the extended_valid_elements in the TinyMCE settings.

Note: I removed all the plugins to make sure the problem is at the core of TinyMCE.

Edit 1 - I also tried: valid_children : "+p[span]" - still does not work

Edit 2: Only reproduced on WebKit (OK on Firefox and IE)

Upvotes: 14

Views: 32170

Answers (9)

Konrad
Konrad

Reputation: 111

I have the same problem and I find solutions. Tiny MCE deleted SPAN tag without any attribute. Try us span with class or another attribute for example:

<h3><span class="emptyClass">text</span></h3>

In TinyMCE 4+ this method good work.

Upvotes: 11

Dip
Dip

Reputation: 696

I was having same issue. empty SPAN tags are being removed. The solution i found is

verify_html: false,

Upvotes: 1

Mahen
Mahen

Reputation: 760

Tinymce remove span tag without any attribute. We can use span with any attribute so that it is not removed.

e.g <span class="my-class">Mahen</span>

Upvotes: 2

caramba
caramba

Reputation: 22480

Came across this question and was not happy with all the provided answers.

We do need to update wordpress at some point so changing core files is not an option. Adding attributes to elements just to fix a tinyMCE behaviour also doesn't seem to be the right thing.

With the following hook in the functions.php file tinyMCE will no longer remove empty <span></span> tags.

function tinyMCEoptions($options) {
    // $options is the existing array of options for TinyMCE
    // We simply add a new array element where the name is the name
    // of the TinyMCE configuration setting.  The value of the array
    // object is the value to be used in the TinyMCE config.

    $options['extended_valid_elements'] = 'span';
    return $options;
}
add_filter('tiny_mce_before_init', 'tinyMCEoptions');

Upvotes: 1

Jon
Jon

Reputation: 21

In the Tinymce plugin parameters enable: Use Joomla Text Filter.

Be sure your user group have set "No filtered" Option in global config > text filters.

Upvotes: 2

Jang-Ho Bae
Jang-Ho Bae

Reputation: 516

Insert extended_valid_elements : 'span' into tinymce.init:

tinymce.init({
    selector: 'textarea.tinymce',
    extended_valid_elements: 'span',
    //other options
});

Upvotes: 21

boateng
boateng

Reputation: 898

It's possible to use the work around by writing it as a JavaScript script which prevents WYSIWIG from stripping empty tags. Here my issue was with including Font Awesome icons which use empty <i> or <span> tags.

<script>document.write('<a href="https://www.facebook.com" target="_blank"><i class="fa fa-facebook"></i></a>');</script>

Upvotes: 1

Ben Eliott
Ben Eliott

Reputation: 654

Try this for 3.5.8:

  1. Replace cleanupStylesWhenDeleting in tiny_mce_src.js (line 1121) with this::

     function cleanupStylesWhenDeleting() {
            function removeMergedFormatSpans(isDelete) {
                    var rng, blockElm, wrapperElm, bookmark, container, offset, elm;
                    function isAtStartOrEndOfElm() {
                            if (container.nodeType == 3) {
                                    if (isDelete && offset == container.length) {
                                            return true;
                                    }
    
                                    if (!isDelete && offset === 0) {
                                            return true;
                                    }
                            }
                    }
    
                    rng = selection.getRng();
                    var tmpRng = [rng.startContainer, rng.startOffset, rng.endContainer, rng.endOffset];
    
                    if (!rng.collapsed) {
                            isDelete = true;
                    }
    
                    container = rng[(isDelete ? 'start' : 'end') + 'Container'];
                    offset = rng[(isDelete ? 'start' : 'end') + 'Offset'];
    
                    if (container.nodeType == 3) {
                            blockElm = dom.getParent(rng.startContainer, dom.isBlock);
    
                            // On delete clone the root span of the next block element
                            if (isDelete) {
                                    blockElm = dom.getNext(blockElm, dom.isBlock);
                            }
    
                            if (blockElm && (isAtStartOrEndOfElm() || !rng.collapsed)) {
                                    // Wrap children of block in a EM and let WebKit stick is
                                    // runtime styles junk into that EM
                                    wrapperElm = dom.create('em', {'id': '__mceDel'});
    
                                    each(tinymce.grep(blockElm.childNodes), function(node) {
                                            wrapperElm.appendChild(node);
                                    });
    
           blockElm.appendChild(wrapperElm);
                            }
                    }
    
                    // Do the backspace/delete action
                    rng = dom.createRng();
                    rng.setStart(tmpRng[0], tmpRng[1]);
                    rng.setEnd(tmpRng[2], tmpRng[3]);
                    selection.setRng(rng);
                    editor.getDoc().execCommand(isDelete ? 'ForwardDelete' : 'Delete', false, null);
    
                    // Remove temp wrapper element
                    if (wrapperElm) {
                            bookmark = selection.getBookmark();
    
                            while (elm = dom.get('__mceDel')) {
                                    dom.remove(elm, true);
                            }
    
                            selection.moveToBookmark(bookmark);
                    }
            }
    
    
                editor.onKeyDown.add(function(editor, e) {
                    var isDelete;
    
                    isDelete = e.keyCode == DELETE;
                    if (!isDefaultPrevented(e) && (isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {
                            e.preventDefault();
                            removeMergedFormatSpans(isDelete);
                    }
            });
    
            editor.addCommand('Delete', function() {removeMergedFormatSpans();});
    };
    
  2. put an external link to tiny_mce_src.js in your html below the tiny_mce.js

Upvotes: 1

am_
am_

Reputation: 2418

Are you running the newest version of TinyMCE? I had the opposite problem - new versions of TinyMCE would add in unwanted span elements. Downgrading to v3.2.7 fixed the issue for me, that might also work for you if you are willing to use an old version.

Similar bugs have been reported, see the following link for bugs filtered on "span" element: http://www.tinymce.com/develop/bugtracker_bugs.php#!order=desc&column=number&filter=span&status=open,verified&type=bug

Upvotes: 0

Related Questions