访问段落

时间:2017-10-06 16:10:58

标签: javascript

我有以下HTML:

<p>
    So many frogs were falling out of the sky 
    <sup>
        <span id="footnote-1">1</span>
    </sup> 
    that the even the priests
    <sup>
        <span id="footnote-2">2</span>
    </sup> 
    didn't know what to do.
</p>

假设我无法改变HTML本身的结构,当用户点击任意脚注时,如何使用Javascript直接修改后面的单词脚注?

示例:用户点击footnote-2然后单词“did not”变为红色。

一些模糊的想法,其中没有一个是美妙的。

1)花哨的正则表达式?

2)用<span>标签包装段落中的每个单词,然后选择那个?

感谢您的帮助。

Shell代码,只是为了明确。

document.getElementById('footnote-2').addEventListener('click', function(){
    // something something something...
    // the word "didn't" is now red.
});

编辑:jQuery中的答案很好,按照下面的问题。

编辑2:在我对问题的原始描述中,我几乎不够明确。

编辑3:语义。

1 个答案:

答案 0 :(得分:1)

“1)花哨的正则表达式?”绝对不是。 : - )

第1步必须修复HTML,div内的sup无效。 sup只能包含措辞内容div流量内容。 (这很重要,浏览器可能会重新排序以尝试修复它。)为了这个答案的目的,我将用div替换那些span元素。

注意:这个问题最初并不清楚OP无法改变HTML,事实上似乎说他/她可以。继续阅读,我们继续创建稍后以编程方式span。)

相反,如你所说,将第一个单词包装在一个范围内:

<p>
    So many frogs were falling out of the sky 
    <sup>
        <span id="footnote-1">1</span>
    </sup> 
    <span class="firstword">that</span> the even the priests
    <sup>
        <span id="footnote-2">2</span>
    </sup> 
    <span class="firstword">didn't</span> know what to do.
</p>

...然后在单击脚注时向该范围添加一个类。您可以像这样在处理程序中获取范围:

this.parentNode.nextElementSibling

根据任何共同特征找出脚注;您可以为它们添加一个类,但您可以通过[id^=footnote-]按原样选择它们(匹配id"footnote-"开头的任何元素。)

例如:

function footnoteClick() {
    this.parentNode.nextElementSibling.classList.add("active");
}
document.querySelectorAll('[id^=footnote-]').forEach(function(e) {
    e.addEventListener('click', footnoteClick);
});

或者更具防御性,footnoteClick可能是:

function footnoteClick() {
    var sib = this.parentNode.nextElementSibling;
    if (sib && sib.classList.contains("firstword")) {
        sib.classList.toggle("active");
    }
}

...您可以使用toggle而不是add,以便红色在重复点击时开启和关闭。

直播示例(带toggle):

if (typeof NodeList !== "undefined" &&
    NodeList.prototype &&
    !NodeList.prototype.forEach) {
    Object.defineProperty(NodeList.prototype, "forEach", {
        value: Array.prototype.forEach
    });
}

function footnoteClick() {
    var sib = this.parentNode.nextElementSibling;
    if (sib && sib.classList.contains("firstword")) {
        sib.classList.toggle("active");
    }
}
document.querySelectorAll('[id^=footnote-]').forEach(function(e) {
    e.addEventListener('click', footnoteClick);
});
.active {
  color: red;
}
<p>
    So many frogs were falling out of the sky 
    <sup>
        <span id="footnote-1">1</span>
    </sup> 
    <span class="firstword">that</span> the even the priests
    <sup>
        <span id="footnote-2">2</span>
    </sup> 
    <span class="firstword">didn't</span> know what to do.
</p>

在评论中,您说过无法更改HTML结构。但是,您将 更改HTML结构,以修复div - 内部 - { - 1}}问题。但是,如果你不能在脚注中添加脚注后面的第一个单词,我们可以动态处理该部分;见评论:

sup

直播示例(带function footnoteClick() { var sib = this.parentNode.nextElementSibling; if (!sib || !sib.classList.contains("firstword")) { // This is the first time, we have to wrap the // word in a span; create the span sib = document.createElement("span"); sib.classList.add("firstword"); // Get the text node var textNode = this.parentNode.nextSibling; // Remove leading and trailing whitespace textNode.nodeValue = textNode.nodeValue.trim(); // Find the end of the first word var endIndex = textNode.nodeValue.indexOf(" "); if (endIndex != -1) { // Have to split it textNode.splitText(endIndex); } // Insert the span and move the word into it textNode.parentNode.insertBefore(sib, textNode); sib.appendChild(textNode); } if (sib) { sib.classList.toggle("active"); } } ):

toggle
if (typeof NodeList !== "undefined" &&
    NodeList.prototype &&
    !NodeList.prototype.forEach) {
    Object.defineProperty(NodeList.prototype, "forEach", {
        value: Array.prototype.forEach
    });
}

function footnoteClick() {
    var sib = this.parentNode.nextElementSibling;
    if (!sib || !sib.classList.contains("firstword")) {
        // This is the first time, we have to wrap the
        // word in a span; create the span
        sib = document.createElement("span");
        sib.classList.add("firstword");
        // Get the text node
        var textNode = this.parentNode.nextSibling;
        // Remove leading and trailing whitespace
        textNode.nodeValue = textNode.nodeValue.trim();
        // Find the end of the first word
        var endIndex = textNode.nodeValue.indexOf(" ");
        if (endIndex != -1) {
            // Have to split it
            textNode.splitText(endIndex);
        }
        // Insert the span and move the word into it
        textNode.parentNode.insertBefore(sib, textNode);
        sib.appendChild(textNode);
    }
    if (sib) {
        sib.classList.toggle("active");
    }
}
document.querySelectorAll('[id^=footnote-]').forEach(function(e) {
    e.addEventListener('click', footnoteClick);
});
.active {
  color: red;
}

附注:<p> So many frogs were falling out of the sky <sup> <span id="footnote-1">1</span> </sup> that the even the priests <sup> <span id="footnote-2">2</span> </sup> didn't know what to do. </p>返回的NodeList上的forEach方法相对较新;对于旧版浏览器,您可能需要对其进行填充:

querySelectorAll

对于像IE8这样的真正过时的浏览器,您可能需要先填充if (typeof NodeList !== "undefined" && NodeList.prototype && !NodeList.prototype.forEach) { Object.defineProperty(NodeList.prototype, "forEach", { value: Array.prototype.forEach }); }

DOM规范中涵盖了上述各种操作:https://www.w3.org/DOM/DOMTR