# Search Behavior

**URL:** <https://www.ruby-forum.com/t/search-behavior/62992>\
**Category:** Radiant CMS\
**Created:** [June 10, 2006, 6:07am UTC](https://www.ruby-forum.com/t/search-behavior/62992 "2006-06-10T06:07:44Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![ol1barn3s](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/o/9de053/32.png) [@ol1barn3s](https://www.ruby-forum.com/u/ol1barn3s)\
**Post date:** [June 10, 2006, 6:07am UTC](https://www.ruby-forum.com/t/search-behavior/62992/1 "2006-06-10T06:07:44Z")

</div>

Hi All:

For those of you who are missing search capability in Radiant, I created  
a  
simple “Search” behavior for pages. It lets you create a search page  
that  
receives keywords as parameters and lists pages that match those  
keywords.  
It also has live search capabilities. It is wrapped into a Rails plugin,  
so  
all you need to do is to dump the plugin it into the ‘vendor/plugins’  
directory of your Radiant installation and restart the instance.

The easiest way to get it is via Subversion:

$ cd vendor/plugins  
$ svn co [http://nobits.org/svn/rails/plugins/search\_behavior](http://nobits.org/svn/rails/plugins/search_behavior)

or unpack the tarball ([http://nobits.org/files/search\_behavior.tar.gz](http://nobits.org/files/search_behavior.tar.gz))  
into  
the same directory.

This time there are no unit tests yet.

You can find a demo at: [http://nobits.org/](http://nobits.org/)

Please let me know any comments or suggestions. Below follows the usage  
description, copied directly from the source.

Cheers,  
Oliver

Usage:

```
The "Search" behavior adds search capabilities to a Radiant site. A
page with this behavior responds to search queries that are passed 

```

to  
it through the request parameter “q”. Each space separated word in  
the  
query string is treated as a keyword. The search result includes  
all published pages whose titles or parts match (substring matching)  
all of the keywords specified in the query.

```
Using the "Search" behavior it is possible to provide standard
form-based search as well as "live" search using the prototype 

```

library.  
When the corresponding search page is called with its canonical URL,  
it  
is rendered similar to a normal page, i.e. with its entire layout.  
When, however, “/live” is appended to the URL the response is  
rendered  
from the “live” page part defined for the page without any layout.

```
To process search results the behavior provides the following tags:

  <r:search:results> [content] </r:search:results>

    Renders [content] only if the result set is not empty.

  <r:search:results:each> [content] </r:search:results:each>

    Renders [content] for every page in the result set. Within this 

```

tag  
default tags to access page attributes (i.e. \<r:url/\>,  
\<r:link/\>,  
r:title/\>, \<r:author/\>, etc.) are valid and defined for the  
currently processed page from the result set.

```
  <r:search:empty> [content] </r:search:empty>

    Render [content] only if the result set is empty
    (e.g. "No match").

  <r:search:query/>

    The original search query string.

Additionally the behavior provides a tag to generate a simple search
form, though its use is not required. Search forms can also be 

```

defined  
in normal HTML by the user:

```
  <r:search:form [label="Search term:"] [live="element-to-update]
                 [prototype="true"]/>

    Generates a simple search form that submits its content to the
    search page for which it was created. Additional attributes are
    optional:

      label:
        Defines an alternative label for the search field, the 

```

default  
is “Search:”.

```
      live:
        Enables the form observer for live search and specifies the 

```

ID  
of the HTML element that is updated with the results.

```
      prototype:
        If its value is "true" the Prototype JavaScript library 

```

shipped  
with Radiant is explicitly loaded, but only if the live  
search  
is enabled.

```
Example:

  Assume a page with slug "search" as a child of the root page. The
  "body" page part of this page may look like:

  <r:search:form />
  <hr />
  <r:search:empty>
    No match.
  </r:search:empty>
  <r:search:results>
    Results:
    <ul>
      <r:search:results:each>
        <li>
          <r:link/> by <r:author/>
        </li>
      </r:search:results:each>
    </ul>
  </r:search:results>

  To extend this example to allow a "live" search from the header
  snippet that is included into every page, (Typo style live 

```

search),  
two additional page parts are created for the search page:

```
  The "live" page part is only rendered when search results are
  returned from a "live" search request:

  <ul>
    <r:search:results:each>
      <li><r:link/></li>
    </r:search:results:each>
  </ul>

  The "form" page part is included into the header snippet, 

```

described  
below:

```
  <r:search:form live="search-results" prototype="true"
                 label="Live search:" />
  <div id="search-results"></div>

  Since, the header snippet itself is not always rendered in the
  context of a "Search" behavior the <r:search:form> tag is not 

```

always  
available. This prevents us from adding the form directly into the  
header snippet and requires the creation of the “form” page part  
for  
the search page. This page part can be easily included into the  
header snippet with the following lines:

```
  <r:find url="/search">
    <r:content part="form"/>
  </r:find>

  This finds the search page and renders its "form" page part in the
  context of the "Search" behavior.

  TODO:

    * escape query string for inclusion in response page
    * behavior based filter for search results

```

---

<div class="post-metadata">

**Author:** ![ol1barn3s](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/o/9de053/32.png) [@ol1barn3s](https://www.ruby-forum.com/u/ol1barn3s)\
**Post date:** [June 10, 2006, 7:50am UTC](https://www.ruby-forum.com/t/search-behavior/62992/2 "2006-06-10T07:50:34Z")

</div>

Very, very cool.

–  
John

---

<div class="post-metadata">

**Author:** ![ol1barn3s](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/o/9de053/32.png) [@ol1barn3s](https://www.ruby-forum.com/u/ol1barn3s)\
**Post date:** [June 10, 2006, 6:56pm UTC](https://www.ruby-forum.com/t/search-behavior/62992/3 "2006-06-10T18:56:27Z")

</div>

Hi Maurizio,

On 10-Jun-2006 18:40 +0200, Maurizio B. was heard to say:

> After I search for a term which is not found, the expected text  
> appears. But when I access again (reload) the page, the text within  
> the “\<r:search:empty\>” tag remains on the page while I’d expect it  
> should not. Maybe there is something I’m doing wrongly …

this is currently not taking care of. That is, the content of  
\<r:search:empty\> will also be evaluated when no query was submitted. I  
will  
fix this in the next few days and let you know.

> The request:
> 
> Could you also provide a tag which will show a snippet of the found  
> page (for example the first 5 rows or so)?

Yes, limiting the number of search results, certainly not a problem to  
implement.

Cheers,  
Oliver

---

<div class="post-metadata">

**Author:** ![ol1barn3s](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/o/9de053/32.png) [@ol1barn3s](https://www.ruby-forum.com/u/ol1barn3s)\
**Post date:** [June 10, 2006, 6:44pm UTC](https://www.ruby-forum.com/t/search-behavior/62992/4 "2006-06-10T18:44:03Z")

</div>

Hello Oliver. This is a great plugin! I’ve an issue and I’ve a request:

The issue:

If I’ve a page like this one:

```
 <r:search:form label="Immettete di seguito il testo da ricercare " 

```

/\>

* * *
  
\<r:search:empty\>  
Nessuna pagina trovata contenente il termine:  
“\<r:search:query/\>”.  
\</r:search:empty\>  
\<r:search:results\>  
Results:  

  
\<r:search:results:each\>  
-   
\<r:link/\> (by \<r:author/\>)  
  
\</r:search:results:each\>  

  
\</r:search:results\>

After I search for a term which is not found, the expected text  
appears. But when I access again (reload) the page, the text within  
the “\<r:search:empty\>” tag remains on the page while I’d expect it  
should not. Maybe there is something I’m doing wrongly …

The request:

Could you also provide a tag which will show a snippet of the found  
page (for example the first 5 rows or so)?

Best regards,

–M

---

<div class="post-metadata">

**Author:** ![ol1barn3s](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/o/9de053/32.png) [@ol1barn3s](https://www.ruby-forum.com/u/ol1barn3s)\
**Post date:** [July 12, 2006, 10:59pm UTC](https://www.ruby-forum.com/t/search-behavior/62992/5 "2006-07-12T22:59:30Z")

</div>

Hi Wolfgang,

I am happy the search behavior works well for you.

On 12-Jul-2006 22:21 +0200, Wolfgang Wopperer was heard to say:

> - An onComplete attribute for the search:form tag that is evaluated in  
> case live search is enabled. I replaced the radius tag with an HTML form  
> and the prototype observer and AJAX call. To this, I added the  
> onComplete attribute to call a JS function that controls the visibility  
> of my result list. This works perfectly, but it would surely be more  
> elegant if one could just use an attribute of your tag to reference a JS  
> function.

Do you mean, instead of having the onComplete attribute being hard-coded  
you would like to have the option to specify a custom function instead?

This certainly is possible and I will add this on a newer version of the  
behavior.

> - Excluding certain pages from search, e.g. virtual pages (404 pages) or  
> xml files (in my case, a Google sitemap). The most elegant solution  
> would be to make the exclusion list configurable, of course.

I planned some sort of filtering as well. Also such that the search page  
itself does not show up in the search.

I may be able to add those improvements in one of the next few days and  
let  
you know.

Cheers,  
Oliver

---

<div class="post-metadata">

**Author:** ![ol1barn3s](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/o/9de053/32.png) [@ol1barn3s](https://www.ruby-forum.com/u/ol1barn3s)\
**Post date:** [July 28, 2006, 6:14pm UTC](https://www.ruby-forum.com/t/search-behavior/62992/6 "2006-07-28T18:14:07Z")

</div>

Olivier: add me to the list of happy search\_behavior users 🙂

In regards to a previous issue:

On 12-Jul-06, at 4:58 PM | Jul 12, Oliver B. wrote:

> On 12-Jul-2006 22:21 +0200, Wolfgang Wopperer was heard to say:
> 
> > - Excluding certain pages from search, e.g. virtual pages (404  
> > pages) or  
> > xml files (in my case, a Google sitemap). The most elegant solution  
> > would be to make the exclusion list configurable, of course.
> 
> I planned some sort of filtering as well. Also such that the search  
> page  
> itself does not show up in the search.

What I just did with my implementation is change line 192 in  
search\_behavior.rb

from this…  
@query\_result = pages.delete\_if { |p| !p.published? }

to this:  
@query\_result = pages.delete\_if { |p| !p.published? ||  
p.parts.find\_by\_name(‘_unsearchable_’) }

Then I add a page part called ‘_unsearchable_’ to any pages I want  
excluded. Kind of ugly, but it works well.

James

---

<div class="post-metadata">

**Author:** ![ol1barn3s](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/o/9de053/32.png) [@ol1barn3s](https://www.ruby-forum.com/u/ol1barn3s)\
**Post date:** [July 12, 2006, 10:21pm UTC](https://www.ruby-forum.com/t/search-behavior/62992/7 "2006-07-12T22:21:01Z")

</div>

Thanks for a really great Radiant behavior! I got search up and running  
in a matter of minutes.

In the course of integrating it into our website, I came up with two  
possible extensions:

- An onComplete attribute for the search:form tag that is evaluated in  
case live search is enabled. I replaced the radius tag with an HTML form  
and the prototype observer and AJAX call. To this, I added the  
onComplete attribute to call a JS function that controls the visibility  
of my result list. This works perfectly, but it would surely be more  
elegant if one could just use an attribute of your tag to reference a JS  
function.

- Excluding certain pages from search, e.g. virtual pages (404 pages) or  
xml files (in my case, a Google sitemap). The most elegant solution  
would be to make the exclusion list configurable, of course.

I think these additions could be of use for many others, too.

Keep up the good work!

Wolfgang
