при реализации визивига некоторые вещи приходится вытворять по схеме: сериализация->обработка->десериализация
в качестве примера - реализация динамической подсветки кода. одними только dom-функциями это реализовывать - страшный геморрой, а ещё и очень медленно. гораздо быстрее и проще пройтись парой регулярок по сериализованному документу.
но тут нас подстерегает одна гадость - после обработки хорошо было бы восстановить выделение или хотябы позицию курсора. очевидно, пока выделение ещё существует, нужно сохранить его позиции в dom-е, обработать и по оставленным меткам восстановить выделение.
очевидно, что метки начала и конца выделения должны быть неиспользуемой последовательностью символов юникода. также они должны иметь нулевую ширину, дабы при вводе текста не было скачков. я остановился на парах диактрических знаков: '\u0300\u0301' и '\u0302\u0303'. вроде как маловероятно, чтобы в тексте потребовалось их применить последовательно. ширины они точно не имеют. единственный недостаток: они имеют визуализацию, но с учётом того, что обработка должна быть "мгновенной" (ибо рилтаймовая подсветка) - кратковременное появление маленьких значков не должно быть заметно на глаз.
пришлось несколько погеморроиться с реализацией этого дела, но всё получилось. отдельный пример не выкладываю ибо его сложно выдрать из фреймворка - выпущу фреймворк - можно будет посмотреть в действии.
в ИЕ всё оказалось весьма шоколадно...
сохранение меток выглядит так:
var range= document.selection.createRange();
range.pasteHTML( '\u0300\u0301' + range.htmlText + '\u0300\u0301' );
восстановление несколько менее тривиально:
var ran= document.body.createRange();
var tr= document.body.createRange();
tr.findText( '\u0300\u0301' );
tr.text= '';
ran.setEndPoint( 'StartToStart', tr );
tr.findText( '\u0302\u0303' );
tr.text= '';
ran.setEndPoint( 'EndToEnd', tr );
ran.select( );
а вот реализуя то же самое для остальных браузеров пришлось несколько попотеть...
сохранение меток:
var ran= window.getSelection().getRangeAt(0);
var rane= ran.cloneRange( );
rane.collapse( false );
var node= document.createTextNode( '\u0302\u0303' );
rane.insertNode( node );
var node= document.createTextNode( '\u0300\u0301' );
ran.insertNode( node );
а для восстановления соответственно приходится бежать по всему дому в поисках открывающей и закрывающей пар node+offset, после чего наведение выделения с помощью функций setStart и setEnd. почему w3c не соизволила узаконить findText остаётся загадкой 8(o_0)8
пятница, сентября 07, 2007
Подписаться на:
Комментарии к сообщению (Atom)
8 комментариев:
Скажи пожалуйста, как ты сделал поиск по DOM открывающихся и закрывающихся node + offset для восстановления спанов? А то я замучился с рекурсивным перебором элементов DOM... Не помешает и ссылка на твою реализацию. :)
если проблема только в пробежке по дому, то можешь подправить этот код: http://fastcoder.org/javascript/21.html
у меня реализация без рекурсии, но сильно завязана на фреймворк (хотя, алгоритм вырвать не сложно, наверное).
http://dollar-script.googlecode.com/svn/trunk/$node.js
функция $descwalk
колбэк функция должна возвращать firstChild, чтобы идти вглубь, nextSibling, чтобы идти к следующему узлу и false, чтобы остановиться.
С рекурсивной пробежкой по DOM-у я справился - смотрю регуляркой в node.textContents() на наличие метки*. Далее выделяю метку и удаляю ее через range.deleteContents().
Но вот как теперь поставить каретку на законное место? setStart и setEnd() применимы только в случае выделения участка текста, начало и конец тут вроде не могут совпадать. =(
* Метка у меня всего одна - ставится в позицию каретки. Дальше я передаю управление парсеру. Парсер вставляет результат в редактор, после чего я пробегаюсь по DOM и ищу метку.
Вопрос снят - воспользовался collapse().
Спасибо большое! Respect за идею.
совпадать-то они могут. думаю проблема была в неправильном порядке - сначала надо устанавливать зад, а потом перед.
Кардеры, продаем банковские карты дампы кредитных карт, дампы карт,дамп с пин кардинг, кардинг взлом кредитных карт, кардер, продам дампы карт. Продаем кредитные карты, банковские карточки Mastercard, кредитки с пин кодом Visa с балансами 800$-5000$, доставка в любой город, гарантия надежности, ищем постоянных партнеров, пишите нам на емайл kredstore@gmail.com
Может обсудим на форуме ?
Is it possible to contact administration?
By the way, anybody home?!
Отправить комментарий