Как получить HTML до, внутри и после выделения (не в текстовой области)? - PullRequest
9 голосов
/ 02 марта 2012

Вот что я пытаюсь сделать: когда пользователь использует мышь, клавиатуру или сенсорный экран для выделения текста внутри «myDiv», я хочу получить три дискретных фрагмента HTML: HTML-код перед выделением (слева) «этого», HTML-код внутри выделения и HTML-код после выделения («справа» от него). HTML должен быть таким, каким он выглядит с myDiv.innerHTML.

Выбор может начинаться или заканчиваться внутри пары тегов (т. Е. Изолированный выбор не обязательно является допустимым HTML). Мне не нужно иметь дело со специальными сценариями, такими как элементы с абсолютным позиционированием в выделении; все выбранные мной варианты будут ограничены одним div, который будет содержать основные теги, такие как strong, em, ul, ol, h1, image и table.

Самое близкое, что я получил, - это использование rangy для захвата выбора и вызов selection.getRangeAt(0).cloneContents() для получения HTML-кода выбора. Это работает достаточно хорошо, пока я не сделаю выделение, которое недопустимо изолированно, и браузер не изменит HTML-фрагмент документа, чтобы сделать его допустимой разметкой.

Дополнительная информация: Вот почему мне это нужно:

Я создаю систему обратной связи с документами, поэтому мне нужно сохранить информацию о выборе в базу данных для последующего поиска и восстановления. Обычно я сохраняю выделение, используя путь DOM и выделенный текст, но текст может измениться между сохранением и восстановлением. Например, автор может перемещать целые абзацы, удалять разделы и т. Д. Путь DOM становится довольно бесполезным.

Так что мой (несовершенный) план - сохранить выделение как [offset, length, html_snippet]. Это «позиция». Я также сохраню фрагменты html, которые пришли непосредственно до и после выделенного текста. Это и есть «контекст».

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

Superthanks!

Ответы [ 2 ]

1 голос
/ 03 марта 2012

У меня есть несколько вопросов:

1.- Когда вы говорите «HTML после выбора» - как этот HTML будет отличаться от HTML до выбора или наоборот? Является ли сам процесс «выбора» вмешательством в HTML из-за вашего «сценария» или чего-то еще?

2.- Вы сказали, что выделение текста не происходит в текстовых областях ... с какими элементами вы работаете тогда? пункты? дивы ...? Сужение поможет.

3.- Думали ли вы использовать jquery?

http://api.jquery.com/select/

Делать что-то вроде

$('#element_with_text_goes_here').select(function() {

//apply grabbing functions here, for example

//copy html 'before' selection:
     $pre_html = $('html').clone();

   // copy selection...see below:

   // copy html 'after' selection'...same as before


});

Выбор копии:

Как отмечено здесь:

Выбор текста в элементе (сродни выделению мышью)

Джейсон написал следующую функцию:

function selectText(element) {
    var doc = document;
    var text = doc.getElementById(element);    

    if (doc.body.createTextRange) { // ms
        var range = doc.body.createTextRange();
        range.moveToElementText(text);
        range.select();
    } else if (window.getSelection) { // moz, opera, webkit
        var selection = window.getSelection();            
        var range = doc.createRange();
        range.selectNodeContents(text);
        selection.removeAllRanges();
        selection.addRange(range);
    }
}

С живой демо-версией, которую можно найти здесь: http://jsfiddle.net/edelman/KcX6A/339/

И версия плагина jquery здесь: http://jsfiddle.net/edelman/KcX6A/340/

Который вы можете использовать для получения выделенного текста. Вам просто нужно настроить его соответственно, так как он приближался к нему под обратным углом. Чем больше деталей вы нам можете дать ... тем лучше мы можем помочь.

Надеюсь, это поможет
G

0 голосов
/ 03 марта 2012

Этот код получает html / текст по выбору пользователя, но работает только в IE.Код также работает с выбором кросс-тегов.(Глобальные значения использовались для краткости кода.)

<script>
function selected(){
    thediv=document.getElementById('div');
    res=document.getElementById('htm');
    userSelection=document.selection;
    userRange=userSelection.createRange();
    /* For wider scale of elements */
    // rangeParent=userRange.parentElement();
    // if(rangeParent!=thediv) userRange.moveToElementText(rangeParent);
    rangeText=userRange.htmlText;   // OR: rangeText=userRange.text;
    res.innerText=rangeText;    
    return; 
}    
</script>
</head>    
<body onload="document.onselectionchange=selected;">
<div id="div">
<h1>The great testpage</h1>
<p>A paragraph with some text</p>
<p>This paragraph <b>contains</b> a child element.</p>
<p>And this is the last paragraph.</p>
<table>
<tr><td>Cell1-1</td><td>cell1-2</td></tr>
<tr><td>Cell2-1</td><td>cell2-2</td></tr>
</table>
<ol>
<li>item1</li>
<li>item2</li>
<li>item3</li>
</ol>
</div>
<br>
<span id="htm"></span>
</body>

Содержимое до и после выделения в thediv вы получите примерно так: prepost=thediv.innerHTML/innerText.split(rangeText);

Если страница содержит какие-либо другие элементыно thediv, их нужно сделать невыбираемыми.

...