diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java index 7889a825a..b74979164 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java @@ -70,6 +70,7 @@ public class PagedSearchController extends FreemarkerHttpServlet { protected static final int DEFAULT_MAX_HIT_COUNT = 1000; private static final String PARAM_XML_REQUEST = "xml"; + private static final String PARAM_CSV_REQUEST = "csv"; private static final String PARAM_START_INDEX = "startIndex"; private static final String PARAM_HITS_PER_PAGE = "hitsPerPage"; private static final String PARAM_CLASSGROUP = "classgroup"; @@ -79,7 +80,7 @@ public class PagedSearchController extends FreemarkerHttpServlet { protected static final Map> templateTable; protected enum Format { - HTML, XML; + HTML, XML, CSV; } protected enum Result { @@ -101,14 +102,27 @@ public class PagedSearchController extends FreemarkerHttpServlet { throws IOException, ServletException { VitroRequest vreq = new VitroRequest(request); boolean wasXmlRequested = isRequestedFormatXml(vreq); - if( ! wasXmlRequested ){ + boolean wasCSVRequested = isRequestedFormatCSV(vreq); + if( !wasXmlRequested && !wasCSVRequested){ super.doGet(vreq,response); - }else{ + }else if (wasXmlRequested){ try { ResponseValues rvalues = processRequest(vreq); response.setCharacterEncoding("UTF-8"); response.setContentType("text/xml;charset=UTF-8"); + response.setHeader("Content-Disposition", "attachment; filename=search.xml"); + writeTemplate(rvalues.getTemplateName(), rvalues.getMap(), request, response); + } catch (Exception e) { + log.error(e, e); + } + }else if (wasCSVRequested){ + try { + ResponseValues rvalues = processRequest(vreq); + + response.setCharacterEncoding("UTF-8"); + response.setContentType("text/csv;charset=UTF-8"); + response.setHeader("Content-Disposition", "attachment; filename=search.csv"); writeTemplate(rvalues.getTemplateName(), rvalues.getMap(), request, response); } catch (Exception e) { log.error(e, e); @@ -122,8 +136,9 @@ public class PagedSearchController extends FreemarkerHttpServlet { //There may be other non-html formats in the future Format format = getFormat(vreq); boolean wasXmlRequested = Format.XML == format; + boolean wasCSVRequested = Format.CSV == format; log.debug("Requested format was " + (wasXmlRequested ? "xml" : "html")); - boolean wasHtmlRequested = ! wasXmlRequested; + boolean wasHtmlRequested = ! (wasXmlRequested || wasCSVRequested); try { @@ -672,10 +687,25 @@ public class PagedSearchController extends FreemarkerHttpServlet { return false; } } + + protected boolean isRequestedFormatCSV(VitroRequest req){ + if( req != null ){ + String param = req.getParameter(PARAM_CSV_REQUEST); + if( param != null && "1".equals(param)){ + return true; + }else{ + return false; + } + }else{ + return false; + } + } protected Format getFormat(VitroRequest req){ if( req != null && req.getParameter("xml") != null && "1".equals(req.getParameter("xml"))) return Format.XML; + else if ( req != null && req.getParameter("csv") != null && "1".equals(req.getParameter("csv"))) + return Format.CSV; else return Format.HTML; } @@ -705,9 +735,20 @@ public class PagedSearchController extends FreemarkerHttpServlet { resultsToTemplates = new HashMap(); resultsToTemplates.put(Result.PAGED, "search-xmlResults.ftl"); resultsToTemplates.put(Result.ERROR, "search-xmlError.ftl"); + // resultsToTemplates.put(Result.BAD_QUERY, "search-xmlBadQuery.ftl"); templateTable.put(Format.XML, Collections.unmodifiableMap(resultsToTemplates)); + + // set up CSV format + resultsToTemplates = new HashMap(); + resultsToTemplates.put(Result.PAGED, "search-csvResults.ftl"); + resultsToTemplates.put(Result.ERROR, "search-csvError.ftl"); + + // resultsToTemplates.put(Result.BAD_QUERY, "search-xmlBadQuery.ftl"); + templateTable.put(Format.CSV, Collections.unmodifiableMap(resultsToTemplates)); + + return Collections.unmodifiableMap(templateTable); } } diff --git a/webapp/web/css/search.css b/webapp/web/css/search.css index 35b6857eb..b3717888a 100644 --- a/webapp/web/css/search.css +++ b/webapp/web/css/search.css @@ -79,7 +79,22 @@ ul.searchTips li { } span#searchHelp { float:right; - margin-top:-45px; + margin-top:10px; font-size:.825em; padding-right:32px +} + +span#downloadResults { + float:left; + margin-top:10px; + font-size:.825em; + padding-left:10px +} + +img#downloadIcon { + cursor: pointer; +} + +.download-url { + padding: 5px 25px 5px; } \ No newline at end of file diff --git a/webapp/web/css/vitro.css b/webapp/web/css/vitro.css index 54e42a6c3..c2001d95b 100644 --- a/webapp/web/css/vitro.css +++ b/webapp/web/css/vitro.css @@ -133,10 +133,17 @@ border-bottom: none } .searchTOC ul a { - display: block; + display: inline; padding-left: 25px; } +.searchTOC ul span { + float:right; + padding-right: 10px; + color:grey; + font-size:smaller; +} + /* -------------------------------------------------> */ /* DROP DOWN USER MENU ----------------------------> */ /* -------------------------------------------------> */ diff --git a/webapp/web/images/download-icon.png b/webapp/web/images/download-icon.png new file mode 100644 index 000000000..dd3213204 Binary files /dev/null and b/webapp/web/images/download-icon.png differ diff --git a/webapp/web/images/share-uri-icon.png b/webapp/web/images/share-uri-icon.png new file mode 100644 index 000000000..a79edd97b Binary files /dev/null and b/webapp/web/images/share-uri-icon.png differ diff --git a/webapp/web/js/searchDownload.js b/webapp/web/js/searchDownload.js new file mode 100644 index 000000000..1bcec1607 --- /dev/null +++ b/webapp/web/js/searchDownload.js @@ -0,0 +1,70 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +$(document).ready(function(){ + // This function creates and styles the "qTip" tooltip that displays the resource uri and the rdf link when the user clicks the uri/rdf icon. + + $('span#downloadResults').children('img#downloadIcon').each(function() + { + $(this).qtip( + { + content: { + prerender: true, // We need this for the .click() event listener on 'a.close' + text: '
' + +'

' + +'

' + +'
' + +'
' + +'
Download the results from this search
' + +'
download results in XML format
' + +'
download results in CSV format
' + +'
close
' + + }, + position: { + corner: { + target: 'bottomLeft', + tooltip: 'topLeft' + } + }, + show: { + when: {event: 'click'} + }, + hide: { + fixed: true, // Make it fixed so it can be hovered over and interacted with + when: { + target: $('a.close'), + event: 'click' + } + }, + style: { + padding: '1em', + width: 500, + backgroundColor: '#f1f2ee' + } + }); + + }); + + $( "#slider-vertical" ).slider({ + orientation: "vertical", + range: "min", + min: 10, + max: 1000, + value: 500, + slide: function( event, ui ) { + $( "#amount" ).val( ui.value ); + $('#csvDownload').attr("href", urlsBase + '/search?' + queryText +'&csv=1&hitsPerPage=' + ui.value); + $('#xmlDownload').attr("href", urlsBase + '/search?' + queryText +'&xml=1&hitsPerPage=' + ui.value); + } + }); + $( "#amount" ).val( $( "#slider-vertical" ).slider( "value" ) ); + + + // Prevent close link for URI qTip from requesting bogus '#' href + $('a.close').click(function() { + $('#downloadIcon').qtip("hide"); + return false; + }); + + +}); \ No newline at end of file diff --git a/webapp/web/templates/freemarker/body/search/search-csvResults.ftl b/webapp/web/templates/freemarker/body/search/search-csvResults.ftl new file mode 100644 index 000000000..575af9584 --- /dev/null +++ b/webapp/web/templates/freemarker/body/search/search-csvResults.ftl @@ -0,0 +1,9 @@ +<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> +<#assign today = .now > +<#assign todayDate = today?date> +Results from ${siteName} for ${querytext} on ${todayDate} + +Name, URI, URL +<#list individuals as individual> +"${individual.name}","${individual.uri}","${individual.profileUrl}" + diff --git a/webapp/web/templates/freemarker/body/search/search-pagedResults.ftl b/webapp/web/templates/freemarker/body/search/search-pagedResults.ftl index 0aa1a9d87..a0946ed23 100644 --- a/webapp/web/templates/freemarker/body/search/search-pagedResults.ftl +++ b/webapp/web/templates/freemarker/body/search/search-pagedResults.ftl @@ -2,13 +2,32 @@ <#-- Template for displaying paged search results --> -

+ + + +

<#escape x as x?html> ${i18n().search_results_for} '${querytext}' <#if classGroupName?has_content>${i18n().limited_to_type} '${classGroupName}' <#if typeName?has_content>${i18n().limited_to_type} '${typeName}' +

+ + + Download Results + + ${i18n().not_expected_results}
@@ -18,7 +37,7 @@

${i18n().display_only}

@@ -33,7 +52,7 @@ @@ -93,4 +112,12 @@ -${stylesheets.add('')} +${stylesheets.add('', + '')} + +${headScripts.add('', + '', + '' + )} + +${scripts.add('')} diff --git a/webapp/web/templates/freemarker/body/search/search-xmlResults.ftl b/webapp/web/templates/freemarker/body/search/search-xmlResults.ftl index b96094453..66821302b 100644 --- a/webapp/web/templates/freemarker/body/search/search-xmlResults.ftl +++ b/webapp/web/templates/freemarker/body/search/search-xmlResults.ftl @@ -14,6 +14,7 @@ ${individual.uri?xml} ${individual.name?xml} + ${individual.profileUrl?xml}"