Выбор JavaScript через узлы: как получить эти узлы? - PullRequest
0 голосов
/ 16 марта 2011

рассмотрите следующий выбранный фрагмент HTML:

<span>...</span><span>...</span><span>....</span>
.......||||||||||||||||||||||||||||||.......

Вторая строка представляет выбор пользователя (каналы), охватывающий несколько тегов span.Используя javascript, я хотел бы получить (нетекстовые) узлы, частично или полностью выделенные (в данном примере это 3 тега span).

Спасибо,

Ответы [ 3 ]

2 голосов
/ 16 марта 2011

Для этого кросс-браузер (включая IE) и довольно удобно, вы можете использовать мою библиотеку Rangy , которая предоставляет расширенные объекты DOM Range и Selection во всех браузерах.Код будет выглядеть примерно так:

var sel = rangy.getSelection();
if (sel.rangeCount) {
    var range = sel.getRangeAt(0);
    var selectedElements = range.getNodes([1]); // [1] is an array of node types
    alert("Found " + selectedElements.length + " selected elements");
}
1 голос
/ 23 апреля 2017

Решение: window.getSelection().getRangeAt(0).cloneContents()
Источник: чей-то удаленный комментарий @ https://stackoverflow.com/questions/43542742/find-text-on-page-and-select-it

Базовый пример

window.getSelection().addRange(new Range());
var dispray = document.querySelectorAll("[id^=dispray]");
var Go = () => {
    var fragm = window.getSelection().getRangeAt(0).cloneContents();
    dispray[0].innerHTML = "";
    dispray[0].appendChild(fragm);
    dispray[1].innerText = dispray[0].innerHTML;
}
#sample {color: red;}
#sample > span {color: green;}
#panel {height: 5em; border: 3px solid #ccc; resize: vertical; overflow-y: scroll;}
#panel > table {width: 100%; height: 100%; /* border-collapse: collapse; */}
#panel > table td {vertical-align: top; padding: 0.5em;}
#panel > table #disprayA {border-right: 1px solid #ccc;}
<p id="sample" onMouseUp="Go()"><span>Lorem ipsum <b>dolor sit</b> amet.⇥</span
> Text node <span>⇤Maecenas <b>porttitor a felis</b> in pharetra.⇥</span><span
>⇤Nulla accumsan auctor est sit amet finibus.</span></p>

<div id="panel"><table><tr>
<td id="disprayA">Copied selection goes here...</td>
<td><code id="disprayB">Source code of copied selection goes here...</code></td>
</tr></table></div>

Полный пример - нет открытых текстовых узлов

Ваше «маленькое» требование, чтобы копия выделения содержала нет пустых текстовых узлов значительно усложняет код.

window.getSelection().addRange(new Range());
var dispray = document.querySelectorAll("[id^=dispray]");
var Go = () => {
    dispray[0].innerHTML = "";
    var r = window.getSelection().getRangeAt(0);
    var fragm = r.cloneContents();
    if ([...fragm.childNodes].some(child => child.nodeType === Node.TEXT_NODE)) {
        /* if selection contains some bare Text nodes... */
        var ancestorElement = r.commonAncestorContainer;
        if (ancestorElement.nodeType === Node.TEXT_NODE)
            ancestorElement = ancestorElement.parentElement;
        var ancestorElement2 = ancestorElement.cloneNode(false);
        ancestorElement2.appendChild(fragm);
        dispray[0].appendChild(ancestorElement2);
    }
    else dispray[0].appendChild(fragm); 
    dispray[1].innerText = dispray[0].innerHTML;
}
#sample {color: red;}
#sample > span {color: green;}
#panel {height: 5em; border: 3px solid #ccc; resize: vertical; overflow-y: scroll;}
#panel > table {width: 100%; height: 100%; /* border-collapse: collapse; */}
#panel > table td {vertical-align: top; padding: 0.5em;}
#panel > table #disprayA {border-right: 1px solid #ccc;}
<p id="sample" onMouseUp="Go()"><span>Lorem ipsum <b>dolor sit</b> amet.⇥</span
> Text node <span>⇤Maecenas <b>porttitor a felis</b> in pharetra.⇥</span><span
>⇤Nulla accumsan auctor est sit amet finibus.</span></p>

<div id="panel"><table><tr>
<td id="disprayA">Copied selection goes here...</td>
<td><code id="disprayB">Source code of copied selection goes here...</code></td>
</tr></table></div>
0 голосов
/ 16 марта 2011

К сожалению, мгновенного решения этой проблемы не существует. Чтобы решить эту проблему, вам нужно будет использовать var sel = window.getSelection(), чтобы получить экземпляр объекта Selection, который представляет выбранные элементы. Оттуда вы можете использовать sel.anchorNode(), чтобы получить элемент, с которого начинается выбор, и sel.focusNode(), чтобы получить элемент, где он заканчивается. Имейте в виду, что это будут экземпляры TextNode и на самом деле они будут дочерними элементами нужного вам диапазона.

Вам нужно будет найти способ определить кратчайший путь между двумя узлами (привязка и фокус), который даст вам всю необходимую информацию.

РЕДАКТИРОВАТЬ: О, кстати, это реализация mozilla / webkit. IE это совершенно другой зверь. Вам нужно будет использовать var sel = document.selection. Проверьте Как я могу получить элемент DOM, который содержит текущий выбор? для получения дополнительной информации о том, как сделать это в кросс-браузерном режиме

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...