Henrik Petterson
Henrik Petterson

Reputation: 7094

Custom TinyMCE button not working with terms containing special characters

I have a custom button added to TinyMCE visual editor. This button wraps any highlighted words in <em> tags with class tle. So, if you highlight term Pulp Fiction and click the button, you will get <em class="tle">Pulp Fiction</em>.

The JS code:

(function() {
    tinymce.PluginManager.add('custom_em', function( editor, url ) {

        editor.on('init', function(e) {
            this.formatter.register('reftitle', {
                inline : 'em',
                classes : 'tle'
            });
        });

        editor.addButton('custom_em', {
            text: 'Title (italic)',
            icon: false,
            onclick : function() {
                var contents = editor.selection.getContent(),
                tags = jQuery(contents).find('em.tle').andSelf();
                if (tags.length) {
                    editor.formatter.remove('reftitle');
                } else {
                    editor.formatter.apply('reftitle', {value: contents});
                }


            }
        });
    });
})(jQuery);

It works great, but it doesn't format any terms that contain any special characters. It only works with characters A-Z and 0-9.

For example, X-Men: Days of Future Past will not work because it contains :. In console, it gives error: Syntax error, unrecognized expression.

Why is it not working properly? Guessing it's an issue with my onclick function. Hoping there is a jQuery or TinyMCE guru here.

Upvotes: 0

Views: 1073

Answers (1)

Sergiu Paraschiv
Sergiu Paraschiv

Reputation: 10153

The issue is at jQuery(contents). This happens because of the dual nature of jQuery (the function itself, not the library):

1) You can pass it a string containing valid HTML and expect it to return a DOM node;

2) You can also pass it a selector ('#div.foo') and expect it to return a list of nodes matching it.

That means somewhere, before applying (1) or (2), this function has to decide what it's dealing with, so it checks if whatever you pass to it looks like a selector. Turns out 'foo: bar' does so it goes through with (2). What happens next is it tries to tokenize the selector and fails.

What you need to do to fix this issue is make sure you use (1), not (2), and you can do that using jQuery.parseHTML so your code should be

tags = jQuery(jQuery.parseHTML(contents)).find('em.tle').andSelf();

The logic after that is a different issue. The final solution is pretty simple actually. Turns out the Formatter class, besides apply and remove, has a toggle method that does exactly what you need, better:

onclick : function() {
    editor.formatter.toggle('reftitle');
}

Upvotes: 1

Related Questions