При разработке плагина для 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
Комментарии
замечательно работает и здорово выручает мой собственный плагин )