HOW TO create a dynamic search results with JQuery

Eric BREHAULT edited this page Sep 22, 2016 · 3 revisions

How to refresh search results automatically every time the user checks a criteria.

Let's assume we have built a basic database to post job descriptions. Our frmJob form contains the following fields:

  • job_title (text)
  • job_location (a selection list)
  • job_skills (a selection list)
  • job_description (text)

Let's make sure they are indexed so we can query the Plomino index on those fields.

Principle

To provide our search feature, we will not create a single Dynamic page form containing the criteria fields, a submit button and a computed field to display the results.

We need to split it in two different forms:

  • the search form (named 'dynamicSearch' in the sample db), containing the editable criteria fields,
  • the result form (named 'filtredResults' in the sample db), able to read the submitted criteria and to produce the results.

And, most importantly, we will add some JQuery code into the search form in order get the current values of the criteria, submit them to the result form, extract the produced results and insert them dynamically into the search form.

The result form

The result form contains only one field named 'results'. It is a computed for display rich text field.

Its formula reads the criteria values submitted in the request, performs the search and format the results as HTML:

db = context.getParentDatabase()

query = {'Form': 'frmJob'}

# read submitted criteria
any_criteria = False
job_location = context.REQUEST.get("job_location")
if job_location:
  any_criteria = True
  query['job_location']=job_location

job_skills = context.REQUEST.get("job_skills")
if job_skills:
  any_criteria = True
  query['job_skills']=job_skills

# perform the search
if any_criteria:
  search_results = db.getIndex().dbsearch(query)
else:
  return """Please select at least one criteria..."""
search_results_cnt = len(search_results)

# format the output
html = u''
html += """ %(found)d result(s) found...<br />""" % { 'found': search_results_cnt}
html += "<ul>"
for result in search_results:
  doc = result.getObject()
  html += """<li><a href="%(link)s">%(title)s</a> (%(location)s)
<p><span class="discreet">%(description)s</span></p>
<p>Skills: %(skills)s</p></li>
""" % {'link': doc.absolute_url_path(),
'title': doc.getItem('job_title'),
'description': doc.getItem('job_description'),
'location': doc.getRenderedItem('job_location'),
'skills': doc.getRenderedItem('job_skills'),
}
html += "</ul>"
return html

So if we call an url like this:

http://www.plomino.net/samples/jquery-example/filteredResults?job_location=Africa

we get the list of all jobs located in Africa.

But, actually, we are not interested in the entire Plone layout (navigation, portlets, etc.), and as we plan to load this page via an AJAX call just to extract the results list, we might prefer to load a smaller page.

An url like that will be more accurate:

http://www.plomino.net/samples/jquery-example/filteredResults/OpenBareForm?job_location=Africa

Note: direct access to /filteredResults makes an implicit call to /filteredResults/OpenForm, here we explicitly calls /filteredResults/OpenBareForm.

The search form

The search form contains editable fields for criterias (in the sample: job_skills and job_location).

It also contains a computed for display rich text field, named 'display_results' producing two elements:

an empty <div id="result_list"> tag which content will be loaded by a JQuery call, a <script> tag containing the javascript code.

This javascript code defines a function which serializes the form's inputs current values to produce the accurate query on /filteredResults/OpenBareForm (using JQuery.serialize()), then calls the resulting url, extracts the content, and inserts it in the target div tag (using JQuery.load()).

Then we bind the form's onChange event to this function. We also insert the spinner.gif image plomino into the target div, so the user knows the results are loading.

searchurl = context.getParentDatabase().absolute_url_path() +"/filteredResults/OpenBareForm?"
html="""
<script>
function get_results() {
    criteria = $('#plomino_form').serialize();
    $('#result_list').load("%s"+criteria+" #plomino_form");
}
$(document).ready(function() {
  $('#plomino_form input').change(function() {
  $('#result_list').html("<img src='spinner.gif' />");
  get_results();
  });

  get_results();
});
</script>
<div id="result_list"></div>
""" % searchurl

return html

The entire sample can be downloaded here so you can import into your own Plone site and play with it.