当用锚点链接替换匹配的关键字文本时,以下内容为何会消除空白?请注意,此错误仅在Chrome中发生,而不在Firefox中发生。
为了获得完整的上下文,文件位于:http://seox.org/lbp/lb-core.js
要查看运行中的代码(尚未发现错误),演示页面位于http://seox.org/test.html。将第一段复制/粘贴到RTF编辑器(即Dreamweaver或启用了RTF编辑器的gmail)中,就会发现问题所在,单词堆积在一起。不会将其粘贴到纯文本编辑器中。
// Find page text (not in links) -> doxdesk.com
function findPlainTextExceptInLinks(element, substring, callback) {
for (var childi= element.childNodes.length; childi-->0;) {
var child= element.childNodes[childi];
if (child.nodeType===1) {
if (child.tagName.toLowerCase()!=='a')
findPlainTextExceptInLinks(child, substring, callback);
} else if (child.nodeType===3) {
var index= child.data.length;
while (true) {
index= child.data.lastIndexOf(substring, index);
if (index===-1 || limit.indexOf(substring.toLowerCase()) !== -1)
break;
// don't match an alphanumeric char
var dontMatch =/\w/;
if(child.nodeValue.charAt(index - 1).match(dontMatch) || child.nodeValue.charAt(index+keyword.length).match(dontMatch))
break;
// alert(child.nodeValue.charAt(index+keyword.length + 1));
callback.call(window, child, index)
}
}
}
}
// Linkup function, call with various type cases (below)
function linkup(node, index) {
node.splitText(index+keyword.length);
var a= document.createElement('a');
a.href= linkUrl;
a.appendChild(node.splitText(index));
node.parentNode.insertBefore(a, node.nextSibling);
limit.push(keyword.toLowerCase()); // Add the keyword to memory
urlMemory.push(linkUrl); // Add the url to memory
}
// lower case (already applied)
findPlainTextExceptInLinks(lbp.vrs.holder, keyword, linkup);
在此先感谢您的帮助。我几乎准备启动该脚本,并将很高兴为您提供帮助,以荣誉表示感谢。
最佳答案
与链接功能无关。碰巧也会复制页面上已经存在的链接和credit
内容,即使processSel()
调用已被注释掉。
Chrome的RTF复制功能似乎是一个奇怪的错误。 holder
中的内容可以;如果您克隆选定范围的Contents并在最后警告其innerHTML,则空格很明显。但是,任何内联元素(不仅仅是链接!)之前,之后和内部边缘的空格都不会以富文本格式显示。
即使您将新文本节点添加到包含链接旁边空格的DOM中,Chrome也会吞下它们。通过插入不间断的空格,我可以使它看起来正确:
var links= lbp.vrs.holder.getElementsByTagName('a');
for (var i= links.length; i-->0;) {
links[i].parentNode.insertBefore(document.createTextNode('\xA0 '), links[i]);
links[i].parentNode.insertBefore(document.createTextNode(' \xA0), links[i].nextSibling);
}
但这很丑陋,应该是不必要的,并且不能修复其他内联元素。镀铬不好!
var keyword = links[i].innerHTML.toLowerCase();
依靠
innerHTML
从元素中获取文本是不明智的,因为浏览器可能会在元素中转义或不转义字符。最值得注意的是&
,但是不能保证浏览器的innerHTML
属性将输出哪些字符。您似乎已经在使用jQuery,请改为使用
text()
捕获内容。var isDomain = new RegExp(document.domain, 'g');
if (isDomain.test(linkUrl)) { ...
这将每隔第二次失败,因为
g
小数正则表达式会记住其先前状态(lastIndex
):当与test
之类的方法一起使用时,您应该不断重复调用直到它们不返回任何匹配项为止。您似乎在这里不需要
g
(多个匹配项)...但是您似乎也不需要在这里使用正则表达式,因为简单的String indexOf
会更可靠。 (在正则表达式中,域中的每个.
都将匹配链接中的任何字符。)更好的是,使用
Location
上的URL分解属性直接比较主机名,而不是对整个URL进行粗略的字符串匹配:if (location.hostname===links[i].hostname) { ...
// don't match an alphanumeric char
var dontMatch =/\w/;
if(child.nodeValue.charAt(index - 1).match(dontMatch) || child.nodeValue.charAt(index+keyword.length).match(dontMatch))
break;
如果您想匹配单词边界上的单词,并且不区分大小写,我认为使用正则表达式而不是纯子字符串匹配会更好。这样一来,每个关键字现在都可以对
findText
进行四个调用。您可以在this answer中获取函数的内部位(在if (child.nodeType==3) { ...
中),并使用它代替当前的字符串匹配。从字符串制作正则表达式的烦人的事情是在标点符号中添加了反斜杠,因此您需要一个函数:
// Backslash-escape string for literal use in a RegExp
//
function RegExp_escape(s) {
return s.replace(/([/\\^$*+?.()|[\]{}])/g, '\\$1')
};
var keywordre= new RegExp('\\b'+RegExp_escape(keyword)+'\\b', 'gi');
您甚至可以一次完成所有关键字替换,以提高效率:
var keywords= [];
var hrefs= [];
for (var i=0; i<links.length; i++) {
...
var text= $(links[i]).text();
keywords.push('(\\b'+RegExp_escape(text)+'\\b)');
hrefs.push[text]= links[i].href;
}
var keywordre= new RegExp(keywords.join('|'), 'gi');
然后对于
linkup
中的每个匹配项,检查哪个匹配组的长度不为零,并链接相同编号的hrefs[
。