/*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; });