SFDC Lookup

by Dan Shahin

HTML

<script src="https://code.jquery.com/jquery-2.2.0.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.min.js"></script>
<div class="container">
    <i class="fa fa-search fa-lg search-icon"></i>
    <label for="testInput" class="typeahead">super lookup</label>
    <input id="testInput" class="typeahead" type="text" />
    <pre id="debug"></pre>
</div>

<script id="item-template" type="text/x-handlebars-template">
  	<li id={{id}}>
    		<i class="fa fa-{{icon}}"></i>
        <span class="data">{{name}}</span> 
        <br/>
        Type: {{type}} <br/>
        Icon: {{icon}}
    </li>
</script>

CSS

div.container {
   font-family: arial;
}

label.typeahead{
    display: block;
}
input.typeahead{
    width: 400px;
    height: 30px;
    font-size: 24px;
    background-color : white;
}

i.search-icon{  
  position:absolute;
  top:35px;
  left:380px;
  color:gray;
}

i.search-icon.success{  
  color:lightgreen;
}

i.search-icon.fail{  
  color:red;
}


ul.typeahead{

  position: absolute;
  top : 47px;
  left : 8px;
  padding : 0px;
  width: 406px;
  
}

ul.typeahead>li{
  border : 1px solid lightgray;
  padding: 2px;
  background-color: white;
  font-size: 24px;
}

ul.typeahead>li.template{
  display:none;
}

ul.typeahead>li.selectable:hover{
  background-color: lightyellow;
  cursor: pointer;
}
ul.typeahead>li.selectable.focused{
  background-color: lightyellow;
  cursor: pointer;
}

JavaScript

(function($) {

  $.fn.lookup = function(options) {
  
  	// Plugin defaults – added as a property on our plugin function.
    $.fn.lookup.defaults = {
      placeholder: "typeahead...",
      //jsr method
      remoteAction: '',
      data: [],
      skipFields: ['id'],
      minMatchLength: 1,
      debug: false,
      //default template
      templateSource : '<li id={{id}}>{{name}}</li>'
    };

    var opts = $.extend({}, $.fn.lookup.defaults, options);

    var $input = $(this), //the original plain text input
      $parent = $input.parent(),
      selectedIndex = -1,
      optionMap = {},
      templateSource,   
      template;
      
      if(opts.templateId){
      		templateSource = $("#"+options.templateId).html();
      }else{
      		templateSource = opts.templateSource;
      }
			template = Handlebars.compile(templateSource);
      
    $clone = $input.clone();// the new typeahead input
    $clone.removeAttr('id')
      .attr({
        'placeholder': opts.placeholder
      })
      .insertAfter($input.hide());
    var html = '<ul class="typeahead"></ul>';
      
    $(html).insertAfter($clone);
    
    var size = opts.data.length;
    var selectedIndex = 0;
    $('i.search-')
    $.each( opts.data, function( index, obj ){
    	optionMap[obj.id] =obj;
      var newLi = template(obj);
      var $newLi = $('ul.typeahead>li').first().clone()
      		.removeClass('template')
          .attr('id',obj.id) //set id of li to object id
          .hide();
      $newLi.children('span.data').html(obj.name);
    	$('ul.typeahead').append(newLi);
      
    });	
    $('ul.typeahead>li').hide();
    $clone.keyup(function(event){
    		hideAllOptions();
    		var $lookup = $(this),
        		query = $lookup.val(),
            key = event.keyCode;
            
        if(query === ''){
        	$('ul.typeahead>li').hide();
          reset();
        	return;
        }
        
        debug(query,event);
        //up arrow
        if(key === 38 ){
           ...