如何在选择之前,之内和之后获取HTML(不在textarea中)?

时间:2012-03-02 17:49:25

标签: javascript html rangy

以下是我要完成的任务:当用户使用鼠标,键盘或触摸选择“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片段。这是“背景”。

使用这些数据的组合,我应该能够在大多数时间重新定位最初选择的文本,即使它已移动或部分更改。当失败时,UI将有办法解决它,但我希望尽可能少发生。

Superthanks!

2 个答案:

答案 0 :(得分:1)

我有几个问题:

1.-当你说'选择后的html'时 - 那个html与选择之前的html有什么不同,反之亦然?由于你的“脚本”或其他什么,“选择”过程本身是否篡改了html?

2.-你说文字选择不是在textareas中发生的......那你使用的是什么元素?段落? div的...?缩小范围会有所帮助。

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


});

复制选择:

如上所述:

Selecting text in an element (akin to highlighting with your mouse)

杰森写了以下函数:

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/

您可以使用它来获取所选文本。你只需要相应地调整它,因为他从一个反向角度接近它。 您可以提供给我们的详细信息......我们可以提供更好的帮助。

希望这会有所帮助
ģ

答案 1 :(得分:0)

此代码从用户的选择中获取html / text,但它仅适用于IE。该代码也适用于交叉标记选择。 (Globals用于保持代码简短。)

<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之外的任何其他元素,则必须使其无法选择。