1
votes

Edit 18th november 2016 I'm trying to mark / highlight long sentences (above 16 words) in a TinyMCE editor.

This is my best bet so far using mark.js and TinyMCE editor

The HTML is quite plain:

<div id="myTextArea" contenteditable="true">
    Put whatever random text you want and as long as it is above 
    16 words per dot separated sentence it should also mark the text.
</div>

JavaScript looks like this at the moment:

tinymce.init({
    selector: '#myTextArea',
    height: 300,
    init_instance_callback : "myCustomInitInstance",
});

function myCustomInitInstance(inst) {
   var rawText = tinyMCE.get('myTextArea').getContent({format : 'text'});
   var sentenceArray = rawText.split(".");
   var matchWarning = [];
   var longSentence = 16;
   var words;
   var wordCounter;

   for (var i in sentenceArray) {
       words = sentenceArray[i].split(" ");
       wordCounter = words.length;
       if (wordCounter > longSentence) {
           matchWarning.push(sentenceArray[i]);
       }
   }

    $("#myTextArea").mark(matchWarning, {
        "separateWordSearch": false,
        "iframes": true,
    });
}

You can see it run on CodePen here: http://codepen.io/MarkBuskbjerg/pen/rWWRbX

Any suggestions as to why TinyMCE is not highlighting the text is very welcome

Heading

Thanks in advance


Original post

I'm playing around with a simple tool calculating lix, long sentences and such.

I really wanna be able to highlight areas in the text, which needs the attention of the person writing.

It's fairly simple with a plain div with contenteditable="true" and an underlay div creating the highlight effect.

I've created a swift demo of the effect here: http://codepen.io/MarkBuskbjerg/pen/qqZBwo

<div id="myTextArea" contenteditable="true">
    ...Text goes here
</div>

<div id="textMarker">

</div>

and then

function textHandler() {
rawText = $("#myTextArea").html();
rawText = rawText.replace(/\n\r?/g, '<br />');
textArray = rawText.split(". ");
var matchWarning = new Array();


for (var i in textArray) {
    var words = textArray[i].split(" ");
    var wordCounter = words.length;
    if (wordCounter > 16) {
        matchWarning.push(i);
    }
}

rawText = $( "#myTextArea" ).html();
rawText = rawText.replace(/\n\r?/g, '<br />');
rawText = rawText.split(". ");

for (var i in matchWarning) {
    for (var y in rawText) {        
        if (matchWarning[i] == y) {
            rawText[y] = "<span class='long-sentence'>" + rawText[y] + "</span>";
        }
    }
}

rawText = rawText.join(". ");

// Output to the #outputText div on top of the TinyMCE editor
$("#textMarker").html(rawText); 
}

$(document).ready(textHandler);
$( "#myTextArea" ).keyup(textHandler);
$( "#myTextArea" ).change(textHandler);

The reason why I'm not just editing the content in the editable div directly is, that I at the same time want the users markup preserved in the editor (bullets, headers and such). I therefore turned to TinyMCE.

I'm perfectly able to do this with TinyMCE if the text mashed through my javascript was just to be dumped in a div outside of the TinyMCE editor.

But I'm more than puzzled trying to figure how to achieve the above shown effect with TinyMCE. Any inputs would be much, much appreciated.

1
Just use mark.jsdude
Thanks for mentioning mark.js @dude it is very nice. However I can't wrap my head around how to mark an entire sentence with mark.js. If I enter a string that should be marked (like: "This is Doctor Muriel speaking") it also matches single words in other sentences (like: "What a wonderful day it <mark>is</mark>) Any suggestions on how to make this more exact? I've been through all of the settings in mark.jsMark Buskbjerg
To disable separate word search you can use separateWordSearch: false. If this isn't what you're searching for maybe the accuracy is what you're looking for.dude
Mark.js was a major help i making text marking easier. However, the mark disappears when I initialize TinyMCE (example here: codepen.io/MarkBuskbjerg/pen/rWWRbX )Mark Buskbjerg

1 Answers

1
votes

You'll need to set the changed HTML using a TinyMCE API method.

This answer demonstrates how to set HTML content using tinyMCE.activeEditor.setContent. Now, since mark.js marks matches directly in the textarea, you'll have to clone the textarea, let mark.js do the changes there and then set the clone's HTML to the original textarea.

This would be the full code:

tinymce.init({
  selector: '#myTextArea',
  height: 300,
  init_instance_callback: "myCustomInitInstance",
});

function myCustomInitInstance(inst) {
  var rawText = tinyMCE.get('myTextArea').getContent({
    format: 'text'
  });

  var sentenceArray = rawText.split(".");
  var matchWarning = [];
  var longSentence = 16;
  var words;
  var wordCounter;

  for (var i in sentenceArray) {
    words = sentenceArray[i].split(" ");
    wordCounter = words.length;
    if (wordCounter > longSentence) {
      matchWarning.push(sentenceArray[i]);
    }
  }

  var $clone = $("#myTextArea").clone();
  $clone.mark(matchWarning, {
    "separateWordSearch": false,
    "iframes": true
  });
  tinyMCE.activeEditor.setContent($clone.html());
}