Birisi bir web sayfasındaki metni vurgulayabilen bir javascript işlevi konusunda bana yardımcı olabilir mi? Ve şart, arama durumunda yaptığımız gibi metnin tüm tekrarlarını vurgulamak gibi, yalnızca bir kez vurgulamaktır.
Birisi bir web sayfasındaki metni vurgulayabilen bir javascript işlevi konusunda bana yardımcı olabilir mi? Ve şart, arama durumunda yaptığımız gibi metnin tüm tekrarlarını vurgulamak gibi, yalnızca bir kez vurgulamaktır.
Yanıtlar:
Jquery vurgulama efektini kullanabilirsiniz .
Ancak ham javascript koduyla ilgileniyorsanız, sahip olduğum şeye bir bakın Basitçe kopyalayıp bir HTML'ye yapıştırın, dosyayı açın ve "vurgulayın" düğmesine tıklayın - bu "tilki" kelimesini vurgulamalıdır. Performans açısından bunun küçük metin ve tek bir tekrar için işe yarayacağını düşünüyorum (belirttiğiniz gibi)
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>
Düzenlemeler:
replace
Bu cevabın biraz popülerlik kazandığını görüyorum, üzerine ekleyebileceğimi düşündüm. Değiştirmeyi de kolayca kullanabilirsiniz
"the fox jumped over the fence".replace(/fox/,"<span>fox</span>");
Veya birden çok kez geçtiğinde (soruyla ilgili değildir, ancak yorumlarda sorulmuştur), basitçe global
değiştirme normal ifadesini eklemeniz yeterlidir .
"the fox jumped over the other fox".replace(/fox/g,"<span>fox</span>");
Umarım bu meraklı yorumculara yardımcı olur.
HTML'yi bir web sayfasının tamamı için değiştirmek için innerHTML
, belgenin gövdesine başvurmalısınız .
document.body.innerHTML
"<span class='highlight'>"
ile "<span style='color: " + color + ";'>"
olduğu gibi, renk olması gereken bir şeyvar color = "#ff0000";
<img src="fox.jpg" />
Şuna benzeyen geçersiz HTML alırsınız: <img src="<span class='highlight'>fox</span>.jpg" />
İyi değil
Burada sunulan çözümler oldukça kötü.
&
& <
için, <için, >
için> için, ä
için için, ö
için ü
için ü ß
için için için, vb.Ne yapmak gerekiyor:
Döngü HTML dokümanının yoluyla olsun, tüm metin düğümleri bulmak textContent
ile vurgulamak metin konumunu almak indexOf
(opsiyonel ile toLowerCase
küçük harf duyarsız olması gerekiyorsa) önce, ekleme herşeyi indexof
olarak textNode
, komuta vurgu açıklıklı eşleşti Metin, ve metin düğümünün geri kalanı için tekrarlayın (vurgu dizesi dizede birden çok kez ortaya çıkabilir textContent
).
İşte bunun kodu:
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
};
O zaman bunu şu şekilde kullanabilirsiniz:
function TestTextHighlighting(highlightText)
{
var container = document.getElementById("testDocument");
InstantSearch.highlight(container, highlightText);
}
İşte örnek bir HTML belgesi
<!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>
Bu arada, bir veritabanında arama yaparsanız LIKE
,
mesela WHERE textField LIKE CONCAT('%', @query, '%')
[sen, tam metin-arama veya lucene kullanmalıdır yapmaması gereken hangi], o zaman, bu şekilde her kaçış karakteri \ ve bir SQL kaçış deyimi ekleyebilir LIKE ifadeleri olan özel karakterler bulacaksınız.
Örneğin
WHERE textField LIKE CONCAT('%', @query, '%') ESCAPE '\'
ve @query'nin değeri, '%completed%'
ancak'%\c\o\m\p\l\e\t\e\d%'
(test edilmiştir, SQL-Server ve PostgreSQL ve ESCAPE'yi destekleyen diğer tüm RDBMS sistemleriyle çalışır)
Revize edilmiş bir daktilo versiyonu:
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
Kullanım:
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
ä
örneğin kullanılırken bile gerçek karaktere dönüştürülecektir innerHTML
.
Kendi vurgulama işlevinizi sıfırdan oluşturmaya başlamanın muhtemelen kötü bir fikir olmasının nedeni, kesinlikle başkalarının halihazırda çözdüğü sorunlarla karşılaşacak olmanızdır. Zorluklar:
innerHTML
)Kulağa karmaşık mı geliyor? Bazı öğeleri vurgulama, aksan eşleme, eş anlamlı eşleme, iframe içinde arama, ayrılmış sözcük arama vb. Gibi bazı özellikleri göz ardı etmek istiyorsanız, bu giderek daha karmaşık hale gelir.
Mevcut, iyi uygulanmış bir eklenti kullanırken, yukarıda belirtilen şeyler için endişelenmenize gerek yok. Makale vurgulayıcı eklentileri 10 jQuery metin popüler vurgulayıcı eklentileri karşılaştırır SitePoint.
mark.js , saf JavaScript ile yazılmış bir eklentidir, ancak jQuery eklentisi olarak da mevcuttur. Aşağıdaki seçeneklerle diğer eklentilerden daha fazla fırsat sunmak için geliştirilmiştir:
Alternatif olarak bu kemanı görebilirsiniz .
Kullanım örneği :
// Highlight "keyword" in the specified context
$(".context").mark("keyword");
// Highlight the custom regular expression in the specified context
$(".context").markRegExp(/Lorem/gmi);
GitHub'da ücretsiz ve geliştirilmiş açık kaynaklıdır ( proje referansı ).
acrossElements
seçeneği kullanarak etiketler arasındaki eşleşmeleri bulabilir . Ve üçüncü yoruma; mark.js sunduğu işlevlere kıyasla büyük değil. Ve hayır, mark.js test edildiğinden, örneğin Chrome 30'un başlatılması ve tarayıcılar arası birim testleri ile tüm yeni sürümlerde ve gelecek sürümlerde hiçbir zaman sorun olmadığından, gelecekte bir şeyin bozulma olasılığı düşüktür.
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";
CSS'ye çevrildiğine dair hatırlatma / ipucu - style="background-color: yellow;"
camelCase ile kesik çizgili gösterim arasındaki ince fark ilk başta beni harekete geçirdi.
İşte benim regexp saf JavaScript çözümüm:
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
>
karakter varsa, metnin yerini almaz . (?!([^<]+)?<)
Çalışması için normal ifadeyi kullanarak değiştirin .
Diğer çözümlerin hiçbiri ihtiyaçlarıma tam olarak uymuyordu ve Stefan Steiger'in çözümü beklediğim gibi çalışmasına rağmen, biraz fazla ayrıntılı buldum.
Benim girişimim şu:
/**
* 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>
Ayrıca , anahtar kelimeleriniz normal ifadelerde öncelenmesi gereken özel karakterlere sahip olabiliyorsa, kaçış-dizesi-regexp gibi bir şey kullanmanızı tavsiye ederim :
const keywordRegex = RegExp(keywords.map(escapeRegexp).join('|')), flags);
Aynı sorunu yaşıyorum, bir xmlhttp isteği aracılığıyla bir grup metin geliyor. Bu metin html formatlıdır. Her olayı vurgulamalıyım.
str='<img src="brown fox.jpg" title="The brown fox" />'
+'<p>some text containing fox.</p>'
Sorun şu ki, etiketlerdeki metni vurgulamama gerek yok. Örneğin tilkiyi vurgulamalıyım:
Şimdi bunu şununla değiştirebilirim:
var word="fox";
word="(\\b"+
word.replace(/([{}()[\]\\.?*+^$|=!:~-])/g, "\\$1")
+ "\\b)";
var r = new RegExp(word,"igm");
str.replace(r,"<span class='hl'>$1</span>")
Sorunuzu yanıtlamak için: regexp seçeneklerinde g'yi bırakabilirsiniz ve yalnızca ilk geçtiği yer değiştirilecektir, ancak bu yine de img src özelliğindedir ve resim etiketini yok eder:
<img src="brown <span class='hl'>fox</span>.jpg" title="The brown <span
class='hl'>fox</span> />
Bu şekilde çözdüm ama daha iyi bir yol olup olmadığını merak ediyordum, normal ifadelerde kaçırdığım bir şey:
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">
veya ile uğraşmadan benim için çalışan tek normal ifade çözümüydü <a href="word">
.
NOT: @Stefan ile birçok konuda hemfikir olsam da, sadece basit bir eşleşmenin vurgulanmasına ihtiyacım vardı :
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));
}
}
}
Ve sonra asıl sonucu oluşturmak:
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;
}
}
}
HTML5'ten beri, <mark></mark>
metni vurgulamak için etiketleri kullanabilirsiniz . Bu etiketler arasında bazı metinleri / anahtar kelimeleri kaydırmak için javascript kullanabilirsiniz. Metnin nasıl işaretleneceğine ve işaretinin kaldırılacağına dair küçük bir örnek.
innerHTML
tehlikeli. Olayları silecek.
2019'a hızlı bir şekilde ilerleyin, Web API artık metinleri vurgulamak için yerel olarak desteğe sahip:
const selection = document.getSelection();
selection.setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset);
Ve gitmekte iyisin! anchorNode
seçim başlangıç düğümü, focusNode
seçim bitiş düğümüdür. Ve eğer bunlar metin düğümleriyse, offset
ilgili düğümlerdeki başlangıç ve bitiş karakterinin dizinidir. İşte belgeler
Canlı bir demoları bile var
Ben de merak ediyordum, bu yazıda öğrendiklerimi deneyebilirsin .
Kullandım:
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>
burada da deneyebilirsiniz: http://henriquedonati.com/projects/Extension/extension.html
xc
Sayfa yüklenirken de vurgulanmasını istiyorsanız, yeni bir yol var.
sadece ekle #:~:text=Highlight%20These
bu bağlantıya erişmeyi dene
/programming/38588721#:~:text=Highlight%20a%20text
Range türünde surroundContents () yöntemini kullanma . Tek argümanı, bu Aralığı saracak bir öğedir.
function styleSelected() {
bg = document.createElement("span");
bg.style.backgroundColor = "yellow";
window.getSelection().getRangeAt(0).surroundContents(bg);
}