Выделение текста путем игнорирования внутренних элементов тега div javascript

<html>
<body>
<script language="javascript">
function getSelectionHTML()
{
    var div = document.getElementById("myDiv");

    if (document.createRange) { 
        var textNode=div.firstChild;
        var rangeObj=document.createRange();
        rangeObj.setStart(textNode,0);
        rangeObj.setEnd(textNode,5);
        div .innerHTML = div .innerHTML.replace(rangeObj.toString(), '<span style="background-color: lime">'+rangeObj.toString()+'</span>')
    }
}
</script>
<div id="myDiv">
asdf as<b>dfas df asf asdf sdfjk  dvh a sjkh jhcdjkv</b> iof scjahjkv ahsjv hdjk biud fcsvjksdhf k

</div>
<form name="aform">
<input type="button" value="Get selection" onclick="getSelectionHTML()">
</body>
</html>

Хорошо. Позвольте мне объяснить -> метод getSelectionHTML() предназначен для выбора символов от 0 до 10. Я получаю значения по идентификатору "myDiv". но внутренние полужирные, курсивные и другие теги доставляют мне неприятности.

Проще говоря, я просто хочу сделать выбор из первых десяти символов (и применить их к тегу span), которые находятся в теге "myDiv".

Что именно мне не хватает?

2 ответа

Решение

Вы пытаетесь выбрать, например, символы от 1 до 10 вашего текста. Но при использовании Range.setStart а также .endStart Первый параметр - это текстовый узел, содержащий ваш текст. Если вы просматриваете DOM с помощью Firebug (или Web Inspector), вы заметите, что символ 10 вашего текста находится в другом элементе (<b> элемент), с собственным текстовым узлом.

Кстати, вы пропустили несколько обязательных элементов / тегов, которые также могут быть источником ошибок.

Моя исправленная версия читает

<!DOCTYPE html>
<html>
<head>
  <title>Title element is required</title>
<body>
<script>
function getSelectionHTML()
{
    var div = document.getElementById("myDiv");
    var bEl = document.getElementById("bEl");

    if (document.createRange) {.
        var textNode=div.firstChild;
        var rangeObj=document.createRange();
        rangeObj.setStart(textNode,0);
        rangeObj.setEnd(bEl.firstChild,2);
        alert(rangeObj.toString());
//        div.innerHTML = div.innerHTML.replace(rangeObj.toString(), '<span style="background-color: lime">'+rangeObj.toString()+'</span>');
    }
}
</script>
<div id="myDiv">
asdf as<b id="bEl">dfas df asf asdf sdfjk  dvh a sjkh jhcdjkv</b> iof scjahjkv ahsjv hdjk biud fcsvjksdhf k
</div>
<form name="aform">
  <input type="button" value="Get selection" onclick="getSelectionHTML()">
</form>
</body>
</html>

Сейчас rangeObj содержит выделенный текст, но вы не можете просто вставить <span> элемент, как вы пытались, потому что элементы не могут быть вложены таким образом:

<span>asdf as<b>dfa</span>s df asf…

Это намного проще в использовании IE TextRange, который основан на символах, словах и предложениях, а не на узлах и смещениях. В браузерах, отличных от IE, вам придется утомительно обходить текстовые узлы вручную в DOM. Однако, даже если вы должны были сделать это, чтобы получить первые десять текстовых символов в вашем <div> (что будет "asdf asdfa"), ваша стратегия имеет недостатки, потому что вы используете замену на innerHTML, который попытался бы и не смог найти "asdf asdfa" (innerHTML будет начинаться с "asdf как<b>dfa "или, возможно," asdf как<B>", в зависимости от браузера).

Я хотел бы предложить выполнить обход DOM, чтобы найти все текстовые узлы в пределах <div> и окружая части текстовых узлов, которые вам нужны <span>s, таким образом, избегая диапазонов в целом и, следовательно, заставляя это работать во всех основных браузерах.

Другие вопросы по тегам