[ DWR Website | Web Application Index ]

Ajax Search Demo

This demo allows you to filter the data in a table.

Search:

Name Age Address

Search Demo

On each change to the filter field we either call the server function People.getMatchingFromLargeCrowd() to find matches, or, if we have already found a set of matches, we filter that set if this makes sense.

The server code simply searches the data using a RegEx.

public List<Person> getMatchingFromLargeCrowd(String filter)
{
    List<Person> reply = new ArrayList<Person>();
    Pattern regex = Pattern.compile(filter, Pattern.CASE_INSENSITIVE);
    for (Person person : largeCrowd.values())
    {
        if (regex.matcher(person.getName()).find())
        {
            reply.add(person);
        }
    }
    return reply;
}

Found rows are added to the page using dwr.util.addRows:

dwr.util.addRows("peoplebody", filtered, [
  function(person) { return person.name.replace(pattern, "$1"); },
  function(person) { return "$" + person.age; },
  function(person) { return person.address; }
], { escapeHtml:false });

We use person.name.replace to highlight the matches.

HTML source:

<p>Search: <input id="filter" onkeyup="filterChanged();"/></p>
<table border="1" class="rowed grey">
  <thead>
    <tr>
      <th>Name</th>
      <th>Age</th>
      <th>Address</th>
    </tr>
  </thead>
  <tbody id="peoplebody">
  </tbody>
</table>

Javascript source:

function init() {
  dwr.util.useLoadingMessage();
  Tabs.init('tabList', 'tabContents');
  dwr.util.setValue("filter", "");
  addSingleRow("peoplebody", "Please enter a search filter");
}

var peopleCache = [ ];
var lastFilter = "";

function fillTable(people) {
  var filter = dwr.util.getValue("filter");
  var pattern = new RegExp("(" + filter + ")", "i");
  var filtered = [];
  for (i = 0; i < people.length; i++) {
    if (pattern.test(people[i].name)) {
      filtered.push(people[i]);
    }
  }
  dwr.util.removeAllRows("peoplebody");
  if (filtered.length == 0) {
    addSingleRow("peoplebody", "No matches");
  }
  else {
    dwr.util.addRows("peoplebody", filtered, [
      function(person) { return person.name.replace(pattern, "<span class='highlight'>$1</span>"); },
      function(person) { return "$" + person.age; },
      function(person) { return person.address; }
    ], { escapeHtml:false });
  }
  peopleCache = people;
}

function filterChanged() {
  var filter = dwr.util.getValue("filter");
  if (filter.length == 0) {
    dwr.util.removeAllRows("peoplebody");
    addSingleRow("peoplebody", "Please enter a search filter");
  }
  else {
    if (filter.charAt(0) == lastFilter.charAt(0)) {
      fillTable(peopleCache);
    }
    else {
      People.getMatchingFromLargeCrowd(filter.charAt(0), fillTable);
    }
  }
  lastFilter = filter;
}

function addSingleRow(id, message) {
  dwr.util.addRows(id, [1], [
    function(data) { return message; }
  ], {
    cellCreator:function() {
      var td = document.createElement("td");
      td.setAttribute("colspan", 3);
      return td;
    }
  });
}

Java source:

public class People {
    public People() {
        largeCrowd = createCrowd(1000);
    }

    public List<Person> getMatchingFromLargeCrowd(String filter) {
        List<Person> reply = new ArrayList<Person>();
        Pattern regex = Pattern.compile(filter, Pattern.CASE_INSENSITIVE);
        for (Person person : largeCrowd.values()) {
            if (regex.matcher(person.getName()).find()) {
                reply.add(person);
            }
        }
        return reply;
    }

    private final Map<String, Person> largeCrowd;

    // ...
}

dwr.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC
    "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN"
    "http://getahead.org/dwr/dwr20.dtd">

<dwr>
  <allow>
    <create creator="new" javascript="People" scope="script">
      <param name="class" value="org.getahead.dwrdemo.people.People"/>
    </create>
    <convert match="org.getahead.dwrdemo.people.Person" converter="bean"/>
  </allow>
</dwr>