Adam
Adam

Reputation: 1874

Automatically convert two dashes into an — in TinyMCE

I'm looking for a TinyMCE plugin or other custom solution which will convert -- into — automatically. Ideally the solution would not require processing the entire TinyMCE contents on every keyPress/keyUp event, but instead only check when the user has either cut, pasted, or typed -. Right now I'm using something like the following, and it's a little slow when the TinyMCE contents are large:

tinyMCE.init({
    //...            
    setup: function (ed) {
        ed.onKeyUp.add(function(ed) {
            //find and replace two dashes with emdash
            //if there was a change, update tinymce/textarea contents
        });
    }
});

More generally, I'm curious about a fast text-processing solution for TinyMCE. I understand that there may be nothing better than the method I'm using right now, but I was just wondering if any of you guys have found a better solution. Thanks!

Upvotes: 2

Views: 1477

Answers (3)

Rohit Vishwakarma
Rohit Vishwakarma

Reputation: 530

If someone just want to do this when user types (not for cases like copy/paste, long press key '-')

setup: function (editor) {
    // emdash support
    let customProcess = function (e) {
      if (e.key === '-') {
        let selection = tinymce.activeEditor.selection;
        let range = selection.getRng();
        const startOffset = range.startOffset;
        let textContent = range.startContainer.textContent;

        if (startOffset > 1 && textContent[startOffset - 2] === '-') {
          range.setStart(range.startContainer, startOffset - 2);
          selection.setRng(range);
          selection.setContent('&#8212');
        }
      }
    };
    editor.on('keyUp', customProcess);
  }
  • First take tinymce.activeEditor.selection
  • get the textcontent of the element at cursor positino
  • check if last two elements are '-'
  • create selection range containg two character left to the cursor
  • update content of the range

Upvotes: 1

gfullam
gfullam

Reputation: 12075

Create a custom processing function in setup

You're on the right track and you won't need a plugin for this.

At your most basic level just perform a .replace() in your event callback:

tinyMCE.init({
    //...            
    setup: function (editor) {
        editor.onKeyUp.add(function (editor) {
            var content = editor.getContent({ format: 'html'});  // Get content in HTML entity encoded format

            // RegEx replacements
            content = content.replace(/--/g, '—'); // Convert two dashes into —

            // Set content of iframe editor with modified string
            editor.setContent(content, { format: 'html' });
        });
    }
});

But you'll want to listen for the onChange event as well and, since you're replacing two characters with one, the above method will result in your cursor position shifting out of sync.

Here is the better way:

tinyMCE.init({
    //...            
    setup: function (editor) {
        var customProcess = function (editor) {
            var lastSelection = editor.selection.getBookmark(2, true), // Store last selection for later restoration
                content       = editor.getContent({ format: 'html'});  // Get content in HTML entity encoded format

            // RegEx replacements
            content = content.replace(/--/g, '—'); // Convert two dashes into —

            // Set content of iframe editor with modified string
            editor.setContent(content, { format: 'html' });

            // Restore selection
            editor.selection.moveToBookmark(lastSelection);
        };

        // Listen for change event
        editor.onChange.add(customProcess);

        // Listen for key up event
        editor.onKeyUp.add(customProcess);
    }
});

See this JSFiddle for a working example.

EDIT:

I see now that you're looking for an alternative to the onKeyUp event. The onChange event is probably your best alternative. I don't know of any other fast-processing solutions.

Upvotes: 1

Thariama
Thariama

Reputation: 50830

Concerning cutting and pasting (and drag/droping) you could check for the corresponding shortcuts or use the onPaste event. For droping content into the editor you could bind an onDrop handler to the tinymce editor instances iframe body (i.e. using jQuery).

If you want to check on every typed character a user types in, you got the solution you want already - except for the speed. But i cannot see a faster solution for this case - you will have to check on every new character, except you can check for the character entered (delete, backspace, &mdash.)

Upvotes: 1

Related Questions