Easy Search As You Type List Filtering with jQuery

This post shows a quick and easy way of searching or filtering a list by typing into a textbox. Matching list items are revealed as you type.

This is great for working with any list to long to scan in a couple of seconds or it can be used for autocomplete or suggestions on searches, a better supported substitute for the HTML5 datalist input or simply add some checkboxes to create a multi-select control.

In this simple example we’ll filter a list of 5 dinosaurs. First, our HTML. We need a textbox and an unordered list:

<input type=”text” id=”dino-search” placeholder=”Search Dinosaurs (start typing)”>

<ul id=”dino-list”>
  <li>Triceratops</li>
  <li>Stegasaurus</li>
  <li>Tyrannosaurus Rex</li>
  <li>Diplodocus</li>
  <li>Pteradactyl</li>
</ul>

The actual filtering is done using jQuery and straight JavaScript. You’ll need to reference jQuery in your page, before the JavaScript block.

Here is the JavaScript. I’ll then explain it a line at a time.

$(document).ready(function () {

/* initially hide list items */
$(“#dino-list li”).hide();

/* filter dinosaurs as you type */
$(“#dino-search”).on(“keyup click input”, function () {
if (this.value.length > 0) {
  $(“#dino-list li”).hide().filter(function () {
    return $(this).text().toLowerCase().indexOf($(“#dino-search”).val().toLowerCase()) != -1;
  }).show();
}
else {
  $(“#dino-list li”).hide();
}
});

});

First of all we hide all the list items. The list itself, the <ul> element, is still shown but the items are hidden from view.

$(“#dino-list li”).hide();

To do the filtering we catch the keyup event on the search box. Every time a key is released while in the textbox the function gets fired. We’ve also used the click event to catch the user clicking the cross to clear the text box in some browsers as well as the input event to catch text being pasted in.

$(“#dino-search”).on(“keyup click input”, function () {
  …
});

If there is any text in the text box (its value has a length greater than zero) we filter, otherwise we keep all the items hidden. This is important so that we can go backwards and delete the search text without breaking it. The this.value.length is JavaScript and slightly easier to read than writing the jQuery version of $(this).val().length though it’s exactly the same in meaning.

if (this.value.length > 0) {
  …
}
else {
$(“#dino-list li”).hide();
}

We’re now looking at the section within the keyup event, where we have some text to match. We now make sure we hide the items again, filter the selection using jQuery’s filter function and then show the new selection of list items.

$(“#dino-list li”).hide().filter(function () {
  …
}).show();

Finally, the content of the filter function. Remember, we have all the list items selected and hidden in the previous line. Now we return list items where the text of the list item converted to lower case contains the value of the text box, also converted to lower case.

return $(this).text().toLowerCase().indexOf($(“#dino-search”).val().toLowerCase()) != -1;

The ‘contains’ part is done by using the indexOf() function which finds the index (numerical place) of a character within a string. This is zero indexed so the first character is 0, the second 1, etc. If the character or selection of characters is not found the function returns a value of -1. So, here we are saying if the index is not ‘not found’, which equates to ‘is found’.

This is the shortest way I’ve found of doing this but if anyone can do it with less code then I’d be very interested to see it. Please leave a comment.

Update

Changed the .keyup() event to .on(“keyup click input”) so that the user clicking the cross to clear the text box is caught by click() and resets the search results. The input() event catches text being pasted into the text box so we’ve now got all forms of input covered.

Posted in click(), datalist, filter(), html, indexOf(), input(), JavaScript, jQuery, on(), toLowerCase() | Tagged , , , , , , , , , , | 4 Comments

Creating simple character icons in CSS using ems

Here’s a quick way of bringing headings and otherwise dull content to life by using simple CSS to create simple single-character icons. Firstly, a quick example:

Circle Icons

And here’s the code, CSS first:

.circled
{
font-weight:bold;
width:1.5em;
height:1.5em;
line-height:1.5;
border-radius:1.5em;
text-align:center;
}

span.circled
{
display:inline-block;
}

.green
{
color: #393;
background-color: #cfc;
border: solid 1px #393;
}

.yellow
{
color: #993;
background-color: #ff9;
border: solid 1px #993;
}

.brown
{
color: #963;
background-color: #fc9;
border: solid 1px #963;
}

And HTML:

<div class=”circled yellow”>Y</div>
<div class=”circled green”>G</div>
<div class=”circled brown”>B</div>

Obviously you can use any colour schemes you like but using the same text and border colour with a lighter background colour seems to work quite nicely.

It’s worth noting the ‘.circled’ CSS class uses ’ems’ for all its properties – width, height, line-height and border-radius. By using ’ems’ we make all of these values relative to the size of the original text so they always resize around it. Using line-height is by far the easiest way of vertically aligning the text.

The element needs to have its ‘display’ property set to ‘block’ or ‘inline-block’ in order to handle the width correctly. Therefore, I’ve set ‘span.circled’ with ‘display:inline-block’ so that it can be used inline.

These single-character icons could be used with number characters for denoting sections or a document, letters A-E for grades or index values. You could even leave them blank to just show a circle at the appropriate text size.

If using a single letter, which is an abbreviation for a word or phrase, remember to use the <abbr> tag too, like this:

<div class=”circled brown”><abbr title=”Brown”>B</abbr></div>
Posted in border-radius, css, display, line-height | Tagged , , , , , , , , , , , | Comments Off on Creating simple character icons in CSS using ems

jQuery .on() – How to use it with $(this)

I’m posting this as I found this particular jQuery method quite difficult to understand from the official documentation at jquery.com. Documentation on the use of $(this) with .on() is not easy to find at the time of writing.

‘Normal’ selectors for events

jQuery selectors are used to select page elements which belong to the DOM (Document Object Model), or, more simply, they are part of the page’s HTML. If you try to select an element which is not in the original HTML or has been added by JavaScript then selecting these in the normal way won’t work.

For example, if you want a button click event you’d normally just use:

HTML

<input id=”continue” type=”button” value=”Continue” />

jQuery

$(document).ready(){

$(“#continue”).click(function(){
// your code
});

});

However, if the button was created in JavaScript but not added to the DOM* then this would not work.

.live()

The original way around this was to use a jQuery method called .live(), which worked by selecting an element and giving it an event. Here are a couple of examples:

$(“#continue”).live(“click”, function(){
// your code
});
$(“select”).live(“change”, function(){
// your code
});

This is quite straightforward to understand. You use the selector in the normal way and just put the event name inside the .live() event. Whilst using .live() currently still works (legacy support) there’s no guarantee it will continue to be supported in the future.

.on()

jQuery has found a far more efficient way of handling this with .on() but there’s a little more to it. Here’s an example of the syntax:

$(“li”).on(“click”, “a”, function(){
// your code
});

Here we have an initial selection “li”, an event “click” and a second selection “a”. The function (your code) will fire when a link (a) within a list item (li) is clicked. The first selector gives the context, the second is the actual selection. By using this first context selector it cuts down the search for the second and makes the whole thing run much faster.

If there is no obvious context element then you can go back to the top level by using $(document) like this:

$(document).on(“click”, “p”, function(){
// your code
});

The important point here, which catches out many people is that the first context selector must be part of the DOM.

.on() and $(this)

In the following code example, if you used $(this) in your code then it would refer to the “a”, rather than the “li” as you might expect.

$(“li”).on(“click”, “a”, function(){
// your code
});

* The easiest way of adding a newly created element to the DOM is by using .append() or .appendTo().

Posted in JavaScript, jQuery, on() | Tagged , , , , , , , , , , , | Comments Off on jQuery .on() – How to use it with $(this)