In a simple search, customers search the catalog by entering text. For example, a customer could search for “shatter-proof helmets.” The customer’s input is searched as a complete string (for example, the above query would be based on “shatter-proof helmets” and not “shatter-proof” or “helmets”). We used SearchFormHandler to build up the query to apply to the SQL Repository (Product Catalog) and to return a result set (empty if no products are found). The result set(s) is a collection of repository items that can be displayed in any format. Simple searches return both products and categories.

We used properties or configuration files to define the action a page performs and Boolean arguments to specify the type of searching to perform. Property names specify which catalog properties to search. The single configurable form handler simplifies catalog searching and should support all searching requirements. If your store requires custom searching beyond configuration changes, you can easily extend this form handler or write another handler.

We implemented the simple search feature as a collection of Java Server Pages, page fragments, and a Nucleus component configuration file (properties file). The configuration file creates and configures a Nucleus component of type atg.commerce.catalog.SearchFormHandler to perform the search. The simple search functionality allows the user to enter a string and get products or categories that match the keywords as results.

Products have multiple properties such as keywords, description, longDescription, and displayName. Keywords are a one-to-many property and the others are one-to-one properties. A keyword search looks through all keyword properties for a string input. A text search looks through all text properties for a string input, but does not search keyword properties.

SimpleSearchFragment.jsp

We wanted customers to be able to search from other store pages besides the search page, SimpleSearch.jsp. Therefore, we created the small search form fragment that defines the search text entry field and the Search button to embed in any page that requires searching.

This fragment imports the CatalogSearch component in order to configure its searchInput property and invoke its seach handler.

Finally, the form redirects to the page name passed via the FormAction parameter. This page fragment declares a page parameter that is used as the action for the search form. In other words, the FormAction parameter is the file name of the page to which the user is redirected when the search form’s submit method is invoked.

The following example shows SimpleSearchFragment.jsp:

<!--
This page fragment is intended to be imbedded on any page that
requires a search capability. The FormAction parameter is the name
of the page to redirect to display the results of the search.
-->

<DECLAREPARAM NAME="FormAction" CLASS="java.lang.String"
  DESCRIPTION="The name of the that will be the action of this form">

<dsp:importbean bean="/atg/userprofiling/Profile"/>
<dsp:importbean bean="/atg/commerce/catalog/CatalogSearch"/>
<dsp:importbean bean="/atg/commerce/catalog/CatalogNavHistory"/>

<!-- Title: Simple Search Form Fragment -->

<dsp:getvalueof id="successUrl" param="FormAction" idtype="java.lang.String">
<dsp:form action="<%=successUrl%>" method="POST">

  Search for <dsp:input bean="CatalogSearch.searchInput" size="20" type="text"/>
  <input name="repositoryKey" type="hidden"
         value='<dsp:valueof bean="/OriginatingRequest.requestLocale.locale"/>'>
  <!-- use this hidden form tag to make sure the search handler is invoked if
       someone does not hit the submit button -->
  <dsp:input bean="CatalogSearch.search" type="hidden" value="Search"/>
  <dsp:input bean="CatalogSearch.search" type="submit" value="Search"/>

</dsp:form></dsp:getvalueof>

The hidden input tag is an HTML (rather than ATG-specific) workaround for forms with a single input field. The hidden input allows the user to invoke the submit method by typing the return key within the text input field. Without this hidden tag, the user must click the Search button.

SimpleSearch.jsp

SimpleSearch.jsp is a page built of several JSP code fragments that provide their own specific functionality. The SimpleSearch page uses two search-specific page fragments: SimpleSearchFragment.jsp accepts the search input string and invokes the search itself and SearchResultsFragment.jsp displays the search results.

SimpleSearchFragment.jsp takes a parameter called FormAction to indicate the page to go to when the form is submitted. In SimpleSearch.jsp, this value is set to SimpleSearch.jsp, causing the search page to reload when the search completes.

SearchResultsFragment.jsp is passed the value of the CatalogSearch component’s searchResultsByItemType parameter in order to format the results.

The following example shows SimpleSearch.jsp:

<%
/* This JSP code demonstrates how to perform a simple search on the
 * product catalog repository.  The CatalogSearch form handler component takes
   customer input and returns search results.  This form handler is configured
   with the following prooperties:
 *
 * doKeywordSearch=true          # search for input in keyword
                                   properties
 * keywordPropertyNames=keywords # which properties to search
 * itemTypes=category,product    # which repository item types to
                                   search
 * $scope=session                # the CatalogSearch component is
                                   session scoped
 *
 * The CatalogSearch form handler's handleSubmit() method will
 * generate a repository query based on the input.  The results of
 * the query are retrieved via the
 * CatalogSearch.searchResultsByItemType property and passed to the
 * SearchResultsFragment JSP droplet to be displayed.
 */
%>
<dsp:importbean bean="/atg/dynamo/droplet/ForEach"/>
<dsp:importbean bean="/atg/commerce/catalog/CatalogSearch"/>
<dsp:importbean bean="/atg/commerce/catalog/Navigator"/>
<dsp:setvalue bean="/atg/userprofiling/Profile.currentLocation"
              value="catalog_search"/>

<dsp:include page="../common/HeadBody.jsp" flush="true"></dsp:include>

<dsp:include page="../common/StoreBrand.jsp" flush="true"></dsp:include>

<span class=storelittle>
  <%
  /* Display Navigation information (list of all parent
   * categories as links users can jump to)
   */
  %>
  <dsp:include page="../catalog/common/breadcrumbs.jsp"
       flush="true">
      <dsp:param name="displaybreadcrumbs" value="true"/>
      <dsp:param name="no_new_crumb" value="true"/>
  </dsp:include>
</span>
<p>
<span class=storebig>Shop by Searching</span><br>
<p>
<table cellpadding=0 cellspacing=2 border=0>
  <tr>
    <td class=box-top-store>Simple Search</td>
  </tr>
  <tr>
    <td class=box>
      <%
       /* Use the SimpleSearchFragment JSP droplet, which contains
        * a simple form, to get the search input and to invoke the
        * CatalogSearch component's handleSubmit() method. */
      %>
      <dsp:include page="SimpleSearchFragment.jsp"
           flush="true"><dsp:param name="FormAction"
           value="SimpleSearch.jsp"/></dsp:include>
      <p>
      <dsp:a href="AdvancedSearch.jsp">Use the advanced search form
           instead</dsp:a>
      <br><font size=-1><i>Simple search result set size limited to
           50.</i></font><br>
    </td>
  </tr>
</table>
<p>
<%/* Display the results with the SearchResultsFragment JSP droplet */%>
<dsp:getvalueof id="pval0"
     bean="CatalogSearch.searchResultsByItemType">
<dsp:include page="SearchResultsFragment.jsp" flush="true">
<dsp:param name="ResultArray" value="<%=pval0%>"/>
</dsp:include></dsp:getvalueof>

<p>

<dsp:include page="../common/CatalogFooter.jsp"
     flush="true"></dsp:include>
<dsp:include page="../common/Copyright.jsp"
     flush="true"></dsp:include>

</BODY>
</HTML>
SearchResultsFragment.jsp

We used the SearchResultsFragment page fragment to iterate and display search results from both SimpleSearch.jsp and AdvancedSearch.jsp. ForEach is sent the parameter array, which can take many kinds of multi-valued objects. The type in this case is a java.util.Map that is the product of the SearchFormHandler component.

The Map has one entry for each value specified in the itemTypes value of the component’s configuration file. In both SimpleSearch and AdvancedSearch the itemTypes are category and product.

The Map is a collection of search result arrays and their associated itemType identifiers. The value associated with category and product in the Map is an array of category or product items, or null if no results are found for that key.

The category and product Map elements are extracted by iterating through the Map with the standard ForEach component in the outermost ForEach droplet tag. For each element of the Map, the Switch component is then invoked to distinguish the category and product elements, and to affect the order in which they’re rendered on the page.

Once the category and product search result array is obtained, it is necessary to iterate through each element of that array to display the results. In order to detect an empty result array, we used another Switch component, this time for the unsetOPARAM feature of Switch that identifies an empty input array and a message is rendered indicating that no items of the given type were found. When the array is non-null, the default OPARAM tag of the Switch is rendered. In this case, another call to the ForEach component iterates through the array and ItemLink.jsp is invoked for each element to properly format and display the repository item.

<%
/* ---------------------------------------------------------------
This jsp droplet demonstrates how to display the contents of search
that potentially returns both category and product repository items.
The one paramater, ResultArray, accepts a HashMap that contains
elements with the keys "category" and "product". The values of these
keys are collections of category or product repository items found in
the search.
----------------------------------------------------------------*/
%>

<DECLAREPARAM NAME="ResultArray"
       CLASS="java.util.Map"
       DESCRIPTION="Array of Search Results">

<dsp:importbean bean="/atg/dynamo/droplet/Switch"/>
<dsp:importbean bean="/atg/dynamo/droplet/ForEach"/>

<dsp:droplet name="ForEach">
 <dsp:param name="array" param="ResultArray"/>

 <%/*Each item in this array is a Collection of Categories or Products...*/%>
 <dsp:param name="elementName" value="ResultCollection"/>

 <dsp:oparam name="output">
  <dsp:droplet name="Switch">

   <%/*The key tells us if this is a Collection of Products or Categories:
    */%>
   <dsp:param name="value" param="key"/>

   <%/*For the list of CATEGORIES: */%>
   <dsp:oparam name="category">
    <b>We found these categories matching your search</b>
    <blockquote>

    <dsp:droplet name="Switch">
     <dsp:param name="value" param="ResultCollection"/>
     <dsp:oparam name="default">
      <p>
      <%/*For each Category in the Collection: */%>
      <dsp:droplet name="ForEach">
       <dsp:param name="array" param="ResultCollection"/>
       <dsp:param name="elementName" value="Category"/>
       <dsp:oparam name="output">

        <%-- Display a link to the Category: --%>
        <dsp:include page="../common/ItemLink.jsp" flush="true">
         <dsp:param name="Item" param="Category"/>
         <dsp:param name="Image" param="Category.thumbnailImage"/>
         <dsp:param name="DisplayText" param="Category.displayName"/>
         <dsp:param name="navAction" value="jump"/>
        </dsp:include>

        <br>
       </dsp:oparam>
      </dsp:droplet>
     </dsp:oparam>
     <%-- If NO Categories returned by the search: --%>
     <dsp:oparam name="unset">
      No category items in the catalog could be found that match your
      query
     </dsp:oparam>
    </dsp:droplet><%/*ForEach Category*/%>

    </blockquote>
    <P>
   </dsp:oparam>

   <%/*For the list of PRODUCTS: */%>
   <dsp:oparam name="product">
    <p>
    <b>We found these products matching your search</b>
    <blockquote><p>

    <dsp:droplet name="Switch">
     <dsp:param name="value" param="ResultCollection"/>

     <dsp:oparam name="default">

      <%/*For each Product in the Collection: */%>
      <dsp:droplet name="ForEach">
       <dsp:param name="array" param="ResultCollection"/>
       <dsp:param name="elementName" value="Product"/>

       <dsp:oparam name="output">
        <dsp:valueof param="element.manufacturer.displayName"/>

        <%/* Display a link to the Product: */%>
     <dsp:include page="../common/ItemLink.jsp" flush="true">
      <dsp:param name="Item" param="Product"/>
      <dsp:param name="Image" param="Product.thumbnailImage"/>
      <dsp:param name="DisplayText" param="Product.displayName"/>
      <dsp:param name="navAction" value="jump"/>
     </dsp:include>

        <br>
       </dsp:oparam>
      </dsp:droplet> <%/*ForEach Product*/%>

     </dsp:oparam>

     <%/*If NO Products returned by the search: */%>
     <dsp:oparam name="unset">
      No product items in the catalog could be found that match your
      query<p>
     </dsp:oparam>

    </dsp:droplet>
    </blockquote><P>
   </dsp:oparam>
  </dsp:droplet>

 </dsp:oparam>

</dsp:droplet>
 
loading table of contents...