Forum: Radiant CMS Search Behavior

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Oliver B. (Guest)
on 2006-06-10 08:07
(Received via mailing list)
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

or unpack the tarball (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/

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
John W. Long (Guest)
on 2006-06-10 09:50
(Received via mailing list)
Very, very cool.

--
John
Maurizio B. (Guest)
on 2006-06-10 20:44
(Received via mailing list)
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 "
/>
     <hr />
     <r:search:empty>
       Nessuna pagina trovata contenente il termine:
"<r:search:query/>".
     </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>

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
Oliver B. (Guest)
on 2006-06-10 20:56
(Received via mailing list)
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
Wolfgang Wopperer (Guest)
on 2006-07-13 00:21
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
Oliver B. (Guest)
on 2006-07-13 00:59
(Received via mailing list)
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
James MacAulay (Guest)
on 2006-07-28 20:14
(Received via mailing list)
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
This topic is locked and can not be replied to.