Ai đó có thể giúp tôi với một hàm javascript có thể đánh dấu văn bản trên một trang web. Và yêu cầu là - chỉ đánh dấu một lần, không phải đánh dấu tất cả các lần xuất hiện của văn bản như chúng ta làm trong trường hợp tìm kiếm.
Ai đó có thể giúp tôi với một hàm javascript có thể đánh dấu văn bản trên một trang web. Và yêu cầu là - chỉ đánh dấu một lần, không phải đánh dấu tất cả các lần xuất hiện của văn bản như chúng ta làm trong trường hợp tìm kiếm.
Câu trả lời:
Bạn có thể sử dụng hiệu ứng đánh dấu jquery .
Nhưng nếu bạn quan tâm đến mã javascript thô, hãy xem những gì tôi nhận được Chỉ cần sao chép dán vào HTML, mở tệp và nhấp vào "tô sáng" - điều này sẽ làm nổi bật từ "cáo". Hiệu suất khôn ngoan Tôi nghĩ điều này sẽ làm cho văn bản nhỏ và một lần lặp lại (như bạn đã chỉ định)
function highlight(text) {
var inputText = document.getElementById("inputText");
var innerHTML = inputText.innerHTML;
var index = innerHTML.indexOf(text);
if (index >= 0) {
innerHTML = innerHTML.substring(0,index) + "<span class='highlight'>" + innerHTML.substring(index,index+text.length) + "</span>" + innerHTML.substring(index + text.length);
inputText.innerHTML = innerHTML;
}
}
.highlight {
background-color: yellow;
}
<button onclick="highlight('fox')">Highlight</button>
<div id="inputText">
The fox went over the fence
</div>
Chỉnh sửa:
replace
Tôi thấy câu trả lời này đã trở nên phổ biến, tôi nghĩ tôi có thể thêm vào nó. Bạn cũng có thể dễ dàng sử dụng thay thế
"the fox jumped over the fence".replace(/fox/,"<span>fox</span>");
Hoặc đối với nhiều lần xuất hiện (không liên quan đến câu hỏi, nhưng được hỏi trong nhận xét), bạn chỉ cần thêm global
vào biểu thức chính quy thay thế.
"the fox jumped over the other fox".replace(/fox/g,"<span>fox</span>");
Hy vọng điều này sẽ giúp ích cho những người bình luận hấp dẫn.
để thay thế HTML cho toàn bộ trang web, bạn nên tham khảo phần nội dung innerHTML
của tài liệu.
document.body.innerHTML
"<span class='highlight'>"
với "<span style='color: " + color + ";'>"
, màu sắc nên được một cái gì đó giống nhưvar color = "#ff0000";
<img src="fox.jpg" />
Bạn sẽ nhận được HTML không hợp lệ mà sẽ trông như thế: <img src="<span class='highlight'>fox</span>.jpg" />
Không tốt
Các giải pháp được đưa ra ở đây khá tệ.
&
&, <
cho <, >
cho>, ä
cho ä, ö
cho ö ü
cho ü ß
cho ß, v.v.Bạn cần gì để làm:
Lặp qua tài liệu HTML, tìm tất cả các nút văn bản, lấy textContent
, lấy vị trí của văn bản được đánh dấu bằng indexOf
(với tùy chọn toLowerCase
nếu nó phải là phân biệt chữ hoa chữ thường), nối mọi thứ trước indexof
như textNode
, nối Văn bản phù hợp với khoảng đánh dấu, và lặp lại cho phần còn lại của textnode (chuỗi đánh dấu có thể xuất hiện nhiều lần trong textContent
chuỗi).
Đây là mã cho việc này:
var InstantSearch = {
"highlight": function (container, highlightText)
{
var internalHighlighter = function (options)
{
var id = {
container: "container",
tokens: "tokens",
all: "all",
token: "token",
className: "className",
sensitiveSearch: "sensitiveSearch"
},
tokens = options[id.tokens],
allClassName = options[id.all][id.className],
allSensitiveSearch = options[id.all][id.sensitiveSearch];
function checkAndReplace(node, tokenArr, classNameAll, sensitiveSearchAll)
{
var nodeVal = node.nodeValue, parentNode = node.parentNode,
i, j, curToken, myToken, myClassName, mySensitiveSearch,
finalClassName, finalSensitiveSearch,
foundIndex, begin, matched, end,
textNode, span, isFirst;
for (i = 0, j = tokenArr.length; i < j; i++)
{
curToken = tokenArr[i];
myToken = curToken[id.token];
myClassName = curToken[id.className];
mySensitiveSearch = curToken[id.sensitiveSearch];
finalClassName = (classNameAll ? myClassName + " " + classNameAll : myClassName);
finalSensitiveSearch = (typeof sensitiveSearchAll !== "undefined" ? sensitiveSearchAll : mySensitiveSearch);
isFirst = true;
while (true)
{
if (finalSensitiveSearch)
foundIndex = nodeVal.indexOf(myToken);
else
foundIndex = nodeVal.toLowerCase().indexOf(myToken.toLowerCase());
if (foundIndex < 0)
{
if (isFirst)
break;
if (nodeVal)
{
textNode = document.createTextNode(nodeVal);
parentNode.insertBefore(textNode, node);
} // End if (nodeVal)
parentNode.removeChild(node);
break;
} // End if (foundIndex < 0)
isFirst = false;
begin = nodeVal.substring(0, foundIndex);
matched = nodeVal.substr(foundIndex, myToken.length);
if (begin)
{
textNode = document.createTextNode(begin);
parentNode.insertBefore(textNode, node);
} // End if (begin)
span = document.createElement("span");
span.className += finalClassName;
span.appendChild(document.createTextNode(matched));
parentNode.insertBefore(span, node);
nodeVal = nodeVal.substring(foundIndex + myToken.length);
} // Whend
} // Next i
}; // End Function checkAndReplace
function iterator(p)
{
if (p === null) return;
var children = Array.prototype.slice.call(p.childNodes), i, cur;
if (children.length)
{
for (i = 0; i < children.length; i++)
{
cur = children[i];
if (cur.nodeType === 3)
{
checkAndReplace(cur, tokens, allClassName, allSensitiveSearch);
}
else if (cur.nodeType === 1)
{
iterator(cur);
}
}
}
}; // End Function iterator
iterator(options[id.container]);
} // End Function highlighter
;
internalHighlighter(
{
container: container
, all:
{
className: "highlighter"
}
, tokens: [
{
token: highlightText
, className: "highlight"
, sensitiveSearch: false
}
]
}
); // End Call internalHighlighter
} // End Function highlight
};
Sau đó, bạn có thể sử dụng nó như thế này:
function TestTextHighlighting(highlightText)
{
var container = document.getElementById("testDocument");
InstantSearch.highlight(container, highlightText);
}
Đây là một tài liệu HTML mẫu
<!DOCTYPE html>
<html>
<head>
<title>Example of Text Highlight</title>
<style type="text/css" media="screen">
.highlight{ background: #D3E18A;}
.light{ background-color: yellow;}
</style>
</head>
<body>
<div id="testDocument">
This is a test
<span> This is another test</span>
äöüÄÖÜäöüÄÖÜ
<span>Test123äöüÄÖÜ</span>
</div>
</body>
</html>
Nhân tiện, nếu bạn tìm kiếm trong cơ sở dữ liệu LIKE
,
ví dụ WHERE textField LIKE CONCAT('%', @query, '%')
[điều bạn không nên làm, bạn nên sử dụng fulltext-search hoặc Lucene], thì bạn có thể thoát mọi ký tự bằng \ và thêm câu lệnh SQL-Escape, theo cách đó bạn sẽ tìm thấy các ký tự đặc biệt là biểu thức LIKE.
ví dụ
WHERE textField LIKE CONCAT('%', @query, '%') ESCAPE '\'
và giá trị của @query không phải là '%completed%'
nhưng'%\c\o\m\p\l\e\t\e\d%'
(đã thử nghiệm, hoạt động với SQL-Server và PostgreSQL và mọi hệ thống RDBMS khác hỗ trợ ESCAPE)
Một phiên bản đánh máy đã sửa đổi:
namespace SearchTools
{
export interface IToken
{
token: string;
className: string;
sensitiveSearch: boolean;
}
export class InstantSearch
{
protected m_container: Node;
protected m_defaultClassName: string;
protected m_defaultCaseSensitivity: boolean;
protected m_highlightTokens: IToken[];
constructor(container: Node, tokens: IToken[], defaultClassName?: string, defaultCaseSensitivity?: boolean)
{
this.iterator = this.iterator.bind(this);
this.checkAndReplace = this.checkAndReplace.bind(this);
this.highlight = this.highlight.bind(this);
this.highlightNode = this.highlightNode.bind(this);
this.m_container = container;
this.m_defaultClassName = defaultClassName || "highlight";
this.m_defaultCaseSensitivity = defaultCaseSensitivity || false;
this.m_highlightTokens = tokens || [{
token: "test",
className: this.m_defaultClassName,
sensitiveSearch: this.m_defaultCaseSensitivity
}];
}
protected checkAndReplace(node: Node)
{
let nodeVal: string = node.nodeValue;
let parentNode: Node = node.parentNode;
let textNode: Text = null;
for (let i = 0, j = this.m_highlightTokens.length; i < j; i++)
{
let curToken: IToken = this.m_highlightTokens[i];
let textToHighlight: string = curToken.token;
let highlightClassName: string = curToken.className || this.m_defaultClassName;
let caseSensitive: boolean = curToken.sensitiveSearch || this.m_defaultCaseSensitivity;
let isFirst: boolean = true;
while (true)
{
let foundIndex: number = caseSensitive ?
nodeVal.indexOf(textToHighlight)
: nodeVal.toLowerCase().indexOf(textToHighlight.toLowerCase());
if (foundIndex < 0)
{
if (isFirst)
break;
if (nodeVal)
{
textNode = document.createTextNode(nodeVal);
parentNode.insertBefore(textNode, node);
} // End if (nodeVal)
parentNode.removeChild(node);
break;
} // End if (foundIndex < 0)
isFirst = false;
let begin: string = nodeVal.substring(0, foundIndex);
let matched: string = nodeVal.substr(foundIndex, textToHighlight.length);
if (begin)
{
textNode = document.createTextNode(begin);
parentNode.insertBefore(textNode, node);
} // End if (begin)
let span: HTMLSpanElement = document.createElement("span");
if (!span.classList.contains(highlightClassName))
span.classList.add(highlightClassName);
span.appendChild(document.createTextNode(matched));
parentNode.insertBefore(span, node);
nodeVal = nodeVal.substring(foundIndex + textToHighlight.length);
} // Whend
} // Next i
} // End Sub checkAndReplace
protected iterator(p: Node)
{
if (p == null)
return;
let children: Node[] = Array.prototype.slice.call(p.childNodes);
if (children.length)
{
for (let i = 0; i < children.length; i++)
{
let cur: Node = children[i];
// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
if (cur.nodeType === Node.TEXT_NODE)
{
this.checkAndReplace(cur);
}
else if (cur.nodeType === Node.ELEMENT_NODE)
{
this.iterator(cur);
}
} // Next i
} // End if (children.length)
} // End Sub iterator
public highlightNode(n:Node)
{
this.iterator(n);
} // End Sub highlight
public highlight()
{
this.iterator(this.m_container);
} // End Sub highlight
} // End Class InstantSearch
} // End Namespace SearchTools
Sử dụng:
let searchText = document.getElementById("txtSearchText");
let searchContainer = document.body; // document.getElementById("someTable");
let highlighter = new SearchTools.InstantSearch(searchContainer, [
{
token: "this is the text to highlight" // searchText.value,
className: "highlight", // this is the individual highlight class
sensitiveSearch: false
}
]);
// highlighter.highlight(); // this would highlight in the entire table
// foreach tr - for each td2
highlighter.highlightNode(td2); // this highlights in the second column of table
ä
Ví dụ: sẽ được chuyển đổi thành ký tự thực, ngay cả khi sử dụng innerHTML
.
Lý do tại sao có lẽ là một ý tưởng tồi nếu bắt đầu xây dựng chức năng đánh dấu của riêng bạn từ đầu là vì bạn chắc chắn sẽ gặp phải những vấn đề mà người khác đã giải quyết. Những thách thức:
innerHTML
)Nghe có vẻ phức tạp? Nếu bạn muốn một số tính năng như bỏ qua một số yếu tố khỏi đánh dấu, ánh xạ dấu phụ, ánh xạ từ đồng nghĩa, tìm kiếm bên trong iframe, tìm kiếm từ được phân tách, v.v. thì điều này càng trở nên phức tạp hơn.
Khi sử dụng một plugin hiện có, được triển khai tốt, bạn không phải lo lắng về những thứ đã nêu ở trên. Bài viết 10 plugin đánh dấu văn bản jQuery trên Sitepoint sẽ so sánh các plugin highlighter phổ biến.
mark.js là một plugin được viết bằng JavaScript thuần túy, nhưng cũng có sẵn dưới dạng plugin jQuery. Nó được phát triển để cung cấp nhiều cơ hội hơn các plugin khác với các tùy chọn:
Ngoài ra, bạn có thể xem trò chơi này .
Ví dụ sử dụng :
// Highlight "keyword" in the specified context
$(".context").mark("keyword");
// Highlight the custom regular expression in the specified context
$(".context").markRegExp(/Lorem/gmi);
Nó miễn phí và được phát triển mã nguồn mở trên GitHub ( tham khảo dự án ).
acrossElements
tùy chọn. Và đến nhận xét thứ ba; mark.js không lớn so với các chức năng mà nó cung cấp. Và không, không chắc có điều gì đó sẽ xảy ra trong tương lai, vì mark.js đã được thử nghiệm, ví dụ như khởi động Chrome 30 và trong tất cả các phiên bản mới hơn với thử nghiệm đơn vị trình duyệt chéo và không bao giờ có bất kỳ sự cố nào với các phiên bản sắp tới.
function stylizeHighlightedString() {
var text = window.getSelection();
// For diagnostics
var start = text.anchorOffset;
var end = text.focusOffset - text.anchorOffset;
range = window.getSelection().getRangeAt(0);
var selectionContents = range.extractContents();
var span = document.createElement("span");
span.appendChild(selectionContents);
span.style.backgroundColor = "yellow";
span.style.color = "black";
range.insertNode(span);
}
span.style.backgroundColor = "yellow";
chuyển sang CSS style="background-color: yellow;"
- đó là sự khác biệt nhỏ giữa camelCase và ký hiệu gạch ngang khiến tôi vấp phải lúc đầu.
Đây là giải pháp JavaScript thuần regexp của tôi:
function highlight(text) {
document.body.innerHTML = document.body.innerHTML.replace(
new RegExp(text + '(?!([^<]+)?<)', 'gi'),
'<b style="background-color:#ff0;font-size:100%">$&</b>'
);
}
one|two|three
>
ký tự. Sửa đổi regex bằng cách sử dụng (?!([^<]+)?<)
để nó hoạt động.
Tôi có cùng một vấn đề, một loạt văn bản đến thông qua một yêu cầu xmlhttp. Văn bản này được định dạng html. Tôi cần phải làm nổi bật mỗi lần xuất hiện.
str='<img src="brown fox.jpg" title="The brown fox" />'
+'<p>some text containing fox.</p>'
Vấn đề là tôi không cần đánh dấu văn bản trong thẻ. Ví dụ, tôi cần tô sáng con cáo:
Bây giờ tôi có thể thay thế nó bằng:
var word="fox";
word="(\\b"+
word.replace(/([{}()[\]\\.?*+^$|=!:~-])/g, "\\$1")
+ "\\b)";
var r = new RegExp(word,"igm");
str.replace(r,"<span class='hl'>$1</span>")
Để trả lời câu hỏi của bạn: bạn có thể bỏ đi các tùy chọn g trong regexp và chỉ lần xuất hiện đầu tiên sẽ được thay thế nhưng đây vẫn là lần xuất hiện trong thuộc tính img src và hủy thẻ hình ảnh:
<img src="brown <span class='hl'>fox</span>.jpg" title="The brown <span
class='hl'>fox</span> />
Đây là cách tôi đã giải quyết nó nhưng tôi đang tự hỏi liệu có cách nào tốt hơn không, điều gì đó tôi đã bỏ qua trong biểu thức chính quy:
str='<img src="brown fox.jpg" title="The brown fox" />'
+'<p>some text containing fox.</p>'
var word="fox";
word="(\\b"+
word.replace(/([{}()[\]\\.?*+^$|=!:~-])/g, "\\$1")
+ "\\b)";
var r = new RegExp(word,"igm");
str.replace(/(>[^<]+<)/igm,function(a){
return a.replace(r,"<span class='hl'>$1</span>");
});
<img src="word">
hoặc <a href="word">
.
Không có giải pháp nào khác thực sự phù hợp với nhu cầu của tôi và mặc dù giải pháp của Stefan Steiger hoạt động như tôi mong đợi nhưng tôi thấy nó hơi dài dòng.
Sau đây là nỗ lực của tôi:
/**
* Highlight keywords inside a DOM element
* @param {string} elem Element to search for keywords in
* @param {string[]} keywords Keywords to highlight
* @param {boolean} caseSensitive Differenciate between capital and lowercase letters
* @param {string} cls Class to apply to the highlighted keyword
*/
function highlight(elem, keywords, caseSensitive = false, cls = 'highlight') {
const flags = caseSensitive ? 'gi' : 'g';
// Sort longer matches first to avoid
// highlighting keywords within keywords.
keywords.sort((a, b) => b.length - a.length);
Array.from(elem.childNodes).forEach(child => {
const keywordRegex = RegExp(keywords.join('|'), flags);
if (child.nodeType !== 3) { // not a text node
highlight(child, keywords, caseSensitive, cls);
} else if (keywordRegex.test(child.textContent)) {
const frag = document.createDocumentFragment();
let lastIdx = 0;
child.textContent.replace(keywordRegex, (match, idx) => {
const part = document.createTextNode(child.textContent.slice(lastIdx, idx));
const highlighted = document.createElement('span');
highlighted.textContent = match;
highlighted.classList.add(cls);
frag.appendChild(part);
frag.appendChild(highlighted);
lastIdx = idx + match.length;
});
const end = document.createTextNode(child.textContent.slice(lastIdx));
frag.appendChild(end);
child.parentNode.replaceChild(frag, child);
}
});
}
// Highlight all keywords found in the page
highlight(document.body, ['lorem', 'amet', 'autem']);
.highlight {
background: lightpink;
}
<p>Hello world lorem ipsum dolor sit amet, consectetur adipisicing elit. Est vel accusantium totam, ipsum delectus et dignissimos mollitia!</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Numquam, corporis.
<small>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusantium autem voluptas perferendis dolores ducimus velit error voluptatem, qui rerum modi?</small>
</p>
Tôi cũng khuyên bạn nên sử dụng một cái gì đó như Escape-string-regexp nếu từ khóa của bạn có thể có các ký tự đặc biệt cần được thoát trong regexes:
const keywordRegex = RegExp(keywords.map(escapeRegexp).join('|')), flags);
LƯU Ý: Mặc dù tôi đồng ý với @Stefan về nhiều thứ, nhưng tôi chỉ cần đánh dấu kết hợp đơn giản :
module myApp.Search {
'use strict';
export class Utils {
private static regexFlags = 'gi';
private static wrapper = 'mark';
private static wrap(match: string): string {
return '<' + Utils.wrapper + '>' + match + '</' + Utils.wrapper + '>';
}
static highlightSearchTerm(term: string, searchResult: string): string {
let regex = new RegExp(term, Utils.regexFlags);
return searchResult.replace(regex, match => Utils.wrap(match));
}
}
}
Và sau đó xây dựng kết quả thực tế:
module myApp.Search {
'use strict';
export class SearchResult {
id: string;
title: string;
constructor(result, term?: string) {
this.id = result.id;
this.title = term ? Utils.highlightSearchTerm(term, result.title) : result.title;
}
}
}
Vì HTML5, bạn có thể sử dụng <mark></mark>
thẻ để đánh dấu văn bản. Bạn có thể sử dụng javascript để bọc một số văn bản / từ khóa giữa các thẻ này. Đây là một ví dụ nhỏ về cách đánh dấu và bỏ đánh dấu văn bản.
innerHTML
là nguy hiểm. Nó sẽ xóa các sự kiện.
Tua nhanh đến năm 2019, Web API hiện đã hỗ trợ nguyên bản để đánh dấu văn bản:
const selection = document.getSelection();
selection.setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset);
Và bạn tốt để đi! anchorNode
là nút bắt đầu lựa chọn, focusNode
là nút kết thúc lựa chọn. Và, nếu chúng là các nút văn bản, offset
là chỉ số của ký tự bắt đầu và kết thúc trong các nút tương ứng. Đây là tài liệu
Họ thậm chí còn có một bản demo trực tiếp
Tôi cũng tự hỏi điều đó, bạn có thể thử những gì tôi học được về điều này bài đăng .
Tôi đã sử dụng:
function highlightSelection() {
var userSelection = window.getSelection();
for(var i = 0; i < userSelection.rangeCount; i++) {
highlightRange(userSelection.getRangeAt(i));
}
}
function highlightRange(range) {
var newNode = document.createElement("span");
newNode.setAttribute(
"style",
"background-color: yellow; display: inline;"
);
range.surroundContents(newNode);
}
<html>
<body contextmenu="mymenu">
<menu type="context" id="mymenu">
<menuitem label="Highlight Yellow" onclick="highlightSelection()" icon="/images/comment_icon.gif"></menuitem>
</menu>
<p>this is text, select and right click to high light me! if you can`t see the option, please use this<button onclick="highlightSelection()">button </button><p>
bạn cũng có thể thử nó tại đây: http://henriquedonati.com/projects/Extension/extension.html
xc
Chúng tôi nếu bạn cũng muốn nó được đánh dấu khi tải trang, có một cách mới.
chỉ cần thêm #:~:text=Highlight%20These
thử truy cập liên kết này
/programming/38588721#:~:text=Highlight%20a%20text
Sử dụng phương thức surroundContents () trên loại Phạm vi . Đối số duy nhất của nó là một phần tử sẽ bao bọc Phạm vi đó.
function styleSelected() {
bg = document.createElement("span");
bg.style.backgroundColor = "yellow";
window.getSelection().getRangeAt(0).surroundContents(bg);
}