Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/410.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/88.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 查找尚未由标记包围的引用,并由标记包围_Javascript_Jquery_Parsing - Fatal编程技术网

Javascript 查找尚未由标记包围的引用,并由标记包围

Javascript 查找尚未由标记包围的引用,并由标记包围,javascript,jquery,parsing,Javascript,Jquery,Parsing,我试图充分利用HTML定义列表,作为带有工具提示的词汇表。有关预期结果,请参见(底部) 如果文章中的部分文本与“定义”列表中的术语相匹配,则将显示工具提示气泡以及匹配的定义。这是由周围的a标记完成的。到目前为止还不错 现在的问题是如何解析这篇文章,以便在术语表中可以找到的所有部分都自动被A标记包围。例如,术语可以是: 团体 社会群体 群体行为 研究 解析必须是“贪婪的”,因此它首先解析最长的定义 var arr = []; /* Array of terms, sorted by lengt

我试图充分利用HTML定义列表,作为带有工具提示的词汇表。有关预期结果,请参见(底部)

如果文章中的部分文本与“定义”列表中的术语相匹配,则将显示工具提示气泡以及匹配的定义。这是由周围的a标记完成的。到目前为止还不错

现在的问题是如何解析这篇文章,以便在术语表中可以找到的所有部分都自动被A标记包围。例如,术语可以是:

  • 团体
  • 社会群体
  • 群体行为
  • 研究
解析必须是“贪婪的”,因此它首先解析最长的定义

var arr = []; /* Array of terms, sorted by length */
$('#glossary dt').each( function() { arr.push($(this).text()); });
arr.sort(function(a,b) { return b.length - a.length; });
接下来,它必须将#article.html中出现的第一个数组项用A-tags包围起来,除非它们已经在A-tags中。这也应该不区分大小写

/* don't know how to approach this */
最后移动到下一个数组项并重复

/* ok, i can figure the loop out myself */
我的问题是检查某个字符串是否已经在a-tags中,以及在文本的一部分周围放置a-tags。应避免替换,以保持大小写相同。检查JSFIDLE以获得预期的结果


编辑:在以下plalx解决方案的基础上,我产生了以下代码:

/*
This script matches text strings in an article with terms in a defintion list (DL);
the DL acts as a glossary. The text strings are wrapped in '<span>' tags,
with the 'title' attribute containing the definition. This allows for easy custom tooltips.

- This script is 'greedy' the longest terms are matched first;
- This script preserves capitalization and escapes HTML in the definitions
 */
var $article = $('#container-inhoud');
var $terms = $('#glossary dt');
//clone to avoid multiple DOM reflows
var $clone = $article.clone();

//create a regex that matches all glossary terms (not case-sensitive), sorted by length
var rx = new RegExp('\\b(' + $terms.map(function () {
            return $(this).text();
        }).get().sort(function (term1, term2) {
                    return term2.length - term1.length;
                }).join('|') + ')\\b', 'ig');


var entityMap = {
    "&": "&amp;",
    "<": "&lt;",
    ">": "&gt;",
    '"': '&quot;',
    "'": '&#39;',
    "/": '&#x2F;'
};

function escapeHtml(string) {
    return String(string).replace(/[&<>"'\/]/g, function (s) {
        return entityMap[s];
    });
}

//wrap any text string that corresponds with a definition term in a 'span' tag
//the title contains the connected definition.
function replacer(match){
        var definition = $terms.filter(function() {
            return $(this).text().toLowerCase() == match.toLowerCase();
        }).next('dd').text();
        definition = escapeHtml(definition);
        return '<span class="tooltip" title="' + definition + '">' + match + '</span>';
}

//call the replace function for every regex match
$clone.html($clone.html().replace(rx , replacer));

//unwrap the terms in the glossary section (to avoid tooltips within the glossary itself)
//only needed if the #glossary is within the #article container, otherwise delete the next line.
$clone.find('#glossary .tooltip').contents().unwrap();

$article.replaceWith($clone);
我曾经使用以下CSS设置工具提示气泡的格式:

#bubble{
            -webkit-border-radius: 4px;
            -moz-border-radius: 4px;
            border-radius: 4px;
            border: 1px solid #888;
            color: #ee6c31;
            background-color: rgba(255, 255, 255, 0.85);
            position:absolute;
            z-index:200;
            padding:5px 8px;
            margin: -15px 5px 5px -10px;
            display:none;
        }

不要将dt文本收集到数组中,而是收集dom项本身,然后创建如下函数:

function add_tags(td) {
    var dd = td.next(),
        q = td.text()
        txt = dd.text().replace(q, '<a href="#">'+q+'</a>');

    dd.html(txt);
};
功能添加标签(td){
var dd=td.next(),
q=td.text()
txt=dd.text().replace(q',);
dd.html(txt);
};

然后循环它。您可能想添加一些检查功能,看看您的单词周围是否已经有任何a标记,但这是一个很好的开始

我为您设计了一个小解决方案。我想这就是你想要的:

HTML示例:

<div id="glossary">
    <dt>test</dt>
    <dt>Testing</dt>
    <dt>something</dt>
    <dt>some other thing</dt>
    <dt>long test</dt>
</div>

<div id="article">
    this is a test, to see if Testing will correctly be wrapped by something, or some other thing.
    This <a data-glossary-term href="#test">test</a> should not be wrapped again however, <span>something</span> should!
    Very long test should also be wrapped first.
</div>

测试
测试
某物
还有别的事
长期测试
这是一个测试,看看测试是否正确地被某个东西或其他东西包装起来。
这不应该再次包装,但是,应该有东西!
很长的测试也应该先包起来。
JS:

$(函数(){
var$article=$(“#article”),
//克隆以避免多次DOM回流
$clone=$article.clone(),
//创建一个匹配所有术语表术语的正则表达式(不区分大小写)
rx=new RegExp('\\b('+$('#glossary dt').map(函数(){
返回$(this.text();
}).get().sort(函数(term1、term2){
返回term2.length-term1.length;
}).join(“|”)+”)\\b,“ig”);
//打开以前包装的术语表术语以避免出现问题
//如果您的初始标记尚未包装术语,则不需要这样做
$clone.find(“[data glossary term]”)。每个(函数(){
$(this.replaceWith)(this.childNodes);
});
//将术语包装在“a”标记中
$clone.html($clone.html().replace(rx,');
$article.replacetwith($clone);
});

请看一看“谢谢”,我现在正试图绕开这一点。如果保存文章内容的节点的父元素不包含任何其他行为直接附加到它们的元素,您可以使用答案中描述的easy regex替换解决方案。如果行为是使用委托附加的,那么替换文章容器的
innerHTML
值不会导致问题。我想我需要数组,因为我需要先按长度排序。正如我所说,简单的replace()可能不适用于大写字母。例如,我希望“Research”与“Research”匹配,但不能用小写字母代替。在您的示例中,A标记的check函数应该放在replace()方法的第二个参数中,对吗?我没有说完全删除数组,我说的是不要为td内的文本构建数组,而是为td本身构建数组。然后根据文本的长度对其排序,并循环我的函数。这只是一个一般的例子,不是一个完整的解决方案。我试着向你展示你不知道如何认可的东西,我明白了。不过,我似乎让那部分工作起来了。也许我的解决方案是次优的不不不。。。我只是在想你应该做些别的事情(在dd中搜索每个td的关键字),但是你现在的小提琴把事情弄清楚了一点。我认为plalx给了你一个更完整的解决方案,直到你不得不检查它,但它有这么多的美丽。正如你们可能已经了解到的,我对javascript是新手,但你们正在使它看起来很好。就像我的魅力一样,但我必须通读正则表达式才能完全理解它。我必须做一些工作:“替换”的问题是它不尊重原始资本。假设一个句子以“某物”开头,这将被“某物”取代。现在,A标记将替换以前的A标记。即使原始A标记跨越更长的文本位,其中包括一个术语。这对我来说不是问题,但是让行为成为可选的会很好。再次感谢您的努力。@snirp基本上,当您修改DOM元素时,它会导致我在这里克隆初始节点,以便在文档流之外使用该元素,以避免在删除初始数据词汇表术语,然后更改该元素的innerHTML属性时出现多次回流。如果不必删除初始术语表术语,则不必使用克隆,因为将执行的唯一操作是更改
innerHTML
prperty,从而导致一次回流。@snirp,您确定它不保留大小写吗?应该是这样的,因为我在replace模式中使用了对捕获组的引用。它对我有用。看一下测试单词。至于初始标记,我将在稍后查看解决方案,因为今天上午时间不够;)@snirp我很高兴我的解决方案能够帮助您构建适合您需求的产品!也许你不需要克隆,而需要合作
<div id="glossary">
    <dt>test</dt>
    <dt>Testing</dt>
    <dt>something</dt>
    <dt>some other thing</dt>
    <dt>long test</dt>
</div>

<div id="article">
    this is a test, to see if Testing will correctly be wrapped by something, or some other thing.
    This <a data-glossary-term href="#test">test</a> should not be wrapped again however, <span>something</span> should!
    Very long test should also be wrapped first.
</div>
$(function () {
    var $article = $('#article'),
        //clone to avoid multiple DOM reflows
        $clone = $article.clone(),
        //create a regex that matches all glossary terms (not case-sensitive)
        rx = new RegExp('\\b(' + $('#glossary dt').map(function () {
            return $(this).text();
        }).get().sort(function (term1, term2) {
            return term2.length - term1.length;
        }).join('|') + ')\\b', 'ig');

    //unwrap previously wrapped glossary terms to avoid issues
    //this would not be needed if your initial markup doesn't have terms wrapped already
    $clone.find('[data-glossary-term]').each(function () {
        $(this).replaceWith(this.childNodes);
    });

    //wrap terms in the 'a' tag
    $clone.html($clone.html().replace(rx, '<a data-glossary-term="$1" href="#$1">$1</a>'));

    $article.replaceWith($clone);
});