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

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

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

Комментарии  

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 все же