JavaScript « Манипуляции с выделенным текстом
Всем привет!
Есть такой код (внутри контейнера с аттрибутом contenteditable="true"):
/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .html4strict.geshi_code {font-family:monospace;} .html4strict.geshi_code .imp {font-weight: bold; color: red;} .html4strict.geshi_code .kw2 {color: #000000; font-weight: bold;} .html4strict.geshi_code .kw3 {color: #000066;} .html4strict.geshi_code .es0 {color: #000099; font-weight: bold;} .html4strict.geshi_code .br0 {color: #66cc66;} .html4strict.geshi_code .sy0 {color: #66cc66;} .html4strict.geshi_code .st0 {color: #ff0000;} .html4strict.geshi_code .nu0 {color: #cc66cc;} .html4strict.geshi_code .sc-1 {color: #808080; font-style: italic;} .html4strict.geshi_code .sc0 {color: #00bbdd;} .html4strict.geshi_code .sc1 {color: #ddbb00;} .html4strict.geshi_code .sc2 {color: #009900;} .html4strict.geshi_code span.xtra { display:block; }
<ol>
<li>Mozilla Firefox 1.5+</li>
<li>Internet <span>Explorer</span> 6+</li>
<li>Opera 9.6+</li>
<li>Google Chrome 2+</li>
<li>Apple Safari 3+</li>
</ol>
Пользователь выделил фрагмент текста:
Так вот, как мне узнать, обернут ли выделенный фрагмент текста каким-нибудь тегом или нет?
Апдейт:
Вот смотрите, если выделить текст и исполнить команду document.execCommand('Bold', false, null), то браузер обернет выделенный текст в теги b. Если опять выделить тот же самый текст (а он уже жирный) и опять испольнить команду document.execCommand('Bold', false, null), то браузер удалит теги b. Тобишь, браузер же ведь как-то знает, обернут выделенный текст тегами или нет. Вроде, не должно быть сложности повторить те же действия Яваскриптом, но не вижу в упор, как…
Еще апдейт (поговорю сам с собой :):
Походу, придется регулярками парсить ХТМЛ. Например, выделяем полностью текст Apple Safari 3+ и задаем ему какой-нить шрифт стандартной командой document.execCommand, в результате получим такой ХТМЛ-код, который браузер создает сам:/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .html4strict.geshi_code {font-family:monospace;} .html4strict.geshi_code .imp {font-weight: bold; color: red;} .html4strict.geshi_code .kw2 {color: #000000; font-weight: bold;} .html4strict.geshi_code .kw3 {color: #000066;} .html4strict.geshi_code .es0 {color: #000099; font-weight: bold;} .html4strict.geshi_code .br0 {color: #66cc66;} .html4strict.geshi_code .sy0 {color: #66cc66;} .html4strict.geshi_code .st0 {color: #ff0000;} .html4strict.geshi_code .nu0 {color: #cc66cc;} .html4strict.geshi_code .sc-1 {color: #808080; font-style: italic;} .html4strict.geshi_code .sc0 {color: #00bbdd;} .html4strict.geshi_code .sc1 {color: #ddbb00;} .html4strict.geshi_code .sc2 {color: #009900;} .html4strict.geshi_code span.xtra { display:block; }
...
<li><font face="Tahoma">Apple Safari 3+</font></li>
...
Получается, что можно выдрать два подряд идущих тега (с их аттрибутами), перекинуть аттрибуты из второго тега в первый (верхний), удалить этот второй тег…/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .html4strict.geshi_code {font-family:monospace;} .html4strict.geshi_code .imp {font-weight: bold; color: red;} .html4strict.geshi_code .kw2 {color: #000000; font-weight: bold;} .html4strict.geshi_code .kw3 {color: #000066;} .html4strict.geshi_code .es0 {color: #000099; font-weight: bold;} .html4strict.geshi_code .br0 {color: #66cc66;} .html4strict.geshi_code .sy0 {color: #66cc66;} .html4strict.geshi_code .st0 {color: #ff0000;} .html4strict.geshi_code .nu0 {color: #cc66cc;} .html4strict.geshi_code .sc-1 {color: #808080; font-style: italic;} .html4strict.geshi_code .sc0 {color: #00bbdd;} .html4strict.geshi_code .sc1 {color: #ddbb00;} .html4strict.geshi_code .sc2 {color: #009900;} .html4strict.geshi_code span.xtra { display:block; }
...
<li face="Tahoma">Apple Safari 3+</li>
...
и заменить аттрибуты на стили:/**
* GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann
* (http://qbnz.com/highlighter/ and http://geshi.org/)
*/
.html4strict.geshi_code {font-family:monospace;}
.html4strict.geshi_code .imp {font-weight: bold; color: red;}
.html4strict.geshi_code .kw2 {color: #000000; font-weight: bold;}
.html4strict.geshi_code .kw3 {color: #000066;}
.html4strict.geshi_code .es0 {color: #000099; font-weight: bold;}
.html4strict.geshi_code .br0 {color: #66cc66;}
.html4strict.geshi_code .sy0 {color: #66cc66;}
.html4strict.geshi_code .st0 {color: #ff0000;}
.html4strict.geshi_code .nu0 {color: #cc66cc;}
.html4strict.geshi_code .sc-1 {color: #808080; font-style: italic;}
.html4strict.geshi_code .sc0 {color: #00bbdd;}
.html4strict.geshi_code .sc1 {color: #ddbb00;}
.html4strict.geshi_code .sc2 {color: #009900;}
.html4strict.geshi_code span.xtra { display:block; }
...
<li style="font-face:Tahoma;">Apple Safari 3+</li>
...
Пока буду так пробовать.
Есть такой код (внутри контейнера с аттрибутом contenteditable="true"):
/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .html4strict.geshi_code {font-family:monospace;} .html4strict.geshi_code .imp {font-weight: bold; color: red;} .html4strict.geshi_code .kw2 {color: #000000; font-weight: bold;} .html4strict.geshi_code .kw3 {color: #000066;} .html4strict.geshi_code .es0 {color: #000099; font-weight: bold;} .html4strict.geshi_code .br0 {color: #66cc66;} .html4strict.geshi_code .sy0 {color: #66cc66;} .html4strict.geshi_code .st0 {color: #ff0000;} .html4strict.geshi_code .nu0 {color: #cc66cc;} .html4strict.geshi_code .sc-1 {color: #808080; font-style: italic;} .html4strict.geshi_code .sc0 {color: #00bbdd;} .html4strict.geshi_code .sc1 {color: #ddbb00;} .html4strict.geshi_code .sc2 {color: #009900;} .html4strict.geshi_code span.xtra { display:block; }
<ol>
<li>Mozilla Firefox 1.5+</li>
<li>Internet <span>Explorer</span> 6+</li>
<li>Opera 9.6+</li>
<li>Google Chrome 2+</li>
<li>Apple Safari 3+</li>
</ol>
Пользователь выделил фрагмент текста:
- конкретно слово «Chrome»,
- или конкретно слово «Explorer».
Так вот, как мне узнать, обернут ли выделенный фрагмент текста каким-нибудь тегом или нет?
- Регулярным выражением? — Не могу понять, как выдернуть текст вместе с ХТМЛ-тегами, получается выдернуть просто чистый текст.
- Используя commonAncestorContainer.parentNode? — Если я выделил слово «Chrome», то родительская нода будет тег li (но этот тег li не оборачивает именно мой выделенный текст, там еще куча символов между выделенным фрагментом и родительской нодой, а задавать стили для li мне не нужно).
- если выделенный фрагмент текста уже впритык обернут каким-нибудь тегом, то просто задам стили внутри этого тега (например, в случае со словом «Explorer» я просто задам стиль style="letter-spacing:1px;" для тега span; если пользователь выделит Apple Safari 3+, то задам стиль уже тегу li);
- если же выделенный фрагмент является просто текстом (никаким тегом вокруг впритык не обернут), то я оберну этот текст span'ом и задам ему стиль. Но с этим пунктом проблем нет, тут всё легко, уже реализовано.
Апдейт:
Вот смотрите, если выделить текст и исполнить команду document.execCommand('Bold', false, null), то браузер обернет выделенный текст в теги b. Если опять выделить тот же самый текст (а он уже жирный) и опять испольнить команду document.execCommand('Bold', false, null), то браузер удалит теги b. Тобишь, браузер же ведь как-то знает, обернут выделенный текст тегами или нет. Вроде, не должно быть сложности повторить те же действия Яваскриптом, но не вижу в упор, как…
Еще апдейт (поговорю сам с собой :):
Походу, придется регулярками парсить ХТМЛ. Например, выделяем полностью текст Apple Safari 3+ и задаем ему какой-нить шрифт стандартной командой document.execCommand, в результате получим такой ХТМЛ-код, который браузер создает сам:/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .html4strict.geshi_code {font-family:monospace;} .html4strict.geshi_code .imp {font-weight: bold; color: red;} .html4strict.geshi_code .kw2 {color: #000000; font-weight: bold;} .html4strict.geshi_code .kw3 {color: #000066;} .html4strict.geshi_code .es0 {color: #000099; font-weight: bold;} .html4strict.geshi_code .br0 {color: #66cc66;} .html4strict.geshi_code .sy0 {color: #66cc66;} .html4strict.geshi_code .st0 {color: #ff0000;} .html4strict.geshi_code .nu0 {color: #cc66cc;} .html4strict.geshi_code .sc-1 {color: #808080; font-style: italic;} .html4strict.geshi_code .sc0 {color: #00bbdd;} .html4strict.geshi_code .sc1 {color: #ddbb00;} .html4strict.geshi_code .sc2 {color: #009900;} .html4strict.geshi_code span.xtra { display:block; }
...
<li><font face="Tahoma">Apple Safari 3+</font></li>
...
Получается, что можно выдрать два подряд идущих тега (с их аттрибутами), перекинуть аттрибуты из второго тега в первый (верхний), удалить этот второй тег…/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .html4strict.geshi_code {font-family:monospace;} .html4strict.geshi_code .imp {font-weight: bold; color: red;} .html4strict.geshi_code .kw2 {color: #000000; font-weight: bold;} .html4strict.geshi_code .kw3 {color: #000066;} .html4strict.geshi_code .es0 {color: #000099; font-weight: bold;} .html4strict.geshi_code .br0 {color: #66cc66;} .html4strict.geshi_code .sy0 {color: #66cc66;} .html4strict.geshi_code .st0 {color: #ff0000;} .html4strict.geshi_code .nu0 {color: #cc66cc;} .html4strict.geshi_code .sc-1 {color: #808080; font-style: italic;} .html4strict.geshi_code .sc0 {color: #00bbdd;} .html4strict.geshi_code .sc1 {color: #ddbb00;} .html4strict.geshi_code .sc2 {color: #009900;} .html4strict.geshi_code span.xtra { display:block; }
...
<li face="Tahoma">Apple Safari 3+</li>
...
...
<li style="font-face:Tahoma;">Apple Safari 3+</li>
...
Пока буду так пробовать.
1 ответов
Регулярки тут точно не помогут. Вообще тема не сложная, но довольно хитрая - оч много возможных вариантов.
Возможно с commonAncestorContainer, но без parentNode.
Я делаю примерно так - в начальную и конечные точки выделения ставлю пустые спаны - что-то вроде bookmark в движке trident. Дальше нахожу ближайшего общего родителя для них. и этих 3 нод достаточно чтобы получить коллекцию выделеных нод (забудьте что она может быть одна - всегда имейте дело с выделением, как с коллекцией нод)
также по "краям" выделения возможны "разночтения" у разных браузеров - например начало выделения оказывается в конце предыдущей ноды и там реально ничего не выделено и тд - таких вариантов не много и можно их отловить