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

плагин 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 

Оставлять комментарии могут только зарегистрированные пользователи

Комментарии  

Maxm
# Maxm 30.07.2012 16:46
Еще бы onchange
Leroy
# Leroy 03.08.2012 20:29
есть такой, сам недавно искал http://cksource.com/forums/viewtopic.php?f=18&t=23605
Treigol
# Treigol 05.08.2014 19:44
спасибо разработчику этого плагина! =)



замечательно работает и здорово выручает мой собственный плагин )
Leroy
# Leroy 06.08.2014 13:52
очень рад, что мои разработки кому-то помогают) для того и писались. отличный редактор ckeditor все же