aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Cabo <david@calibea.com>2011-07-26 22:07:30 +0200
committerDavid Cabo <david@calibea.com>2011-07-26 22:07:30 +0200
commit9925d8f83864dc740d9b284a9e472d422dba12fb (patch)
treeb8116a4f12140912b76440211bc9674007f9286a
parent058a65ae0d079729b10a2954c472c336dce43245 (diff)
Adapting New Request flow to new wireframes: added type ahead search when creating new requests
-rw-r--r--app/controllers/request_controller.rb12
-rw-r--r--app/views/layouts/default.rhtml2
-rw-r--r--app/views/request/_search_ahead.rhtml13
-rw-r--r--app/views/request/new.rhtml94
-rw-r--r--config/routes.rb1
-rw-r--r--public/javascripts/ba-throttle-debounce.js9
-rw-r--r--spec/controllers/request_controller_spec.rb31
7 files changed, 111 insertions, 51 deletions
diff --git a/app/controllers/request_controller.rb b/app/controllers/request_controller.rb
index 472f18f6e..b6111b087 100644
--- a/app/controllers/request_controller.rb
+++ b/app/controllers/request_controller.rb
@@ -736,5 +736,17 @@ class RequestController < ApplicationController
return
end
end
+
+ # Type ahead search
+ def search_typeahead
+ # Since acts_as_xapian doesn't support the Partial match flag, we work around it
+ # by making the last work a wildcard, which is quite the same
+ query = params[:q] + '*'
+
+ query = query.split(' ').join(' OR ') # XXX: HACK for OR instead of default AND!
+ @xapian_requests = perform_search([InfoRequestEvent], query, 'relevant', 'request_collapse', 5)
+
+ render :partial => "request/search_ahead.rhtml"
+ end
end
diff --git a/app/views/layouts/default.rhtml b/app/views/layouts/default.rhtml
index 94ec5a956..a14dfcf8e 100644
--- a/app/views/layouts/default.rhtml
+++ b/app/views/layouts/default.rhtml
@@ -1,8 +1,8 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="<%= I18n.locale %>">
<head>
+ <script type="text/javascript" src="/javascripts/jquery.js"></script>
<% if @profile_photo_javascript %>
- <script type="text/javascript" src="/javascripts/jquery.js"></script>
<script type="text/javascript" src="/javascripts/jquery.Jcrop.js"></script>
<script type="text/javascript" src="/javascripts/profile_photo.js"></script>
<link rel="stylesheet" href="/stylesheets/jquery.Jcrop.css" type="text/css" >
diff --git a/app/views/request/_search_ahead.rhtml b/app/views/request/_search_ahead.rhtml
new file mode 100644
index 000000000..053b10146
--- /dev/null
+++ b/app/views/request/_search_ahead.rhtml
@@ -0,0 +1,13 @@
+<p>
+ <div id="request_search_ahead_results">
+ <% if @xapian_requests.results.size > 0 %>
+ <h3>Possibly related requests:</h3>
+ <% end %>
+ <% for result in @xapian_requests.results %>
+ <%= render :partial => 'request/request_listing_short_via_event', :locals => { :event => result[:model], :info_request => result[:model].info_request } %>
+ <% end %>
+ </div>
+</p>
+
+
+
diff --git a/app/views/request/new.rhtml b/app/views/request/new.rhtml
index a97116aa3..45014b5fc 100644
--- a/app/views/request/new.rhtml
+++ b/app/views/request/new.rhtml
@@ -1,3 +1,14 @@
+<script type="text/javascript" src="/javascripts/ba-throttle-debounce.js"></script>
+<script>
+ $(document).ready(function(){
+ // Avoid triggering too often (on each keystroke) by using the debounce jQuery plugin:
+ // http://benalman.com/projects/jquery-throttle-debounce-plugin/
+ $("#typeahead_search").keypress($.debounce( 300, function() {
+ $("#typeahead_response").load("<%=search_ahead_url%>?q="+encodeURI(this.value));
+ }));
+ });
+</script>
+
<% @title = _("Make an {{law_used_short}} request to '{{public_body_name}}'",:law_used_short=>h(@info_request.law_used_short),:public_body_name=>h(@info_request.public_body.name)) %>
<% if @existing_request %>
@@ -12,41 +23,45 @@
<%= foi_error_messages_for :info_request, :outgoing_message %>
-<div id="request_advice">
- <h1><%= _('Read this before writing your {{info_request_law_used_full}} request', :info_request_law_used_full=>h(@info_request.law_used_full)) %></h1>
- <ul>
- <li>
- <% form_tag("http://www.google.co.uk/search", {:id => "search_body_website_form", :method => "get"} ) do %>
- <p>
- <%= _('First,') %>
- <% if !@info_request.public_body.publication_scheme.empty? %>
- <%= _('<strong>browse</strong> the authority\'s <a href="%s">publication scheme</a> or <strong>search</strong> their web site ...') % [@info_request.public_body.publication_scheme] %>
- <% else %>
- <%= _('<strong>search</strong> the authority\'s web site ...') %>
- <% end %>
- <% if !@info_request.public_body.calculated_home_page.nil? %>
- <br>
- &nbsp; &nbsp; &nbsp; &nbsp; <%= text_field_tag 'q', params[:q], { :size => 20 } %>
- <%= hidden_field_tag 'as_sitesearch', @info_request.public_body.calculated_home_page %>
- <%= submit_tag _("Search") %>
- <% end %>
- <br>
- ... <%= _('to check that the info isn\'t already published.') %>
- </p>
- <% end %>
- </li>
+<h1><%= _('2. Ask for Information') %></h1>
+
+<% form_for(:info_request, @info_request, :html => { :id => 'write_form' } ) do |f| %>
- <li>
+<div id="request_header">
+ <p>
+ <label class="form_label" for="info_request_public_body_id"><%= _('To:') %></label>
+ <span id="to_public_body"><%=h(@info_request.public_body.name)%></span>
+ <div class="form_item_note">
<% if @info_request.public_body.info_requests.size > 0 %>
<%= _("Browse <a href='%s'>other requests</a> to '{{public_body_name}}' for examples of how to word your request.", :public_body_name=>h(@info_request.public_body.name)) % [public_body_url(@info_request.public_body)] %>
<% else %>
- <%= _('Browse <a href="%s">other requests</a> for examples of how to word your request.') % [request_list_url] %>
+ <%= _('Browse <a href="%s">other requests</a> for examples of how to word your request.') % [request_list_url] %>
<% end %>
- </li>
+ </div>
+ </p>
+ <p>
+ <label class="form_label" for="info_request_title"><%= _('Summary:') %></label>
+ <%= f.text_field :title, :size => 50, :id =>"typeahead_search" %>
+ </p>
+ <div class="form_item_note">
+ (<%= _('a one line summary of the information you are requesting,
+ e.g.') %>
+ <% if @info_request.law_used == 'eir' %>
+ <%= _("'Pollution levels over time for the River Tyne'") %>
+ <% else %>
+ <%= _("'Crime statistics by ward level for Wales'") %>
+ <% end %>
+ )
+ </div>
+ <div id="typeahead_response">
+ </div>
+</div>
+
+<div id="request_advice">
+ <ul>
<li><%= _('Write your request in <strong>simple, precise language</strong>.') %></li>
<li><%= _('Ask for <strong>specific</strong> documents or information, this site is not suitable for general enquiries.') %></li>
<li><%= _('Keep it <strong>focused</strong>, you\'ll be more likely to get what you want (<a href="%s">why?</a>).') % [help_requesting_path + '#focused'] %></li>
- <li><%= _('This site is <strong>public</strong>. Everything you type and any response will be published.') %></li>
</ul>
<% if @info_request.public_body.has_notes? %>
@@ -80,30 +95,9 @@
time</strong> or the time of the public authority by requesting unrelated information.') %></p>
<% end %>
</div>
-
-<% form_for(:info_request, @info_request, :html => { :id => 'write_form' } ) do |f| %>
- <div id="request_form">
- <h1>
- <label class="form_label" for="info_request_public_body_id"><%= _('To:') %></label>
- <span id="to_public_body"><%=h(@info_request.public_body.name)%></span>
- </h1>
-
- <p>
- <label class="form_label" for="info_request_title"><%= _('Summary:') %></label>
- <%= f.text_field :title, :size => 50 %>
- </p>
- <div class="form_item_note">
- (<%= _('a one line summary of the information you are requesting,
- e.g.') %>
- <% if @info_request.law_used == 'eir' %>
- <%= _("'Pollution levels over time for the River Tyne'") %>
- <% else %>
- <%= _("'Crime statistics by ward level for Wales'") %>
- <% end %>
- )
- </div>
-
+
+ <div id="request_form">
<% fields_for :outgoing_message do |o| %>
<p>
<label class="form_label" for="outgoing_message_body"><%= _('Your request:') %></label>
diff --git a/config/routes.rb b/config/routes.rb
index d9989a800..0747797d7 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -52,6 +52,7 @@ ActionController::Routing::Routes.draw do |map|
request.upload_response "/upload/request/:url_title", :action => 'upload_response'
+ request.search_ahead '/request_search_ahead', :action => 'search_typeahead'
end
# Use /profile for things to do with the currently signed in user.
diff --git a/public/javascripts/ba-throttle-debounce.js b/public/javascripts/ba-throttle-debounce.js
new file mode 100644
index 000000000..07205508e
--- /dev/null
+++ b/public/javascripts/ba-throttle-debounce.js
@@ -0,0 +1,9 @@
+/*
+ * jQuery throttle / debounce - v1.1 - 3/7/2010
+ * http://benalman.com/projects/jquery-throttle-debounce-plugin/
+ *
+ * Copyright (c) 2010 "Cowboy" Ben Alman
+ * Dual licensed under the MIT and GPL licenses.
+ * http://benalman.com/about/license/
+ */
+(function(b,c){var $=b.jQuery||b.Cowboy||(b.Cowboy={}),a;$.throttle=a=function(e,f,j,i){var h,d=0;if(typeof f!=="boolean"){i=j;j=f;f=c}function g(){var o=this,m=+new Date()-d,n=arguments;function l(){d=+new Date();j.apply(o,n)}function k(){h=c}if(i&&!h){l()}h&&clearTimeout(h);if(i===c&&m>e){l()}else{if(f!==true){h=setTimeout(i?k:l,i===c?e-m:e)}}}if($.guid){g.guid=j.guid=j.guid||$.guid++}return g};$.debounce=function(d,e,f){return f===c?a(d,e,false):a(d,f,e!==false)}})(this); \ No newline at end of file
diff --git a/spec/controllers/request_controller_spec.rb b/spec/controllers/request_controller_spec.rb
index 9d91bf8c2..e2febacd7 100644
--- a/spec/controllers/request_controller_spec.rb
+++ b/spec/controllers/request_controller_spec.rb
@@ -1250,5 +1250,36 @@ describe RequestController, "when showing JSON version for API" do
end
+describe RequestController, "when doing type ahead searches" do
+ fixtures :info_requests, :info_request_events, :public_bodies, :public_body_translations, :users, :incoming_messages, :raw_emails, :outgoing_messages, :comments
+
+ it "should return nothing for the empty query string" do
+ get :search_typeahead, :q => ""
+ response.should render_template('request/_search_ahead.rhtml')
+ assigns[:xapian_requests].results.size.should == 0
+ end
+
+ it "should return a request matching the given keyword, but not users with a matching description" do
+ get :search_typeahead, :q => "chicken"
+ response.should render_template('request/_search_ahead.rhtml')
+ assigns[:xapian_requests].results.size.should == 1
+ assigns[:xapian_requests].results[0][:model].title.should == info_requests(:naughty_chicken_request).title
+ end
+
+ it "should return all requests matching any of the given keywords" do
+ get :search_typeahead, :q => "money dog"
+ response.should render_template('request/_search_ahead.rhtml')
+ assigns[:xapian_requests].results.size.should == 2
+ assigns[:xapian_requests].results[0][:model].title.should == info_requests(:fancy_dog_request).title
+ assigns[:xapian_requests].results[1][:model].title.should == info_requests(:naughty_chicken_request).title
+ end
+
+ it "should return partial matches" do
+ get :search_typeahead, :q => "chick" # 'chick' for 'chicken'
+ response.should render_template('request/_search_ahead.rhtml')
+ assigns[:xapian_requests].results.size.should == 1
+ assigns[:xapian_requests].results[0][:model].title.should == info_requests(:naughty_chicken_request).title
+ end
+end