Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select a text range in CKEditor from javascript

Tags:

ckeditor

I want to select a specific text in CKEditor. I used the following:

var sel = editor.getSelection();

var element = sel.root;
console.log(element);
sel.selectElement(element);
var findString = 'foobar';
var ranges = editor.getSelection().getRanges();
var startIndex = element.getHtml().indexOf(findString);

if (startIndex != -1) {
    ranges[0].setStart(element.getFirst(), startIndex);
    console.log(element.getFirst() +" - "+ startIndex);
    console.log(element.getFirst() +" - "+ startIndex + findString.length);
    ranges[0].setEnd(element.getFirst(), startIndex + findString.length);
    sel.selectRanges([ranges[0]]);
}

It works fine if it's a plain text without a line break. If the text I want to select is after the second line or it's formatted, I get the following error:

Uncaught Error: IndexSizeError: DOM Exception 1

What is going wrong?

like image 560
sathees Avatar asked May 15 '26 16:05

sathees


1 Answers

I revisited your code and changed it "a little bit". The following code will select all occurrences of the word "the" in editor contents:

// Note: your instance name may differ.
var editor = CKEDITOR.instances.editor1, 
    selection = editor.getSelection(),
    root = selection.root,
    textNodes = [],
    ranges = [],
    range, text, index;

function getTextNodes( element ) {
    var children = element.getChildren(),
        child;

    for ( var i = children.count(); i--; ) {
        child = children.getItem( i );
        if ( child.type == CKEDITOR.NODE_ELEMENT ) 
            getTextNodes( child );
        else if ( child.type == CKEDITOR.NODE_TEXT )
            textNodes.push( child );
    }
}

// Recursively search for text nodes starting from root.
// You may want to search a specific branch starting from other element.
getTextNodes( root ); 

// Iterate over found text nodes. If some contains
// phrase "the", create a range that selects this word.
for ( i = textNodes.length; i--; ) {
   text = textNodes[ i ];
   index = text.getText().indexOf( 'the' );
   if ( index > -1 ) {
      range = editor.createRange();
      range.setStart( text, index );
      // Note: 3 is fixed length of "the". You may want to change it.
      range.setEnd( text, index + 3 ); 
      ranges.push( range );
   }  
}

// Select all ranges "containing" phrase "the".
selection.selectRanges( ranges );

Please note that if you run this code in Chrome or IE, only the first occurrence will be selected. Only Firefox supports multiple selections and the result should look like this:

Multiple selections in Firefox

I hope this example will help you fixing the problem.

like image 107
oleq Avatar answered May 19 '26 03:05

oleq



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!