209 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
		
			Vendored
		
	
	
	
			
		
		
	
	
			209 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
		
			Vendored
		
	
	
	
| //qs_score - Quicksilver Score
 | |
| //
 | |
| //A port of the Quicksilver string ranking algorithm
 | |
| //
 | |
| //"hello world".score("axl") //=> 0.0
 | |
| //"hello world".score("ow") //=> 0.6
 | |
| //"hello world".score("hello world") //=> 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 "Software"), 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 "AS IS", 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 > this.length) return 0.0
 | |
| 
 | |
| for (var i = abbreviation.length; i > 0; i--) {
 | |
|  var sub_abbreviation = abbreviation.substring(0,i)
 | |
|  var index = this.indexOf(sub_abbreviation)
 | |
| 
 | |
| 
 | |
|  if(index < 0) continue;
 | |
|  if(index + abbreviation.length > this.length + offset) continue;
 | |
| 
 | |
|  var next_string       = this.substring(index+sub_abbreviation.length)
 | |
|  var next_abbreviation = null
 | |
| 
 | |
|  if(i >= abbreviation.length)
 | |
|    next_abbreviation = ''
 | |
|  else
 | |
|    next_abbreviation = abbreviation.substring(i)
 | |
| 
 | |
|  var remaining_score   = next_string.score(next_abbreviation,offset+index)
 | |
| 
 | |
|  if (remaining_score > 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 >= 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 >= (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
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| // Live search function taken from John Resig
 | |
| // http://ejohn.org/blog/jquery-livesearch/
 | |
| jQuery.fn.liveUpdate = function(list){
 | |
| 	list = jQuery(list);
 | |
| 
 | |
| 	// console.log(list);
 | |
| 	
 | |
| 	if ( list.length ) {
 | |
| 		// console.log(this);
 | |
| 		var rows = list.find('li > a'),
 | |
| 			cache = rows.map(function(){
 | |
| 				// console.log(this.innerHTML.toLowerCase());
 | |
| 				return this.innerHTML.toLowerCase();
 | |
| 			});
 | |
| 			
 | |
| 		this
 | |
| 			.keyup(filter).keyup()
 | |
| 			.parents('form').submit(function(){
 | |
| 				return false;
 | |
| 			});
 | |
| 
 | |
| 	}
 | |
| 		
 | |
| 	return this;
 | |
| 		
 | |
| 	function filter(){
 | |
| 		var term = jQuery.trim( jQuery(this).val().toLowerCase() ), scores = [];
 | |
| 		
 | |
| 		// we replace  space char with nothing since the score understand it	
 | |
| 		term = term.split(' ').join('');
 | |
| 		// console.log(term);
 | |
| 		
 | |
| 		if ( !term ) {
 | |
| 			rows.show();
 | |
| 			// update main window
 | |
| 			jQuery('#fileinfo ul#contents li').show();
 | |
| 			jQuery('#fileinfo table#contents td').parent().show();
 | |
| 		} else {
 | |
| 			rows.hide();
 | |
| 			// update main window
 | |
| 			jQuery('#fileinfo ul#contents li').hide();
 | |
| 			jQuery('#fileinfo table#contents td').parent().hide();
 | |
| 			
 | |
| 
 | |
| 			cache.each(function(i){
 | |
| 				var score = this.score(term);
 | |
| 				if (score > 0) { scores.push([score, i]); }
 | |
| 			});
 | |
| 			
 | |
| 			
 | |
| 			jQuery.each(scores.sort(function(a, b){return b[0] - a[0];}), function(){
 | |
| 				jQuery(rows[ this[1] ]).show();
 | |
| 				
 | |
| 			});
 | |
| 			
 | |
| 			// update main window
 | |
| 			jQuery('#filetree ul').find('li > a').each(function() {
 | |
| 				
 | |
| 				var rel = $(this).attr('rel');
 | |
| 				// console.log(rel);
 | |
| 				
 | |
| 				if($(this).css('display')!='none') {
 | |
| 					jQuery('#fileinfo ul#contents li[title="'+rel+'"]').show();
 | |
| 					jQuery('#fileinfo table#contents td[title="'+rel+'"]').parent().show();
 | |
| 				}
 | |
| 			});
 | |
| 			// update main window
 | |
| 		}
 | |
| 	}
 | |
| };
 | |
| 
 | |
| $(document).ready(function() {
 | |
| 	
 | |
| 		// remove default label on focus
 | |
| 		$("#q").focus(function() {
 | |
| 			$("#search span.q-inactive").css('display', 'none');
 | |
| 		});
 | |
| 		// if we click label we remove it and give focus to text field
 | |
| 		$("#search span.q-inactive").click(function() {
 | |
| 			$(this).css('display', 'none');
 | |
| 			$("#q").focus();
 | |
| 		});
 | |
| 		
 | |
| 		// display default label if val == ""
 | |
| 		// if not, display reset button
 | |
| 		$("#q").bind('blur keyup', function() {
 | |
| 			if ($(this).val() == "") {
 | |
| 				$("#search span.q-inactive").css('display', 'inline');
 | |
| 				$("#search a.q-reset").css('display', 'none');
 | |
| 			} else {
 | |
| 				$("#search a.q-reset").css('display', 'inline-table');
 | |
| 			}
 | |
| 		});
 | |
| 		
 | |
| 		
 | |
| 		
 | |
| 		// handle reset action
 | |
| 		$("#search a.q-reset").click(function() {
 | |
| 			$("#q").val('');
 | |
| 			$('#q').liveUpdate('#filetree ul').blur();
 | |
| 			return false;
 | |
| 		});
 | |
| 		
 | |
| 		// disable search form submit
 | |
| 		$('#search').submit(function(){
 | |
| 			return false;
 | |
| 		});
 | |
| 		
 | |
| 		// field init
 | |
| 		$('#q').blur();
 | |
| }); | 
