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

B. *_*non 3 html javascript css jquery meteor

我想创建带有 url 的页面,例如:

http://xyzcorp/schedules/2015Aug24_Aug28/Jim_Hawkins
http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones
http://xyzcorp/schedules/2015Aug24_Aug28/John_Silver
Run Code Online (Sandbox Code Playgroud)

这些特定的 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
Run Code Online (Sandbox Code Playgroud)

这可以在 HTML/CSS 中完成吗?或者是否还需要 JavaScript 或 jQuery?

Seb*_*mon 6

如果你调用该函数

\n\n
highlight(employee);\n
Run Code Online (Sandbox Code Playgroud)\n\n

该函数在 ECMAScript 2018+ 中如下所示:

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

这是 ECMAScript 5.1 版本:

\n\n
function highlight(employee){\n  Array.prototype.slice.call(document.querySelectorAll("body, body *:not(script):not(style):not(noscript)")) // First, get all regular elements under the `<body>` element\n    .map(function(elem){\n      return Array.prototype.slice.call(elem.childNodes); // Then extract their child nodes and convert them to an array.\n    })\n    .reduce(function(nodesA, nodesB){\n      return nodesA.concat(nodesB); // Flatten each array into a single array\n    })\n    .filter(function(node){\n      return node.nodeType === document.TEXT_NODE && node.textContent.indexOf(employee) > -1; // Filter only text nodes that contain the employee\xe2\x80\x99s name.\n    })\n    .forEach(function(node){\n      var nextNode = node.nextSibling, // Remember the next node if it exists\n        parent = node.parentNode, // Remember the parent node\n        content = node.textContent, // Remember the content\n        newNodes = []; // Create empty array for new highlighted content\n\n      node.parentNode.removeChild(node); // Remove it for now.\n      content.split(employee).forEach(function(part, i, arr){ // Find each occurrence of the employee\xe2\x80\x99s name\n        newNodes.push(document.createTextNode(part)); // Create text nodes for everything around it\n\n        if(i < arr.length - 1){\n          newNodes.push(document.createElement("mark")); // Create mark element nodes for each occurrence of the employee\xe2\x80\x99s name\n          newNodes[newNodes.length - 1].innerHTML = employee;\n          // newNodes[newNodes.length - 1].setAttribute("class", "highlighted");\n        }\n      });\n\n      newNodes.forEach(function(n){ // Append or insert everything back into place\n        if(nextNode){\n          parent.insertBefore(n, nextNode);\n        }\n        else{\n          parent.appendChild(n);\n        }\n      });\n    });\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

替换单个文本节点的主要好处是事件侦听器不会丢失。该网站保持不变,只是文本发生了变化。

\n\n

除了元素之外,mark您还可以使用 aspan并取消注释class该行的属性并在 CSS 中指定。

\n\n

这是我使用此函数的示例,以及MDN节点highlight("Text");页面上的后续示例:Text

\n\n

突出显示所有出现 \xe2\x80\x9cText\xe2\x80\x9d 的网站

\n\n

(突出显示的\xe2\x80\x99t 事件是 之外的 SVG 节点<iframe>)。

\n