jquery ui autocomplete, multiple values, templated results

by rwone

HTML

<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://cdn.rawgit.com/anseki/jquery-ui-autocomplete-scroll/master/jquery.ui.autocomplete.scroll.min.js"></script>
<p class="instructions">
  some good demonstrative searches include: "granite","92","ta", "wooden", "te".
</p>
<p class="instructions">
 matches at the START of the first object properly and ANYWHERE is the second object property.
</p>

<div class="product_container">

  <input class="my_lookup" placeholder="search..."><i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw"></i>
  <span class="sr-only">Loading...</span><span class="matches_prompt"></span><span class="matches_count"></span><span class="matches_text"></span>
  <br>
  <br>
  <input disabled class="product_desc related_info">
  <br>
  <input disabled class="product_type related_info">
  <br>
  <input disabled class="product_attr_01 related_info">
  <br>
  <input disabled class="product_attr_02 related_info">
  <br>
</div>

<div class="product_container">

  <input class="my_lookup" placeholder="search..."><i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw"></i>
  <span class="sr-only">Loading...</span><span class="matches_prompt"></span><span class="matches_count"></span><span class="matches_text"></span>
  <br>
  <br>
  <input disabled class="product_desc related_info">
  <br>
  <input disabled class="product_type related_info">
  <br>
  <input disabled class="product_attr_01 related_info">
  <br>
  <input disabled class="product_attr_02 related_info">
  <br>
</div>


<div class="product_container">

  <input class="my_lookup" placeholder="search..."><i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw"></i>
  <span class="sr-only">Loading...</span><span...

CSS

.matches_prompt,
.matches_count,
.matches_text {
  color: #8a8a8a;
  font-family: arial;
  font-size: 12px;
}

.ui-state-highlight {
  background: #ffffff !important;
  padding: 3px;
  color: #0681cf !important;
  border: 1px solid #60c1ff !important;
}

.ui-widget-content .ui-state-active .ui-state-highlight {
  background: #ffffff !important;
  padding: 0px !important;
  color: #0a7cff !important;
  border: 0px !important;
}

.instructions {
  font-family: arial;
  color: #333;
  font-size: 13px;
  margin-left: 5px;
}

.product_container {
  border: 1px solid #ccc;
  margin-bottom: 10px;
  padding: 10px;
  background: #fff;
}

.my_result {
  font-size: 15px !important;
  /* padding-right to give space next to scrollbar */
  padding: 15px 35px 15px 15px !important;
  font-family: arial !important;
  border-bottom: 1px solid #ccc !important;
}

.ui-menu-item:last-child .my_result {
  border-bottom: 0px !important;
}

.ui-widget-content .ui-state-active .result_img {
  border: 1px solid #0a7cff;
}

.ui-widget-content {
  background: #efefef !important;
}

.ui-widget-content .ui-state-active {
  border-top: 0px !important;
  border-right: 0px !important;
  border-left: 0px !important;
  /* this controls border color on hover */
  /*background: #ececec;*/
  background: #fefefe;
  /* this controls background color on hover */
  font-weight: normal;
  /*color: #212121;*/
  color: #0a7cff;
  margin: 0px !important;
  border-bottom: 1px solid #ccc !important;
}


/* see:  https://stackoverflow.com/questions/7273338/how-to-vertically-align-an-image-inside-div */

.helper {
  display: inline-block;
  height: 100%;
  vertical-align: middle;
}

.result_img {
  /*float: left;*/
  margin-right: 10px;
  vertical-align: middle;
  border: 1px solid #818181;
  border-radius: 1px;
}


/* to have image ready to display in results, so that dropdown is the correct width */

.loaded_img {
  display: none;
}


/* 

BEGIN unsuccesful attempts to style autocomplete

.ui-menu-item-wrapper...

JavaScript

// BEGIN show message prompt requiring 2 characters
$(".my_lookup").on("keyup", function() {
  var product_container = $(this).parent();
  var $matches_count = product_container.find(".matches_count");
  var $matches_text = product_container.find(".matches_text");
  var input_length = $(this).val().length;
  if (input_length < 2 && input_length !== 0) {
    $(this).siblings(".matches_prompt").text("search requires min 2 characters").show();
    $matches_count.text("").hide();
    $matches_text.text("").hide();
  } else if (input_length === 0 || input_length >= 2) {
    $(this).siblings(".matches_prompt").hide();
  }
});
// END show message prompt requiring 2 characters

// BEGIN look up on two values solution
// see:  https://stackoverflow.com/a/15849692
function lightwell(request, response) {
  // request.term is what you typed
  // response is the data to suggest to the user
  // added the 'match_type' argument to hasMatch() to:
  // - check for match at beginning of object's 'value' string
  // - check for match anywhere in object's 'product_desc' string
  // BEGIN hasMatch() function
  function hasMatch(s, match_type) {
    // to match beginning of string only,
    // use:  === 0
    // see:  https://stackoverflow.com/a/12482182
    // originally was !==-1 
    // to match anywhere in the string,
    // use !==-1
    // when match_type === "start",
    // below returns true if request.term is at the 0 index
    // of the object.value or object.product_desc string
    // when match_type === "anywhere",
    // returns true if at any index other than no index
    // original usage (anywhere) below
    // (remove 'match_type' argument and references to it):
    // return s.toLowerCase().indexOf(request.term.toLowerCase()) !== -1;
    // added conditional handling
    // BEGIN if match_type === "start"
    if (match_type === "start") {
      // check if typed in term is at the 0 index of object's 'value' string
      var is_at_start_of_string =...