У меня есть HTML-страница, как показано ниже. Я хочу выделить слово со специальным знаком внутри. Например, я ищу C#, но C# не выделяется, а другие слова без специального символа выделяются. В чем может быть проблема? Я включил jquery, используемый для выделения.
index.html
<!doctype html>
<html>
<head>
<meta charset = "utf-8">
<meta http-equiv = "X-UA-Compatible" content = "IE=edge,chrome=1">
<meta name = "viewport" content = "width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Example</title>
<style>
body { min-height: 100vh;background-image: linear-gradient(to right, #74ebd5 0%, #9face6 100%); }
.container { margin: 150px auto; max-width: 640px; font-family: 'Raleway'; line-height: 1.8;}
.highlight {background: #FFCD69;color:#222; padding: 5px 10px; border-radius: 3px;}
</style>
</head>
<body>
<div class = "container">
<h1>C C++ C# Java</h1>
<h1>Java is a programming language</h1>
</div>
<div class = "container">
<p>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's
standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make
a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting,
remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages,
and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
<h1>Java is a programming language</h1>
</div>
<script src = "https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script type = "text/javascript" src = "jquery.highlight.js"></script>
<script>
$('.container').each(function () {
$(this).highlight("c#",
{
wordsOnly: true, wordsBoundary: '\\b\\W*'
});
});
</script>
</body>
</html>
jquery.highlight.js
/*
* jQuery Highlight plugin
*
* Based on highlight v3 by Johann Burkard
* http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html
*
* Code a little bit refactored and cleaned (in my humble opinion).
* Most important changes:
* - has an option to highlight only entire words (wordsOnly - false by default),
* - has an option to be case sensitive (caseSensitive - false by default)
* - highlight element tag and class names can be specified in options
*
* Usage:
* // wrap every occurrence of text 'lorem' in content
* // with <span class='highlight'> (default options)
* $('#content').highlight('lorem');
*
* // search for and highlight more terms at once
* // so you can save some time on traversing DOM
* $('#content').highlight(['lorem', 'ipsum']);
* $('#content').highlight('lorem ipsum');
*
* // search only for entire word 'lorem'
* $('#content').highlight('lorem', { wordsOnly: true });
*
* // search only for the entire word 'C#'
* // and make sure that the word boundary can also
* // be a 'non-word' character, as well as a regex latin1 only boundary:
* $('#content').highlight('C#', { wordsOnly: true , wordsBoundary: '[\\b\\W]' });
*
* // don't ignore case during search of term 'lorem'
* $('#content').highlight('lorem', { caseSensitive: true });
*
* // wrap every occurrence of term 'ipsum' in content
* // with <em class='important'>
* $('#content').highlight('ipsum', { element: 'em', className: 'important' });
*
* // remove default highlight
* $('#content').unhighlight();
*
* // remove custom highlight
* $('#content').unhighlight({ element: 'em', className: 'important' });
*
*
* Copyright (c) 2009 Bartek Szopka
*
* Licensed under MIT license.
*
*/
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS
factory(require('jquery'));
} else {
// Browser globals
factory(jQuery);
}
}(function (jQuery) {
jQuery.extend({
highlight: function (node, re, nodeName, className, callback) {
if (node.nodeType === 3) {
var match = node.data.match(re);
if (match) {
// The new highlight Element Node
var highlight = document.createElement(nodeName || 'span');
highlight.className = className || 'highlight';
// Note that we use the captured value to find the real index
// of the match. This is because we do not want to include the matching word boundaries
var capturePos = node.data.indexOf( match[1] , match.index );
// Split the node and replace the matching wordnode
// with the highlighted node
var wordNode = node.splitText(capturePos);
wordNode.splitText(match[1].length);
var wordClone = wordNode.cloneNode(true);
highlight.appendChild(wordClone);
wordNode.parentNode.replaceChild(highlight, wordNode);
if (typeof callback == 'function') {
callback(highlight)
}
return 1; //skip added node in parent
}
} else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children
!/(script|style)/i.test(node.tagName) && // ignore script and style nodes
!(node.tagName === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted
for (var i = 0; i < node.childNodes.length; i++) {
i += jQuery.highlight(node.childNodes[i], re, nodeName, className, callback);
}
}
return 0;
}
});
jQuery.fn.unhighlight = function (options) {
var settings = {
className: 'highlight',
element: 'span'
};
jQuery.extend(settings, options);
return this.find(settings.element + '.' + settings.className).each(function () {
var parent = this.parentNode;
parent.replaceChild(this.firstChild, this);
parent.normalize();
}).end();
};
jQuery.fn.highlight = function (words, options, callback) {
var settings = {
className: 'highlight',
element: 'span',
caseSensitive: false,
wordsOnly: false,
wordsBoundary: '\\b'
};
jQuery.extend(settings, options);
if (typeof words === 'string') {
words = [words];
}
words = jQuery.grep(words, function(word, i){
return word != '';
});
words = jQuery.map(words, function(word, i) {
return word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
});
if (words.length === 0) {
return this;
};
var flag = settings.caseSensitive ? '' : 'i';
// The capture parenthesis will make sure we can match
// only the matching word
var pattern = '(' + words.join('|') + ')';
if (settings.wordsOnly) {
pattern =
(settings.wordsBoundaryStart || settings.wordsBoundary) +
pattern +
(settings.wordsBoundaryEnd || settings.wordsBoundary);
}
var re = new RegExp(pattern, flag);
return this.each(function () {
jQuery.highlight(this, re, settings.element, settings.className, callback);
});
};
}));
@ Дэвид Томас: Да, пробовал wordsOnly: false. Проблема в том, что он также выделяет отдельные символы. если я ищу c, он также выделяет символ c, который находится между словами. Например, он выделяет c в связи, c в процессе и т. д. Я не хочу, чтобы это было так
Вы пробовали экранировать # с помощью обратной косой черты?
@NielsNet Да, все еще не работает
@Vinod Я пробовал wordsBoundary: '[\\ b \\ W]' работает.
@samabcde '[\\ b \\ W]' в этом случае обязательно требует специального символа. В моем коде, например, после изменения на это, если я ищу C. Он не выделяет символ c в <h1>C C++ C# Java</h1>



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Приведенный ниже фрагмент кода демонстрирует эффект при настройке различных wordBoundary.
(function(factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS
factory(require('jquery'));
} else {
// Browser globals
factory(jQuery);
}
}(function(jQuery) {
jQuery.extend({
highlight: function(node, re, nodeName, className, callback) {
if (node.nodeType === 3) {
var match = node.data.match(re);
if (match) {
// The new highlight Element Node
var highlight = document.createElement(nodeName || 'span');
highlight.className = className || 'highlight';
// Note that we use the captured value to find the real index
// of the match. This is because we do not want to include the matching word boundaries
var capturePos = node.data.indexOf(match[1], match.index);
// Split the node and replace the matching wordnode
// with the highlighted node
var wordNode = node.splitText(capturePos);
wordNode.splitText(match[1].length);
var wordClone = wordNode.cloneNode(true);
highlight.appendChild(wordClone);
wordNode.parentNode.replaceChild(highlight, wordNode);
if (typeof callback == 'function') {
callback(highlight)
}
return 1; //skip added node in parent
}
} else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children
!/(script|style)/i.test(node.tagName) && // ignore script and style nodes
!(node.tagName === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted
for (var i = 0; i < node.childNodes.length; i++) {
i += jQuery.highlight(node.childNodes[i], re, nodeName, className, callback);
}
}
return 0;
}
});
jQuery.fn.unhighlight = function(options) {
var settings = {
className: 'highlight',
element: 'span'
};
jQuery.extend(settings, options);
return this.find(settings.element + '.' + settings.className).each(function() {
var parent = this.parentNode;
parent.replaceChild(this.firstChild, this);
parent.normalize();
}).end();
};
jQuery.fn.highlight = function(words, options, callback) {
var settings = {
className: 'highlight',
element: 'span',
caseSensitive: false,
wordsOnly: false,
wordsBoundary: '\\b'
};
jQuery.extend(settings, options);
if (typeof words === 'string') {
words = [words];
}
words = jQuery.grep(words, function(word, i) {
return word != '';
});
words = jQuery.map(words, function(word, i) {
return word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
});
if (words.length === 0) {
return this;
};
var flag = settings.caseSensitive ? '' : 'i';
// The capture parenthesis will make sure we can match
// only the matching word
var pattern = '(' + words.join('|') + ')';
//console.info(pattern);
if (settings.wordsOnly) {
pattern =
(settings.wordsBoundaryStart || settings.wordsBoundary) +
pattern +
(settings.wordsBoundaryEnd || settings.wordsBoundary);
}
//console.info(pattern);
var re = new RegExp(pattern, flag);
return this.each(function() {
jQuery.highlight(this, re, settings.element, settings.className, callback);
});
};
}));<!doctype html>
<html>
<head>
<meta charset = "utf-8">
<meta http-equiv = "X-UA-Compatible" content = "IE=edge,chrome=1">
<meta name = "viewport" content = "width=device-width, initial-scale=1, shrink-to-fit=no">
<script src = "https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src = "https://github.com/knownasilya/jquery-highlight/blob/master/jquery.highlight.js"></script>
<title>Example</title>
<style>
body {
min-height: 100vh;
background-image: linear-gradient(to right, #74ebd5 0%, #9face6 100%);
}
.container .container2 .container3 {
margin: 10px auto;
max-width: 640px;
font-family: 'Raleway';
line-height: 1.8;
}
.highlight {
background: pink;
color: #222;
padding: 5px 10px;
border-radius: 3px;
}
.highlight2 {
background: #EE0000;
color: #222;
padding: 5px 10px;
border-radius: 3px;
}
.highlight3 {
background: #00EE00;
color: #222;
padding: 5px 10px;
border-radius: 3px;
}
</style>
</head>
<body>
<p>Using <b>\\b\\W*</b></p>
<div class = "container">
<p>++F a C++ Java a ++D a E++</p>
<p>Z a language</p>
<p>++G++</p>
</div>
<p>Using <b>\\W*\\b</b></p>
<div class = "container2">
<p>++F a C++ Java a ++D a E++</p>
<p>Z a language</p>
<p>++G++</p>
</div>
<p>Using Start:<b>(?:^|\\W*\\b|\\b\\W*)</b> End:<b>(?:$|\\W*\\b|\\b\\W*)</b></p>
<div class = "container3">
<p>++F a C++ Java a ++D a E++</p>
<p>Z a language</p>
<p>++G++</p>
</div>
<script>
$(function() {
var searchList = ["Z", "java","c++", "++D", "E++", "++F", "language","++G++"];
$('.container').each(function() {
$(this).highlight(searchList, {
wordsOnly: true,
wordsBoundary: '\\b\\W*'
});
});
$('.container2').each(function() {
$(this).highlight(searchList, {
wordsOnly: true,
className: 'highlight2',
wordsBoundary: '\\W*\\b'
});
});
$('.container3').each(function() {
$(this).highlight(searchList, {
wordsOnly: true,
className: 'highlight3',
wordsBoundaryStart: '(?:^|\\W*\\b|\\b\\W*)',
wordsBoundaryEnd: '(?:$|\\W*\\b|\\b\\W*)'
});
});
});
</script>
</body>
</html>Как цитата из Документация по API из jquery-highlight
wordsBoundary -- If wordsOnly is set to true, this is used to determine these boundaries, defaults to \b (word boundary).
wordsBoundaryStart -- If wordsOnly is set to true, this is used to determine prefix word boundaries, defaults to the value of wordsBoundary.
wordsBoundaryEnd -- If wordsOnly is set to true, this is used to determine suffix word boundaries, defaults to the value of wordsBoundary.
Для wordsBoundary \b\W* поисковое выражение станет \b\W*(target word)\b\W*, это означает
.
1. начните с позиции границы слова между словом и не символом слова (\ b),
2. за которым следует ноль или более несловых символов (\ W *),
3. затем целевое слово
4. затем позиция границы слова между словом и не символом слова (\ b),
5. заканчиваться нулевым или более несловым символом (\ W *).
Следовательно, можно искать слово ++DНачните с несловесным символом.
И для противоположного случая \W*\b(target word)\W*\b, можно искать слово C++конец с символом, отличным от слова.
Обратите внимание, что ++F и E++ не совпадают, надеюсь, что кто-то, знакомый с Regex, может помочь объяснить.
В любом случае, это подсказка, что объединение первого и второго выражения должно быть тем, что мы ищем. Поскольку нам нужны разные выражения в начале и в конце, мы можем использовать опции wordsBoundaryStart и wordsBoundaryEnd. Затем, используя оператор или |, чтобы объединить первое и второе выражение и добавить начало (^) в wordsBoundaryStart, конец ($) в wordsBoundaryEnd, целевые слова будут выделены.
Поскольку метод highlight будет рассматривать первую группу как цель выделения, нам нужно использовать не захватывающую группу (?:) для условия «или».
Я не смотрел внимательно на код, который вы опубликовали, но эта часть выделяется:
wordsOnly: true; учитывая, что#- это, и большинство - если не все - «специальные символы» не считаются буквами, кажется, что поиск только слов является частью проблемы. Вы пробовалиwordsOnly: false?