При разработке плагина для wysiwyg редактора ckeditor столкнулся с такой проблемой, что в нем нет события выделения текста onselect. Реализуем его сами.

Для начала, стоит отметить, что в редакторе все же есть событие selectionChange. Повесить на него обработчик можно таким образом
editor.on( 'selectionChange', getTextSelection );
где getTextSelection
function getTextSelection(){
var text = '';
if ( editor.mode != 'source' ){
var sel = editor.getSelection();
text = ( sel&&sel.getType()==CKEDITOR.SELECTION_TEXT&&sel.getSelectedText()!==null )?sel.getSelectedText():'';
}
alert(text);
}
здорово придумано, но к сожалению, не работает. Вызывается событие совсем, как-то странно: при переходе на новую строчку или выделении всего текста. Однако даже эти способности, нам пригодятся, ибо заходя немного вперед, скажу, что полноценного решения я не нашел и лишь совместив ряд найденных, получил приемлемый результат.
Следующий способ, а точнее событие при котором можно будет получить выделение, я заметил совершенно случайно. При выделении текста, иконка кнопки cut- вырезание, становиться активной. Работает, это также не всегда, но уже более предсказуемо. Осталось узнать, как функционирует данный механизм.
Все сложно. Команды cut, paste, copy — это нативные команды wysiwig редактора, не ckeditor’а, а самого html элемента у которого поставлен атрибут editable. ckeditor лишь прицепляет к нативным событиям свои. Сделать это можно не в любой момент, а только когда срабатывает событие contentDom. Далее код:
editor.on( 'contentDom', function(e){
this.getCommand('cut').on('state',getTextSelection);// прицепляемся к нативной команде cut
});
В результате мы получаем почти то, что нужно. Дело в том, что это ’псевдособытие’ срабатывает в момент выделения, однако не в момент его завершения. Т.е. оно может сработать в тот момент когда вы выделили только одну букву, хотя вы хотите выделить все слово. Этот недостаток решит следующий код:
var startSelect = false;
editor.on( 'contentDom', function(e){
this.getCommand('cut').on('state',getStatSelect)
editor.document.on('keyup',function(e){
if ( e.data.$.shiftKey ){
var keyCode = e.data.$.keyCode;
if( keyCode>=33&&keyCode<=40 )getTextSelection();
}
});
editor.document.on('mousedown',function(e){
startSelect = true;
});
editor.document.on('mouseup',function(e){
startSelect = false;
});
});
window.onmousemove = function(e){
if( startSelect )getTextSelection();
};
window.onmouseup = function(e){
startSelect = false;
};
editor.on( 'selectionChange', getTextSelection );
мы добавили к двум имеющимся событиям контроль над выделением с помощью мыши и с помощью клавиатуры. Клавиатурой можно выделять используя клавишу shift и стрелки либо shift и home,pgDn, pgUp, end. Полученный код сработает когда это нужно.
Однако он избыточен, события могут происходить одновременно и это может существенно нагрузить редактор ckeditor. Поэтому в данную схему необходимо внести небольшое дополнение, а конкретно мы изменим функцию getTextSelection
var timerSelect = 0;
function _getTextSelection(){
var text = '';
if ( editor.mode != 'source' ){
var sel = editor.getSelection();
text = ( sel&&sel.getType()==CKEDITOR.SELECTION_TEXT&&sel.getSelectedText()!==null )?sel.getSelectedText():'';
}
alert(text);
}
function getTextSelection(){
clearTimeout(timerSelect);
timerSelect = setTimeout(_getTextSelection,100);//c таймаутом можно поиграть на свое усмотрение
}
как видите при срабатывании события запускается таймер, и если до истечения этого таймера событие вновь повторилось мы останавливаем предыдущий таймер и запускаем таймер вновь. Теперь оформим данный код в виде плагина, после подключения которого, Вы сможете использовать в своем плагине такую конструкцию
editor.on( 'select', function( e ){
alert(e.getSelection().getSelectedText());
});
далее небольшое интро, как оформляется плагин для ckeditor.
Файл плагина должен лежать в отдельной папке с его названием в папке ckeditor/plugins/ и называться plugin.js. Назвать плагин можно, как угодно я назвал onSelect. Чтобы плагин заработал необходимо сообщить о нем ckeditor’у в config.js:
CKEDITOR.editorConfig = function( config )
{
config.extraPlugins = 'onselect';
****
теперь перейдем к содержанию файла plugins.js. Вот заготовка для любого плагина:
CKEDITOR.plugins.add( 'onselect',{
init : function( editor ){
// здесь будет наш код
}
} );
метод init сработает при инициализации плагина, в него и засунем весь наш код, за тем исключением, что нам теперь не потребуется находить выделенный текст, нам лишь необходимо известить систему о том, что произошло событие onselect, а как этим воспользуется программист нас не интересует:
CKEDITOR.plugins.add( 'onselect',{
init : function( editor ){
var timerSelect = 0;
function getTextSelection(){
clearTimeout(timerSelect);
timerSelect = setTimeout(function(){
editor.fire('select');// наше событие
},editor.config.onselecttimeout||100);//c таймаутом можно поиграть на свое усмотрение
}
var startSelect = false;
editor.on( 'contentDom', function(e){
this.getCommand('cut').on('state',getTextSelection)
editor.document.on('keyup',function(e){
if ( e.data.$.shiftKey ){
var keyCode = e.data.$.keyCode;
if( keyCode>=33&&keyCode<=40 )getTextSelection();
}
});
editor.document.on('mousedown',function(e){
startSelect = true;
});
editor.document.on('mouseup',function(e){
startSelect = false;
});
});
window.onmousemove = function(e){
if( startSelect )getTextSelection();
};
window.onmouseup = function(e){
startSelect = false;
};
editor.on( 'selectionChange', getTextSelection );
}
} );
поэтому на таймер мы запускаем событие таким образом editor.fire(’select’); и если где-то в другом месте, есть обработчик, то он сработает:
editor.on( 'select', function( e ){
alert(e.getSelection().getSelectedText());
});
Параметр таймера 100 лучше вынести в настройки editor.config.onselecttimeout и он может быть изменен в config.js
CKEDITOR.editorConfig = function( config )
{
config.extraPlugins = 'onselect';
config.onselecttimeout = 200;
*****
Исходники, как и всегда прилагаются ckeditor plugin onselect


Комментарии
замечательно работает и здорово выручает мой собственный плагин )