Skip to content
Extraits de code Groupes Projets
Valider 9c48c5ae rédigé par renato's avatar renato
Parcourir les fichiers

escape special chars in regexs and avoid looping the browser on some conditions

parent 9e188369
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
/** /**
* SearchHighlight plugin for jQuery * SearchHighlight plugin for jQuery
* *
* Thanks to Scott Yang <http://scott.yang.id.au/> * Thanks to Scott Yang <http://scott.yang.id.au/>
* for the original idea and some code * for the original idea and some code
* *
* @author Renato Formato <renatoformato@virgilio.it> * @author Renato Formato <renatoformato@virgilio.it>
* *
* @version 0.32 * @version 0.32
* *
* Options * Options
* - exact (string, default:"exact") * - exact (string, default:"exact")
* "exact" : find and highlight the exact words. * "exact" : find and highlight the exact words.
* "whole" : find partial matches but highlight whole words * "whole" : find partial matches but highlight whole words
* "partial": find and highlight partial matches * "partial": find and highlight partial matches
* *
* - style_name (string, default:'hilite') * - style_name (string, default:'hilite')
* The class given to the span wrapping the matched words. * The class given to the span wrapping the matched words.
* *
* - style_name_suffix (boolean, default:true) * - style_name_suffix (boolean, default:true)
* If true a different number is added to style_name for every different matched word. * If true a different number is added to style_name for every different matched word.
* *
* - debug_referrer (string, default:null) * - debug_referrer (string, default:null)
* Set a referrer for debugging purpose. * Set a referrer for debugging purpose.
* *
* - engines (array of regex, default:null) * - engines (array of regex, default:null)
* Add a new search engine regex to highlight searches coming from new search engines. * Add a new search engine regex to highlight searches coming from new search engines.
* The first element is the regex to match the domain. * The first element is the regex to match the domain.
* The second element is the regex to match the query string. * The second element is the regex to match the query string.
* Ex: [/^http:\/\/my\.site\.net/i,/search=([^&]+)/i] * Ex: [/^http:\/\/my\.site\.net/i,/search=([^&]+)/i]
* *
* - startHighlightComment (string, default:null) * - startHighlightComment (string, default:null)
* The text of a comment that starts a block enabled for highlight. * The text of a comment that starts a block enabled for highlight.
* If null all the document is enabled for highlight. * If null all the document is enabled for highlight.
* *
* - stopHighlightComment (string, default:null) * - stopHighlightComment (string, default:null)
* The text of a comment that ends a block enabled for highlight. * The text of a comment that ends a block enabled for highlight.
* If null all the document is enabled for highlight. * If null all the document is enabled for highlight.
*/ */
(function($){ (function($){
jQuery.fn.SearchHighlight = function(options) { jQuery.fn.SearchHighlight = function(options) {
var ref = options.debug_referrer || document.referrer; var ref = options.debug_referrer || document.referrer;
if(!ref && options.keys==undefined) return this; if(!ref && options.keys==undefined) return this;
SearchHighlight.options = $.extend({exact:"exact",style_name:'hilite',style_name_suffix:true},options); SearchHighlight.options = $.extend({exact:"exact",style_name:'hilite',style_name_suffix:true},options);
if(options.engines) SearchHighlight.engines.unshift(options.engines); if(options.engines) SearchHighlight.engines.unshift(options.engines);
var q = options.keys!=undefined?options.keys.split(/[\s,\+\.]+/):SearchHighlight.decodeURL(ref,SearchHighlight.engines); var q = options.keys!=undefined?options.keys.toLowerCase().split(/[\s,\+\.]+/):SearchHighlight.decodeURL(ref,SearchHighlight.engines);
if(q && q.join("")) { if(q && q.join("")) {
SearchHighlight.buildReplaceTools(q); SearchHighlight.buildReplaceTools(q);
return this.each(function(){ return this.each(function(){
var el = this; var el = this;
if(el==document) el = $("body")[0]; if(el==document) el = $("body")[0];
SearchHighlight.hiliteElement(el, q); SearchHighlight.hiliteElement(el, q);
}) })
} else return this; } else return this;
} }
var SearchHighlight = { var SearchHighlight = {
options: {}, options: {},
regex: [], regex: [],
engines: [ engines: [
[/^http:\/\/(www\.)?google\./i, /q=([^&]+)/i], // Google [/^http:\/\/(www\.)?google\./i, /q=([^&]+)/i], // Google
[/^http:\/\/(www\.)?search\.yahoo\./i, /p=([^&]+)/i], // Yahoo [/^http:\/\/(www\.)?search\.yahoo\./i, /p=([^&]+)/i], // Yahoo
[/^http:\/\/(www\.)?search\.msn\./i, /q=([^&]+)/i], // MSN [/^http:\/\/(www\.)?search\.msn\./i, /q=([^&]+)/i], // MSN
[/^http:\/\/(www\.)?search\.live\./i, /query=([^&]+)/i], // MSN Live [/^http:\/\/(www\.)?search\.live\./i, /query=([^&]+)/i], // MSN Live
[/^http:\/\/(www\.)?search\.aol\./i, /userQuery=([^&]+)/i], // AOL [/^http:\/\/(www\.)?search\.aol\./i, /userQuery=([^&]+)/i], // AOL
[/^http:\/\/(www\.)?ask\.com/i, /q=([^&]+)/i], // Ask.com [/^http:\/\/(www\.)?ask\.com/i, /q=([^&]+)/i], // Ask.com
[/^http:\/\/(www\.)?altavista\./i, /q=([^&]+)/i], // AltaVista [/^http:\/\/(www\.)?altavista\./i, /q=([^&]+)/i], // AltaVista
[/^http:\/\/(www\.)?feedster\./i, /q=([^&]+)/i], // Feedster [/^http:\/\/(www\.)?feedster\./i, /q=([^&]+)/i], // Feedster
[/^http:\/\/(www\.)?search\.lycos\./i, /q=([^&]+)/i], // Lycos [/^http:\/\/(www\.)?search\.lycos\./i, /q=([^&]+)/i], // Lycos
[/^http:\/\/(www\.)?alltheweb\./i, /q=([^&]+)/i], // AllTheWeb [/^http:\/\/(www\.)?alltheweb\./i, /q=([^&]+)/i], // AllTheWeb
[/^http:\/\/(www\.)?technorati\.com/i, /([^\?\/]+)(?:\?.*)$/i], // Technorati [/^http:\/\/(www\.)?technorati\.com/i, /([^\?\/]+)(?:\?.*)$/i], // Technorati
], ],
subs: {}, subs: {},
decodeURL: function(URL,reg) { decodeURL: function(URL,reg) {
URL = decodeURIComponent(URL); URL = decodeURIComponent(URL);
var query = null; var query = null;
$.each(reg,function(i,n){ $.each(reg,function(i,n){
if(n[0].test(URL)) { if(n[0].test(URL)) {
var match = URL.match(n[1]); var match = URL.match(n[1]);
if(match) { if(match) {
query = match[1]; query = match[1].toLowerCase();
return false; return false;
} }
} }
}) })
if (query) { if (query) {
query = query.replace(/(\'|")/, '\$1'); query = query.replace(/(\'|")/, '\$1');
query = query.split(/[\s,\+\.]+/); query = query.split(/[\s,\+\.]+/);
} }
return query; return query;
}, },
regexAccent : [ regexAccent : [
[/[\xC0-\xC5\u0100-\u0105]/ig,'a'], [/[\xC0-\xC5\u0100-\u0105]/ig,'a'],
[/[\xC7\u0106-\u010D]/ig,'c'], [/[\xC7\u0106-\u010D]/ig,'c'],
[/[\xC8-\xCB]/ig,'e'], [/[\xC8-\xCB]/ig,'e'],
[/[\xCC-\xCF]/ig,'i'], [/[\xCC-\xCF]/ig,'i'],
[/\xD1/ig,'n'], [/\xD1/ig,'n'],
[/[\xD2-\xD6\xD8]/ig,'o'], [/[\xD2-\xD6\xD8]/ig,'o'],
[/[\u015A-\u0161]/ig,'s'], [/[\u015A-\u0161]/ig,'s'],
[/[\u0162-\u0167]/ig,'t'], [/[\u0162-\u0167]/ig,'t'],
[/[\xD9-\xDC]/ig,'u'], [/[\xD9-\xDC]/ig,'u'],
[/\xFF/ig,'y'], [/\xFF/ig,'y'],
[/[\x91\x92\u2018\u2019]/ig,'\''] [/[\x91\x92\u2018\u2019]/ig,'\'']
], ],
matchAccent : /[\x91\x92\xC0-\xC5\xC7-\xCF\xD1-\xD6\xD8-\xDC\xFF\u0100-\u010D\u015A-\u0167\u2018\u2019]/ig, matchAccent : /[\x91\x92\xC0-\xC5\xC7-\xCF\xD1-\xD6\xD8-\xDC\xFF\u0100-\u010D\u015A-\u0167\u2018\u2019]/ig,
replaceAccent: function(q) { replaceAccent: function(q) {
SearchHighlight.matchAccent.lastIndex = 0; SearchHighlight.matchAccent.lastIndex = 0;
if(SearchHighlight.matchAccent.test(q)) { if(SearchHighlight.matchAccent.test(q)) {
for(var i=0,l=SearchHighlight.regexAccent.length;i<l;i++) for(var i=0,l=SearchHighlight.regexAccent.length;i<l;i++)
q = q.replace(SearchHighlight.regexAccent[i][0],SearchHighlight.regexAccent[i][1]); q = q.replace(SearchHighlight.regexAccent[i][0],SearchHighlight.regexAccent[i][1]);
} }
return q; return q;
}, },
buildReplaceTools : function(query) { escapeRegEx : /((?:\\{2})*)([[\]{}*?|])/g, //the special chars . and + are already gone at this point because they are considered split chars
re = new Array(); buildReplaceTools : function(query) {
for (var i = 0, l=query.length; i < l; i ++) { var re = [], regex;
query[i] = SearchHighlight.replaceAccent(query[i].toLowerCase()); $.each(query,function(i,n){
re.push(query[i]); if(n = SearchHighlight.replaceAccent(n).replace(SearchHighlight.escapeRegEx,"$1\\$2"))
} re.push(n);
});
var regex = re.join("|");
switch(SearchHighlight.options.exact) { regex = re.join("|");
case "exact": switch(SearchHighlight.options.exact) {
regex = '\\b(?:'+regex+')\\b'; case "exact":
break; regex = '\\b(?:'+regex+')\\b';
case "whole": break;
regex = '\\b\\w*('+regex+')\\w*\\b'; case "whole":
break; regex = '\\b\\w*('+regex+')\\w*\\b';
} break;
SearchHighlight.regex = new RegExp(regex, "gi"); }
SearchHighlight.regex = new RegExp(regex, "gi");
for (var i = 0, l = query.length; i < l; i ++) {
SearchHighlight.subs[query[i]] = SearchHighlight.options.style_name+ $.each(re,function(i,n){
(SearchHighlight.options.style_name_suffix?i+1:''); SearchHighlight.subs[n] = SearchHighlight.options.style_name+
} (SearchHighlight.options.style_name_suffix?i+1:'');
}, });
nosearch: /s(?:cript|tyle)|textarea/i, },
hiliteElement: function(el, query) { nosearch: /s(?:cript|tyle)|textarea/i,
var startIndex, endIndex, comment = false, opt = SearchHighlight.options; hiliteElement: function(el, query) {
if(!opt.startHighlightComment || !opt.stopHighlightComment) var startIndex, endIndex, comment = false, opt = SearchHighlight.options;
return SearchHighlight.hiliteTree(0,el.childNodes.length,el,query); if(!opt.startHighlightComment || !opt.stopHighlightComment)
if($.browser.msie) { return SearchHighlight.hiliteTree(0,el.childNodes.length,el,query);
var item = el.firstChild, i = 0, parents = [], startComment = false; if($.browser.msie) {
while(item) { var item = el.firstChild, i = 0, parents = [], startComment = false;
if(item.nodeType==8) { while(item) {
if($.trim(item.data)==opt.startHighlightComment) { if(item.nodeType==8) {
comment = startComment = true; if($.trim(item.data)==opt.startHighlightComment) {
startIndex= i+1; comment = startComment = true;
} else if($.trim(item.data)==opt.stopHighlightComment) { startIndex= i+1;
endIndex = i; } else if($.trim(item.data)==opt.stopHighlightComment) {
SearchHighlight.hiliteTree(startIndex,endIndex,item.parentNode,query); endIndex = i;
startComment = false; SearchHighlight.hiliteTree(startIndex,endIndex,item.parentNode,query);
} startComment = false;
} }
var next = item.nextSibling, back, child; }
if(!startComment && (child = item.firstChild)) { var next = item.nextSibling, back, child;
if(next) if(!startComment && (child = item.firstChild)) {
parents.push([next,i+1]); if(next)
item = child; parents.push([next,i+1]);
i = 0; item = child;
} else { i = 0;
if(!(item = next)) { } else {
if(back = parents.pop()) { if(!(item = next)) {
item = back[0]; if(back = parents.pop()) {
i = back[1]; item = back[0];
} i = back[1];
} else i++; }
} } else i++;
} }
} else { }
var walker = document.createTreeWalker(el,NodeFilter.SHOW_COMMENT,null,false), currComment; } else {
while(currComment = walker.nextNode()) { var walker = document.createTreeWalker(el,NodeFilter.SHOW_COMMENT,null,false), currComment;
if($.trim(currComment.data)==opt.startHighlightComment) { while(currComment = walker.nextNode()) {
comment = true; if($.trim(currComment.data)==opt.startHighlightComment) {
el = currComment.parentNode; comment = true;
startIndex = 0; el = currComment.parentNode;
endIndex = el.childNodes.length; startIndex = 0;
while(el.childNodes[startIndex]!=currComment) startIndex++; endIndex = el.childNodes.length;
startIndex++; while(el.childNodes[startIndex]!=currComment) startIndex++;
} else if($.trim(currComment.data)==opt.stopHighlightComment) { startIndex++;
while(el.childNodes[endIndex-1]!=currComment) endIndex--; } else if($.trim(currComment.data)==opt.stopHighlightComment) {
SearchHighlight.hiliteTree(startIndex,endIndex,el,query); while(el.childNodes[endIndex-1]!=currComment) endIndex--;
} SearchHighlight.hiliteTree(startIndex,endIndex,el,query);
} }
} }
if(!comment) SearchHighlight.hiliteTree(0,el.childNodes.length,el,query); }
}, if(!comment) SearchHighlight.hiliteTree(0,el.childNodes.length,el,query);
hiliteTree : function(startIndex,endIndex,el,query) { },
var matchIndex = SearchHighlight.options.exact=="whole"?1:0; hiliteTree : function(startIndex,endIndex,el,query) {
for(;startIndex<endIndex;startIndex++) { var matchIndex = SearchHighlight.options.exact=="whole"?1:0;
var item = el.childNodes[startIndex]; for(;startIndex<endIndex;startIndex++) {
if ( item.nodeType != 8 ) {//comment node var item = el.childNodes[startIndex];
//text node if ( item.nodeType != 8 ) {//comment node
if(item.nodeType==3) { //text node
var text = item.data, textNoAcc = SearchHighlight.replaceAccent(text); if(item.nodeType==3) {
var newtext="",match,index=0; var text = item.data, textNoAcc = SearchHighlight.replaceAccent(text);
SearchHighlight.regex.lastIndex = 0; var newtext="",match,index=0;
while(match = SearchHighlight.regex.exec(textNoAcc)) { SearchHighlight.regex.lastIndex = 0;
newtext += text.substr(index,match.index-index)+'<span class="'+ while(match = SearchHighlight.regex.exec(textNoAcc)) {
SearchHighlight.subs[match[matchIndex].toLowerCase()]+'">'+text.substr(match.index,match[0].length)+"</span>"; newtext += text.substr(index,match.index-index)+'<span class="'+
index = match.index+match[0].length; SearchHighlight.subs[match[matchIndex].toLowerCase()]+'">'+text.substr(match.index,match[0].length)+"</span>";
} index = match.index+match[0].length;
if(newtext) { }
//add ther last part of the text if(newtext) {
newtext += text.substring(index); //add the last part of the text
var repl = $.merge([],$("<span>"+newtext+"</span>")[0].childNodes); newtext += text.substring(index);
endIndex += repl.length-1; var repl = $.merge([],$("<span>"+newtext+"</span>")[0].childNodes);
startIndex += repl.length-1; endIndex += repl.length-1;
$(item).before(repl).remove(); startIndex += repl.length-1;
} $(item).before(repl).remove();
} else { }
if(item.nodeType==1 && item.nodeName.search(SearchHighlight.nosearch)==-1) } else {
SearchHighlight.hiliteTree(0,item.childNodes.length,item,query); if(item.nodeType==1 && item.nodeName.search(SearchHighlight.nosearch)==-1)
} SearchHighlight.hiliteTree(0,item.childNodes.length,item,query);
} }
} }
} }
}
};
})(jQuery) };
})(jQuery)
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter