Permalink
Browse files

Ajaxified search form based on p.a.search and p.a.contentlisting.

  • Loading branch information...
1 parent b83ca47 commit cf0c6034a6d7b122219a493087342edc0208a772 @buchi buchi committed Mar 19, 2012
@@ -7,7 +7,7 @@
<browser:viewlet
name="plone.searchbox"
manager="plone.app.layout.viewlets.interfaces.IPortalHeader"
- class="collective.solr.browser.facets.SearchBox"
+ class="ftw.solr.browser.search.SearchBoxViewlet"
permission="zope2.View"
layer="ftw.solr.interfaces.IFtwSolrLayer"
/>
@@ -21,4 +21,30 @@
allowed_attributes="facet_parameters"
layer="ftw.solr.interfaces.IFtwSolrLayer" />
+ <browser:page
+ for="*"
+ name="search"
+ template="search.pt"
+ class=".search.SearchView"
+ permission="zope2.View"
+ layer="ftw.solr.interfaces.IFtwSolrLayer" />
+
+ <browser:page
+ name="search-results"
+ class=".search.SearchView"
+ permission="zope2.View"
+ for="Products.CMFCore.interfaces.IFolderish"
+ template="results.pt"
+ layer="ftw.solr.interfaces.IFtwSolrLayer" />
+
+ <browser:resource
+ name="search.js"
+ file="search.js"
+ layer="ftw.solr.interfaces.IFtwSolrLayer" />
+
+ <browser:resource
+ name="jquery.history.js"
+ file="jquery.history.js" />
+
+
</configure>

Large diffs are not rendered by default.

Oops, something went wrong.
View
@@ -0,0 +1,120 @@
+<div id="search-results-wrapper"
+ tal:define="b_start python:0;
+ b_start request/b_start | b_start;
+ b_size python:10;
+ batch python: view.results(b_size=b_size, b_start=b_start);
+ normalizeString nocall:context/@@plone/normalizeString;">
+
+ <h1 class="documentFirstHeading">
+ <span i18n:translate="heading_search_results">
+ Search results
+ </span>
+ <span class="discreet">
+ &mdash;
+ <span i18n:translate="batch_x_items_matching_your_criteria"
+ ><span i18n:name="number"
+ tal:omit-tag=""
+ tal:content="batch/sequence_length|string:0">234</span> items matching your search terms</span>
+ </h1>
+
+ <metal:searchfacets define-macro="search_facets">
+ <div tal:define="facets nocall: context/@@search-facets | nothing"
+ tal:condition="python: batch and facets"
+ tal:replace="structure python: facets(results=view.solr_response)" />
+ </metal:searchfacets>
+
+ <metal:searchresults define-macro="search_results">
+ <div id="search-results">
+
+ <metal:noresults tal:condition="not: batch">
+ <p i18n:domain="plone"><strong i18n:translate="description_no_results_found">No results were found.</strong></p>
+ </metal:noresults>
+
+ <metal:results tal:condition="batch"
+ tal:define="isAnon context/@@plone_portal_state/anonymous;
+ toLocalizedTime nocall: context/@@plone/toLocalizedTime;
+ site_properties context/portal_properties/site_properties;
+ allowAnonymousViewAbout site_properties/allowAnonymousViewAbout;
+ show_about python:not isAnon or allowAnonymousViewAbout;">
+ <dl class="searchResults">
+ <tal:results repeat="item batch">
+ <dt tal:attributes="class item/ContentTypeClass">
+ <img tal:replace="structure item/getIcon" />
+ <a href="#"
+ tal:attributes="href item/getURL;
+ class string:state-${item/review_state}"
+ tal:content="item/Title" />
+ </dt>
+ <dd>
+ <span class="discreet" i18n:domain="plone"
+ tal:condition="show_about">
+ <span class="documentAuthor"
+ i18n:translate="label_by_author">
+ by
+ <tal:block tal:condition="item/Creator"
+ tal:define="author python:context.portal_membership.getMemberInfo(item.Creator())">
+ <a href="#"
+ tal:attributes="href string:${context/@@plone_portal_state/navigation_root_url}/author/${item/Creator}"
+ tal:content="python:author and author['fullname'] or item.Creator()"
+ tal:omit-tag="not:item/Creator"
+ i18n:name="author">
+ Bob Dobalina
+ </a>
+ </tal:block>
+ </span>
+
+ <span tal:define="modification_date item/ModificationDate">
+
+ <span class="documentModified">
+ &mdash;
+ <span i18n:translate="box_last_modified">
+ last modified
+ </span>
+ <span tal:replace="python:toLocalizedTime(modification_date, long_format=1)">
+ August 16, 2001 at 23:35:59
+ </span>
+ </span>
+
+ </span>
+
+ </span>
+ <div tal:content="item/CroppedDescription">
+ Cropped description
+ </div>
+
+ <cite class="documentLocation link-location"
+ tal:define="breadcrumbs python: view.breadcrumbs(item);
+ is_rtl context/@@plone_portal_state/is_rtl;"
+ tal:condition='breadcrumbs'>
+ <span i18n:translate="text_searchitem_location">
+ Located in
+ </span>
+ <span tal:repeat="crumb breadcrumbs"
+ tal:attributes="dir python:is_rtl and 'rtl' or 'ltr';">
+ <tal:item tal:define="is_last repeat/crumb/end;
+ url crumb/absolute_url;
+ title crumb/Title">
+ <a href="#"
+ tal:omit-tag="not: url"
+ tal:attributes="href url"
+ tal:content="title">
+ crumb
+ </a>
+ <span class="breadcrumbSeparator" tal:condition="not: is_last">
+ <tal:ltr condition="not: is_rtl">&rsaquo;</tal:ltr>
+ <tal:rtl condition="is_rtl">&lsaquo;</tal:rtl>
+ </span>
+ </tal:item>
+ </span>
+
+ </cite>
+
+ </dd>
+ </tal:results>
+ </dl>
+ <div metal:use-macro="context/batch_macros/macros/navigation" />
+ </metal:results>
+ </div>
+ </metal:searchresults>
+
+</div>
View
@@ -0,0 +1,54 @@
+jQuery(function ($) {
+
+ var History = window.History;
+
+ History.Adapter.bind(window, 'statechange', function() {
+ var State = History.getState();
+ var qs = State.url.replace(/^.*\?/, '');
+ var results_container = $('#search-results-wrapper');
+ $.get('@@search-results', qs, function(data) {
+ results_container.hide();
+ results_container.html(data);
+ results_container.fadeIn(200);
+ });
+ });
+
+ // Returns query string values from a querystring.
+ // function qs_values(qs) {
+ // var a = qs.split('&');
+ // if (a === "") return {};
+ // var b = {};
+ // for (var i = 0; i < a.length; ++i)
+ // {
+ // var p=a[i].split('=');
+ // if (!b[p[0]]) {
+ // b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
+ // } else {
+ // if (typeof(b[p[0]])=='string') {
+ // b[p[0]] = [b[p[0]]];
+ // }
+ // b[p[0]].push(decodeURIComponent(p[1].replace(/\+/g, " ")));
+ // }
+ // }
+ // return b;
+ // }
+
+ // We need to update the site-wide search field (at the top right in
+ // stock Plone) when the main search field is updated
+ $('#search-field input[name="SearchableText"]').keyup(function () {
+ $('input#searchGadget').val($(this).val());
+ });
+
+
+ $('form.searchPage').submit(function (e) {
+ var url = '@@search?' + $(this).serialize();
+ History.pushState(null, null, url);
+ e.preventDefault();
+ });
+
+ $('#portal-searchfacets a, #search-results .listingBar a').live('click', function (e) {
+ History.pushState(null, null, jq(this).attr('href'));
+ e.preventDefault();
+ });
+
+});
View
@@ -0,0 +1,68 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
+ xmlns:tal="http://xml.zope.org/namespaces/tal"
+ xmlns:metal="http://xml.zope.org/namespaces/metal"
+ xmlns:i18n="http://xml.zope.org/namespaces/i18n"
+ lang="en"
+ metal:use-macro="context/main_template/macros/master"
+ i18n:domain="plone">
+
+<head>
+ <metal:block metal:fill-slot="head_slot">
+
+ <link rel="alternate" title="RSS 1.0" type="application/rss+xml"
+ tal:define="here_url context/@@plone_context_state/object_url;"
+ tal:condition="request/SearchableText|nothing"
+ tal:attributes="href string:$here_url/search_rss?${request/QUERY_STRING}"/>
+
+ </metal:block>
+
+ <metal:block fill-slot="top_slot"
+ tal:define="dummy python:request.set('disable_border',1);
+ disable_column_one python:request.set('disable_plone.leftcolumn',1);
+ disable_column_two python:request.set('disable_plone.rightcolumn',1);" />
+</head>
+
+<body>
+
+ <div id="content-core" metal:fill-slot="main">
+
+ <form name="searchform"
+ action="@@search"
+ class="searchPage enableAutoFocus"
+ tal:define="portal context/@@plone_portal_state/portal;
+ first_call not:request/advanced_search|nothing;
+ st python:request.get('SearchableText', '');
+ DateTime python:modules['DateTime'].DateTime;">
+
+ <input type="hidden" name="advanced_search" value="False" />
+ <input type="hidden" name="sort_on" value="" />
+
+ <fieldset id="search-field" i18n:domain="plone" class="noborder">
+ <input class="searchPage"
+ name="SearchableText"
+ type="text"
+ size="25"
+ title="Search Site"
+ i18n:attributes="title title_search_title;"
+ tal:attributes="value st;"
+ />
+ <input class="searchPage searchButton allowMultiSubmit"
+ type="submit"
+ value="Search"
+ i18n:attributes="value label_search;"/>
+
+ <div tal:define="view nocall: context/@@search-facets | nothing"
+ tal:condition="python: view"
+ tal:replace="structure view/hiddenfields" />
+
+ </fieldset>
+
+ <tal:results tal:replace="structure context/@@search-results" />
+
+ <div class="visualClear"><!-- --></div>
+ </form>
+
+ </div>
+
+</body>
+</html>
View
@@ -0,0 +1,50 @@
+from logging import getLogger
+from plone.app.search import browser
+from plone.app.contentlisting.interfaces import IContentListing
+from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
+from Products.CMFCore.utils import getToolByName
+from Products.CMFPlone.PloneBatch import Batch
+from Products.ZCTextIndex.ParseTree import ParseError
+from plone.app.layout.viewlets import common
+from collective.solr.solr import SolrException
+from collective.solr.browser.facets import FacetMixin
+
+logger = getLogger('ftw.solr')
+
+
+class SearchView(browser.Search):
+
+ def results(self, query=None, batch=True, b_size=10, b_start=0):
+ """Get properly wrapped search results from the catalog.
+ 'query' should be a dictionary of catalog parameters.
+ """
+ if query is None:
+ query = {}
+
+ query['b_start'] = b_start = int(b_start)
+ query['b_size'] = b_size
+ query = self.filter_query(query)
+
+ if query is None:
+ results = []
+ else:
+ query.update({'qt': 'hlsearch'});
+ catalog = getToolByName(self.context, 'portal_catalog')
+ try:
+ results = catalog(**query)
+ except ParseError:
+ logger.exception('Exception while searching')
+ return []
+ except SolrException:
+ logger.exception('Exception while searching')
+ return []
+
+ self.solr_response = results
+ results = IContentListing(results)
+ if batch:
+ results = Batch(results, b_size, b_start)
+ return results
+
+class SearchBoxViewlet(common.SearchBoxViewlet, FacetMixin):
+
+ index = ViewPageTemplateFile('searchbox.pt')
@@ -0,0 +1,48 @@
+<div id="portal-searchbox"
+ i18n:domain="plone">
+ <form name="searchform"
+ action="@@search"
+ tal:attributes="action string:${view/site_url}/@@search">
+
+ <label for="searchGadget" class="hiddenStructure"
+ i18n:translate="text_search">Search Site</label>
+
+ <div class="LSBox">
+ <input name="SearchableText"
+ type="text"
+ size="18"
+ value=""
+ title="Search Site"
+ accesskey="4"
+ i18n:attributes="title title_search_site;"
+ tal:attributes="value request/SearchableText|nothing;
+ id view/search_input_id"
+ class="inputLabel" />
+
+ <input class="searchButton"
+ type="submit"
+ value="Search"
+ i18n:attributes="value label_search;" />
+
+ <div class="searchSection">
+ <input id="searchbox_currentfolder_only"
+ class="noborder"
+ type="checkbox"
+ name="path"
+ tal:attributes="value view/folder_path"
+ />
+ <label for="searchbox_currentfolder_only"
+ i18n:translate="label_searchbox_currentfolder_only"
+ style="cursor: pointer">
+ only in current section
+ </label>
+ </div>
+
+ <div class="LSResult" id="LSResult" style=""><div class="LSShadow" id="LSShadow"></div></div>
+ </div>
+
+ <div tal:replace="structure view/hiddenfields" />
+
+ </form>
+
+</div>
Oops, something went wrong.

0 comments on commit cf0c603

Please sign in to comment.