我有以下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:语义。
答案 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