在dom元素中插入span而不覆盖子节点?

时间:2015-01-26 10:31:52

标签: javascript jquery html dom nodes

我有一篇HTML文章,其中包含一些我使用SPARQL查询检索的注释。这些注释引用了文档中的一些文本,我必须突出显示该文本(将其包装在一个范围内)。

我已经问过如何在一个范围内包装文本,但现在我有一个更具体的问题,我不知道如何解决。 我写的代码是:

var currentText = $("#"+v[4]["element"]+"").text();
var newText = currentText.substring(0, v[5]["start"]) + "<span class=' annotation' >" + currentText.substring(v[5]["start"], v[6]["end"]) + "</span>" + currentText.substring(v[6]["end"], currentText.length);
$("#"+v[4]["element"]+"").html(newText);

其中:

v[4]["element"]是注释

的父元素的id

v[5]["start"]是注释的第一个字符的位置

v[6]["end"]是annoation的最后一个字符的位置

请注意startend不要考虑使用html代码。

实际上我的错误在于使用text()方法从节点中提取数据(以便能够返回到注释的正确位置)并使用html()方法返回;但是以这种方式,如果父节点有子节点,它们将被丢失并被简单文本覆盖。

实施例: 在&#39; 2003&#39;

上添加注释
<p class="metadata-entry" id="k673f4141ea127b">
    <span class="generated" id="bcf5791f3bcca26">Publication date (<span class="data" id="caa7b9266191929">collection</span>): </span>
    2003
</p>

变成:

<p class="metadata-entry" id="k673f4141ea127b">
    Publication date (collection): 
    <span class="annotation">2003</span>
</p>

我认为我应该使用节点而不是简单地提取和重写内容,但我不知道如何确定插入注释的确切位置,而不考虑html标记而不删除子元素。

我读了一些关于jQuery .contents()方法的内容,但我没有弄清楚如何在我的代码中使用它。

任何人都可以帮我解决这个问题吗?谢谢

编辑:添加了php代码来提取页面正文。

function get_doc_body(){
    if (isset ($_GET ["doc_url"])) {

        $doc_url = $_GET ["doc_url"];
        $doc_name = $_GET ["doc_name"];

        $doc = new DOMDocument;
        $mock_doc = new DOMDocument;

        $doc->loadHTML(file_get_contents($doc_url.'/'.$doc_name));
        $doc_body = $doc->getElementsByTagName('body')->item(0);
        foreach ($doc_body->childNodes as $child){
            $mock_doc->appendChild($mock_doc->importNode($child, true));
        }
        $doc_html = $mock_doc->saveHTML();
        $doc_html = str_replace ('src="images','src="'.$doc_url.'/images',$doc_html);

        echo($doc_html);
    }

}

2 个答案:

答案 0 :(得分:4)

您可以使用$(el).append()$(el).prepend()插入<span>代码,而不是执行所有这些操作!

$("#k673f4141ea127b").append('<span class="annotation">2003</span>');

或者,如果我理解正确,你想用最后的2003包裹span.annotation对吗?如果是这样的话,你可以这样做:

$("#k673f4141ea127b").contents().eq(1).wrap('<span class="annotation" />');

小提琴:

&#13;
&#13;
$(document).ready(function() {
  $("#k673f4141ea127b").contents().eq(1).wrap('<span class="annotation" />');
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="metadata-entry" id="k673f4141ea127b">
    <span class="generated" id="bcf5791f3bcca26">Publication date (<span class="data" id="caa7b9266191929">collection</span>): </span>
    2003
</p>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

最后,我的解决方案在this小提琴。

泛化:

        var element = document.getElementById(id);
        var totalText = element.textContent;
        var toFindText = totalText.substring(start,end);
        var toReplaceText = "<span class='annotation'>"+toFindText+"</span>";
        element.innerHTML = element.innerHTML.replace(toFindText, toReplaceText);

希望它可以帮助别人。

注意:这不会检查两个或多个注释是否指向同一个节点,我现在正在处理它。