Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   получение контента childNodes (https://javascript.ru/forum/events/14857-poluchenie-kontenta-childnodes.html)

traa 03.02.2011 21:30

получение контента childNodes
 
Столкнулся с проблемой, которая, как оказалось, не так уж и тривиально решается.
Есть функция.

function mk_Selection(){ 
  var sel, output; 
  if (window.getSelection) { 
     sel = window.getSelection().getRangeAt(0).cloneContents(); 
  } else if (document.selection) { 
     sel = document.selection.createRange().htmlText; 
  }; 
 return sel;
}


Она берет выделенный фрагмент текста и возвращает его вместе со всей разметкой.
Одно НО!
Полученный результат невозможно вставить куда-то на страницу, поскольку он представляет собой объект Document Fragment.

Попытка получить его посредством
var st = mk_Selection();
 for (var i = 0; i < st.childNodes.length; i++) 
....

Успехом не увенчивается, поскольку у childNodes нет единого формата вывода, а перечислять все возможные виды тэгов и их атрибуты, чтобы сохранить разметку, - нереально.

Может, я что-то где-то пропустил, хотелось бы что-то в духе
var st = mk_Selection();
$(st).text();

(выводит только текст, без разметки, но нужно с разметкой, т.е. что-то типа $(st).html())

Иначе говоря, гуглю, да никак не нагуглю конвертацию чайлдНодов в стринг .

И, напоследок, вот как выглядит в консоли хрома полученный результат. Как бы его теперь из консоли вытащить в обычный хтмл?

Заранее благодарен.

Aetae 03.02.2011 21:45

documentFragment - это элемент dom, и работа с ним протекает как и с любым другим элементом.
<html>
<head>
<script type="text/javascript">
function mk_Selection(){
  var sel, output;
  if (window.getSelection) {
     sel = window.getSelection().getRangeAt(0).cloneContents();
  } else if (document.selection) {
     sel = document.selection.createRange().htmlText;
  };
 return sel;
}
</script>
</head>
<body onkeypress="document.body.appendChild(mk_Selection())">   
<div>Выделите<b> кусок текста</b> и <i>нажмите</i> любую <u>клавишу</u></div>
</body>
</html>


Кстати в случае ie у вас выдаётся просто строка, так что вам надо определиться с удобным вам вариантом, чтобы функция возвращала универсальный ответ.

traa 04.02.2011 00:14

Спасибо большое.

Подскажите пожалуйста, как лучше проверить результат работы функции mk_Selection() на пустоту? Т.е. если ничего не выделено, либо выделен пробел.

Особенно важен первый вариант, т.к. событие показа менюшки, которая появляется по окончании выделения вешается на mouseup, что приводит при любом клике к появлению меню, в то время как меню должно появляться только при не пустом выделении

P.S.: Разумеется, на обычный $.trim проверять объект нет смысла.

Aetae 04.02.2011 01:03

var s=mk_Selection()
//Если строка то:
if(s){ ... }
//Если дом элемент то:
if(s.firstChild){ ... }

Надо только определиться таки что должна возвращать функция.

traa 04.02.2011 11:24

Снова большое спасибо за ответ, действительно, все хорошо при определение на присутствие выделения, но как проверить то же выделение на $.trim к примеру? Обращение напрямую к firstChild не помогает что-то, вернее, помогает только в консоли.

Т.е. эта конструкция не дает желаемого результата, выделенный пробел по-прежнему проходит условие.
if (st.firstChild && $.trim(st.firstChild)!='')


А насчет того, что возвращает функция, - не подскажете, как заставить ИЕ отдавать подобный объект?

И конечно же, большое спасибо Вам за своевременную помощь!

traa 04.02.2011 11:36

как один из вариантов написал следующий костыль.
if ((st.firstChild && st.firstChild.nodeType==3 && $.trim(st.firstChild.nodeValue)!='' && st.childNodes.length==1) || 
 st.childNodes.length>1 ||
 	 (st.firstChild && st.firstChild.nodeType==1))


- Проверяем на наличие вообще firstChild
- Тип ноды у пробелов будет всегда равен текстовой ноде, т.е. троечке, что разумно вроде как.
- Если мы знаем тип нода, то мы можем обратиться к его свойству nodeValue
- чтобы в наше условие не попадали выделения у которых в начале стоит пробела, а затем идут другие ноды, ограничиваем область вхождения только одноНодовым выделением
- альтернативное условие - если несколько нодов, то текст нам подходит, т.к. пробелы разбиваться на несколько нодов явно не будут (правда, будут пробелы с тэгами, в которых пустоты или пробелы. да)
- альтернативное условие - при типе чайлдНода равного тэгу - всегда пропускаем, думаю, там нет нужды фильтровать.

traa 04.02.2011 14:27

правда, при усиленных тестах видно, что такие хитрые условия не спасают особо.
Есть у кого варианты, как проверять и избавляться от пробелов в выделении? ( когда выделены только пробелы или пустоты)

traa 04.02.2011 20:25

Один из наиболее простых и вроде как работающих вариантов, -
var s=mk_Selection();

if ($(s).text().trim()!='')
{
//do something
}


Часовой пояс GMT +3, время: 12:47.