AJAX search with Lemonstand

January 15, 2013

Even the best organized ecommerce store can probably benefit from a search feature: here at 320ny we prefer Lemonstand for our projects, and it features some excellent search abilities right out of the box.

If you follow the Lemonstand documentation you can quickly implement a basic search form and results page, but what if you want a more responsive results page? One that can filter results and update the product list without reloading a new page? Fortunately it's pretty straightforward.

I'm assuming that you've already completed the basic Lemonstand search page: that means you have a page for search, and partials product_list and search_form. We're going to start by creating a new page that also implements the Shop:Search action, but for this one, we don't assign a layout because the contents will be delivered via AJAX and inserted into the DOM.

Let's call this page ajaxsearch, leave the layout blank and assign a url (I use '/ajax/search' ). The contents are very simple, you'll just render your product_list partial.

Now we need to create a partial for the search results filter. This is basically implementing the advanced search options described in the Lemonstand docs, but we'll add some javascript to enhance its behavior. For brevity, we won't list EVERY search option you can add, but we'll use 'size' as an example. For reference the entire shop;search_filter_form is on github.

A few things to notice here:

  • We use conditionals to assign a few variables: option_values - check whether we have a specific category, if so display the sizes within that one, otherwise display all size options in the store. selected_size - is this a blank search page, or do we have results - if you've made a search it's good UI to have your filter display the relevant search options that were chosen.
  • We use the selected_size variable to assign a particular class to an option element if it was the one chosen in the search.
  • The actual <select> tag is hidden, we create our own spans and will style and attach event listeners to those. This is a matter of personal preference of course, and could be accomplished any number of other ways.

Now we need to start putting the pieces together. We use the search filter on every category page, and the search results page - with only a slight difference in the way the partial is called. For each category page, we'd like to only filter products within that category, for the search page in general we'd like the ability to search within all categories, or maybe a few chosen categories. How might this be accomplished?

So what's going on here?

First you might notice that we use a custom method. Lemonstand gives you the ability to search for ALL product options within the shop, but not all the options within a single category. Since we wanted an effective category search feature we had to provide our own custom method (available on github).

With that out of the way, what else is this block doing?

  • Is selected_categories defined? We check if this is a return from an actual search with categories chosen by the user. If selected_categories isn't defined, we check if we're on a specific category page (is the 'category' variable defined?)
  • We define the beginning of the search form, with a hidden input at the top for the search query if it exists (if the user searched products for a specific string)
  • We use a for loop to build our category select tag and the options. If we're on a category page, we make this hidden and we assign that category as the select tag's value.
  • If there isn't a category variable, which means we're on a search page, we use another loop to create our option spans. These are what the users will actually see and click.
  • At the bottom we set a my_cat variable, we use this to output the category specific options for the search terms to follow if we're on a category page. i.e only the colors, sizes, brands, etc within Category A.

Take some time and examine the rest of the page, next we'll take a look at the javascript that will handle the form behavior. There are really only two major tasks for the javascript - detect a form submit event and override with AJAX, and use click listeners to handle the user clicking and selecting different search options.

This isn't a huge file and there's not a lot of advance behavior:

  • At the top, we have a 'submit' event bound to the 'search-filter' form. We use $.ajax to serialize the form data, submit to our ajax url, and on success insert the result into the DOM.
  • We have $.toggle functions defined for each of the search options present in the filter. These are responsible for adding a class (or removing a class) to show the user they've selected/deselected that option, and for submitting the form afterwards (using Lemonstand's getForm function).

So that's about it. Hopefully by now you'll be able to implement some basic AJAX search for your Lemonstand store. If something was unclear, confusing, or contradictory - or if you have any unrelated Lemonstand questions - please don't hesitate to let me know.

Happy building!