user4584963
user4584963

Reputation: 2523

Why is typeahead matching periods?

I am using the same code from the typeahead example here. However if you type in a period . the dropdown will appear with matches. Is all this code above the array definition necessary? Is there an easier way to accomplish the same thing where you won't get matches for periods if there are no periods in your array?

I see the bloodhound example below it accomplishes the same thing and doesn't match periods but is it using var states to define an array and then using var states to construct a new bloodhound engine is this a mistake?

Copied code from the website:

var substringMatcher = function(strs) {
  return function findMatches(q, cb) {
    var matches, substringRegex;

    // an array that will be populated with substring matches
    matches = [];

    // regex used to determine if a string contains the substring `q`
    substrRegex = new RegExp(q, 'i');

    // iterate through the pool of strings and for any string that
    // contains the substring `q`, add it to the `matches` array
    $.each(strs, function(i, str) {
      if (substrRegex.test(str)) {
        matches.push(str);
      }
    });

    cb(matches);
  };
};

var states = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California',
  'Colorado', 'Connecticut', 'Delaware', 'Florida', 'Georgia', 'Hawaii',
  'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana',
  'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota',
  'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire',
  'New Jersey', 'New Mexico', 'New York', 'North Carolina', 'North Dakota',
  'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island',
  'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont',
  'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming'
];

$('#the-basics .typeahead').typeahead({
  hint: true,
  highlight: true,
  minLength: 1
},
{
  name: 'states',
  source: substringMatcher(states)
});

In my case I am generating an array of tags so instead of the states I am using var tags = <%= raw Tag.all.pluck(:name) %>;

Upvotes: 0

Views: 119

Answers (2)

Shaun Hubbard
Shaun Hubbard

Reputation: 21

So regular expressions are "complicated", and easy to get wrong. "." for instance has special meaning in regex which matches any charachter except newline in JS, so for example based on Mozilla's docs RexExp(".n", "i") would match ".n", "an", "in", "?n" and many more.

Regular expressions are difficult to get right.

@John-Hascall's suggestion is a good fix for the problem.

Upvotes: 1

John Hascall
John Hascall

Reputation: 9416

You may find indexOf to be more useful than a regex for your application.

if (haystack.indexOf(needle) != -1) {
        /* needle is in haystack */
}

or, case insensitively:

if (haystack.toLowerCase().indexOf(needle.toLowerCase()) != -1) {
}

something like this:

function findMatches(q, cb) {
    var lq = q.toLowerCase();
    var matches = [];

    $.each(strs, function(i, str) {
        if (str.toLowerCase().indexOf(lq) != -1) matches.push(str);
    });

    cb(matches);
}

Upvotes: 1

Related Questions