Merge branch 'DS-1229'
Conflicts: dspace-xmlui/dspace-xmlui-webapp/src/main/webapp/themes/Mirage/lib/css/style.css
@@ -490,6 +490,8 @@ public class AuthorizeManager
|
||||
rp.setRpType(type);
|
||||
|
||||
rp.update();
|
||||
|
||||
o.updateLastModified();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -543,6 +545,8 @@ public class AuthorizeManager
|
||||
rp.setRpType(type);
|
||||
|
||||
rp.update();
|
||||
|
||||
o.updateLastModified();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -805,6 +809,8 @@ public class AuthorizeManager
|
||||
// and write out new policy
|
||||
drp.update();
|
||||
}
|
||||
|
||||
dest.updateLastModified();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -820,6 +826,8 @@ public class AuthorizeManager
|
||||
public static void removeAllPolicies(Context c, DSpaceObject o)
|
||||
throws SQLException
|
||||
{
|
||||
o.updateLastModified();
|
||||
|
||||
// FIXME: authorization check?
|
||||
DatabaseManager.updateQuery(c, "DELETE FROM resourcepolicy WHERE "
|
||||
+ "resource_type_id= ? AND resource_id= ? ",
|
||||
@@ -882,6 +890,7 @@ public class AuthorizeManager
|
||||
public static void removePoliciesActionFilter(Context context,
|
||||
DSpaceObject dso, int actionID) throws SQLException
|
||||
{
|
||||
dso.updateLastModified();
|
||||
if (actionID == -1)
|
||||
{
|
||||
// remove all policies from object
|
||||
@@ -929,6 +938,8 @@ public class AuthorizeManager
|
||||
public static void removeGroupPolicies(Context c, DSpaceObject o, Group g)
|
||||
throws SQLException
|
||||
{
|
||||
o.updateLastModified();
|
||||
|
||||
DatabaseManager.updateQuery(c, "DELETE FROM resourcepolicy WHERE "
|
||||
+ "resource_type_id= ? AND resource_id= ? AND epersongroup_id= ? ",
|
||||
o.getType(), o.getID(), g.getID());
|
||||
@@ -950,6 +961,7 @@ public class AuthorizeManager
|
||||
public static void removeEPersonPolicies(Context c, DSpaceObject o, EPerson e)
|
||||
throws SQLException
|
||||
{
|
||||
o.updateLastModified();
|
||||
DatabaseManager.updateQuery(c, "DELETE FROM resourcepolicy WHERE "
|
||||
+ "resource_type_id= ? AND resource_id= ? AND eperson_id= ? ",
|
||||
o.getType(), o.getID(), e.getID());
|
||||
|
@@ -180,6 +180,16 @@ public class ResourcePolicy
|
||||
*/
|
||||
public void delete() throws SQLException
|
||||
{
|
||||
if(getResourceID() != -1 && getResourceType() != -1)
|
||||
{
|
||||
//A policy for a DSpace Object has been modified, fire a modify event on the DSpace object
|
||||
DSpaceObject dso = DSpaceObject.find(myContext, getResourceType(), getResourceID());
|
||||
if(dso != null)
|
||||
{
|
||||
dso.updateLastModified();
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: authorizations
|
||||
// Remove ourself
|
||||
DatabaseManager.delete(myContext, myRow);
|
||||
@@ -455,8 +465,15 @@ public class ResourcePolicy
|
||||
/**
|
||||
* Update the ResourcePolicy
|
||||
*/
|
||||
public void update() throws SQLException
|
||||
{
|
||||
public void update() throws SQLException, AuthorizeException {
|
||||
if(getResourceID() != -1 && getResourceType() != -1){
|
||||
//A policy for a DSpace Object has been modified, fire a modify event on the DSpace object
|
||||
DSpaceObject dso = DSpaceObject.find(myContext, getResourceType(), getResourceID());
|
||||
if(dso != null){
|
||||
dso.updateLastModified();
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Check authorisation
|
||||
DatabaseManager.update(myContext, myRow);
|
||||
}
|
||||
|
@@ -384,6 +384,12 @@ public class BrowseItem extends DSpaceObject
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLastModified()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public boolean isArchived()
|
||||
{
|
||||
return in_archive;
|
||||
|
@@ -735,4 +735,11 @@ public class Bitstream extends DSpaceObject
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLastModified()
|
||||
{
|
||||
//Also fire a modified event since the bitstream HAS been modified
|
||||
bContext.addEvent(new Event(Event.MODIFY, Constants.BITSTREAM, getID(), null));
|
||||
}
|
||||
}
|
||||
|
@@ -811,4 +811,10 @@ public class Bundle extends DSpaceObject
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLastModified()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -1487,4 +1487,11 @@ public class Collection extends DSpaceObject
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLastModified()
|
||||
{
|
||||
//Also fire a modified event since the collection HAS been modified
|
||||
ourContext.addEvent(new Event(Event.MODIFY, Constants.COLLECTION, getID(), null));
|
||||
}
|
||||
}
|
||||
|
@@ -1282,4 +1282,11 @@ public class Community extends DSpaceObject
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLastModified()
|
||||
{
|
||||
//Also fire a modified event since the community HAS been modified
|
||||
ourContext.addEvent(new Event(Event.MODIFY, Constants.COMMUNITY, getID(), null));
|
||||
}
|
||||
}
|
||||
|
@@ -161,4 +161,6 @@ public abstract class DSpaceObject
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract void updateLastModified();
|
||||
}
|
||||
|
@@ -10,6 +10,7 @@ package org.dspace.content;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
@@ -326,11 +327,18 @@ public class Item extends DSpaceObject
|
||||
|
||||
/**
|
||||
* Method that updates the last modified date of the item
|
||||
* The modified boolean will be set to true and the actual date update will occur on item.update().
|
||||
*/
|
||||
void updateLastModified()
|
||||
public void updateLastModified()
|
||||
{
|
||||
modified = true;
|
||||
try {
|
||||
Date lastModified = new Timestamp(new Date().getTime());
|
||||
itemRow.setColumn("last_modified", lastModified);
|
||||
DatabaseManager.updateQuery(ourContext, "UPDATE item SET last_modified = ? WHERE item_id= ? ", lastModified, getID());
|
||||
//Also fire a modified event since the item HAS been modified
|
||||
ourContext.addEvent(new Event(Event.MODIFY, Constants.ITEM, getID(), null));
|
||||
} catch (SQLException e) {
|
||||
log.error(LogManager.getHeader(ourContext, "Error while updating last modified timestamp", "Item: " + getID()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -105,6 +105,12 @@ public class Site extends DSpaceObject
|
||||
return ConfigurationManager.getProperty("dspace.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLastModified()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public String getURL()
|
||||
{
|
||||
return ConfigurationManager.getProperty("dspace.url");
|
||||
|
@@ -1103,4 +1103,10 @@ public class EPerson extends DSpaceObject
|
||||
return getEmail();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLastModified()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1419,4 +1419,10 @@ public class Group extends DSpaceObject
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLastModified()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery;
|
||||
|
||||
/**
|
||||
* Configuration for one field that is to be highlighted
|
||||
* Giving 0 as max chars ensures that the entire field is returned !
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
*/
|
||||
public class DiscoverHitHighlightingField {
|
||||
|
||||
public static final int UNLIMITED_FRAGMENT_LENGTH = 0;
|
||||
|
||||
private String field;
|
||||
private int maxChars;
|
||||
private int maxSnippets;
|
||||
|
||||
public DiscoverHitHighlightingField(String field, int maxChars, int maxSnippets)
|
||||
{
|
||||
this.field = field;
|
||||
this.maxChars = maxChars;
|
||||
this.maxSnippets = maxSnippets;
|
||||
}
|
||||
|
||||
public String getField()
|
||||
{
|
||||
return field;
|
||||
}
|
||||
|
||||
/**
|
||||
* The max number of characters that should be shown for a
|
||||
* field containing a matching hit. e.g. If maxChars = 200
|
||||
* and a hit is found in the full-text the 200 chars
|
||||
* surrounding the hit will be shown
|
||||
*/
|
||||
public int getMaxChars()
|
||||
{
|
||||
return maxChars;
|
||||
}
|
||||
|
||||
public int getMaxSnippets()
|
||||
{
|
||||
return maxSnippets;
|
||||
}
|
||||
}
|
@@ -40,6 +40,7 @@ public class DiscoverQuery {
|
||||
private int facetLimit = -1;
|
||||
private int facetMinCount = -1;
|
||||
private int facetOffset = 0;
|
||||
private Map<String, DiscoverHitHighlightingField> hitHighlighting;
|
||||
|
||||
/** Used when you want to search for a specific field value **/
|
||||
private List<String> searchFields;
|
||||
@@ -55,6 +56,7 @@ public class DiscoverQuery {
|
||||
this.facetFields = new ArrayList<DiscoverFacetField>();
|
||||
this.facetQueries = new ArrayList<String>();
|
||||
this.searchFields = new ArrayList<String>();
|
||||
this.hitHighlighting = new HashMap<String, DiscoverHitHighlightingField>();
|
||||
//Use a linked hashmap since sometimes insertion order might matter
|
||||
this.properties = new LinkedHashMap<String, List<String>>();
|
||||
}
|
||||
@@ -239,10 +241,27 @@ public class DiscoverQuery {
|
||||
public void addProperty(String property, String value){
|
||||
List<String> toAddList = properties.get(property);
|
||||
if(toAddList == null)
|
||||
{
|
||||
toAddList = new ArrayList<String>();
|
||||
}
|
||||
|
||||
toAddList.add(value);
|
||||
|
||||
properties.put(property, toAddList);
|
||||
}
|
||||
|
||||
public DiscoverHitHighlightingField getHitHighlightingField(String field)
|
||||
{
|
||||
return hitHighlighting.get(field);
|
||||
}
|
||||
|
||||
public List<DiscoverHitHighlightingField> getHitHighlightingFields()
|
||||
{
|
||||
return new ArrayList<DiscoverHitHighlightingField>(hitHighlighting.values());
|
||||
}
|
||||
|
||||
public void addHitHighlightingField(DiscoverHitHighlightingField hitHighlighting)
|
||||
{
|
||||
this.hitHighlighting.put(hitHighlighting.getField(), hitHighlighting);
|
||||
}
|
||||
}
|
||||
|
@@ -25,12 +25,15 @@ public class DiscoverResult {
|
||||
/** A map that contains all the documents sougth after, the key is a string representation of the DSpace object */
|
||||
private Map<String, List<SearchDocument>> searchDocuments;
|
||||
private int maxResults = -1;
|
||||
private int searchTime;
|
||||
private Map<String, DSpaceObjectHighlightResult> highlightedResults;
|
||||
|
||||
|
||||
public DiscoverResult() {
|
||||
dspaceObjects = new ArrayList<DSpaceObject>();
|
||||
facetResults = new LinkedHashMap<String, List<FacetResult>>();
|
||||
searchDocuments = new LinkedHashMap<String, List<SearchDocument>>();
|
||||
highlightedResults = new HashMap<String, DSpaceObjectHighlightResult>();
|
||||
}
|
||||
|
||||
|
||||
@@ -66,6 +69,16 @@ public class DiscoverResult {
|
||||
this.maxResults = maxResults;
|
||||
}
|
||||
|
||||
public int getSearchTime()
|
||||
{
|
||||
return searchTime;
|
||||
}
|
||||
|
||||
public void setSearchTime(int searchTime)
|
||||
{
|
||||
this.searchTime = searchTime;
|
||||
}
|
||||
|
||||
public void addFacetResult(String facetField, FacetResult ...facetResults){
|
||||
List<FacetResult> facetValues = this.facetResults.get(facetField);
|
||||
if(facetValues == null)
|
||||
@@ -84,6 +97,16 @@ public class DiscoverResult {
|
||||
return facetResults.get(facet) == null ? new ArrayList<FacetResult>() : facetResults.get(facet);
|
||||
}
|
||||
|
||||
public DSpaceObjectHighlightResult getHighlightedResults(DSpaceObject dso)
|
||||
{
|
||||
return highlightedResults.get(dso.getHandle());
|
||||
}
|
||||
|
||||
public void addHighlightedResult(DSpaceObject dso, DSpaceObjectHighlightResult highlightedResult)
|
||||
{
|
||||
this.highlightedResults.put(dso.getHandle(), highlightedResult);
|
||||
}
|
||||
|
||||
public static final class FacetResult{
|
||||
private String asFilterQuery;
|
||||
private String displayedValue;
|
||||
@@ -108,6 +131,28 @@ public class DiscoverResult {
|
||||
}
|
||||
}
|
||||
|
||||
public static final class DSpaceObjectHighlightResult
|
||||
{
|
||||
private DSpaceObject dso;
|
||||
private Map<String, List<String>> highlightResults;
|
||||
|
||||
public DSpaceObjectHighlightResult(DSpaceObject dso, Map<String, List<String>> highlightResults)
|
||||
{
|
||||
this.dso = dso;
|
||||
this.highlightResults = highlightResults;
|
||||
}
|
||||
|
||||
public DSpaceObject getDso()
|
||||
{
|
||||
return dso;
|
||||
}
|
||||
|
||||
public List<String> getHighlightResults(String metadataKey)
|
||||
{
|
||||
return highlightResults.get(metadataKey);
|
||||
}
|
||||
}
|
||||
|
||||
public void addSearchDocument(DSpaceObject dso, SearchDocument searchDocument){
|
||||
String dsoString = SearchDocument.getDspaceObjectStringRepresentation(dso);
|
||||
List<SearchDocument> docs = searchDocuments.get(dsoString);
|
||||
|
@@ -8,8 +8,9 @@
|
||||
package org.dspace.discovery;
|
||||
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.discovery.configuration.DiscoverySortConfiguration;
|
||||
import org.dspace.discovery.configuration.DiscoveryMoreLikeThisConfiguration;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.sql.SQLException;
|
||||
@@ -28,23 +29,13 @@ public interface SearchService {
|
||||
|
||||
DiscoverResult search(Context context, DSpaceObject dso, DiscoverQuery query) throws SearchServiceException;
|
||||
|
||||
InputStream searchJSON(DiscoverQuery query, String jsonIdentifier) throws SearchServiceException;
|
||||
InputStream searchJSON(Context context, DiscoverQuery query, String jsonIdentifier) throws SearchServiceException;
|
||||
|
||||
InputStream searchJSON(DiscoverQuery query, DSpaceObject dso, String jsonIdentifier) throws SearchServiceException;
|
||||
InputStream searchJSON(Context context, DiscoverQuery query, DSpaceObject dso, String jsonIdentifier) throws SearchServiceException;
|
||||
|
||||
|
||||
List<DSpaceObject> search(Context context, String query, String orderfield, boolean ascending, int offset, int max, String... filterquery);
|
||||
|
||||
|
||||
/**
|
||||
* Transforms the given string into a filter query
|
||||
* @param context the DSpace context
|
||||
* @param filterQuery the filter query
|
||||
* @return a filter query object
|
||||
* @throws java.sql.SQLException ...
|
||||
*/
|
||||
DiscoverFilterQuery toFilterQuery(Context context, String filterQuery) throws SQLException;
|
||||
|
||||
/**
|
||||
* Transforms the given string field and value into a filter query
|
||||
* @param context the DSpace context
|
||||
@@ -53,7 +44,9 @@ public interface SearchService {
|
||||
* @return a filter query
|
||||
* @throws SQLException ...
|
||||
*/
|
||||
DiscoverFilterQuery toFilterQuery(Context context, String field, String value) throws SQLException;
|
||||
DiscoverFilterQuery toFilterQuery(Context context, String field, String operator, String value) throws SQLException;
|
||||
|
||||
List<Item> getRelatedItems(Context context, Item item, DiscoveryMoreLikeThisConfiguration moreLikeThisConfiguration);
|
||||
|
||||
/**
|
||||
* Transforms the metadata field of the given sort configuration into the indexed field which we can then use in our solr queries
|
||||
|
@@ -7,18 +7,21 @@
|
||||
*/
|
||||
package org.dspace.discovery.configuration;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Required;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
*/
|
||||
public class DiscoveryConfiguration {
|
||||
public class DiscoveryConfiguration implements InitializingBean{
|
||||
|
||||
/** The configuration for the sidebar facets **/
|
||||
private List<SidebarFacetConfiguration> sidebarFacets = new ArrayList<SidebarFacetConfiguration>();
|
||||
private List<DiscoverySearchFilterFacet> sidebarFacets = new ArrayList<DiscoverySearchFilterFacet>();
|
||||
|
||||
/** The default filter queries which will be applied to any search & the recent submissions **/
|
||||
private List<String> defaultFilterQueries;
|
||||
@@ -32,6 +35,8 @@ public class DiscoveryConfiguration {
|
||||
private DiscoverySortConfiguration searchSortConfiguration;
|
||||
|
||||
private String id;
|
||||
private DiscoveryHitHighlightingConfiguration hitHighlightingConfiguration;
|
||||
private DiscoveryMoreLikeThisConfiguration moreLikeThisConfiguration;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
@@ -41,12 +46,12 @@ public class DiscoveryConfiguration {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public List<SidebarFacetConfiguration> getSidebarFacets() {
|
||||
public List<DiscoverySearchFilterFacet> getSidebarFacets() {
|
||||
return sidebarFacets;
|
||||
}
|
||||
|
||||
@Required
|
||||
public void setSidebarFacets(List<SidebarFacetConfiguration> sidebarFacets) {
|
||||
public void setSidebarFacets(List<DiscoverySearchFilterFacet> sidebarFacets) {
|
||||
this.sidebarFacets = sidebarFacets;
|
||||
}
|
||||
|
||||
@@ -88,4 +93,46 @@ public class DiscoveryConfiguration {
|
||||
public void setSearchSortConfiguration(DiscoverySortConfiguration searchSortConfiguration) {
|
||||
this.searchSortConfiguration = searchSortConfiguration;
|
||||
}
|
||||
|
||||
public void setHitHighlightingConfiguration(DiscoveryHitHighlightingConfiguration hitHighlightingConfiguration) {
|
||||
this.hitHighlightingConfiguration = hitHighlightingConfiguration;
|
||||
}
|
||||
|
||||
public DiscoveryHitHighlightingConfiguration getHitHighlightingConfiguration() {
|
||||
return hitHighlightingConfiguration;
|
||||
}
|
||||
|
||||
public void setMoreLikeThisConfiguration(DiscoveryMoreLikeThisConfiguration moreLikeThisConfiguration) {
|
||||
this.moreLikeThisConfiguration = moreLikeThisConfiguration;
|
||||
}
|
||||
|
||||
public DiscoveryMoreLikeThisConfiguration getMoreLikeThisConfiguration() {
|
||||
return moreLikeThisConfiguration;
|
||||
}
|
||||
|
||||
/**
|
||||
* After all the properties are set check that the sidebar facets are a subset of our search filters
|
||||
*
|
||||
* @throws Exception throws an exception if this isn't the case
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception
|
||||
{
|
||||
Collection missingSearchFilters = CollectionUtils.subtract(getSidebarFacets(), getSearchFilters());
|
||||
if(CollectionUtils.isNotEmpty(missingSearchFilters))
|
||||
{
|
||||
StringBuilder error = new StringBuilder();
|
||||
error.append("The following sidebar facet configurations are not present in the search filters list: ");
|
||||
for (Object missingSearchFilter : missingSearchFilters)
|
||||
{
|
||||
DiscoverySearchFilter searchFilter = (DiscoverySearchFilter) missingSearchFilter;
|
||||
error.append(searchFilter.getIndexFieldName()).append(" ");
|
||||
|
||||
}
|
||||
error.append("all the sidebar facets MUST be a part of the search filters list.");
|
||||
|
||||
throw new DiscoveryConfigurationException(error.toString());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery.configuration;
|
||||
|
||||
/**
|
||||
* Exception that can be thrown if there are issues with the discovery configuration
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
*/
|
||||
public class DiscoveryConfigurationException extends Exception{
|
||||
|
||||
public DiscoveryConfigurationException() {
|
||||
}
|
||||
|
||||
public DiscoveryConfigurationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public DiscoveryConfigurationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public DiscoveryConfigurationException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
@@ -16,7 +16,8 @@ public class DiscoveryConfigurationParameters {
|
||||
|
||||
public static final String TYPE_TEXT = "text";
|
||||
public static final String TYPE_DATE = "date";
|
||||
public static final String TYPE_AC = "date";
|
||||
public static final String TYPE_HIERARCHICAL = "hierarchical";
|
||||
public static final String TYPE_AC = "ac";
|
||||
|
||||
public static enum SORT {VALUE, COUNT}
|
||||
|
||||
|
@@ -38,7 +38,7 @@ public class DiscoveryConfigurationService {
|
||||
System.out.println("Facets:");
|
||||
DiscoveryConfiguration discoveryConfiguration = mainService.getMap().get(key);
|
||||
for (int i = 0; i < discoveryConfiguration.getSidebarFacets().size(); i++) {
|
||||
SidebarFacetConfiguration sidebarFacet = discoveryConfiguration.getSidebarFacets().get(i);
|
||||
DiscoverySearchFilterFacet sidebarFacet = discoveryConfiguration.getSidebarFacets().get(i);
|
||||
System.out.println("\t" + sidebarFacet.getIndexFieldName());
|
||||
for (int j = 0; j < sidebarFacet.getMetadataFields().size(); j++) {
|
||||
String metadataField = sidebarFacet.getMetadataFields().get(j);
|
||||
@@ -49,7 +49,6 @@ public class DiscoveryConfigurationService {
|
||||
System.out.println("Search filters");
|
||||
List<DiscoverySearchFilter> searchFilters = discoveryConfiguration.getSearchFilters();
|
||||
for (DiscoverySearchFilter searchFilter : searchFilters) {
|
||||
System.out.println("\t" + searchFilter.getIndexFieldName() + " full: " + searchFilter.isFullAutoComplete());
|
||||
for (int i = 0; i < searchFilter.getMetadataFields().size(); i++) {
|
||||
String metadataField = searchFilter.getMetadataFields().get(i);
|
||||
System.out.println("\t\t" + metadataField);
|
||||
|
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery.configuration;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Required;
|
||||
|
||||
/**
|
||||
* Configuration class that holds hit highlighting configuration for a single metadata field
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
*/
|
||||
public class DiscoveryHitHighlightFieldConfiguration
|
||||
{
|
||||
private String field;
|
||||
private int maxSize = 0;
|
||||
private int snippets = 3;
|
||||
|
||||
|
||||
public String getField()
|
||||
{
|
||||
return field;
|
||||
}
|
||||
|
||||
@Required
|
||||
public void setField(String field)
|
||||
{
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
public int getMaxSize()
|
||||
{
|
||||
return maxSize;
|
||||
}
|
||||
|
||||
public void setMaxSize(int maxSize)
|
||||
{
|
||||
this.maxSize = maxSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum number of highlighted snippets to generate per field
|
||||
* @param snippets the number of maximum snippets
|
||||
*/
|
||||
public void setSnippets(int snippets)
|
||||
{
|
||||
this.snippets = snippets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum number of highlighted snippets to generate per field
|
||||
*/
|
||||
public int getSnippets()
|
||||
{
|
||||
return snippets;
|
||||
}
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery.configuration;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Required;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class that contains all the configuration concerning the hit highlighting in search resutls
|
||||
* This class can be configured in the [dspace.dir]/config/spring/discovery/spring-dspace-addon-discovery-configuration-services.xml
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
*/
|
||||
public class DiscoveryHitHighlightingConfiguration
|
||||
{
|
||||
|
||||
/* A list of metadata fields for which the hit highlighting is possible */
|
||||
private List<DiscoveryHitHighlightFieldConfiguration> metadataFields;
|
||||
|
||||
|
||||
@Required
|
||||
public void setMetadataFields(List<DiscoveryHitHighlightFieldConfiguration> metadataFields)
|
||||
{
|
||||
this.metadataFields = metadataFields;
|
||||
}
|
||||
|
||||
public List<DiscoveryHitHighlightFieldConfiguration> getMetadataFields()
|
||||
{
|
||||
return metadataFields;
|
||||
}
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery.configuration;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Required;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class that contains the more like this configuration on item pages
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
*/
|
||||
public class DiscoveryMoreLikeThisConfiguration {
|
||||
private List<String> similarityMetadataFields;
|
||||
private int minTermFrequency;
|
||||
private int max;
|
||||
private int minWordLength;
|
||||
|
||||
@Required
|
||||
public void setSimilarityMetadataFields(List<String> similarityMetadataFields)
|
||||
{
|
||||
this.similarityMetadataFields = similarityMetadataFields;
|
||||
}
|
||||
|
||||
public List<String> getSimilarityMetadataFields()
|
||||
{
|
||||
return similarityMetadataFields;
|
||||
}
|
||||
|
||||
@Required
|
||||
public void setMinTermFrequency(int minTermFrequency)
|
||||
{
|
||||
this.minTermFrequency = minTermFrequency;
|
||||
}
|
||||
|
||||
public int getMinTermFrequency()
|
||||
{
|
||||
return minTermFrequency;
|
||||
}
|
||||
|
||||
@Required
|
||||
public void setMax(int max)
|
||||
{
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
public int getMax()
|
||||
{
|
||||
return max;
|
||||
}
|
||||
|
||||
public int getMinWordLength()
|
||||
{
|
||||
return minWordLength;
|
||||
}
|
||||
|
||||
public void setMinWordLength(int minWordLength)
|
||||
{
|
||||
this.minWordLength = minWordLength;
|
||||
}
|
||||
}
|
@@ -16,10 +16,10 @@ import java.util.List;
|
||||
*/
|
||||
public class DiscoverySearchFilter {
|
||||
|
||||
private String indexFieldName;
|
||||
private List<String> metadataFields;
|
||||
private boolean fullAutoComplete;
|
||||
private String type = DiscoveryConfigurationParameters.TYPE_TEXT;
|
||||
protected String indexFieldName;
|
||||
protected List<String> metadataFields;
|
||||
protected String type = DiscoveryConfigurationParameters.TYPE_TEXT;
|
||||
public static final String FILTER_TYPE_DEFAULT = "default";
|
||||
|
||||
public String getIndexFieldName() {
|
||||
return indexFieldName;
|
||||
@@ -39,28 +39,29 @@ public class DiscoverySearchFilter {
|
||||
this.metadataFields = metadataFields;
|
||||
}
|
||||
|
||||
public boolean isFullAutoComplete() {
|
||||
return fullAutoComplete;
|
||||
}
|
||||
|
||||
public void setFullAutoComplete(boolean fullAutoComplete) {
|
||||
this.fullAutoComplete = fullAutoComplete;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
if(type.equalsIgnoreCase(DiscoveryConfigurationParameters.TYPE_TEXT)){
|
||||
public void setType(String type) throws DiscoveryConfigurationException {
|
||||
if(type.equalsIgnoreCase(DiscoveryConfigurationParameters.TYPE_TEXT))
|
||||
{
|
||||
this.type = DiscoveryConfigurationParameters.TYPE_TEXT;
|
||||
} else
|
||||
if(type.equalsIgnoreCase(DiscoveryConfigurationParameters.TYPE_DATE)){
|
||||
if(type.equalsIgnoreCase(DiscoveryConfigurationParameters.TYPE_DATE))
|
||||
{
|
||||
this.type = DiscoveryConfigurationParameters.TYPE_DATE;
|
||||
} else
|
||||
if(type.equalsIgnoreCase(DiscoveryConfigurationParameters.TYPE_HIERARCHICAL))
|
||||
{
|
||||
throw new DiscoveryConfigurationException("The " + type + " can't be used with a default side bar facet use the \"HierarchicalSidebarFacetConfiguration\" class instead.");
|
||||
}else{
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
|
||||
public String getFilterType(){
|
||||
return FILTER_TYPE_DEFAULT;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery.configuration;
|
||||
|
||||
/**
|
||||
* An expanded class that allows a search filter to be used as a sidebar facet
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
*/
|
||||
public class DiscoverySearchFilterFacet extends DiscoverySearchFilter {
|
||||
|
||||
private static final int DEFAULT_FACET_LIMIT = 10;
|
||||
private int facetLimit = -1;
|
||||
private DiscoveryConfigurationParameters.SORT sortOrder = DiscoveryConfigurationParameters.SORT.COUNT;
|
||||
public static final String FILTER_TYPE_FACET = "facet";
|
||||
|
||||
|
||||
public int getFacetLimit()
|
||||
{
|
||||
if(facetLimit == -1){
|
||||
return DEFAULT_FACET_LIMIT;
|
||||
}else{
|
||||
return facetLimit;
|
||||
}
|
||||
}
|
||||
|
||||
public void setFacetLimit(int facetLimit)
|
||||
{
|
||||
this.facetLimit = facetLimit;
|
||||
}
|
||||
|
||||
public DiscoveryConfigurationParameters.SORT getSortOrder()
|
||||
{
|
||||
return sortOrder;
|
||||
}
|
||||
|
||||
public void setSortOrder(DiscoveryConfigurationParameters.SORT sortOrder)
|
||||
{
|
||||
this.sortOrder = sortOrder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilterType()
|
||||
{
|
||||
return FILTER_TYPE_FACET;
|
||||
}
|
||||
}
|
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery.configuration;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Required;
|
||||
|
||||
/**
|
||||
* Special sidebar facet configuration used for hierarchical facets
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
*/
|
||||
public class HierarchicalSidebarFacetConfiguration extends DiscoverySearchFilterFacet{
|
||||
|
||||
private String splitter;
|
||||
private boolean skipFirstNodeLevel = true;
|
||||
|
||||
|
||||
public HierarchicalSidebarFacetConfiguration() {
|
||||
//Our default type is the hieracrhical, can be overridden by the configuration
|
||||
this.type = DiscoveryConfigurationParameters.TYPE_HIERARCHICAL;
|
||||
}
|
||||
|
||||
public String getSplitter() {
|
||||
return splitter;
|
||||
}
|
||||
|
||||
@Required
|
||||
public void setSplitter(String splitter) {
|
||||
this.splitter = splitter;
|
||||
}
|
||||
|
||||
public boolean isSkipFirstNodeLevel() {
|
||||
return skipFirstNodeLevel;
|
||||
}
|
||||
|
||||
public void setSkipFirstNodeLevel(boolean skipFirstNodeLevel) {
|
||||
this.skipFirstNodeLevel = skipFirstNodeLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setType(String type) throws DiscoveryConfigurationException {
|
||||
if(type.equalsIgnoreCase(DiscoveryConfigurationParameters.TYPE_HIERARCHICAL)){
|
||||
this.type = type;
|
||||
}else{
|
||||
throw new DiscoveryConfigurationException("The " + type + " can't be used with a hierarchical facet side bar facet use the \"DiscoverySearchFilterFacet\" class instead.");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -9,6 +9,7 @@ package org.dspace.discovery;
|
||||
|
||||
import org.apache.solr.common.SolrInputDocument;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
|
||||
/**
|
||||
@@ -19,7 +20,7 @@ import org.dspace.content.DSpaceObject;
|
||||
public class SolrServiceIndexOutputPlugin implements SolrServiceIndexPlugin{
|
||||
|
||||
@Override
|
||||
public void additionalIndex(DSpaceObject dso, SolrInputDocument document) {
|
||||
public void additionalIndex(Context context, DSpaceObject dso, SolrInputDocument document) {
|
||||
System.out.println("Currently indexing: " + dso.getHandle());
|
||||
}
|
||||
}
|
||||
|
@@ -9,13 +9,16 @@ package org.dspace.discovery;
|
||||
|
||||
import org.apache.solr.common.SolrInputDocument;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
/**
|
||||
* Indexing plugin used when indexing the communities/collections/items into DSpace
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
*/
|
||||
public interface SolrServiceIndexPlugin {
|
||||
|
||||
public void additionalIndex(DSpaceObject dso, SolrInputDocument document);
|
||||
public void additionalIndex(Context context, DSpaceObject dso, SolrInputDocument document);
|
||||
}
|
||||
|
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.solr.client.solrj.SolrQuery;
|
||||
import org.apache.solr.common.SolrInputDocument;
|
||||
import org.dspace.authorize.AuthorizeManager;
|
||||
import org.dspace.authorize.ResourcePolicy;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.LogManager;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.eperson.Group;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Restriction plugin that ensures that indexes all the resource policies.
|
||||
* When a search is performed extra filter queries are added to retrieve only results to which the user has READ access
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
*/
|
||||
public class SolrServiceResourceRestrictionPlugin implements SolrServiceIndexPlugin, SolrServiceSearchPlugin{
|
||||
|
||||
private static final Logger log = Logger.getLogger(SolrServiceResourceRestrictionPlugin.class);
|
||||
|
||||
@Override
|
||||
public void additionalIndex(Context context, DSpaceObject dso, SolrInputDocument document) {
|
||||
try {
|
||||
List<ResourcePolicy> policies = AuthorizeManager.getPoliciesActionFilter(context, dso, Constants.READ);
|
||||
for (ResourcePolicy resourcePolicy : policies) {
|
||||
String fieldValue;
|
||||
if(resourcePolicy.getGroupID() != -1){
|
||||
//We have a group add it to the value
|
||||
fieldValue = "g" + resourcePolicy.getGroupID();
|
||||
}else{
|
||||
//We have an eperson add it to the value
|
||||
fieldValue = "e" + resourcePolicy.getEPersonID();
|
||||
|
||||
}
|
||||
|
||||
document.addField("read", fieldValue);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.error(LogManager.getHeader(context, "Error while indexing resource policies", "DSpace object: (id " + dso.getID() + " type " + dso.getType() + ")"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void additionalSearchParameters(Context context, DiscoverQuery discoveryQuery, SolrQuery solrQuery) {
|
||||
StringBuilder resourceQuery = new StringBuilder();
|
||||
//Always add the anonymous group id to the query
|
||||
resourceQuery.append("read:(g0");
|
||||
EPerson currentUser = context.getCurrentUser();
|
||||
if(currentUser != null){
|
||||
try {
|
||||
resourceQuery.append(" OR e").append(currentUser.getID());
|
||||
//Retrieve all the groups the current user is a member of !
|
||||
Set<Integer> groupIds = Group.allMemberGroupIDs(context, currentUser);
|
||||
for (Integer groupId : groupIds) {
|
||||
resourceQuery.append(" OR g").append(groupId);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.error(LogManager.getHeader(context, "Error while adding resource policy information to query", "") ,e);
|
||||
}
|
||||
}
|
||||
resourceQuery.append(")");
|
||||
try {
|
||||
if(AuthorizeManager.isAdmin(context)){
|
||||
//Admins always have read access even if no policies are present !
|
||||
resourceQuery.append(" OR (!read[* TO *])");
|
||||
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.error(LogManager.getHeader(context, "Error while verifying if current user is admin !", ""), e);
|
||||
}
|
||||
solrQuery.addFilterQuery(resourceQuery.toString());
|
||||
}
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery;
|
||||
|
||||
import org.apache.solr.client.solrj.SolrQuery;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
/**
|
||||
* Plugin from which users can add additional search parameters for every search that occurs in discovery
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
*/
|
||||
public interface SolrServiceSearchPlugin {
|
||||
|
||||
public void additionalSearchParameters(Context context, DiscoverQuery discoveryQuery, SolrQuery solrQuery);
|
||||
}
|
@@ -11,8 +11,12 @@ import org.apache.cocoon.caching.CacheableProcessingComponent;
|
||||
import org.apache.cocoon.environment.ObjectModelHelper;
|
||||
import org.apache.cocoon.environment.Request;
|
||||
import org.apache.cocoon.util.HashUtil;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.excalibur.source.SourceValidity;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.app.util.MetadataExposure;
|
||||
import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer;
|
||||
import org.dspace.app.xmlui.utils.DSpaceValidity;
|
||||
import org.dspace.app.xmlui.utils.HandleUtil;
|
||||
@@ -24,13 +28,14 @@ import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.*;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.LogManager;
|
||||
import org.dspace.discovery.*;
|
||||
import org.dspace.discovery.configuration.DiscoveryConfiguration;
|
||||
import org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration;
|
||||
import org.dspace.discovery.configuration.DiscoverySortConfiguration;
|
||||
import org.dspace.discovery.configuration.DiscoverySortFieldConfiguration;
|
||||
import org.dspace.handle.HandleManager;
|
||||
import org.dspace.sort.SortOption;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -54,22 +59,17 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement
|
||||
|
||||
private static final Logger log = Logger.getLogger(AbstractSearch.class);
|
||||
|
||||
|
||||
/**
|
||||
* Language strings
|
||||
*/
|
||||
|
||||
private static final Message T_head1_community =
|
||||
message("xmlui.ArtifactBrowser.AbstractSearch.head1_community");
|
||||
message("xmlui.Discovery.AbstractSearch.head1_community");
|
||||
|
||||
private static final Message T_head1_collection =
|
||||
message("xmlui.ArtifactBrowser.AbstractSearch.head1_collection");
|
||||
message("xmlui.Discovery.AbstractSearch.head1_collection");
|
||||
|
||||
private static final Message T_head1_none =
|
||||
message("xmlui.ArtifactBrowser.AbstractSearch.head1_none");
|
||||
|
||||
private static final Message T_head2 =
|
||||
message("xmlui.ArtifactBrowser.AbstractSearch.head2");
|
||||
message("xmlui.Discovery.AbstractSearch.head1_none");
|
||||
|
||||
private static final Message T_no_results =
|
||||
message("xmlui.ArtifactBrowser.AbstractSearch.no_results");
|
||||
@@ -78,19 +78,13 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement
|
||||
message("xmlui.ArtifactBrowser.AbstractSearch.all_of_dspace");
|
||||
|
||||
private static final Message T_sort_by_relevance =
|
||||
message("xmlui.ArtifactBrowser.AbstractSearch.sort_by.relevance");
|
||||
message("xmlui.Discovery.AbstractSearch.sort_by.relevance");
|
||||
|
||||
private static final Message T_sort_by = message("xmlui.ArtifactBrowser.AbstractSearch.sort_by");
|
||||
private static final Message T_sort_by = message("xmlui.Discovery.AbstractSearch.sort_by.head");
|
||||
|
||||
private static final Message T_order = message("xmlui.ArtifactBrowser.AbstractSearch.order");
|
||||
private static final Message T_order_asc = message("xmlui.ArtifactBrowser.AbstractSearch.order.asc");
|
||||
private static final Message T_order_desc = message("xmlui.ArtifactBrowser.AbstractSearch.order.desc");
|
||||
|
||||
private static final Message T_rpp = message("xmlui.ArtifactBrowser.AbstractSearch.rpp");
|
||||
|
||||
|
||||
private static final Message T_sort_head = message("xmlui.Discovery.SimpleSearch.sort_head");
|
||||
private static final Message T_sort_button = message("xmlui.Discovery.SimpleSearch.sort_apply");
|
||||
private static final Message T_rpp = message("xmlui.Discovery.AbstractSearch.rpp");
|
||||
private static final Message T_result_head_3 = message("xmlui.Discovery.AbstractSearch.head3");
|
||||
private static final Message T_result_head_2 = message("xmlui.Discovery.AbstractSearch.head2");
|
||||
|
||||
/**
|
||||
* Cached query results
|
||||
@@ -180,7 +174,7 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement
|
||||
List<DiscoverResult.FacetResult> facetValues = facetResults.get(facetField);
|
||||
for (DiscoverResult.FacetResult facetResult : facetValues)
|
||||
{
|
||||
validity.add(facetResult.getAsFilterQuery() + facetResult.getCount());
|
||||
validity.add(facetField + facetResult.getAsFilterQuery() + facetResult.getCount());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,6 +200,65 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement
|
||||
public abstract void addBody(Body body) throws SAXException, WingException,
|
||||
UIException, SQLException, IOException, AuthorizeException;
|
||||
|
||||
/**
|
||||
* Build the main form that should be the only form that the user interface requires
|
||||
* This form will be used for all discovery queries, filters, ....
|
||||
* At the moment however this form is only used to track search result hits
|
||||
* @param searchDiv the division to add the form to
|
||||
*/
|
||||
protected void buildMainForm(Division searchDiv) throws WingException, SQLException {
|
||||
Request request = ObjectModelHelper.getRequest(objectModel);
|
||||
|
||||
//We set our action to context path, since the eventual action will depend on which url we click on
|
||||
Division mainForm = searchDiv.addInteractiveDivision("main-form", getBasicUrl(), Division.METHOD_POST, "");
|
||||
|
||||
String query = getQuery();
|
||||
mainForm.addHidden("query").setValue(query);
|
||||
|
||||
Map<String, String[]> fqs = getParameterFilterQueries();
|
||||
if (fqs != null)
|
||||
{
|
||||
for (String parameter : fqs.keySet())
|
||||
{
|
||||
String[] values = fqs.get(parameter);
|
||||
if(values != null)
|
||||
{
|
||||
for (String value : values)
|
||||
{
|
||||
mainForm.addHidden(parameter).setValue(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mainForm.addHidden("rpp").setValue(getParameterRpp());
|
||||
Hidden sort_by = mainForm.addHidden("sort_by");
|
||||
if(!StringUtils.isBlank(request.getParameter("sort_by")))
|
||||
{
|
||||
sort_by.setValue(request.getParameter("sort_by"));
|
||||
}else{
|
||||
sort_by.setValue("score");
|
||||
}
|
||||
|
||||
Hidden order = mainForm.addHidden("order");
|
||||
if(getParameterOrder() != null)
|
||||
{
|
||||
order.setValue(request.getParameter("order"));
|
||||
}else{
|
||||
DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
|
||||
DiscoveryConfiguration discoveryConfiguration = SearchUtils.getDiscoveryConfiguration(dso);
|
||||
order.setValue(discoveryConfiguration.getSearchSortConfiguration().getDefaultSortOrder().toString());
|
||||
}
|
||||
if(!StringUtils.isBlank(request.getParameter("page")))
|
||||
{
|
||||
mainForm.addHidden("page").setValue(request.getParameter("page"));
|
||||
}
|
||||
//Optional redirect url !
|
||||
mainForm.addHidden("redirectUrl");
|
||||
}
|
||||
|
||||
protected abstract String getBasicUrl() throws SQLException;
|
||||
|
||||
/**
|
||||
* Attach a division to the given search division named "search-results"
|
||||
* which contains results for this search query.
|
||||
@@ -232,19 +285,33 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement
|
||||
}
|
||||
|
||||
Division results = search.addDivision("search-results", "primary");
|
||||
buildSearchControls(results);
|
||||
|
||||
|
||||
DSpaceObject searchScope = getScope();
|
||||
|
||||
if (searchScope instanceof Community) {
|
||||
int displayedResults;
|
||||
long totalResults;
|
||||
float searchTime;
|
||||
|
||||
if(queryResults != null && 0 < queryResults.getTotalSearchResults())
|
||||
{
|
||||
displayedResults = queryResults.getDspaceObjects().size();
|
||||
totalResults = queryResults.getTotalSearchResults();
|
||||
searchTime = ((float) queryResults.getSearchTime() / 1000) % 60;
|
||||
|
||||
if (searchScope instanceof Community)
|
||||
{
|
||||
Community community = (Community) searchScope;
|
||||
String communityName = community.getMetadata("name");
|
||||
results.setHead(T_head1_community.parameterize(communityName));
|
||||
results.setHead(T_head1_community.parameterize(displayedResults, totalResults, communityName, searchTime));
|
||||
} else if (searchScope instanceof Collection){
|
||||
Collection collection = (Collection) searchScope;
|
||||
String collectionName = collection.getMetadata("name");
|
||||
results.setHead(T_head1_collection.parameterize(collectionName));
|
||||
results.setHead(T_head1_collection.parameterize(displayedResults, totalResults, collectionName, searchTime));
|
||||
} else {
|
||||
results.setHead(T_head1_none);
|
||||
results.setHead(T_head1_none.parameterize(displayedResults, totalResults, searchTime));
|
||||
}
|
||||
}
|
||||
|
||||
if (queryResults != null && 0 < queryResults.getDspaceObjects().size())
|
||||
@@ -262,12 +329,20 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement
|
||||
Map<String, String> parameters = new HashMap<String, String>();
|
||||
parameters.put("page", "{pageNum}");
|
||||
String pageURLMask = generateURL(parameters);
|
||||
//Check for facet queries ? If we have any add them
|
||||
String[] fqs = getParameterFilterQueries();
|
||||
if(fqs != null) {
|
||||
Map<String, String[]> filterQueryParams = getParameterFilterQueries();
|
||||
if(filterQueryParams != null)
|
||||
{
|
||||
StringBuilder maskBuilder = new StringBuilder(pageURLMask);
|
||||
for (String fq : fqs) {
|
||||
maskBuilder.append("&fq=").append(fq);
|
||||
for (String filterQueryParam : filterQueryParams.keySet())
|
||||
{
|
||||
String[] filterQueryValues = filterQueryParams.get(filterQueryParam);
|
||||
if(filterQueryValues != null)
|
||||
{
|
||||
for (String filterQueryValue : filterQueryValues)
|
||||
{
|
||||
maskBuilder.append("&").append(filterQueryParam).append("=").append(filterQueryValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pageURLMask = maskBuilder.toString();
|
||||
@@ -277,34 +352,62 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement
|
||||
lastItemIndex, currentPage, pagesTotal, pageURLMask);
|
||||
|
||||
// Look for any communities or collections in the mix
|
||||
ReferenceSet referenceSet = null;
|
||||
org.dspace.app.xmlui.wing.element.List dspaceObjectsList = null;
|
||||
|
||||
// Put in palce top level search result list
|
||||
dspaceObjectsList = results.addList("search-results-repository",
|
||||
org.dspace.app.xmlui.wing.element.List.TYPE_DSO_LIST, "repository-search-results");
|
||||
|
||||
List<DSpaceObject> commCollList = new ArrayList<DSpaceObject>();
|
||||
List<Item> itemList = new ArrayList<Item>();
|
||||
for (DSpaceObject resultDso : queryResults.getDspaceObjects())
|
||||
{
|
||||
if (resultDso instanceof Community || resultDso instanceof Collection) {
|
||||
if (referenceSet == null) {
|
||||
referenceSet = results.addReferenceSet("search-results-repository",
|
||||
ReferenceSet.TYPE_SUMMARY_LIST, null, "repository-search-results");
|
||||
// Set a heading showing that we will be listing containers that matched:
|
||||
referenceSet.setHead(T_head2);
|
||||
}
|
||||
if(resultDso != null){
|
||||
referenceSet.addReference(resultDso);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Put in palce top level referenceset
|
||||
referenceSet = results.addReferenceSet("search-results-repository",
|
||||
ReferenceSet.TYPE_SUMMARY_LIST, null, "repository-search-results");
|
||||
|
||||
|
||||
for (DSpaceObject resultDso : queryResults.getDspaceObjects())
|
||||
if(resultDso.getType() == Constants.COMMUNITY || resultDso.getType() == Constants.COLLECTION)
|
||||
{
|
||||
if (resultDso instanceof Item)
|
||||
commCollList.add(resultDso);
|
||||
}else
|
||||
if(resultDso.getType() == Constants.ITEM)
|
||||
{
|
||||
referenceSet.addReference(resultDso);
|
||||
itemList.add((Item) resultDso);
|
||||
}
|
||||
}
|
||||
|
||||
if(CollectionUtils.isNotEmpty(commCollList))
|
||||
{
|
||||
org.dspace.app.xmlui.wing.element.List commCollWingList = dspaceObjectsList.addList("comm-coll-result-list");
|
||||
commCollWingList.setHead(T_result_head_2);
|
||||
for (DSpaceObject dso : commCollList)
|
||||
{
|
||||
DiscoverResult.DSpaceObjectHighlightResult highlightedResults = queryResults.getHighlightedResults(dso);
|
||||
if(dso.getType() == Constants.COMMUNITY)
|
||||
{
|
||||
//Render our community !
|
||||
org.dspace.app.xmlui.wing.element.List communityMetadata = commCollWingList.addList(dso.getHandle() + ":community");
|
||||
|
||||
renderCommunity((Community) dso, highlightedResults, communityMetadata);
|
||||
}else
|
||||
if(dso.getType() == Constants.COLLECTION)
|
||||
{
|
||||
//Render our collection !
|
||||
org.dspace.app.xmlui.wing.element.List collectionMetadata = commCollWingList.addList(dso.getHandle() + ":collection");
|
||||
|
||||
renderCollection((Collection) dso, highlightedResults, collectionMetadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(CollectionUtils.isNotEmpty(itemList))
|
||||
{
|
||||
org.dspace.app.xmlui.wing.element.List itemWingList = dspaceObjectsList.addList("item-result-list");
|
||||
if(CollectionUtils.isNotEmpty(commCollList))
|
||||
{
|
||||
itemWingList.setHead(T_result_head_3);
|
||||
|
||||
}
|
||||
for (Item resultDso : itemList)
|
||||
{
|
||||
DiscoverResult.DSpaceObjectHighlightResult highlightedResults = queryResults.getHighlightedResults(resultDso);
|
||||
renderItem(itemWingList, resultDso, highlightedResults);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,6 +417,239 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement
|
||||
//}// Empty query
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the given item, all metadata is added to the given list, which metadata will be rendered where depends on the xsl
|
||||
* @param dspaceObjectsList a list of DSpace objects
|
||||
* @param item the DSpace item to be rendered
|
||||
* @param highlightedResults the highlighted results
|
||||
* @throws WingException
|
||||
* @throws SQLException Database failure in services this calls
|
||||
*/
|
||||
protected void renderItem(org.dspace.app.xmlui.wing.element.List dspaceObjectsList, Item item, DiscoverResult.DSpaceObjectHighlightResult highlightedResults) throws WingException, SQLException {
|
||||
org.dspace.app.xmlui.wing.element.List itemList = dspaceObjectsList.addList(item.getHandle() + ":item");
|
||||
|
||||
MetadataField[] metadataFields = MetadataField.findAll(context);
|
||||
for (MetadataField metadataField : metadataFields)
|
||||
{
|
||||
//Retrieve the schema for this field
|
||||
String schema = MetadataSchema.find(context, metadataField.getSchemaID()).getName();
|
||||
//Check if our field isn't hidden
|
||||
if (!MetadataExposure.isHidden(context, schema, metadataField.getElement(), metadataField.getQualifier()))
|
||||
{
|
||||
//Check if our metadata field is highlighted
|
||||
StringBuilder metadataKey = new StringBuilder();
|
||||
metadataKey.append(schema).append(".").append(metadataField.getElement());
|
||||
if (metadataField.getQualifier() != null)
|
||||
{
|
||||
metadataKey.append(".").append(metadataField.getQualifier());
|
||||
}
|
||||
|
||||
StringBuilder itemName = new StringBuilder();
|
||||
itemName.append(item.getHandle()).append(":").append(metadataKey.toString());
|
||||
|
||||
|
||||
DCValue[] itemMetadata = item.getMetadata(schema, metadataField.getElement(), metadataField.getQualifier(), Item.ANY);
|
||||
if(!ArrayUtils.isEmpty(itemMetadata))
|
||||
{
|
||||
org.dspace.app.xmlui.wing.element.List metadataFieldList = itemList.addList(itemName.toString());
|
||||
for (DCValue metadataValue : itemMetadata)
|
||||
{
|
||||
String value = metadataValue.value;
|
||||
addMetadataField(highlightedResults, metadataKey.toString(), metadataFieldList, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Check our highlighted results, we may need to add non metadata (like our full text)
|
||||
if(highlightedResults != null)
|
||||
{
|
||||
//Also add the full text snippet (if available !)
|
||||
List<String> fullSnippets = highlightedResults.getHighlightResults("fulltext");
|
||||
if(CollectionUtils.isNotEmpty(fullSnippets))
|
||||
{
|
||||
StringBuilder itemName = new StringBuilder();
|
||||
itemName.append(item.getHandle()).append(":").append("fulltext");
|
||||
|
||||
org.dspace.app.xmlui.wing.element.List fullTextFieldList = itemList.addList(itemName.toString());
|
||||
|
||||
for (String snippet : fullSnippets)
|
||||
{
|
||||
addMetadataField(fullTextFieldList, snippet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the given collection, all collection metadata is added to the list
|
||||
* @param collection the collection to be rendered
|
||||
* @param highlightedResults the highlighted results
|
||||
* @throws WingException
|
||||
*/
|
||||
protected void renderCollection(Collection collection, DiscoverResult.DSpaceObjectHighlightResult highlightedResults, org.dspace.app.xmlui.wing.element.List collectionMetadata) throws WingException {
|
||||
|
||||
String description = collection.getMetadata("introductory_text");
|
||||
String description_abstract = collection.getMetadata("short_description");
|
||||
String description_table = collection.getMetadata("side_bar_text");
|
||||
String identifier_uri = "http://hdl.handle.net/" + collection.getHandle();
|
||||
String provenance = collection.getMetadata("provenance_description");
|
||||
String rights = collection.getMetadata("copyright_text");
|
||||
String rights_license = collection.getMetadata("license");
|
||||
String title = collection.getMetadata("name");
|
||||
|
||||
if(StringUtils.isNotBlank(description))
|
||||
{
|
||||
addMetadataField(highlightedResults, "dc.description", collectionMetadata.addList(collection.getHandle() + ":dc.description"), description);
|
||||
}
|
||||
if(StringUtils.isNotBlank(description_abstract))
|
||||
{
|
||||
addMetadataField(highlightedResults, "dc.description.abstract", collectionMetadata.addList(collection.getHandle() + ":dc.description.abstract"), description_abstract);
|
||||
}
|
||||
if(StringUtils.isNotBlank(description_table))
|
||||
{
|
||||
addMetadataField(highlightedResults, "dc.description.tableofcontents", collectionMetadata.addList(collection.getHandle() + ":dc.description.tableofcontents"), description_table);
|
||||
}
|
||||
if(StringUtils.isNotBlank(identifier_uri))
|
||||
{
|
||||
addMetadataField(highlightedResults, "dc.identifier.uri", collectionMetadata.addList(collection.getHandle() + ":dc.identifier.uri"), identifier_uri);
|
||||
}
|
||||
if(StringUtils.isNotBlank(provenance))
|
||||
{
|
||||
addMetadataField(highlightedResults, "dc.provenance", collectionMetadata.addList(collection.getHandle() + ":dc.provenance"), provenance);
|
||||
}
|
||||
if(StringUtils.isNotBlank(rights))
|
||||
{
|
||||
addMetadataField(highlightedResults, "dc.rights", collectionMetadata.addList(collection.getHandle() + ":dc.rights"), rights);
|
||||
}
|
||||
if(StringUtils.isNotBlank(rights_license))
|
||||
{
|
||||
addMetadataField(highlightedResults, "dc.rights.license", collectionMetadata.addList(collection.getHandle() + ":dc.rights.license"), rights_license);
|
||||
}
|
||||
if(StringUtils.isNotBlank(title))
|
||||
{
|
||||
addMetadataField(highlightedResults, "dc.title", collectionMetadata.addList(collection.getHandle() + ":dc.title"), title);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the given collection, all collection metadata is added to the list
|
||||
* @param community the community to be rendered
|
||||
* @param highlightedResults the highlighted results
|
||||
* @throws WingException
|
||||
*/
|
||||
|
||||
protected void renderCommunity(Community community, DiscoverResult.DSpaceObjectHighlightResult highlightedResults, org.dspace.app.xmlui.wing.element.List communityMetadata) throws WingException {
|
||||
String description = community.getMetadata("introductory_text");
|
||||
String description_abstract = community.getMetadata("short_description");
|
||||
String description_table = community.getMetadata("side_bar_text");
|
||||
String identifier_uri = "http://hdl.handle.net/" + community.getHandle();
|
||||
String rights = community.getMetadata("copyright_text");
|
||||
String title = community.getMetadata("name");
|
||||
|
||||
if(StringUtils.isNotBlank(description))
|
||||
{
|
||||
addMetadataField(highlightedResults, "dc.description", communityMetadata.addList(community.getHandle() + ":dc.description"), description);
|
||||
}
|
||||
if(StringUtils.isNotBlank(description_abstract))
|
||||
{
|
||||
addMetadataField(highlightedResults, "dc.description.abstract", communityMetadata.addList(community.getHandle() + ":dc.description.abstract"), description_abstract);
|
||||
}
|
||||
if(StringUtils.isNotBlank(description_table))
|
||||
{
|
||||
addMetadataField(highlightedResults, "dc.description.tableofcontents", communityMetadata.addList(community.getHandle() + ":dc.description.tableofcontents"), description_table);
|
||||
}
|
||||
if(StringUtils.isNotBlank(identifier_uri))
|
||||
{
|
||||
addMetadataField(highlightedResults, "dc.identifier.uri", communityMetadata.addList(community.getHandle() + ":dc.identifier.uri"), identifier_uri);
|
||||
}
|
||||
if(StringUtils.isNotBlank(rights))
|
||||
{
|
||||
addMetadataField(highlightedResults, "dc.rights", communityMetadata.addList(community.getHandle() + ":dc.rights"), rights);
|
||||
}
|
||||
if(StringUtils.isNotBlank(title))
|
||||
{
|
||||
addMetadataField(highlightedResults, "dc.title", communityMetadata.addList(community.getHandle() + ":dc.title"), title);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the current value to the wing list,
|
||||
* @param highlightedResults the highlighted results
|
||||
* @param metadataKey the metadata key {schema}.{element}.{qualifier}
|
||||
* @param metadataFieldList the wing list we need to add the metadata value to
|
||||
* @param value the metadata value
|
||||
* @throws WingException
|
||||
*/
|
||||
protected void addMetadataField(DiscoverResult.DSpaceObjectHighlightResult highlightedResults, String metadataKey, org.dspace.app.xmlui.wing.element.List metadataFieldList, String value) throws WingException {
|
||||
if(value == null){
|
||||
//In the unlikely event that the value is null, do not attempt to render this
|
||||
return;
|
||||
}
|
||||
|
||||
if(highlightedResults != null && highlightedResults.getHighlightResults(metadataKey) != null)
|
||||
{
|
||||
//Loop over all our highlighted results
|
||||
for (String highlight : highlightedResults.getHighlightResults(metadataKey))
|
||||
{
|
||||
//If our non highlighted value matches our original one, ensure that the highlighted one is used
|
||||
DiscoverHitHighlightingField highlightConfig = queryArgs.getHitHighlightingField(metadataKey);
|
||||
//We might also have it configured for ALL !
|
||||
if(highlightConfig == null)
|
||||
{
|
||||
highlightConfig = queryArgs.getHitHighlightingField("*");
|
||||
}
|
||||
switch (highlightConfig.getMaxChars())
|
||||
{
|
||||
case DiscoverHitHighlightingField.UNLIMITED_FRAGMENT_LENGTH:
|
||||
//Exact match required
|
||||
//\r is not indexed in solr & will cause issues
|
||||
if(highlight.replaceAll("</?em>", "").equals(value.replace("\r", "")))
|
||||
{
|
||||
value = highlight;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//Partial match allowed, only render the highlighted part
|
||||
if(value.contains(highlight.replaceAll("</?em>", "")))
|
||||
{
|
||||
value = highlight;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
addMetadataField(metadataFieldList, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add our metadata value, this value will might contain the highlight ("<em></em>") tags, these will be removed & rendered as highlight wing fields.
|
||||
* @param metadataFieldList the metadata list we need to add the value to
|
||||
* @param value the metadata value to be rendered
|
||||
* @throws WingException
|
||||
*/
|
||||
protected void addMetadataField(org.dspace.app.xmlui.wing.element.List metadataFieldList, String value) throws WingException {
|
||||
//We need to put everything in <em> tags in a highlight !
|
||||
org.dspace.app.xmlui.wing.element.Item metadataItem = metadataFieldList.addItem();
|
||||
while(value.contains("<em>") && value.contains("</em>"))
|
||||
{
|
||||
if(0 < value.indexOf("<em>"))
|
||||
{
|
||||
//Add everything before the <em> !
|
||||
metadataItem.addContent(value.substring(0, value.indexOf("<em>")));
|
||||
}
|
||||
metadataItem.addHighlight("highlight").addContent(StringUtils.substringBetween(value, "<em>", "</em>"));
|
||||
|
||||
value = StringUtils.substringAfter(value, "</em>");
|
||||
|
||||
}
|
||||
if(0 < value.length())
|
||||
{
|
||||
metadataItem.addContent(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add options to the search scope field. This field determines in what
|
||||
* communities or collections to search for the query.
|
||||
@@ -472,60 +808,14 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement
|
||||
queryArgs.setStart(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Use mlt
|
||||
// queryArgs.add("mlt", "true");
|
||||
|
||||
// The fields to use for similarity. NOTE: if possible, these should have a stored TermVector
|
||||
// queryArgs.add("mlt.fl", "author");
|
||||
|
||||
// Minimum Term Frequency - the frequency below which terms will be ignored in the source doc.
|
||||
// queryArgs.add("mlt.mintf", "1");
|
||||
|
||||
// Minimum Document Frequency - the frequency at which words will be ignored which do not occur in at least this many docs.
|
||||
// queryArgs.add("mlt.mindf", "1");
|
||||
|
||||
//queryArgs.add("mlt.q", "");
|
||||
|
||||
// mlt.minwl
|
||||
// minimum word length below which words will be ignored.
|
||||
|
||||
// mlt.maxwl
|
||||
// maximum word length above which words will be ignored.
|
||||
|
||||
// mlt.maxqt
|
||||
// maximum number of query terms that will be included in any generated query.
|
||||
|
||||
// mlt.maxntp
|
||||
// maximum number of tokens to parse in each example doc field that is not stored with TermVector support.
|
||||
|
||||
// mlt.boost
|
||||
// [true/false] set if the query will be boosted by the interesting term relevance.
|
||||
|
||||
// mlt.qf
|
||||
// Query fields and their boosts using the same format as that used in DisMaxRequestHandler. These fields must also be specified in mlt.fl.
|
||||
|
||||
|
||||
//filePost.addParameter("fl", "handle, "search.resourcetype")");
|
||||
//filePost.addParameter("field", "search.resourcetype");
|
||||
|
||||
//Set the default limit to 11
|
||||
/*
|
||||
ClientUtils.escapeQueryChars(location)
|
||||
//f.category.facet.limit=5
|
||||
|
||||
for(Enumeration en = request.getParameterNames(); en.hasMoreElements();)
|
||||
if(discoveryConfiguration.getHitHighlightingConfiguration() != null)
|
||||
{
|
||||
String key = (String)en.nextElement();
|
||||
if(key.endsWith(".facet.limit"))
|
||||
List<DiscoveryHitHighlightFieldConfiguration> metadataFields = discoveryConfiguration.getHitHighlightingConfiguration().getMetadataFields();
|
||||
for (DiscoveryHitHighlightFieldConfiguration fieldConfiguration : metadataFields)
|
||||
{
|
||||
filePost.addParameter(key, request.getParameter(key));
|
||||
queryArgs.addHitHighlightingField(new DiscoverHitHighlightingField(fieldConfiguration.getField(), fieldConfiguration.getMaxSize(), fieldConfiguration.getSnippets()));
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
this.queryResults = SearchUtils.getSearchService().search(context, scope, queryArgs);
|
||||
}
|
||||
@@ -536,9 +826,12 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement
|
||||
* Returns a list of the filter queries for use in rendering pages, creating page more urls, ....
|
||||
* @return an array containing the filter queries
|
||||
*/
|
||||
protected String[] getParameterFilterQueries(){
|
||||
protected Map<String, String[]> getParameterFilterQueries()
|
||||
{
|
||||
try {
|
||||
return ObjectModelHelper.getRequest(objectModel).getParameterValues("fq");
|
||||
Map<String, String[]> result = new HashMap<String, String[]>();
|
||||
result.put("fq", ObjectModelHelper.getRequest(objectModel).getParameterValues("fq"));
|
||||
return result;
|
||||
}
|
||||
catch (Exception e) {
|
||||
return null;
|
||||
@@ -659,89 +952,46 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement
|
||||
protected void buildSearchControls(Division div)
|
||||
throws WingException, SQLException {
|
||||
|
||||
org.dspace.app.xmlui.wing.element.List controlsList = div.addList("search-controls", org.dspace.app.xmlui.wing.element.List.TYPE_FORM);
|
||||
|
||||
|
||||
controlsList.setHead(T_sort_head);
|
||||
//Table controlsTable = div.addTable("search-controls", 1, 4);
|
||||
|
||||
org.dspace.app.xmlui.wing.element.Item controlsItem = controlsList.addItem();
|
||||
// Create a control for the number of records to display
|
||||
controlsItem.addContent(T_rpp);
|
||||
Select rppSelect = controlsItem.addSelect("rpp");
|
||||
for (int i : RESULTS_PER_PAGE_PROGRESSION) {
|
||||
rppSelect.addOption((i == getParameterRpp()), i, Integer.toString(i));
|
||||
}
|
||||
|
||||
/*
|
||||
Cell groupCell = controlsRow.addCell();
|
||||
try {
|
||||
// Create a drop down of the different sort columns available
|
||||
groupCell.addContent(T_group_by);
|
||||
Select groupSelect = groupCell.addSelect("group_by");
|
||||
groupSelect.addOption(false, "none", T_group_by_none);
|
||||
|
||||
|
||||
String[] groups = {"publication_grp"};
|
||||
for (String group : groups) {
|
||||
groupSelect.addOption(group.equals(getParameterGroup()), group,
|
||||
message("xmlui.ArtifactBrowser.AbstractSearch.group_by." + group));
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception se) {
|
||||
throw new WingException("Unable to get group options", se);
|
||||
}
|
||||
*/
|
||||
|
||||
// Create a drop down of the different sort columns available
|
||||
controlsItem.addContent(T_sort_by);
|
||||
Select sortSelect = controlsItem.addSelect("sort_by");
|
||||
sortSelect.addOption(false, "score", T_sort_by_relevance);
|
||||
|
||||
DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
|
||||
DiscoveryConfiguration discoveryConfiguration = SearchUtils.getDiscoveryConfiguration(dso);
|
||||
|
||||
Division searchControlsGear = div.addDivision("masked-page-control").addDivision("search-controls-gear", "controls-gear-wrapper");
|
||||
|
||||
|
||||
/**
|
||||
* Add sort by options, the gear will be rendered by a combination fo javascript & css
|
||||
*/
|
||||
String currentSort = getParameterSortBy();
|
||||
org.dspace.app.xmlui.wing.element.List sortList = searchControlsGear.addList("sort-options", org.dspace.app.xmlui.wing.element.List.TYPE_SIMPLE, "gear-selection");
|
||||
sortList.addItem("sort-head", "gear-head first").addContent(T_sort_by);
|
||||
DiscoverySortConfiguration searchSortConfiguration = discoveryConfiguration.getSearchSortConfiguration();
|
||||
if(searchSortConfiguration != null){
|
||||
for (DiscoverySortFieldConfiguration sortFieldConfiguration : searchSortConfiguration.getSortFields()) {
|
||||
|
||||
org.dspace.app.xmlui.wing.element.List sortOptions = sortList.addList("sort-selections");
|
||||
boolean selected = ("score".equals(currentSort) || (currentSort == null && searchSortConfiguration.getDefaultSort() == null));
|
||||
sortOptions.addItem("relevance", "gear-option" + (selected ? " gear-option-selected" : "")).addXref("sort_by=score&order=" + searchSortConfiguration.getDefaultSortOrder(), T_sort_by_relevance);
|
||||
|
||||
if(searchSortConfiguration.getSortFields() != null)
|
||||
{
|
||||
for (DiscoverySortFieldConfiguration sortFieldConfiguration : searchSortConfiguration.getSortFields())
|
||||
{
|
||||
String sortField = SearchUtils.getSearchService().toSortFieldIndex(sortFieldConfiguration.getMetadataField(), sortFieldConfiguration.getType());
|
||||
|
||||
String currentSort = getParameterSortBy();
|
||||
sortSelect.addOption((sortField.equals(currentSort) || sortFieldConfiguration.equals(searchSortConfiguration.getDefaultSort())), sortField,
|
||||
message("xmlui.ArtifactBrowser.AbstractSearch.sort_by." + sortField));
|
||||
boolean selectedAsc = ((sortField.equals(currentSort) && "asc".equals(getParameterOrder())) || (sortFieldConfiguration.equals(searchSortConfiguration.getDefaultSort())) && DiscoverySortConfiguration.SORT_ORDER.asc.equals(searchSortConfiguration.getDefaultSortOrder()));
|
||||
boolean selectedDesc= ((sortField.equals(currentSort) && "desc".equals(getParameterOrder())) || (sortFieldConfiguration.equals(searchSortConfiguration.getDefaultSort())) && DiscoverySortConfiguration.SORT_ORDER.desc.equals(searchSortConfiguration.getDefaultSortOrder()));
|
||||
String sortFieldParam = "sort_by=" + sortField + "&order=";
|
||||
sortOptions.addItem(sortField, "gear-option" + (selectedAsc ? " gear-option-selected" : "")).addXref(sortFieldParam + "asc", message("xmlui.Discovery.AbstractSearch.sort_by." + sortField + "_asc"));
|
||||
sortOptions.addItem(sortField, "gear-option" + (selectedDesc ? " gear-option-selected" : "")).addXref(sortFieldParam + "desc", message("xmlui.Discovery.AbstractSearch.sort_by." + sortField + "_desc"));
|
||||
}
|
||||
}
|
||||
|
||||
// Create a control to changing ascending / descending order
|
||||
controlsItem.addContent(T_order);
|
||||
Select orderSelect = controlsItem.addSelect("order");
|
||||
|
||||
String parameterOrder = getParameterOrder();
|
||||
if(parameterOrder == null && searchSortConfiguration != null) {
|
||||
parameterOrder = searchSortConfiguration.getDefaultSortOrder().toString();
|
||||
//Add the rows per page
|
||||
sortList.addItem("rpp-head", "gear-head").addContent(T_rpp);
|
||||
org.dspace.app.xmlui.wing.element.List rppOptions = sortList.addList("rpp-selections");
|
||||
for (int i : RESULTS_PER_PAGE_PROGRESSION)
|
||||
{
|
||||
rppOptions.addItem("rpp-" + i, "gear-option" + (i == getParameterRpp() ? " gear-option-selected" : "")).addXref("rpp=" + i, Integer.toString(i));
|
||||
}
|
||||
orderSelect.addOption(SortOption.ASCENDING.equalsIgnoreCase(parameterOrder), SortOption.ASCENDING, T_order_asc);
|
||||
orderSelect.addOption(SortOption.DESCENDING.equalsIgnoreCase(parameterOrder), SortOption.DESCENDING, T_order_desc);
|
||||
|
||||
controlsItem.addButton("submit_sort").setValue(T_sort_button);
|
||||
|
||||
// Create a control for the number of authors per item to display
|
||||
// FIXME This is currently disabled, as the supporting functionality
|
||||
// is not currently present in xmlui
|
||||
//if (isItemBrowse(info))
|
||||
//{
|
||||
// controlsForm.addContent(T_etal);
|
||||
// Select etalSelect = controlsForm.addSelect(BrowseParams.ETAL);
|
||||
//
|
||||
// etalSelect.addOption((info.getEtAl() < 0), 0, T_etal_all);
|
||||
// etalSelect.addOption(1 == info.getEtAl(), 1, Integer.toString(1));
|
||||
//
|
||||
// for (int i = 5; i <= 50; i += 5)
|
||||
// {
|
||||
// etalSelect.addOption(i == info.getEtAl(), i, Integer.toString(i));
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.xmlui.aspect.discovery;
|
||||
|
||||
import org.apache.cocoon.environment.Request;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.discovery.SearchService;
|
||||
import org.dspace.utils.DSpace;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
*/
|
||||
public class DiscoveryUIUtils {
|
||||
|
||||
private static SearchService searchService = null;
|
||||
|
||||
static {
|
||||
DSpace dspace = new DSpace();
|
||||
searchService = dspace.getServiceManager().getServiceByName(SearchService.class.getName(),SearchService.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns a list of the filter queries for use in rendering pages, creating page more urls, ....
|
||||
* @return an array containing the filter queries
|
||||
*/
|
||||
public static Map<String, String[]> getParameterFilterQueries(Request request) {
|
||||
Map<String, String[]> fqs = new HashMap<String, String[]>();
|
||||
|
||||
List<String> filterTypes = getRepeatableParameters(request, "filtertype");
|
||||
List<String> filterOperators = getRepeatableParameters(request, "filter_relational_operator");
|
||||
List<String> filterValues = getRepeatableParameters(request, "filter");
|
||||
|
||||
for (int i = 0; i < filterTypes.size(); i++) {
|
||||
String filterType = filterTypes.get(i);
|
||||
String filterValue = filterValues.get(i);
|
||||
String filterOperator = filterOperators.get(i);
|
||||
|
||||
fqs.put("filtertype_" + i, new String[]{filterType});
|
||||
fqs.put("filter_relational_operator_" + i, new String[]{filterOperator});
|
||||
fqs.put("filter_" + i, new String[]{filterValue});
|
||||
}
|
||||
return fqs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the filter queries for use by discovery
|
||||
* @return an array containing the filter queries
|
||||
*/
|
||||
public static String[] getFilterQueries(Request request, Context context) {
|
||||
try {
|
||||
List<String> allFilterQueries = new ArrayList<String>();
|
||||
List<String> filterTypes = getRepeatableParameters(request, "filtertype");
|
||||
List<String> filterOperators = getRepeatableParameters(request, "filter_relational_operator");
|
||||
List<String> filterValues = getRepeatableParameters(request, "filter");
|
||||
|
||||
for (int i = 0; i < filterTypes.size(); i++) {
|
||||
String filterType = filterTypes.get(i);
|
||||
String filterOperator = filterOperators.get(i);
|
||||
String filterValue = filterValues.get(i);
|
||||
|
||||
if(StringUtils.isNotBlank(filterValue)){
|
||||
allFilterQueries.add(searchService.toFilterQuery(context, (filterType.equals("*") ? "" : filterType), filterOperator, filterValue).getFilterQuery());
|
||||
}
|
||||
}
|
||||
|
||||
return allFilterQueries.toArray(new String[allFilterQueries.size()]);
|
||||
}
|
||||
catch (RuntimeException re) {
|
||||
throw re;
|
||||
} catch (Exception e) {
|
||||
return new String[0];
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> getRepeatableParameters(Request request, String prefix){
|
||||
TreeMap<String, String> result = new TreeMap<String, String>();
|
||||
|
||||
Enumeration parameterNames = request.getParameterNames();
|
||||
while (parameterNames.hasMoreElements()) {
|
||||
String parameter = (String) parameterNames.nextElement();
|
||||
if(parameter.startsWith(prefix)){
|
||||
result.put(parameter, request.getParameter(parameter));
|
||||
}
|
||||
}
|
||||
return new ArrayList<String>(result.values());
|
||||
}
|
||||
}
|
@@ -10,20 +10,18 @@ package org.dspace.app.xmlui.aspect.discovery;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer;
|
||||
import org.dspace.app.xmlui.utils.HandleUtil;
|
||||
import org.dspace.app.xmlui.utils.UIException;
|
||||
import org.dspace.app.xmlui.wing.Message;
|
||||
import org.dspace.app.xmlui.wing.WingException;
|
||||
import org.dspace.app.xmlui.wing.element.*;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.discovery.DiscoverQuery;
|
||||
import org.dspace.discovery.DiscoverResult;
|
||||
import org.dspace.discovery.SearchUtils;
|
||||
import org.dspace.discovery.configuration.DiscoveryConfiguration;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.dspace.discovery.SearchServiceException;
|
||||
|
||||
/**
|
||||
* Displays related items to the currently viewable item
|
||||
@@ -34,23 +32,15 @@ import org.dspace.discovery.SearchServiceException;
|
||||
*/
|
||||
public class RelatedItems extends AbstractDSpaceTransformer
|
||||
{
|
||||
/**
|
||||
* Cached query results
|
||||
*/
|
||||
protected DiscoverResult queryResults;
|
||||
|
||||
private static final Message T_head = message("xmlui.Discovery.RelatedItems.head");
|
||||
private static final Message T_related_help = message("xmlui.Discovery.RelatedItems.help");
|
||||
|
||||
/**
|
||||
* Cached query arguments
|
||||
*/
|
||||
protected DiscoverQuery queryArgs;
|
||||
|
||||
private static final Logger log = Logger.getLogger(RelatedItems.class);
|
||||
|
||||
/**
|
||||
* Display a single item
|
||||
* Display items related to the given item
|
||||
*/
|
||||
public void addBody(Body body) throws SAXException, WingException,
|
||||
UIException, SQLException, IOException, AuthorizeException
|
||||
SQLException, IOException, AuthorizeException
|
||||
{
|
||||
|
||||
DSpaceObject dspaceObject = HandleUtil.obtainHandle(objectModel);
|
||||
@@ -59,109 +49,34 @@ public class RelatedItems extends AbstractDSpaceTransformer
|
||||
return;
|
||||
}
|
||||
Item item = (Item) dspaceObject;
|
||||
DiscoveryConfiguration discoveryConfiguration = SearchUtils.getDiscoveryConfiguration(item);
|
||||
|
||||
try {
|
||||
performSearch(item);
|
||||
} catch (SearchServiceException e) {
|
||||
log.error(e.getMessage(),e);
|
||||
}
|
||||
|
||||
// Build the collection viewer division.
|
||||
|
||||
|
||||
if (this.queryResults != null) {
|
||||
// TODO: develop this !
|
||||
/*
|
||||
NamedList nList = this.queryResults.getResponse();
|
||||
|
||||
SimpleOrderedMap<SolrDocumentList> mlt = (SimpleOrderedMap<SolrDocumentList>)nList.get("moreLikeThis");
|
||||
|
||||
//home.addPara(nList.toString());
|
||||
|
||||
if(mlt != null && 0 < mlt.size())
|
||||
if(discoveryConfiguration != null && discoveryConfiguration.getMoreLikeThisConfiguration() != null)
|
||||
{
|
||||
//TODO: also make sure if an item is unresolved we do not end up with an empty referenceset !
|
||||
List<DSpaceObject> dsos = new ArrayList<DSpaceObject>();
|
||||
for(Map.Entry<String,SolrDocumentList> entry : mlt)
|
||||
java.util.List<Item> relatedItems = SearchUtils.getSearchService().getRelatedItems(context, item, discoveryConfiguration.getMoreLikeThisConfiguration());
|
||||
if(CollectionUtils.isNotEmpty(relatedItems))
|
||||
{
|
||||
//org.dspace.app.xmlui.wing.element.List mltList = mltDiv.addList(key);
|
||||
Division mltDiv = body.addDivision("item-related-container").addDivision("item-related", "secondary related");
|
||||
mltDiv.setHead(T_head);
|
||||
|
||||
//mltList.setHead(key);
|
||||
|
||||
for(SolrDocument doc : entry.getValue())
|
||||
{
|
||||
try{
|
||||
dsos.add(SearchUtils.findDSpaceObject(context, doc));
|
||||
}catch(Exception e){
|
||||
log.error(LogManager.getHeader(context, "Error while resolving related item doc to dso", "Main item: " + item.getID()));
|
||||
}
|
||||
//mltList.addItem().addContent(doc.toString());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if(0 < dsos.size()){
|
||||
Division home = body.addDivision("test", "secondary related");
|
||||
|
||||
String name = "Related Items";
|
||||
|
||||
//if (name == null || name.length() == 0)
|
||||
// home.setHead(T_untitled);
|
||||
//else
|
||||
home.setHead(name);
|
||||
|
||||
Division mltDiv = home.addDivision("item-related", "secondary related");
|
||||
|
||||
mltDiv.setHead("Items By Author:");
|
||||
mltDiv.addPara(T_related_help);
|
||||
|
||||
ReferenceSet set = mltDiv.addReferenceSet(
|
||||
"item-related-items", ReferenceSet.TYPE_SUMMARY_LIST,
|
||||
null, "related-items");
|
||||
|
||||
for (DSpaceObject dso : dsos) {
|
||||
for (DSpaceObject dso : relatedItems)
|
||||
{
|
||||
set.addReference(dso);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void performSearch(DSpaceObject dso) throws SearchServiceException {
|
||||
|
||||
if(queryResults != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
/*
|
||||
this.queryArgs = getQueryArgs(getView());
|
||||
this.queryArgs.setMaxResults(1);
|
||||
this.queryArgs.add("fl","author,handle");
|
||||
this.queryArgs.add("mlt","true");
|
||||
this.queryArgs.add("mlt.fl","author,handle");
|
||||
this.queryArgs.add("mlt.mindf","1");
|
||||
this.queryArgs.add("mlt.mintf","1");
|
||||
this.queryArgs.setQuery("handle:" + dso.getHandle());
|
||||
this.queryArgs.setRows(1);
|
||||
*/
|
||||
//queryResults = SearchUtils.getSearchService().search(context, queryArgs);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public String getView()
|
||||
{
|
||||
return "item";
|
||||
}
|
||||
|
||||
/**
|
||||
* Recycle
|
||||
*/
|
||||
public void recycle() {
|
||||
this.queryArgs = null;
|
||||
this.queryResults = null;
|
||||
super.recycle();
|
||||
}
|
||||
}
|
||||
|
@@ -27,13 +27,10 @@ import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.discovery.*;
|
||||
import org.dspace.discovery.configuration.DiscoveryConfiguration;
|
||||
import org.dspace.discovery.configuration.DiscoveryConfigurationParameters;
|
||||
import org.dspace.discovery.configuration.SidebarFacetConfiguration;
|
||||
import org.dspace.handle.HandleManager;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.utils.DSpace;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
@@ -77,15 +74,12 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
|
||||
private int DEFAULT_PAGE_SIZE = 10;
|
||||
|
||||
|
||||
private ConfigurationService config = null;
|
||||
|
||||
private SearchService searchService = null;
|
||||
private static final Message T_go = message("xmlui.general.go");
|
||||
|
||||
public SearchFacetFilter() {
|
||||
|
||||
DSpace dspace = new DSpace();
|
||||
config = dspace.getConfigurationService();
|
||||
searchService = dspace.getServiceManager().getServiceByName(SearchService.class.getName(),SearchService.class);
|
||||
|
||||
}
|
||||
@@ -146,7 +140,7 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
|
||||
|
||||
java.util.List<DiscoverResult.FacetResult> facetValues = queryResults.getFacetResults().get(facetField);
|
||||
for (DiscoverResult.FacetResult facetValue : facetValues) {
|
||||
validity.add(facetValue.getAsFilterQuery() + facetValue.getCount());
|
||||
validity.add(facetField + facetValue.getAsFilterQuery() + facetValue.getCount());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,7 +185,7 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
|
||||
|
||||
queryArgs.setMaxResults(0);
|
||||
|
||||
queryArgs.addFilterQueries(getDiscoveryFilterQueries());
|
||||
queryArgs.addFilterQueries(DiscoveryUIUtils.getFilterQueries(request, context));
|
||||
|
||||
|
||||
//Set the default limit to 11
|
||||
@@ -317,11 +311,7 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
|
||||
|
||||
Table singleTable = results.addTable("browse-by-" + facetField + "-results", (int) (queryResults.getDspaceObjects().size() + 1), 1);
|
||||
|
||||
List<String> filterQueries = new ArrayList<String>();
|
||||
if(request.getParameterValues("fq") != null)
|
||||
{
|
||||
filterQueries = Arrays.asList(request.getParameterValues("fq"));
|
||||
}
|
||||
List<String> filterQueries = Arrays.asList(DiscoveryUIUtils.getFilterQueries(request, context));
|
||||
|
||||
|
||||
int end = values.size();
|
||||
@@ -341,7 +331,7 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
|
||||
}
|
||||
|
||||
private void addBrowseJumpNavigation(Division div, SearchFilterParam browseParams, Request request)
|
||||
throws WingException, SQLException {
|
||||
throws WingException, SQLException, UnsupportedEncodingException {
|
||||
String action;
|
||||
DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
|
||||
if(dso != null){
|
||||
@@ -359,9 +349,14 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
|
||||
for(Map.Entry<String, String> param : params.entrySet()){
|
||||
jump.addHidden(param.getKey()).setValue(param.getValue());
|
||||
}
|
||||
String[] filterQueries = getParameterFilterQueries();
|
||||
for (String filterQuery : filterQueries) {
|
||||
jump.addHidden("fq").setValue(filterQuery);
|
||||
Map<String, String[]> filterQueries = DiscoveryUIUtils.getParameterFilterQueries(request);
|
||||
for (String parameter : filterQueries.keySet())
|
||||
{
|
||||
for (int i = 0; i < filterQueries.get(parameter).length; i++)
|
||||
{
|
||||
String value = filterQueries.get(parameter)[i];
|
||||
jump.addHidden(parameter).setValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
//We cannot create a filter for dates
|
||||
@@ -394,7 +389,6 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
|
||||
|
||||
private void renderFacetField(SearchFilterParam browseParams, DSpaceObject dso, String facetField, Table singleTable, List<String> filterQueries, DiscoverResult.FacetResult value) throws SQLException, WingException, UnsupportedEncodingException {
|
||||
String displayedValue = value.getDisplayedValue();
|
||||
String filterQuery = value.getAsFilterQuery();
|
||||
// if(field.getGap() != null){
|
||||
// //We have a date get the year so we can display it
|
||||
// DateFormat simpleDateformat = new SimpleDateFormat("yyyy");
|
||||
@@ -405,7 +399,7 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
|
||||
Cell cell = singleTable.addRow().addCell();
|
||||
|
||||
//No use in selecting the same filter twice
|
||||
if(filterQueries.contains(filterQuery)){
|
||||
if(filterQueries.contains(searchService.toFilterQuery(context, facetField, "equals", displayedValue).getFilterQuery())){
|
||||
cell.addContent(displayedValue + " (" + value.getCount() + ")");
|
||||
} else {
|
||||
//Add the basics
|
||||
@@ -415,13 +409,15 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
|
||||
//Add already existing filter queries
|
||||
url = addFilterQueriesToUrl(url);
|
||||
//Last add the current filter query
|
||||
url += "&fq=" + URLEncoder.encode(filterQuery, "UTF-8");
|
||||
url += "&filtertype=" + facetField;
|
||||
url += "&filter_relational_operator=equals";
|
||||
url += "&filter=" + URLEncoder.encode(displayedValue, "UTF-8");
|
||||
cell.addXref(url, displayedValue + " (" + value.getCount() + ")"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private String getNextPageURL(SearchFilterParam browseParams, Request request) {
|
||||
private String getNextPageURL(SearchFilterParam browseParams, Request request) throws UnsupportedEncodingException, UIException {
|
||||
int offSet = Util.getIntParameter(request, SearchFilterParam.OFFSET);
|
||||
if (offSet == -1)
|
||||
{
|
||||
@@ -433,7 +429,6 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
|
||||
parameters.putAll(browseParams.getControlParameters());
|
||||
parameters.put(SearchFilterParam.OFFSET, String.valueOf(offSet + DEFAULT_PAGE_SIZE));
|
||||
|
||||
//TODO: correct comm/collection url
|
||||
// Add the filter queries
|
||||
String url = generateURL("search-filter", parameters);
|
||||
url = addFilterQueriesToUrl(url);
|
||||
@@ -441,7 +436,7 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
|
||||
return url;
|
||||
}
|
||||
|
||||
private String getPreviousPageURL(SearchFilterParam browseParams, Request request) {
|
||||
private String getPreviousPageURL(SearchFilterParam browseParams, Request request) throws UnsupportedEncodingException, UIException {
|
||||
//If our offset should be 0 then we shouldn't be able to view a previous page url
|
||||
if (0 == queryArgs.getFacetOffset() && Util.getIntParameter(request, "offset") == -1)
|
||||
{
|
||||
@@ -459,7 +454,6 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
|
||||
parameters.putAll(browseParams.getControlParameters());
|
||||
parameters.put(SearchFilterParam.OFFSET, String.valueOf(offset - DEFAULT_PAGE_SIZE));
|
||||
|
||||
//TODO: correct comm/collection url
|
||||
// Add the filter queries
|
||||
String url = generateURL("search-filter", parameters);
|
||||
url = addFilterQueriesToUrl(url);
|
||||
@@ -477,74 +471,25 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
|
||||
super.recycle();
|
||||
}
|
||||
|
||||
public String addFilterQueriesToUrl(String url){
|
||||
String[] fqs = getParameterFilterQueries();
|
||||
if (fqs != null) {
|
||||
public String addFilterQueriesToUrl(String url) throws UIException {
|
||||
Map<String, String[]> fqs = DiscoveryUIUtils.getParameterFilterQueries(ObjectModelHelper.getRequest(objectModel));
|
||||
if (fqs != null)
|
||||
{
|
||||
StringBuilder urlBuilder = new StringBuilder(url);
|
||||
for (String fq : fqs) {
|
||||
urlBuilder.append("&fq=").append(fq);
|
||||
for (String parameter : fqs.keySet())
|
||||
{
|
||||
for (int i = 0; i < fqs.get(parameter).length; i++)
|
||||
{
|
||||
String value = fqs.get(parameter)[i];
|
||||
urlBuilder.append("&").append(parameter).append("=").append(encodeForURL(value));
|
||||
}
|
||||
}
|
||||
|
||||
return urlBuilder.toString();
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
|
||||
protected String[] getParameterFilterQueries() {
|
||||
Request request = ObjectModelHelper.getRequest(objectModel);
|
||||
java.util.List<String> fqs = new ArrayList<String>();
|
||||
if(request.getParameterValues("fq") != null)
|
||||
{
|
||||
fqs.addAll(Arrays.asList(request.getParameterValues("fq")));
|
||||
}
|
||||
|
||||
//Have we added a filter using the UI
|
||||
if(request.getParameter("filter") != null && !"".equals(request.getParameter("filter")))
|
||||
{
|
||||
fqs.add((request.getParameter("filtertype").equals("*") ? "" : request.getParameter("filtertype") + ":") + request.getParameter("filter"));
|
||||
}
|
||||
return fqs.toArray(new String[fqs.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the filter queries for use by discovery
|
||||
* This method returns more expanded filter queries then the getParameterFilterQueries
|
||||
* @return an array containing the filter queries
|
||||
*/
|
||||
protected String[] getDiscoveryFilterQueries() {
|
||||
try {
|
||||
java.util.List<String> allFilterQueries = new ArrayList<String>();
|
||||
Request request = ObjectModelHelper.getRequest(objectModel);
|
||||
java.util.List<String> fqs = new ArrayList<String>();
|
||||
|
||||
if(request.getParameterValues("fq") != null)
|
||||
{
|
||||
fqs.addAll(Arrays.asList(request.getParameterValues("fq")));
|
||||
}
|
||||
|
||||
String type = request.getParameter("filtertype");
|
||||
String value = request.getParameter("filter");
|
||||
|
||||
if(value != null && !value.equals("")){
|
||||
allFilterQueries.add(searchService.toFilterQuery(context, (type.equals("*") ? "" : type), value).getFilterQuery());
|
||||
}
|
||||
|
||||
//Add all the previous filters also
|
||||
for (String fq : fqs) {
|
||||
allFilterQueries.add(searchService.toFilterQuery(context, fq).getFilterQuery());
|
||||
}
|
||||
|
||||
return allFilterQueries.toArray(new String[allFilterQueries.size()]);
|
||||
}
|
||||
catch (RuntimeException re) {
|
||||
throw re;
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static class SearchFilterParam {
|
||||
private Request request;
|
||||
|
||||
|
@@ -11,6 +11,7 @@ import org.apache.cocoon.caching.CacheableProcessingComponent;
|
||||
import org.apache.cocoon.environment.ObjectModelHelper;
|
||||
import org.apache.cocoon.environment.Request;
|
||||
import org.apache.cocoon.util.HashUtil;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.excalibur.source.SourceValidity;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer;
|
||||
@@ -28,14 +29,14 @@ import org.dspace.core.LogManager;
|
||||
import org.dspace.discovery.*;
|
||||
import org.dspace.discovery.configuration.DiscoveryConfiguration;
|
||||
import org.dspace.discovery.configuration.DiscoveryConfigurationParameters;
|
||||
import org.dspace.discovery.configuration.SidebarFacetConfiguration;
|
||||
import org.dspace.discovery.configuration.DiscoverySearchFilterFacet;
|
||||
import org.dspace.handle.HandleManager;
|
||||
import org.dspace.utils.DSpace;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.net.URLEncoder;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
@@ -134,7 +135,7 @@ public class SidebarFacetsTransformer extends AbstractDSpaceTransformer implemen
|
||||
|
||||
java.util.List<DiscoverResult.FacetResult> facetValues = queryResults.getFacetResults().get(facetField);
|
||||
for (DiscoverResult.FacetResult facetValue : facetValues) {
|
||||
val.add(facetValue.getAsFilterQuery() + facetValue.getCount());
|
||||
val.add(facetField + facetValue.getAsFilterQuery() + facetValue.getCount());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,9 +152,9 @@ public class SidebarFacetsTransformer extends AbstractDSpaceTransformer implemen
|
||||
|
||||
public void performSearch() throws SearchServiceException, UIException, SQLException {
|
||||
DSpaceObject dso = getScope();
|
||||
queryArgs = getQueryArgs(context, dso, getAllFilterQueries());
|
||||
//If we are on a search page performing a search a query may be used
|
||||
Request request = ObjectModelHelper.getRequest(objectModel);
|
||||
queryArgs = getQueryArgs(context, dso, DiscoveryUIUtils.getFilterQueries(request, context));
|
||||
//If we are on a search page performing a search a query may be used
|
||||
String query = request.getParameter("query");
|
||||
if(query != null && !"".equals(query)){
|
||||
queryArgs.setQuery(query);
|
||||
@@ -179,22 +180,16 @@ public class SidebarFacetsTransformer extends AbstractDSpaceTransformer implemen
|
||||
|
||||
if (this.queryResults != null) {
|
||||
DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
|
||||
java.util.List<String> fqs = new ArrayList<String>();
|
||||
if(request.getParameterValues("fq") != null){
|
||||
for (int i = 0; i < request.getParameterValues("fq").length; i++) {
|
||||
String fq = request.getParameterValues("fq")[i];
|
||||
fqs.add(getSearchService().toFilterQuery(context, fq).getFilterQuery());
|
||||
}
|
||||
}
|
||||
java.util.List<String> fqs = Arrays.asList(DiscoveryUIUtils.getFilterQueries(request, context));
|
||||
|
||||
DiscoveryConfiguration discoveryConfiguration = SearchUtils.getDiscoveryConfiguration(dso);
|
||||
java.util.List<SidebarFacetConfiguration> facets = discoveryConfiguration.getSidebarFacets();
|
||||
java.util.List<DiscoverySearchFilterFacet> facets = discoveryConfiguration.getSidebarFacets();
|
||||
|
||||
if (facets != null && 0 < facets.size()) {
|
||||
|
||||
List browse = null;
|
||||
|
||||
for (SidebarFacetConfiguration field : facets) {
|
||||
for (DiscoverySearchFilterFacet field : facets) {
|
||||
//Retrieve our values
|
||||
java.util.List<DiscoverResult.FacetResult> facetValues = queryResults.getFacetResult(field.getIndexFieldName());
|
||||
//Check if we are dealing with a date, sometimes the facet values arrive as dates !
|
||||
@@ -224,6 +219,10 @@ public class SidebarFacetsTransformer extends AbstractDSpaceTransformer implemen
|
||||
|
||||
if (!iter.hasNext())
|
||||
{
|
||||
//When we have an hierarchical facet always show the view more they may want to filter the children of the top nodes
|
||||
if(field.getType().equals(DiscoveryConfigurationParameters.TYPE_HIERARCHICAL)){
|
||||
addViewMoreUrl(filterValsList, dso, request, field.getIndexFieldName());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -233,7 +232,7 @@ public class SidebarFacetsTransformer extends AbstractDSpaceTransformer implemen
|
||||
String displayedValue = value.getDisplayedValue();
|
||||
String filterQuery = value.getAsFilterQuery();
|
||||
|
||||
if (fqs.contains(filterQuery)) {
|
||||
if (fqs.contains(getSearchService().toFilterQuery(context, field.getIndexFieldName(), "equals", value.getDisplayedValue()).getFilterQuery())) {
|
||||
filterValsList.addItem(Math.random() + "", "selected").addContent(displayedValue + " (" + value.getCount() + ")");
|
||||
} else {
|
||||
String paramsQuery = retrieveParameters(request);
|
||||
@@ -243,15 +242,15 @@ public class SidebarFacetsTransformer extends AbstractDSpaceTransformer implemen
|
||||
(dso == null ? "" : "/handle/" + dso.getHandle()) +
|
||||
"/discover?" +
|
||||
paramsQuery +
|
||||
"fq=" +
|
||||
URLEncoder.encode(filterQuery, "UTF-8"),
|
||||
"filtertype=" + field.getIndexFieldName() +
|
||||
"&filter_relational_operator=equals" +
|
||||
"&filter=" + encodeForURL(filterQuery),
|
||||
displayedValue + " (" + value.getCount() + ")"
|
||||
);
|
||||
}
|
||||
}
|
||||
//Show a view more url should there be more values, unless we have a date
|
||||
if (i == shownFacets - 1 && !field.getType().equals(DiscoveryConfigurationParameters.TYPE_DATE)/*&& facetField.getGap() == null*/) {
|
||||
|
||||
addViewMoreUrl(filterValsList, dso, request, field.getIndexFieldName());
|
||||
}
|
||||
}
|
||||
@@ -266,26 +265,42 @@ public class SidebarFacetsTransformer extends AbstractDSpaceTransformer implemen
|
||||
* @param request the cocoon request
|
||||
* @return the parameters used on this page
|
||||
*/
|
||||
private String retrieveParameters(Request request) {
|
||||
StringBuffer result = new StringBuffer();
|
||||
Enumeration keys = request.getParameterNames();
|
||||
if(keys != null){
|
||||
while (keys.hasMoreElements()){
|
||||
String key = (String) keys.nextElement();
|
||||
//Ignore the page and submit button keys
|
||||
if(key != null && !"page".equals(key) && !key.startsWith("submit")){
|
||||
String[] vals = request.getParameterValues(key);
|
||||
for(String paramValue : vals){
|
||||
result.append(key).append("=").append(paramValue);
|
||||
result.append("&");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
private String retrieveParameters(Request request) throws UnsupportedEncodingException, UIException {
|
||||
java.util.List<String> parameters = new ArrayList<String>();
|
||||
if(StringUtils.isNotBlank(request.getParameter("query"))){
|
||||
parameters.add("query=" + encodeForURL(request.getParameter("query")));
|
||||
}
|
||||
|
||||
private void addViewMoreUrl(List facet, DSpaceObject dso, Request request, String fieldName) throws WingException {
|
||||
if(StringUtils.isNotBlank(request.getParameter("scope"))){
|
||||
parameters.add("scope=" + request.getParameter("scope"));
|
||||
}
|
||||
if(StringUtils.isNotBlank(request.getParameter("sort_by"))){
|
||||
parameters.add("sort_by=" + request.getParameter("sort_by"));
|
||||
}
|
||||
if(StringUtils.isNotBlank(request.getParameter("order"))){
|
||||
parameters.add("order=" + request.getParameter("order"));
|
||||
}
|
||||
if(StringUtils.isNotBlank(request.getParameter("rpp"))){
|
||||
parameters.add("rpp=" + request.getParameter("rpp"));
|
||||
}
|
||||
|
||||
Map<String, String[]> parameterFilterQueries = DiscoveryUIUtils.getParameterFilterQueries(request);
|
||||
for(String parameter : parameterFilterQueries.keySet()){
|
||||
for (int i = 0; i < parameterFilterQueries.get(parameter).length; i++) {
|
||||
String value = parameterFilterQueries.get(parameter)[i];
|
||||
parameters.add(parameter + "=" + encodeForURL(value));
|
||||
}
|
||||
|
||||
}
|
||||
//Join all our parameters by using an "&" sign
|
||||
String parametersString = StringUtils.join(parameters.toArray(new String[parameters.size()]), "&");
|
||||
if(StringUtils.isNotEmpty(parametersString)){
|
||||
parametersString += "&";
|
||||
}
|
||||
return parametersString;
|
||||
}
|
||||
|
||||
private void addViewMoreUrl(List facet, DSpaceObject dso, Request request, String fieldName) throws WingException, UnsupportedEncodingException {
|
||||
String parameters = retrieveParameters(request);
|
||||
facet.addItem().addXref(
|
||||
contextPath +
|
||||
@@ -300,7 +315,7 @@ public class SidebarFacetsTransformer extends AbstractDSpaceTransformer implemen
|
||||
DiscoverQuery queryArgs = new DiscoverQuery();
|
||||
|
||||
DiscoveryConfiguration discoveryConfiguration = SearchUtils.getDiscoveryConfiguration(scope);
|
||||
java.util.List<SidebarFacetConfiguration> facets = discoveryConfiguration.getSidebarFacets();
|
||||
java.util.List<DiscoverySearchFilterFacet> facets = discoveryConfiguration.getSidebarFacets();
|
||||
|
||||
log.info("facets for scope, " + scope + ": " + (facets != null ? facets.size() : null));
|
||||
|
||||
@@ -317,7 +332,7 @@ public class SidebarFacetsTransformer extends AbstractDSpaceTransformer implemen
|
||||
|
||||
/** enable faceting of search results */
|
||||
if (facets != null){
|
||||
for (SidebarFacetConfiguration facet : facets) {
|
||||
for (DiscoverySearchFilterFacet facet : facets) {
|
||||
if(facet.getType().equals(DiscoveryConfigurationParameters.TYPE_DATE)){
|
||||
String dateFacet = facet.getIndexFieldName() + ".year";
|
||||
try{
|
||||
@@ -447,50 +462,13 @@ public class SidebarFacetsTransformer extends AbstractDSpaceTransformer implemen
|
||||
int facetLimit = facet.getFacetLimit();
|
||||
//Add one to our facet limit to make sure that if we have more then the shown facets that we show our show more url
|
||||
facetLimit++;
|
||||
queryArgs.addFacetField(new DiscoverFacetField(facet.getIndexFieldName(), DiscoveryConfigurationParameters.TYPE_TEXT, facetLimit, facet.getSortOrder()));
|
||||
queryArgs.addFacetField(new DiscoverFacetField(facet.getIndexFieldName(), facet.getType(), facetLimit, facet.getSortOrder()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return queryArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the filter queries for use by discovery
|
||||
* This method returns more expanded filter queries then the getParameterFilterQueries
|
||||
* @return an array containing the filter queries
|
||||
*/
|
||||
protected String[] getAllFilterQueries() {
|
||||
try {
|
||||
java.util.List<String> allFilterQueries = new ArrayList<String>();
|
||||
Request request = ObjectModelHelper.getRequest(objectModel);
|
||||
java.util.List<String> fqs = new ArrayList<String>();
|
||||
|
||||
if(request.getParameterValues("fq") != null)
|
||||
{
|
||||
fqs.addAll(Arrays.asList(request.getParameterValues("fq")));
|
||||
}
|
||||
|
||||
String type = request.getParameter("filtertype");
|
||||
String value = request.getParameter("filter");
|
||||
|
||||
if(value != null && !value.equals("")){
|
||||
allFilterQueries.add(getSearchService().toFilterQuery(context, (type.equals("*") ? "" : type), value).getFilterQuery());
|
||||
}
|
||||
|
||||
//Add all the previous filters also
|
||||
for (String fq : fqs) {
|
||||
allFilterQueries.add(getSearchService().toFilterQuery(context, fq).getFilterQuery());
|
||||
}
|
||||
|
||||
return allFilterQueries.toArray(new String[allFilterQueries.size()]);
|
||||
}
|
||||
catch (RuntimeException re) {
|
||||
throw re;
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the current scope. This may be derived from the current url
|
||||
* handle if present or the scope parameter is given. If no scope is
|
||||
|
@@ -10,12 +10,11 @@ package org.dspace.app.xmlui.aspect.discovery;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.cocoon.caching.CacheableProcessingComponent;
|
||||
import org.apache.cocoon.environment.ObjectModelHelper;
|
||||
import org.apache.cocoon.environment.Request;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer;
|
||||
import org.dspace.app.xmlui.utils.HandleUtil;
|
||||
import org.dspace.app.xmlui.utils.UIException;
|
||||
@@ -55,21 +54,24 @@ public class SimpleSearch extends AbstractSearch implements CacheableProcessingC
|
||||
message("xmlui.ArtifactBrowser.SimpleSearch.trail");
|
||||
|
||||
private static final Message T_search_scope =
|
||||
message("xmlui.ArtifactBrowser.SimpleSearch.search_scope");
|
||||
message("xmlui.Discovery.SimpleSearch.search_scope");
|
||||
|
||||
private static final Message T_head =
|
||||
message("xmlui.ArtifactBrowser.SimpleSearch.head");
|
||||
|
||||
private static final Message T_search_label =
|
||||
message("xmlui.discovery.SimpleSearch.search_label");
|
||||
// private static final Message T_search_label =
|
||||
// message("xmlui.discovery.SimpleSearch.search_label");
|
||||
|
||||
private static final Message T_go =
|
||||
message("xmlui.general.go");
|
||||
private static final Message T_go = message("xmlui.general.go");
|
||||
private static final Message T_filter_label = message("xmlui.Discovery.SimpleSearch.filter_head");
|
||||
private static final Message T_filter_help = message("xmlui.Discovery.SimpleSearch.filter_help");
|
||||
private static final Message T_add_filter = message("xmlui.Discovery.SimpleSearch.filter_add");
|
||||
private static final Message T_filter_apply = message("xmlui.Discovery.SimpleSearch.filter_apply");
|
||||
private static final Message T_FILTERS_SELECTED = message("xmlui.ArtifactBrowser.SimpleSearch.filter.selected");
|
||||
private static final String T_filter_new_filters = "xmlui.Discovery.AbstractSearch.filters.controls.new-filters.head";
|
||||
private static final Message T_filter_controls_apply = message("xmlui.Discovery.AbstractSearch.filters.controls.apply-filters");
|
||||
private static final Message T_filter_controls_add = message("xmlui.Discovery.AbstractSearch.filters.controls.add-filter");
|
||||
private static final Message T_filter_controls_remove = message("xmlui.Discovery.AbstractSearch.filters.controls.remove-filter");
|
||||
private static final Message T_filters_show = message("xmlui.Discovery.AbstractSearch.filters.display");
|
||||
private static final Message T_filter_contain = message("xmlui.Discovery.SimpleSearch.filter.contains");
|
||||
private static final Message T_filter_equals = message("xmlui.Discovery.SimpleSearch.filter.equals");
|
||||
|
||||
private SearchService searchService = null;
|
||||
|
||||
@@ -117,15 +119,18 @@ public class SimpleSearch extends AbstractSearch implements CacheableProcessingC
|
||||
}
|
||||
search.addHidden("contextpath").setValue(contextPath);
|
||||
|
||||
String[] fqs = getFilterQueries();
|
||||
Map<String, String[]> fqs = getParameterFilterQueries();
|
||||
|
||||
Division mainSearchDiv = search.addInteractiveDivision("general-query",
|
||||
"discover", Division.METHOD_GET, "discover-search-box search");
|
||||
Division searchBoxDivision = search.addDivision("discovery-search-box", "discoverySearchBox");
|
||||
|
||||
Division mainSearchDiv = searchBoxDivision.addInteractiveDivision("general-query",
|
||||
"discover", Division.METHOD_GET, "discover-search-box");
|
||||
|
||||
List searchList = mainSearchDiv.addList("primary-search", List.TYPE_FORM);
|
||||
|
||||
searchList.setHead(T_search_label);
|
||||
if (variableScope()) {
|
||||
// searchList.setHead(T_search_label);
|
||||
if (variableScope())
|
||||
{
|
||||
Select scope = searchList.addItem().addSelect("scope");
|
||||
scope.setLabel(T_search_scope);
|
||||
buildScopeList(scope);
|
||||
@@ -134,106 +139,74 @@ public class SimpleSearch extends AbstractSearch implements CacheableProcessingC
|
||||
Item searchBoxItem = searchList.addItem();
|
||||
Text text = searchBoxItem.addText("query");
|
||||
text.setValue(queryString);
|
||||
text.setSize(75);
|
||||
searchBoxItem.addButton("submit").setValue(T_go);
|
||||
addHiddenFormFields("search", request, fqs, mainSearchDiv);
|
||||
|
||||
searchBoxItem.addButton("submit", "search-icon").setValue(T_go);
|
||||
|
||||
DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
|
||||
DiscoveryConfiguration discoveryConfiguration = SearchUtils.getDiscoveryConfiguration(dso);
|
||||
java.util.List<DiscoverySearchFilter> filterFields = discoveryConfiguration.getSearchFilters();
|
||||
if(0 < fqs.length || 0 < filterFields.size()){
|
||||
Division searchFiltersDiv = search.addInteractiveDivision("search-filters",
|
||||
"discover", Division.METHOD_GET, "discover-search-box search");
|
||||
java.util.List<String> filterTypes = DiscoveryUIUtils.getRepeatableParameters(request, "filtertype");
|
||||
java.util.List<String> filterOperators = DiscoveryUIUtils.getRepeatableParameters(request, "filter_relational_operator");
|
||||
java.util.List<String> filterValues = DiscoveryUIUtils.getRepeatableParameters(request, "filter");
|
||||
|
||||
List secondarySearchList = searchFiltersDiv.addList("secondary-search", List.TYPE_FORM);
|
||||
secondarySearchList.setHead(T_filter_label);
|
||||
if(0 < filterFields.size() && filterTypes.size() == 0)
|
||||
{
|
||||
//Display the add filters url ONLY if we have no filters selected & fitlers can be added
|
||||
searchList.addItem().addXref("display-filters", T_filters_show);
|
||||
}
|
||||
addHiddenFormFields("search", request, fqs, mainSearchDiv);
|
||||
|
||||
|
||||
if(0 < filterFields.size())
|
||||
{
|
||||
Division searchFiltersDiv = searchBoxDivision.addInteractiveDivision("search-filters",
|
||||
"discover", Division.METHOD_GET, "discover-filters-box " + (0 < filterTypes.size() ? "" : "hidden"));
|
||||
|
||||
Division filtersWrapper = searchFiltersDiv.addDivision("discovery-filters-wrapper");
|
||||
filtersWrapper.setHead(T_filter_label);
|
||||
filtersWrapper.addPara(T_filter_help);
|
||||
Table filtersTable = filtersWrapper.addTable("discovery-filters", 1, 4, "discovery-filters");
|
||||
|
||||
|
||||
// queryList.addItem().addContent("Filters");
|
||||
//If we have any filters, show them
|
||||
if(fqs.length > 0){
|
||||
//if(filters != null && filters.size() > 0){
|
||||
Item item = secondarySearchList.addItem("used-filters", "used-filters-list");
|
||||
if(filterTypes.size() > 0)
|
||||
{
|
||||
|
||||
for (int i = 0; i < filterTypes.size(); i++)
|
||||
{
|
||||
String filterType = filterTypes.get(i);
|
||||
String filterValue = filterValues.get(i);
|
||||
String filterOperator = filterOperators.get(i);
|
||||
|
||||
// Composite composite = item.addComposite("facet-controls");
|
||||
|
||||
// composite.setLabel(T_FILTERS_SELECTED);
|
||||
|
||||
|
||||
for (int i = 0; i < fqs.length; i++) {
|
||||
String filterQuery = fqs[i];
|
||||
DiscoverFilterQuery fq = searchService.toFilterQuery(context, filterQuery);
|
||||
|
||||
// CheckBox box = item.addCheckBox("fq");
|
||||
CheckBox box = item.addCheckBox("fq");
|
||||
if(i == 0){
|
||||
box.setLabel(T_FILTERS_SELECTED);
|
||||
if(StringUtils.isNotBlank(filterValue))
|
||||
{
|
||||
Row row = filtersTable.addRow("used-filters-" + i, Row.ROLE_DATA, "search-filter used-filter");
|
||||
addFilterRow(filterFields, i, row, filterType, filterOperator, filterValue);
|
||||
}
|
||||
Option option = box.addOption(true, fq.getFilterQuery());
|
||||
String field = fq.getField();
|
||||
option.addContent(message("xmlui.ArtifactBrowser.SimpleSearch.filter." + field));
|
||||
|
||||
//We have a filter query get the display value
|
||||
//Check for a range query
|
||||
Pattern pattern = Pattern.compile("\\[(.*? TO .*?)\\]");
|
||||
Matcher matcher = pattern.matcher(fq.getDisplayedValue());
|
||||
boolean hasPattern = matcher.find();
|
||||
if (hasPattern) {
|
||||
String[] years = matcher.group(0).replace("[", "").replace("]", "").split(" TO ");
|
||||
option.addContent(": " + years[0] + " - " + years[1]);
|
||||
continue;
|
||||
}
|
||||
|
||||
option.addContent(": " + fq.getDisplayedValue());
|
||||
}
|
||||
secondarySearchList.addItem().addButton("submit_update_filters", "update-filters").setValue(T_filter_apply);
|
||||
filtersTable.addRow(Row.ROLE_HEADER).addCell("", Cell.ROLE_HEADER, 1, 4, "new-filter-header").addContent(message(T_filter_new_filters));
|
||||
}
|
||||
|
||||
|
||||
int index = filterTypes.size() + 1;
|
||||
Row row = filtersTable.addRow("filter-new-" + index, Row.ROLE_DATA, "search-filter");
|
||||
|
||||
if(0 < filterFields.size()){
|
||||
//We have at least one filter so add our filter box
|
||||
Item item = secondarySearchList.addItem("search-filter-list", "search-filter-list");
|
||||
Composite filterComp = item.addComposite("search-filter-controls");
|
||||
filterComp.setLabel(T_add_filter);
|
||||
filterComp.setHelp(T_filter_help);
|
||||
addFilterRow(filterFields, index, row, null, null, null);
|
||||
|
||||
// filterComp.setLabel("");
|
||||
|
||||
Select select = filterComp.addSelect("filtertype");
|
||||
|
||||
//For each field found (at least one) add options
|
||||
for (DiscoverySearchFilter searchFilter : filterFields) {
|
||||
select.addOption(searchFilter.getIndexFieldName(), message("xmlui.ArtifactBrowser.SimpleSearch.filter." + searchFilter.getIndexFieldName()));
|
||||
}
|
||||
|
||||
//Add a box so we can search for our value
|
||||
filterComp.addText("filter").setSize(30);
|
||||
|
||||
//And last add an add button
|
||||
filterComp.enableAddOperation();
|
||||
}
|
||||
Row filterControlsItem = filtersTable.addRow("filter-controls", Row.ROLE_DATA, "apply-filter");
|
||||
filterControlsItem.addCell(1, 3).addContent("");
|
||||
filterControlsItem.addCell().addButton("submit_apply_filter", "discovery-apply-filter-button").setValue(T_filter_controls_apply);
|
||||
|
||||
addHiddenFormFields("filter", request, fqs, searchFiltersDiv);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Division searchControlsDiv = search.addInteractiveDivision("search-controls",
|
||||
"discover", Division.METHOD_GET, "discover-sort-box search");
|
||||
|
||||
buildSearchControls(searchControlsDiv);
|
||||
addHiddenFormFields("sort", request, fqs, searchControlsDiv);
|
||||
|
||||
|
||||
// query.addPara(null, "button-list").addButton("submit").setValue(T_go);
|
||||
|
||||
// Build the DRI Body
|
||||
//Division results = body.addDivision("results", "primary");
|
||||
//results.setHead(T_head);
|
||||
buildMainForm(search);
|
||||
|
||||
// Add the result division
|
||||
try {
|
||||
@@ -244,61 +217,49 @@ public class SimpleSearch extends AbstractSearch implements CacheableProcessingC
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of the filter queries for use in rendering pages, creating page more urls, ....
|
||||
* @return an array containing the filter queries
|
||||
*/
|
||||
protected String[] getParameterFilterQueries() {
|
||||
protected void addFilterRow(java.util.List<DiscoverySearchFilter> filterFields, int index, Row row, String selectedFilterType, String relationalOperator, String value) throws WingException {
|
||||
Select select = row.addCell("", Cell.ROLE_DATA, "selection").addSelect("filtertype_" + index);
|
||||
|
||||
//For each field found (at least one) add options
|
||||
for (DiscoverySearchFilter searchFilter : filterFields)
|
||||
{
|
||||
select.addOption(StringUtils.equals(searchFilter.getIndexFieldName(), selectedFilterType), searchFilter.getIndexFieldName(), message("xmlui.ArtifactBrowser.SimpleSearch.filter." + searchFilter.getIndexFieldName()));
|
||||
}
|
||||
Select typeSelect = row.addCell("", Cell.ROLE_DATA, "selection").addSelect("filter_relational_operator_" + index);
|
||||
typeSelect.addOption(StringUtils.equals(relationalOperator, "contains"), "contains", T_filter_contain);
|
||||
typeSelect.addOption(StringUtils.equals(relationalOperator, "equals"), "equals", T_filter_equals);
|
||||
|
||||
|
||||
|
||||
//Add a box so we can search for our value
|
||||
row.addCell("", Cell.ROLE_DATA, "discovery-filter-input-cell").addText("filter_" + index, "discovery-filter-input").setValue(value == null ? "" : value);
|
||||
|
||||
//And last add an add button
|
||||
Cell buttonsCell = row.addCell("filter-controls_" + index, Cell.ROLE_DATA, "filter-controls");
|
||||
buttonsCell.addButton("add-filter_" + index, "filter-control filter-add").setValue(T_filter_controls_add);
|
||||
buttonsCell.addButton("remove-filter_" + index, "filter-control filter-remove").setValue(T_filter_controls_remove);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getBasicUrl() throws SQLException {
|
||||
Request request = ObjectModelHelper.getRequest(objectModel);
|
||||
java.util.List<String> fqs = new ArrayList<String>();
|
||||
if(request.getParameterValues("fq") != null)
|
||||
{
|
||||
fqs.addAll(Arrays.asList(request.getParameterValues("fq")));
|
||||
DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
|
||||
|
||||
return request.getContextPath() + (dso == null ? "" : "/handle/" + dso.getHandle()) + "/discover";
|
||||
}
|
||||
|
||||
//Have we added a filter using the UI
|
||||
if(request.getParameter("filter") != null && !"".equals(request.getParameter("filter")))
|
||||
{
|
||||
fqs.add((request.getParameter("filtertype")) + ":" + request.getParameter("filter"));
|
||||
}
|
||||
return fqs.toArray(new String[fqs.size()]);
|
||||
}
|
||||
protected Map<String, String[]> getParameterFilterQueries(){
|
||||
return DiscoveryUIUtils.getParameterFilterQueries(ObjectModelHelper.getRequest(objectModel));
|
||||
|
||||
}
|
||||
/**
|
||||
* Returns all the filter queries for use by discovery
|
||||
* This method returns more expanded filter queries then the getParameterFilterQueries
|
||||
* @return an array containing the filter queries
|
||||
*/
|
||||
protected String[] getFilterQueries() {
|
||||
try {
|
||||
java.util.List<String> allFilterQueries = new ArrayList<String>();
|
||||
Request request = ObjectModelHelper.getRequest(objectModel);
|
||||
java.util.List<String> fqs = new ArrayList<String>();
|
||||
|
||||
if(request.getParameterValues("fq") != null)
|
||||
{
|
||||
fqs.addAll(Arrays.asList(request.getParameterValues("fq")));
|
||||
}
|
||||
|
||||
String type = request.getParameter("filtertype");
|
||||
String value = request.getParameter("filter");
|
||||
|
||||
if(value != null && !value.equals("")){
|
||||
allFilterQueries.add(searchService.toFilterQuery(context, (type.equals("*") ? "" : type), value).getFilterQuery());
|
||||
}
|
||||
|
||||
//Add all the previous filters also
|
||||
for (String fq : fqs) {
|
||||
allFilterQueries.add(searchService.toFilterQuery(context, fq).getFilterQuery());
|
||||
}
|
||||
|
||||
return allFilterQueries.toArray(new String[allFilterQueries.size()]);
|
||||
}
|
||||
catch (RuntimeException re) {
|
||||
throw re;
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
return DiscoveryUIUtils.getFilterQueries(ObjectModelHelper.getRequest(objectModel), context);
|
||||
}
|
||||
|
||||
|
||||
@@ -375,7 +336,7 @@ public class SimpleSearch extends AbstractSearch implements CacheableProcessingC
|
||||
* @param division the division that requires the hidden fields
|
||||
* @throws WingException will never occur
|
||||
*/
|
||||
private void addHiddenFormFields(String type, Request request, String[] fqs, Division division) throws WingException {
|
||||
private void addHiddenFormFields(String type, Request request, Map<String, String[]> fqs, Division division) throws WingException {
|
||||
if(type.equals("filter") || type.equals("sort")){
|
||||
if(request.getParameter("query") != null){
|
||||
division.addHidden("query").setValue(request.getParameter("query"));
|
||||
@@ -386,9 +347,14 @@ public class SimpleSearch extends AbstractSearch implements CacheableProcessingC
|
||||
}
|
||||
|
||||
//Add the filter queries, current search settings so these remain saved when performing a new search !
|
||||
if(type.equals("search") || type.equals("sort")){
|
||||
for (String fq : fqs) {
|
||||
division.addHidden("fq").setValue(fq);
|
||||
if(type.equals("search") || type.equals("sort"))
|
||||
{
|
||||
for (String parameter : fqs.keySet())
|
||||
{
|
||||
String[] values = fqs.get(parameter);
|
||||
for (String value : values) {
|
||||
division.addHidden(parameter).setValue(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -26,7 +26,6 @@ import org.dspace.handle.HandleManager;
|
||||
import org.dspace.utils.DSpace;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.SQLException;
|
||||
@@ -118,7 +117,7 @@ public class JSONDiscoverySearcher extends AbstractReader implements Recyclable
|
||||
|
||||
try {
|
||||
Context context = ContextUtil.obtainContext(objectModel);
|
||||
JSONStream = getSearchService().searchJSON(queryArgs, getScope(context, objectModel), jsonWrf);
|
||||
JSONStream = getSearchService().searchJSON(context, queryArgs, getScope(context, objectModel), jsonWrf);
|
||||
} catch (Exception e) {
|
||||
log.error("Error while retrieving JSON string for Discovery auto complete", e);
|
||||
}
|
||||
|
@@ -85,7 +85,6 @@
|
||||
<message key="xmlui.ArtifactBrowser.SimpleSearch.filter.title">Title</message>
|
||||
<message key="xmlui.ArtifactBrowser.SimpleSearch.filter.subject">Subject</message>
|
||||
<message key="xmlui.ArtifactBrowser.SimpleSearch.filter.dateIssued">Date issued</message>
|
||||
<message key="xmlui.ArtifactBrowser.SimpleSearch.filter.selected">Selected filters</message>
|
||||
|
||||
|
||||
|
||||
@@ -103,8 +102,22 @@
|
||||
<message key="xmlui.Discovery.AbstractSearch.startswith">Starts with</message>
|
||||
<message key="xmlui.Discovery.AbstractSearch.startswith.help">Or enter first few letters:</message>
|
||||
|
||||
<message key="xmlui.ArtifactBrowser.AbstractSearch.sort_by.dc.title_sort">Title</message>
|
||||
<message key="xmlui.ArtifactBrowser.AbstractSearch.sort_by.dc.date.issued_dt">Issue Date</message>
|
||||
<message key="xmlui.Discovery.AbstractSearch.sort_by.head">Sort Options:</message>
|
||||
<message key="xmlui.Discovery.AbstractSearch.sort_by.relevance">Relevance</message>
|
||||
<message key="xmlui.Discovery.AbstractSearch.sort_by.dc.title_sort_desc">Title Desc</message>
|
||||
<message key="xmlui.Discovery.AbstractSearch.sort_by.dc.date.issued_dt_desc">Issue Date Desc</message>
|
||||
|
||||
<message key="xmlui.Discovery.AbstractSearch.sort_by.dc.title_sort_asc">Title Asc</message>
|
||||
<message key="xmlui.Discovery.AbstractSearch.sort_by.dc.date.issued_dt_asc">Issue Date Asc</message>
|
||||
|
||||
<message key="xmlui.Discovery.AbstractSearch.rpp">Results Per Page:</message>
|
||||
|
||||
|
||||
<message key="xmlui.Discovery.AbstractSearch.filters.controls.add-filter">Add Filter</message>
|
||||
<message key="xmlui.Discovery.AbstractSearch.filters.controls.apply-filters">Apply</message>
|
||||
<message key="xmlui.Discovery.AbstractSearch.filters.controls.remove-filter">Remove</message>
|
||||
<message key="xmlui.Discovery.AbstractSearch.filters.controls.new-filters.head">New Filters:</message>
|
||||
<message key="xmlui.Discovery.AbstractSearch.filters.display">Add filters</message>
|
||||
|
||||
<message key="xmlui.discovery.SearchFacetFilter.no-results">No filter values found</message>
|
||||
|
||||
@@ -112,13 +125,22 @@
|
||||
<message key="xmlui.discovery.AbstractFiltersTransformer.filters.view-more">... View More</message>
|
||||
|
||||
|
||||
<message key="xmlui.Discovery.SimpleSearch.search_scope">Search</message>
|
||||
<message key="xmlui.discovery.SimpleSearch.search_label">Search</message>
|
||||
<message key="xmlui.Discovery.SimpleSearch.filter_head">Filters</message>
|
||||
<message key="xmlui.Discovery.SimpleSearch.filter_add">Add Filters</message>
|
||||
<message key="xmlui.Discovery.SimpleSearch.filter_help">Use filters to refine the search results.</message>
|
||||
<message key="xmlui.Discovery.SimpleSearch.filter_apply">Update filters</message>
|
||||
|
||||
<message key="xmlui.Discovery.SimpleSearch.sort_head">Sort options</message>
|
||||
<message key="xmlui.Discovery.SimpleSearch.sort_apply">Apply</message>
|
||||
<message key="xmlui.Discovery.SimpleSearch.filter.contains">Contains</message>
|
||||
<message key="xmlui.Discovery.SimpleSearch.filter.equals">Equals</message>
|
||||
|
||||
<message key="xmlui.Discovery.RelatedItems.head">Related items</message>
|
||||
<message key="xmlui.Discovery.RelatedItems.help">Showing items related by title, author, creator and subject.</message>
|
||||
|
||||
<message key="xmlui.Discovery.AbstractSearch.head1_community">Showing {0} out of a total of {1} results for community: {2}. <span class="searchTime">({3} seconds)</span></message>
|
||||
<message key="xmlui.Discovery.AbstractSearch.head1_collection">Showing {0} out of a total of {1} results for collection: {2}. <span class="searchTime">({3} seconds)</span></message>
|
||||
<message key="xmlui.Discovery.AbstractSearch.head1_none">Showing {0} out of a total of {1} results. <span class="searchTime">({2} seconds)</span></message>
|
||||
|
||||
<message key="xmlui.Discovery.AbstractSearch.head2">Communities or Collections matching your query</message>
|
||||
<message key="xmlui.Discovery.AbstractSearch.head3">Items matching your query</message>
|
||||
|
||||
</catalogue>
|
||||
|
@@ -100,19 +100,10 @@ and searching the repository.
|
||||
<map:transform type="SidebarFacetsTransformer"/>
|
||||
<map:transform type="SimpleSearch"/>
|
||||
<map:transform type="IncludePageMeta">
|
||||
<map:parameter name="stylesheet.screen.discovery#1" value="../../static/css/discovery/style.css"/>
|
||||
<map:parameter name="stylesheet.screen.discovery#1" value="../../static/css/discovery/discovery-style.css"/>
|
||||
|
||||
<map:parameter name="javascript.static#1" value="loadJQuery.js"/>
|
||||
<map:parameter name="javascript.static#2" value="static/js/discovery/core/Core.js"/>
|
||||
<map:parameter name="javascript.static#3" value="static/js/discovery/core/AbstractManager.js"/>
|
||||
<map:parameter name="javascript.static#4" value="static/js/discovery/core/Parameter.js"/>
|
||||
<map:parameter name="javascript.static#5" value="static/js/discovery/core/ParameterStore.js"/>
|
||||
<map:parameter name="javascript.static#6" value="static/js/discovery/core/AbstractWidget.js"/>
|
||||
<map:parameter name="javascript.static#7" value="static/js/discovery/core/AbstractFacetWidget.js"/>
|
||||
<map:parameter name="javascript.static#8" value="static/js/discovery/managers/Manager.jquery.js"/>
|
||||
<map:parameter name="javascript.static#9" value="static/js/jquery/jquery.autocomplete.js"/>
|
||||
<map:parameter name="javascript.static#10" value="static/js/discovery/widgets/AutocompleteWidget.js"/>
|
||||
<map:parameter name="javascript.static#11" value="static/js/discovery/search/search.js"/>
|
||||
<map:parameter name="javascript.static#2" value="static/js/discovery/search-controls.js"/>
|
||||
</map:transform>
|
||||
<map:serialize type="xml"/>
|
||||
</map:match>
|
||||
@@ -145,19 +136,10 @@ and searching the repository.
|
||||
<map:transform type="SidebarFacetsTransformer"/>
|
||||
<map:transform type="SimpleSearch"/>
|
||||
<map:transform type="IncludePageMeta">
|
||||
<map:parameter name="stylesheet.screen.discovery#1" value="../../static/css/discovery/style.css"/>
|
||||
<map:parameter name="stylesheet.screen.discovery#1" value="../../static/css/discovery/discovery-style.css"/>
|
||||
|
||||
<map:parameter name="javascript.static#1" value="loadJQuery.js"/>
|
||||
<map:parameter name="javascript.static#2" value="static/js/discovery/core/Core.js"/>
|
||||
<map:parameter name="javascript.static#3" value="static/js/discovery/core/AbstractManager.js"/>
|
||||
<map:parameter name="javascript.static#4" value="static/js/discovery/core/Parameter.js"/>
|
||||
<map:parameter name="javascript.static#5" value="static/js/discovery/core/ParameterStore.js"/>
|
||||
<map:parameter name="javascript.static#6" value="static/js/discovery/core/AbstractWidget.js"/>
|
||||
<map:parameter name="javascript.static#7" value="static/js/discovery/core/AbstractFacetWidget.js"/>
|
||||
<map:parameter name="javascript.static#8" value="static/js/discovery/managers/Manager.jquery.js"/>
|
||||
<map:parameter name="javascript.static#9" value="static/js/jquery/jquery.autocomplete.js"/>
|
||||
<map:parameter name="javascript.static#10" value="static/js/discovery/widgets/AutocompleteWidget.js"/>
|
||||
<map:parameter name="javascript.static#11" value="static/js/discovery/search/search.js"/>
|
||||
<map:parameter name="javascript.static#2" value="static/js/discovery/search-controls.js"/>
|
||||
</map:transform>
|
||||
<map:serialize type="xml"/>
|
||||
</map:match>
|
||||
|
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
Discovery control gears start
|
||||
**/
|
||||
|
||||
div.controls-gear-wrapper{
|
||||
position: relative;
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.controls-gear-wrapper .discovery-controls-gear{
|
||||
padding: 3px 24px;
|
||||
margin-right: 3px;
|
||||
margin-bottom: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
ul.gear-selection{
|
||||
margin: 0 2px 0 0;
|
||||
list-style: none;
|
||||
background-color: #FFFFFF;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
z-index: 999;
|
||||
border: 1px solid #EBEBEB;
|
||||
padding: 0;
|
||||
/*Hidden by default*/
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
.bottom ul.gear-selection {
|
||||
/*Css to ensure that the bottom gear selection list is shown on TOP of the button */
|
||||
bottom: 33px;
|
||||
}
|
||||
|
||||
div.gear-icon{
|
||||
height: 25px;
|
||||
width: 25px;
|
||||
}
|
||||
|
||||
|
||||
.rgba.boxshadow ul.gear-selection{
|
||||
-webkit-box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.2);
|
||||
-moz-box-shadow: 2px 2px 10px rgba(0,0,0,0.2);
|
||||
box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
ul.gear-selection ul {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
ul.gear-selection li {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
ul.gear-selection li.gear-head{
|
||||
padding: 5px;
|
||||
border-top: 1px solid #EBEBEB;
|
||||
}
|
||||
|
||||
ul.gear-selection li.gear-head.first{
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
|
||||
ul.gear-selection li.gear-option{
|
||||
padding: 5px 5px 5px 25px;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
ul.gear-selection li.gear-option:hover{
|
||||
background-color: #EBEBEB;
|
||||
}
|
||||
|
||||
ul.gear-selection li.gear-option a{
|
||||
color: #444444;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/**
|
||||
Discovery control gears end
|
||||
**/
|
||||
|
||||
|
||||
table.discovery-filters td.discovery-filter-input-cell input{
|
||||
width: 98%;
|
||||
}
|
||||
|
||||
table.discovery-filters tr.search-filter.used-filter input.filter-add
|
||||
{
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.searchTime{
|
||||
font-size: 80%;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
|
||||
input#aspect_discovery_SimpleSearch_field_query{
|
||||
height: 25px;
|
||||
font-size: 18px;
|
||||
float: left;
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
input.search-icon{
|
||||
height: 33px;
|
||||
float: left;
|
||||
margin-left: 5px;
|
||||
display: block;
|
||||
width: 75px;
|
||||
}
|
||||
|
||||
div#aspect_discovery_SimpleSearch_div_search-results ul{
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
div#aspect_discovery_SimpleSearch_div_search-results ul li{
|
||||
list-style: none;
|
||||
}
|
@@ -1,56 +0,0 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
.ac_results {
|
||||
padding: 0px;
|
||||
border: 1px solid black;
|
||||
background-color: white;
|
||||
overflow: hidden;
|
||||
z-index: 99999;
|
||||
}
|
||||
|
||||
.ac_results ul {
|
||||
width: 100%;
|
||||
list-style-position: outside;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.ac_results li {
|
||||
margin: 0px;
|
||||
padding: 2px 5px;
|
||||
cursor: default;
|
||||
display: block;
|
||||
text-align:left;
|
||||
/*
|
||||
if width will be 100% horizontal scrollbar will apear
|
||||
when scroll mode will be used
|
||||
*/
|
||||
/*width: 100%;*/
|
||||
font: menu;
|
||||
font-size: 12px;
|
||||
/*
|
||||
it is very important, if line-height not setted or setted
|
||||
in relative units scroll will be broken in firefox
|
||||
*/
|
||||
line-height: 16px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ac_loading {
|
||||
/*background: white url('indicator.gif') right center no-repeat;*/
|
||||
}
|
||||
|
||||
.ac_odd {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.ac_over {
|
||||
background-color: #0A246A;
|
||||
color: white;
|
||||
}
|
@@ -1,17 +0,0 @@
|
||||
Portions of this AJAX Solr are licensed under the Apache License (ASL) v2.0.
|
||||
|
||||
===
|
||||
|
||||
Copyright 2009 Evolving Web Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
@@ -1,133 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
// $Id$
|
||||
|
||||
/**
|
||||
* Baseclass for all facet widgets.
|
||||
*
|
||||
* @class AbstractFacetWidget
|
||||
* @augments AjaxSolr.AbstractWidget
|
||||
*/
|
||||
AjaxSolr.AbstractFacetWidget = AjaxSolr.AbstractWidget.extend(
|
||||
/** @lends AjaxSolr.AbstractFacetWidget.prototype */
|
||||
{
|
||||
/**
|
||||
* The field to facet on.
|
||||
*
|
||||
* @field
|
||||
* @public
|
||||
* @type String
|
||||
*/
|
||||
field: null,
|
||||
|
||||
/**
|
||||
* @returns {Boolean} Whether any filter queries have been set using this
|
||||
* widget's facet field.
|
||||
*/
|
||||
isEmpty: function () {
|
||||
return !this.manager.store.find('fq', new RegExp('^-?' + this.field + ':'));
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a filter query.
|
||||
*
|
||||
* @returns {Boolean} Whether a filter query was added.
|
||||
*/
|
||||
add: function (value) {
|
||||
return this.changeSelection(function () {
|
||||
return this.manager.store.addByValue('fq', this.fq(value));
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes a filter query.
|
||||
*
|
||||
* @returns {Boolean} Whether a filter query was removed.
|
||||
*/
|
||||
remove: function (value) {
|
||||
return this.changeSelection(function () {
|
||||
return this.manager.store.removeByValue('fq', this.fq(value));
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes all filter queries using the widget's facet field.
|
||||
*
|
||||
* @returns {Boolean} Whether a filter query was removed.
|
||||
*/
|
||||
clear: function () {
|
||||
return this.changeSelection(function () {
|
||||
return this.manager.store.removeByValue('fq', new RegExp('^-?' + this.field + ':'));
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper for selection functions.
|
||||
*
|
||||
* @param {Function} Selection function to call.
|
||||
* @returns {Boolean} Whether the selection changed.
|
||||
*/
|
||||
changeSelection: function (func) {
|
||||
changed = func.apply(this);
|
||||
if (changed) {
|
||||
this.afterChangeSelection();
|
||||
}
|
||||
return changed;
|
||||
},
|
||||
|
||||
/**
|
||||
* An abstract hook for child implementations.
|
||||
*
|
||||
* <p>This method is executed after the filter queries change.</p>
|
||||
*/
|
||||
afterChangeSelection: function () {},
|
||||
|
||||
/**
|
||||
* @param {String} value The value.
|
||||
* @returns {Function} Sends a request to Solr if it successfully adds a
|
||||
* filter query with the given value.
|
||||
*/
|
||||
clickHandler: function (value) {
|
||||
var self = this;
|
||||
return function () {
|
||||
if (self.add(value)) {
|
||||
self.manager.doRequest(0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {String} value The value.
|
||||
* @returns {Function} Sends a request to Solr if it successfully removes a
|
||||
* filter query with the given value.
|
||||
*/
|
||||
unclickHandler: function (value) {
|
||||
var self = this;
|
||||
return function () {
|
||||
if (self.remove(value)) {
|
||||
self.manager.doRequest(0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {String} value The facet value.
|
||||
* @param {Boolean} exclude Whether to exclude this fq parameter value.
|
||||
* @returns {String} An fq parameter value.
|
||||
*/
|
||||
fq: function (value, exclude) {
|
||||
// If the field value has a space or a colon in it, wrap it in quotes,
|
||||
// unless it is a range query.
|
||||
if (value.match(/[ :]/) && !value.match(/[\[\{]\S+ TO \S+[\]\}]/)) {
|
||||
value = '"' + value + '"';
|
||||
}
|
||||
return (exclude ? '-' : '') + this.field + ':' + value;
|
||||
}
|
||||
});
|
@@ -1,189 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
// $Id$
|
||||
|
||||
/**
|
||||
* The Manager acts as the controller in a Model-View-Controller framework. All
|
||||
* public calls should be performed on the manager object.
|
||||
*
|
||||
* @param properties A map of fields to set. Refer to the list of public fields.
|
||||
* @class AbstractManager
|
||||
*/
|
||||
AjaxSolr.AbstractManager = AjaxSolr.Class.extend(
|
||||
/** @lends AjaxSolr.AbstractManager.prototype */
|
||||
{
|
||||
/**
|
||||
* The fully-qualified URL of the Solr application. You must include the
|
||||
* trailing slash. Do not include the path to any Solr servlet.
|
||||
*
|
||||
* @field
|
||||
* @public
|
||||
* @type String
|
||||
* @default "http://localhost:8983/solr/"
|
||||
*/
|
||||
solrUrl: 'http://localhost:8983/solr/',
|
||||
|
||||
/**
|
||||
* If we want to proxy queries through a script, rather than send queries
|
||||
* to Solr directly, set this field to the fully-qualified URL of the script.
|
||||
*
|
||||
* @field
|
||||
* @public
|
||||
* @type String
|
||||
*/
|
||||
proxyUrl: null,
|
||||
|
||||
/**
|
||||
* The default Solr servlet.
|
||||
*
|
||||
* @field
|
||||
* @public
|
||||
* @type String
|
||||
* @default "select"
|
||||
*/
|
||||
servlet: 'select',
|
||||
|
||||
/**
|
||||
* The most recent response from Solr.
|
||||
*
|
||||
* @field
|
||||
* @private
|
||||
* @type Object
|
||||
* @default {}
|
||||
*/
|
||||
response: {},
|
||||
|
||||
/**
|
||||
* A collection of all registered widgets. For internal use only.
|
||||
*
|
||||
* @field
|
||||
* @private
|
||||
* @type Object
|
||||
* @default {}
|
||||
*/
|
||||
widgets: {},
|
||||
|
||||
/**
|
||||
* The parameter store for the manager and its widgets. For internal use only.
|
||||
*
|
||||
* @field
|
||||
* @private
|
||||
* @type Object
|
||||
*/
|
||||
store: null,
|
||||
|
||||
/**
|
||||
* Whether <tt>init()</tt> has been called yet. For internal use only.
|
||||
*
|
||||
* @field
|
||||
* @private
|
||||
* @type Boolean
|
||||
* @default false
|
||||
*/
|
||||
initialized: false,
|
||||
|
||||
/**
|
||||
* An abstract hook for child implementations.
|
||||
*
|
||||
* <p>This method should be called after the store and the widgets have been
|
||||
* added. It should initialize the widgets and the store, and do any other
|
||||
* one-time initializations, e.g., perform the first request to Solr.</p>
|
||||
*
|
||||
* <p>If no store has been set, it sets the store to the basic <tt>
|
||||
* AjaxSolr.ParameterStore</tt>.</p>
|
||||
*/
|
||||
init: function () {
|
||||
this.initialized = true;
|
||||
if (this.store === null) {
|
||||
this.setStore(new AjaxSolr.ParameterStore());
|
||||
}
|
||||
this.store.load(false);
|
||||
for (var widgetId in this.widgets) {
|
||||
this.widgets[widgetId].init();
|
||||
}
|
||||
this.store.init();
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the manager's parameter store.
|
||||
*
|
||||
* @param {AjaxSolr.ParameterStore} store
|
||||
*/
|
||||
setStore: function (store) {
|
||||
store.manager = this;
|
||||
this.store = store;
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a widget to the manager.
|
||||
*
|
||||
* @param {AjaxSolr.AbstractWidget} widget
|
||||
*/
|
||||
addWidget: function (widget) {
|
||||
widget.manager = this;
|
||||
this.widgets[widget.id] = widget;
|
||||
},
|
||||
|
||||
/**
|
||||
* Stores the Solr parameters to be sent to Solr and sends a request to Solr.
|
||||
*
|
||||
* @param {Boolean} [start] The Solr start offset parameter.
|
||||
* @param {String} [servlet] The Solr servlet to send the request to.
|
||||
*/
|
||||
doRequest: function (start, servlet) {
|
||||
if (this.initialized === false) {
|
||||
this.init();
|
||||
}
|
||||
// Allow non-pagination widgets to reset the offset parameter.
|
||||
if (start !== undefined) {
|
||||
this.store.get('start').val(start);
|
||||
}
|
||||
if (servlet === undefined) {
|
||||
servlet = this.servlet;
|
||||
}
|
||||
|
||||
this.store.save();
|
||||
|
||||
for (var widgetId in this.widgets) {
|
||||
this.widgets[widgetId].beforeRequest();
|
||||
}
|
||||
|
||||
this.executeRequest(servlet);
|
||||
},
|
||||
|
||||
/**
|
||||
* An abstract hook for child implementations.
|
||||
*
|
||||
* <p>Sends the request to Solr, i.e. to <code>this.solrUrl</code> or <code>
|
||||
* this.proxyUrl</code>, and receives Solr's response. It should send <code>
|
||||
* this.store.string()</code> as the Solr query, and it should pass Solr's
|
||||
* response to <code>handleResponse()</code> for handling.</p>
|
||||
*
|
||||
* <p>See <tt>managers/Manager.jquery.js</tt> for a jQuery implementation.</p>
|
||||
*
|
||||
* @param {String} servlet The Solr servlet to send the request to.
|
||||
* @throws If not defined in child implementation.
|
||||
*/
|
||||
executeRequest: function (servlet) {
|
||||
throw 'Abstract method executeRequest must be overridden in a subclass.';
|
||||
},
|
||||
|
||||
/**
|
||||
* This method is executed after the Solr response data arrives. Allows each
|
||||
* widget to handle Solr's response separately.
|
||||
*
|
||||
* @param {Object} data The Solr response.
|
||||
*/
|
||||
handleResponse: function (data) {
|
||||
this.response = data;
|
||||
|
||||
for (var widgetId in this.widgets) {
|
||||
this.widgets[widgetId].afterRequest();
|
||||
}
|
||||
}
|
||||
});
|
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
// $Id$
|
||||
|
||||
/**
|
||||
* Baseclass for all widgets.
|
||||
*
|
||||
* Provides abstract hooks for child classes.
|
||||
*
|
||||
* @param properties A map of fields to set. May be new or public fields.
|
||||
* @class AbstractWidget
|
||||
*/
|
||||
AjaxSolr.AbstractWidget = AjaxSolr.Class.extend(
|
||||
/** @lends AjaxSolr.AbstractWidget.prototype */
|
||||
{
|
||||
/**
|
||||
* A unique identifier of this widget.
|
||||
*
|
||||
* @field
|
||||
* @public
|
||||
* @type String
|
||||
*/
|
||||
id: null,
|
||||
|
||||
/**
|
||||
* The CSS selector for this widget's target HTML element, e.g. a specific
|
||||
* <tt>div</tt> or <tt>ul</tt>. A Widget is usually implemented to perform
|
||||
* all its UI changes relative to its target HTML element.
|
||||
*
|
||||
* @field
|
||||
* @public
|
||||
* @type String
|
||||
*/
|
||||
target: null,
|
||||
|
||||
/**
|
||||
* A reference to the widget's manager. For internal use only.
|
||||
*
|
||||
* @field
|
||||
* @private
|
||||
* @type AjaxSolr.AbstractManager
|
||||
*/
|
||||
manager: null,
|
||||
|
||||
/**
|
||||
* An abstract hook for child implementations.
|
||||
*
|
||||
* <p>This method should do any necessary one-time initializations.</p>
|
||||
*/
|
||||
init: function () {},
|
||||
|
||||
/**
|
||||
* An abstract hook for child implementations.
|
||||
*
|
||||
* <p>This method is executed before the Solr request is sent.</p>
|
||||
*/
|
||||
beforeRequest: function () {},
|
||||
|
||||
/**
|
||||
* An abstract hook for child implementations.
|
||||
*
|
||||
* <p>This method is executed after the Solr response is received.</p>
|
||||
*/
|
||||
afterRequest: function () {}
|
||||
});
|
@@ -1,233 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
// $Id$
|
||||
|
||||
/**
|
||||
* @namespace A unique namespace for the AJAX Solr library.
|
||||
*/
|
||||
AjaxSolr = function () {};
|
||||
|
||||
/**
|
||||
* @namespace Baseclass for all classes
|
||||
*/
|
||||
AjaxSolr.Class = function () {};
|
||||
|
||||
/**
|
||||
* A class 'extends' itself into a subclass.
|
||||
*
|
||||
* @static
|
||||
* @param properties The properties of the subclass.
|
||||
* @returns A function that represents the subclass.
|
||||
*/
|
||||
AjaxSolr.Class.extend = function (properties) {
|
||||
var klass = this; // Safari dislikes 'class'
|
||||
// The subclass is just a function that when called, instantiates itself.
|
||||
// Nothing is _actually_ shared between _instances_ of the same class.
|
||||
var subClass = function (options) {
|
||||
// 'this' refers to the subclass, which starts life as an empty object.
|
||||
// Add its parent's properties, its own properties, and any passed options.
|
||||
AjaxSolr.extend(this, new klass(options), properties, options);
|
||||
}
|
||||
// Allow the subclass to extend itself into further subclasses.
|
||||
subClass.extend = this.extend;
|
||||
return subClass;
|
||||
};
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @param {Object} obj Any object.
|
||||
* @returns {Number} the number of properties on an object.
|
||||
* @see http://stackoverflow.com/questions/5223/length-of-javascript-associative-array
|
||||
*/
|
||||
AjaxSolr.size = function (obj) {
|
||||
var size = 0;
|
||||
for (var key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
size++;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
};
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @param foo A value.
|
||||
* @param bar A value.
|
||||
* @returns {Boolean} Whether the two given values are equal.
|
||||
*/
|
||||
AjaxSolr.equals = function (foo, bar) {
|
||||
if (AjaxSolr.isArray(foo) && AjaxSolr.isArray(bar)) {
|
||||
if (foo.length !== bar.length) {
|
||||
return false;
|
||||
}
|
||||
for (var i = 0, l = foo.length; i < l; i++) {
|
||||
if (foo[i] !== bar[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (AjaxSolr.isRegExp(foo) && AjaxSolr.isString(bar)) {
|
||||
return bar.match(foo);
|
||||
}
|
||||
else if (AjaxSolr.isRegExp(bar) && AjaxSolr.isString(foo)) {
|
||||
return foo.match(bar);
|
||||
}
|
||||
else {
|
||||
return foo === bar;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @param value A value.
|
||||
* @param array An array.
|
||||
* @returns {Boolean} Whether value exists in the array.
|
||||
*/
|
||||
AjaxSolr.inArray = function (value, array) {
|
||||
if (array) {
|
||||
for (var i = 0, l = array.length; i < l; i++) {
|
||||
if (AjaxSolr.equals(array[i], value)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
/**
|
||||
* A copy of MooTools' Array.flatten function.
|
||||
*
|
||||
* @static
|
||||
* @see http://ajax.googleapis.com/ajax/libs/mootools/1.2.4/mootools.js
|
||||
*/
|
||||
AjaxSolr.flatten = function(array) {
|
||||
var ret = [];
|
||||
for (var i = 0, l = array.length; i < l; i++) {
|
||||
ret = ret.concat(AjaxSolr.isArray(array[i]) ? AjaxSolr.flatten(array[i]) : array[i]);
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
/**
|
||||
* A copy of jQuery's jQuery.grep function.
|
||||
*
|
||||
* @static
|
||||
* @see http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js
|
||||
*/
|
||||
AjaxSolr.grep = function(array, callback) {
|
||||
var ret = [];
|
||||
for (var i = 0, l = array.length; i < l; i++) {
|
||||
if (!callback(array[i], i) === false) {
|
||||
ret.push(array[i]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to Ruby's Array#compact.
|
||||
*/
|
||||
AjaxSolr.compact = function(array) {
|
||||
return AjaxSolr.grep(array, function (item) {
|
||||
return item.toString();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Can't use toString.call(obj) === "[object Array]", as it may return
|
||||
* "[xpconnect wrapped native prototype]", which is undesirable.
|
||||
*
|
||||
* @static
|
||||
* @see http://thinkweb2.com/projects/prototype/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/
|
||||
* @see http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.3/prototype.js
|
||||
*/
|
||||
AjaxSolr.isArray = function (obj) {
|
||||
return obj != null && typeof obj == 'object' && 'splice' in obj && 'join' in obj;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param obj Any object.
|
||||
* @returns {Boolean} Whether the object is a RegExp object.
|
||||
*/
|
||||
AjaxSolr.isRegExp = function (obj) {
|
||||
return obj != null && (typeof obj == 'object' || typeof obj == 'function') && 'ignoreCase' in obj;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param obj Any object.
|
||||
* @returns {Boolean} Whether the object is a String object.
|
||||
*/
|
||||
AjaxSolr.isString = function (obj) {
|
||||
return obj != null && typeof obj == 'string';
|
||||
};
|
||||
|
||||
/**
|
||||
* Define theme functions to separate, as much as possible, your HTML from your
|
||||
* JavaScript. Theme functions provided by AJAX Solr are defined in the
|
||||
* AjaxSolr.theme.prototype namespace, e.g. AjaxSolr.theme.prototype.select_tag.
|
||||
*
|
||||
* To override a theme function provided by AJAX Solr, define a function of the
|
||||
* same name in the AjaxSolr.theme namespace, e.g. AjaxSolr.theme.select_tag.
|
||||
*
|
||||
* To retrieve the HTML output by AjaxSolr.theme.prototype.select_tag(...), call
|
||||
* AjaxSolr.theme('select_tag', ...).
|
||||
*
|
||||
* @param {String} func
|
||||
* The name of the theme function to call.
|
||||
* @param ...
|
||||
* Additional arguments to pass along to the theme function.
|
||||
* @returns
|
||||
* Any data the theme function returns. This could be a plain HTML string,
|
||||
* but also a complex object.
|
||||
*
|
||||
* @static
|
||||
* @throws Exception if the theme function is not defined.
|
||||
* @see http://cvs.drupal.org/viewvc.py/drupal/drupal/misc/drupal.js?revision=1.58
|
||||
*/
|
||||
AjaxSolr.theme = function (func) {
|
||||
for (var i = 1, args = []; i < arguments.length; i++) {
|
||||
args.push(arguments[i]);
|
||||
}
|
||||
try {
|
||||
return (AjaxSolr.theme[func] || AjaxSolr.theme.prototype[func]).apply(this, args);
|
||||
}
|
||||
catch (e) {
|
||||
if (console && console.log) {
|
||||
console.log('Theme function "' + func + '" is not defined.');
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A simplified version of jQuery's extend function.
|
||||
*
|
||||
* @static
|
||||
* @see http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.js
|
||||
*/
|
||||
AjaxSolr.extend = function () {
|
||||
var target = arguments[0] || {}, i = 1, length = arguments.length, options;
|
||||
for (; i < length; i++) {
|
||||
if ((options = arguments[i]) != null) {
|
||||
for (var name in options) {
|
||||
var src = target[name], copy = options[name];
|
||||
if (target === copy) {
|
||||
continue;
|
||||
}
|
||||
if (copy && typeof copy == 'object' && !copy.nodeType) {
|
||||
target[name] = AjaxSolr.extend(src || (copy.length != null ? [] : {}), copy);
|
||||
}
|
||||
else if (copy !== undefined) {
|
||||
target[name] = copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return target;
|
||||
};
|
@@ -1,168 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
// $Id$
|
||||
|
||||
/**
|
||||
* Represents a Solr parameter.
|
||||
*
|
||||
* @param properties A map of fields to set. Refer to the list of public fields.
|
||||
* @class Parameter
|
||||
*/
|
||||
AjaxSolr.Parameter = AjaxSolr.Class.extend(
|
||||
/** @lends AjaxSolr.Parameter.prototype */
|
||||
{
|
||||
/**
|
||||
* The parameter's name.
|
||||
*
|
||||
* @field
|
||||
* @private
|
||||
* @type String
|
||||
*/
|
||||
name: null,
|
||||
|
||||
/**
|
||||
* The parameter's value.
|
||||
*
|
||||
* @field
|
||||
* @private
|
||||
* @type String
|
||||
*/
|
||||
value: null,
|
||||
|
||||
/**
|
||||
* The parameter's local parameters.
|
||||
*
|
||||
* @field
|
||||
* @private
|
||||
* @type Object
|
||||
* @default {}
|
||||
*/
|
||||
locals: {},
|
||||
|
||||
/**
|
||||
* Returns the value. If called with an argument, sets the value.
|
||||
*
|
||||
* @param {String|Number|String[]|Number[]} [value] The value to set.
|
||||
* @returns The value.
|
||||
*/
|
||||
val: function (value) {
|
||||
if (value === undefined) {
|
||||
return this.value;
|
||||
}
|
||||
else {
|
||||
this.value = value;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the value of a local parameter. If called with a second argument,
|
||||
* sets the value of a local parameter.
|
||||
*
|
||||
* @param {String} name The name of the local parameter.
|
||||
* @param {String|Number|String[]|Number[]} [value] The value to set.
|
||||
* @returns The value.
|
||||
*/
|
||||
local: function (name, value) {
|
||||
if (value === undefined) {
|
||||
return this.locals[name];
|
||||
}
|
||||
else {
|
||||
this.locals[name] = value;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Deletes a local parameter.
|
||||
*
|
||||
* @param {String} name The name of the local parameter.
|
||||
*/
|
||||
remove: function (name) {
|
||||
delete this.locals[name];
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the Solr parameter as a query string key-value pair.
|
||||
*
|
||||
* <p>IE6 calls the default toString() if you write <tt>store.toString()
|
||||
* </tt>. So, we need to choose another name for toString().</p>
|
||||
*/
|
||||
string: function () {
|
||||
var pairs = [];
|
||||
|
||||
for (var name in this.locals) {
|
||||
if (this.locals[name]) {
|
||||
pairs.push(name + '=' + encodeURIComponent(this.locals[name]));
|
||||
}
|
||||
}
|
||||
|
||||
var prefix = pairs.length ? '{!' + pairs.join('%20') + '}' : '';
|
||||
|
||||
if (this.value) {
|
||||
return this.name + '=' + prefix + this.valueString(this.value);
|
||||
}
|
||||
// For dismax request handlers, if the q parameter has local params, the
|
||||
// q parameter must be set to a non-empty value. In case the q parameter
|
||||
// is empty, use the q.alt parameter, which accepts wildcards.
|
||||
else if (this.name == 'q') {
|
||||
return 'q.alt=' + prefix + encodeURIComponent('*.*');
|
||||
}
|
||||
else {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Parses a string formed by calling string().
|
||||
*
|
||||
* @param {String} str The string to parse.
|
||||
*/
|
||||
parseString: function (str) {
|
||||
var param = str.match(/^([^=]+)=(?:\{!([^\}]*)\})?(.*)$/);
|
||||
if (param) {
|
||||
var matches;
|
||||
|
||||
while (matches = /([^\s=]+)=(\S*)/g.exec(decodeURIComponent(param[2]))) {
|
||||
this.locals[matches[1]] = decodeURIComponent(matches[2]);
|
||||
param[2] = param[2].replace(matches[0], ''); // Safari's exec seems not to do this on its own
|
||||
}
|
||||
|
||||
if (param[1] == 'q.alt') {
|
||||
this.name = 'q';
|
||||
// if q.alt is present, assume it is because q was empty, as above
|
||||
}
|
||||
else {
|
||||
this.name = param[1];
|
||||
this.value = this.parseValueString(param[3]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the value as a URL-encoded string.
|
||||
*
|
||||
* @private
|
||||
* @param {String|Number|String[]|Number[]} value The value.
|
||||
* @returns {String} The URL-encoded string.
|
||||
*/
|
||||
valueString: function (value) {
|
||||
value = AjaxSolr.isArray(value) ? value.join(',') : value;
|
||||
return encodeURIComponent(value);
|
||||
},
|
||||
|
||||
/**
|
||||
* Parses a URL-encoded string to return the value.
|
||||
*
|
||||
* @private
|
||||
* @param {String} str The URL-encoded string.
|
||||
* @returns {Array} The value.
|
||||
*/
|
||||
parseValueString: function (str) {
|
||||
str = decodeURIComponent(str);
|
||||
return str.indexOf(',') == -1 ? str : str.split(',');
|
||||
}
|
||||
});
|
@@ -1,361 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
// $Id$
|
||||
|
||||
/**
|
||||
* The ParameterStore, as its name suggests, stores Solr parameters. Widgets
|
||||
* expose some of these parameters to the user. Whenever the user changes the
|
||||
* values of these parameters, the state of the application changes. In order to
|
||||
* allow the user to move back and forth between these states with the browser's
|
||||
* Back and Forward buttons, and to bookmark these states, each state needs to
|
||||
* be stored. The easiest method is to store the exposed parameters in the URL
|
||||
* hash (see the <tt>ParameterHashStore</tt> class). However, you may implement
|
||||
* your own storage method by extending this class.
|
||||
*
|
||||
* <p>For a list of possible parameters, please consult the links below.</p>
|
||||
*
|
||||
* @see http://wiki.apache.org/solr/CoreQueryParameters
|
||||
* @see http://wiki.apache.org/solr/CommonQueryParameters
|
||||
* @see http://wiki.apache.org/solr/SimpleFacetParameters
|
||||
* @see http://wiki.apache.org/solr/HighlightingParameters
|
||||
* @see http://wiki.apache.org/solr/MoreLikeThis
|
||||
* @see http://wiki.apache.org/solr/SpellCheckComponent
|
||||
* @see http://wiki.apache.org/solr/StatsComponent
|
||||
* @see http://wiki.apache.org/solr/TermsComponent
|
||||
* @see http://wiki.apache.org/solr/TermVectorComponent
|
||||
* @see http://wiki.apache.org/solr/LocalParams
|
||||
*
|
||||
* @param properties A map of fields to set. Refer to the list of public fields.
|
||||
* @class ParameterStore
|
||||
*/
|
||||
AjaxSolr.ParameterStore = AjaxSolr.Class.extend(
|
||||
/** @lends AjaxSolr.ParameterStore.prototype */
|
||||
{
|
||||
/**
|
||||
* The names of the exposed parameters. Any parameters that your widgets
|
||||
* expose to the user, directly or indirectly, should be listed here.
|
||||
*
|
||||
* @field
|
||||
* @public
|
||||
* @type String[]
|
||||
* @default []
|
||||
*/
|
||||
exposed: [],
|
||||
|
||||
/**
|
||||
* The Solr parameters.
|
||||
*
|
||||
* @field
|
||||
* @private
|
||||
* @type Object
|
||||
* @default {}
|
||||
*/
|
||||
params: {},
|
||||
|
||||
/**
|
||||
* A reference to the parameter store's manager. For internal use only.
|
||||
*
|
||||
* @field
|
||||
* @private
|
||||
* @type AjaxSolr.AbstractManager
|
||||
*/
|
||||
manager: null,
|
||||
|
||||
/**
|
||||
* An abstract hook for child implementations.
|
||||
*
|
||||
* <p>This method should do any necessary one-time initializations.</p>
|
||||
*/
|
||||
init: function () {},
|
||||
|
||||
/**
|
||||
* Some Solr parameters may be specified multiple times. It is easiest to
|
||||
* hard-code a list of such parameters. You may change the list by passing
|
||||
* <code>{ multiple: /pattern/ }</code> as an argument to the constructor of
|
||||
* this class or one of its children, e.g.:
|
||||
*
|
||||
* <p><code>new ParameterStore({ multiple: /pattern/ })</code>
|
||||
*
|
||||
* @param {String} name The name of the parameter.
|
||||
* @returns {Boolean} Whether the parameter may be specified multiple times.
|
||||
*/
|
||||
isMultiple: function (name) {
|
||||
return name.match(/^(?:bf|bq|facet\.date|facet\.date\.other|facet\.field|facet\.query|fq|pf|qf)$/);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a parameter. If the parameter doesn't exist, creates it.
|
||||
*
|
||||
* @param {String} name The name of the parameter.
|
||||
* @returns {AjaxSolr.Parameter|AjaxSolr.Parameter[]} The parameter.
|
||||
*/
|
||||
get: function (name) {
|
||||
if (this.params[name] === undefined) {
|
||||
var param = new AjaxSolr.Parameter({ name: name });
|
||||
if (this.isMultiple(name)) {
|
||||
this.params[name] = [ param ];
|
||||
}
|
||||
else {
|
||||
this.params[name] = param;
|
||||
}
|
||||
}
|
||||
return this.params[name];
|
||||
},
|
||||
|
||||
/**
|
||||
* If the parameter may be specified multiple times, returns the values of
|
||||
* all identically-named parameters. If the parameter may be specified only
|
||||
* once, returns the value of that parameter.
|
||||
*
|
||||
* @param {String} name The name of the parameter.
|
||||
* @returns {String[]|Number[]} The value(s) of the parameter.
|
||||
*/
|
||||
values: function (name) {
|
||||
if (this.params[name] !== undefined) {
|
||||
if (this.isMultiple(name)) {
|
||||
var values = [];
|
||||
for (var i = 0, l = this.params[name].length; i < l; i++) {
|
||||
values.push(this.params[name][i].val());
|
||||
}
|
||||
return values;
|
||||
}
|
||||
else {
|
||||
return [ this.params[name].val() ];
|
||||
}
|
||||
}
|
||||
return [];
|
||||
},
|
||||
|
||||
/**
|
||||
* If the parameter may be specified multiple times, adds the given parameter
|
||||
* to the list of identically-named parameters, unless one already exists with
|
||||
* the same value. If it may be specified only once, replaces the parameter.
|
||||
*
|
||||
* @param {String} name The name of the parameter.
|
||||
* @param {AjaxSolr.Parameter} [param] The parameter.
|
||||
* @returns {AjaxSolr.Parameter|Boolean} The parameter, or false.
|
||||
*/
|
||||
add: function (name, param) {
|
||||
if (param === undefined) {
|
||||
param = new AjaxSolr.Parameter({ name: name });
|
||||
}
|
||||
if (this.isMultiple(name)) {
|
||||
if (this.params[name] === undefined) {
|
||||
this.params[name] = [ param ];
|
||||
}
|
||||
else {
|
||||
if (AjaxSolr.inArray(param.val(), this.values(name)) == -1) {
|
||||
this.params[name].push(param);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.params[name] = param;
|
||||
}
|
||||
return param;
|
||||
},
|
||||
|
||||
/**
|
||||
* Deletes a parameter.
|
||||
*
|
||||
* @param {String} name The name of the parameter.
|
||||
* @param {Number} [index] The index of the parameter.
|
||||
*/
|
||||
remove: function (name, index) {
|
||||
if (index === undefined) {
|
||||
delete this.params[name];
|
||||
}
|
||||
else {
|
||||
this.params[name].splice(index, 1);
|
||||
if (this.params[name].length == 0) {
|
||||
delete this.params[name];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Finds all parameters with matching values.
|
||||
*
|
||||
* @param {String} name The name of the parameter.
|
||||
* @param {String|Number|String[]|Number[]|RegExp} value The value.
|
||||
* @returns {String|Number[]} The indices of the parameters found.
|
||||
*/
|
||||
find: function (name, value) {
|
||||
if (this.params[name] !== undefined) {
|
||||
if (this.isMultiple(name)) {
|
||||
var indices = [];
|
||||
for (var i = 0, l = this.params[name].length; i < l; i++) {
|
||||
if (AjaxSolr.equals(this.params[name][i].val(), value)) {
|
||||
indices.push(i);
|
||||
}
|
||||
}
|
||||
return indices.length ? indices : false;
|
||||
}
|
||||
else {
|
||||
if (AjaxSolr.equals(this.params[name].val(), value)) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* If the parameter may be specified multiple times, creates a parameter using
|
||||
* the given name and value, and adds it to the list of identically-named
|
||||
* parameters, unless one already exists with the same value. If it may be
|
||||
* specified only once, replaces the parameter.
|
||||
*
|
||||
* @param {String} name The name of the parameter.
|
||||
* @param {String|Number|String[]|Number[]} value The value.
|
||||
* @returns {AjaxSolr.Parameter|Boolean} The parameter, or false.
|
||||
*/
|
||||
addByValue: function (name, value) {
|
||||
if (this.isMultiple(name) && AjaxSolr.isArray(value)) {
|
||||
var ret = [];
|
||||
for (var i = 0, l = value.length; i < l; i++) {
|
||||
ret.push(this.add(name, new AjaxSolr.Parameter({ name: name, value: value[i] })));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
else {
|
||||
return this.add(name, new AjaxSolr.Parameter({ name: name, value: value }))
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Deletes any parameter with a matching value.
|
||||
*
|
||||
* @param {String} name The name of the parameter.
|
||||
* @param {String|Number|String[]|Number[]|RegExp} value The value.
|
||||
* @returns {String|Number[]} The indices deleted.
|
||||
*/
|
||||
removeByValue: function (name, value) {
|
||||
var indices = this.find(name, value);
|
||||
if (indices) {
|
||||
if (AjaxSolr.isArray(indices)) {
|
||||
for (var i = indices.length - 1; i >= 0; i--) {
|
||||
this.remove(name, indices[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.remove(indices);
|
||||
}
|
||||
}
|
||||
return indices;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the Solr parameters as a query string.
|
||||
*
|
||||
* <p>IE6 calls the default toString() if you write <tt>store.toString()
|
||||
* </tt>. So, we need to choose another name for toString().</p>
|
||||
*/
|
||||
string: function () {
|
||||
var params = [];
|
||||
for (var name in this.params) {
|
||||
if (this.isMultiple(name)) {
|
||||
for (var i = 0, l = this.params[name].length; i < l; i++) {
|
||||
params.push(this.params[name][i].string());
|
||||
}
|
||||
}
|
||||
else {
|
||||
params.push(this.params[name].string());
|
||||
}
|
||||
}
|
||||
return AjaxSolr.compact(params).join('&');
|
||||
},
|
||||
|
||||
/**
|
||||
* Parses a query string into Solr parameters.
|
||||
*
|
||||
* @param {String} str The string to parse.
|
||||
*/
|
||||
parseString: function (str) {
|
||||
var pairs = str.split('&');
|
||||
for (var i = 0, l = pairs.length; i < l; i++) {
|
||||
if (pairs[i]) { // ignore leading, trailing, and consecutive &'s
|
||||
var param = new AjaxSolr.Parameter();
|
||||
param.parseString(pairs[i]);
|
||||
this.add(param.name, param);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the exposed parameters as a query string.
|
||||
*
|
||||
* @returns {String} A string representation of the exposed parameters.
|
||||
*/
|
||||
exposedString: function () {
|
||||
var params = [];
|
||||
for (var i = 0, l = this.exposed.length; i < l; i++) {
|
||||
if (this.params[this.exposed[i]] !== undefined) {
|
||||
if (this.isMultiple(this.exposed[i])) {
|
||||
for (var j = 0, m = this.params[this.exposed[i]].length; j < m; j++) {
|
||||
params.push(this.params[this.exposed[i]][j].string());
|
||||
}
|
||||
}
|
||||
else {
|
||||
params.push(this.params[this.exposed[i]].string());
|
||||
}
|
||||
}
|
||||
}
|
||||
return AjaxSolr.compact(params).join('&');
|
||||
},
|
||||
|
||||
/**
|
||||
* Resets the values of the exposed parameters.
|
||||
*/
|
||||
exposedReset: function () {
|
||||
for (var i = 0, l = this.exposed.length; i < l; i++) {
|
||||
this.remove(this.exposed[i]);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Loads the values of exposed parameters from persistent storage. It is
|
||||
* necessary, in most cases, to reset the values of exposed parameters before
|
||||
* setting the parameters to the values in storage. This is to ensure that a
|
||||
* parameter whose name is not present in storage is properly reset.
|
||||
*
|
||||
* @param {Boolean} [reset=true] Whether to reset the exposed parameters.
|
||||
* before loading new values from persistent storage. Default: true.
|
||||
*/
|
||||
load: function (reset) {
|
||||
if (reset === undefined) {
|
||||
reset = true;
|
||||
}
|
||||
if (reset) {
|
||||
this.exposedReset();
|
||||
}
|
||||
this.parseString(this.storedString());
|
||||
},
|
||||
|
||||
/**
|
||||
* An abstract hook for child implementations.
|
||||
*
|
||||
* <p>Stores the values of the exposed parameters in persistent storage. This
|
||||
* method should usually be called before each Solr request.</p>
|
||||
*/
|
||||
save: function () {},
|
||||
|
||||
/**
|
||||
* An abstract hook for child implementations.
|
||||
*
|
||||
* <p>Returns the string to parse from persistent storage.</p>
|
||||
*
|
||||
* @returns {String} The string from persistent storage.
|
||||
*/
|
||||
storedString: function () {
|
||||
return '';
|
||||
}
|
||||
});
|
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
// $Id$
|
||||
|
||||
/**
|
||||
* @see http://wiki.apache.org/solr/SolJSON#JSON_specific_parameters
|
||||
* @class Manager
|
||||
* @augments AjaxSolr.AbstractManager
|
||||
*/
|
||||
AjaxSolr.Manager = AjaxSolr.AbstractManager.extend(
|
||||
/** @lends AjaxSolr.Manager.prototype */
|
||||
{
|
||||
executeRequest: function (servlet) {
|
||||
var self = this;
|
||||
if (this.proxyUrl) {
|
||||
jQuery.post(this.proxyUrl, { query: this.store.string() }, function (data) { self.handleResponse(data); }, 'json');
|
||||
}
|
||||
else {
|
||||
// jQuery.getJSON(this.solrUrl + servlet + '?' + this.store.string() + '&wt=json&json.wrf=?', {}, function (data) { self.handleResponse(data); });
|
||||
jQuery.getJSON(this.solrUrl + '?' + this.store.string() + '&wt=json&json.wrf=?', {}, function (data) { self.handleResponse(data); });
|
||||
}
|
||||
}
|
||||
});
|
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
(function ($) {
|
||||
|
||||
$(document).ready(function() {
|
||||
initializeGear();
|
||||
initializeFilters();
|
||||
});
|
||||
|
||||
function initializeGear(){
|
||||
var gearControlsDivs = $('div#aspect_discovery_SimpleSearch_div_search-controls-gear');
|
||||
jQuery.each(gearControlsDivs, function(index, value) {
|
||||
var gearControlsDiv = $(value);
|
||||
var gearControls = gearControlsDiv.find('ul#aspect_discovery_SimpleSearch_list_sort-options');
|
||||
var gearButton = $('<button class="discovery-controls-gear ds-button-field"><div class="gear-icon"> </div></button>');
|
||||
|
||||
gearButton.click(function(){
|
||||
if(gearControls.is(':visible')){
|
||||
gearControls.hide();
|
||||
}else{
|
||||
gearControls.show();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
//Disable the default click
|
||||
gearControls.find('li.gear-option,li.gear-option a').click(function(event){
|
||||
//Ensure that our html click isn't called !
|
||||
event.stopPropagation();
|
||||
var $link = $(this);
|
||||
var listItem;
|
||||
if($link.is('li')){
|
||||
listItem = $link;
|
||||
}else{
|
||||
listItem = $link.parents('li:first');
|
||||
}
|
||||
|
||||
//Check if this option is currently selected, if so skip the next stuff
|
||||
if(listItem.hasClass('gear-option-selected')){
|
||||
return false;
|
||||
}
|
||||
if(!$link.attr('href')){
|
||||
$link = $link.find('a');
|
||||
}
|
||||
//Retrieve the params we are to fill in in our main form
|
||||
var params = $link.attr('href').split('&');
|
||||
|
||||
var mainForm = $('form#aspect_discovery_SimpleSearch_div_main-form');
|
||||
//Split them & fill in in the main form, when done submit the main form !
|
||||
for(var i = 0; i < params.length; i++){
|
||||
var param = params[i].split('=')[0];
|
||||
var value = params[i].split('=')[1];
|
||||
|
||||
mainForm.find('input[name="' + param + '"]').val(value);
|
||||
}
|
||||
//Clear the page param
|
||||
mainForm.find('input[name="page"]').val('1');
|
||||
|
||||
mainForm.submit();
|
||||
return false;
|
||||
});
|
||||
|
||||
gearButton.prependTo(gearControlsDiv);
|
||||
gearControls.hide();
|
||||
|
||||
$('html').click(function() {
|
||||
//Hide the menus if visible
|
||||
if(gearControls.is(':visible')){
|
||||
gearControls.hide();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function initializeFilters(){
|
||||
//Initialize the show filters link
|
||||
$('a[href="display-filters"]').click(function(){
|
||||
var filtersForm = $('form#aspect_discovery_SimpleSearch_div_search-filters');
|
||||
filtersForm.show();
|
||||
filtersForm.css('visibility', 'visible');
|
||||
$(this).hide();
|
||||
return false;
|
||||
});
|
||||
|
||||
$('input[name^="add-filter_"]').click(function(){
|
||||
addFilterRow();
|
||||
|
||||
//Disable "normal" button actions
|
||||
return false;
|
||||
});
|
||||
$('input[name^=remove-filter_]').click(function(){
|
||||
removeFilterRow($(this));
|
||||
return false;
|
||||
});
|
||||
//Disable the enter key !
|
||||
$('input[name^=filter_][type=text]').keypress(function(event){
|
||||
if(event.which == 13){
|
||||
//Entered pressed, do NOT submit the form, add a new filter instead !
|
||||
addFilterRow();
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function removeFilterRow(button){
|
||||
var parentRow = button.parents('tr:first');
|
||||
|
||||
//Check if we are removing a new filter AND our last new filter at that, if so removes values instead of the row
|
||||
if(parentRow.is('[id^="aspect_discovery_SimpleSearch_row_filter-new-"]')
|
||||
&& parentRow.parents('table:first').find('tr[id^="aspect_discovery_SimpleSearch_row_filter-new-"]').length == 1){
|
||||
//Hide ourselves & clear our values!
|
||||
parentRow.find('input[type=text]", select').val('');
|
||||
}else{
|
||||
parentRow.remove();
|
||||
}
|
||||
}
|
||||
|
||||
function addFilterRow(){
|
||||
var previousFilterRow = $('tr#aspect_discovery_SimpleSearch_row_filter-controls').prev();
|
||||
//Duplicate our element & give it a new index !
|
||||
var newFilterRow = previousFilterRow.clone();
|
||||
//Alter the html to update the index
|
||||
var rowIdentifier = newFilterRow.attr('id');
|
||||
var oldIndex = parseInt(rowIdentifier.substr(rowIdentifier.lastIndexOf('-')+1, rowIdentifier.length));
|
||||
//Add one to the index !
|
||||
var newIndex = oldIndex + 1;
|
||||
//Update the index of all inputs & our list
|
||||
newFilterRow.attr('id', newFilterRow.attr('id').replace('-' + oldIndex, '-' + newIndex));
|
||||
newFilterRow.find('input, select').each(function(){
|
||||
var $this = $(this);
|
||||
//Update the index of the name (if present)
|
||||
$this.attr('name', $this.attr('name').replace('_' + oldIndex, '_' + newIndex));
|
||||
$this.attr('id', $this.attr('id').replace('_' + oldIndex, '_' + newIndex));
|
||||
});
|
||||
//Clear the values
|
||||
newFilterRow.find('input[type=text], select').val('');
|
||||
|
||||
previousFilterRow = newFilterRow.insertAfter(previousFilterRow);
|
||||
//Initialize the add button
|
||||
previousFilterRow.find('input[name^="add-filter_"]').click(function(){
|
||||
addFilterRow();
|
||||
return false;
|
||||
});
|
||||
//Initialize the remove button
|
||||
previousFilterRow.find('input[name^=remove-filter_]').click(function(){
|
||||
removeFilterRow($(this));
|
||||
return false;
|
||||
});
|
||||
}
|
||||
})(jQuery);
|
@@ -1,133 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
var Manager;
|
||||
var query;
|
||||
var defaultFacets = new Array();
|
||||
|
||||
(function ($) {
|
||||
$(function () {
|
||||
var searchUrl = $("input[name='discovery-json-search-url']").val();
|
||||
Manager = new AjaxSolr.Manager({
|
||||
solrUrl: searchUrl
|
||||
});
|
||||
|
||||
//Retrieve our filterSelect, which contains all the types to be sorted on
|
||||
var filterSelect = $("select[id='aspect_discovery_SimpleSearch_field_filtertype']");
|
||||
//Get our filters
|
||||
/*
|
||||
var filterOptions = filterSelect.find('option');
|
||||
//Get all the
|
||||
for (var index = 1; index < filterOptions.length; index++){
|
||||
//We skip the first one (for the moment)
|
||||
defaultFacets[index - 1] = filterOptions[index].value;
|
||||
}
|
||||
*/
|
||||
//As a default facet we use the selected value
|
||||
defaultFacets[0] = filterSelect.find('option:selected').val();
|
||||
|
||||
var widget = Manager.addWidget(new AjaxSolr.AutocompleteWidget({
|
||||
id: 'text',
|
||||
target: 'li#aspect_discovery_SimpleSearch_item_search-filter-list',
|
||||
field: 'allText',
|
||||
fields: defaultFacets
|
||||
}));
|
||||
|
||||
Manager.init();
|
||||
|
||||
query = $('input#aspect_discovery_SimpleSearch_field_query').val();
|
||||
if(query == '')
|
||||
query = '*:*';
|
||||
|
||||
Manager.store.addByValue('q', query);
|
||||
//Retrieve our filter queries
|
||||
var fqs = $("input[name='fq']");
|
||||
for(var j = 0; j < fqs.length; j ++){
|
||||
Manager.store.addByValue('fq', $(fqs[j]).val());
|
||||
}
|
||||
Manager.store.addByValue('facet.sort', 'count');
|
||||
|
||||
|
||||
var params = {
|
||||
facet: true,
|
||||
'facet.field': defaultFacets,
|
||||
'facet.limit': 20,
|
||||
'facet.mincount': 1,
|
||||
'f.topics.facet.limit': 50,
|
||||
'json.nl': 'map'
|
||||
};
|
||||
for (var name in params) {
|
||||
Manager.store.addByValue(name, params[name]);
|
||||
}
|
||||
|
||||
//Attempt to add our scope !
|
||||
var scope = $("input[name='discovery-json-scope']").val();
|
||||
if(scope != undefined){
|
||||
Manager.store.addByValue("scope", scope);
|
||||
}
|
||||
|
||||
Manager.doRequest();
|
||||
|
||||
filterSelect.change(function() {
|
||||
// TODO: this is dirty, but with lack of time the best I could do
|
||||
var oldInput = $('input#aspect_discovery_SimpleSearch_field_filter');
|
||||
var newInput = oldInput.clone(false);
|
||||
|
||||
// newInput.val(oldInput.val());
|
||||
newInput.appendTo(oldInput.parent());
|
||||
oldInput.remove();
|
||||
|
||||
//Remove any results lists we may still have standing
|
||||
$("div#discovery_autocomplete_div").remove();
|
||||
//Put the field in which our facet is going to facet into the widget
|
||||
var facetFields;
|
||||
|
||||
if($(this).val() != '*'){
|
||||
var facetVal = $(this).val();
|
||||
//Only facet on autocomplete fields
|
||||
// if(!facetVal.match(/.year$/)){
|
||||
// facetVal += '_ac';
|
||||
// }
|
||||
facetFields = [facetVal];
|
||||
} else {
|
||||
facetFields = defaultFacets;
|
||||
}
|
||||
|
||||
Manager.widgets.text.fields = facetFields;
|
||||
Manager.initialized = false;
|
||||
|
||||
Manager.init();
|
||||
//TODO: does this need to happen twice ?
|
||||
Manager.store.addByValue('q', query);
|
||||
//Retrieve our filter queries
|
||||
var fqs = $("input[name='fq']");
|
||||
for(var j = 0; j < fqs.length; j ++){
|
||||
Manager.store.addByValue('fq', $(fqs[j]).val());
|
||||
}
|
||||
Manager.store.addByValue('facet.sort', 'count');
|
||||
|
||||
var params = {
|
||||
facet: true,
|
||||
'facet.field': facetFields,
|
||||
'facet.limit': 20,
|
||||
'facet.mincount': 1,
|
||||
'f.topics.facet.limit': 50,
|
||||
'json.nl': 'map'
|
||||
};
|
||||
for (var name in params) {
|
||||
Manager.store.addByValue(name, params[name]);
|
||||
}
|
||||
|
||||
//Attempt to add our scope !
|
||||
var scope = $("input[name='discovery-json-scope']").val();
|
||||
if(scope != undefined){
|
||||
Manager.store.addByValue("scope", scope);
|
||||
}
|
||||
Manager.doRequest();
|
||||
});
|
||||
});
|
||||
})(jQuery);
|
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
(function ($) {
|
||||
|
||||
AjaxSolr.AutocompleteWidget = AjaxSolr.AbstractFacetWidget.extend({
|
||||
|
||||
afterRequest: function () {
|
||||
|
||||
$(this.target).find("input[type='text']").val('');
|
||||
|
||||
var self = this;
|
||||
|
||||
var callback = function (response) {
|
||||
var list = [];
|
||||
for (var field in response.facet_counts.facet_fields) {
|
||||
for (var facet in response.facet_counts.facet_fields[field]) {
|
||||
list.push({
|
||||
field: field,
|
||||
value: facet,
|
||||
text: facet + ' (' + response.facet_counts.facet_fields[field][facet] + ')'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
self.requestSent = false;
|
||||
$(self.target).find("input[type='text']").autocomplete(list, {
|
||||
formatItem: function(facet) {
|
||||
return facet.text;
|
||||
}
|
||||
}).result(function(e, facet) {
|
||||
$(this).val(facet.value);
|
||||
// self.requestSent = true;
|
||||
// if (self.manager.store.addByValue('fq', facet.field + ':' + facet.value)) {
|
||||
// self.manager.doRequest(0);
|
||||
// }
|
||||
}).bind('keydown', function(e) {
|
||||
if (self.requestSent === false && e.which == 13) {
|
||||
var value = $(this).val();
|
||||
if (value && self.add(value)) {
|
||||
self.manager.doRequest(0);
|
||||
}
|
||||
}
|
||||
});
|
||||
}; // end callback
|
||||
|
||||
var params = [ 'q=' + query + '&facet=true&facet.limit=-1&facet.sort=count&facet.mincount=1&json.nl=map' ];
|
||||
for (var i = 0; i < this.fields.length; i++) {
|
||||
params.push('facet.field=' + this.fields[i]);
|
||||
}
|
||||
var fqs = $("input[name='fq']");
|
||||
for(var j = 0; j < fqs.length; j ++){
|
||||
params.push('fq=' + encodeURIComponent($(fqs[j]).val()));
|
||||
}
|
||||
//Attempt to add our scope !
|
||||
var scope = $("input[name='discovery-json-scope']").val();
|
||||
if(scope != undefined){
|
||||
params.push("scope=" + scope);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// jQuery.getJSON(this.manager.solrUrl + 'select?' + params.join('&') + '&wt=json&json.wrf=?', {}, callback);
|
||||
jQuery.getJSON(this.manager.solrUrl + '?' + params.join('&') + '&wt=json&json.wrf=?', {}, callback);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
})(jQuery);
|
@@ -1,20 +0,0 @@
|
||||
Copyright (c) 2010 John Resig, http://jquery.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -1,799 +0,0 @@
|
||||
;(function($) {
|
||||
|
||||
$.fn.extend({
|
||||
autocomplete: function(urlOrData, options) {
|
||||
var isUrl = typeof urlOrData == "string";
|
||||
options = $.extend({}, $.Autocompleter.defaults, {
|
||||
url: isUrl ? urlOrData : null,
|
||||
data: isUrl ? null : urlOrData,
|
||||
delay: isUrl ? $.Autocompleter.defaults.delay : 10,
|
||||
max: options && !options.scroll ? 10 : 150
|
||||
}, options);
|
||||
|
||||
// if highlight is set to false, replace it with a do-nothing function
|
||||
options.highlight = options.highlight || function(value) { return value; };
|
||||
|
||||
// if the formatMatch option is not specified, then use formatItem for backwards compatibility
|
||||
options.formatMatch = options.formatMatch || options.formatItem;
|
||||
|
||||
return this.each(function() {
|
||||
new $.Autocompleter(this, options);
|
||||
});
|
||||
},
|
||||
result: function(handler) {
|
||||
return this.bind("result", handler);
|
||||
},
|
||||
search: function(handler) {
|
||||
return this.trigger("search", [handler]);
|
||||
},
|
||||
flushCache: function() {
|
||||
return this.trigger("flushCache");
|
||||
},
|
||||
setOptions: function(options){
|
||||
return this.trigger("setOptions", [options]);
|
||||
},
|
||||
unautocomplete: function() {
|
||||
return this.trigger("unautocomplete");
|
||||
}
|
||||
});
|
||||
|
||||
$.Autocompleter = function(input, options) {
|
||||
|
||||
var KEY = {
|
||||
UP: 38,
|
||||
DOWN: 40,
|
||||
DEL: 46,
|
||||
TAB: 9,
|
||||
RETURN: 13,
|
||||
ESC: 27,
|
||||
COMMA: 188,
|
||||
PAGEUP: 33,
|
||||
PAGEDOWN: 34,
|
||||
BACKSPACE: 8
|
||||
};
|
||||
|
||||
// Create $ object for input element
|
||||
var $input = $(input).attr("autocomplete", "off").addClass(options.inputClass);
|
||||
|
||||
var timeout;
|
||||
var previousValue = "";
|
||||
var cache = $.Autocompleter.Cache(options);
|
||||
var hasFocus = 0;
|
||||
var lastKeyPressCode;
|
||||
var config = {
|
||||
mouseDownOnSelect: false
|
||||
};
|
||||
var select = $.Autocompleter.Select(options, input, selectCurrent, config);
|
||||
|
||||
var blockSubmit;
|
||||
|
||||
// prevent form submit in opera when selecting with return key
|
||||
$.browser.opera && $(input.form).bind("submit.autocomplete", function() {
|
||||
if (blockSubmit) {
|
||||
blockSubmit = false;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// only opera doesn't trigger keydown multiple times while pressed, others don't work with keypress at all
|
||||
$input.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete", function(event) {
|
||||
// a keypress means the input has focus
|
||||
// avoids issue where input had focus before the autocomplete was applied
|
||||
hasFocus = 1;
|
||||
// track last key pressed
|
||||
lastKeyPressCode = event.keyCode;
|
||||
switch(event.keyCode) {
|
||||
|
||||
case KEY.UP:
|
||||
event.preventDefault();
|
||||
if ( select.visible() ) {
|
||||
select.prev();
|
||||
} else {
|
||||
onChange(0, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY.DOWN:
|
||||
event.preventDefault();
|
||||
if ( select.visible() ) {
|
||||
select.next();
|
||||
} else {
|
||||
onChange(0, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY.PAGEUP:
|
||||
event.preventDefault();
|
||||
if ( select.visible() ) {
|
||||
select.pageUp();
|
||||
} else {
|
||||
onChange(0, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY.PAGEDOWN:
|
||||
event.preventDefault();
|
||||
if ( select.visible() ) {
|
||||
select.pageDown();
|
||||
} else {
|
||||
onChange(0, true);
|
||||
}
|
||||
break;
|
||||
|
||||
// matches also semicolon
|
||||
case options.multiple && $.trim(options.multipleSeparator) == "," && KEY.COMMA:
|
||||
case KEY.TAB:
|
||||
case KEY.RETURN:
|
||||
if( selectCurrent() ) {
|
||||
// stop default to prevent a form submit, Opera needs special handling
|
||||
event.preventDefault();
|
||||
blockSubmit = true;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY.ESC:
|
||||
select.hide();
|
||||
break;
|
||||
|
||||
default:
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(onChange, options.delay);
|
||||
break;
|
||||
}
|
||||
}).focus(function(){
|
||||
// track whether the field has focus, we shouldn't process any
|
||||
// results if the field no longer has focus
|
||||
hasFocus++;
|
||||
}).blur(function() {
|
||||
hasFocus = 0;
|
||||
if (!config.mouseDownOnSelect) {
|
||||
hideResults();
|
||||
}
|
||||
}).click(function() {
|
||||
// show select when clicking in a focused field
|
||||
if ( hasFocus++ > 1 && !select.visible() ) {
|
||||
onChange(0, true);
|
||||
}
|
||||
}).bind("search", function() {
|
||||
// TODO why not just specifying both arguments?
|
||||
var fn = (arguments.length > 1) ? arguments[1] : null;
|
||||
function findValueCallback(q, data) {
|
||||
var result;
|
||||
if( data && data.length ) {
|
||||
for (var i=0; i < data.length; i++) {
|
||||
if( data[i].result.toLowerCase() == q.toLowerCase() ) {
|
||||
result = data[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( typeof fn == "function" ) fn(result);
|
||||
else $input.trigger("result", result && [result.data, result.value]);
|
||||
}
|
||||
$.each(trimWords($input.val()), function(i, value) {
|
||||
request(value, findValueCallback, findValueCallback);
|
||||
});
|
||||
}).bind("flushCache", function() {
|
||||
cache.flush();
|
||||
}).bind("setOptions", function() {
|
||||
$.extend(options, arguments[1]);
|
||||
// if we've updated the data, repopulate
|
||||
if ( "data" in arguments[1] )
|
||||
cache.populate();
|
||||
}).bind("unautocomplete", function() {
|
||||
select.unbind();
|
||||
$input.unbind();
|
||||
$(input.form).unbind(".autocomplete");
|
||||
});
|
||||
|
||||
|
||||
function selectCurrent() {
|
||||
var selected = select.selected();
|
||||
if( !selected )
|
||||
return false;
|
||||
|
||||
var v = selected.result;
|
||||
previousValue = v;
|
||||
|
||||
if ( options.multiple ) {
|
||||
var words = trimWords($input.val());
|
||||
if ( words.length > 1 ) {
|
||||
var separator = options.multipleSeparator.length;
|
||||
var cursorAt = $(input).selection().start;
|
||||
var wordAt, progress = 0;
|
||||
$.each(words, function(i, word) {
|
||||
progress += word.length;
|
||||
if (cursorAt <= progress) {
|
||||
wordAt = i;
|
||||
return false;
|
||||
}
|
||||
progress += separator;
|
||||
});
|
||||
words[wordAt] = v;
|
||||
// TODO this should set the cursor to the right position, but it gets overriden somewhere
|
||||
//$.Autocompleter.Selection(input, progress + separator, progress + separator);
|
||||
v = words.join( options.multipleSeparator );
|
||||
}
|
||||
v += options.multipleSeparator;
|
||||
}
|
||||
|
||||
$input.val(v);
|
||||
hideResultsNow();
|
||||
$input.trigger("result", [selected.data, selected.value]);
|
||||
return true;
|
||||
}
|
||||
|
||||
function onChange(crap, skipPrevCheck) {
|
||||
if( lastKeyPressCode == KEY.DEL ) {
|
||||
select.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
var currentValue = $input.val();
|
||||
|
||||
if ( !skipPrevCheck && currentValue == previousValue )
|
||||
return;
|
||||
|
||||
previousValue = currentValue;
|
||||
|
||||
currentValue = lastWord(currentValue);
|
||||
if ( currentValue.length >= options.minChars) {
|
||||
$input.addClass(options.loadingClass);
|
||||
if (!options.matchCase)
|
||||
currentValue = currentValue.toLowerCase();
|
||||
request(currentValue, receiveData, hideResultsNow);
|
||||
} else {
|
||||
stopLoading();
|
||||
select.hide();
|
||||
}
|
||||
};
|
||||
|
||||
function trimWords(value) {
|
||||
if (!value)
|
||||
return [""];
|
||||
if (!options.multiple)
|
||||
return [$.trim(value)];
|
||||
return $.map(value.split(options.multipleSeparator), function(word) {
|
||||
return $.trim(value).length ? $.trim(word) : null;
|
||||
});
|
||||
}
|
||||
|
||||
function lastWord(value) {
|
||||
if ( !options.multiple )
|
||||
return value;
|
||||
var words = trimWords(value);
|
||||
if (words.length == 1)
|
||||
return words[0];
|
||||
var cursorAt = $(input).selection().start;
|
||||
if (cursorAt == value.length) {
|
||||
words = trimWords(value)
|
||||
} else {
|
||||
words = trimWords(value.replace(value.substring(cursorAt), ""));
|
||||
}
|
||||
return words[words.length - 1];
|
||||
}
|
||||
|
||||
// fills in the input box w/the first match (assumed to be the best match)
|
||||
// q: the term entered
|
||||
// sValue: the first matching result
|
||||
function autoFill(q, sValue){
|
||||
// autofill in the complete box w/the first match as long as the user hasn't entered in more data
|
||||
// if the last user key pressed was backspace, don't autofill
|
||||
if( options.autoFill && (lastWord($input.val()).toLowerCase() == q.toLowerCase()) && lastKeyPressCode != KEY.BACKSPACE ) {
|
||||
// fill in the value (keep the case the user has typed)
|
||||
$input.val($input.val() + sValue.substring(lastWord(previousValue).length));
|
||||
// select the portion of the value not typed by the user (so the next character will erase)
|
||||
$(input).selection(previousValue.length, previousValue.length + sValue.length);
|
||||
}
|
||||
};
|
||||
|
||||
function hideResults() {
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(hideResultsNow, 200);
|
||||
};
|
||||
|
||||
function hideResultsNow() {
|
||||
var wasVisible = select.visible();
|
||||
select.hide();
|
||||
clearTimeout(timeout);
|
||||
stopLoading();
|
||||
if (options.mustMatch) {
|
||||
// call search and run callback
|
||||
$input.search(
|
||||
function (result){
|
||||
// if no value found, clear the input box
|
||||
if( !result ) {
|
||||
if (options.multiple) {
|
||||
var words = trimWords($input.val()).slice(0, -1);
|
||||
$input.val( words.join(options.multipleSeparator) + (words.length ? options.multipleSeparator : "") );
|
||||
}
|
||||
else {
|
||||
$input.val( "" );
|
||||
$input.trigger("result", null);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
function receiveData(q, data) {
|
||||
if ( data && data.length && hasFocus ) {
|
||||
stopLoading();
|
||||
select.display(data, q);
|
||||
autoFill(q, data[0].value);
|
||||
select.show();
|
||||
} else {
|
||||
hideResultsNow();
|
||||
}
|
||||
};
|
||||
|
||||
function request(term, success, failure) {
|
||||
if (!options.matchCase)
|
||||
term = term.toLowerCase();
|
||||
var data = cache.load(term);
|
||||
// receive the cached data
|
||||
if (data && data.length) {
|
||||
success(term, data);
|
||||
// if an AJAX url has been supplied, try loading the data now
|
||||
} else if( (typeof options.url == "string") && (options.url.length > 0) ){
|
||||
|
||||
var extraParams = {
|
||||
timestamp: +new Date()
|
||||
};
|
||||
$.each(options.extraParams, function(key, param) {
|
||||
extraParams[key] = typeof param == "function" ? param() : param;
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
// try to leverage ajaxQueue plugin to abort previous requests
|
||||
mode: "abort",
|
||||
// limit abortion to this input
|
||||
port: "autocomplete" + input.name,
|
||||
dataType: options.dataType,
|
||||
url: options.url,
|
||||
data: $.extend({
|
||||
q: lastWord(term),
|
||||
limit: options.max
|
||||
}, extraParams),
|
||||
success: function(data) {
|
||||
var parsed = options.parse && options.parse(data) || parse(data);
|
||||
cache.add(term, parsed);
|
||||
success(term, parsed);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// if we have a failure, we need to empty the list -- this prevents the the [TAB] key from selecting the last successful match
|
||||
select.emptyList();
|
||||
failure(term);
|
||||
}
|
||||
};
|
||||
|
||||
function parse(data) {
|
||||
var parsed = [];
|
||||
var rows = data.split("\n");
|
||||
for (var i=0; i < rows.length; i++) {
|
||||
var row = $.trim(rows[i]);
|
||||
if (row) {
|
||||
row = row.split("|");
|
||||
parsed[parsed.length] = {
|
||||
data: row,
|
||||
value: row[0],
|
||||
result: options.formatResult && options.formatResult(row, row[0]) || row[0]
|
||||
};
|
||||
}
|
||||
}
|
||||
return parsed;
|
||||
};
|
||||
|
||||
function stopLoading() {
|
||||
$input.removeClass(options.loadingClass);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
$.Autocompleter.defaults = {
|
||||
inputClass: "ac_input",
|
||||
resultId: "discovery_autocomplete_div",
|
||||
resultsClass: "ac_results",
|
||||
loadingClass: "ac_loading",
|
||||
minChars: 1,
|
||||
delay: 400,
|
||||
matchCase: false,
|
||||
matchSubset: true,
|
||||
matchContains: false,
|
||||
cacheLength: 10,
|
||||
max: 100,
|
||||
mustMatch: false,
|
||||
extraParams: {},
|
||||
selectFirst: true,
|
||||
formatItem: function(row) { return row[0]; },
|
||||
formatMatch: null,
|
||||
autoFill: false,
|
||||
width: 0,
|
||||
multiple: false,
|
||||
multipleSeparator: ", ",
|
||||
highlight: function(value, term) {
|
||||
return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>");
|
||||
},
|
||||
scroll: true,
|
||||
scrollHeight: 180
|
||||
};
|
||||
|
||||
$.Autocompleter.Cache = function(options) {
|
||||
|
||||
var data = {};
|
||||
var length = 0;
|
||||
|
||||
function matchSubset(s, sub) {
|
||||
if (!options.matchCase)
|
||||
s = s.toLowerCase();
|
||||
var i = s.indexOf(sub);
|
||||
if (options.matchContains == "word"){
|
||||
i = s.toLowerCase().search("\\b" + sub.toLowerCase());
|
||||
}
|
||||
if (i == -1) return false;
|
||||
return i == 0 || options.matchContains;
|
||||
};
|
||||
|
||||
function add(q, value) {
|
||||
if (length > options.cacheLength){
|
||||
flush();
|
||||
}
|
||||
if (!data[q]){
|
||||
length++;
|
||||
}
|
||||
data[q] = value;
|
||||
}
|
||||
|
||||
function populate(){
|
||||
if( !options.data ) return false;
|
||||
// track the matches
|
||||
var stMatchSets = {},
|
||||
nullData = 0;
|
||||
|
||||
// no url was specified, we need to adjust the cache length to make sure it fits the local data store
|
||||
if( !options.url ) options.cacheLength = 1;
|
||||
|
||||
// track all options for minChars = 0
|
||||
stMatchSets[""] = [];
|
||||
|
||||
// loop through the array and create a lookup structure
|
||||
for ( var i = 0, ol = options.data.length; i < ol; i++ ) {
|
||||
var rawValue = options.data[i];
|
||||
// if rawValue is a string, make an array otherwise just reference the array
|
||||
rawValue = (typeof rawValue == "string") ? [rawValue] : rawValue;
|
||||
|
||||
var value = options.formatMatch(rawValue, i+1, options.data.length);
|
||||
if ( value === false )
|
||||
continue;
|
||||
|
||||
var firstChar = value.charAt(0).toLowerCase();
|
||||
// if no lookup array for this character exists, look it up now
|
||||
if( !stMatchSets[firstChar] )
|
||||
stMatchSets[firstChar] = [];
|
||||
|
||||
// if the match is a string
|
||||
var row = {
|
||||
value: value,
|
||||
data: rawValue,
|
||||
result: options.formatResult && options.formatResult(rawValue) || value
|
||||
};
|
||||
|
||||
// push the current match into the set list
|
||||
stMatchSets[firstChar].push(row);
|
||||
|
||||
// keep track of minChars zero items
|
||||
if ( nullData++ < options.max ) {
|
||||
stMatchSets[""].push(row);
|
||||
}
|
||||
};
|
||||
|
||||
// add the data items to the cache
|
||||
$.each(stMatchSets, function(i, value) {
|
||||
// increase the cache size
|
||||
options.cacheLength++;
|
||||
// add to the cache
|
||||
add(i, value);
|
||||
});
|
||||
}
|
||||
|
||||
// populate any existing data
|
||||
setTimeout(populate, 25);
|
||||
|
||||
function flush(){
|
||||
data = {};
|
||||
length = 0;
|
||||
}
|
||||
|
||||
return {
|
||||
flush: flush,
|
||||
add: add,
|
||||
populate: populate,
|
||||
load: function(q) {
|
||||
if (!options.cacheLength || !length)
|
||||
return null;
|
||||
/*
|
||||
* if dealing w/local data and matchContains than we must make sure
|
||||
* to loop through all the data collections looking for matches
|
||||
*/
|
||||
if( !options.url && options.matchContains ){
|
||||
// track all matches
|
||||
var csub = [];
|
||||
// loop through all the data grids for matches
|
||||
for( var k in data ){
|
||||
// don't search through the stMatchSets[""] (minChars: 0) cache
|
||||
// this prevents duplicates
|
||||
if( k.length > 0 ){
|
||||
var c = data[k];
|
||||
$.each(c, function(i, x) {
|
||||
// if we've got a match, add it to the array
|
||||
if (matchSubset(x.value, q)) {
|
||||
csub.push(x);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return csub;
|
||||
} else
|
||||
// if the exact item exists, use it
|
||||
if (data[q]){
|
||||
return data[q];
|
||||
} else
|
||||
if (options.matchSubset) {
|
||||
for (var i = q.length - 1; i >= options.minChars; i--) {
|
||||
var c = data[q.substr(0, i)];
|
||||
if (c) {
|
||||
var csub = [];
|
||||
$.each(c, function(i, x) {
|
||||
if (matchSubset(x.value, q)) {
|
||||
csub[csub.length] = x;
|
||||
}
|
||||
});
|
||||
return csub;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
$.Autocompleter.Select = function (options, input, select, config) {
|
||||
var CLASSES = {
|
||||
ACTIVE: "ac_over"
|
||||
};
|
||||
|
||||
var listItems,
|
||||
active = -1,
|
||||
data,
|
||||
term = "",
|
||||
needsInit = true,
|
||||
element,
|
||||
list;
|
||||
|
||||
// Create results
|
||||
function init() {
|
||||
if (!needsInit)
|
||||
return;
|
||||
|
||||
element = $("<div/>")
|
||||
.hide()
|
||||
.addClass(options.resultsClass)
|
||||
.attr("id", options.resultId)
|
||||
.css("position", "absolute")
|
||||
.appendTo(document.body);
|
||||
|
||||
list = $("<ul/>").appendTo(element).mouseover( function(event) {
|
||||
if(target(event).nodeName && target(event).nodeName.toUpperCase() == 'LI') {
|
||||
active = $("li", list).removeClass(CLASSES.ACTIVE).index(target(event));
|
||||
$(target(event)).addClass(CLASSES.ACTIVE);
|
||||
}
|
||||
}).click(function(event) {
|
||||
$(target(event)).addClass(CLASSES.ACTIVE);
|
||||
select();
|
||||
// TODO provide option to avoid setting focus again after selection? useful for cleanup-on-focus
|
||||
input.focus();
|
||||
return false;
|
||||
}).mousedown(function() {
|
||||
config.mouseDownOnSelect = true;
|
||||
}).mouseup(function() {
|
||||
config.mouseDownOnSelect = false;
|
||||
});
|
||||
|
||||
if( options.width > 0 )
|
||||
element.css("width", options.width);
|
||||
|
||||
needsInit = false;
|
||||
}
|
||||
|
||||
function target(event) {
|
||||
var element = event.target;
|
||||
while(element && element.tagName != "LI")
|
||||
element = element.parentNode;
|
||||
// more fun with IE, sometimes event.target is empty, just ignore it then
|
||||
if(!element)
|
||||
return [];
|
||||
return element;
|
||||
}
|
||||
|
||||
function moveSelect(step) {
|
||||
listItems.slice(active, active + 1).removeClass(CLASSES.ACTIVE);
|
||||
movePosition(step);
|
||||
var activeItem = listItems.slice(active, active + 1).addClass(CLASSES.ACTIVE);
|
||||
if(options.scroll) {
|
||||
var offset = 0;
|
||||
listItems.slice(0, active).each(function() {
|
||||
offset += this.offsetHeight;
|
||||
});
|
||||
if((offset + activeItem[0].offsetHeight - list.scrollTop()) > list[0].clientHeight) {
|
||||
list.scrollTop(offset + activeItem[0].offsetHeight - list.innerHeight());
|
||||
} else if(offset < list.scrollTop()) {
|
||||
list.scrollTop(offset);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function movePosition(step) {
|
||||
active += step;
|
||||
if (active < 0) {
|
||||
active = listItems.size() - 1;
|
||||
} else if (active >= listItems.size()) {
|
||||
active = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function limitNumberOfItems(available) {
|
||||
return options.max && options.max < available
|
||||
? options.max
|
||||
: available;
|
||||
}
|
||||
|
||||
function fillList() {
|
||||
list.empty();
|
||||
var max = limitNumberOfItems(data.length);
|
||||
for (var i=0; i < max; i++) {
|
||||
if (!data[i])
|
||||
continue;
|
||||
var formatted = options.formatItem(data[i].data, i+1, max, data[i].value, term);
|
||||
if ( formatted === false )
|
||||
continue;
|
||||
var li = $("<li/>").html( options.highlight(formatted, term) ).addClass(i%2 == 0 ? "ac_even" : "ac_odd").appendTo(list)[0];
|
||||
$.data(li, "ac_data", data[i]);
|
||||
}
|
||||
listItems = list.find("li");
|
||||
if ( options.selectFirst ) {
|
||||
listItems.slice(0, 1).addClass(CLASSES.ACTIVE);
|
||||
active = 0;
|
||||
}
|
||||
// apply bgiframe if available
|
||||
if ( $.fn.bgiframe )
|
||||
list.bgiframe();
|
||||
}
|
||||
|
||||
return {
|
||||
display: function(d, q) {
|
||||
init();
|
||||
data = d;
|
||||
term = q;
|
||||
fillList();
|
||||
},
|
||||
next: function() {
|
||||
moveSelect(1);
|
||||
},
|
||||
prev: function() {
|
||||
moveSelect(-1);
|
||||
},
|
||||
pageUp: function() {
|
||||
if (active != 0 && active - 8 < 0) {
|
||||
moveSelect( -active );
|
||||
} else {
|
||||
moveSelect(-8);
|
||||
}
|
||||
},
|
||||
pageDown: function() {
|
||||
if (active != listItems.size() - 1 && active + 8 > listItems.size()) {
|
||||
moveSelect( listItems.size() - 1 - active );
|
||||
} else {
|
||||
moveSelect(8);
|
||||
}
|
||||
},
|
||||
hide: function() {
|
||||
element && element.hide();
|
||||
listItems && listItems.removeClass(CLASSES.ACTIVE);
|
||||
active = -1;
|
||||
},
|
||||
visible : function() {
|
||||
return element && element.is(":visible");
|
||||
},
|
||||
current: function() {
|
||||
return this.visible() && (listItems.filter("." + CLASSES.ACTIVE)[0] || options.selectFirst && listItems[0]);
|
||||
},
|
||||
show: function() {
|
||||
var offset = $(input).offset();
|
||||
element.css({
|
||||
width: typeof options.width == "string" || options.width > 0 ? options.width : $(input).width(),
|
||||
top: offset.top + input.offsetHeight,
|
||||
left: offset.left
|
||||
}).show();
|
||||
if(options.scroll) {
|
||||
list.scrollTop(0);
|
||||
list.css({
|
||||
maxHeight: options.scrollHeight,
|
||||
overflow: 'auto'
|
||||
});
|
||||
|
||||
if($.browser.msie && typeof document.body.style.maxHeight === "undefined") {
|
||||
var listHeight = 0;
|
||||
listItems.each(function() {
|
||||
listHeight += this.offsetHeight;
|
||||
});
|
||||
var scrollbarsVisible = listHeight > options.scrollHeight;
|
||||
list.css('height', scrollbarsVisible ? options.scrollHeight : listHeight );
|
||||
if (!scrollbarsVisible) {
|
||||
// IE doesn't recalculate width when scrollbar disappears
|
||||
listItems.width( list.width() - parseInt(listItems.css("padding-left")) - parseInt(listItems.css("padding-right")) );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
selected: function() {
|
||||
var selected = listItems && listItems.filter("." + CLASSES.ACTIVE).removeClass(CLASSES.ACTIVE);
|
||||
return selected && selected.length && $.data(selected[0], "ac_data");
|
||||
},
|
||||
emptyList: function (){
|
||||
list && list.empty();
|
||||
},
|
||||
unbind: function() {
|
||||
element && element.remove();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
$.fn.selection = function(start, end) {
|
||||
if (start !== undefined) {
|
||||
return this.each(function() {
|
||||
if( this.createTextRange ){
|
||||
var selRange = this.createTextRange();
|
||||
if (end === undefined || start == end) {
|
||||
selRange.move("character", start);
|
||||
selRange.select();
|
||||
} else {
|
||||
selRange.collapse(true);
|
||||
selRange.moveStart("character", start);
|
||||
selRange.moveEnd("character", end);
|
||||
selRange.select();
|
||||
}
|
||||
} else if( this.setSelectionRange ){
|
||||
this.setSelectionRange(start, end);
|
||||
} else if( this.selectionStart ){
|
||||
this.selectionStart = start;
|
||||
this.selectionEnd = end;
|
||||
}
|
||||
});
|
||||
}
|
||||
var field = this[0];
|
||||
if ( field.createTextRange ) {
|
||||
var range = document.selection.createRange(),
|
||||
orig = field.value,
|
||||
teststring = "<->",
|
||||
textLength = range.text.length;
|
||||
range.text = teststring;
|
||||
var caretAt = field.value.indexOf(teststring);
|
||||
field.value = orig;
|
||||
this.selection(caretAt, caretAt + textLength);
|
||||
return {
|
||||
start: caretAt,
|
||||
end: caretAt + textLength
|
||||
}
|
||||
} else if( field.selectionStart !== undefined ){
|
||||
return {
|
||||
start: field.selectionStart,
|
||||
end: field.selectionEnd
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
})(jQuery);
|
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 3.0 KiB |
@@ -288,6 +288,8 @@ div.pagination {
|
||||
div.pagination-masked {
|
||||
position: relative;
|
||||
margin: 10px 20px 10px 20px;
|
||||
/*Property below is required for IE7 when using discovery*/
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
a.previous-page-link {
|
||||
@@ -886,3 +888,81 @@ margin: 2px 2px 0px 2px;
|
||||
/* border: 1px solid rgb(240, 240, 210); */
|
||||
}
|
||||
|
||||
/* Start discovery layout DSpace 3.x*/
|
||||
div.discoverySearchBox label{
|
||||
width: auto;
|
||||
}
|
||||
|
||||
input#aspect_discovery_SimpleSearch_field_query{
|
||||
width: 700px;
|
||||
}
|
||||
|
||||
input.search-icon{
|
||||
background-image: url('../images/search_icon_000000_20x20.png');
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
text-indent: -1000px;
|
||||
/*Css props below are required for IE*/
|
||||
font-size: 0;
|
||||
line-height: 0;
|
||||
background-color: #F3F3F3;
|
||||
border: 1px solid #000000;
|
||||
}
|
||||
|
||||
|
||||
div.controls-gear-wrapper{
|
||||
float: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
div.gear-icon{
|
||||
background-image: url('../images/gear_000000_25x25.png');
|
||||
}
|
||||
|
||||
ul.gear-selection li.gear-option-selected{
|
||||
background: url('../images/check_606060_15x15.png') no-repeat 3px center;
|
||||
}
|
||||
|
||||
|
||||
table.discovery-filters input.filter-control {
|
||||
width: 30px;
|
||||
margin-left: 5px;
|
||||
text-indent: -1000px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
height: 22px;
|
||||
float: left;
|
||||
/*Css props below are required for IE*/
|
||||
font-size: 0;
|
||||
display:block;
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
table.discovery-filters input.filter-control.filter-remove{
|
||||
margin-left: 15px;
|
||||
background-image: url('../images/remove_icon_000000_16x16.png');
|
||||
background-color: #F3F3F3;
|
||||
border: 1px solid #000000;
|
||||
}
|
||||
|
||||
table.discovery-filters input.filter-control.filter-add{
|
||||
background-image: url('../images/plus_icon_000000_16x16.png');
|
||||
background-color: #F3F3F3;
|
||||
border: 1px solid #000000;
|
||||
}
|
||||
|
||||
ul.gear-selection{
|
||||
left: 0;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
ul.gear-selection li {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
div#aspect_discovery_SimpleSearch_div_search a.previous-page-link {
|
||||
left: 80px;
|
||||
}
|
||||
|
||||
/* End discovery layout DSpace 3.x*/
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 3.0 KiB |
@@ -816,52 +816,73 @@ td select.ds-select-field {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
form.search {
|
||||
form.search,
|
||||
div.discoverySearchBox
|
||||
{
|
||||
background-color: #fafafa;
|
||||
border: 1px solid #ebebeb;
|
||||
padding: 10px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
form.search label {
|
||||
form.search label,
|
||||
div.discoverySearchBox label
|
||||
{
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
form.search p.ds-paragraph.button-list {
|
||||
form.search p.ds-paragraph.button-list,
|
||||
div.discoverySearchBox p.ds-paragraph.button-list
|
||||
{
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
form.search fieldset {
|
||||
form.search fieldset,
|
||||
div.discoverySearchBox fieldset {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
form.search .ds-form-item {
|
||||
form.search .ds-form-item,
|
||||
div.discoverySearchBox .ds-form-item
|
||||
{
|
||||
margin: 0;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
form.search .ds-form-item select{
|
||||
form.search .ds-form-item select,
|
||||
div.discoverySearchBox .ds-form-item select
|
||||
{
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
form.search label.ds-composite-component .ds-select-field{
|
||||
form.search label.ds-composite-component .ds-select-field,
|
||||
div.discoverySearchBox label.ds-composite-component .ds-select-field
|
||||
{
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
form.search .ds-form-item label {
|
||||
form.search .ds-form-item label,
|
||||
div.discoverySearchBox .ds-form-item label
|
||||
{
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
form.search .ds-form-content {
|
||||
form.search .ds-form-content,
|
||||
div.discoverySearchBox .ds-form-content
|
||||
{
|
||||
display: inline;
|
||||
}
|
||||
|
||||
form.search table input.ds-text-field {
|
||||
form.search table input.ds-text-field,
|
||||
div.discoverySearchBox table input.ds-text-field
|
||||
{
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
form.search .field-help {
|
||||
form.search .field-help,
|
||||
div.discoverySearchBox .field-help
|
||||
{
|
||||
margin: 3px 0;
|
||||
}
|
||||
|
||||
@@ -1071,11 +1092,6 @@ form.discover-search-box{
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
li.search-filter-list,
|
||||
li.used-filters-list
|
||||
{
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
form.discover-sort-box select{
|
||||
margin: 0 4px;
|
||||
@@ -1183,3 +1199,111 @@ margin: 2px 2px 0px 2px;
|
||||
{
|
||||
border: 1px solid lightgray;
|
||||
}
|
||||
|
||||
|
||||
span.highlight{
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.gear-icon{
|
||||
background-image: url('../../images/gear_ffffff_25x25.png');
|
||||
}
|
||||
|
||||
ul.gear-selection li.gear-option-selected{
|
||||
background: url('../../images/check_606060_15x15.png') no-repeat 3px center;
|
||||
}
|
||||
|
||||
input#aspect_discovery_SimpleSearch_field_query{
|
||||
width: 565px;
|
||||
}
|
||||
|
||||
input.search-icon{
|
||||
background-image: url('../../images/search_icon_ffffff_20x20.png');
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
text-indent: -1000px;
|
||||
/*Css props below are required for IE*/
|
||||
font-size: 0;
|
||||
display:block;
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
div#aspect_discovery_SimpleSearch_div_search p.pagination-info{
|
||||
display: none;
|
||||
}
|
||||
|
||||
div#aspect_discovery_SimpleSearch_div_search .pagination-links{
|
||||
float: left;
|
||||
}
|
||||
|
||||
table.discovery-filters{
|
||||
width: 100%;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
table.discovery-filters tr{
|
||||
border-top: 1px solid #EBEBEB;
|
||||
}
|
||||
table.discovery-filters td{
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
table.discovery-filters td.selection{
|
||||
width: 1%;
|
||||
}
|
||||
|
||||
table.discovery-filters th.new-filter-header{
|
||||
text-align: left;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
|
||||
table.discovery-filters td.discovery-filter-input-cell {
|
||||
padding-left: 3px;
|
||||
}
|
||||
|
||||
|
||||
table.discovery-filters tr.apply-filter{
|
||||
background-color: #FAFAFA;
|
||||
}
|
||||
|
||||
table.discovery-filters tr.apply-filter input{
|
||||
width: 75px;
|
||||
height: 33px;
|
||||
margin-left: 5px;
|
||||
font-size: 108%;
|
||||
}
|
||||
|
||||
|
||||
table.discovery-filters td.filter-controls{
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
table.discovery-filters input.filter-control {
|
||||
width: 30px;
|
||||
margin-left: 5px;
|
||||
text-indent: -1000px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
height: 22px;
|
||||
float: left;
|
||||
/*Css props below are required for IE*/
|
||||
font-size: 0;
|
||||
display:block;
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
table.discovery-filters input.filter-control.filter-remove{
|
||||
margin-left: 15px;
|
||||
background-image: url('../../images/remove_icon_ffffff_16x16.png');
|
||||
}
|
||||
|
||||
table.discovery-filters input.filter-control.filter-add{
|
||||
background-image: url('../../images/plus_icon_ffffff_16x16.png');
|
||||
}
|
||||
|
||||
|
||||
|
||||
.searchTime{
|
||||
color: #999999;
|
||||
}
|
||||
|
@@ -180,9 +180,29 @@
|
||||
</xsl:if>
|
||||
|
||||
</ul>
|
||||
<xsl:if test="parent::node()/dri:div[@n = 'masked-page-control']">
|
||||
<xsl:apply-templates select="parent::node()/dri:div[@n='masked-page-control']/dri:div">
|
||||
<xsl:with-param name="position" select="$position"/>
|
||||
</xsl:apply-templates>
|
||||
</xsl:if>
|
||||
</div>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="dri:div[@n = 'masked-page-control']">
|
||||
<!--Do not render this division, this is handled by the xsl-->
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="dri:div[@n ='search-controls-gear']">
|
||||
<xsl:param name="position"/>
|
||||
<div>
|
||||
<xsl:call-template name="standardAttributes">
|
||||
<xsl:with-param name="class"><xsl:value-of select="$position"/></xsl:with-param>
|
||||
</xsl:call-template>
|
||||
|
||||
<xsl:apply-templates/>
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
||||
|
@@ -44,6 +44,7 @@
|
||||
<xsl:template match="dri:options">
|
||||
<div id="ds-options-wrapper">
|
||||
<div id="ds-options">
|
||||
<xsl:if test="not(contains(/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='request'][@qualifier='URI'], 'discover'))">
|
||||
<h1 id="ds-search-option-head" class="ds-option-set-head">
|
||||
<i18n:text>xmlui.dri2xhtml.structural.search</i18n:text>
|
||||
</h1>
|
||||
@@ -125,6 +126,7 @@
|
||||
</xsl:if>
|
||||
</div>
|
||||
|
||||
</xsl:if>
|
||||
<!-- Once the search box is built, the other parts of the options are added -->
|
||||
<xsl:apply-templates/>
|
||||
|
||||
|
@@ -475,7 +475,7 @@
|
||||
</xsl:variable>
|
||||
|
||||
<xsl:if test="$ccLicenseName and $ccLicenseUri and contains($ccLicenseUri, 'creativecommons')">
|
||||
<div about="{$handleUri}">
|
||||
<div about="{$handleUri}" class="clearfix">
|
||||
<xsl:attribute name="style">
|
||||
<xsl:text>margin:0em 2em 0em 2em; padding-bottom:0em;</xsl:text>
|
||||
</xsl:attribute>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 3.1 KiB |
@@ -1246,22 +1246,6 @@ span.Z3988 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
form.discover-search-box div.ds-form-content,
|
||||
form.discover-sort-box div.ds-form-content
|
||||
{
|
||||
width: auto;
|
||||
}
|
||||
|
||||
form.discover-search-box div.ds-form-content input.update-filters{
|
||||
margin-left: 145px;
|
||||
}
|
||||
|
||||
form.discover-sort-box select{
|
||||
margin: 0 4px;
|
||||
}
|
||||
|
||||
|
||||
.hidden {
|
||||
display:none;
|
||||
visibility:hidden;
|
||||
@@ -1333,3 +1317,85 @@ select#aspect_submission_submit_SelectCollectionStep_field_handle
|
||||
{
|
||||
max-width: 350px;
|
||||
}
|
||||
|
||||
|
||||
/* Start discovery layout DSpace 3.x*/
|
||||
div.discoverySearchBox
|
||||
{
|
||||
background-color: #FFFFF5;
|
||||
border: 2px solid #F0F0D2;
|
||||
}
|
||||
|
||||
form.discover-search-box fieldset{
|
||||
border: none;
|
||||
}
|
||||
|
||||
div.discoverySearchBox label{
|
||||
width: auto;
|
||||
}
|
||||
|
||||
div.discoverySearchBox div.ds-form-content{
|
||||
width: auto;
|
||||
}
|
||||
|
||||
input#aspect_discovery_SimpleSearch_field_query{
|
||||
width: 480px;
|
||||
}
|
||||
|
||||
input.search-icon{
|
||||
background-image: url('../images/search_icon_DF6E00_20x20.png');
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
text-indent: -1000px;
|
||||
/*Css props below are required for IE*/
|
||||
font-size: 0;
|
||||
line-height: 0;
|
||||
border: 1px solid #000000;
|
||||
}
|
||||
|
||||
div.controls-gear-wrapper{
|
||||
float: none;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
div.gear-icon{
|
||||
background-image: url('../images/gear_DF6E00_25x25.png');
|
||||
}
|
||||
|
||||
ul.gear-selection li.gear-option-selected{
|
||||
background: url('../images/check_606060_15x15.png') no-repeat 3px center;
|
||||
}
|
||||
|
||||
table.discovery-filters input.filter-control {
|
||||
width: 30px;
|
||||
margin-left: 5px;
|
||||
text-indent: -1000px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
height: 22px;
|
||||
float: left;
|
||||
/*Css props below are required for IE*/
|
||||
font-size: 0;
|
||||
display:block;
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
table.discovery-filters input.filter-control.filter-remove{
|
||||
margin-left: 15px;
|
||||
background-image: url('../images/remove_icon_DF6E00_16x16.png');
|
||||
border: 1px solid #000000;
|
||||
}
|
||||
|
||||
table.discovery-filters input.filter-control.filter-add{
|
||||
background-image: url('../images/plus_icon_DF6E00_16x16.png');
|
||||
border: 1px solid #000000;
|
||||
}
|
||||
|
||||
ul.gear-selection{
|
||||
left: 0;
|
||||
right: auto;
|
||||
background-color: ivory;
|
||||
border: 2px solid #F0F0D2;
|
||||
}
|
||||
|
||||
/* End discovery layout DSpace 3.x*/
|
@@ -42,6 +42,7 @@
|
||||
<xsl:import href="community-view.xsl"/>
|
||||
<xsl:import href="ORE.xsl"/>
|
||||
<xsl:import href="COinS.xsl"/>
|
||||
<xsl:import href="discovery.xsl"/>
|
||||
|
||||
<xsl:output indent="yes"/>
|
||||
|
||||
|
@@ -0,0 +1,298 @@
|
||||
<!--
|
||||
|
||||
The contents of this file are subject to the license and copyright
|
||||
detailed in the LICENSE and NOTICE files at the root of the source
|
||||
tree and available online at
|
||||
|
||||
http://www.dspace.org/license/
|
||||
|
||||
-->
|
||||
<xsl:stylesheet
|
||||
xmlns:i18n="http://apache.org/cocoon/i18n/2.1"
|
||||
xmlns:dri="http://di.tamu.edu/DRI/1.0/"
|
||||
xmlns:mets="http://www.loc.gov/METS/"
|
||||
xmlns:dim="http://www.dspace.org/xmlns/dspace/dim"
|
||||
xmlns:xlink="http://www.w3.org/TR/xlink/"
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
|
||||
xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:xalan="http://xml.apache.org/xalan"
|
||||
xmlns:encoder="xalan://java.net.URLEncoder"
|
||||
exclude-result-prefixes="xalan encoder i18n dri mets dim xlink xsl">
|
||||
|
||||
<xsl:output indent="yes"/>
|
||||
|
||||
<!--
|
||||
These templaes are devoted to rendering the search results for discovery.
|
||||
Since discovery used hit highlighting seperate templates are required !
|
||||
-->
|
||||
|
||||
|
||||
<xsl:template match="dri:list[@type='dsolist']" priority="2">
|
||||
<xsl:apply-templates select="dri:head"/>
|
||||
<ul class="ds-artifact-list">
|
||||
<xsl:apply-templates select="*[not(name()='head')]" mode="dsoList"/>
|
||||
</ul>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="dri:list/dri:list" mode="dsoList" priority="7">
|
||||
<xsl:apply-templates select="dri:head"/>
|
||||
<ul>
|
||||
<xsl:apply-templates select="*[not(name()='head')]" mode="dsoList"/>
|
||||
</ul>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="dri:list/dri:list/dri:list" mode="dsoList" priority="8">
|
||||
<li>
|
||||
<xsl:attribute name="class">
|
||||
<xsl:text>ds-artifact-item clearfix </xsl:text>
|
||||
<xsl:choose>
|
||||
<xsl:when test="position() mod 2 = 0">even</xsl:when>
|
||||
<xsl:otherwise>odd</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<!--
|
||||
Retrieve the type from our name, the name contains the following format:
|
||||
{handle}:{metadata}
|
||||
-->
|
||||
<xsl:variable name="handle">
|
||||
<xsl:value-of select="substring-before(@n, ':')"/>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="type">
|
||||
<xsl:value-of select="substring-after(@n, ':')"/>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="externalMetadataURL">
|
||||
<xsl:text>cocoon://metadata/handle/</xsl:text>
|
||||
<xsl:value-of select="$handle"/>
|
||||
<xsl:text>/mets.xml</xsl:text>
|
||||
<!-- Since this is a summary only grab the descriptive metadata, and the thumbnails -->
|
||||
<xsl:text>?sections=dmdSec,fileSec&fileGrpTypes=THUMBNAIL</xsl:text>
|
||||
<!-- An example of requesting a specific metadata standard (MODS and QDC crosswalks only work for items)->
|
||||
<xsl:if test="@type='DSpace Item'">
|
||||
<xsl:text>&dmdTypes=DC</xsl:text>
|
||||
</xsl:if>-->
|
||||
</xsl:variable>
|
||||
|
||||
|
||||
<xsl:choose>
|
||||
<xsl:when test="$type='community'">
|
||||
<xsl:call-template name="communitySummaryList">
|
||||
<xsl:with-param name="handle">
|
||||
<xsl:value-of select="$handle"/>
|
||||
</xsl:with-param>
|
||||
<xsl:with-param name="externalMetadataUrl">
|
||||
<xsl:value-of select="$externalMetadataURL"/>
|
||||
</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
<xsl:when test="$type='collection'">
|
||||
<xsl:call-template name="collectionSummaryList">
|
||||
<xsl:with-param name="handle">
|
||||
<xsl:value-of select="$handle"/>
|
||||
</xsl:with-param>
|
||||
<xsl:with-param name="externalMetadataUrl">
|
||||
<xsl:value-of select="$externalMetadataURL"/>
|
||||
</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
<xsl:when test="$type='item'">
|
||||
<xsl:call-template name="itemSummaryList">
|
||||
<xsl:with-param name="handle">
|
||||
<xsl:value-of select="$handle"/>
|
||||
</xsl:with-param>
|
||||
<xsl:with-param name="externalMetadataUrl">
|
||||
<xsl:value-of select="$externalMetadataURL"/>
|
||||
</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</li>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="communitySummaryList">
|
||||
<xsl:param name="handle"/>
|
||||
<xsl:param name="externalMetadataUrl"/>
|
||||
|
||||
<xsl:variable name="metsDoc" select="document($externalMetadataUrl)"/>
|
||||
|
||||
<div class="artifact-title">
|
||||
<a href="{$metsDoc/mets:METS/@OBJID}">
|
||||
<xsl:choose>
|
||||
<xsl:when test="dri:list[@n=(concat($handle, ':dc.title'))]">
|
||||
<xsl:apply-templates select="dri:list[@n=(concat($handle, ':dc.title'))]/dri:item"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<i18n:text>xmlui.dri2xhtml.METS-1.0.no-title</i18n:text>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</a>
|
||||
<!--Display community strengths (item counts) if they exist-->
|
||||
<xsl:if test="string-length($metsDoc/mets:METS/mets:dmdSec/mets:mdWrap/mets:xmlData/dim:dim/dim:field[@element='format'][@qualifier='extent'][1]) > 0">
|
||||
<xsl:text> [</xsl:text>
|
||||
<xsl:value-of
|
||||
select="$metsDoc/mets:METS/mets:dmdSec/mets:mdWrap/mets:xmlData/dim:dim/dim:field[@element='format'][@qualifier='extent'][1]"/>
|
||||
<xsl:text>]</xsl:text>
|
||||
</xsl:if>
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="collectionSummaryList">
|
||||
<xsl:param name="handle"/>
|
||||
<xsl:param name="externalMetadataUrl"/>
|
||||
|
||||
<xsl:variable name="metsDoc" select="document($externalMetadataUrl)"/>
|
||||
|
||||
<div class="artifact-title">
|
||||
<a href="{$metsDoc/mets:METS/@OBJID}">
|
||||
<xsl:choose>
|
||||
<xsl:when test="dri:list[@n=(concat($handle, ':dc.title'))]">
|
||||
<xsl:apply-templates select="dri:list[@n=(concat($handle, ':dc.title'))]/dri:item"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<i18n:text>xmlui.dri2xhtml.METS-1.0.no-title</i18n:text>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<!--Display collection strengths (item counts) if they exist-->
|
||||
<xsl:if test="string-length($metsDoc/mets:METS/mets:dmdSec/mets:mdWrap/mets:xmlData/dim:dim/dim:field[@element='format'][@qualifier='extent'][1]) > 0">
|
||||
<xsl:text> [</xsl:text>
|
||||
<xsl:value-of
|
||||
select="$metsDoc/mets:METS/mets:dmdSec/mets:mdWrap/mets:xmlData/dim:dim/dim:field[@element='format'][@qualifier='extent'][1]"/>
|
||||
<xsl:text>]</xsl:text>
|
||||
</xsl:if>
|
||||
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="itemSummaryList">
|
||||
<xsl:param name="handle"/>
|
||||
<xsl:param name="externalMetadataUrl"/>
|
||||
|
||||
<xsl:variable name="metsDoc" select="document($externalMetadataUrl)"/>
|
||||
|
||||
|
||||
<!--Generates thumbnails (if present)-->
|
||||
<xsl:apply-templates select="$metsDoc/mets:METS/mets:fileSec" mode="artifact-preview"/>
|
||||
|
||||
<div class="artifact-description">
|
||||
<div class="artifact-title">
|
||||
<xsl:element name="a">
|
||||
<xsl:attribute name="href">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$metsDoc/mets:METS/mets:dmdSec/mets:mdWrap/mets:xmlData/dim:dim/@withdrawn">
|
||||
<xsl:value-of select="$metsDoc/mets:METS/@OBJEDIT"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="concat($context-path, '/handle/', $handle)"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:choose>
|
||||
<xsl:when test="dri:list[@n=(concat($handle, ':dc.title'))]">
|
||||
<xsl:apply-templates select="dri:list[@n=(concat($handle, ':dc.title'))]/dri:item"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<i18n:text>xmlui.dri2xhtml.METS-1.0.no-title</i18n:text>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:element>
|
||||
<!-- Generate COinS with empty content per spec but force Cocoon to not create a minified tag -->
|
||||
<span class="Z3988">
|
||||
<xsl:attribute name="title">
|
||||
<xsl:for-each select="$metsDoc/mets:METS/mets:dmdSec/mets:mdWrap/mets:xmlData/dim:dim">
|
||||
<xsl:call-template name="renderCOinS"/>
|
||||
</xsl:for-each>
|
||||
</xsl:attribute>
|
||||
 <!-- non-breaking space to force separating the end tag -->
|
||||
</span>
|
||||
</div>
|
||||
<div class="artifact-info">
|
||||
<span class="author">
|
||||
<xsl:choose>
|
||||
<xsl:when test="dri:list[@n=(concat($handle, ':dc.contributor.author'))]">
|
||||
<xsl:for-each select="dri:list[@n=(concat($handle, ':dc.contributor.author'))]/dri:item">
|
||||
<xsl:variable name="author">
|
||||
<xsl:value-of select="."/>
|
||||
</xsl:variable>
|
||||
<span>
|
||||
<!--Check authority in the mets document-->
|
||||
<xsl:if test="$metsDoc/mets:METS/mets:dmdSec/mets:mdWrap/mets:xmlData/dim:dim/dim:field[@element='contributor' and @qualifier='author' and . = $author]/@authority">
|
||||
<xsl:attribute name="class">
|
||||
<xsl:text>ds-dc_contributor_author-authority</xsl:text>
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:apply-templates select="."/>
|
||||
</span>
|
||||
|
||||
<xsl:if test="count(following-sibling::dri:item) != 0">
|
||||
<xsl:text>; </xsl:text>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</xsl:when>
|
||||
<xsl:when test="dri:list[@n=(concat($handle, ':dc.creator'))]">
|
||||
<xsl:for-each select="dri:list[@n=(concat($handle, ':dc.creator'))]/dri:item">
|
||||
<xsl:apply-templates select="."/>
|
||||
<xsl:if test="count(following-sibling::dri:item) != 0">
|
||||
<xsl:text>; </xsl:text>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</xsl:when>
|
||||
<xsl:when test="dri:list[@n=(concat($handle, ':dc.contributor'))]">
|
||||
<xsl:for-each select="dri:list[@n=(concat($handle, ':dc.contributor'))]/dri:item">
|
||||
<xsl:apply-templates select="."/>
|
||||
<xsl:if test="count(following-sibling::dri:item) != 0">
|
||||
<xsl:text>; </xsl:text>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<i18n:text>xmlui.dri2xhtml.METS-1.0.no-author</i18n:text>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</span>
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:if test="dri:list[@n=(concat($handle, ':dc.date.issued'))] or dri:list[@n=(concat($handle, ':dc.publisher'))]">
|
||||
<span class="publisher-date">
|
||||
<xsl:text>(</xsl:text>
|
||||
<xsl:if test="dri:list[@n=(concat($handle, ':dc.publisher'))]">
|
||||
<span class="publisher">
|
||||
<xsl:apply-templates select="dri:list[@n=(concat($handle, ':dc.publisher'))]/dri:item"/>
|
||||
</span>
|
||||
<xsl:text>, </xsl:text>
|
||||
</xsl:if>
|
||||
<span class="date">
|
||||
<xsl:value-of
|
||||
select="substring(dri:list[@n=(concat($handle, ':dc.date.issued'))]/dri:item,1,10)"/>
|
||||
</span>
|
||||
<xsl:text>)</xsl:text>
|
||||
</span>
|
||||
</xsl:if>
|
||||
<xsl:choose>
|
||||
<xsl:when test="dri:list[@n=(concat($handle, ':dc.description.abstract'))]/dri:item/dri:hi">
|
||||
<div class="abstract">
|
||||
<xsl:for-each select="dri:list[@n=(concat($handle, ':dc.description.abstract'))]/dri:item">
|
||||
<xsl:apply-templates select="."/>
|
||||
<xsl:text>...</xsl:text>
|
||||
<br/>
|
||||
</xsl:for-each>
|
||||
|
||||
</div>
|
||||
</xsl:when>
|
||||
<xsl:when test="dri:list[@n=(concat($handle, ':fulltext'))]">
|
||||
<div class="abstract">
|
||||
<xsl:for-each select="dri:list[@n=(concat($handle, ':fulltext'))]/dri:item">
|
||||
<xsl:apply-templates select="."/>
|
||||
<xsl:text>...</xsl:text>
|
||||
<br/>
|
||||
</xsl:for-each>
|
||||
</div>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</div>
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
@@ -169,6 +169,11 @@
|
||||
<i18n:text>xmlui.dri2xhtml.structural.pagination-next</i18n:text>
|
||||
</a>
|
||||
</xsl:if>
|
||||
<xsl:if test="parent::node()/dri:div[@n = 'masked-page-control']">
|
||||
<xsl:apply-templates select="parent::node()/dri:div[@n='masked-page-control']/dri:div">
|
||||
<xsl:with-param name="position" select="$position"/>
|
||||
</xsl:apply-templates>
|
||||
</xsl:if>
|
||||
</div>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
@@ -245,4 +250,19 @@
|
||||
<!-- The general "catch-all" template for attributes matched, but not handled above -->
|
||||
<xsl:template match="@*"></xsl:template>
|
||||
|
||||
<xsl:template match="dri:div[@n = 'masked-page-control']">
|
||||
<!--Do not render this division, this is handled by the xsl-->
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="dri:div[@n ='search-controls-gear']">
|
||||
<xsl:param name="position"/>
|
||||
<div>
|
||||
<xsl:call-template name="standardAttributes">
|
||||
<xsl:with-param name="class"><xsl:value-of select="$position"/></xsl:with-param>
|
||||
</xsl:call-template>
|
||||
|
||||
<xsl:apply-templates/>
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
||||
|
@@ -482,10 +482,13 @@
|
||||
|
||||
<xsl:template match="dri:list[not(@type)]/dri:item" priority="2" mode="nested">
|
||||
<li>
|
||||
<xsl:apply-templates />
|
||||
<xsl:call-template name="standardAttributes">
|
||||
<xsl:with-param name="class">ds-simple-list-item</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
<!-- Wrap orphaned sub-lists into the preceding item -->
|
||||
<xsl:variable name="node-set1" select="./following-sibling::dri:list"/>
|
||||
<xsl:variable name="node-set2" select="./following-sibling::dri:item[1]/following-sibling::dri:list"/>
|
||||
<xsl:apply-templates />
|
||||
<xsl:apply-templates select="$node-set1[count(.|$node-set2) != count($node-set2)]"/>
|
||||
</li>
|
||||
</xsl:template>
|
||||
@@ -512,6 +515,9 @@
|
||||
<!-- Generic item handling for cases where nothing special needs to be done -->
|
||||
<xsl:template match="dri:item" mode="nested">
|
||||
<li>
|
||||
<xsl:call-template name="standardAttributes">
|
||||
<xsl:with-param name="class">ds-simple-list-item</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
<xsl:apply-templates />
|
||||
</li>
|
||||
</xsl:template>
|
||||
|
@@ -224,6 +224,7 @@
|
||||
<xsl:when test="dri:field">
|
||||
<xsl:choose>
|
||||
<xsl:when test="preceding-sibling::*[1][local-name()='label']">
|
||||
<xsl:if test="string-length(string(preceding-sibling::*[1][local-name()='label'])) > 0">
|
||||
<label class="ds-form-label">
|
||||
<xsl:choose>
|
||||
<xsl:when test="./dri:field/@id">
|
||||
@@ -233,11 +234,12 @@
|
||||
</xsl:when>
|
||||
<xsl:otherwise></xsl:otherwise>
|
||||
</xsl:choose>
|
||||
<xsl:apply-templates select="preceding-sibling::*[1][local-name()='label']"/> 
|
||||
<xsl:apply-templates select="preceding-sibling::*[1][local-name()='label']"/>
|
||||
</label>
|
||||
</xsl:if>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:apply-templates select="preceding-sibling::*[1][local-name()='label']"/> 
|
||||
<xsl:apply-templates select="preceding-sibling::*[1][local-name()='label']"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
|
@@ -1182,6 +1182,9 @@
|
||||
|
||||
<xsl:template match="dri:list[not(@type)]/dri:item" priority="2" mode="nested">
|
||||
<li>
|
||||
<xsl:call-template name="standardAttributes">
|
||||
<xsl:with-param name="class">ds-simple-list-item</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
<xsl:apply-templates />
|
||||
<!-- Wrap orphaned sub-lists into the preceding item -->
|
||||
<xsl:variable name="node-set1" select="./following-sibling::dri:list"/>
|
||||
@@ -1571,6 +1574,9 @@
|
||||
<!-- Generic item handling for cases where nothing special needs to be done -->
|
||||
<xsl:template match="dri:item" mode="nested">
|
||||
<li>
|
||||
<xsl:call-template name="standardAttributes">
|
||||
<xsl:with-param name="class">ds-simple-list-item</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
<xsl:apply-templates />
|
||||
</li>
|
||||
</xsl:template>
|
||||
@@ -2692,11 +2698,33 @@
|
||||
<i18n:text>xmlui.dri2xhtml.structural.pagination-next</i18n:text>
|
||||
</a>
|
||||
</xsl:if>
|
||||
<xsl:if test="parent::node()/dri:div[@n = 'masked-page-control']">
|
||||
<xsl:apply-templates select="parent::node()/dri:div[@n='masked-page-control']/dri:div">
|
||||
<xsl:with-param name="position" select="$position"/>
|
||||
</xsl:apply-templates>
|
||||
</xsl:if>
|
||||
</div>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="dri:div[@n = 'masked-page-control']" priority="5">
|
||||
<!--Do not render this division, this is handled by the xsl-->
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="dri:div[@n ='search-controls-gear']">
|
||||
<xsl:param name="position"/>
|
||||
<div>
|
||||
<xsl:call-template name="standardAttributes">
|
||||
<xsl:with-param name="class"><xsl:value-of select="$position"/></xsl:with-param>
|
||||
</xsl:call-template>
|
||||
|
||||
<xsl:apply-templates/>
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
|
||||
<!-- A quick helper function used by the @pagination template for repetitive tasks -->
|
||||
<xsl:template name="offset-link">
|
||||
<xsl:param name="pageOffset"/>
|
||||
@@ -3489,4 +3517,272 @@
|
||||
</td>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
|
||||
<xsl:template match="dri:list[@type='dsolist']" priority="2">
|
||||
<xsl:apply-templates select="dri:head"/>
|
||||
<ul class="ds-artifact-list">
|
||||
<xsl:apply-templates select="*[not(name()='head')]" mode="dsoList"/>
|
||||
</ul>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="dri:list/dri:list" mode="dsoList" priority="7">
|
||||
<xsl:apply-templates select="dri:head"/>
|
||||
<ul>
|
||||
<xsl:apply-templates select="*[not(name()='head')]" mode="dsoList"/>
|
||||
</ul>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="dri:list/dri:list/dri:list" mode="dsoList" priority="8">
|
||||
<li>
|
||||
<xsl:attribute name="class">
|
||||
<xsl:text>ds-artifact-item clearfix </xsl:text>
|
||||
<xsl:choose>
|
||||
<xsl:when test="position() mod 2 = 0">even</xsl:when>
|
||||
<xsl:otherwise>odd</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<!--
|
||||
Retrieve the type from our name, the name contains the following format:
|
||||
{handle}:{metadata}
|
||||
-->
|
||||
<xsl:variable name="handle">
|
||||
<xsl:value-of select="substring-before(@n, ':')"/>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="type">
|
||||
<xsl:value-of select="substring-after(@n, ':')"/>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="externalMetadataURL">
|
||||
<xsl:text>cocoon://metadata/handle/</xsl:text>
|
||||
<xsl:value-of select="$handle"/>
|
||||
<xsl:text>/mets.xml</xsl:text>
|
||||
<!-- Since this is a summary only grab the descriptive metadata, and the thumbnails -->
|
||||
<xsl:text>?sections=dmdSec,fileSec&fileGrpTypes=THUMBNAIL</xsl:text>
|
||||
<!-- An example of requesting a specific metadata standard (MODS and QDC crosswalks only work for items)->
|
||||
<xsl:if test="@type='DSpace Item'">
|
||||
<xsl:text>&dmdTypes=DC</xsl:text>
|
||||
</xsl:if>-->
|
||||
</xsl:variable>
|
||||
|
||||
|
||||
<xsl:choose>
|
||||
<xsl:when test="$type='community'">
|
||||
<xsl:call-template name="communitySummaryList">
|
||||
<xsl:with-param name="handle">
|
||||
<xsl:value-of select="$handle"/>
|
||||
</xsl:with-param>
|
||||
<xsl:with-param name="externalMetadataUrl">
|
||||
<xsl:value-of select="$externalMetadataURL"/>
|
||||
</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
<xsl:when test="$type='collection'">
|
||||
<xsl:call-template name="collectionSummaryList">
|
||||
<xsl:with-param name="handle">
|
||||
<xsl:value-of select="$handle"/>
|
||||
</xsl:with-param>
|
||||
<xsl:with-param name="externalMetadataUrl">
|
||||
<xsl:value-of select="$externalMetadataURL"/>
|
||||
</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
<xsl:when test="$type='item'">
|
||||
<xsl:call-template name="itemSummaryList">
|
||||
<xsl:with-param name="handle">
|
||||
<xsl:value-of select="$handle"/>
|
||||
</xsl:with-param>
|
||||
<xsl:with-param name="externalMetadataUrl">
|
||||
<xsl:value-of select="$externalMetadataURL"/>
|
||||
</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</li>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="communitySummaryList">
|
||||
<xsl:param name="handle"/>
|
||||
<xsl:param name="externalMetadataUrl"/>
|
||||
|
||||
<xsl:variable name="metsDoc" select="document($externalMetadataUrl)"/>
|
||||
|
||||
<div class="artifact-title">
|
||||
<a href="{$metsDoc/mets:METS/@OBJID}">
|
||||
<xsl:choose>
|
||||
<xsl:when test="dri:list[@n=(concat($handle, ':dc.title'))]">
|
||||
<xsl:apply-templates select="dri:list[@n=(concat($handle, ':dc.title'))]/dri:item"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<i18n:text>xmlui.dri2xhtml.METS-1.0.no-title</i18n:text>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</a>
|
||||
<!--Display community strengths (item counts) if they exist-->
|
||||
<xsl:if test="string-length($metsDoc/mets:METS/mets:dmdSec/mets:mdWrap/mets:xmlData/dim:dim/dim:field[@element='format'][@qualifier='extent'][1]) > 0">
|
||||
<xsl:text> [</xsl:text>
|
||||
<xsl:value-of
|
||||
select="$metsDoc/mets:METS/mets:dmdSec/mets:mdWrap/mets:xmlData/dim:dim/dim:field[@element='format'][@qualifier='extent'][1]"/>
|
||||
<xsl:text>]</xsl:text>
|
||||
</xsl:if>
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="collectionSummaryList">
|
||||
<xsl:param name="handle"/>
|
||||
<xsl:param name="externalMetadataUrl"/>
|
||||
|
||||
<xsl:variable name="metsDoc" select="document($externalMetadataUrl)"/>
|
||||
|
||||
<div class="artifact-title">
|
||||
<a href="{$metsDoc/mets:METS/@OBJID}">
|
||||
<xsl:choose>
|
||||
<xsl:when test="dri:list[@n=(concat($handle, ':dc.title'))]">
|
||||
<xsl:apply-templates select="dri:list[@n=(concat($handle, ':dc.title'))]/dri:item"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<i18n:text>xmlui.dri2xhtml.METS-1.0.no-title</i18n:text>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<!--Display collection strengths (item counts) if they exist-->
|
||||
<xsl:if test="string-length($metsDoc/mets:METS/mets:dmdSec/mets:mdWrap/mets:xmlData/dim:dim/dim:field[@element='format'][@qualifier='extent'][1]) > 0">
|
||||
<xsl:text> [</xsl:text>
|
||||
<xsl:value-of
|
||||
select="$metsDoc/mets:METS/mets:dmdSec/mets:mdWrap/mets:xmlData/dim:dim/dim:field[@element='format'][@qualifier='extent'][1]"/>
|
||||
<xsl:text>]</xsl:text>
|
||||
</xsl:if>
|
||||
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="itemSummaryList">
|
||||
<xsl:param name="handle"/>
|
||||
<xsl:param name="externalMetadataUrl"/>
|
||||
|
||||
<xsl:variable name="metsDoc" select="document($externalMetadataUrl)"/>
|
||||
|
||||
<div class="artifact-description">
|
||||
<div class="artifact-title">
|
||||
<xsl:element name="a">
|
||||
<xsl:attribute name="href">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$metsDoc/mets:METS/mets:dmdSec/mets:mdWrap/mets:xmlData/dim:dim/@withdrawn">
|
||||
<xsl:value-of select="$metsDoc/mets:METS/@OBJEDIT"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="concat($context-path, '/handle/', $handle)"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:choose>
|
||||
<xsl:when test="dri:list[@n=(concat($handle, ':dc.title'))]">
|
||||
<xsl:apply-templates select="dri:list[@n=(concat($handle, ':dc.title'))]/dri:item"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<i18n:text>xmlui.dri2xhtml.METS-1.0.no-title</i18n:text>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:element>
|
||||
<!-- Generate COinS with empty content per spec but force Cocoon to not create a minified tag -->
|
||||
<span class="Z3988">
|
||||
<xsl:attribute name="title">
|
||||
<xsl:for-each select="$metsDoc/mets:METS/mets:dmdSec/mets:mdWrap/mets:xmlData/dim:dim">
|
||||
<xsl:call-template name="renderCOinS"/>
|
||||
</xsl:for-each>
|
||||
</xsl:attribute>
|
||||
 <!-- non-breaking space to force separating the end tag -->
|
||||
</span>
|
||||
</div>
|
||||
<div class="artifact-info">
|
||||
<span class="author">
|
||||
<xsl:choose>
|
||||
<xsl:when test="dri:list[@n=(concat($handle, ':dc.contributor.author'))]">
|
||||
<xsl:for-each select="dri:list[@n=(concat($handle, ':dc.contributor.author'))]/dri:item">
|
||||
<xsl:variable name="author">
|
||||
<xsl:value-of select="."/>
|
||||
</xsl:variable>
|
||||
<span>
|
||||
<!--Check authority in the mets document-->
|
||||
<xsl:if test="$metsDoc/mets:METS/mets:dmdSec/mets:mdWrap/mets:xmlData/dim:dim/dim:field[@element='contributor' and @qualifier='author' and . = $author]/@authority">
|
||||
<xsl:attribute name="class">
|
||||
<xsl:text>ds-dc_contributor_author-authority</xsl:text>
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:apply-templates select="."/>
|
||||
</span>
|
||||
|
||||
<xsl:if test="count(following-sibling::dri:item) != 0">
|
||||
<xsl:text>; </xsl:text>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</xsl:when>
|
||||
<xsl:when test="dri:list[@n=(concat($handle, ':dc.creator'))]">
|
||||
<xsl:for-each select="dri:list[@n=(concat($handle, ':dc.creator'))]/dri:item">
|
||||
<xsl:apply-templates select="."/>
|
||||
<xsl:if test="count(following-sibling::dri:item) != 0">
|
||||
<xsl:text>; </xsl:text>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</xsl:when>
|
||||
<xsl:when test="dri:list[@n=(concat($handle, ':dc.contributor'))]">
|
||||
<xsl:for-each select="dri:list[@n=(concat($handle, ':dc.contributor'))]/dri:item">
|
||||
<xsl:apply-templates select="."/>
|
||||
<xsl:if test="count(following-sibling::dri:item) != 0">
|
||||
<xsl:text>; </xsl:text>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<i18n:text>xmlui.dri2xhtml.METS-1.0.no-author</i18n:text>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</span>
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:if test="dri:list[@n=(concat($handle, ':dc.date.issued'))] or dri:list[@n=(concat($handle, ':dc.publisher'))]">
|
||||
<span class="publisher-date">
|
||||
<xsl:text>(</xsl:text>
|
||||
<xsl:if test="dri:list[@n=(concat($handle, ':dc.publisher'))]">
|
||||
<span class="publisher">
|
||||
<xsl:apply-templates select="dri:list[@n=(concat($handle, ':dc.publisher'))]/dri:item"/>
|
||||
</span>
|
||||
<xsl:text>, </xsl:text>
|
||||
</xsl:if>
|
||||
<span class="date">
|
||||
<xsl:value-of
|
||||
select="substring(dri:list[@n=(concat($handle, ':dc.date.issued'))]/dri:item,1,10)"/>
|
||||
</span>
|
||||
<xsl:text>)</xsl:text>
|
||||
</span>
|
||||
</xsl:if>
|
||||
<xsl:choose>
|
||||
<xsl:when test="dri:list[@n=(concat($handle, ':dc.description.abstract'))]/dri:item/dri:hi">
|
||||
<div class="abstract">
|
||||
<xsl:for-each select="dri:list[@n=(concat($handle, ':dc.description.abstract'))]/dri:item">
|
||||
<xsl:apply-templates select="."/>
|
||||
<xsl:text>...</xsl:text>
|
||||
<br/>
|
||||
</xsl:for-each>
|
||||
|
||||
</div>
|
||||
</xsl:when>
|
||||
<xsl:when test="dri:list[@n=(concat($handle, ':fulltext'))]">
|
||||
<div class="abstract">
|
||||
<xsl:for-each select="dri:list[@n=(concat($handle, ':fulltext'))]/dri:item">
|
||||
<xsl:apply-templates select="."/>
|
||||
<xsl:text>...</xsl:text>
|
||||
<br/>
|
||||
</xsl:for-each>
|
||||
</div>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--Generates thumbnails (if present)-->
|
||||
<xsl:apply-templates select="$metsDoc/mets:METS/mets:fileSec" mode="artifact-preview"/>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
||||
|
@@ -84,9 +84,11 @@ public class List extends AbstractWingElement implements WingMergeableElement,
|
||||
|
||||
public static final String TYPE_FORM = "form";
|
||||
|
||||
public static final String TYPE_DSO_LIST = "dsolist";
|
||||
|
||||
/** All the possible list types collected into one array */
|
||||
public static final String[] TYPES = { TYPE_SIMPLE, TYPE_ORDERED,
|
||||
TYPE_BULLETED, TYPE_GLOSS, TYPE_PROGRESS, TYPE_FORM };
|
||||
TYPE_BULLETED, TYPE_GLOSS, TYPE_PROGRESS, TYPE_FORM, TYPE_DSO_LIST };
|
||||
|
||||
/** The list's name */
|
||||
private String name;
|
||||
|
@@ -8,7 +8,7 @@
|
||||
search.server = http://localhost:8080/solr/search
|
||||
|
||||
#Char used to ensure that the sidebar facets are case insensitive
|
||||
#solr.facets.split.char=|||
|
||||
#solr.facets.split.char=\n|||\n
|
||||
|
||||
#All metadata fields that will not end up in the index, this is a comma separated list
|
||||
index.ignore=dc.description.provenance
|
||||
|
@@ -42,9 +42,9 @@
|
||||
<!--Which sidebar facets are to be displayed-->
|
||||
<property name="sidebarFacets">
|
||||
<list>
|
||||
<ref bean="sidebarFacetAuthor" />
|
||||
<ref bean="sidebarFacetSubject" />
|
||||
<ref bean="sidebarFacetDateIssued" />
|
||||
<ref bean="searchFilterAuthor" />
|
||||
<ref bean="searchFilterSubject" />
|
||||
<ref bean="searchFilterIssued" />
|
||||
</list>
|
||||
</property>
|
||||
<!--The search filters which can be used on the discovery search page-->
|
||||
@@ -85,6 +85,52 @@
|
||||
<property name="max" value="5"/>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="hitHighlightingConfiguration">
|
||||
<bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightingConfiguration">
|
||||
<property name="metadataFields">
|
||||
<list>
|
||||
<bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration">
|
||||
<property name="field" value="dc.title"/>
|
||||
<property name="snippets" value="5"/>
|
||||
</bean>
|
||||
<bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration">
|
||||
<property name="field" value="dc.contributor.author"/>
|
||||
<property name="snippets" value="5"/>
|
||||
</bean>
|
||||
<bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration">
|
||||
<property name="field" value="dc.description.abstract"/>
|
||||
<property name="maxSize" value="250"/>
|
||||
<property name="snippets" value="2"/>
|
||||
</bean>
|
||||
<bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration">
|
||||
<property name="field" value="fulltext"/>
|
||||
<property name="maxSize" value="250"/>
|
||||
<property name="snippets" value="2"/>
|
||||
</bean>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="moreLikeThisConfiguration">
|
||||
<bean class="org.dspace.discovery.configuration.DiscoveryMoreLikeThisConfiguration">
|
||||
<!--When altering this list also alter the "xmlui.Discovery.RelatedItems.help" key as it describes
|
||||
the metadata fields below-->
|
||||
<property name="similarityMetadataFields">
|
||||
<list>
|
||||
<value>dc.title</value>
|
||||
<value>dc.contributor.author</value>
|
||||
<value>dc.creator</value>
|
||||
<value>dc.subject</value>
|
||||
</list>
|
||||
</property>
|
||||
<!--The minimum number of matching terms across the metadata fields above before an item is found as related -->
|
||||
<property name="minTermFrequency" value="5"/>
|
||||
<!--The maximum number of related items displayed-->
|
||||
<property name="max" value="3"/>
|
||||
<!--The minimum word length below which words will be ignored-->
|
||||
<property name="minWordLength" value="5"/>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
|
||||
@@ -97,45 +143,9 @@
|
||||
<value>dc.title</value>
|
||||
</list>
|
||||
</property>
|
||||
<property name="fullAutoComplete" value="false"/>
|
||||
</bean>
|
||||
|
||||
<bean id="searchFilterAuthor" class="org.dspace.discovery.configuration.DiscoverySearchFilter">
|
||||
<property name="indexFieldName" value="author"/>
|
||||
<property name="metadataFields">
|
||||
<list>
|
||||
<value>dc.contributor.author</value>
|
||||
<value>dc.creator</value>
|
||||
</list>
|
||||
</property>
|
||||
<property name="fullAutoComplete" value="true"/>
|
||||
</bean>
|
||||
|
||||
<bean id="searchFilterSubject" class="org.dspace.discovery.configuration.DiscoverySearchFilter">
|
||||
<property name="indexFieldName" value="subject"/>
|
||||
<property name="metadataFields">
|
||||
<list>
|
||||
<value>dc.subject.*</value>
|
||||
</list>
|
||||
</property>
|
||||
<property name="fullAutoComplete" value="true"/>
|
||||
</bean>
|
||||
|
||||
<bean id="searchFilterIssued" class="org.dspace.discovery.configuration.DiscoverySearchFilter">
|
||||
<property name="indexFieldName" value="dateIssued"/>
|
||||
<property name="metadataFields">
|
||||
<list>
|
||||
<value>dc.date.issued</value>
|
||||
</list>
|
||||
</property>
|
||||
<property name="type" value="date"/>
|
||||
<property name="fullAutoComplete" value="false"/>
|
||||
</bean>
|
||||
|
||||
|
||||
|
||||
<!--Sidebar facet configuration beans-->
|
||||
<bean id="sidebarFacetAuthor" class="org.dspace.discovery.configuration.SidebarFacetConfiguration">
|
||||
<bean id="searchFilterAuthor" class="org.dspace.discovery.configuration.DiscoverySearchFilterFacet">
|
||||
<property name="indexFieldName" value="author"/>
|
||||
<property name="metadataFields">
|
||||
<list>
|
||||
@@ -147,7 +157,7 @@
|
||||
<property name="sortOrder" value="COUNT"/>
|
||||
</bean>
|
||||
|
||||
<bean id="sidebarFacetSubject" class="org.dspace.discovery.configuration.SidebarFacetConfiguration">
|
||||
<bean id="searchFilterSubject" class="org.dspace.discovery.configuration.DiscoverySearchFilterFacet">
|
||||
<property name="indexFieldName" value="subject"/>
|
||||
<property name="metadataFields">
|
||||
<list>
|
||||
@@ -158,7 +168,7 @@
|
||||
<property name="sortOrder" value="COUNT"/>
|
||||
</bean>
|
||||
|
||||
<bean id="sidebarFacetDateIssued" class="org.dspace.discovery.configuration.SidebarFacetConfiguration">
|
||||
<bean id="searchFilterIssued" class="org.dspace.discovery.configuration.DiscoverySearchFilterFacet">
|
||||
<property name="indexFieldName" value="dateIssued"/>
|
||||
<property name="metadataFields">
|
||||
<list>
|
||||
@@ -169,7 +179,6 @@
|
||||
<property name="sortOrder" value="VALUE"/>
|
||||
</bean>
|
||||
|
||||
|
||||
<!--Sort properties-->
|
||||
<bean id="sortTitle" class="org.dspace.discovery.configuration.DiscoverySortFieldConfiguration">
|
||||
<property name="metadataField" value="dc.title"/>
|
||||
|
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
The contents of this file are subject to the license and copyright
|
||||
detailed in the LICENSE and NOTICE files at the root of the source
|
||||
tree and available online at
|
||||
|
||||
http://www.dspace.org/license/
|
||||
|
||||
-->
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
|
||||
|
||||
<context:annotation-config /> <!-- allows us to use spring annotations in beans -->
|
||||
|
||||
<bean class="org.dspace.discovery.SolrServiceResourceRestrictionPlugin" id="solrServiceResourceIndexPlugin" scope="prototype"/>
|
||||
|
||||
<alias name="solrServiceResourceIndexPlugin" alias="org.dspace.discovery.SolrServiceResourceRestrictionPlugin"/>
|
||||
|
||||
</beans>
|
@@ -437,12 +437,13 @@
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<fieldType name="dspaceFilter" class="solr.TextField" sortMissingLast="true" omitNorms="true">
|
||||
<fieldType name="keywordFilter" class="solr.TextField" sortMissingLast="true" omitNorms="true">
|
||||
<analyzer>
|
||||
<!--Treats the entire field as a single token, regardless of its content-->
|
||||
<tokenizer class="solr.KeywordTokenizerFactory"/>
|
||||
|
||||
<!--<filter class="solr.LowerCaseFilterFactory" />-->
|
||||
<filter class="solr.TrimFilterFactory" />
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
</types>
|
||||
@@ -480,7 +481,7 @@
|
||||
<field name="text" type="text" indexed="true" stored="false" multiValued="true"/>
|
||||
|
||||
|
||||
<field name="fulltext" type="text" indexed="true" stored="false" multiValued="true"/>
|
||||
<field name="fulltext" type="text" indexed="true" stored="true" multiValued="true"/>
|
||||
|
||||
<!-- Internal DSpace Object ID -->
|
||||
<field name="search.resourceid" type="sint" indexed="true" stored="true" required="true" omitNorms="true" />
|
||||
@@ -510,11 +511,17 @@
|
||||
<dynamicField name="*_ac" type="dspaceAutoComplete" indexed="true" stored="true" omitNorms="true" multiValued="true"/>
|
||||
|
||||
<!--Dynamic field used for sidebar filters-->
|
||||
<dynamicField name="*_filter" type="dspaceFilter" indexed="true" stored="true" multiValued="true" omitNorms="true" />
|
||||
<dynamicField name="*_filter" type="keywordFilter" indexed="true" stored="true" multiValued="true" omitNorms="true" />
|
||||
<dynamicField name="*_keyword" type="keywordFilter" indexed="true" stored="true" multiValued="true" omitNorms="true" />
|
||||
|
||||
<!--Dynamic field used for hit highlighting-->
|
||||
<dynamicField name="*_hl" type="text" indexed="true" stored="true" multiValued="true" omitNorms="true"/>
|
||||
|
||||
<dynamicField name="*_sort" type="lowerCaseSort" indexed="true" stored="true" multiValued="false" omitNorms="true"/>
|
||||
|
||||
<!--Dynamic field used for related item searches-->
|
||||
<dynamicField name="*_mlt" type="text" indexed="true" stored="true" multiValued="true" omitNorms="true" termVectors="true" termPositions="true" termOffsets="true"/>
|
||||
|
||||
<!--Date matching-->
|
||||
<dynamicField name="*.year" type="sint" indexed="true" stored="true" multiValued="true" omitNorms="true" />
|
||||
<dynamicField name="*_dt" type="date" indexed="true" stored="true" multiValued="false" omitNorms="true" />
|
||||
|