Skip to content

Commit 49e53f4

Browse files
author
Jessie Keck
committed
Merge pull request #809 from projectblacklight/track_click
Change the click tracking route to be CatalogController#track.
2 parents fb76145 + 2875905 commit 49e53f4

File tree

10 files changed

+157
-51
lines changed

10 files changed

+157
-51
lines changed
Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,42 @@
11
//= require blacklight/core
22
(function($) {
33
Blacklight.do_search_context_behavior = function() {
4-
$('a[data-counter]').click(function(event) {
5-
var f = document.createElement('form'); f.style.display = 'none';
6-
this.parentNode.appendChild(f);
7-
f.method = 'POST';
8-
f.action = $(this).attr('href');
9-
if(event.metaKey || event.ctrlKey){f.target = '_blank';};
10-
var d = document.createElement('input'); d.setAttribute('type', 'hidden');
11-
d.setAttribute('name', 'counter'); d.setAttribute('value', $(this).data('counter')); f.appendChild(d);
12-
var id = document.createElement('input'); id.setAttribute('type', 'hidden');
13-
id.setAttribute('name', 'search_id'); id.setAttribute('value', $(this).data('search_id')); f.appendChild(id);
14-
var m = document.createElement('input'); m.setAttribute('type', 'hidden');
15-
m.setAttribute('name', '_method'); m.setAttribute('value', 'put'); f.appendChild(m);
16-
var m = document.createElement('input'); m.setAttribute('type', 'hidden');
17-
m.setAttribute('name', $('meta[name="csrf-param"]').attr('content')); m.setAttribute('value', $('meta[name="csrf-token"]').attr('content')); f.appendChild(m);
18-
19-
f.submit();
20-
21-
return false;
22-
});
23-
24-
};
25-
Blacklight.onLoad(function() {
26-
Blacklight.do_search_context_behavior();
27-
});
4+
$('a[data-context-href]').on('click.search-context', Blacklight.handleSearchContextMethod);
5+
};
6+
7+
// this is the $.rails.handleMethod with a couple adjustments, described inline:
8+
// first, we're attaching this directly to the event handler, so we can check for meta-keys
9+
Blacklight.handleSearchContextMethod = function(event) {
10+
var link = $(this);
11+
12+
// instead of using the normal href, we need to use the context href instead
13+
var href = link.data('context-href'),
14+
method = 'post',
15+
target = link.attr('target'),
16+
csrfToken = $('meta[name=csrf-token]').attr('content'),
17+
csrfParam = $('meta[name=csrf-param]').attr('content'),
18+
form = $('<form method="post" action="' + href + '"></form>'),
19+
metadataInput = '<input name="_method" value="' + method + '" type="hidden" />',
20+
redirectHref = '<input name="redirect" value="' + link.attr('href') + '" type="hidden" />';
21+
22+
// check for meta keys.. if set, we should open in a new tab
23+
if(event.metaKey || event.ctrlKey) {
24+
target = '_blank';
25+
}
26+
27+
if (csrfParam !== undefined && csrfToken !== undefined) {
28+
metadataInput += '<input name="' + csrfParam + '" value="' + csrfToken + '" type="hidden" />';
29+
}
30+
31+
if (target) { form.attr('target', target); }
32+
33+
form.hide().append(metadataInput).append(redirectHref).appendTo('body');
34+
form.submit();
35+
36+
return false;
37+
};
38+
39+
Blacklight.onLoad(function() {
40+
Blacklight.do_search_context_behavior();
41+
});
2842
})(jQuery);

app/helpers/blacklight/url_helper_behavior.rb

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
1+
require 'deprecation'
12
module Blacklight::UrlHelperBehavior
3+
extend Deprecation
4+
self.deprecation_horizon = 'blacklight 6.0'
25

36
##
47
# Extension point for downstream applications
5-
# to provide more interesting routing to
8+
# to provide more interesting routing to
69
# documents
710
def url_for_document doc
8-
doc
11+
if controller.is_a? Blacklight::Catalog and doc.is_a? SolrDocument and
12+
(!doc.respond_to?(:to_model) or doc.to_model.is_a? SolrDocument)
13+
{ controller: controller_name, action: :show, id: doc }
14+
else
15+
doc
16+
end
917
end
1018

1119
# link_to_document(doc, :label=>'VIEW', :counter => 3)
@@ -15,30 +23,55 @@ def url_for_document doc
1523
def link_to_document(doc, opts={:label=>nil, :counter => nil})
1624
opts[:label] ||= document_show_link_field(doc)
1725
label = render_document_index_label doc, opts
18-
link_to label, url_for_document(doc), search_session_params(opts[:counter]).merge(opts.reject { |k,v| [:label, :counter].include? k })
26+
link_to label, url_for_document(doc), document_link_params(doc, opts)
1927
end
2028

29+
def document_link_params(doc, opts)
30+
session_tracking_params(doc, opts[:counter]).merge(opts.reject { |k,v| [:label, :counter].include? k })
31+
end
32+
protected :document_link_params
33+
2134
##
2235
# Link to the previous document in the current search context
2336
def link_to_previous_document(previous_document)
24-
link_to_unless previous_document.nil?, raw(t('views.pagination.previous')), url_for_document(previous_document), search_session_params(search_session['counter'].to_i - 1).merge(:class => "previous", :rel => 'prev') do
37+
link_opts = session_tracking_params(previous_document, search_session['counter'].to_i - 1).merge(:class => "previous", :rel => 'prev')
38+
link_to_unless previous_document.nil?, raw(t('views.pagination.previous')), url_for_document(previous_document), link_opts do
2539
content_tag :span, raw(t('views.pagination.previous')), :class => 'previous'
2640
end
2741
end
2842

2943
##
3044
# Link to the next document in the current search context
3145
def link_to_next_document(next_document)
32-
link_to_unless next_document.nil?, raw(t('views.pagination.next')), url_for_document(next_document), search_session_params(search_session['counter'].to_i + 1).merge(:class => "next", :rel => 'next') do
46+
link_opts = session_tracking_params(next_document, search_session['counter'].to_i + 1).merge(:class => "next", :rel => 'next')
47+
link_to_unless next_document.nil?, raw(t('views.pagination.next')), url_for_document(next_document), link_opts do
3348
content_tag :span, raw(t('views.pagination.next')), :class => 'next'
3449
end
3550
end
3651

3752
##
3853
# Current search context parameters
39-
def search_session_params counter
54+
def search_session_params counter
4055
{ :'data-counter' => counter, :'data-search_id' => current_search_session.try(:id) }
4156
end
57+
deprecation_deprecate :search_session_params
58+
59+
##
60+
# Attributes for a link that gives a URL we can use to track clicks for the current search session
61+
# @param [SolrDocument] document
62+
# @param [Integer] counter
63+
# @example
64+
# session_tracking_params(SolrDocument.new(id: 123), 7)
65+
# => { data: { :'tracker-href' => '/catalog/123/track?counter=7&search_id=999' } }
66+
def session_tracking_params document, counter
67+
if document.nil?
68+
return {}
69+
end
70+
71+
{ :data => {:'context-href' => track_solr_document_path(document, counter: counter, search_id: current_search_session.try(:id))}}
72+
end
73+
protected :session_tracking_params
74+
4275

4376
#
4477
# link based helpers ->

lib/blacklight/catalog.rb

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,16 @@ def show
5757
end
5858

5959
# updates the search counter (allows the show view to paginate)
60-
def update
60+
def track
6161
search_session['counter'] = params[:counter]
62-
redirect_to :action => "show", :status => 303
62+
path = if params[:redirect] and (params[:redirect].starts_with?("/") or params[:redirect] =~ URI::regexp)
63+
URI.parse(params[:redirect]).path
64+
else
65+
{ action: 'show' }
66+
end
67+
redirect_to path, :status => 303
6368
end
64-
69+
6570
# displays values and pagination links for a single facet field
6671
def facet
6772
@facet = blacklight_config.facet_fields[params[:id]]

lib/blacklight/catalog/search_context.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ def blacklisted_search_session_params
9494
def setup_next_and_previous_documents
9595
if search_session['counter'] and current_search_session
9696
index = search_session['counter'].to_i - 1
97-
response, documents = get_previous_and_next_documents_for_search index, current_search_session.query_params
97+
response, documents = get_previous_and_next_documents_for_search index, current_search_session.query_params.with_indifferent_access
9898

9999
search_session['total'] = response.total
100100
@search_context_response = response

lib/blacklight/routes.rb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,14 @@ def export(primary_resource)
108108
def solr_document(primary_resource)
109109
add_routes do |options|
110110

111-
args = {only: [:show, :update]}
111+
args = {only: [:show]}
112112
args[:constraints] = options[:constraints] if options[:constraints]
113113

114-
resources :solr_document, args.merge(path: primary_resource, controller: primary_resource)
114+
resources :solr_document, args.merge(path: primary_resource, controller: primary_resource) do
115+
member do
116+
post "track"
117+
end
118+
end
115119

116120
# :show and :update are for backwards-compatibility with catalog_url named routes
117121
resources primary_resource, args

spec/controllers/catalog_controller_spec.rb

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -195,23 +195,33 @@ def assigns_response
195195

196196
end # describe index action
197197

198-
describe "update action" do
198+
describe "track action" do
199199
doc_id = '2007020969'
200200

201201
it "should set counter value into session[:search]" do
202-
put :update, :id => doc_id, :counter => 3
202+
put :track, :id => doc_id, :counter => 3
203203
expect(session[:search]['counter']).to eq "3"
204204
end
205205

206206
it "should redirect to show action for doc id" do
207-
put :update, :id => doc_id, :counter => 3
207+
put :track, :id => doc_id, :counter => 3
208208
assert_redirected_to(catalog_path(doc_id))
209209
end
210210

211211
it "HTTP status code for redirect should be 303" do
212-
put :update, :id => doc_id, :counter => 3
212+
put :track, :id => doc_id, :counter => 3
213213
expect(response.status).to eq 303
214214
end
215+
216+
it "should redirect to the path given in the redirect param" do
217+
put :track, :id => doc_id, :counter => 3, redirect: '/xyz'
218+
assert_redirected_to("/xyz")
219+
end
220+
221+
it "should redirect to the path of the uri given in the redirect param" do
222+
put :track, :id => doc_id, :counter => 3, redirect: 'http://localhost:3000/xyz'
223+
assert_redirected_to("/xyz")
224+
end
215225
end
216226

217227
# SHOW ACTION

spec/features/alternate_controller_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
fill_in "q", :with=>"history"
3030
click_button 'search'
3131
expect(page).to have_selector ".document-thumbnail"
32-
expect(page).to have_selector ".document-thumbnail a[data-counter]"
32+
expect(page).to have_selector ".document-thumbnail a[data-context-href]"
3333
expect(page).to have_selector ".document-thumbnail a img"
3434

3535
end

spec/features/search_results_spec.rb

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,19 @@
5555
click_on 'Pluvial nectar of blessings'
5656
expect(page).to have_content "« Previous | 10 of 30 | Next »"
5757
prev = page.find("#previousNextDocument .previous")
58-
expect(prev['data-counter']).to eq "9"
59-
expect(prev['data-search_id']).to eq search_id
58+
expect(prev['data-context-href']).to eq "/catalog/2003546302/track?counter=9&search_id=#{search_id}"
6059

6160
click_on "« Previous"
6261

6362
prev = page.find("#previousNextDocument .previous")
64-
expect(prev['data-counter']).to eq "8"
65-
expect(prev['data-search_id']).to eq search_id
63+
expect(prev['data-context-href']).to eq "/catalog/2004310986/track?counter=8&search_id=#{search_id}"
64+
end
65+
66+
it "should redirect context urls to the original url", :js => true do
67+
search_for ''
68+
first('.index_title a').click
69+
expect(page).to have_content "« Previous | 1 of 30 | Next »"
70+
expect(page.current_url).to_not have_content "/track"
6671
end
6772

6873
end

spec/helpers/url_helper_spec.rb

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,41 @@
1818
helper.stub(current_search_session: nil)
1919
end
2020

21+
describe "url_for_document" do
22+
let(:controller_class) { ::CatalogController.new }
23+
24+
before do
25+
helper.stub(controller: controller_class)
26+
helper.stub(controller_name: controller_class.controller_name)
27+
end
28+
29+
it "should be a polymorphic routing-ready object" do
30+
doc = double
31+
expect(helper.url_for_document(doc)).to eq doc
32+
end
33+
34+
it "should be a catalog controller-specific route" do
35+
doc = SolrDocument.new
36+
expect(helper.url_for_document(doc)).to eq({controller: 'catalog', action: :show, id: doc})
37+
end
38+
39+
context "within an alternative catalog controller" do
40+
let(:controller_class) { ::AlternateController.new }
41+
42+
it "should be a catalog controller-specific route" do
43+
doc = SolrDocument.new
44+
expect(helper.url_for_document(doc)).to eq({controller: 'alternate', action: :show, id: doc})
45+
end
46+
end
47+
48+
it "should be a polymorphic route if the solr document responds to #to_model with a non-SolrDocument" do
49+
some_model = double
50+
doc = SolrDocument.new
51+
doc.stub(to_model: some_model)
52+
expect(helper.url_for_document(doc)).to eq doc
53+
end
54+
end
55+
2156
describe "link_back_to_catalog" do
2257
let(:query_params) {{:q => "query", :f => "facets", :per_page => "10", :page => "2", :controller=>'catalog'}}
2358
let(:bookmarks_query_params) {{ :page => "2", :controller=>'bookmarks'}}
@@ -210,7 +245,7 @@
210245
it "should convert the counter parameter into a data- attribute" do
211246
data = {'id'=>'123456','title_display'=>['654321']}
212247
@document = SolrDocument.new(data)
213-
expect(helper.link_to_document(@document, { :label => :title_display, :counter => 5 })).to match /data-counter="5"/
248+
expect(helper.link_to_document(@document, { :label => :title_display, :counter => 5 })).to match /\/catalog\/123456\/track\?counter=5/
214249
end
215250

216251
it "passes on the title attribute to the link_to_with_data method" do
@@ -352,4 +387,4 @@
352387
expect(added_facet_params_from_facet_action).to eq added_facet_params.except(Blacklight::Solr::FacetPaginator.request_keys[:page], Blacklight::Solr::FacetPaginator.request_keys[:sort])
353388
end
354389
end
355-
end
390+
end

spec/lib/blacklight/routes_spec.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@
77
describe "without constraints" do
88
let(:options) { Hash.new }
99
it "should define the resources" do
10-
router.should_receive(:resources).with(:solr_document, {:path=>:records, :controller=>:records, :only=>[:show, :update]})
11-
router.should_receive(:resources).with(:records, :only=>[:show, :update])
10+
router.should_receive(:resources).with(:solr_document, {:path=>:records, :controller=>:records, :only=>[:show]})
11+
router.should_receive(:resources).with(:records, :only=>[:show])
1212
subject.solr_document(:records)
1313
end
1414
end
1515

1616
describe "with constraints" do
1717
let(:options) { { :constraints => {id: /[a-z]+/, format: false } } }
1818
it "should define the resources" do
19-
router.should_receive(:resources).with(:solr_document, {:path=>:records, :controller=>:records, :only=>[:show, :update], :constraints=>{:id=>/[a-z]+/, :format=>false} })
20-
router.should_receive(:resources).with(:records, :only=>[:show, :update], :constraints=>{:id=>/[a-z]+/, :format=>false})
19+
router.should_receive(:resources).with(:solr_document, {:path=>:records, :controller=>:records, :only=>[:show], :constraints=>{:id=>/[a-z]+/, :format=>false} })
20+
router.should_receive(:resources).with(:records, :only=>[:show], :constraints=>{:id=>/[a-z]+/, :format=>false})
2121
subject.solr_document(:records)
2222
end
2323
end

0 commit comments

Comments
 (0)