Reputation: 2910
I found the jquery code (I forgot the original site) is working to replace a word in a html page to be star sign (*), and the code is running well, but the code can only be used to replace each a single word, can't change the part of the word and also case-sensitive.
JQuery code :
String.prototype.repeat = function(num){
return new Array(num + 1).join(this);
}
/* Word or Character to be replace */
var filter = ['itch','asshole', 'uck', 'sex'];
$('body').text(function(i, txt){
// iterate over all words
for(var i=0; i<filter.length; i++){
// Create a regular expression and make it global
var pattern = new RegExp('\\b' + filter[i] + '\\b', 'g');
// Create a new string filled with '*'
var replacement = '*'.repeat(filter[i].length);
txt = txt.replace(pattern, replacement);
}
// returning txt will set the new text value for the current element
return txt;
});
word filter:
['itch','asshole', 'uck', 'sex'];
and result :
sex -> *** // successfully replacing
SEX -> SEX // not replaced, i want this word also replaced to ***
bitch -> bitch // not replaced, i want this word replaced to b****
how to modify this jquery code so that can be used to change some of the characters in the word and not case-sensitive?
the fiddle : http://jsfiddle.net/bGhq8/
Thank you.
Upvotes: 1
Views: 1495
Reputation: 5245
The reason you are seeing the behavior you mention is because of the regular expression you have written (repeated below):
var pattern = new RegExp('\\b' + filter[i] + '\\b', 'g');
For starters, to get this to replace values in a case-insensitive manner, you need to add the 'i' flag for case-insensitivity
var pattern = new RegExp('\\b' + filter[i] + '\\b', 'gi');
In addition, the reason it is only replacing whole words is because of the word boundary flags (\b) being placed around the search criteria. If you don't want to limit yourself to replacing whole words, you need to consider what additional patterns are candidates for being replaced and how you want to replace them. One possible solution that gets you a bit closer by allowing for zero or one letters before the pattern would be:
var pattern = new RegExp('\\b([A-Z]?)' + filter[i] + '\\b', 'gi');
var replacement = '$1'+'*'.repeat(filter[i].length);
txt = txt.replace(pattern, replacement);
As a side note http://regexpal.com/ is a great place for testing (and therefore learning about) regular expressions.
Upvotes: 0
Reputation: 14429
Use the case sensitive option and no need for boundary.
String.prototype.repeat = function(num){
return new Array(num + 1).join(this);
}
/* Word or Character to be replace */
var filter = ['itch','asshole', 'uck', 'sex'];
$('body').text(function(i, txt){
// iterate over all words
for(var i=0; i<filter.length; i++){
// Create a regular expression and make it global
var pattern = new RegExp(filter[i] , 'gi'); // Add the "i" modifier for case insensitivity
// Create a new string filled with '*'
var replacement = '*'.repeat(filter[i].length);
txt = txt.replace(pattern, replacement);
}
// returning txt will set the new text value for the current element
return txt;
});
Updated fiddle: http://jsfiddle.net/bGhq8/3/
Upvotes: 1
Reputation: 5071
The following line in the code you provided:
var pattern = new RegExp('\\b' + filter[i] + '\\b', 'g');
matches on word boundaries (e.g. whitespace). In other words, it's a whole-word match on each word in the filter
array.
To match against any occurrence of the words in filter, whether or not they occur as partial words, you can remove '\\b'
from the start, the end, or both ends of the regular expression.
This approach, however, is not really ideal. Plenty of legitimate, non-offensive words -- itch
, sextet
, and so on -- will be censored by your filter. This is not something that is simple to solve without either:
Keeping the word boundary constraint as in the original code
Writing a custom regular expression for every offensive word you wish to censor (perhaps too time-consuming)
You should note that no single approach is going to be without false positives.
Upvotes: 0