При написании плагинов для 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. Дальше работаем, с этим объектом исходя из методов браузера. Все понятно? Если нет, пишите в комментах вопросы, я объясню.

Рассказать друзьям

Добавить комментарий


Защитный код
Обновить