Javascript 如何在网页上动态突出显示字符串?

Javascript 如何在网页上动态突出显示字符串?,javascript,jquery,html,css,meteor,Javascript,Jquery,Html,Css,Meteor,我想创建包含URL的页面,例如: http://xyzcorp/schedules/2015Aug24_Aug28/Jim_Hawkins http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones http://xyzcorp/schedules/2015Aug24_Aug28/John_Silver 这些特定URL将包含完全相同的内容(“2015Aug24_Aug28”页面),但将突出显示标记在末尾的名称的所有实例。例如,“http://xyz

我想创建包含URL的页面,例如:

http://xyzcorp/schedules/2015Aug24_Aug28/Jim_Hawkins
http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones
http://xyzcorp/schedules/2015Aug24_Aug28/John_Silver
这些特定URL将包含完全相同的内容(“2015Aug24_Aug28”页面),但将突出显示标记在末尾的名称的所有实例。例如,“
http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones
“将突出显示名称“Billy Bones”的每个实例,就好像该名称的“查找”是通过浏览器在页面上执行的

我认为需要这样的东西,客户端:

var employee = getLastURLPortion(); // return "Billy_Bones" (or whatever)
employee = humanifyTheName(employee); // replaces underscores with spaces, so that it's "Billy Bones" (etc.)
Highlight(employee); // this I have no clue how to do

这可以在HTML/CSS中完成吗,或者也需要JavaScript或jQuery吗?

我使用以下正则表达式替换所有匹配的url,用突出显示的文本创建锚定:

(http://xyzcorp/schedules/(.*?)/)(.*?)( |<|\n|\r|$)

(http://xyzcorp/schedules/(.*?/)(.*?)(|一种解决方案是,在加载窗口后,递归遍历所有节点,并使用突出显示类将搜索项包装在文本节点中。这样,就不会保留原始结构和事件订阅

(这里,使用jquery,但可以不使用):

Javascript:
$(函数(){
//从url获取术语
//var term=window.location.href.match(/\/(\w+)\/?$/)[1]。替换(“”,“”);
var术语组http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones/“.match(/\/(\w+)\/?$/)[1]。替换(“\”,”);
//搜索regexp
var re=new RegExp(“(“+term+”)”,“gi”);
//递归函数
功能远光灯(elem){
var contents=$(elem.contents();
如果(contents.length>0){
contents.each(函数(){
强光术语(本);
});
}否则{
//文本节点
if(elem.nodeType==3){
变量$elem=$(elem);
var text=$elem.text();
if(重新测试(文本)){
$elem.wrap(“”.parent().html(text.replace(re,$1'));
}
}
}
}
highlightTerm(document.body);
});
。突出显示{
背景颜色:黄色;
}

我想创建包含URL的页面,例如:

http://xyzcorp/schedules/2015Aug24_Aug28/Jim_Hawkins
http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones
http://xyzcorp/schedules/2015Aug24_Aug28/John_Silver

http
:
//xyzcorp/schedules/2015年8月24日/28日/Jim_Hawkins
http
:
//xyzcorp/schedules/2015年8月24日/28日/Billy\u Bones
http
:
//xyzcorp/schedules/2015年8月24日/28日/John_Silver
这些特定URL都将包含完全相同的内容(“2015Aug24_Aug28”页面),但将突出显示标记在末尾的名称的所有实例。例如,“
http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones
将突出显示名称“Billy Bones”的每个实例,就好像该名称的“查找”是通过浏览器在页面上执行的

我认为需要这样的东西,客户端:

var employee = getLastURLPortion(); // return "Billy_Bones" (or whatever)
employee = humanifyTheName(employee); // replaces underscores with spaces, so that it's "Billy Bones" (etc.)
Highlight(employee); // this I have no clue how to do

变量
雇员
=
GetLastUrlPart
();
//返回“Billy_Bones”(或其他)
雇员
=
人名
(
雇员
);
//将下划线替换为空格,使其成为“Billy Bones”(等)
突出
(
雇员
);
//我不知道该怎么做
这可以在HTML/CSS中完成,还是需要JavaScript或jQuery


如果调用该函数

highlight(employee);
这就是ECMAScript 2018+中该函数的外观:

function highlight(employee){
  Array.from(document.querySelectorAll("body, body *:not(script):not(style):not(noscript)"))
    .flatMap(({childNodes}) => [...childNodes])
    .filter(({nodeType, textContent}) => nodeType === document.TEXT_NODE && textContent.includes(employee))
    .forEach((textNode) => textNode.replaceWith(...textNode.textContent.split(employee).flatMap((part) => [
        document.createTextNode(part),
        Object.assign(document.createElement("mark"), {
          textContent: employee
        })
      ])
      .slice(0, -1))); // The above flatMap creates a [text, employeeName, text, employeeName, text, employeeName]-pattern. We need to remove the last superfluous employeeName.
}
这是ECMAScript 5.1版本:

function highlight(employee){
  Array.prototype.slice.call(document.querySelectorAll("body, body *:not(script):not(style):not(noscript)")) // First, get all regular elements under the `<body>` element
    .map(function(elem){
      return Array.prototype.slice.call(elem.childNodes); // Then extract their child nodes and convert them to an array.
    })
    .reduce(function(nodesA, nodesB){
      return nodesA.concat(nodesB); // Flatten each array into a single array
    })
    .filter(function(node){
      return node.nodeType === document.TEXT_NODE && node.textContent.indexOf(employee) > -1; // Filter only text nodes that contain the employee’s name.
    })
    .forEach(function(node){
      var nextNode = node.nextSibling, // Remember the next node if it exists
        parent = node.parentNode, // Remember the parent node
        content = node.textContent, // Remember the content
        newNodes = []; // Create empty array for new highlighted content

      node.parentNode.removeChild(node); // Remove it for now.
      content.split(employee).forEach(function(part, i, arr){ // Find each occurrence of the employee’s name
        newNodes.push(document.createTextNode(part)); // Create text nodes for everything around it

        if(i < arr.length - 1){
          newNodes.push(document.createElement("mark")); // Create mark element nodes for each occurrence of the employee’s name
          newNodes[newNodes.length - 1].innerHTML = employee;
          // newNodes[newNodes.length - 1].setAttribute("class", "highlighted");
        }
      });

      newNodes.forEach(function(n){ // Append or insert everything back into place
        if(nextNode){
          parent.insertBefore(n, nextNode);
        }
        else{
          parent.appendChild(n);
        }
      });
    });
}
功能突出显示(员工){
Array.prototype.slice.call(document.queryselectoral(“body,body*:not(script):not(style):not(noscript)”)//首先,获取``元素下的所有常规元素
.map(功能(elem){
返回Array.prototype.slice.call(elem.childNodes);//然后提取其子节点并将其转换为数组。
})
.reduce(函数(nodesA、nodesB){
返回nodesA.concat(nodesB);//将每个数组展平为单个数组
})
.filter(函数(节点){
return node.nodeType==document.TEXT\u node&&node.textContent.indexOf(employee)>-1;//仅筛选包含员工姓名的文本节点。
})
.forEach(函数(节点){
var nextNode=node.nextSibling,//记住下一个节点(如果存在的话)
parent=node.parentNode,//还记得父节点吗
content=node.textContent,//记住内容
newNodes=[];//为新突出显示的内容创建空数组
node.parentNode.removeChild(node);//现在删除它。
content.split(employee).forEach(function(part,i,arr){//查找每个出现的员工姓名
newNodes.push(document.createTextNode(part));//为其周围的所有内容创建文本节点
如果(i
替换单个文本节点的主要好处是事件监听器不会丢失。站点保持不变,只有文本更改

您也可以使用
span
来代替
mark
元素,并使用
class
属性取消对行的注释,并在CSS中指定该行

这是一个示例,其中我使用了此函数,并在以下页面上使用了后续的
高亮显示(“Text”);

(未突出显示的一个实例是
之外的SVG节点)。

Neit
highlight(employee);
function highlight(employee){
  Array.from(document.querySelectorAll("body, body *:not(script):not(style):not(noscript)"))
    .flatMap(({childNodes}) => [...childNodes])
    .filter(({nodeType, textContent}) => nodeType === document.TEXT_NODE && textContent.includes(employee))
    .forEach((textNode) => textNode.replaceWith(...textNode.textContent.split(employee).flatMap((part) => [
        document.createTextNode(part),
        Object.assign(document.createElement("mark"), {
          textContent: employee
        })
      ])
      .slice(0, -1))); // The above flatMap creates a [text, employeeName, text, employeeName, text, employeeName]-pattern. We need to remove the last superfluous employeeName.
}
function highlight(employee){
  Array.prototype.slice.call(document.querySelectorAll("body, body *:not(script):not(style):not(noscript)")) // First, get all regular elements under the `<body>` element
    .map(function(elem){
      return Array.prototype.slice.call(elem.childNodes); // Then extract their child nodes and convert them to an array.
    })
    .reduce(function(nodesA, nodesB){
      return nodesA.concat(nodesB); // Flatten each array into a single array
    })
    .filter(function(node){
      return node.nodeType === document.TEXT_NODE && node.textContent.indexOf(employee) > -1; // Filter only text nodes that contain the employee’s name.
    })
    .forEach(function(node){
      var nextNode = node.nextSibling, // Remember the next node if it exists
        parent = node.parentNode, // Remember the parent node
        content = node.textContent, // Remember the content
        newNodes = []; // Create empty array for new highlighted content

      node.parentNode.removeChild(node); // Remove it for now.
      content.split(employee).forEach(function(part, i, arr){ // Find each occurrence of the employee’s name
        newNodes.push(document.createTextNode(part)); // Create text nodes for everything around it

        if(i < arr.length - 1){
          newNodes.push(document.createElement("mark")); // Create mark element nodes for each occurrence of the employee’s name
          newNodes[newNodes.length - 1].innerHTML = employee;
          // newNodes[newNodes.length - 1].setAttribute("class", "highlighted");
        }
      });

      newNodes.forEach(function(n){ // Append or insert everything back into place
        if(nextNode){
          parent.insertBefore(n, nextNode);
        }
        else{
          parent.appendChild(n);
        }
      });
    });
}