[ DWR Website | Web Application Index ]

# Ajax Search Demo

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

- Demo
- How it works
- Source

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>