При написании плагинов для ckeditor'а, часто возникает задача: необходимо получить выделенную пользователем информацию, а в некоторых случая произвести манипуляцию с ней. Если необходим просто выделенный текст, то тут все просто. У объекта editor есть метод getSelection(), он возвращает объект, который помимо полной информации о выделенном тексте содержит еще метод getSelectedText(). В простейшем случае в плагине это бы выглядело так:
CKEDITOR.plugins.add('pluginname',{
init: function(editor){
alert(editor.getSelection().getSelectedText())
}
});
Надеюсь Вам понятно, что плагин работать не будет. Это псевдокод. При инициализации плагина, никакой текст не выделен.
А как же насчет html кода, для работы необходим именно он.
Я уже проводил изыскания по этому поводу ранее, с выделенным текстом можно и нужно работать. Но только в API редактора таких методов, увы, нет. Вновь берем в руки молоток редактор и ваяем свой велосипед. Метод подсмотрен на одном из формуов
function getSelectionHTML(selection){
var range = (document.all ? selection.createRange() : selection.getRangeAt(selection.rangeCount - 1).cloneRange());
if (document.all){
return range.htmlText;
}else{
var clonedSelection = range.cloneContents();
var div = document.createElement('div');
div.appendChild(clonedSelection);
return div.innerHTML;
}
}
Берем выделенную часть html кода в виде htmlFragment. У API ckeditor'а есть своя кроссбраузерная надстройка над этим объектом. Далее если это Internet Explorer, то у него есть поле htmlText у объекта типа range. При этом - это «нативный» range, не тот который возвращает метод selection.getRanges().
Если это не Internet Explorer, а любой другой браузер, то используются методы копирования фрагмента кода cloneContents, затем этот фрагмент закидывается в div, и уже у него берется внутреннее содержимое.. Вот такие костыли. Пол веба на этом работает, скажу я Вам.
Это не единственный способ получить содержимое выделенного фрагмента. Приведу еще одну реализацию:
CKEDITOR.editor.prototype.getSelectedHtml = function(){
var selection = this.getSelection();
if( selection ){
var bookmarks = selection.createBookmarks(),
range = selection.getRanges()[ 0 ],
fragment = range.clone().cloneContents();
selection.selectBookmarks( bookmarks );
var retval = "",
childList = fragment.getChildren(),
childCount = childList.count();
for ( var i = 0; i < childCount; i++ ){
var child = childList.getItem( i );
retval += ( child.getOuterHtml?
child.getOuterHtml() : child.getText() );
}
return retval;
}
};
Тут более хитрый костыль. Мы добавили редактору метод getSelectedHtml, и далее а плагине можно уже использовать его напрямую. Примерно так:
CKEDITOR.plugins.add('pluginname',{
init: function(editor){
alert(editor.getSelectedHtml())
}
});
Опять псевдокод. Но это ведь не статья про то, как писать плагины на ckeditor. Метод описанный выше кстати не просто удобней, он еще и не создает лишних div блоков. А просто перебирает выделенный фрагмент по его потомкам.
selection.getRanges()[ 0 ] - если кому не понятно, то по некоторой логике (в некоторых браузерах), при нажатии ctrl, можно перенести курсор в другое место, и выделить там другую часть страницы и получить несколько выделений. Этого нам не надо, сколько я не пытался, повторить такое мне не удалось. Так что берем только самое первое.
bookmarks = selection.createBookmarks()- насколько я понял, необходимо для плагинов undo и redo. Если Вы вдруг, каким-то мистическим образом смогли изменить html код в странице, то плагин undo поможет Вам вернуть все на место.
Почему мистическим? Потому, что если Вам это удалось, то Вы наверняка уже владелец виллы в Барселоне, и яхты, там же, и вообще Вы очень успешный человек. Я говорю так, потому, что заработать на яхту и виллу задача весьма нетривиальная, как и заменить незакрытый тег. Подумайте сами, пользователь может выделать на странице все, что угодно. К примеру часть параграфа, захватив закрывающий </p>. Но не захватив открывающий. Как себя должна вести себя замена, известно наверно только всевышнему.
Максимум, который мне удалось достичь - это метод editor.insertHtml('html').
В обычном случае, метод просто вставляет в страницу код, но если часть страницы выделено, то метод произведет ее замену. Работает это все мягко говоря странно. Я бы сказал, что в сложносочиненных страницах, с таблицами, оно работает не так, как хотелось бы.
Если Вам все же захотелось сделать прямую замену, читаем мою старую статью или используем готовый код. CKEditor заботливо предоставляет нам метод getNative у selection. Дальше работаем, с этим объектом исходя из методов браузера. Все понятно? Если нет, пишите в комментах вопросы, я объясню.

