Делаю так:
if ( window.getSelection ) {
var selection = window.getSelection();
} else if ( document.selection ){
var selection = document.selection.createRange();
}
var range = selection.getRangeAt(0);
var div = document.createElement('div');
div.appendChild( range.cloneContents() );
console.log( div.innerHTML ); // двойной клик по слову "новый" даёт результат: но<i>вы</i>й - не хватает тегов b
console.log( div.innerHTML ); // если выделить "я новый редактор", даёт результат: я <b>но<i>вы</i>й</b> редактор
есть ещё range.commonAncestorContainer, который:
console.log( range.commonAncestorContainer ); // двойной клик по слову "новый" даёт результат: <b>но<i>вы</i>й</b> - то что нужно
console.log( range.commonAncestorContainer ); // если выделить "я новый редактор", даёт результат: <p>Привет я <b>но<i>вы</i>й</b> редактор</p>, а не выделение.
Я думал совместить эти две функции. range.commonAncestorContainer даёт ближайшего родителя. Затем в строке range.commonAncestorContainer искать подстроку div.innerHTML, и регуляркой вытаскивать ближайшие теги. Типа такого: (/<МОЯ_ПОДСТРОКА>/ig)
Но регулярки я, к сожалению, не знаю. Да и вообще, походит на какой-то костыль. Может есть более простое и элегантное решение?
Суть в том, чтобы получить html выделенного текста вместе с внешними тегами: и по двойному клику по слову, и обычным выделением группы слов.