/*global define */
define(['jquery', 'underscore', 'backbone', 'models/SolrResult', 'models/PackageModel', 'views/CitationView', 'text!templates/resultsItem.html'],
function($, _, Backbone, SolrResult, Package, CitationView, ResultItemTemplate) {
'use strict';
// SearchResult View
// --------------
// The DOM element for a SearchResult item...
var SearchResultView = Backbone.View.extend({
tagName: 'div',
className: 'row-fluid result-row',
// Cache the template function for a single item.
//template: _.template($('#result-template').html()),
template: _.template(ResultItemTemplate),
//Templates
metricStatTemplate: _.template( " <%=metricValue%> "),
// The DOM events specific to an item.
events: {
'click .result-selection' : 'toggleSelected',
'click .download' : 'download'
},
// The SearchResultView listens for changes to its model, re-rendering. Since there's
// a one-to-one correspondence between a **SolrResult** and a **SearchResultView** in this
// app, we set a direct reference on the model for convenience.
initialize: function (options) {
if(typeof options !== "object"){
var options = {}
}
this.listenTo(this.model, 'change', this.render);
this.listenTo(this.model, 'reset', this.render);
//this.listenTo(this.model, 'destroy', this.remove);
//this.listenTo(this.model, 'visible', this.toggleVisible);
if(typeof options.metricsModel !== "undefined")
this.metricsModel = options.metricsModel;
},
// Re-render the citation of the result item.
render: function () {
//Convert the model to JSON and create the result row from the template
var json = this.model.toJSON();
/* Add other attributes to the JSON to send to the template */
//Determine if there is a prov trace
json.hasProv = this.model.hasProvTrace();
// Add flag to add in annotation icon in results item view if appropriate
json.hasAnnotations = json.sem_annotation &&
json.sem_annotation.length &&
json.sem_annotation.length > 0;
json.showAnnotationIndicator = MetacatUI.appModel.get("showAnnotationIndicator");
//Find the member node object
json.memberNode = _.findWhere(MetacatUI.nodeModel.get("members"), {identifier: this.model.get("datasource")});
//Figure out if this objbect is a collection or portal
var isCollection = this.model.getType() == "collection" || this.model.getType() == "portal";
//Determine if this metadata doc documents any data files
if( Array.isArray(json.documents) && json.documents.length ){
var dataFileIDs = _.without(json.documents, this.model.get("id"), this.model.get("seriesId"), this.model.get("resourceMap"));
json.numDataFiles = dataFileIDs.length;
json.dataFilesMessage = "This dataset contains " + json.numDataFiles + " data file";
if(json.numDataFiles > 1){
json.dataFilesMessage += "s";
}
}
else{
json.numDataFiles = 0;
json.dataFilesMessage = "This dataset doesn't contain any data files";
}
if( MetacatUI.appModel.get("displayRepoLogosInSearchResults") ){
//If this result has a logo and it is not a URL, assume it is an ID and create a full URL
if( json.logo && !json.logo.startsWith("http") ){
json.logo = MetacatUI.appModel.get("objectServiceUrl") + json.logo;
}
var datasourceId = json.memberNode? json.memberNode.identifier : json.datasource,
currentMemberNode = MetacatUI.appModel.get("nodeId") || datasourceId;
//Construct a URL to the profile of this repository
json.profileURL = (datasourceId == currentMemberNode)?
MetacatUI.root + "/profile" :
MetacatUI.appModel.get("dataoneSearchUrl") + "/portals/" + datasourceId.replace("urn:node:", "");
}
//Create a URL that leads to a view of this object
json.viewURL = this.model.createViewURL();
var resultRow = this.template(json);
this.$el.html(resultRow);
//Create the citation
var citation = new CitationView({metadata: this.model}).render().el;
var placeholder = this.$(".citation");
if(placeholder.length < 1) this.$el.append(citation);
else $(placeholder).replaceWith(citation);
//Create the OpenURL COinS
var span = this.getOpenURLCOinS();
this.$el.append(span);
//Non-collection metadata types will display metrics
if( !isCollection ){
if( MetacatUI.appModel.get("displayDatasetMetrics") && this.metricsModel ){
if (this.metricsModel.get("views") !== null) {
// Display metrics if the model has already been fetched
this.displayMetrics();
}
else if( this.metricsModel ) {
// waiting for the fetch() call to succeed.
this.listenTo(this.metricsModel, "sync", this.displayMetrics);
}
}
}
else{
this.$el.addClass("collection");
}
//Save the id in the DOM for later use
var id = json.id;
this.$el.attr("data-id", id);
if(this.model.get("abstract")){
var abridgedAbstract = (this.model.get("abstract").indexOf(" ", 250) < 0) ? this.model.get("abstract") : this.model.get("abstract").substring(0, this.model.get("abstract").indexOf(" ", 250)) + "...";
var content = $(document.createElement("div"))
.append($(document.createElement("p")).text(abridgedAbstract));
this.$(".popover-this.abstract").popover({
trigger: "hover",
html: true,
content: content,
title: "Abstract",
placement: "top",
container: this.el
});
}
else{
this.$(".popover-this.abstract").addClass("inactive");
this.$(".icon.abstract").addClass("inactive");
}
return this;
},
displayMetrics: function() {
//If metrics for this object should be hidden, exit the function
if( this.model.hideMetrics() ){
return;
}
var datasets = this.metricsModel.get("datasets");
var downloads = this.metricsModel.get("downloads");
var views = this.metricsModel.get("views");
var citations = this.metricsModel.get("citations");
// Initializing the metric counts
var viewCount = 0;
var downloadCount = 0;
var citationCount = 0;
// Get the individual dataset metics only if the response from Metrics Service API
// has non-zero array sizes
if(datasets && datasets.length > 0) {
var index = datasets.indexOf(this.model.get("id"));
viewCount = views[index];
downloadCount = downloads[index];
citationCount = citations[index];
}
// Generating tool-tip title
// Citations
if(citationCount == 1){
var citationToolTip = citationCount + " citation";
}
else {
var citationToolTip = MetacatUI.appView.numberAbbreviator(citationCount,1) + " citations";
}
// Downloads
if(downloadCount == 1){
var downloadToolTip = downloadCount + " download";
}
else {
var downloadToolTip = MetacatUI.appView.numberAbbreviator(downloadCount,1) + " downloads";
}
// Views
if(viewCount == 1){
var viewToolTip = viewCount + " view";
}
else {
var viewToolTip = MetacatUI.appView.numberAbbreviator(viewCount,1) + " views";
}
// Replacing the metric total count with the spinning icon.
this.$('.resultItem-CitationCount').html(this.metricStatTemplate({metricValue:MetacatUI.appView.numberAbbreviator(citationCount,1), metricIcon:'icon-quote-right'}))
.tooltip({
placement: "top",
trigger: "hover",
delay: 800,
container: this.el,
title: citationToolTip
});
this.$('.resultItem-DownloadCount').html(this.metricStatTemplate({metricValue:MetacatUI.appView.numberAbbreviator(downloadCount,1), metricIcon:'icon-cloud-download'}))
.tooltip({
placement: "top",
trigger: "hover",
delay: 800,
container: this.el,
title: downloadToolTip
});
this.$('.resultItem-ViewCount').html(this.metricStatTemplate({metricValue:MetacatUI.appView.numberAbbreviator(viewCount,1), metricIcon:'icon-eye-open'}))
.tooltip({
placement: "top",
trigger: "hover",
delay: 800,
container: this.el,
title: viewToolTip
});
// Removing Citation metric if the citationCount is 0
if (citationCount === 0) {
this.$('.resultItem-CitationCount').css("visibility","hidden");
}
// Removing Download metric if the downloadCount is 0
if (downloadCount === 0) {
this.$('.resultItem-DownloadCount').css("visibility","hidden");
}
// Removing View metric if the viewCount is 0
if (viewCount === 0) {
this.$('.resultItem-ViewCount').css("visibility","hidden");
}
},
// Toggle the `"selected"` state of the model.
toggleSelected: function () {
this.model.toggle();
},
routeToMetadata: function(e){
var id = this.model.get("id");
//If the user clicked on a download button or any element with the class 'stop-route', we don't want to navigate to the metadata
if ($(e.target).hasClass('stop-route') || (typeof id === "undefined") || !id)
return;
MetacatUI.uiRouter.navigate('view/' + encodeURIComponent(id), {trigger: true});
},
download: function(e){
if(MetacatUI.appUserModel.get("loggedIn") && !this.model.get("isPublic")){
if(e){
e.preventDefault();
var packageId = $(e.target).attr("data-id") || this.model.get("resourceMap");
}
else
var packageId = this.model.get("resourceMap");
var fileName = this.model.get("fileName") || this.model.get("title");
//Download the entire package if there is one
if(packageId){
//If there is more than one resource map, download all of them
if(Array.isArray(packageId)){
for(var i = 0; i 0)
pkgFileName = pkgFileName.substring(0, pkgFileName.lastIndexOf("."));
var packageModel = new Package({
id: packageId[i],
fileName: pkgFileName + ".zip"
});
packageModel.downloadWithCredentials();
}
}
else{
//Take off the file extension part of the file name
if(fileName.lastIndexOf(".") > 0)
fileName = fileName.substring(0, fileName.lastIndexOf("."));
//Create a model to represent the package
var packageModel = new Package({
id: packageId,
fileName: fileName + ".zip"
});
packageModel.downloadWithCredentials();
}
}
//Otherwise just download this solo object
else{
this.model.downloadWithCredentials();
}
}
else
return true;
},
getOpenURLCOinS: function(){
//Create the OpenURL COinS
var spanTitle = "ctx_ver=Z39.88-2004&rft_val_fmt=info:ofi/fmt:kev:mtx:dc&rfr_id=info:sid/ocoins.info:generator&rft.type=Dataset";
if(this.model.get("title")) spanTitle += "&rft.title=" + this.model.get("title");
if(this.model.get("origin")) spanTitle += "&rft.creator=" + this.model.get("origin");
if(this.model.get("keywords")) spanTitle += "&rft.subject=" + this.model.get("keywords");
if(this.model.get("abstract")) spanTitle += "&rft.description=" + this.model.get("abstract");
if(this.model.get("datasource")) spanTitle += "&rft.publisher=" + this.model.get("datasource");
if(this.model.get("endDate")) spanTitle += "&rft.date=" + this.model.get("endDate");
if(this.model.get("formatID")) spanTitle += "&rft.format=" + this.model.get("formatID");
if(this.model.get("id")) spanTitle += "&rft.identifier=" + this.model.get("id");
if(this.model.get("url")) spanTitle += "&rft.source=" + this.model.get("url");
if(this.model.get("northBoundCoord")){
spanTitle += "&rft.coverage=POLYGON((" + this.model.get("southBoundCoord") + " " + this.model.get("westBoundCoord") + ", " +
this.model.get("northBoundCoord") + " " + this.model.get("westBoundCoord") + ", " +
this.model.get("northBoundCoord") + " " + this.model.get("eastBoundCoord") + ", " +
this.model.get("southBoundCoord") + " " + this.model.get("eastBoundCoord") + "))";
}
spanTitle = encodeURI(spanTitle);
return $(document.createElement("span")).attr("title", spanTitle).addClass("Z3988");
},
// Remove the item, destroy the model from *localStorage* and delete its view.
clear: function () {
this.model.destroy();
},
onClose: function(){
this.clear();
}
});
return SearchResultView;
});