如何在jQuery UI自动完成中匹配两个对象值的开头?

时间:2017-06-16 05:32:23

标签: jquery-ui jquery-ui-autocomplete

我已成功修改了this blog post的代码段。

为了只匹配一个对象值的开头:

$.ui.autocomplete.filter = function(array, term) {
var matcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(term), "i");
return $.grep(array, function(value) {
return matcher.test(value.value);
});
};

我希望能够匹配两个对象值 - 对象valuedescription,例如:搜索"01"应返回对象1和3:

var array_of_objects = [
{value: "01000", product_desc: "a unique orange from spain"},
{value: "02000", product_desc: "a unique pear from spain 01"},
{value: "02001", product_desc: "01000 desc starts with number"}];

jsFiddle

修改

This answer查找两个值,所以我可以将它与我的jsFiddle解决方案合并,但我只需要它来匹配开头。

编辑2:

updated my original fiddle它似乎正在做所需要的事情,但我不确定它是否是最有效的方法,或者它是否真的有效。 a d d::::::::::

1 个答案:

答案 0 :(得分:0)

我想我想出了一些更酷的东西,与我实际需要做的更相关 - 它匹配value字符串的开头任何地方product_desc字符串中。

forked jsFiddle被高度评论,因此那些想要对两个值(匹配位于任一字符串的开头)进行查找的人可以注释掉一些行并实现这种效果。

我还实现了许多其他功能:

  • 匹配突出显示
  • 显示比赛次数
  • 可滚动结果区域
  • 使用对象中的多个值填充页面元素
  • 模板化结果
  • 一页上的多个实例

这些也有很多评论,因此可以根据需要删除或修改它们。

我仍然会感谢确认这是一个相对干净的解决方案,不会使用两个多个div混淆dom(自动完成似乎在dom中添加了许多未使用的div?)

<强> JS

// 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 = s.toLowerCase().indexOf(request.term.toLowerCase()) === 0;
      if (is_at_start_of_string === true) {
        console.log("typed term is at start of value string");
      }
      return is_at_start_of_string;
    }
    // END if match_type === "start"

    // BEGIN if match_type === "anywhere"
    else if (match_type === "anywhere") {
      // check if typed in term is at any index of object's 'product_desc' string
      var exists_in_string = s.toLowerCase().indexOf(request.term.toLowerCase()) !== -1;
      if (exists_in_string === true) {
        console.log("typed term exists in product_desc string");
      }
      return exists_in_string;
    }
    // END if match_type === "anywhere"
  }
  // END hasMatch() function

  // declare variables, i and obj are undefined, matches is []
  var i, obj, matches = [];

  // BEGIN get the index of the input being used
  // see: https://stackoverflow.com/a/11278006/1063287
  var current_input_index = $(document.activeElement).parent().index() - 1;
  // END get the index of the input being used

  // BEGIN get refererences to dproduct relative dom elements
  var $product_container = $(".product_container").eq(current_input_index);

  var $matches_count = $product_container.find(".matches_count");
  var $matches_text = $product_container.find(".matches_text");
  // END get refererences to dproduct relative dom elements

  // BEGIN if the typed in term is nothing
  // pass an empty array to response()
  if (request.term === "") {
    console.log("this thing is happening");
    // hide the matches count display
    $matches_count.text("").hide();
    $matches_text.text("").hide();
    response([]);
    return;
  }
  // END if the typed in term is nothing

  // get length of array_of_objects
  var array_of_objects_length = array_of_objects.length;

  // for each object in the array, call the hasMatch() function
  // and pass it the object's 'value' and 'product_desc' strings
  for (i = 0; i < array_of_objects_length; i++) {
    obj = array_of_objects[i];
    // if either of the below conditions return true,
    // push the object to the matches array
    if (hasMatch(obj.value, "start") || hasMatch(obj.product_desc, "anywhere")) {
      matches.push(obj);
    }
  }
  // pass the matches array to response()
  // get the count of matches for display
  var matches_count = matches.length;
  console.log("matches length is: " + matches_count)
  if (matches_count === 0 || matches_count > 1) {
    var matches_text = " matches"
  } else if (matches_count === 1) {
    var matches_text = " match"
  }
  // display the count of matches
  $matches_count.text(matches_count).show();
  $matches_text.text(matches_text).show();
  response(matches);
}
// END look up on two values solution


// BEGIN autocomplete
$(".my_lookup").autocomplete({
  // only show 5 results with scrollbar
  // from:  http://anseki.github.io/jquery-ui-autocomplete-scroll
  maxShowItems: 5,
  source: lightwell,
  minLength: 2,
  // called on input blur if value has changed
  change: function(event, ui) {
    var product_container = $(this).closest(".product_container");
    var $matches_count = product_container.find(".matches_count");
    var $matches_text = product_container.find(".matches_text");
    $matches_count.text("").hide();
    $matches_text.text("").hide();
  },
  // called when selecting an option
  select: function(event, ui) {

    // get references to product relative selectors
    var product_container = $(this).closest(".product_container");
    var product_desc = product_container.find(".product_desc");
    var product_type = product_container.find(".product_type");
    var product_attr_01 = product_container.find(".product_attr_01");
    var product_attr_02 = product_container.find(".product_attr_02");

    var $matches_count = product_container.find(".matches_count");
    var $matches_text = product_container.find(".matches_text");
    $matches_count.text("").hide();
    $matches_text.text("").hide();

    // add object's values to relative product container inputs
    product_desc.val(ui.item.product_desc);
    product_type.val(ui.item.product_type);
    product_attr_01.val(ui.item.product_attr_01);
    product_attr_02.val(ui.item.product_attr_02);

    // BEGIN animate realtive inputs when selecting an option
    product_desc.animate({
      "backgroundColor": "#d0e4ff"
    }, {
      "queue": false,
      "duration": 800
    });
    product_desc.animate({
      "borderColor": "#7190dd"
    }, {
      "queue": false,
      "duration": 800
    });
    product_type.animate({
      "backgroundColor": "#d0e4ff"
    }, {
      "queue": false,
      "duration": 800
    });
    product_type.animate({
      "borderColor": "#7190dd"
    }, {
      "queue": false,
      "duration": 800
    });
    product_attr_01.animate({
      "backgroundColor": "#d0e4ff"
    }, {
      "queue": false,
      "duration": 800
    });
    product_attr_01.animate({
      "borderColor": "#7190dd"
    }, {
      "queue": false,
      "duration": 800
    });
    product_attr_02.animate({
      "backgroundColor": "#d0e4ff"
    }, {
      "queue": false,
      "duration": 800
    });
    product_attr_02.animate({
      "borderColor": "#7190dd"
    }, {
      "queue": false,
      "duration": 800
    });
    setTimeout(function() {
      product_desc.animate({
        "backgroundColor": "#ffff"
      }, {
        "queue": false,
        "duration": 800
      });
      product_desc.animate({
        "borderColor": "#cacaca"
      }, {
        "queue": false,
        "duration": 800
      });
      product_type.animate({
        "backgroundColor": "#ffff"
      }, {
        "queue": false,
        "duration": 800
      });
      product_type.animate({
        "borderColor": "#cacaca"
      }, {
        "queue": false,
        "duration": 800
      });
      product_attr_01.animate({
        "backgroundColor": "#ffff"
      }, {
        "queue": false,
        "duration": 800
      });
      product_attr_01.animate({
        "borderColor": "#cacaca"
      }, {
        "queue": false,
        "duration": 800
      });
      product_attr_02.animate({
        "backgroundColor": "#ffff"
      }, {
        "queue": false,
        "duration": 800
      });
      product_attr_02.animate({
        "borderColor": "#cacaca"
      }, {
        "queue": false,
        "duration": 800
      });
    }, 2000);
    // END animate realtive inputs when selecting an option
  },
  // show fontawesome loading animation when search starts
  search: function(event, ui) {
    console.log("search started");
    $(this).closest(".product_container").find(".fa-circle-o-notch").css("visibility", "visible");
  },
  // hide fontawesome loading animation when search finishes
  response: function(event, ui) {
    console.log("search finished");
    $(this).closest(".product_container").find(".fa-circle-o-notch").css("visibility", "hidden");
  },

  // BEGIN add styles to results
  // from:  https://gist.github.com/DBasic/9545690
  create: function() {
      $(this).data('ui-autocomplete')._renderItem = function(ul, item) {

        // create a new 'value' string for match highlighting
        // see: https://stackoverflow.com/a/9889056/1063287
        var newValueText = String(item.value).replace(
          // changed "gi" to i so that the match
          // on instance of search term is limited
          // to the first match, see:  
          // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp
          new RegExp(this.term, "i"),
          "<span class='ui-state-highlight'>$&</span>");

        // create a new 'description' string for match highlighting
        var newDescText = String(item.product_desc.toUpperCase()).replace(
          new RegExp(this.term, "gi"),
          "<span class='ui-state-highlight'>$&</span>");

        return $("<li></li>")
          .data("ui-autocomplete-item", item)
          // newValueText below used to be: item.value.toUpperCase()
          // newDescText below used to be: item.product_desc.toUpperCase()
          .append("<div class=\"my_result\"><span class=\"helper\"></span><img class=\"result_img\" src=\"https://placeimg.com/30/30/nature\">" + newValueText + " - " + newDescText + "</div>")
          .appendTo(ul);
      }
    }
    // END add styles to results

});
// END autocomplete


// new data set generated from https://github.com/Marak/faker.js

var array_of_objects = [{
  "value": "020101",
  "product_desc": "Handmade Frozen Pants",
  "product_type": "Automotive",
  "product_attr_01": "106.00",
  "product_attr_02": "171.00"
}, {
  "value": "010101",
  "product_desc": "Practical Fresh Hat",
  "product_type": "Movies",
  "product_attr_01": "589.00",
  "product_attr_02": "777.00"
}, {
  "value": "7099",
  "product_desc": "Awesome Concrete Sausages",
  "product_type": "Grocery",
  "product_attr_01": "249.00",
  "product_attr_02": "167.00"
}, {
  "value": "5740",
  "product_desc": "Sleek Plastic Pizza",
  "product_type": "Home",
  "product_attr_01": "924.00",
  "product_attr_02": "379.00"
}, {
  "value": "7627",
  "product_desc": "Intelligent Plastic Mouse",
  "product_type": "Games",
  "product_attr_01": "71.00",
  "product_attr_02": "412.00"
}, {
  "value": "6606",
  "product_desc": "Handmade Steel Pizza",
  "product_type": "Music",
  "product_attr_01": "71.00",
  "product_attr_02": "791.00"
}, {
  "value": "0973",
  "product_desc": "Intelligent Granite Tuna",
  "product_type": "Industrial",
  "product_attr_01": "25.00",
  "product_attr_02": "441.00"
}, {
  "value": "5453",
  "product_desc": "Generic Steel Sausages",
  "product_type": "Sports",
  "product_attr_01": "887.00",
  "product_attr_02": "786.00"
}, {
  "value": "3871",
  "product_desc": "Refined Wooden Keyboard",
  "product_type": "Sports",
  "product_attr_01": "897.00",
  "product_attr_02": "402.00"
}, {
  "value": "9646",
  "product_desc": "Incredible Soft Chicken",
  "product_type": "Kids",
  "product_attr_01": "849.00",
  "product_attr_02": "438.00"
}, {
  "value": "2948",
  "product_desc": "Licensed Plastic Gloves",
  "product_type": "Baby",
  "product_attr_01": "608.00",
  "product_attr_02": "748.00"
}, {
  "value": "1561",
  "product_desc": "Sleek Steel Towels",
  "product_type": "Music",
  "product_attr_01": "315.00",
  "product_attr_02": "332.00"
}, {
  "value": "5012",
  "product_desc": "Licensed Rubber Computer",
  "product_type": "Electronics",
  "product_attr_01": "886.00",
  "product_attr_02": "738.00"
}, {
  "value": "4827",
  "product_desc": "Unbranded Wooden Shoes",
  "product_type": "Shoes",
  "product_attr_01": "390.00",
  "product_attr_02": "753.00"
}, {
  "value": "0056",
  "product_desc": "Handcrafted Fresh Sausages",
  "product_type": "Shoes",
  "product_attr_01": "26.00",
  "product_attr_02": "257.00"
}, {
  "value": "0628",
  "product_desc": "Fantastic Steel Tuna",
  "product_type": "Tools",
  "product_attr_01": "881.00",
  "product_attr_02": "127.00"
}, {
  "value": "8498",
  "product_desc": "Gorgeous Soft Fish",
  "product_type": "Toys",
  "product_attr_01": "105.00",
  "product_attr_02": "604.00"
}, {
  "value": "9265",
  "product_desc": "Gorgeous Wooden Cheese",
  "product_type": "Clothing",
  "product_attr_01": "257.00",
  "product_attr_02": "438.00"
}, {
  "value": "0666",
  "product_desc": "Small Soft Keyboard",
  "product_type": "Baby",
  "product_attr_01": "960.00",
  "product_attr_02": "852.00"
}, {
  "value": "4628",
  "product_desc": "Intelligent Plastic Car",
  "product_type": "Music",
  "product_attr_01": "598.00",
  "product_attr_02": "339.00"
}, {
  "value": "3341",
  "product_desc": "Intelligent Metal Mouse",
  "product_type": "Garden",
  "product_attr_01": "92.00",
  "product_attr_02": "371.00"
}, {
  "value": "6547",
  "product_desc": "Awesome Concrete Shirt",
  "product_type": "Health",
  "product_attr_01": "344.00",
  "product_attr_02": "145.00"
}, {
  "value": "0803",
  "product_desc": "Unbranded Metal Chair",
  "product_type": "Kids",
  "product_attr_01": "343.00",
  "product_attr_02": "700.00"
}, {
  "value": "9769",
  "product_desc": "Awesome Granite Bike",
  "product_type": "Home",
  "product_attr_01": "545.00",
  "product_attr_02": "391.00"
}, {
  "value": "3087",
  "product_desc": "Refined Wooden Tuna",
  "product_type": "Industrial",
  "product_attr_01": "58.00",
  "product_attr_02": "68.00"
}, {
  "value": "3202",
  "product_desc": "Small Concrete Gloves",
  "product_type": "Kids",
  "product_attr_01": "846.00",
  "product_attr_02": "60.00"
}, {
  "value": "9638",
  "product_desc": "Generic Rubber Ball",
  "product_type": "Garden",
  "product_attr_01": "160.00",
  "product_attr_02": "123.00"
}, {
  "value": "4762",
  "product_desc": "Tasty Frozen Computer",
  "product_type": "Health",
  "product_attr_01": "698.00",
  "product_attr_02": "832.00"
}, {
  "value": "6606",
  "product_desc": "Rustic Frozen Shirt",
  "product_type": "Automotive",
  "product_attr_01": "867.00",
  "product_attr_02": "92.00"
}, {
  "value": "6853",
  "product_desc": "Ergonomic Steel Pants",
  "product_type": "Sports",
  "product_attr_01": "712.00",
  "product_attr_02": "378.00"
}, {
  "value": "5418",
  "product_desc": "Awesome Cotton Cheese",
  "product_type": "Toys",
  "product_attr_01": "483.00",
  "product_attr_02": "918.00"
}, {
  "value": "0230",
  "product_desc": "Licensed Cotton Towels",
  "product_type": "Clothing",
  "product_attr_01": "540.00",
  "product_attr_02": "415.00"
}, {
  "value": "3975",
  "product_desc": "Sleek Granite Pants",
  "product_type": "Outdoors",
  "product_attr_01": "823.00",
  "product_attr_02": "331.00"
}, {
  "value": "7581",
  "product_desc": "Ergonomic Concrete Bacon",
  "product_type": "Automotive",
  "product_attr_01": "640.00",
  "product_attr_02": "718.00"
}, {
  "value": "8550",
  "product_desc": "Practical Granite Table",
  "product_type": "Shoes",
  "product_attr_01": "94.00",
  "product_attr_02": "487.00"
}, {
  "value": "3358",
  "product_desc": "Fantastic Plastic Computer",
  "product_type": "Clothing",
  "product_attr_01": "448.00",
  "product_attr_02": "440.00"
}, {
  "value": "4586",
  "product_desc": "Ergonomic Steel Table",
  "product_type": "Games",
  "product_attr_01": "218.00",
  "product_attr_02": "806.00"
}, {
  "value": "6331",
  "product_desc": "Intelligent Wooden Gloves",
  "product_type": "Shoes",
  "product_attr_01": "236.00",
  "product_attr_02": "546.00"
}, {
  "value": "2871",
  "product_desc": "Handcrafted Wooden Salad",
  "product_type": "Beauty",
  "product_attr_01": "546.00",
  "product_attr_02": "259.00"
}, {
  "value": "1648",
  "product_desc": "Tasty Soft Pants",
  "product_type": "Kids",
  "product_attr_01": "641.00",
  "product_attr_02": "251.00"
}, {
  "value": "8096",
  "product_desc": "Practical Steel Chair",
  "product_type": "Toys",
  "product_attr_01": "609.00",
  "product_attr_02": "374.00"
}, {
  "value": "5810",
  "product_desc": "Refined Steel Chicken",
  "product_type": "Kids",
  "product_attr_01": "529.00",
  "product_attr_02": "705.00"
}, {
  "value": "7057",
  "product_desc": "Tasty Metal Mouse",
  "product_type": "Garden",
  "product_attr_01": "911.00",
  "product_attr_02": "935.00"
}, {
  "value": "2344",
  "product_desc": "Intelligent Cotton Pizza",
  "product_type": "Sports",
  "product_attr_01": "705.00",
  "product_attr_02": "220.00"
}, {
  "value": "9188",
  "product_desc": "Awesome Wooden Ball",
  "product_type": "Movies",
  "product_attr_01": "896.00",
  "product_attr_02": "850.00"
}, {
  "value": "1474",
  "product_desc": "Sleek Plastic Salad",
  "product_type": "Tools",
  "product_attr_01": "15.00",
  "product_attr_02": "668.00"
}, {
  "value": "6513",
  "product_desc": "Small Soft Chips",
  "product_type": "Health",
  "product_attr_01": "433.00",
  "product_attr_02": "74.00"
}, {
  "value": "4036",
  "product_desc": "Unbranded Wooden Soap",
  "product_type": "Grocery",
  "product_attr_01": "826.00",
  "product_attr_02": "920.00"
}, {
  "value": "9226",
  "product_desc": "Licensed Fresh Cheese",
  "product_type": "Industrial",
  "product_attr_01": "144.00",
  "product_attr_02": "102.00"
}, {
  "value": "1944",
  "product_desc": "Fantastic Rubber Shoes",
  "product_type": "Electronics",
  "product_attr_01": "820.00",
  "product_attr_02": "808.00"
}, {
  "value": "9379",
  "product_desc": "Small Wooden Tuna",
  "product_type": "Baby",
  "product_attr_01": "199.00",
  "product_attr_02": "160.00"
}, {
  "value": "7888",
  "product_desc": "Handcrafted Frozen Sausages",
  "product_type": "Electronics",
  "product_attr_01": "70.00",
  "product_attr_02": "419.00"
}, {
  "value": "1941",
  "product_desc": "Fantastic Granite Car",
  "product_type": "Grocery",
  "product_attr_01": "821.00",
  "product_attr_02": "853.00"
}, {
  "value": "8322",
  "product_desc": "Licensed Wooden Fish",
  "product_type": "Games",
  "product_attr_01": "998.00",
  "product_attr_02": "703.00"
}, {
  "value": "5586",
  "product_desc": "Fantastic Cotton Salad",
  "product_type": "Games",
  "product_attr_01": "887.00",
  "product_attr_02": "841.00"
}];

/* code to generate the above data set,
from: https://github.com/Marak/faker.js

var array_of_objects = [];

for (i = 0; i < 5; i++) {
    var obj = {}; 
    obj['value'] = faker.fake("{{finance.mask}}");
    obj['product_desc'] = faker.fake("{{commerce.productName}}");
    obj['product_type'] = faker.fake("{{commerce.department}}");
    obj['product_attr_01'] = faker.fake("{{commerce.price}}");
    obj['product_attr_02'] = faker.fake("{{commerce.price}}");
    array_of_objects.push(obj);
}

*/