Javascript 包裹<;a>;http文本周围的标记
如何查找以http://开头的页面上的每个单词并在其周围加上标记Javascript 包裹<;a>;http文本周围的标记,javascript,jquery,regex,string,Javascript,Jquery,Regex,String,如何查找以http://开头的页面上的每个单词并在其周围加上标记 我可以用一些类似regex的东西吗?我不太实际,但你可以试试 $('a([href^="http://"])').each( function(){ //perform your task }) 这是jQuery不能直接帮助您的少数几件事情之一。基本上,您必须遍历DOM树并检查文本节点(nodeType==3);如果找到包含要换行的目标文本的文本节点(“http://.....,无论您想应用什么规则),然
我可以用一些类似regex的东西吗?我不太实际,但你可以试试
$('a([href^="http://"])').each( function(){
//perform your task
})
这是jQuery不能直接帮助您的少数几件事情之一。基本上,您必须遍历DOM树并检查文本节点(
nodeType==3
);如果找到包含要换行的目标文本的文本节点(“http://.....,无论您想应用什么规则),然后将文本节点(使用)拆分为三个部分(字符串前的部分、字符串中的部分和字符串后的部分),然后将元素放在第二个部分的周围
这听起来有点复杂,但实际上并没有那么糟糕。它只是一个递归下降walker函数(用于处理DOM),一个正则表达式匹配来查找要替换的内容,然后是对splitText
,,,,的几个调用
下面是一个搜索固定字符串的示例;只需添加与“http://”匹配的正则表达式:
更新:如果在同一文本节点(doh!)中存在多个匹配项,则上述操作无法处理该问题。哦,见鬼,我做了一个regexp匹配-你必须调整regexp,并且可能对每个匹配做一些后处理,因为这里的内容太简单了。但这只是一个开始:
// The regexp should have a capture group that
// will be the href. In our case below, we just
// make it the whole thing, but that's up to you.
// THIS REGEXP IS ALMOST CERTAINLY TOO SIMPLISTIC
// AND WILL NEED ADJUSTING (for instance: what if
// the link appears at the end of a sentence and
// it shouldn't include the ending puncutation?).
walk(document.body, /(http:\/\/[^ ]+)/i);
function walk(node, targetRe) {
var child;
switch (node.nodeType) {
case 1: // Element
for (child = node.firstChild;
child;
child = child.nextSibling) {
walk(child, targetRe);
}
break;
case 3: // Text node
handleText(node, targetRe);
break;
}
}
function handleText(node, targetRe) {
var match, targetNode, followingNode, wrapper;
// Does the text contain our target string?
// (This would be a regex test in your http://... case)
match = targetRe.exec(node.nodeValue);
if (match) {
// Split at the beginning of the match
targetNode = node.splitText(match.index);
// Split at the end of the match.
// match[0] is the full text that was matched.
followingNode = targetNode.splitText(match[0].length);
// Wrap the target in an `a` element.
// First we create the wrapper and insert it in front
// of the target text. We use the first capture group
// as the `href`.
wrapper = document.createElement('a');
wrapper.href = match[1];
targetNode.parentNode.insertBefore(wrapper, targetNode);
// Now we move the target text inside it
wrapper.appendChild(targetNode);
// Clean up any empty nodes (in case the target text
// was at the beginning or end of a text ndoe)
if (node.nodeValue.length == 0) {
node.parentNode.removeChild(node);
}
if (followingNode.nodeValue.length == 0) {
followingNode.parentNode.removeChild(followingNode);
}
// Continue with the next match in the node, if any
match = followingNode
? targetRe.exec(followingNode.nodeValue)
: null;
}
}
我非常不同意jQuery在这里找到解决方案时有多大用处。当然,您必须处理一些textNode元素属性,但是在分割匹配的节点后重新组合DOM可以使使用jQuery库变得稍微容易一些
以下代码是内联文档,用于解释所采取的操作。我把它写成了一个jQuery插件,以防你想把它放到别处。通过这种方式,您可以确定要为哪些元素转换URL,或者只需使用$(“body”)选择器
(function($) {
$.fn.anchorTextUrls = function() {
// Test a text node's contents for URLs and split and rebuild it with an achor
var testAndTag = function(el) {
// Test for URLs along whitespace and punctuation boundaries (don't look too hard or you will be consumed)
var m = el.nodeValue.match(/(https?:\/\/.*?)[.!?;,]?(\s+|"|$)/);
// If we've found a valid URL, m[1] contains the URL
if (m) {
// Clone the text node to hold the "tail end" of the split node
var tail = $(el).clone()[0];
// Substring the nodeValue attribute of the text nodes based on the match boundaries
el.nodeValue = el.nodeValue.substring(0, el.nodeValue.indexOf(m[1]));
tail.nodeValue = tail.nodeValue.substring(tail.nodeValue.indexOf(m[1]) + m[1].length);
// Rebuild the DOM inserting the new anchor element between the split text nodes
$(el).after(tail).after($("<a></a>").attr("href", m[1]).html(m[1]));
// Recurse on the new tail node to check for more URLs
testAndTag(tail);
}
// Behave like a function
return false;
}
// For each element selected by jQuery
this.each(function() {
// Select all descendant nodes of the element and pick out only text nodes
var textNodes = $(this).add("*", this).contents().filter(function() {
return this.nodeType == 3
});
// Take action on each text node
$.each(textNodes, function(i, el) {
testAndTag(el);
});
});
}
}(jQuery));
$("body").anchorTextUrls(); //Sample call
(函数($){
$.fn.anchorTextUrls=函数(){
//测试文本节点的URL内容,并使用achor拆分和重建它
var testAndTag=功能(el){
//沿空格和标点符号边界测试URL(不要看得太重,否则会被占用)
var m=el.nodeValue.match(/(https?:\/\/.[.!?;,]?(\s+|“|$)/);
//如果找到了有效的URL,则m[1]包含该URL
如果(m){
//克隆文本节点以保留拆分节点的“尾端”
var tail=$(el.clone()[0];
//基于匹配边界对文本节点的nodeValue属性进行子串
el.nodeValue=el.nodeValue.substring(0,el.nodeValue.indexOf(m[1]);
tail.nodeValue=tail.nodeValue.substring(tail.nodeValue.indexOf(m[1])+m[1].length);
//在拆分文本节点之间插入新的锚元素来重建DOM
$(“Tim:我给了你时间来扩展它,你做到了:)太棒了。谢谢TJ!!如果我能投更多的票,我会的。所以,呃,我们能在这一点上投更多的票吗?这比我的小东西好一公吨,“这已经解决了”。@TJ:对不起,老兄…改变这一点只会让“http://”的范围缩小文本而不是链接的其余部分:walk(document.body,“http://”);请告知..!许多thanks@Tim:这就是我所说的如何扩展它以支持进行正则表达式匹配或类似操作的意思。我只是想说明如何查找文本并将其包装到元素中;如何匹配所需的http模式(可能使用regexp)如评论所示,留给读者作为练习。:-@TJ:lol好的,很公平:)我想我可以从这里算出来-谢谢你的帮助。@Tim为了它的价值,正则表达式尽可能地考虑常见标点符号或空格可能出现在URL的末尾,因此它不必特别以空格分隔。考虑到你使用了jQuery(+更少的代码)并编写了来自地狱的正则表达式-我会将此标记为正确答案。感谢您的时间和JS&jQ卓越!:D@Tim不要看得太近,否则你会被消耗掉的!事实上,我并没有写所有的东西,只是在后面写了边界检查。基地是从上的工作中借来的。应该早点记入贷方。@Tim我只是做了一个sm对textNodes选择器的所有编辑都很重要。我需要使用.add()来代替.find(),以确保标记中包含顶级的文本节点子项。如果只想从所选元素而不是其子项中获取文本节点,只需删除.add()调用。此外,事实证明我的边界正则表达式优于长期设计的混乱,因为它很好地找到了URL的限制,只需要一个起点。啊,是的,这要好得多-以前的正则表达式规则是将任何字符串与一个.连接成一个链接:)现在都很有魅力。非常感谢!
(function($) {
$.fn.anchorTextUrls = function() {
// Test a text node's contents for URLs and split and rebuild it with an achor
var testAndTag = function(el) {
// Test for URLs along whitespace and punctuation boundaries (don't look too hard or you will be consumed)
var m = el.nodeValue.match(/(https?:\/\/.*?)[.!?;,]?(\s+|"|$)/);
// If we've found a valid URL, m[1] contains the URL
if (m) {
// Clone the text node to hold the "tail end" of the split node
var tail = $(el).clone()[0];
// Substring the nodeValue attribute of the text nodes based on the match boundaries
el.nodeValue = el.nodeValue.substring(0, el.nodeValue.indexOf(m[1]));
tail.nodeValue = tail.nodeValue.substring(tail.nodeValue.indexOf(m[1]) + m[1].length);
// Rebuild the DOM inserting the new anchor element between the split text nodes
$(el).after(tail).after($("<a></a>").attr("href", m[1]).html(m[1]));
// Recurse on the new tail node to check for more URLs
testAndTag(tail);
}
// Behave like a function
return false;
}
// For each element selected by jQuery
this.each(function() {
// Select all descendant nodes of the element and pick out only text nodes
var textNodes = $(this).add("*", this).contents().filter(function() {
return this.nodeType == 3
});
// Take action on each text node
$.each(textNodes, function(i, el) {
testAndTag(el);
});
});
}
}(jQuery));
$("body").anchorTextUrls(); //Sample call