我正在为我的网络应用构建键盘访问库。要提示应按下哪些键,我想在链接中加下键。 E.g。
O rders --- 我 nvoices --- Ope n 事件
对于纯文本片段,这很容易(这里使用jQuery):
part.html(part.html().replace(new RegExp(key, 'i'), '<u>$&</u>'));
但如果part
内有任何html标记,这会破坏性。是否有一种优雅的方式来更新文本节点而永远不会标记?
澄清:我的用例是数百个嵌套模板服务器端生成HTML。目前手动添加accesskey
属性。导致像<a href="angebote.html" accesskey="t"><i class="fa fa-fw fa-podcast"></i>Ange<b>bote</b></a>
这样的事情。然后,Javascript前端脚本会添加键绑定并尝试为绑定键加下划线。
答案 0 :(得分:2)
要仅访问文本节点,并在那里进行替换,您可以使用树步行器。我还会创建一个函数来隔离span
元素中找到的字母并返回它。然后你可以使用jQuery(或其他任何方法)来装饰你想要的元素:
function getLetter(elem, letter){
if (elem.get) elem = elem.get(0); // remove jQuery wrapper
var nodes = document.createTreeWalker(elem, NodeFilter.SHOW_TEXT, null, null),
$node, text, pos, $span;
letter = letter.toLowerCase();
while ($node = $(nodes.nextNode())) {
text = $node.text();
pos = text.toLowerCase().indexOf(letter);
if (pos > -1) {
$span = $('<span>').text(text[pos]);
$node.replaceWith( // separate the letter from the other text
text.substr(0, pos),
$span,
text.substr(pos+1)
);
return $span; // return the element that just has that one letter
}
}
}
getLetter($('#orders'), 'o').addClass('underline');
getLetter($('#invoices'), 'i').addClass('underline');
getLetter($('#incidents'), 'n').addClass('underline');
.underline { text-decoration: underline }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h3>Some mix of HTML:</h3>
<div id="orders">
<span style="color: purple">Order<i>(s)</i></span>
</div>
<div id="invoices">
<ul><li><b>!!</b>Invoices <i>(urgent)</i></li></ul>
</div>
<div id="incidents">
<table style="border: 1px solid"><tr><td>Open</td><td>incidents</td></tr></table>
</div>
该函数有两个参数:
elem
:包含需要搜索的文本的容器元素。此元素可能有也可能没有嵌套的HTML标记。letter
:要在该元素中识别的字母:只有该字母的第一次出现才会起作用。 该函数返回:
undefined
当没有匹配时,即所提供的元素包含的任何文本中不会出现提供的字母。span
元素:它将包含找到的字母。其余文本放在该新元素之前和之后的单独文本节点中。答案 1 :(得分:1)
对于单个字母,range API应该是微不足道的,因为它们不会被分割为多个嵌套节点。
let range = document.createRange();
let div = document.createElement("div")
div.textContent = "Orders --- Invoices --- Open Incidents"
let textNode = div.firstChild
let underline = document.createElement("u")
range.setStart(textNode, 0);
range.setEnd(textNode, 1);
range.surroundContents(underline);
console.log(div.outerHTML)
// <div><u>O</u>rders --- Invoices --- Open Incidents</div>
答案 2 :(得分:0)
[].forEach.call(document.getElementsByTagName('a'),function(el){
el.innerHTML=el.innerHTML.replace(el.getAttribute('acceskey'),
'<u>'+el.getAttribute('acceskey')+'</u>')
})
在此处试试:JS FIddle