如何动态突出显示网页上的字符串? [英] How can I dynamically highlight strings on a web page?

查看:59
本文介绍了如何动态突出显示网页上的字符串?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要创建带有以下网址的页面:

  http://xyzcorp/schedules/2015Aug24_Aug28/Jim_Hawkinshttp://xyzcorp/schedules/2015Aug24_Aug28/Billy_Boneshttp://xyzcorp/schedules/2015Aug24_Aug28/John_Silver 

这些特定的URL都将包含完全相同的内容("2015Aug24_Aug28"页面),但会在末尾突出显示该名称的所有实例.例如," http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones "将突出显示名称"Billy Bones"的每个实例,就像在页面上执行了该名称的查找"一样通过浏览器.

我想客户端需要这样的东西

  var员工= getLastURLPortion();//返回"Billy_Bones"(或其他任何值)员工= humanifyTheName(员工);//用空格替换下划线,以使其为比利骨头"(等)重点(员工);//这我不知道该怎么办 

可以在HTML/CSS中完成此操作吗?或者还需要JavaScript或jQuery吗?

解决方案

如果调用该函数

  highlight(employee); 

该功能在ECMAScript 2018+中的外观如下:

 功能突出显示(员工){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:员工})]).slice(0,-1)));//上面的flatMap创建一个[text,employeeName,text,employeeName,text,employeeName]模式.我们需要删除最后一个多余的employeeName.} 

这是ECMAScript 5.1版本:

 功能突出显示(员工){Array.prototype.slice.call(document.querySelectorAll("body,body *:not(script):not(style):not(noscript)"))//首先,获取< body>"下的所有常规元素`元素.map(function(elem){返回Array.prototype.slice.call(elem.childNodes);//然后提取其子节点并将其转换为数组.}).reduce(function(nodesA,nodesB){返回nodesA.concat(nodesB);//将每个数组展平为单个数组}).filter(function(node){返回node.nodeType === document.TEXT_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));//为周围的所有内容创建文本节点if(i< arr.length-1){newNodes.push(document.createElement("mark"));//为每次出现的员工姓名创建标记元素节点newNodes [newNodes.length-1] .innerHTML =员工;//newNodes [newNodes.length-1] .setAttribute("class",突出显示");}});newNodes.forEach(function(n){//将所有内容追加或插入到位if(nextNode){parent.insertBefore(n,nextNode);}别的{parent.appendChild(n);}});});} 

替换单个文本节点的主要好处是事件监听器不会丢失.该站点保持不变,只有 text 发生更改.

代替 mark 元素,您还可以使用 span 并用 class 属性取消注释该行,并在CSS中进行指定./p>

这是一个示例,我在

(未突出显示的一个事件是< iframe> 之外的SVG节点).

I want to create pages with urls such as:

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

These particular URLs would all contain the exact same content (the "2015Aug24_Aug28" page), but would highlight all instances of the name tagged on to the end. For example, "http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones" would show every instance of the name "Billy Bones" highlighted, as if a "Find" for that name was executed on the page via the browser.

I imagine something like this is required, client-side:

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

Can this be done in HTML/CSS, or is JavaScript or jQuery also required for this?

解决方案

If you call the function

highlight(employee);

this is what that function would look like in 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.
}

And this is an ECMAScript 5.1 version:

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);
        }
      });
    });
}

The major benefit of replacing individual text nodes is that event listeners don’t get lost. The site remains intact, only the text changes.

Instead of the mark element you can also use a span and uncomment the line with the class attribute and specify that in CSS.

This is an example where I used this function and a subsequent highlight("Text"); on the MDN page for Text nodes:

(The one occurrence that isn’t highlighted is an SVG node beyond an <iframe>).

这篇关于如何动态突出显示网页上的字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆