Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to wrap selected text in ckeditor

I wanted to wrap selected words in CKEditor in a <p> element.

From:

<p>This is a paragraph. And this is Selected text.</p>

To:

<p>This is a paragraph. And this is</p>
<p class="myclass">Selected text.</p>

I found some code:

( function() {
    CKEDITOR.plugins.add( 'qna', { 
        init: function( editor ) {
            editor.addCommand( 'insertQnA', { 
                exec : function( editor ) {    
                    if(CKEDITOR.env.ie) {
                        editor.getSelection().unlock(true); 
                            var selected_text = editor.getSelection().getNative().createRange().text; 
                    } else { 
                        var selected_text = editor.getSelection().getNative();
                    }
                    editor.insertHtml('[before]' + selected_text + '[after]'); 
                } 
            }); 
            editor.ui.addButton( 'qna', { 
                label: 'Insert QnA', 
                command: 'insertQnA', 
                icon: this.path + 'images/qna.png'
            }); 
        } 
    });
})();

I wanted to replace the [before] and [after] with <p class"myclass"> and </p> but it doesn't work.

I'm quite a newbie in JS/Jquery. I hope you can shed some light on it for me.

EDIT: From Spon's reply.

( function() {
  CKEDITOR.plugins.add( 'qna', { 
    init: function( editor ) {
      editor.addCommand( 'insertQnA', { 
        exec : function( editor ) {    
          editor.applyStyle(new CKEDITOR.style({
            Element : 'p', 
            Attributes : { class : 'Myclass' }, 
            Styles : { color : '#ff0000','font-family' : 'Courier'} 
          }));
        } 
      }); 
      editor.ui.addButton( 'qna', { 
        label: 'Insert QnA', 
        command: 'insertQnA', 
        icon: this.path + 'images/question.png'
      }); 
    } 
  });
})();

The above code wraps the selected text/words in a <span> element for some unknown reason.

Example:

From...

<p>This is a paragraph. And this is Selected text.</p>

To...

<p>This is a paragraph. And this is <span>Selected text.</span></p>

This is not what I want.

like image 938
ninjascorner Avatar asked Apr 03 '13 01:04

ninjascorner


3 Answers

In case you want a universal solution that works both select text and any number of elements then this will work:

var selectedHtml = "";
var selection = editor.getSelection();
if (selection) {
    selectedHtml = getSelectionHtml(selection);
}
editor.insertHtml('something' + selectedHtml + 'something');

You will need two additional functions:

/**
    Get HTML of a range.
*/
function getRangeHtml(range) {
    var content = range.extractContents();
    // `content.$` is an actual DocumentFragment object (not a CKEDitor abstract)
    var children = content.$.childNodes;
    var html = '';
    for (var i = 0; i < children.length; i++) {
        var child = children[i];
        if (typeof child.outerHTML === 'string') {
            html += child.outerHTML;
        } else {
            html += child.textContent;
        }
    }
    return html;
}
/**
    Get HTML of a selection.
*/
function getSelectionHtml(selection) {
    var ranges = selection.getRanges();
    var html = '';
    for (var i = 0; i < ranges.length; i++) {
        html += getRangeHtml(ranges[i]);
    }
    return html;
}

Note that in CKEditor 4.5 you actually have getHtml function so getRangeHtml could be simplified by using content.getHtml(). See documentFragment doc.

like image 131
Nux Avatar answered Oct 14 '22 15:10

Nux


Duplicate see Stackoverflow: Ckeditor Selection wrapping

editor.applyStyle(new CKEDITOR.style({Element : 'p', Attributes : { class : 'Myclass' }, Styles : { color : '#ff0000','font-family' : 'Courier' } ));

This piece of code makes sure that if you have multiple block level selection, that you will keep the same structure. (If you make your p.myclass inline offcourse).

<p>This is a paragraph. And this is </p><p> Selected text.</p>

this example will be merged and output as:

<p>This is a paragraph. </p><p class="myClass">And this is  Selected text.</p>

But this example:

<div>This is a paragraph. And this is</div><div>  Selected text.</div>

this example will be merged and output as:

<div>This is a paragraph. <P class="myclass">And this is</p></div><div><P class="myclass">  Selected text.</p></div>
like image 23
Spons Avatar answered Nov 14 '22 20:11

Spons


Worth noting the CKEDITOR.style syntax has (apparently) changed in CKEditor 4; to use editor.applyStyle() (Which is preferable in some cases so you don't get a bunch of nested HTML), change the editor.applyStyle() stanza in the question's second example to:

editor.applyStyle(new CKEDITOR.style({
        element : 'p', 
        attributes : { class : 'Myclass' }, 
        styles : { color : '#ff0000','font-family' : 'Courier'} 
      })
);

Notice how the keys are all lowercase now.

It would really help if they'd document this -- the only documentation there at the moment says "TODO..."!

like image 3
aendra Avatar answered Nov 14 '22 19:11

aendra