[SPIP] +2.1.12
[velocampus/web/www.git] / www / prive / javascript / SearchHighlight.js
diff --git a/www/prive/javascript/SearchHighlight.js b/www/prive/javascript/SearchHighlight.js
new file mode 100644 (file)
index 0000000..ee4dfc6
--- /dev/null
@@ -0,0 +1,222 @@
+/**
+ * SearchHighlight plugin for jQuery
+ * 
+ * Thanks to Scott Yang <http://scott.yang.id.au/>
+ * for the original idea and some code
+ *    
+ * @author Renato Formato <rformato@gmail.com> 
+ *  
+ * @version 0.37 (9/1/2009)
+ *
+ *  Options
+ *  - exact (string, default:"exact") 
+ *    "exact" : find and highlight the exact words.
+ *    "whole" : find partial matches but highlight whole words
+ *    "partial": find and highlight partial matches
+ *     
+ *  - style_name (string, default:'hilite')
+ *    The class given to the span wrapping the matched words.
+ *     
+ *  - style_name_suffix (boolean, default:true)
+ *    If true a different number is added to style_name for every different matched word.
+ *     
+ *  - debug_referrer (string, default:null)
+ *    Set a referrer for debugging purpose.
+ *     
+ *  - engines (array of regex, default:null)
+ *    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 second element is the regex to match the query string. 
+ *    Ex: [/^http:\/\/my\.site\.net/i,/search=([^&]+)/i]        
+ *            
+ *  - highlight (string, default:null)
+ *    A jQuery selector or object to set the elements enabled for highlight.
+ *    If null or no elements are found, all the document is enabled for highlight.
+ *        
+ *  - nohighlight (string, default:null)  
+ *    A jQuery selector or object to set the elements not enabled for highlight.
+ *    This option has priority on highlight. 
+ *    
+ *  - keys (string, default:null)
+ *    Disable the analisys of the referrer and search for the words given as argument    
+ *    
+ *  - min_length (number, default:null)
+ *    Set the minimun length of a key  
+ *   
+ */
+
+if (window.jQuery)
+(function($){
+  jQuery.fn.SearchHighlight = function(options) {
+    var ref = options.debug_referrer || document.referrer;
+    if(!ref && options.keys==undefined) return this;
+    
+    SearchHighlight.options = $.extend({exact:"exact",style_name:'hilite',style_name_suffix:true},options);
+    
+    if(options.engines) SearchHighlight.engines.unshift(options.engines);  
+    var q = SearchHighlight.splitKeywords(options.keys!=undefined?options.keys.toLowerCase():SearchHighlight.decodeURL(ref,SearchHighlight.engines));
+    if(q && q.join("")) {
+      SearchHighlight.buildReplaceTools(q);
+      if(!SearchHighlight.regex) return this;
+      return this.each(function(){
+        var el = this;
+        if(el==document) el = $("body")[0];
+        SearchHighlight.hiliteElement(el); 
+      })
+    } else return this;
+  };    
+
+  var SearchHighlight = {
+    options: {},
+    regex: null,
+    engines: [
+    [/^http:\/\/(www\.)?google\./i, /q=([^&]+)/i],                            // Google
+    [/^http:\/\/(www\.)?search\.yahoo\./i, /p=([^&]+)/i],                     // Yahoo
+    [/^http:\/\/(www\.)?search\.msn\./i, /q=([^&]+)/i],                       // MSN
+    [/^http:\/\/(www\.)?search\.live\./i, /query=([^&]+)/i],                  // MSN Live
+    [/^http:\/\/(www\.)?search\.aol\./i, /userQuery=([^&]+)/i],               // AOL
+    [/^http:\/\/(www\.)?ask\.com/i, /q=([^&]+)/i],                            // Ask.com
+    [/^http:\/\/(www\.)?altavista\./i, /q=([^&]+)/i],                         // AltaVista
+    [/^http:\/\/(www\.)?feedster\./i, /q=([^&]+)/i],                          // Feedster
+    [/^http:\/\/(www\.)?search\.lycos\./i, /q=([^&]+)/i],                     // Lycos
+    [/^http:\/\/(www\.)?alltheweb\./i, /q=([^&]+)/i],                         // AllTheWeb
+    [/^http:\/\/(www\.)?technorati\.com/i, /([^\?\/]+)(?:\?.*)$/i]           // Technorati
+    ],
+    subs: {},
+    decodeURL: function(URL,reg) {
+      //try to properly escape not UTF-8 URI encoded chars
+                       try {
+                               URL = decodeURIComponent(URL);
+                       } catch (e) {
+                               URL = unescape(URL);
+                       }
+      var query = null;
+      $.each(reg,function(i,n){
+        if(n[0].test(URL)) {
+          var match = URL.match(n[1]);
+          if(match) {
+            query = match[1].toLowerCase();
+            return false;
+          }
+        }
+      });
+      
+      return query;
+    },
+    splitKeywords: function(query) {
+      if(query) {
+        //do not split keywords enclosed by "
+        var m = query.match(/"([^"]*)"/g); 
+        if(m)
+          for(var i=0, ml=m.length;i<ml;i++) {
+            var regex = new RegExp(m[i]);
+            query = query.replace(regex,'@@@'+i+'@@@');
+          }
+        query = query.split(/[\s,\+]+/);
+        if(m)
+          for(var i=0,l = query.length;i<l;i++) {
+            for(var j=0, ml=m.length;j<ml;j++) {
+              var regex = new RegExp("@@@"+j+"@@@");
+              query[i] = query[i].replace(regex,m[j].substring(1,m[j].length-1))
+            }
+          }
+      };
+      return query;
+    },
+    
+               regexAccent : [
+      [/[\xC0-\xC5\u0100-\u0105]/ig,'a'],
+      [/[\xC7\u0106-\u010D]/ig,'c'],
+      [/[\xC8-\xCB]/ig,'e'],
+      [/[\xCC-\xCF]/ig,'i'],
+      [/[\u0141]/ig,'l'],
+      [/\xD1/ig,'n'],
+      [/[\xD2-\xD6\xD8]/ig,'o'],
+      [/[\u015A-\u0161]/ig,'s'],
+      [/[\u0162-\u0167]/ig,'t'],
+      [/[\xD9-\xDC]/ig,'u'],
+      [/\xFF/ig,'y'],
+      [/[\x91\x92\u2018\u2019]/ig,'\'']
+    ],
+    matchAccent : /[\x91\x92\xC0-\xC5\xC7-\xCF\xD1-\xD6\xD8-\xDC\xFF\u0100-\u010D\u0141\u015A-\u0167\u2018\u2019]/ig,  
+               replaceAccent: function(q) {
+                 SearchHighlight.matchAccent.lastIndex = 0;
+      if(SearchHighlight.matchAccent.test(q)) {
+        for(var i=0,l=SearchHighlight.regexAccent.length;i<l;i++)
+          q = q.replace(SearchHighlight.regexAccent[i][0],SearchHighlight.regexAccent[i][1]);
+      }
+      return q;
+    },
+    escapeRegEx : /((?:\\{2})*)([[\]{}*?|])/g, //the special chars . and + are already gone at this point because they are considered split chars
+    buildReplaceTools : function(query) {
+        var re = [], regex;
+        $.each(query,function(i,n){
+            if(!SearchHighlight.options.min_length || n.length>=SearchHighlight.options.min_length)
+              if(n = SearchHighlight.replaceAccent(n).replace(SearchHighlight.escapeRegEx,"$1\\$2"))
+                re.push(n);        
+        });
+        
+        if(!re.length) return;
+        regex = re.join("|");
+        switch(SearchHighlight.options.exact) {
+          case "exact":
+            regex = '\\b(?:'+regex+')\\b';
+            break;
+          case "whole":
+            regex = '\\b\\w*('+regex+')\\w*\\b';
+            break;
+        }    
+        SearchHighlight.regex = new RegExp(regex, "gi");
+        
+        $.each(re,function(i,n){
+            SearchHighlight.subs[n] = SearchHighlight.options.style_name+
+              (SearchHighlight.options.style_name_suffix?i+1:''); 
+        });       
+    },
+    nosearch: /s(?:cript|tyle)|textarea/i,
+    hiliteElement: function(el) {
+        var opt = SearchHighlight.options, elHighlight, noHighlight;
+        elHighlight = opt.highlight?$(opt.highlight):$("body"); 
+        if(!elHighlight.length) elHighlight = $("body"); 
+        noHighlight = opt.nohighlight?$(opt.nohighlight):$([]);
+                
+        elHighlight.each(function(){
+          SearchHighlight.hiliteTree(this,noHighlight);
+        });
+    },
+    hiliteTree : function(el,noHighlight) {
+        if(noHighlight.index(el)!=-1) return;
+        var matchIndex = SearchHighlight.options.exact=="whole"?1:0;
+        for(var startIndex=0,endIndex=el.childNodes.length;startIndex<endIndex;startIndex++) {
+          var item = el.childNodes[startIndex];
+          if ( item.nodeType != 8 ) {//comment node
+                                 //text node
+            if(item.nodeType==3) {
+              var text = item.data, textNoAcc = SearchHighlight.replaceAccent(text);
+              var newtext="",match,index=0;
+              SearchHighlight.regex.lastIndex = 0;
+              while(match = SearchHighlight.regex.exec(textNoAcc)) {
+                newtext += SearchHighlight.fixTags(text.substr(index,match.index-index))+'<span class="'+
+                SearchHighlight.subs[match[matchIndex].toLowerCase()]+'">'+SearchHighlight.fixTags(text.substr(match.index,match[0].length))+"</span>";
+                index = match.index+match[0].length;
+              }
+              if(newtext) {
+                //add the last part of the text
+                newtext += SearchHighlight.fixTags(text.substring(index));
+                var repl = $.merge([],$("<span>"+newtext+"</span>")[0].childNodes);
+                endIndex += repl.length-1;
+                startIndex += repl.length-1;
+                $(item).before(repl).remove();
+              }                
+            } else {
+              if(item.nodeType==1 && item.nodeName.search(SearchHighlight.nosearch)==-1)
+                  SearchHighlight.hiliteTree(item,noHighlight);
+            }  
+          }
+        }    
+    },
+    fixTags : function(text) {
+      return text.replace("<","&lt;").replace(">","&gt;");
+    }
+  };
+})(jQuery)