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.
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.
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>
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..."!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With