diff --git a/src/js/views/MetadataView.js b/src/js/views/MetadataView.js index 8083d2397..19d42fa7b 100644 --- a/src/js/views/MetadataView.js +++ b/src/js/views/MetadataView.js @@ -38,7 +38,7 @@ define([ "text!templates/metaTagsHighwirePress.html", "uuid", "views/MetricView", -], function ( +], ( $, $ui, _, @@ -78,18 +78,18 @@ define([ metaTagsHighwirePressTemplate, uuid, MetricView, -) { +) => { "use strict"; /** * @class MetadataView * @classdesc A human-readable view of a science metadata file * @classcategory Views - * @extends Backbone.View - * @constructor + * @augments Backbone.View + * @class * @screenshot views/MetadataView.png */ - var MetadataView = Backbone.View.extend( + const MetadataView = Backbone.View.extend( /** @lends MetadataView.prototype */ { subviews: [], @@ -116,7 +116,7 @@ define([ type: "Metadata", - //Templates + // Templates template: _.template(MetadataTemplate), alertTemplate: _.template(AlertTemplate), doiTemplate: _.template(PublishDoiTemplate), @@ -156,7 +156,7 @@ define([ "click #save-metadata-prov": "saveProv", }, - initialize: function (options) { + initialize(options) { if (options === undefined || !options) var options = {}; this.pid = @@ -168,13 +168,13 @@ define([ }, // Render the main metadata view - render: function () { + render() { this.stopListening(); MetacatUI.appModel.set("headerType", "default"); // this.showLoading("Loading..."); - //Reset various properties of this view first + // Reset various properties of this view first this.classMap = new Array(); this.subviews = new Array(); this.model.set(this.model.defaults); @@ -185,18 +185,18 @@ define([ this.listenTo(MetacatUI.appUserModel, "change:loggedIn", this.render); - //Listen to when the metadata has been rendered + // Listen to when the metadata has been rendered this.once("metadataLoaded", function () { this.createAnnotationViews(); this.insertMarkdownViews(); }); - //Listen to when the package table has been rendered + // Listen to when the package table has been rendered this.once("dataPackageRendered", function () { - var packageTableContainer = this.$("#data-package-container"); + const packageTableContainer = this.$("#data-package-container"); $(packageTableContainer).children(".loading").remove(); - //Scroll to the element on the page that is in the hash fragment (if there is one) + // Scroll to the element on the page that is in the hash fragment (if there is one) this.scrollToFragment(); }); @@ -211,11 +211,11 @@ define([ * table view, if there is one. * @param {string} pid - The PID of the resource map */ - getDataPackage: function (pid) { - //Create a DataONEObject model to use in the DataPackage collection. - var dataOneObject = new ScienceMetadata({ id: this.model.get("id") }); + getDataPackage(pid) { + // Create a DataONEObject model to use in the DataPackage collection. + const dataOneObject = new ScienceMetadata({ id: this.model.get("id") }); - var view = this; + const view = this; // Create a new data package with this id this.dataPackage = new DataPackage([dataOneObject], { id: pid }); @@ -235,7 +235,7 @@ define([ this.listenToOnce(this.dataPackage, "complete", function () { this.dataPackageSynced = true; this.trigger("changed:dataPackageSynced"); - var dataPackageView = _.findWhere(this.subviews, { + const dataPackageView = _.findWhere(this.subviews, { type: "DataPackage", }); if (dataPackageView) { @@ -244,16 +244,16 @@ define([ } }); - this.listenToOnce(this.dataPackage, "fetchFailed", function () { + this.listenToOnce(this.dataPackage, "fetchFailed", () => { view.dataPackageSynced = false; // stop listening to the fetch complete view.stopListening(view.dataPackage, "complete"); - //Remove the loading elements + // Remove the loading elements view.$(view.tableContainer).find(".loading").remove(); - //Show an error message + // Show an error message MetacatUI.appView.showAlert( "Error retrieving files for this data package.", "alert-error", @@ -281,15 +281,15 @@ define([ * Retrieves information from the index about this object, given the id (passed from the URL) * When the object info is retrieved from the index, we set up models depending on the type of object this is */ - getModel: function (pid) { - //Get the pid and sid - if (typeof pid === "undefined" || !pid) var pid = this.pid; + getModel(pid) { + // Get the pid and sid + if (typeof pid === "undefined" || !pid) var { pid } = this; if (typeof this.seriesId !== "undefined" && this.seriesId) var sid = this.seriesId; - //Get the package ID + // Get the package ID this.model.set({ id: pid, seriesId: sid }); - var model = this.model; + const { model } = this; this.listenToOnce(model, "sync", function () { if ( @@ -299,94 +299,89 @@ define([ this.model = model; this.renderMetadata(); } else if (this.model.get("formatType") == "DATA") { - //Get the metadata pids that document this data object - var isDocBy = this.model.get("isDocumentedBy"); + // Get the metadata pids that document this data object + const isDocBy = this.model.get("isDocumentedBy"); - //If there is only one metadata pid that documents this data object, then + // If there is only one metadata pid that documents this data object, then // get that metadata model for this view. if (isDocBy && isDocBy.length == 1) { this.navigateWithFragment(_.first(isDocBy), this.pid); return; } - //If more than one metadata doc documents this data object, it is most likely + // If more than one metadata doc documents this data object, it is most likely // multiple versions of the same metadata. So we need to find the latest version. - else if (isDocBy && isDocBy.length > 1) { - var view = this; - - require([ - "collections/Filters", - "collections/SolrResults", - ], function (Filters, SolrResults) { - //Create a search for the metadata docs that document this data object - var searchFilters = new Filters([ - { - values: isDocBy, - fields: ["id", "seriesId"], - operator: "OR", - fieldsOperator: "OR", - matchSubstring: false, - }, - ]), - //Create a list of search results - searchResults = new SolrResults([], { - rows: isDocBy.length, - query: searchFilters.getQuery(), - fields: "obsoletes,obsoletedBy,id", - }); + if (isDocBy && isDocBy.length > 1) { + const view = this; + + require(["collections/Filters", "collections/SolrResults"], ( + Filters, + SolrResults, + ) => { + // Create a search for the metadata docs that document this data object + const searchFilters = new Filters([ + { + values: isDocBy, + fields: ["id", "seriesId"], + operator: "OR", + fieldsOperator: "OR", + matchSubstring: false, + }, + ]); + // Create a list of search results + const searchResults = new SolrResults([], { + rows: isDocBy.length, + query: searchFilters.getQuery(), + fields: "obsoletes,obsoletedBy,id", + }); - //When the search results are returned, process those results - view.listenToOnce( - searchResults, - "sync", - function (searchResults) { - //Keep track of the latest version of the metadata doc(s) - var latestVersions = []; - - //Iterate over each search result and find the latest version of each metadata version chain - searchResults.each(function (searchResult) { - //If this metadata isn't obsoleted by another object, it is the latest version - if (!searchResult.get("obsoletedBy")) { - latestVersions.push(searchResult.get("id")); - } - //If it is obsoleted by another object but that newer object does not document this data, then this is the latest version - else if ( - !_.contains(isDocBy, searchResult.get("obsoletedBy")) - ) { - latestVersions.push(searchResult.get("id")); - } - }, view); - - //If at least one latest version was found (should always be the case), - if (latestVersions.length) { - //Set that metadata pid as this view's pid and get that metadata model. - // TODO: Support navigation to multiple metadata docs. This should be a rare occurence, but - // it is possible that more than one metadata version chain documents a data object, and we need - // to show the user that the data is involved in multiple datasets. - view.navigateWithFragment(latestVersions[0], view.pid); + // When the search results are returned, process those results + view.listenToOnce(searchResults, "sync", (searchResults) => { + // Keep track of the latest version of the metadata doc(s) + const latestVersions = []; + + // Iterate over each search result and find the latest version of each metadata version chain + searchResults.each((searchResult) => { + // If this metadata isn't obsoleted by another object, it is the latest version + if (!searchResult.get("obsoletedBy")) { + latestVersions.push(searchResult.get("id")); } - //If a latest version wasn't found, which should never happen, but just in case, default to the - // last metadata pid in the isDocumentedBy field (most liekly to be the most recent since it was indexed last). - else { - view.navigateWithFragment(_.last(isDocBy), view.pid); + // If it is obsoleted by another object but that newer object does not document this data, then this is the latest version + else if ( + !_.contains(isDocBy, searchResult.get("obsoletedBy")) + ) { + latestVersions.push(searchResult.get("id")); } - }, - ); + }, view); + + // If at least one latest version was found (should always be the case), + if (latestVersions.length) { + // Set that metadata pid as this view's pid and get that metadata model. + // TODO: Support navigation to multiple metadata docs. This should be a rare occurence, but + // it is possible that more than one metadata version chain documents a data object, and we need + // to show the user that the data is involved in multiple datasets. + view.navigateWithFragment(latestVersions[0], view.pid); + } + // If a latest version wasn't found, which should never happen, but just in case, default to the + // last metadata pid in the isDocumentedBy field (most liekly to be the most recent since it was indexed last). + else { + view.navigateWithFragment(_.last(isDocBy), view.pid); + } + }); - //Send the query to the Solr search service + // Send the query to the Solr search service searchResults.query(); }); return; - } else { - this.noMetadata(this.model); } + this.noMetadata(this.model); } else if (this.model.get("formatType") == "RESOURCE") { - var packageModel = new Package({ id: this.model.get("id") }); + const packageModel = new Package({ id: this.model.get("id") }); packageModel.on( "complete", function () { - var metadata = packageModel.getMetadata(); + const metadata = packageModel.getMetadata(); if (!metadata) { this.noMetadata(packageModel); @@ -404,23 +399,23 @@ define([ return; } - //Get the package information + // Get the package information this.getPackageDetails(model.get("resourceMap")); }); - //Listen to 404 and 401 errors when we get the metadata object + // Listen to 404 and 401 errors when we get the metadata object this.listenToOnce(model, "404", this.showNotFound); this.listenToOnce(model, "401", this.showIsPrivate); - //Fetch the model + // Fetch the model model.getInfo(); }, - renderMetadata: function () { - var pid = this.model.get("id"); + renderMetadata() { + const pid = this.model.get("id"); this.hideLoading(); - //Load the template which holds the basic structure of the view + // Load the template which holds the basic structure of the view this.$el.html(this.template()); this.$(this.tableContainer).html( this.loadingTemplate({ @@ -428,11 +423,11 @@ define([ }), ); - //Insert the breadcrumbs + // Insert the breadcrumbs this.insertBreadcrumbs(); - //Insert the citation + // Insert the citation this.insertCitation(); - //Insert the data source logo + // Insert the data source logo this.insertDataSource(); // is this the latest version? (includes DOI link when needed) this.showLatestVersion(); @@ -443,11 +438,11 @@ define([ // If we're displaying the metrics well then display copy citation and edit button // inside the well if (MetacatUI.appModel.get("displayDatasetMetrics")) { - //Insert Metrics Stats into the dataset landing pages + // Insert Metrics Stats into the dataset landing pages this.insertMetricsControls(); } - //Show loading icon in metadata section + // Show loading icon in metadata section this.$(this.metadataContainer).html( this.loadingTemplate({ msg: "Retrieving metadata ..." }), ); @@ -461,15 +456,15 @@ define([ MetacatUI.appModel.get("viewServiceUrl") + encodeURIComponent(pid); if (endpoint && typeof endpoint !== "undefined") { - var viewRef = this; - var loadSettings = { + const viewRef = this; + const loadSettings = { url: endpoint, - success: function (response, status, xhr) { + success(response, status, xhr) { try { - //If the user has navigated away from the MetadataView, then don't render anything further + // If the user has navigated away from the MetadataView, then don't render anything further if (MetacatUI.appView.currentView != viewRef) return; - //Our fallback is to show the metadata details from the Solr index + // Our fallback is to show the metadata details from the Solr index if ( status == "error" || !response || @@ -477,7 +472,7 @@ define([ ) viewRef.renderMetadataFromIndex(); else { - //Check for a response that is a 200 OK status, but is an error msg + // Check for a response that is a 200 OK status, but is an error msg if ( response.length < 250 && response.indexOf("Error transforming document") > -1 && @@ -486,8 +481,8 @@ define([ viewRef.renderMetadataFromIndex(); return; } - //Mark this as a metadata doc with no stylesheet, or one that is at least different than usual EML and FGDC - else if (response.indexOf('id="Metadata"') == -1) { + // Mark this as a metadata doc with no stylesheet, or one that is at least different than usual EML and FGDC + if (response.indexOf('id="Metadata"') == -1) { viewRef.$el.addClass("container no-stylesheet"); if (viewRef.model.get("indexed")) { @@ -496,15 +491,15 @@ define([ } } - //Now show the response from the view service + // Now show the response from the view service viewRef.$(viewRef.metadataContainer).html(response); - _.each($(response).find(".entitydetails"), function (entityEl) { - var entityId = $(entityEl).data("id"); + _.each($(response).find(".entitydetails"), (entityEl) => { + const entityId = $(entityEl).data("id"); viewRef.storeEntityPIDs(entityEl, entityId); }); - //If there is no info from the index and there is no metadata doc rendered either, then display a message + // If there is no info from the index and there is no metadata doc rendered either, then display a message if ( viewRef.$el.is(".no-stylesheet") && viewRef.model.get("archived") && @@ -520,7 +515,7 @@ define([ viewRef.trigger("metadataLoaded"); - //Add a map of the spatial coverage + // Add a map of the spatial coverage if (gmaps) viewRef.insertSpatialCoverageMap(); // Injects Clipboard objects into DOM elements returned from the View Service @@ -535,7 +530,7 @@ define([ viewRef.renderMetadataFromIndex(); } }, - error: function (xhr, textStatus, errorThrown) { + error(xhr, textStatus, errorThrown) { viewRef.renderMetadataFromIndex(); }, }; @@ -547,7 +542,7 @@ define([ // Insert the Linked Data into the header of the page. if (MetacatUI.appModel.get("isJSONLDEnabled")) { - var json = this.generateJSONLD(); + const json = this.generateJSONLD(); this.insertJSONLD(json); } @@ -555,76 +550,76 @@ define([ }, /* If there is no view service available, then display the metadata fields from the index */ - renderMetadataFromIndex: function () { - var metadataFromIndex = new MetadataIndex({ + renderMetadataFromIndex() { + const metadataFromIndex = new MetadataIndex({ pid: this.pid, parentView: this, }); this.subviews.push(metadataFromIndex); - //Add the metadata HTML + // Add the metadata HTML this.$(this.metadataContainer).html(metadataFromIndex.render().el); - var view = this; + const view = this; - this.listenTo(metadataFromIndex, "complete", function () { - //Add the package contents + this.listenTo(metadataFromIndex, "complete", () => { + // Add the package contents view.insertPackageDetails(); - //Add a map of the spatial coverage + // Add a map of the spatial coverage if (gmaps) view.insertSpatialCoverageMap(); }); }, - removeCitation: function () { - var citation = "", - citationEl = null; + removeCitation() { + let citation = ""; + let citationEl = null; - //Find the citation element + // Find the citation element if (this.$(".citation").length > 0) { - //Get the text for the citation + // Get the text for the citation citation = this.$(".citation").text(); - //Save this element in the view + // Save this element in the view citationEl = this.$(".citation"); } - //Older versions of Metacat (v2.4.3 and older) will not have the citation class in the XSLT. Find the citation another way + // Older versions of Metacat (v2.4.3 and older) will not have the citation class in the XSLT. Find the citation another way else { - //Find the DOM element with the citation - var wells = this.$(".well"), - viewRef = this; + // Find the DOM element with the citation + const wells = this.$(".well"); + const viewRef = this; - //Find the div.well with the citation. If we never find it, we don't insert the list of contents - _.each(wells, function (well) { + // Find the div.well with the citation. If we never find it, we don't insert the list of contents + _.each(wells, (well) => { if ( (!citationEl && $(well).find("#viewMetadataCitationLink").length > 0) || $(well).children(".row-fluid > .span10 > a") ) { - //Save this element in the view + // Save this element in the view citationEl = well; - //Mark this in the DOM for CSS styling + // Mark this in the DOM for CSS styling $(well).addClass("citation"); - //Save the text of the citation + // Save the text of the citation citation = $(well).text(); } }); - //Remove the unnecessary classes that are used in older versions of Metacat (2.4.3 and older) - var citationText = $(citationEl).find(".span10"); + // Remove the unnecessary classes that are used in older versions of Metacat (2.4.3 and older) + const citationText = $(citationEl).find(".span10"); $(citationText).removeClass("span10").addClass("span12"); } - //Set the document title to the citation + // Set the document title to the citation MetacatUI.appModel.set("title", citation); citationEl.remove(); }, - insertBreadcrumbs: function () { - var breadcrumbs = $(document.createElement("ol")) + insertBreadcrumbs() { + const breadcrumbs = $(document.createElement("ol")) .addClass("breadcrumb") .append( $(document.createElement("li")) @@ -643,12 +638,13 @@ define([ $(document.createElement("a")) .attr( "href", - MetacatUI.root + - "/data" + - (MetacatUI.appModel.get("page") > 0 - ? "/page/" + - (parseInt(MetacatUI.appModel.get("page")) + 1) - : ""), + `${MetacatUI.root}/data${ + MetacatUI.appModel.get("page") > 0 + ? `/page/${ + parseInt(MetacatUI.appModel.get("page")) + 1 + }` + : "" + }`, ) .addClass("search") .text("Search"), @@ -659,7 +655,7 @@ define([ $(document.createElement("a")) .attr( "href", - MetacatUI.root + "/view/" + encodeURIComponent(this.pid), + `${MetacatUI.root}/view/${encodeURIComponent(this.pid)}`, ) .addClass("inactive") .text("Metadata"), @@ -671,11 +667,11 @@ define([ $(document.createElement("a")) .attr( "href", - MetacatUI.root + - "/data/page/" + - (MetacatUI.appModel.get("page") > 0 + `${MetacatUI.root}/data/page/${ + MetacatUI.appModel.get("page") > 0 ? parseInt(MetacatUI.appModel.get("page")) + 1 - : ""), + : "" + }`, ) .attr("title", "Back") .addClass("back") @@ -693,16 +689,16 @@ define([ /* * When the metadata object doesn't exist, display a message to the user */ - showNotFound: function () { - //If the model was found, exit this function + showNotFound() { + // If the model was found, exit this function if (!this.model.get("notFound")) { return; } try { - //Check if a query string was in the URL and if so, try removing it in the identifier + // Check if a query string was in the URL and if so, try removing it in the identifier if (this.model.get("id").match(/\?\S+\=\S+/g) && !this.findTries) { - let newID = this.model.get("id").replace(/\?\S+\=\S+/g, ""); + const newID = this.model.get("id").replace(/\?\S+\=\S+/g, ""); this.onClose(); this.model.set("id", newID); this.pid = newID; @@ -714,38 +710,38 @@ define([ console.warn("Caught error while determining query string", e); } - //Construct a message that shows this object doesn't exist - var msg = - "
The dataset identifier '" + - Utilities.encodeHTML(this.model.get("id")) + - "' " + - "does not exist or it may have been removed. Search for " + - "datasets that mention " + - Utilities.encodeHTML(this.model.get("id")) + - "
"; + // Construct a message that shows this object doesn't exist + const msg = + `The dataset identifier '${Utilities.encodeHTML( + this.model.get("id"), + )}' ` + + `does not exist or it may have been removed. Search for ` + + `datasets that mention ${Utilities.encodeHTML( + this.model.get("id"), + )}
`; - //Remove the loading message + // Remove the loading message this.hideLoading(); - //Show the not found error message + // Show the not found error message this.showError(msg); - //Add the pid to the link href. Add via JS so it is Attribute-encoded to prevent XSS attacks + // Add the pid to the link href. Add via JS so it is Attribute-encoded to prevent XSS attacks this.$("#metadata-view-not-found-message a").attr( "href", - MetacatUI.root + - "/data/query=" + - encodeURIComponent(this.model.get("id")), + `${MetacatUI.root}/data/query=${encodeURIComponent( + this.model.get("id"), + )}`, ); }, /* * When the metadata object is private, display a message to the user */ - showIsPrivate: function () { - //If we haven't checked the logged-in status of the user yet, wait a bit - //until we show a 401 msg, in case this content is their private content + showIsPrivate() { + // If we haven't checked the logged-in status of the user yet, wait a bit + // until we show a 401 msg, in case this content is their private content if (!MetacatUI.appUserModel.get("checked")) { this.listenToOnce( MetacatUI.appUserModel, @@ -755,7 +751,7 @@ define([ return; } - //If the user is logged in, the message will display that this dataset is private. + // If the user is logged in, the message will display that this dataset is private. if (MetacatUI.appUserModel.get("loggedIn")) { var msg = '' + " This is a private dataset."; } - //If the user isn't logged in, display a log in link. + // If the user isn't logged in, display a log in link. else { var msg = - '' + - '' + - '' + - " This is a private dataset. If you believe you have permission " + - 'to access this dataset, then sign in.'; + `` + + `` + + `` + + ` This is a private dataset. If you believe you have permission ` + + `to access this dataset, then sign in.`; } - //Remove the loading message + // Remove the loading message this.hideLoading(); - //Show the not found error message + // Show the not found error message this.showError(msg); }, - getPackageDetails: function (packageIDs) { - var completePackages = 0; + getPackageDetails(packageIDs) { + let completePackages = 0; - //This isn't a package, but just a lonely metadata doc... + // This isn't a package, but just a lonely metadata doc... if (!packageIDs || !packageIDs.length) { - var thisPackage = new Package({ id: null, members: [this.model] }); + const thisPackage = new Package({ id: null, members: [this.model] }); thisPackage.flagComplete(); this.packageModels = [thisPackage]; this.insertPackageDetails(thisPackage, { @@ -801,32 +795,30 @@ define([ _.each( packageIDs, function (thisPackageID, i) { - //Create a model representing the data package - var thisPackage = new Package({ id: thisPackageID }); + // Create a model representing the data package + const thisPackage = new Package({ id: thisPackageID }); - //Listen for any parent packages + // Listen for any parent packages this.listenToOnce( thisPackage, "change:parentPackageMetadata", this.insertParentLink, ); - //When the package info is fully retrieved + // When the package info is fully retrieved this.listenToOnce( thisPackage, "complete", function (thisPackage) { - //When all packages are fully retrieved + // When all packages are fully retrieved completePackages++; if (completePackages >= packageIDs.length) { - var latestPackages = _.filter( + const latestPackages = _.filter( this.packageModels, - function (m) { - return !_.contains(packageIDs, m.get("obsoletedBy")); - }, + (m) => !_.contains(packageIDs, m.get("obsoletedBy")), ); - //Set those packages as the most recent package + // Set those packages as the most recent package this.packageModels = latestPackages; this.insertPackageDetails(latestPackages); @@ -834,13 +826,13 @@ define([ }, ); - //Save the package in the view + // Save the package in the view this.packageModels.push(thisPackage); - //Make sure we get archived content, too + // Make sure we get archived content, too thisPackage.set("getArchivedMembers", true); - //Get the members + // Get the members thisPackage.getMembers({ getParentMetadata: true }); }, this, @@ -848,19 +840,19 @@ define([ } }, - alterMarkup: function () { - //Find the taxonomic range and give it a class for styling - for older versions of Metacat only (v2.4.3 and older) + alterMarkup() { + // Find the taxonomic range and give it a class for styling - for older versions of Metacat only (v2.4.3 and older) if (!this.$(".taxonomicCoverage").length) this.$('h4:contains("Taxonomic Range")') .parent() .addClass("taxonomicCoverage"); - //Remove ecogrid links and replace them with workable links + // Remove ecogrid links and replace them with workable links this.replaceEcoGridLinks(); - //Find the tab links for attribute names - this.$(".attributeListTable tr a").on("shown", function (e) { - //When the attribute link is clicked on, highlight the tab as active + // Find the tab links for attribute names + this.$(".attributeListTable tr a").on("shown", (e) => { + // When the attribute link is clicked on, highlight the tab as active $(e.target) .parents(".attributeListTable") .find(".active") @@ -868,7 +860,7 @@ define([ $(e.target).parents("tr").first().addClass("active"); }); - //Mark the first row in each attribute list table as active since the first attribute is displayed at first + // Mark the first row in each attribute list table as active since the first attribute is displayed at first this.$(".attributeListTable tr:first-child()").addClass("active"); // Add explanation text to the alternate identifier @@ -882,7 +874,7 @@ define([ * @returns {jQuery} The jQuery object for the icon element. * @since 2.26.0 */ - renderAltIdentifierHelpText: function () { + renderAltIdentifierHelpText() { try { // Find the HTML element that contains the alternate identifier. const altIdentifierLabel = this.$( @@ -920,17 +912,17 @@ define([ /* * Inserts a table with all the data package member information and sends the call to display annotations */ - insertPackageDetails: function (packages, options) { + insertPackageDetails(packages, options) { if (typeof options === "undefined") { var options = {}; } - //Don't insert the package details twice - var view = this; - var tableEls = this.$(view.tableContainer).children().not(".loading"); + // Don't insert the package details twice + const view = this; + const tableEls = this.$(view.tableContainer).children().not(".loading"); if (tableEls.length > 0) return; - //wait for the metadata to load - var metadataEls = this.$(view.metadataContainer).children(); + // wait for the metadata to load + const metadataEls = this.$(view.metadataContainer).children(); if (!metadataEls.length || metadataEls.first().is(".loading")) { this.once("metadataLoaded", function () { view.insertPackageDetails(this.packageModels, options); @@ -940,26 +932,26 @@ define([ if (!packages) var packages = this.packageModels; - //Get the entity names from this page/metadata + // Get the entity names from this page/metadata this.getEntityNames(packages); _.each( packages, function (packageModel) { - //If the package model is not complete, don't do anything + // If the package model is not complete, don't do anything if (!packageModel.complete) return; - //Insert a package table for each package in viewRef dataset - var nestedPckgs = packageModel.getNestedPackages(), - nestedPckgsToDisplay = []; + // Insert a package table for each package in viewRef dataset + const nestedPckgs = packageModel.getNestedPackages(); + let nestedPckgsToDisplay = []; - //If this metadata is not archived, filter out archived packages + // If this metadata is not archived, filter out archived packages if (!this.model.get("archived")) { - nestedPckgsToDisplay = _.reject(nestedPckgs, function (pkg) { - return pkg.get("archived"); - }); + nestedPckgsToDisplay = _.reject(nestedPckgs, (pkg) => + pkg.get("archived"), + ); } else { - //Display all packages is this metadata is archived + // Display all packages is this metadata is archived nestedPckgsToDisplay = nestedPckgs; } @@ -971,16 +963,16 @@ define([ ) ) { var title = packageModel.get("id") - ? 'Package: ' + - packageModel.get("id") + - "" + ? `Package: ${packageModel.get( + "id", + )}` : ""; - options.title = "Files in this dataset " + title; + options.title = `Files in this dataset ${title}`; options.nested = true; this.insertPackageTable(packageModel, options); } } else { - //If this metadata is not archived, then don't display archived packages + // If this metadata is not archived, then don't display archived packages if ( !( !this.model.get("archived") && @@ -988,24 +980,24 @@ define([ ) ) { var title = packageModel.get("id") - ? 'Package: ' + - packageModel.get("id") + - "" + ? `Package: ${packageModel.get( + "id", + )}` : ""; - options.title = "Files in this dataset " + title; + options.title = `Files in this dataset ${title}`; this.insertPackageTable(packageModel, options); } } - //Remove the extra download button returned from the XSLT since the package table will have all the download links + // Remove the extra download button returned from the XSLT since the package table will have all the download links $("#downloadPackage").remove(); }, this, ); - //If this metadata doc is not in a package, but is just a lonely metadata doc... + // If this metadata doc is not in a package, but is just a lonely metadata doc... if (!packages.length) { - var packageModel = new Package({ + const packageModel = new Package({ members: [this.model], }); packageModel.complete = true; @@ -1014,7 +1006,7 @@ define([ this.insertPackageTable(packageModel, options); } - //Insert the data details sections + // Insert the data details sections this.insertDataDetails(); // Get data package, if there is one, before checking write permissions @@ -1028,20 +1020,20 @@ define([ try { // Get the most recent package to display the provenance graphs if (packages.length) { - //Find the most recent Package model and fetch it + // Find the most recent Package model and fetch it let mostRecentPackage = _.find( packages, (p) => !p.get("obsoletedBy"), ); - //If all of the packages are obsoleted, then use the last package in the array, + // If all of the packages are obsoleted, then use the last package in the array, // which is most likely the most recent. /** @todo Use the DataONE version API to find the most recent package in the version chain */ if (!mostRecentPackage) { mostRecentPackage = packages[packages.length - 1]; } - //Get the data package only if it is not the same as the previously fetched package + // Get the data package only if it is not the same as the previously fetched package if (mostRecentPackage.get("id") != packages[0].get("id")) this.getDataPackage(mostRecentPackage.get("id")); } @@ -1052,16 +1044,16 @@ define([ ); } - //Initialize tooltips in the package table(s) + // Initialize tooltips in the package table(s) this.$(".tooltip-this").tooltip(); return this; }, - insertPackageTable: function (packageModel, options) { - var view = this; + insertPackageTable(packageModel, options) { + const view = this; if (this.dataPackage == null || !this.dataPackageSynced) { - this.listenToOnce(this, "changed:dataPackageSynced", function () { + this.listenToOnce(this, "changed:dataPackageSynced", () => { view.insertPackageTable(packageModel, options); }); return; @@ -1086,39 +1078,39 @@ define([ nested = false, disablePackageDownloads = false; - //** Draw the package table **// - var tableView = new DataPackageView({ + //* * Draw the package table **// + const tableView = new DataPackageView({ edit: false, dataPackage: this.dataPackage, currentlyViewing: this.pid, dataEntities: this.entities, - disablePackageDownloads: disablePackageDownloads, + disablePackageDownloads, parentView: this, - title: title, + title, packageTitle: this.model.get("title"), - nested: nested, + nested, metricsModel: this.metricsModel, }); - //Get the package table container - var tablesContainer = this.$(this.tableContainer); + // Get the package table container + const tablesContainer = this.$(this.tableContainer); - //After the first table, start collapsing them - var numTables = $(tablesContainer).find( + // After the first table, start collapsing them + const numTables = $(tablesContainer).find( "table.download-contents", ).length; if (numTables == 1) { var tableContainer = $(document.createElement("div")).attr( "id", - "additional-tables-for-" + this.cid, + `additional-tables-for-${this.cid}`, ); tableContainer.hide(); $(tablesContainer).append(tableContainer); } else if (numTables > 1) - var tableContainer = this.$("#additional-tables-for-" + this.cid); + var tableContainer = this.$(`#additional-tables-for-${this.cid}`); else var tableContainer = tablesContainer; - //Insert the package table HTML + // Insert the package table HTML $(tableContainer).empty(); $(tableContainer).append(tableView.render().el); @@ -1143,39 +1135,39 @@ define([ this.subviews.push(tableView); - //Trigger a custom event in this view that indicates the package table has been rendered + // Trigger a custom event in this view that indicates the package table has been rendered this.trigger("dataPackageRendered"); }, - insertParentLink: function (packageModel) { - var parentPackageMetadata = packageModel.get("parentPackageMetadata"), - view = this; + insertParentLink(packageModel) { + const parentPackageMetadata = packageModel.get("parentPackageMetadata"); + const view = this; - _.each(parentPackageMetadata, function (m, i) { - var title = m.get("title"), - icon = $(document.createElement("i")).addClass( - "icon icon-on-left icon-level-up", - ), - link = $(document.createElement("a")) - .attr( - "href", - MetacatUI.root + "/view/" + encodeURIComponent(m.get("id")), - ) - .addClass("parent-link") - .text("Parent dataset: " + title) - .prepend(icon); + _.each(parentPackageMetadata, (m, i) => { + const title = m.get("title"); + const icon = $(document.createElement("i")).addClass( + "icon icon-on-left icon-level-up", + ); + const link = $(document.createElement("a")) + .attr( + "href", + `${MetacatUI.root}/view/${encodeURIComponent(m.get("id"))}`, + ) + .addClass("parent-link") + .text(`Parent dataset: ${title}`) + .prepend(icon); view.$(view.parentLinkContainer).append(link); }); }, - insertSpatialCoverageMap: function (customCoordinates) { - //Find the geographic region container. Older versions of Metacat (v2.4.3 and less) will not have it classified so look for the header text + insertSpatialCoverageMap(customCoordinates) { + // Find the geographic region container. Older versions of Metacat (v2.4.3 and less) will not have it classified so look for the header text if (!this.$(".geographicCoverage").length) { - //For EML - var title = this.$('h4:contains("Geographic Region")'); + // For EML + let title = this.$('h4:contains("Geographic Region")'); - //For FGDC + // For FGDC if (title.length == 0) { title = this.$('label:contains("Bounding Coordinates")'); } @@ -1188,11 +1180,11 @@ define([ var directions = new Array("north", "south", "east", "west"); } - for (var i = 0; i < georegionEls.length; i++) { + for (let i = 0; i < georegionEls.length; i++) { var georegion = georegionEls[i]; if (typeof customCoordinates !== "undefined") { - //Extract the coordinates + // Extract the coordinates var n = customCoordinates[0]; var s = customCoordinates[1]; var e = customCoordinates[2]; @@ -1200,16 +1192,16 @@ define([ } else { var coordinates = new Array(); - _.each(directions, function (direction) { - //Parse text for older versions of Metacat (v2.4.3 and earlier) + _.each(directions, (direction) => { + // Parse text for older versions of Metacat (v2.4.3 and earlier) if (parseText) { - var labelEl = $(georegion).find( - 'label:contains("' + direction + '")', + const labelEl = $(georegion).find( + `label:contains("${direction}")`, ); if (labelEl.length) { var coordinate = $(labelEl).next().html(); if ( - typeof coordinate != "undefined" && + typeof coordinate !== "undefined" && coordinate.indexOf(" ") > -1 ) coordinate = coordinate.substring( @@ -1219,115 +1211,62 @@ define([ } } else { var coordinate = $(georegion) - .find("." + direction + "BoundingCoordinate") + .find(`.${direction}BoundingCoordinate`) .attr("data-value"); } - //Save our coordinate value + // Save our coordinate value coordinates.push(coordinate); }); - //Extract the coordinates + // Extract the coordinates var n = coordinates[0]; var s = coordinates[1]; var e = coordinates[2]; var w = coordinates[3]; } - //Create Google Map LatLng objects out of our coordinates - var latLngSW = new gmaps.LatLng(s, w); - var latLngNE = new gmaps.LatLng(n, e); - var latLngNW = new gmaps.LatLng(n, w); - var latLngSE = new gmaps.LatLng(s, e); + // Create Google Map LatLng objects out of our coordinates + const latLngSW = new gmaps.LatLng(s, w); + const latLngNE = new gmaps.LatLng(n, e); + const latLngNW = new gmaps.LatLng(n, w); + const latLngSE = new gmaps.LatLng(s, e); - //Get the centertroid location of this data item - var bounds = new gmaps.LatLngBounds(latLngSW, latLngNE); - var latLngCEN = bounds.getCenter(); + // Get the centertroid location of this data item + const bounds = new gmaps.LatLngBounds(latLngSW, latLngNE); + const latLngCEN = bounds.getCenter(); - //If there isn't a center point found, don't draw the map. - if (typeof latLngCEN == "undefined") { + // If there isn't a center point found, don't draw the map. + if (typeof latLngCEN === "undefined") { return; } - //Get the map path color - var pathColor = MetacatUI.appModel.get("datasetMapPathColor"); + // Get the map path color + let pathColor = MetacatUI.appModel.get("datasetMapPathColor"); if (pathColor) { - pathColor = "color:" + pathColor + "|"; + pathColor = `color:${pathColor}|`; } else { pathColor = ""; } - //Get the map path fill color - var fillColor = MetacatUI.appModel.get("datasetMapFillColor"); + // Get the map path fill color + let fillColor = MetacatUI.appModel.get("datasetMapFillColor"); if (fillColor) { - fillColor = "fillcolor:" + fillColor + "|"; + fillColor = `fillcolor:${fillColor}|`; } else { fillColor = ""; } - //Create a google map image - var mapHTML = - ""; - - //Find the spot in the DOM to insert our map image + // Create a google map image + const mapHTML = + ``; + + // Find the spot in the DOM to insert our map image if (parseText) var insertAfter = $(georegion) .find('label:contains("West")') @@ -1335,7 +1274,7 @@ define([ .parent().length ? $(georegion).find('label:contains("West")').parent().parent() : georegion; - //The last coordinate listed + // The last coordinate listed else var insertAfter = georegion; // Get the URL to the interactive Google Maps instance @@ -1345,7 +1284,7 @@ define([ $(insertAfter).append( this.mapTemplate({ map: mapHTML, - url: url, + url, }), ); @@ -1370,7 +1309,7 @@ define([ * @returns {string} The URL to the Google Maps instance. * @since 2.27.0 */ - getGoogleMapsUrl: function (latLngCEN, bounds) { + getGoogleMapsUrl(latLngCEN, bounds) { // Use the window width and height as a proxy for the map dimensions const mapDim = { height: $(window).height(), @@ -1387,50 +1326,60 @@ define([ * Returns the zoom level that will display the given bounding box at * the given dimensions. * @param {LatLngBounds} bounds - The bounding box to display. - * @param {Object} mapDim - The dimensions of the map. + * @param {object} mapDim - The dimensions of the map. * @param {number} mapDim.height - The height of the map. * @param {number} mapDim.width - The width of the map. * @returns {number} The zoom level. * @since 2.27.0 */ - getBoundsZoomLevel: function (bounds, mapDim) { - var WORLD_DIM = { height: 256, width: 256 }; - var ZOOM_MAX = 15; + getBoundsZoomLevel(bounds, mapDim) { + const WORLD_DIM = { height: 256, width: 256 }; + const ZOOM_MAX = 15; // 21 is actual max, but any closer and the map is too zoomed in to be // useful + /** + * + * @param lat + */ function latRad(lat) { - var sin = Math.sin((lat * Math.PI) / 180); - var radX2 = Math.log((1 + sin) / (1 - sin)) / 2; + const sin = Math.sin((lat * Math.PI) / 180); + const radX2 = Math.log((1 + sin) / (1 - sin)) / 2; return Math.max(Math.min(radX2, Math.PI), -Math.PI) / 2; } + /** + * + * @param mapPx + * @param worldPx + * @param fraction + */ function zoom(mapPx, worldPx, fraction) { return Math.floor(Math.log(mapPx / worldPx / fraction) / Math.LN2); } - var ne = bounds.getNorthEast(); - var sw = bounds.getSouthWest(); + const ne = bounds.getNorthEast(); + const sw = bounds.getSouthWest(); - var latFraction = (latRad(ne.lat()) - latRad(sw.lat())) / Math.PI; + const latFraction = (latRad(ne.lat()) - latRad(sw.lat())) / Math.PI; - var lngDiff = ne.lng() - sw.lng(); - var lngFraction = (lngDiff < 0 ? lngDiff + 360 : lngDiff) / 360; + const lngDiff = ne.lng() - sw.lng(); + const lngFraction = (lngDiff < 0 ? lngDiff + 360 : lngDiff) / 360; - var latZoom = zoom(mapDim.height, WORLD_DIM.height, latFraction); - var lngZoom = zoom(mapDim.width, WORLD_DIM.width, lngFraction); + const latZoom = zoom(mapDim.height, WORLD_DIM.height, latFraction); + const lngZoom = zoom(mapDim.width, WORLD_DIM.width, lngFraction); return Math.min(latZoom, lngZoom, ZOOM_MAX); }, - insertCitation: function () { + insertCitation() { if (!this.model) return false; - //Create a citation header element from the model attributes - var header = new CitationHeaderView({ model: this.model }); + // Create a citation header element from the model attributes + const header = new CitationHeaderView({ model: this.model }); this.$(this.citationContainer).html(header.render().el); }, - insertDataSource: function () { + insertDataSource() { if ( !this.model || !MetacatUI.nodeModel || @@ -1439,12 +1388,12 @@ define([ ) return; - var dataSource = MetacatUI.nodeModel.getMember(this.model), - replicaMNs = MetacatUI.nodeModel.getMembers( - this.model.get("replicaMN"), - ); + const dataSource = MetacatUI.nodeModel.getMember(this.model); + let replicaMNs = MetacatUI.nodeModel.getMembers( + this.model.get("replicaMN"), + ); - //Filter out the data source from the replica nodes + // Filter out the data source from the replica nodes if (Array.isArray(replicaMNs) && replicaMNs.length) { replicaMNs = _.without(replicaMNs, dataSource); } @@ -1452,20 +1401,20 @@ define([ if (dataSource && dataSource.logo) { this.$("img.data-source").remove(); - //Construct a URL to the profile of this repository - var profileURL = + // Construct a URL to the profile of this repository + const profileURL = dataSource.identifier == MetacatUI.appModel.get("nodeId") - ? MetacatUI.root + "/profile" - : MetacatUI.appModel.get("dataoneSearchUrl") + - "/portals/" + - dataSource.shortIdentifier; + ? `${MetacatUI.root}/profile` + : `${MetacatUI.appModel.get("dataoneSearchUrl")}/portals/${ + dataSource.shortIdentifier + }`; - //Insert the data source template + // Insert the data source template this.$(this.dataSourceContainer) .html( this.dataSourceTemplate({ node: dataSource, - profileURL: profileURL, + profileURL, }), ) .addClass("has-data-source"); @@ -1477,25 +1426,19 @@ define([ .popover({ trigger: "manual", html: true, - title: "From the " + dataSource.name + " repository", - content: function () { - var content = "" + dataSource.description + "
"; + title: `From the ${dataSource.name} repository`, + content() { + let content = `${dataSource.description}
`; if (replicaMNs.length) { - content += - "Your changes could not be saved.
", - ); + saveError(errorMsg) { + const errorId = `error${Math.round(Math.random() * 100)}`; + const message = $(document.createElement("div")).append( + "Your changes could not be saved.
", + ); message.append( $(document.createElement("a")) .text("See details") .attr("data-toggle", "collapse") - .attr("data-target", "#" + errorId) + .attr("data-target", `#${errorId}`) .addClass("pointer"), $(document.createElement("div")) .addClass("collapse") @@ -2282,7 +2222,7 @@ define([ ); MetacatUI.appView.showAlert(message, "alert-error", "body", null, { - emailBody: "Error message: Data Package save error: " + errorMsg, + emailBody: `Error message: Data Package save error: ${errorMsg}`, remove: true, }); @@ -2297,11 +2237,11 @@ define([ /* If provenance relationships have been modified by the provenance editor (in ProvChartView), then update the ORE Resource Map and save it to the server. */ - saveProv: function () { + saveProv() { // Only call this function once per save operation. if (this.saveProvPending) return; - var view = this; + const view = this; if (this.dataPackage.provEditsPending()) { this.saveProvPending = true; // If the Data Package failed saving, display an error message @@ -2315,12 +2255,12 @@ define([ this.showSaving(); this.dataPackage.saveProv(); } else { - //TODO: should a dialog be displayed saying that no prov edits were made? + // TODO: should a dialog be displayed saying that no prov edits were made? } }, - showSaving: function () { - //Change the style of the save button + showSaving() { + // Change the style of the save button this.$("#save-metadata-prov") .html(' Saving...') .addClass("btn-disabled"); @@ -2328,59 +2268,59 @@ define([ this.$("input, textarea, select, button").prop("disabled", true); }, - hideSaving: function () { + hideSaving() { this.$("input, textarea, select, button").prop("disabled", false); - //When prov is saved, revert the Save button back to normal + // When prov is saved, revert the Save button back to normal this.$("#save-metadata-prov").html("Save").removeClass("btn-disabled"); }, - showEditorControls: function () { + showEditorControls() { this.$("#editor-footer").slideDown(); }, - hideEditorControls: function () { + hideEditorControls() { this.$("#editor-footer").slideUp(); }, - getEntityNames: function (packageModels) { - var viewRef = this; + getEntityNames(packageModels) { + const viewRef = this; - _.each(packageModels, function (packageModel) { - //Don't get entity names for larger packages - users must put the names in the system metadata + _.each(packageModels, (packageModel) => { + // Don't get entity names for larger packages - users must put the names in the system metadata if (packageModel.get("members").length > 100) return; - //If this package has a different metadata doc than the one we are currently viewing - var metadataModel = packageModel.getMetadata(); + // If this package has a different metadata doc than the one we are currently viewing + const metadataModel = packageModel.getMetadata(); if (!metadataModel) return; if (metadataModel.get("id") != viewRef.pid) { - var requestSettings = { + const requestSettings = { url: MetacatUI.appModel.get("viewServiceUrl") + encodeURIComponent(metadataModel.get("id")), - success: function (parsedMetadata, response, xhr) { - _.each(packageModel.get("members"), function (solrResult, i) { - var entityName = ""; + success(parsedMetadata, response, xhr) { + _.each(packageModel.get("members"), (solrResult, i) => { + let entityName = ""; if (solrResult.get("formatType") == "METADATA") entityName = solrResult.get("title"); - var container = viewRef.findEntityDetailsContainer( + const container = viewRef.findEntityDetailsContainer( solrResult, parsedMetadata, ); if (container) entityName = viewRef.getEntityName(container); - //Set the entity name + // Set the entity name if (entityName) { solrResult.set("fileName", entityName); - //Update the UI with the new name + // Update the UI with the new name viewRef .$( - ".entity-name-placeholder[data-id='" + - solrResult.get("id") + - "']", + `.entity-name-placeholder[data-id='${solrResult.get( + "id", + )}']`, ) .text(entityName); } @@ -2398,8 +2338,8 @@ define([ return; } - _.each(packageModel.get("members"), function (solrResult, i) { - var entityName = ""; + _.each(packageModel.get("members"), (solrResult, i) => { + let entityName = ""; if (solrResult.get("fileName")) entityName = solrResult.get("fileName"); @@ -2407,23 +2347,23 @@ define([ entityName = solrResult.get("title"); else if (solrResult.get("formatType") == "RESOURCE") return; else { - var container = viewRef.findEntityDetailsContainer(solrResult); + const container = viewRef.findEntityDetailsContainer(solrResult); if (container && container.length > 0) entityName = viewRef.getEntityName(container); else entityName = null; } - //Set the entityName, even if it's null + // Set the entityName, even if it's null solrResult.set("fileName", entityName); }); }); }, - getEntityName: function (containerEl) { + getEntityName(containerEl) { if (!containerEl) return false; - var entityName = $(containerEl) + let entityName = $(containerEl) .find(".entityName") .attr("data-entity-name"); if (typeof entityName === "undefined" || !entityName) { @@ -2437,26 +2377,25 @@ define([ return entityName; }, - //Checks if the metadata has entity details sections - hasEntityDetails: function () { + // Checks if the metadata has entity details sections + hasEntityDetails() { return this.$(".entitydetails").length > 0; }, /** * Finds the element in the rendered metadata that describes the given data entity. - * * @param {(DataONEObject|SolrResult|string)} model - Either a model that represents the data object or the identifier of the data object * @param {Element} [el] - The DOM element to exclusivly search inside. - * @return {Element} - The DOM element that describbbes the given data entity. + * @returns {Element} - The DOM element that describbbes the given data entity. */ - findEntityDetailsContainer: function (model, el) { - if (!el) var el = this.el; + findEntityDetailsContainer(model, el) { + if (!el) var { el } = this; - //Get the id and file name for this data object - var id = "", - fileName = ""; + // Get the id and file name for this data object + let id = ""; + let fileName = ""; - //If a model is given, get the id and file name from the object + // If a model is given, get the id and file name from the object if ( model && (DataONEObject.prototype.isPrototypeOf(model) || @@ -2465,69 +2404,68 @@ define([ id = model.get("id"); fileName = model.get("fileName"); } - //If a string is given instead, it must be the id of the data object - else if (typeof model == "string") { + // If a string is given instead, it must be the id of the data object + else if (typeof model === "string") { id = model; } - //Otherwise, there isn't enough info to find the element, so exit + // Otherwise, there isn't enough info to find the element, so exit else { return; } - //If we already found it earlier, return it now - var container = this.$( - ".entitydetails[data-id='" + - id + - "'], " + - ".entitydetails[data-id='" + - DataONEObject.prototype.getXMLSafeID(id) + - "']", + // If we already found it earlier, return it now + let container = this.$( + `.entitydetails[data-id='${id}'], ` + + `.entitydetails[data-id='${DataONEObject.prototype.getXMLSafeID( + id, + )}']`, ); if (container.length) { - //Store the PID on this element for moreInfo icons + // Store the PID on this element for moreInfo icons this.storeEntityPIDs(container, id); return container; } - //Are we looking for the main object that this MetadataView is displaying? + // Are we looking for the main object that this MetadataView is displaying? if (id == this.pid) { if (this.$("#Metadata").length > 0) return this.$("#Metadata"); - else return this.el; + return this.el; } - //Metacat 2.4.2 and up will have the Online Distribution Link marked - var link = this.$(".entitydetails a[data-pid='" + id + "']"); + // Metacat 2.4.2 and up will have the Online Distribution Link marked + let link = this.$(`.entitydetails a[data-pid='${id}']`); - //Otherwise, try looking for an anchor with the id matching this object's id + // Otherwise, try looking for an anchor with the id matching this object's id if (!link.length) - link = $(el).find("a#" + id.replace(/[^A-Za-z0-9]/g, "\\$&")); + link = $(el).find(`a#${id.replace(/[^A-Za-z0-9]/g, "\\$&")}`); - //Get metadata index view - var metadataFromIndex = _.findWhere(this.subviews, { + // Get metadata index view + let metadataFromIndex = _.findWhere(this.subviews, { type: "MetadataIndex", }); if (typeof metadataFromIndex === "undefined") metadataFromIndex = null; - //Otherwise, find the Online Distribution Link the hard way + // Otherwise, find the Online Distribution Link the hard way if (link.length < 1 && !metadataFromIndex) link = $(el).find( - ".control-label:contains('Online Distribution Info') + .controls-well > a[href*='" + - id.replace(/[^A-Za-z0-9]/g, "\\$&") + - "']", + `.control-label:contains('Online Distribution Info') + .controls-well > a[href*='${id.replace( + /[^A-Za-z0-9]/g, + "\\$&", + )}']`, ); if (link.length > 0) { - //Get the container element + // Get the container element container = $(link).parents(".entitydetails"); if (container.length < 1) { - //backup - find the parent of this link that is a direct child of the form element - var firstLevelContainer = _.intersection( + // backup - find the parent of this link that is a direct child of the form element + const firstLevelContainer = _.intersection( $(link).parents("form").children(), $(link).parents(), ); - //Find the controls-well inside of that first level container, which is the well that contains info about this data object + // Find the controls-well inside of that first level container, which is the well that contains info about this data object if (firstLevelContainer.length > 0) container = $(firstLevelContainer).children(".controls-well"); @@ -2537,21 +2475,21 @@ define([ $(container).addClass("entitydetails"); } - //Add the id so we can easily find it later + // Add the id so we can easily find it later container.attr("data-id", id); - //Store the PID on this element for moreInfo icons + // Store the PID on this element for moreInfo icons this.storeEntityPIDs(container, id); return container; } - //----Find by file name rather than id----- + // ----Find by file name rather than id----- if (!fileName) { - //Get the name of the object first + // Get the name of the object first for (var i = 0; i < this.packageModels.length; i++) { var model = _.findWhere(this.packageModels[i].get("members"), { - id: id, + id, }); if (model) { fileName = model.get("fileName"); @@ -2561,49 +2499,46 @@ define([ } if (fileName) { - var possibleLocations = [ - ".entitydetails [data-object-name='" + fileName + "']", - ".entitydetails .control-label:contains('Object Name') + .controls-well:contains('" + - fileName + - "')", - ".entitydetails .control-label:contains('Entity Name') + .controls-well:contains('" + - fileName + - "')", + const possibleLocations = [ + `.entitydetails [data-object-name='${fileName}']`, + `.entitydetails .control-label:contains('Object Name') + .controls-well:contains('${fileName}')`, + `.entitydetails .control-label:contains('Entity Name') + .controls-well:contains('${fileName}')`, ]; - //Search through each possible location in the DOM where the file name might be + // Search through each possible location in the DOM where the file name might be for (var i = 0; i < possibleLocations.length; i++) { - //Get the elements in this view that match the possible location - var matches = this.$(possibleLocations[i]); + // Get the elements in this view that match the possible location + const matches = this.$(possibleLocations[i]); - //If exactly one match is found + // If exactly one match is found if (matches.length == 1) { - //Get the entity details parent element + // Get the entity details parent element container = $(matches).parents(".entitydetails").first(); - //Set the object ID on the element for easier locating later + // Set the object ID on the element for easier locating later container.attr("data-id", id); if (container.length) break; } } if (container.length) { - //Store the PID on this element for moreInfo icons + // Store the PID on this element for moreInfo icons this.storeEntityPIDs(container, id); return container; } } - //--- The last option:---- - //If this package has only one item, we can assume the only entity details are about that item - var members = this.packageModels[0].get("members"), - dataMembers = _.filter(members, function (m) { - return m.get("formatType") == "DATA"; - }); + // --- The last option:---- + // If this package has only one item, we can assume the only entity details are about that item + const members = this.packageModels[0].get("members"); + const dataMembers = _.filter( + members, + (m) => m.get("formatType") == "DATA", + ); if (dataMembers.length == 1) { if (this.$(".entitydetails").length == 1) { this.$(".entitydetails").attr("data-id", id); - //Store the PID on this element for moreInfo icons + // Store the PID on this element for moreInfo icons this.storeEntityPIDs(this.$(".entitydetails"), id); return this.$(".entitydetails"); @@ -2616,79 +2551,81 @@ define([ /* * Inserts new image elements into the DOM via the image template. Use for displaying images that are part of this metadata's resource map. */ - insertDataDetails: function () { - //If there is a metadataIndex subview, render from there. - var metadataFromIndex = _.findWhere(this.subviews, { + insertDataDetails() { + // If there is a metadataIndex subview, render from there. + const metadataFromIndex = _.findWhere(this.subviews, { type: "MetadataIndex", }); if (typeof metadataFromIndex !== "undefined") { - _.each(this.packageModels, function (packageModel) { + _.each(this.packageModels, (packageModel) => { metadataFromIndex.insertDataDetails(packageModel); }); return; } - var viewRef = this; + const viewRef = this; - _.each(this.packageModels, function (packageModel) { - var dataDisplay = "", - images = [], - other = [], - packageMembers = packageModel.get("members"); + _.each(this.packageModels, (packageModel) => { + const dataDisplay = ""; + const images = []; + const other = []; + const packageMembers = packageModel.get("members"); - //Don't do this for large packages + // Don't do this for large packages if (packageMembers.length > 150) return; - //==== Loop over each visual object and create a dataDisplay template for it to attach to the DOM ==== - _.each(packageMembers, function (solrResult, i) { - //Don't display any info about nested packages + //= === Loop over each visual object and create a dataDisplay template for it to attach to the DOM ==== + _.each(packageMembers, (solrResult, i) => { + // Don't display any info about nested packages if (solrResult.type == "Package") return; - var objID = solrResult.get("id"); + const objID = solrResult.get("id"); if (objID == viewRef.pid) return; - //Is this a visual object (image)? - var type = + // Is this a visual object (image)? + const type = solrResult.type == "SolrResult" ? solrResult.getType() : "Data set"; if (type == "image") images.push(solrResult); - //Find the part of the HTML Metadata view that describes this data object - var anchor = $(document.createElement("a")).attr( - "id", - objID.replace(/[^A-Za-z0-9]/g, "-"), - ), - container = viewRef.findEntityDetailsContainer(objID); + // Find the part of the HTML Metadata view that describes this data object + const anchor = $(document.createElement("a")).attr( + "id", + objID.replace(/[^A-Za-z0-9]/g, "-"), + ); + const container = viewRef.findEntityDetailsContainer(objID); - var downloadButton = new DownloadButtonView({ model: solrResult }); + const downloadButton = new DownloadButtonView({ + model: solrResult, + }); downloadButton.render(); - //Insert the data display HTML and the anchor tag to mark this spot on the page + // Insert the data display HTML and the anchor tag to mark this spot on the page if (container) { - //Only show data displays for images hosted on the same origin + // Only show data displays for images hosted on the same origin if (type == "image") { - //Create the data display HTML - var dataDisplay = $.parseHTML( + // Create the data display HTML + const dataDisplay = $.parseHTML( viewRef .dataDisplayTemplate({ - type: type, + type, src: solrResult.get("url"), - objID: objID, + objID, }) .trim(), ); - //Insert into the page + // Insert into the page if ($(container).children("label").length > 0) $(container).children("label").first().after(dataDisplay); else $(container).prepend(dataDisplay); - //If this image is private, we need to load it via an XHR request + // If this image is private, we need to load it via an XHR request if (!solrResult.get("isPublic")) { - //Create an XHR - var xhr = new XMLHttpRequest(); + // Create an XHR + const xhr = new XMLHttpRequest(); xhr.withCredentials = true; xhr.onload = function () { @@ -2698,12 +2635,12 @@ define([ .attr("src", window.URL.createObjectURL(xhr.response)); }; - //Open and send the request with the user's auth token + // Open and send the request with the user's auth token xhr.open("GET", solrResult.get("url")); xhr.responseType = "blob"; xhr.setRequestHeader( "Authorization", - "Bearer " + MetacatUI.appUserModel.get("token"), + `Bearer ${MetacatUI.appUserModel.get("token")}`, ); xhr.send(); } @@ -2711,7 +2648,7 @@ define([ $(container).prepend(anchor); - var nameLabel = $(container).find( + const nameLabel = $(container).find( "label:contains('Entity Name')", ); if (nameLabel.length) { @@ -2720,65 +2657,60 @@ define([ } }); - //==== Initialize the fancybox images ===== + //= === Initialize the fancybox images ===== // We will be checking every half-second if all the HTML has been loaded into the DOM - once they are all loaded, we can initialize the lightbox functionality. - var numImages = images.length, - //The shared lightbox options for both images - lightboxOptions = { - prevEffect: "elastic", - nextEffect: "elastic", - closeEffect: "elastic", - openEffect: "elastic", - aspectRatio: true, - closeClick: true, - afterLoad: function () { - //Create a custom HTML caption based on data stored in the DOM element - viewRef.title = - viewRef.title + - " Download "; - }, - helpers: { - title: { - type: "outside", - }, + const numImages = images.length; + // The shared lightbox options for both images + const lightboxOptions = { + prevEffect: "elastic", + nextEffect: "elastic", + closeEffect: "elastic", + openEffect: "elastic", + aspectRatio: true, + closeClick: true, + afterLoad() { + // Create a custom HTML caption based on data stored in the DOM element + viewRef.title = `${viewRef.title} Download `; + }, + helpers: { + title: { + type: "outside", }, - }; + }, + }; if (numImages > 0) { - var numImgChecks = 0, //Keep track of how many interval checks we have so we don't wait forever for images to load - lightboxImgSelector = - "a[class^='fancybox'][data-fancybox-type='image']"; + let numImgChecks = 0; // Keep track of how many interval checks we have so we don't wait forever for images to load + const lightboxImgSelector = + "a[class^='fancybox'][data-fancybox-type='image']"; - //Add additional options for images - var imgLightboxOptions = lightboxOptions; + // Add additional options for images + const imgLightboxOptions = lightboxOptions; imgLightboxOptions.type = "image"; imgLightboxOptions.perload = 1; - var initializeImgLightboxes = function () { + const initializeImgLightboxes = function () { numImgChecks++; - //Initialize what images have loaded so far after 5 seconds + // Initialize what images have loaded so far after 5 seconds if (numImgChecks == 10) { $(lightboxImgSelector).fancybox(imgLightboxOptions); } - //When 15 seconds have passed, stop checking so we don't blow up the browser + // When 15 seconds have passed, stop checking so we don't blow up the browser else if (numImgChecks > 30) { $(lightboxImgSelector).fancybox(imgLightboxOptions); window.clearInterval(imgIntervalID); return; } - //Are all of our images loaded yet? + // Are all of our images loaded yet? if (viewRef.$(lightboxImgSelector).length < numImages) return; - else { - //Initialize our lightboxes - $(lightboxImgSelector).fancybox(imgLightboxOptions); - //We're done - clear the interval - window.clearInterval(imgIntervalID); - } + // Initialize our lightboxes + $(lightboxImgSelector).fancybox(imgLightboxOptions); + + // We're done - clear the interval + window.clearInterval(imgIntervalID); }; var imgIntervalID = window.setInterval( @@ -2789,22 +2721,22 @@ define([ }); }, - replaceEcoGridLinks: function () { - var viewRef = this; + replaceEcoGridLinks() { + const viewRef = this; - //Find the element in the DOM housing the ecogrid link - $("a:contains('ecogrid://')").each(function (i, thisLink) { - //Get the link text - var linkText = $(thisLink).text(); + // Find the element in the DOM housing the ecogrid link + $("a:contains('ecogrid://')").each((i, thisLink) => { + // Get the link text + const linkText = $(thisLink).text(); - //Clean up the link text - var withoutPrefix = linkText.substring( - linkText.indexOf("ecogrid://") + 10, - ), - pid = withoutPrefix.substring(withoutPrefix.indexOf("/") + 1), - baseUrl = - MetacatUI.appModel.get("resolveServiceUrl") || - MetacatUI.appModel.get("objectServiceUrl"); + // Clean up the link text + const withoutPrefix = linkText.substring( + linkText.indexOf("ecogrid://") + 10, + ); + const pid = withoutPrefix.substring(withoutPrefix.indexOf("/") + 1); + const baseUrl = + MetacatUI.appModel.get("resolveServiceUrl") || + MetacatUI.appModel.get("objectServiceUrl"); $(thisLink) .attr("href", baseUrl + encodeURIComponent(pid)) @@ -2812,68 +2744,65 @@ define([ }); }, - publish: function (event) { + publish(event) { // target may not actually prevent click events, so double check - var disabled = $(event.target).closest("a").attr("disabled"); + const disabled = $(event.target).closest("a").attr("disabled"); if (disabled) { return false; } - var publishServiceUrl = MetacatUI.appModel.get("publishServiceUrl"); - var pid = $(event.target).closest("a").attr("pid"); - var ret = confirm( - "Are you sure you want to publish " + pid + " with a DOI?", + const publishServiceUrl = MetacatUI.appModel.get("publishServiceUrl"); + const pid = $(event.target).closest("a").attr("pid"); + const ret = confirm( + `Are you sure you want to publish ${pid} with a DOI?`, ); if (ret) { // show the loading icon - var message = "Publishing package...this may take a few moments"; + const message = "Publishing package...this may take a few moments"; this.showLoading(message); - var identifier = null; - var viewRef = this; - var requestSettings = { + let identifier = null; + const viewRef = this; + const requestSettings = { url: publishServiceUrl + pid, type: "PUT", xhrFields: { withCredentials: true, }, - success: function (data, textStatus, xhr) { + success(data, textStatus, xhr) { // the response should have new identifier in it identifier = $(data).find("d1\\:identifier, identifier").text(); if (identifier) { viewRef.hideLoading(); - var msg = - "Published data package '" + - identifier + - "'. If you are not redirected soon, you can view your published data package here"; + const msg = `Published data package '${identifier}'. If you are not redirected soon, you can view your published data package here`; viewRef.$el.find(".container").prepend( viewRef.alertTemplate({ - msg: msg, + msg, classes: "alert-success", }), ); // navigate to the new view after a few seconds - setTimeout(function () { + setTimeout(() => { // avoid a double fade out/in viewRef.$el.html(""); viewRef.showLoading(); - MetacatUI.uiRouter.navigate("view/" + identifier, { + MetacatUI.uiRouter.navigate(`view/${identifier}`, { trigger: true, }); }, 3000); } }, - error: function (xhr, textStatus, errorThrown) { + error(xhr, textStatus, errorThrown) { // show the error message, but stay on the same page - var msg = - "Publish failed: " + - $(xhr.responseText).find("description").text(); + const msg = `Publish failed: ${$(xhr.responseText) + .find("description") + .text()}`; viewRef.hideLoading(); viewRef.showError(msg); @@ -2889,25 +2818,25 @@ define([ } }, - //When the given ID from the URL is a resource map that has no metadata, do the following... - noMetadata: function (solrResultModel) { + // When the given ID from the URL is a resource map that has no metadata, do the following... + noMetadata(solrResultModel) { this.hideLoading(); this.$el.html(this.template()); this.pid = solrResultModel.get("resourceMap") || solrResultModel.get("id"); - //Insert breadcrumbs + // Insert breadcrumbs this.insertBreadcrumbs(); this.insertDataSource(); - //Insert a table of contents + // Insert a table of contents this.insertPackageTable(solrResultModel); this.renderMetadataFromIndex(); - //Insert a message that this data is not described by metadata + // Insert a message that this data is not described by metadata MetacatUI.appView.showAlert( "Additional information about this data is limited since metadata was not provided by the creator.", "alert-warning", @@ -2916,19 +2845,19 @@ define([ }, // this will lookup the latest version of the PID - showLatestVersion: function () { - //If this metadata doc is not obsoleted by a new version, then exit the function + showLatestVersion() { + // If this metadata doc is not obsoleted by a new version, then exit the function if (!this.model.get("obsoletedBy")) { return; } - var view = this; + const view = this; - //When the latest version is found, - this.listenTo(this.model, "change:newestVersion", function () { - //Make sure it has a newer version, and if so, + // When the latest version is found, + this.listenTo(this.model, "change:newestVersion", () => { + // Make sure it has a newer version, and if so, if (view.model.get("newestVersion") != view.model.get("id")) { - //Put a link to the newest version in the content + // Put a link to the newest version in the content view.$(".newer-version").replaceWith( view.versionTemplate({ pid: view.model.get("newestVersion"), @@ -2939,23 +2868,23 @@ define([ } }); - //Insert the newest version template with a loading message + // Insert the newest version template with a loading message this.$el.prepend( this.versionTemplate({ loading: true, }), ); - //Find the latest version of this metadata object + // Find the latest version of this metadata object this.model.findLatestVersion(); }, - showLoading: function (message) { + showLoading(message) { this.hideLoading(); MetacatUI.appView.scrollToTop(); - var loading = this.loadingTemplate({ msg: message }); + const loading = this.loadingTemplate({ msg: message }); if (!loading) return; this.$loading = $($.parseHTML(loading)); @@ -2964,18 +2893,18 @@ define([ this.$el.html(loading); }, - hideLoading: function () { + hideLoading() { if (this.$loading) this.$loading.remove(); if (this.$detached) this.$el.html(this.$detached); }, - showError: function (msg) { - //Remove any existing error messages + showError(msg) { + // Remove any existing error messages this.$el.children(".alert-container").remove(); this.$el.prepend( this.alertTemplate({ - msg: msg, + msg, classes: "alert-error", containerClasses: "page", includeEmail: true, @@ -2987,18 +2916,19 @@ define([ * When the "Metadata" button in the table is clicked while we are on the Metadata view, * we want to scroll to the anchor tag of this data object within the page instead of navigating * to the metadata page again, which refreshes the page and re-renders (more loading time) - **/ - previewData: function (e) { - //Don't go anywhere yet... + * @param e + */ + previewData(e) { + // Don't go anywhere yet... e.preventDefault(); - //Get the target and id of the click - var link = $(e.target); + // Get the target and id of the click + let link = $(e.target); if (!$(link).hasClass("preview")) link = $(link).parents("a.preview"); if (link) { var id = $(link).attr("data-id"); - if (typeof id === "undefined" || !id) return false; //This will make the app defualt to the child view previewData function + if (typeof id === "undefined" || !id) return false; // This will make the app defualt to the child view previewData function } else return false; // If we are on the Metadata view, update the URL and scroll to the @@ -3017,18 +2947,18 @@ define([ * element on the page set to an XML-safe version of the value in the * fragment/hash. Used to provide direct links to sub-resources on a page. */ - scrollToFragment: function () { - var hash = window.location.hash; + scrollToFragment() { + const { hash } = window.location; if (!hash || hash.length <= 1) { return; } - //Get the id from the URL hash and decode it - var idFragment = decodeURIComponent(hash.substring(1)); + // Get the id from the URL hash and decode it + const idFragment = decodeURIComponent(hash.substring(1)); - //Find the corresponding entity details section for this id - var entityDetailsEl = this.findEntityDetailsContainer(idFragment); + // Find the corresponding entity details section for this id + const entityDetailsEl = this.findEntityDetailsContainer(idFragment); if (entityDetailsEl || entityDetailsEl.length) { MetacatUI.appView.scrollTo(entityDetailsEl); @@ -3042,25 +2972,24 @@ define([ * is not a metadata PID but is, instead, a data PID. getModel() does * the work of finding an appropriate metadata PID for the data PID and * this method handles re-routing to the correct URL. - * * @param {string} metadata_pid - The new metadata PID * @param {string} data_pid - Optional. A data PID that's part of the * package metadata_pid exists within. */ - navigateWithFragment: function (metadata_pid, data_pid) { - var next_route = "view/" + encodeURIComponent(metadata_pid); + navigateWithFragment(metadata_pid, data_pid) { + let next_route = `view/${encodeURIComponent(metadata_pid)}`; if (typeof data_pid === "string" && data_pid.length > 0) { - next_route += "#" + encodeURIComponent(data_pid); + next_route += `#${encodeURIComponent(data_pid)}`; } MetacatUI.uiRouter.navigate(next_route, { trigger: true }); }, - closePopovers: function (e) { - //If this is a popover element or an element that has a popover, don't close anything. - //Check with the .classList attribute to account for SVG elements - var svg = $(e.target).parents("svg"); + closePopovers(e) { + // If this is a popover element or an element that has a popover, don't close anything. + // Check with the .classList attribute to account for SVG elements + const svg = $(e.target).parents("svg"); if ( _.contains(e.target.classList, "popover-this") || @@ -3071,38 +3000,38 @@ define([ ) return; - //Close all active popovers + // Close all active popovers this.$(".popover-this.active").popover("hide"); }, - highlightNode: function (e) { - //Find the id - var id = $(e.target).attr("data-id"); + highlightNode(e) { + // Find the id + let id = $(e.target).attr("data-id"); if (typeof id === "undefined" || !id) id = $(e.target).parents("[data-id]").attr("data-id"); - //If there is no id, return + // If there is no id, return if (typeof id === "undefined") return false; - //Highlight its node - $(".prov-chart .node[data-id='" + id + "']").toggleClass("active"); + // Highlight its node + $(`.prov-chart .node[data-id='${id}']`).toggleClass("active"); - //Highlight its metadata section + // Highlight its metadata section if (MetacatUI.appModel.get("pid") == id) this.$("#Metadata").toggleClass("active"); else { - var entityDetails = this.findEntityDetailsContainer(id); + const entityDetails = this.findEntityDetailsContainer(id); if (entityDetails) entityDetails.toggleClass("active"); } }, - onClose: function () { - var viewRef = this; + onClose() { + const viewRef = this; this.stopListening(); - _.each(this.subviews, function (subview) { + _.each(this.subviews, (subview) => { if (subview.onClose) subview.onClose(); }); @@ -3114,10 +3043,10 @@ define([ this.$detached = null; this.$loading = null; - //Put the document title back to the default + // Put the document title back to the default MetacatUI.appModel.resetTitle(); - //Remove view-specific classes + // Remove view-specific classes this.$el.removeClass("container no-stylesheet"); this.$el.empty(); @@ -3128,18 +3057,19 @@ define([ * a dataset citation from the value stored in the underlying model's * origin field. */ - getAuthorText: function () { - var authors = this.model.get("origin"), - count = 0, - authorText = ""; + getAuthorText() { + const authors = this.model.get("origin"); + let count = 0; + let authorText = ""; - _.each(authors, function (author) { + _.each(authors, (author) => { count++; if (count == 6) { authorText += ", et al. "; return; - } else if (count > 6) { + } + if (count > 6) { return; } @@ -3168,29 +3098,27 @@ define([ * dataset citation. This method falls back to the node ID when the proper * node name cannot be fetched from the app's NodeModel instance. */ - getPublisherText: function () { - var datasource = this.model.get("datasource"), - memberNode = MetacatUI.nodeModel.getMember(datasource); + getPublisherText() { + const datasource = this.model.get("datasource"); + const memberNode = MetacatUI.nodeModel.getMember(datasource); if (memberNode) { return memberNode.name; - } else { - return datasource; } + return datasource; }, /** * Generate a string appropriate to be used as the publication date in a * dataset citation. */ - getDatePublishedText: function () { + getDatePublishedText() { // Dataset/datePublished // Prefer pubDate, fall back to dateUploaded so we have something to show if (this.model.get("pubDate") !== "") { return this.model.get("pubDate"); - } else { - return this.model.get("dateUploaded"); } + return this.model.get("dateUploaded"); }, /** @@ -3200,27 +3128,27 @@ define([ * Note: `insertJSONLD` should be called to do the actual inserting into the * DOM. */ - generateJSONLD: function () { - var model = this.model; + generateJSONLD() { + const { model } = this; // Determine the path (either #view or view, depending on router // configuration) for use in the 'url' property - var href = document.location.href, - route = href - .replace(document.location.origin + "/", "") - .split("/")[0]; + const { href } = document.location; + const route = href + .replace(`${document.location.origin}/`, "") + .split("/")[0]; // First: Create a minimal Schema.org Dataset with just the fields we // know will come back from Solr (System Metadata fields). // Add the rest in conditional on whether they are present. - var elJSON = { + const elJSON = { "@context": { "@vocab": "https://schema.org/", }, "@type": "Dataset", - "@id": - "https://dataone.org/datasets/" + - encodeURIComponent(model.get("id")), + "@id": `https://dataone.org/datasets/${encodeURIComponent( + model.get("id"), + )}`, datePublished: this.getDatePublishedText(), dateModified: model.get("dateModified"), publisher: { @@ -3229,9 +3157,9 @@ define([ }, identifier: this.generateSchemaOrgIdentifier(model.get("id")), version: model.get("version"), - url: - "https://dataone.org/datasets/" + - encodeURIComponent(model.get("id")), + url: `https://dataone.org/datasets/${encodeURIComponent( + model.get("id"), + )}`, schemaVersion: model.get("formatId"), isAccessibleForFree: true, }; @@ -3239,10 +3167,10 @@ define([ // Attempt to add in a sameAs property of we have high confidence the // identifier is a DOI if (this.model.isDOI(model.get("id"))) { - var doi = this.getCanonicalDOIIRI(model.get("id")); + const doi = this.getCanonicalDOIIRI(model.get("id")); if (doi) { - elJSON["sameAs"] = doi; + elJSON.sameAs = doi; } } @@ -3250,17 +3178,15 @@ define([ // Name if (model.get("title")) { - elJSON["name"] = model.get("title"); + elJSON.name = model.get("title"); } // Creator if (model.get("origin")) { - elJSON["creator"] = model.get("origin").map(function (creator) { - return { - "@type": "Person", - name: creator, - }; - }); + elJSON.creator = model.get("origin").map((creator) => ({ + "@type": "Person", + name: creator, + })); } // Dataset/spatialCoverage @@ -3270,7 +3196,7 @@ define([ model.get("southBoundCoord") && model.get("westBoundCoord") ) { - var spatialCoverage = { + const spatialCoverage = { "@type": "Place", additionalProperty: [ { @@ -3306,8 +3232,7 @@ define([ if (model.get("beginDate") && !model.get("endDate")) { elJSON.temporalCoverage = model.get("beginDate"); } else if (model.get("beginDate") && model.get("endDate")) { - elJSON.temporalCoverage = - model.get("beginDate") + "/" + model.get("endDate"); + elJSON.temporalCoverage = `${model.get("beginDate")}/${model.get("endDate")}`; } // Dataset/variableMeasured @@ -3319,13 +3244,10 @@ define([ if (model.get("abstract")) { elJSON.description = model.get("abstract"); } else { - var datasets_url = - "https://dataone.org/datasets/" + - encodeURIComponent(model.get("id")); - elJSON.description = - "No description is available. Visit " + - datasets_url + - " for complete metadata about this dataset."; + const datasets_url = `https://dataone.org/datasets/${encodeURIComponent( + model.get("id"), + )}`; + elJSON.description = `No description is available. Visit ${datasets_url} for complete metadata about this dataset.`; } // Dataset/keywords @@ -3339,7 +3261,6 @@ define([ /** * Insert Schema.org-compliant JSONLD for the model bound to the view into * the head tag of the page (at the end). - * * @param {object} json - JSON-LD to insert into the page * * Some notes: @@ -3348,15 +3269,15 @@ define([ * - If not create a new script tag and append otherwise replace the text * for the script */ - insertJSONLD: function (json) { + insertJSONLD(json) { if (!document.getElementById("jsonld")) { - var el = document.createElement("script"); + const el = document.createElement("script"); el.type = "application/ld+json"; el.id = "jsonld"; el.text = JSON.stringify(json); document.querySelector("head").appendChild(el); } else { - var script = document.getElementById("jsonld"); + const script = document.getElementById("jsonld"); script.text = JSON.stringify(json); } }, @@ -3366,15 +3287,14 @@ define([ * * Tries to use the PropertyValue pattern when the identifier is a DOI * and falls back to a Text value otherwise - * * @param {string} identifier - The raw identifier */ - generateSchemaOrgIdentifier: function (identifier) { + generateSchemaOrgIdentifier(identifier) { if (!this.model.isDOI()) { return identifier; } - var doi = this.getCanonicalDOIIRI(identifier); + const doi = this.getCanonicalDOIIRI(identifier); if (!doi) { return identifier; @@ -3393,20 +3313,23 @@ define([ * * Either generates a GeoCoordinates (when the north and east coords are * the same) or a GeoShape otherwise. + * @param north + * @param east + * @param south + * @param west */ - generateSchemaOrgGeo: function (north, east, south, west) { + generateSchemaOrgGeo(north, east, south, west) { if (north === south) { return { "@type": "GeoCoordinates", latitude: north, longitude: west, }; - } else { - return { - "@type": "GeoShape", - box: west + ", " + south + " " + east + ", " + north, - }; } + return { + "@type": "GeoShape", + box: `${west}, ${south} ${east}, ${north}`, + }; }, /** @@ -3424,46 +3347,41 @@ define([ * * e.g., if the east bounding coordinate is 120 W and west bounding * coordinate is 140 E, geoJSON requires we specify 140 E as 220 - * * @param {number} north - North bounding coordinate * @param {number} east - East bounding coordinate * @param {number} south - South bounding coordinate * @param {number} west - West bounding coordinate */ - generateGeoJSONString: function (north, east, south, west) { + generateGeoJSONString(north, east, south, west) { if (north === south) { return this.generateGeoJSONPoint(north, east); - } else { - return this.generateGeoJSONPolygon(north, east, south, west); } + return this.generateGeoJSONPolygon(north, east, south, west); }, /** - * Generate a GeoJSON Point object - * - * @param {number} north - North bounding coordinate - * @param {number} east - East bounding coordinate - * - * Example: - * { - * "type": "Point", - * "coordinates": [ - * -105.01621, - * 39.57422 - * ]} - - */ - generateGeoJSONPoint: function (north, east) { - var preamble = '{"type":"Point","coordinates":', - inner = "[" + east + "," + north + "]", - postamble = "}"; + * Generate a GeoJSON Point object + * @param {number} north - North bounding coordinate + * @param {number} east - East bounding coordinate + * + * Example: + * { + * "type": "Point", + * "coordinates": [ + * -105.01621, + * 39.57422 + * ]} + */ + generateGeoJSONPoint(north, east) { + const preamble = '{"type":"Point","coordinates":'; + const inner = `[${east},${north}]`; + const postamble = "}"; return preamble + inner + postamble; }, /** * Generate a GeoJSON Polygon object from - * * @param {number} north - North bounding coordinate * @param {number} east - East bounding coordinate * @param {number} south - South bounding coordinate @@ -3481,10 +3399,9 @@ define([ * [ 100, 1 ], * [ 100, 0 ] * ]} - * */ - generateGeoJSONPolygon: function (north, east, south, west) { - var preamble = + generateGeoJSONPolygon(north, east, south, west) { + const preamble = '{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[['; // Handle the case when the polygon wraps across the 180W/180E boundary @@ -3492,44 +3409,24 @@ define([ east = 360 - east; } - var inner = - "[" + - west + - "," + - south + - "]," + - "[" + - east + - "," + - south + - "]," + - "[" + - east + - "," + - north + - "]," + - "[" + - west + - "," + - north + - "]," + - "[" + - west + - "," + - south + - "]"; - - var postamble = "]]}}"; + const inner = + `[${west},${south}],` + + `[${east},${south}],` + + `[${east},${north}],` + + `[${west},${north}],` + + `[${west},${south}]`; + + const postamble = "]]}}"; return preamble + inner + postamble; }, /** * Create a canonical IRI for a DOI given a random DataONE identifier. - * * @param {string} identifier: The identifier to (possibly) create the IRI * for. - * @return {string|null} Returns null when matching the identifier to a DOI + * @param identifier + * @returns {string|null} Returns null when matching the identifier to a DOI * regex fails or a string when the match is successful * * Useful for describing resources identified by DOIs in linked open data @@ -3537,7 +3434,7 @@ define([ * * Note: Really could be generalized to more identifier schemes. */ - getCanonicalDOIIRI: function (identifier) { + getCanonicalDOIIRI(identifier) { return MetacatUI.appModel.DOItoURL(identifier) || null; }, @@ -3547,26 +3444,26 @@ define([ * Currently supports Highwire Press style tags (citation_) which is * supposedly what Google (Scholar), Mendeley, and Zotero support. */ - insertCitationMetaTags: function () { + insertCitationMetaTags() { // Generate template data to use for all templates - var title = this.model.get("title"), - authors = this.model.get("origin"), - publisher = this.getPublisherText(), - date = new Date(this.getDatePublishedText()) - .getUTCFullYear() - .toString(), - isDOI = this.model.isDOI(this.model.get("id")), - id = this.model.get("id"), - abstract = this.model.get("abstract"); + const title = this.model.get("title"); + const authors = this.model.get("origin"); + const publisher = this.getPublisherText(); + const date = new Date(this.getDatePublishedText()) + .getUTCFullYear() + .toString(); + const isDOI = this.model.isDOI(this.model.get("id")); + const id = this.model.get("id"); + const abstract = this.model.get("abstract"); // Generate HTML strings from each template - var hwpt = this.metaTagsHighwirePressTemplate({ - title: title, - authors: authors, - publisher: publisher, - date: date, - isDOI: isDOI, - id: id, + const hwpt = this.metaTagsHighwirePressTemplate({ + title, + authors, + publisher, + date, + isDOI, + id, abstract, }); @@ -3592,12 +3489,12 @@ define([ ); }, - createAnnotationViews: function () { + createAnnotationViews() { try { - var viewRef = this; + const viewRef = this; - _.each($(".annotation"), function (annoEl) { - var newView = new AnnotationView({ + _.each($(".annotation"), (annoEl) => { + const newView = new AnnotationView({ el: annoEl, }); viewRef.subviews.push(newView); @@ -3607,11 +3504,11 @@ define([ } }, - insertMarkdownViews: function () { - var viewRef = this; + insertMarkdownViews() { + const viewRef = this; - _.each($(".markdown"), function (markdownEl) { - var newView = new MarkdownView({ + _.each($(".markdown"), (markdownEl) => { + const newView = new MarkdownView({ markdown: $(markdownEl).text().trim(), el: $(markdownEl).parent(), }); @@ -3625,25 +3522,26 @@ define([ }); }, - storeEntityPIDs: function (entityEl, entityId) { + storeEntityPIDs(entityEl, entityId) { + let entityPID = entityId; // Get the entity ID if it is null or undefined - if (entityId == null) entityId = $(entityEl).data("id"); + if (entityPID == null) entityPID = $(entityEl).data("id"); // Perform clean up with the entity ID - if (entityId & (typeof entityId === "string")) { + if (entityPID && typeof entityPID === "string") { // Check and replace urn-uuid- with urn:uuid: if the string starts with urn-uuid- - if (entityId.startsWith("urn-uuid-")) { - entityId = entityId.replace("urn-uuid-", "urn:uuid:"); + if (entityPID.startsWith("urn-uuid-")) { + entityPID = entityPID.replace("urn-uuid-", "urn:uuid:"); } // Check and replace doi-10. with doi:10. if the string starts with doi-10. - if (entityId.startsWith("doi-10.")) { - entityId = entityId.replace("doi-10.", "doi:10."); + if (entityPID.startsWith("doi-10.")) { + entityPID = entityPID.replace("doi-10.", "doi:10."); } } - if (!this.entities.includes(entityId)) { - this.entities.push(entityId); + if (!this.entities.includes(entityPID)) { + this.entities.push(entityPID); } }, },