Archive

Archive for September, 2015

Select2: Custom matcher and highlighting

September 28th, 2015 No comments

    The Select2 uses the “contains”-matcher by default. In case of a big number of options, we’ve run into the time lag whenever the drop-down appears with the filtered out items. Of course, we could increase the minimumInputLength setting to minimize items within the drop-down. We, however, decided to change the algorithm used for filtering. The method below looks for options, any word of which is starting with the pattern typed in.

function wordStartMatcher(term, text, highlighting) {
	var myRe  = new RegExp("(?:^|\\s)" + term, "i");
	var match = myRe.exec(text);

	if (match != null && highlighting) {
		myRe = new RegExp("\\b" + term, "i");
		match = myRe.exec(text);
	}

	return match;
}

The method is used twice: for filtering out and for highlighting the found pattern in options. Two regexps in the method do the same, they both capture the beginning of each word. However, they handle Unicode in different ways. So the first one accurately chooses options that match while the second one fetches out the parts of the options to be highlighted.

Below is the method responsible for highlighting

function markMatch(text, term, markup, escapeMarkup) {
	var wordMatch = wordStartMatcher(term, text, true);

	var match = wordMatch ? wordMatch.index : -1;
	var tl = term.length;

	if (match < 0) {
		markup.push(Select2.util.escapeMarkup(text));
		return;
	}

	markup.push(Select2.util.escapeMarkup(text.substring(0, match)));
	markup.push("<span class='select2-match'>");
	markup.push(Select2.util.escapeMarkup(text.substring(match, match + tl)));
	markup.push("</span>");
	markup.push(Select2.util.escapeMarkup(text.substring(match + tl, text.length)));
}

The method fetches out the string part which meets the pattern and wraps it in special tags.

Ok, now is how to apply the custom matcher and highlighing to the Select2 control

$("#magazines").select2({
	matcher: function (term, text) {
		return wordStartMatcher(term, text) != null;
	},
	formatResult: function (result, container, query, escapeMarkup) {
		var markup = [];
		markMatch(this.text(result), query.term, markup, escapeMarkup);
		return markup.join("");
	}
});

Where the “#magazines“-control from the example is specified as

<select id="magazines" name="magazines">
	<option value="">Select a subscription</option>
	<option value="Msdn">MSDN Magazine</option>
	<option value="VS">Visual Studio Magazine</option>
	<option value="Code">CODE Magazine</option>
	<option value="Dobbs">Dr. Dobbs Journal</option>
	<option value="GameDev">Game Developer Magazine</option>
	<option value="LinUsDev">Linux User and Developer</option>
</select>

So, for the above listed options and the pattern defined as “u” the “contains”-matcher would give

  • Visual Studio Magazine
  • Dr. Dobbs Journal
  • Linux User and Developer

while the custom matcher gives what we really need

  • Linux User and Developer

Categories: HTML, JavaScript, Select2 Tags: , ,