При разработке плагина для wysiwyg редактора ckeditor столкнулся с такой проблемой, что в нем нет события выделения текста onselect. Реализуем его сами.
Для начала, стоит отметить, что в редакторе все же есть событие selectionChange. Повесить на него обработчик можно таким образом
1 | editor.on( 'selectionChange' , getTextSelection ); |
где getTextSelection
1 2 3 4 5 6 7 8 | 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. Далее код:
1 2 3 | editor.on( 'contentDom' , function (e){ this .getCommand( 'cut' ).on( 'state' ,getTextSelection); // прицепляемся к нативной команде cut }); |
В результате мы получаем почти то, что нужно. Дело в том, что это ’псевдособытие’ срабатывает в момент выделения, однако не в момент его завершения. Т.е. оно может сработать в тот момент когда вы выделили только одну букву, хотя вы хотите выделить все слово. Этот недостаток решит следующий код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 таймаутом можно поиграть на свое усмотрение } |
как видите при срабатывании события запускается таймер, и если до истечения этого таймера событие вновь повторилось мы останавливаем предыдущий таймер и запускаем таймер вновь. Теперь оформим данный код в виде плагина, после подключения которого, Вы сможете использовать в своем плагине такую конструкцию
1 2 3 | editor.on( 'select' , function ( e ){ alert(e.getSelection().getSelectedText()); }); |
далее небольшое интро, как оформляется плагин для ckeditor.
Файл плагина должен лежать в отдельной папке с его названием в папке ckeditor/plugins/ и называться plugin.js. Назвать плагин можно, как угодно я назвал onSelect. Чтобы плагин заработал необходимо сообщить о нем ckeditor’у в config.js:
1 2 3 4 | CKEDITOR.editorConfig = function ( config ) { config.extraPlugins = 'onselect' ; **** |
теперь перейдем к содержанию файла plugins.js. Вот заготовка для любого плагина:
1 2 3 4 5 | CKEDITOR.plugins.add( 'onselect' ,{ init : function ( editor ){ // здесь будет наш код } } ); |
метод init сработает при инициализации плагина, в него и засунем весь наш код, за тем исключением, что нам теперь не потребуется находить выделенный текст, нам лишь необходимо известить систему о том, что произошло событие onselect, а как этим воспользуется программист нас не интересует:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 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’); и если где-то в другом месте, есть обработчик, то он сработает:
1 2 3 | editor.on( 'select' , function ( e ){ alert(e.getSelection().getSelectedText()); }); |
Параметр таймера 100 лучше вынести в настройки editor.config.onselecttimeout и он может быть изменен в config.js
1 2 3 4 5 | CKEDITOR.editorConfig = function ( config ) { config.extraPlugins = 'onselect' ; config.onselecttimeout = 200; ***** |
Исходники, как и всегда прилагаются ckeditor plugin onselect
Комментарии
замечательно работает и здорово выручает мой собственный плагин )