<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -1038,6 +1038,7 @@ function getSavedSearch(tab_name){
 function setListScrollerContent(s){
 	
 	$('listScroller').innerHTML = s;
+	QSAddition.buildCache();
 }
 
 function setMainContent(s){
@@ -1209,8 +1210,8 @@ function scrollToName(searcher_name){
 
 	var scroller = $('listScroller');
 	var a_array = scroller.getElementsByTagName('a');
-
-	if (!searcher_name.match(new RegExp(/\\s+/))){ //if searcher name is blank
+	
+	if (!searcher_name.match(new RegExp(/\s+/))){ //if searcher name is blank
 		
 		//var searcher_pattern = new RegExp(&quot;^&quot;+searcher_name, &quot;i&quot;); //the &quot;i&quot; is for case INsensitive
 		var searcher_pattern = new RegExp(&quot;^&quot;+RegExp.escape(searcher_name.escapeHTML()), &quot;i&quot;); //the &quot;i&quot; is for case INsensitive
@@ -1232,10 +1233,16 @@ function scrollToName(searcher_name){
 		// // an attempt at binary searching... have not given up on this yet...
 		//found_index = binSearcher(searcher_pattern, a_array, 0, a_array.length);
 
-		if ((found_index &gt;= 0) &amp;&amp; (found_index &lt; a_array.length)){
-
+		if ((found_index &gt;= 0) &amp;&amp; (found_index &lt; a_array.length)) {
 			scrollListToAnchor(a_array[found_index].id);//scroll to the item
 			setListActiveAnchor(a_array[found_index].id);//highlight the item
+		} else {
+			var result = QSAddition.searchCache(searcher_name);
+			if (result) {
+			  if (window.console &amp;&amp; window.console.log) { console.log('searching with qs'); }
+				scrollListToAnchor(result);
+				setListActiveAnchor(result);
+			}
 		}
 	}else{ //since searcher name is blank 
 		//scrollListToIndex(a_array, 0);//scroll to the item
@@ -1390,6 +1397,128 @@ function jsHref(url){
 //			return(split_point);
 //	
 //}
+
+var QSAddition = {	
+	buildCache: function() {
+	  if (window.console &amp;&amp; window.console.log) { console.log('building cache'); }
+	  QSAddition.rows = $A([]);
+	  QSAddition.cache = $A([]);
+		$$('#listScroller li a').each(function(element) {
+			QSAddition.rows.push(element);
+			QSAddition.cache.push(element.innerHTML.toLowerCase());
+		});
+	},
+	
+	searchCache: function(term) {
+		var term = term.toLowerCase();
+		var len = QSAddition.cache.length;
+		var scores = $A([]);
+		
+		for(var i=0; i &lt; len; i++) {
+			var score = QSAddition.cache[i].score(term);
+			if (score &gt; 0) { scores.push([score, i]); }
+		}
+		
+		sorted = scores.sort(function(a,b) { return b[0] - a[0]; })
+		return sorted.length &gt; 0 ? QSAddition.rows[sorted[0][1]] : null;
+	}
+}
+
+// qs_score - Quicksilver Score
+// 
+// A port of the Quicksilver string ranking algorithm
+// 
+// &quot;hello world&quot;.score(&quot;axl&quot;) //=&gt; 0.0
+// &quot;hello world&quot;.score(&quot;ow&quot;) //=&gt; 0.6
+// &quot;hello world&quot;.score(&quot;hello world&quot;) //=&gt; 1.0
+//
+// Tested in Firefox 2 and Safari 3
+//
+// The Quicksilver code is available here
+// http://code.google.com/p/blacktree-alchemy/
+// http://blacktree-alchemy.googlecode.com/svn/trunk/Crucible/Code/NSString+BLTRRanking.m
+//
+// The MIT License
+// 
+// Copyright (c) 2008 Lachie Cox
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the &quot;Software&quot;), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+// 
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+
+String.prototype.score = function(abbreviation,offset) {
+  offset = offset || 0 // TODO: I think this is unused... remove
+ 
+  if(abbreviation.length == 0) return 0.9
+  if(abbreviation.length &gt; this.length) return 0.0
+
+  for (var i = abbreviation.length; i &gt; 0; i--) {
+    var sub_abbreviation = abbreviation.substring(0,i)
+    var index = this.indexOf(sub_abbreviation)
+
+
+    if(index &lt; 0) continue;
+    if(index + abbreviation.length &gt; this.length + offset) continue;
+
+    var next_string       = this.substring(index+sub_abbreviation.length)
+    var next_abbreviation = null
+
+    if(i &gt;= abbreviation.length)
+      next_abbreviation = ''
+    else
+      next_abbreviation = abbreviation.substring(i)
+ 
+    var remaining_score   = next_string.score(next_abbreviation,offset+index)
+ 
+    if (remaining_score &gt; 0) {
+      var score = this.length-next_string.length;
+
+      if(index != 0) {
+        var j = 0;
+
+        var c = this.charCodeAt(index-1)
+        if(c==32 || c == 9) {
+          for(var j=(index-2); j &gt;= 0; j--) {
+            c = this.charCodeAt(j)
+            score -= ((c == 32 || c == 9) ? 1 : 0.15)
+          }
+
+          // XXX maybe not port this heuristic
+          // 
+          //          } else if ([[NSCharacterSet uppercaseLetterCharacterSet] characterIsMember:[self characterAtIndex:matchedRange.location]]) {
+          //            for (j = matchedRange.location-1; j &gt;= (int) searchRange.location; j--) {
+          //              if ([[NSCharacterSet uppercaseLetterCharacterSet] characterIsMember:[self characterAtIndex:j]])
+          //                score--;
+          //              else
+          //                score -= 0.15;
+          //            }
+        } else {
+          score -= index
+        }
+      }
+   
+      score += remaining_score * next_string.length
+      score /= this.length;
+      return score
+    }
+  }
+  return 0.0
+}
 API_GREASE_START
 
 PROTOTYPE_JS = &lt;&lt;PROTOTYPE_JS_START</diff>
      <filename>rdoc/generators/template/ajax/ajax.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>68ef5c06dcba3c60fe728ddd1b2432c468b149e5</id>
    </parent>
  </parents>
  <author>
    <name>John Nunemaker</name>
    <email>nunemaker@gmail.com</email>
  </author>
  <url>http://github.com/jnunemaker/ajax-rdoc/commit/f27242f1a4beef4d1788d48356024e3c03855e28</url>
  <id>f27242f1a4beef4d1788d48356024e3c03855e28</id>
  <committed-date>2008-06-30T13:13:31-07:00</committed-date>
  <authored-date>2008-06-30T13:13:31-07:00</authored-date>
  <message>pimped the ajax template to use the quicksilver string ranking algorithm if an exact match is not found</message>
  <tree>e7502df2f167ffeb514adf0580ad1fe77486a256</tree>
  <committer>
    <name>John Nunemaker</name>
    <email>nunemaker@gmail.com</email>
  </committer>
</commit>
