define(['jquery', 'underscore', 'backbone', 'models/SolrResult'],
function($, _, Backbone, SolrResult) {
'use strict';
var CitationView = Backbone.View.extend({
type: "Citation",
initialize: function(options){
if((options === undefined) || (!options)) var options = {};
this.id = options.id || null;
this.attributes = options.attributes || null;
this.className += options.className || "";
this.model = options.model || null;
this.metadata = options.metadata || null;
this.title = options.title || null;
this.createLink = (options.createLink === false) ? false : true;
this.createTitleLink = (options.createTitleLink === false) ? false : true;
//If a metadata doc was passed but no data or package model, then save the metadata as our model, too
if(!this.model && this.metadata) this.model = this.metadata;
//If the model is a Package, then get the metadata doc in this package
else if(this.model && this.model.type == "Package")
this.metadata = this.model.getMetadata();
//If the model is a metadata doc and there was no other metadata specified, then use the model
else if(this.model && (this.model.getType && this.model.getType() == "metadata") && !this.metadata)
this.metadata = this.model;
//Check if the given metadata object is a portal or collection
if( this.metadata ){
this.isCollection = this.metadata.getType() == "collection" || this.metadata.getType() == "portal";
}
if( !this.metadata ){
this.metadata = this.model;
}
},
tagName : "cite",
className : "citation",
/*
* Creates a citation
*/
render: function(){
if (!this.model && !this.metadata && !this.id)
return this;
else if(!this.model && !this.metadata && this.id){
//Create a model
this.metadata = new SolrResult({id: this.id});
this.model = this.metadata;
//Retrieve the citation info for this model and render once we have it
var view = this;
this.model.on("change", function(){ view.render.call(view); });
this.model.getCitationInfo();
return;
}
// If the model is retreived from the Metrics Service
// and of type CitationModel, simply set the fields as
// retrieved from the response
else if(this.model.type == "CitationModel") {
var authorText = this.model.get("origin") || "",
datasource = this.model.get("journal"),
dateUploaded = this.model.get("year_of_publishing"),
sourceUrl = this.model.get("source_url"),
sourceId = this.model.get("source_id"),
title = this.model.get("title"),
journal =this.model.get("publisher"),
volume =this.model.get("volume"),
page =this.model.get("page"),
citationMetadata =this.model.get("citationMetadata");
// Format the Author textarea else if (this.model.type == "CitationModel") {
if (authorText.length > 0) {
var authors = authorText.split(", "),
count = 0,
authorText = "";
_.each(authors, function (author) {
count++;
if(count == 6){
authorText += ", et al. ";
return;
}
else if(count > 6)
return;
if(count > 1){
if(authors.length > 2) authorText += ",";
if (count == authors.length) authorText += " and";
if (authors.length > 1) authorText += " ";
}
// Checking for incorrectly escaped characters
if (/&[A-Za-z0-9]/.test(author)) {
// initializing the DOM parser
var parser = new DOMParser();
// parsing the incorrectly escaped `&`
var unescapeAmpersand = parser.parseFromString(author, 'text/html');
// unescaping the & and retrieving the actual character
var unescapedString = parser.parseFromString(unescapeAmpersand.body.textContent, 'text/html');
// saving the correct author text before displaying
author = unescapedString.body.textContent;
}
authorText += author;
if (count == authors.length) authorText += ". ";
});
}
}
else if(this.metadata && this.metadata.get("archived") && !MetacatUI.appModel.get("archivedContentIsIndexed")){
this.$el.append('This content has been archived. ');
//The ID
var idEl = this.createIDElement();
this.$el.append(idEl);
return this;
}
//Create the citation from the metadata doc if we have one
else if (this.metadata) {
//If this object is in progress of saving, don't RErender this view.
if(this.metadata.get("uploadStatus") == "p" && this.$el.children().length)
return;
//Clear the element
this.$el.html("");
var pubDate = this.metadata.get("pubDate"),
dateUploaded = this.metadata.get("dateUploaded"),
title = Array.isArray(this.metadata.get("title")) ? (this.metadata.get("title")[0] || this.title || "") : this.metadata.get("title") || this.title || "",
datasource = this.metadata.get("datasource");
//Format the author text
if(this.metadata.type == "EML"){
var authors = this.metadata.get("creator"),
count = 0,
authorText = "";
_.each(authors, function (author) {
count++;
if(count == 6){
authorText += ", et al. ";
return;
}
else if(count > 6)
return;
//Get the individual's name, or position name, or organization name, in that order
var name = author.get("individualName") ?
_.flatten([author.get("individualName").givenName, author.get("individualName").surName]).join(" ") :
author.get("positionName") || author.get("organizationName");
if(count > 1){
if(authors.length > 2) authorText += ",";
if (count == authors.length) authorText += " and";
if (authors.length > 1) authorText += " ";
}
authorText += name;
if (count == authors.length) authorText += ". ";
});
}
else{
var authors = this.metadata.get("origin"),
count = 0,
authorText = "";
_.each(authors, function (author) {
count++;
if(count == 6){
authorText += ", et al. ";
return;
}
else if(count > 6)
return;
if(count > 1){
if(authors.length > 2) authorText += ",";
if (count == authors.length) authorText += " and";
if (authors.length > 1) authorText += " ";
}
authorText += author;
if (count == authors.length) authorText += ". ";
});
}
}
//If there is no metadata doc, then this is probably a data doc without science metadata.
//So create the citation from the index values
else {
var authorText = this.model.get("rightsHolder") || this.model.get("submitter") || "",
dateUploaded = this.model.get("dateUploaded"),
datasource = this.model.get("datasource");
}
if( !this.isCollection ){
//The author
var authorEl = $(document.createElement("span")).addClass("author").text(authorText);
//The publication date
var pubDateText = "";
if ((typeof pubDate !== "undefined") && pubDate) {
var pubDateFormatted = new Date(pubDate).getUTCFullYear();
if (!isNaN(pubDateFormatted)) pubDateText += pubDateFormatted;
}
if (dateUploaded && (isNaN(pubDateFormatted) || !pubDate)) {
var dateUploadedFormatted = dateUploaded;
if (!isNaN(dateUploadedFormatted)) pubDateText += dateUploadedFormatted;
}
var pubDateEl = $(document.createElement("span")).addClass("pubdate")
// Only set text if we have a non-zero-length pubDate string
if (pubDateText.length > 0) {
pubDateEl.text(pubDateText + ". ");
}
//The publisher (source member node)
var publisherText = "";
if (typeof datasource !== "undefined" && datasource) {
var memberNode = MetacatUI.nodeModel.getMember(datasource);
if(memberNode)
publisherText = memberNode.name + ". ";
else
publisherText = datasource + ". ";
}
else{
var memberNode = MetacatUI.nodeModel.getMember(MetacatUI.nodeModel.get("currentMemberNode"));
if(memberNode)
publisherText = memberNode.name + ". ";
}
var publisherEl = $(document.createElement("span")).addClass('publisher');
// Only set text if we have a non-zero-length publisherText string
if (publisherText) {
publisherEl.text(publisherText);
}
}
//Collections will get the collection class added
else{
this.$el.addClass("collection");
}
if(this.model.type == "CitationModel") {
// displaying decoded source url
var idEl = $(document.createElement("span")).addClass("publisher-id");
idEl.append(decodeURIComponent(sourceUrl), $(document.createElement("span")).text(". "));
}
else {
//The ID
var idEl = this.createIDElement();
}
var model = this.metadata || this.model,
id = model.get("id"),
seriesId = model.get("seriesId");
if ((typeof title !== "undefined") && title){
if(title.trim().charAt(title.length-1) != ".")
title = title.trim() + ". ";
else
title = title.trim() + " ";
if(this.model.type == "CitationModel") {
// Appending the title as a link
var titleEl = $(document.createElement("a"))
.addClass("metrics-route-to-metadata")
.attr("data-id", id)
.attr("href", sourceUrl)
.attr("target", "_blank")
.append(title);
}
else {
var titleEl = $(document.createElement("span"))
.addClass("title")
.attr("data-id", this.metadata.get("id"))
.text(title);
}
}
else
var titleEl = document.createElement("span");
//Create a link and put all the citation parts together
if (this.createLink){
if(this.model.type == "CitationModel") {
// Creating a volume element to display in Citations Modal Window
if(volume === "NULL") {
var volumeText = "";
}
else {
var volumeText = "Vol. " + volume + ". ";
}
var volumeEl = $(document.createElement("span")).addClass("publisher").text(volumeText);
// Creating a 'pages' element to display in Citations Modal Window
if(page === "NULL") {
var pageText = "";
}
else {
var pageText = "pp. " + page + ". ";
}
var pageEl = $(document.createElement("span")).addClass("publisher").text(pageText);
var datasetLinkEl = $(document.createElement("span"))
.text("Cites Data: ");
// Generate links for the cited datasets
var citationMetadataCounter = 0;
if (citationMetadata != undefined) {
for (var key in citationMetadata) {
citationMetadataCounter += 1;
var commaSeperator = (citationMetadataCounter < Object.keys(citationMetadata).length) ? "," : ".";
var mdPID = key, mdAuthorText = "", additionalAuthors = "", mdText = "", mdDateText = "";
// Display first author in the dataset link
if (citationMetadata[key]["origin"] != undefined && Array.isArray(citationMetadata[key]["origin"])) {
mdAuthorText = citationMetadata[key]["origin"][0];
additionalAuthors = citationMetadata[key]["origin"].length > 1 ? " et al." : "";
mdText = "(" + mdAuthorText + additionalAuthors + " ";
}
// save the date
if (citationMetadata[key]["datePublished"] != undefined) {
mdDateText = (citationMetadata[key]["datePublished"]).slice(0,4);
if (mdText.length == 0) {
mdText = "(";
}
mdText += mdDateText;
}
else if (citationMetadata[key]["dateUpdated"] != undefined) {
mdDateText = (citationMetadata[key]["dateUpdated"]).slice(0,4);
if (mdText.length == 0) {
mdText = "(";
}
mdText += mdDateText;
}
else if (citationMetadata[key]["dateModified"] != undefined) {
mdDateText = (citationMetadata[key]["dateModified"]).slice(0,4);
if (mdText.length == 0) {
mdText = "(";
}
mdText += mdDateText;
}
// retrieve the PID
if (citationMetadata[key]["id"] != undefined) {
mdPID = citationMetadata[key]["id"];
}
else if (key.startsWith("10."))
{
mdPID = "doi:" + key
}
if (mdText.length > 0) {
mdText += ")" + commaSeperator + " ";
var targetLinkEl = $(document.createElement("a"))
.addClass("metrics-route-to-metadata")
.attr("data-id", key)
.attr("href", MetacatUI.root + "/view/" + encodeURIComponent(mdPID))
.attr("target", "_blank")
.text(mdText);
datasetLinkEl.append(targetLinkEl);
}
}
}
// creating citation display string
var linkEl = $(document.createElement("span"))
.append(authorEl, pubDateEl, titleEl, publisherEl, volumeEl, pageEl, idEl);
}
else {
var linkEl = $(document.createElement("a"))
.addClass("route-to-metadata")
.attr("data-id", id)
.attr("href", this.metadata.createViewURL())
.append(authorEl, pubDateEl, titleEl, publisherEl, idEl);
}
this.$el.append(linkEl);
// Only append the citation link when we have non-zero datasets
// Append the cited dataset text to the link element
if ( datasetLinkEl !== "undefined" && citationMetadataCounter > 0) {
// Displaying the cites data on the new line
this.$el.append("
");
this.$el.append(datasetLinkEl);
}
}
else if(this.createTitleLink){
var linkEl = $(document.createElement("a"))
.addClass("route-to-metadata")
.attr("data-id", seriesId)
.attr("href", this.metadata.createViewURL())
.append(titleEl);
this.$el.append(authorEl, pubDateEl, linkEl, publisherEl, idEl);
}
else{
this.$el.append(authorEl, pubDateEl, titleEl, publisherEl, idEl);
}
this.setUpListeners();
return this;
},
createIDElement: function(){
var model = this.metadata || this.model,
id = model.get("id"),
seriesId = model.get("seriesId"),
datasource = model.get("datasource");
var idEl = $(document.createElement("span")).addClass("id");
if(seriesId){
//Create a link for the identifier if it is a DOI
if( model.isDOI(seriesId) && !this.createLink ){
var doiURL = this.createDoiUrl(seriesId),
doiLink = $(document.createElement("a"))
.attr("href", doiURL)
.text(seriesId);
// Begin PANGAEA-specific override 1 (this is temporary)
// If this is a PENGAEA dataset with a seriesId, then don't show the pid.
if (typeof datasource !== "undefined" && datasource === "urn:node:PANGAEA") {
idEl.append(doiLink, $(document.createElement("span")).text(". "));
}
// End PANGAEA-specific override 1
else{
idEl.append(doiLink, $(document.createElement("span")).text(", version: "));
}
}
else{
// Begin PANGAEA-specific override 2 (this is temporary)
// If this is a PENGAEA dataset with a seriesId, then don't show the pid.
if (typeof datasource !== "undefined" && datasource === "urn:node:PANGAEA") {
idEl.html($(document.createElement("span")).text(seriesId + ". "));
}
// End PANGAEA-specific override 2
else{
idEl.html($(document.createElement("span")).text(seriesId + ", version: "));
}
}
}
// Begin PANGAEA-specific override 3 (this is temporary)
// If this is a PENGAEA dataset with a seriesId, then don't show the pid. Return now.
if(typeof datasource !== "undefined" && datasource === "urn:node:PANGAEA" && seriesId){
return idEl;
}
// End PANGAEA-specific override 3
else if( model.isDOI(id) && !this.createLink ){
var doiURL = this.createDoiUrl(id),
doiLink = $(document.createElement("a"))
.attr("href", doiURL)
.text(id);
idEl.append(doiLink, $(document.createElement("span")).text(". "));
}
else{
idEl.append($(document.createElement("span")).text(id + ". "));
}
return idEl;
},
createDoiUrl: function(doi){
if( doi.indexOf("http") == 0 ){
return doi;
}
else if( doi.indexOf("doi:") == 0){
return "https://doi.org/" + doi.substring(4);
}
else{
return "https://doi.org/" + doi;
}
},
setUpListeners: function(){
if (!this.metadata) return;
this.stopListening();
//If anything in the model changes, rerender this citation
this.listenTo(this.metadata, "change:origin change:creator change:pubDate change:dateUploaded change:title change:seriesId change:id change:datasource", this.render);
//If this model is an EML211 model, then listen differently
if(this.metadata.type == "EML"){
var creators = this.metadata.get("creator");
//Listen to the names
for(var i=0; i