Welcome, guest ( Login )

» Home (JDC Blog)
» Forums

Page Tags

filter filtered search facet faceted facets pivot tutorial

Search Tags:
WikiHome » JotDoc » Tutorials » FilteredSearchTutorial

FilteredSearchTutorial

Version 4, changed by ScottMcmullan. 09/27/2006.   Show version history

JotSpot Developer Documentation

jot developer tutorials

Filtered Search

Some times you want to view a list or a table or a collection of pages based on some filter or "pivot" or "facet". You want to be able to pick from a list and then view pages based on your selection.

For example here on the JDC, we're moving code examples into individual pages to allow them to be tagged, searched, and discovered in different ways:

Simple Filtered (or Pivoted) Searches in Jot

So how does this work? The basic idea is to create a Jot page that uses an HTML form to allow users to select one or more filter values. You then perform a Jot search based on these filter arguments in the page's query string.

Let's take a look at the ViewExamples page used here on the JDC. (Note: this code requires the use of an HTML form, so we'll need to use XML mode to edit our page.)

Step 1: Create the HTML form

This is the standard HTML form that hard-codes a dropdown list of choices for navigating the JDC examples. Note that the form's action points back to my ViewExamples wiki page.

   <form action="wiki:ViewExamples" method="GET">
   <select name="tag">
      <option value="">View examples by tag...</option>
      <option value="search">search</option>
      <option value="search">table</option>
      <option value="search">form</option>
      <option value="all">All Tags</option>
   </select>
   <input type="submit" value="Go" />
   </form>

Step 2: Search for pages based on user selection

When the user makes a selection and presses the "Go" button, the tag query string parameter is added to our page. So the page's URL ends up looking like:

http://developer.jot.com/WikiHome/ViewExamples?tag=search

I access the query string parameter with the ${req/args/tag} expression and use it to parameterize my search. I use a filter that returns only those pages with the tag specified by req/args/tag:

<jot:search forFormName="DevDocExampleForm" filter="${it/main/tags = req/args/tag}" set="exampleSet" />

Step 3: Display your pages

With the set of pages from the search in hand, you can display them any way you want. Common methods include a Jot table or looping over the set and displaying some type of list.

Here's code that uses a loop to display the examples and their text in a simple list:

   <jot:loop over="exampleSet">
      <br /><br />
      <h3><a href="${it/name}">${it/DevDocExampleForm/title}</a></h3>
      by <a href="wiki:/${it/createUser}-profile" style="color: #999">${it/createUser}</a><br />
      <jot:include node="${it}" />
      <br />
   </jot:loop>

Complete Source

Here's the full source of ViewExamples. Remember this requires working in XML editing mode. There's a bunch of other stuff in here to make the page a bit prettier. You can play with it by going to the ViewExamples page.

Of particular interest is the way I populate the select box from a search result instead of hard-coding the list. First I search for all example tags using <jot:search forFormName="DevDocExampleForm" collect="it/main/tags" set="exampleTags" />, then construct the option list by looping over exampleTags:

      <jot:loop over="exampleTags">
         <option value="${it}">${it}</option>
      </jot:loop>

Snapshot of ViewExamples

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:jot="http://www.foopee.com/ns/s3/srvtmpl/">
   <br />
   <jot:search forFormName="DevDocExampleForm" collect="it/main/tags" set="exampleTags" />
   <form action="wiki:ViewExamples" method="GET">
   <select name="tag">
      <option value="">View examples by tag...</option>
      <jot:loop over="exampleTags">
         <option value="${it}">${it}</option>
      </jot:loop>
      <option value="all">All Tags</option>
   </select>
   <input type="submit" value="Go" />
   </form>
   <br />
   <jot:if test="${util:isDefined(req/args/tag)}">
   <jot:then>
      <jot:if test="${req/args/tag = 'all'}">
      <jot:then>
         <h2>All Examples</h2>
         <jot:search forFormName="DevDocExampleForm" set="exampleSet" />
      </jot:then>
      <jot:else>
         <h2>All Examples Tagged <i>${req/args/tag}</i></h2>
         <jot:search forFormName="DevDocExampleForm" filter="${it/main/tags = req/args/tag}" set="exampleSet" />
      </jot:else>
      </jot:if>
   </jot:then>
   <jot:else>
      <jot:search forFormName="DevDocExampleForm" filter="contains(it/path, page/name)" set="exampleSet" />
   </jot:else>
   </jot:if>
   <jot:loop over="exampleSet">
      <ol>
         <li><a href="#${it/name}">${it/DevDocExampleForm/title}</a>
<span style="color: #999; font-size: smaller;">by
<a href="wiki:/${it/createUser}-profile" style="color: #999">${it/createUser}</a></span></li>
      </ol>
   </jot:loop>
   <jot:loop over="exampleSet">
      <br /><br />
      <h3><a name="${it/name}"><a href="${it/name}">${it/DevDocExampleForm/title}</a></a></h3>
      <span style="color: #999; font-size: smaller;">by
<a href="wiki:/${it/createUser}-profile" style="color: #999">${it/createUser}</a></span><br />
      <jot:include node="${it}" />
      <br />
   </jot:loop>
   <br /><br />
   <jot:include node="PostNewExampleForm" />
</html>

Filtering on Two or More Properties

To filter on two or more properties, we'll simply extend the technique used above. This time we'll define our search filters in Server-side Javascript, which allows us to create just about any filter logic we can dream up. (In this case, I've kept it simple.)

Complete Source

Here's the complete source code for the SearchTextAndTags example. This code searches using two filters, in this case looking for specific strings in the main/text property AND specific tags in the main/tags property. These are the properties I've chosen for this example -- you can search for any properties you want.

Snapshot of SearchTextAndTags

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:jot="http://www.foopee.com/ns/s3/srvtmpl/">
<br /><h3>Search for pages with specific content and tags</h3>
<form action="wiki:${page/name}" method="GET">
Main text contains: <input name="mainTextValue" />
and tags contain:
<select name="tagValue">
   <option value="" />
   <option value="search">search</option>
   <option value="filter">filter</option>
   <option value="table">table</option>
</select>
<input type="submit" value="Search" />
</form>

<jot:if test="${util:isDefined(req/args/mainTextValue) and util:isDefined(req/args/tagValue)}">
<jot:then>

<hr />
<jot:script>
<![CDATA[
  //custom search filter, which looks at a page's main/tags stringList property
  function filterByTag(pg, tag) {
    if (pg && typeof(pg.main) != "undefined" && typeof(pg.main.tags) != "undefined")
       return pg.main.tags.toString().indexOf(tag) >= 0;
  }
  //custom search filter, which searches a page's main/text wiki property
  function filterByMainTextContent(pg, str) {
    if (pg && typeof(pg.main) != "undefined" && typeof(pg.main.text) != "undefined")
       return jot.lib.util.isTextMatch(str, pg);
  }
]]>
</jot:script>

<h4>Pages that contain the string "<i>${req/args/mainTextValue}</i>" that are
    also tagged <i>${req/args/tagValue}</i>:</h4>
<jot:search forAll="1"
            filter="${filterByTag(it, req/args/tagValue) and filterByMainTextContent(it, req/args/mainTextValue)}"
            limit="9999"
            set="resultSet" />
<jot:table contents="resultSet" />

</jot:then>
</jot:if>
</html>

Attachment (1)

  File By Size Attached Ver.
 searchTextAndTagsScreenshot.png ScottMcmullan 17K 09/27/2006 1 Delete attachment