如何匹配jQuery UI自动完成中两个对象值的开头? [英] How to match beginning of two object values in jQuery UI autocomplete?

查看:103
本文介绍了如何匹配jQuery UI自动完成中两个对象值的开头?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经成功地从为了只匹配一个对象值的开头:

In order to only match the beginning of one object value:

$.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:

I would like to be able to match on two object values - the object value and description, eg: searching for "01" should return object's 1 and 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

此答案查找两个值,因此我可以将其与我的jsFiddle解决方案合并,但我只需要它即可仅比赛开始.

This answer looks up on two values, so I could possibly merge it with my jsFiddle solution, but I just need it to match beginning only.

更新了我的原始小提琴,它似乎在执行所需的操作,但是我'不确定这是否是最有效的方法,或者是否会使dom变得混乱很多:/.

I've updated my original fiddle and it seems to be doing what is required, but I'm not sure if it's the most efficient way to do it or if it's cluttering up the dom a lot :/.

推荐答案

我认为我想出了一些更酷的东西,并且与我实际需要做的事情更相关-它在开始的 匹配value字符串或product_desc字符串中的任意位置.

I think I came up with something cooler and more relevant to what I actually needed to do - it matches at the beginning of the value string or anywhere in the product_desc string.

分叉的jsFiddle 的评论很高,因此那些只想对两个值(其中匹配项位于任一字符串的开头),可以注释掉某些行并达到该效果.

The forked jsFiddle is highly commented so those wanting to just do a lookup on two values (where the match is at the beginning of either string), can comment out some lines and achieve that effect.

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

I also implemented a number of other features:

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

这些内容也受到严重评论,因此可以根据需要将其删除或修改.

These are also heavily commented so they can be removed or modified if required.

我仍然希望确认这是一个相对干净的解决方案,它不会使两个多div的dom杂乱无章(自动完成功能似乎会向dom添加很多未使用的div?)

I would still appreciate confirmation that this is a relatively clean solution that does not clutter up the dom with two many divs (autocomplete seems to add lots of unused divs to the dom?)

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);
}

*/

这篇关于如何匹配jQuery UI自动完成中两个对象值的开头?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆