/*global define */ define(['jquery', 'jqueryui', 'underscore', 'backbone'], function($, $ui, _, Backbone) { 'use strict'; /** * @class LookupModel * @classdesc A uttility model that contains functions for looking up values from various services * @classcategory Models */ var LookupModel = Backbone.Model.extend( /** @lends LookupModel.prototype */{ defaults: { concepts: {} }, initialize: function() { }, bioportalSearch: function(request, response, localValues, allValues) { // make sure we have something to lookup if (!MetacatUI.appModel.get('bioportalAPIKey')) { response(localValues); return; } var query = MetacatUI.appModel.get('bioportalSearchUrl') + "?q=" + request.term + "&apikey=" + MetacatUI.appModel.get("bioportalAPIKey") + "&ontologies=ECSO&pagesize=1000&suggest=true"; var availableTags = []; $.get(query, function(data, textStatus, xhr) { _.each(data.collection, function(obj) { var choice = {}; choice.label = obj['prefLabel']; var synonyms = obj['synonym']; if (synonyms) { choice.synonyms = []; _.each(synonyms, function(synonym) { choice.synonyms.push(synonym); }); } choice.filterLabel = obj['prefLabel']; choice.value = obj['@id']; if (obj['definition']) { choice.desc = obj['definition'][0]; } // mark items that we know we have matches for if (allValues) { var matchingChoice = _.findWhere(allValues, {value: choice.value}); if (matchingChoice) { //choice.label = "*" + choice.label; choice.match = true; // remove it from the local value - why have two? if (localValues) { localValues = _.reject(localValues, function(obj) { return obj.value == matchingChoice.value; }); } //availableTags.push(choice); } } availableTags.push(choice); }); // combine the lists if called that way if (localValues) { availableTags = localValues.concat(availableTags); } response(availableTags); }); }, bioportalExpand: function(term) { // make sure we have something to lookup if (!MetacatUI.appModel.get('bioportalAPIKey')) { response(null); return; } var terms = []; var countdown = 0; var query = MetacatUI.appModel.get('bioportalSearchUrl') + "?q=" + term + "&apikey=" + MetacatUI.appModel.get("bioportalAPIKey") + "&ontologies=ECSO&pagesize=1000&suggest=true";; $.ajax( { url: query, method: "GET", async: false, // we want to wait for the response! success: function(data, textStatus, xhr) { _.each(data.collection, function(obj) { // use the preferred label var prefLabel = obj['prefLabel']; terms.push(prefLabel); // add the synonyms var synonyms = obj['synonym']; if (synonyms) { _.each(synonyms, function(synonym) { terms.push(synonym); }); } // process the descendants var descendantsUrl = obj['links']['descendants']; //if (false) { if (descendantsUrl && countdown > 0) { countdown--; $.ajax( { url: descendantsUrl + "?apikey=" + MetacatUI.appModel.get("bioportalAPIKey"), method: "GET", async: false, success: function(data, textStatus, xhr) { _.each(data.collection, function(obj) { var prefLabel = obj['prefLabel']; var synonyms = obj['synonym']; if (synonyms) { _.each(synonyms, function(synonym) { terms.push(synonym); }); } }); } }); } }); } }); return terms; }, bioportalGetConcepts: function(uri, callback) { var concepts = this.get('concepts')[uri]; if (concepts) { callback(concepts); return; } else { concepts = []; } // make sure we have something to lookup if (!MetacatUI.appModel.get('bioportalAPIKey')) { return; } var query = MetacatUI.appModel.get('bioportalSearchUrl') + "?q=" + encodeURIComponent(uri) + "&apikey=" + MetacatUI.appModel.get("bioportalAPIKey") + "&ontologies=ECSO&pagesize=1000&suggest=true"; var availableTags = []; var model = this; $.get(query, function(data, textStatus, xhr) { _.each(data.collection, function(obj) { var concept = {}; concept.label = obj['prefLabel']; concept.value = obj['@id']; if (obj['definition']) { concept.desc = obj['definition'][0]; } // add the synonyms var synonyms = obj['synonym']; if (synonyms) { concept.synonyms = []; _.each(synonyms, function(synonym) { concept.synonyms.push(synonym); }); } concepts.push(concept); }); model.get('concepts')[uri] = concepts; callback(concepts); }); }, bioportalGetConceptsBatch: function(uris, callback) { // make sure we have something to lookup if (!MetacatUI.appModel.get('bioportalBatchUrl')) { return; } // prepare the request JSON var batchData = {}; batchData["http://www.w3.org/2002/07/owl#Class"] = {}; batchData["http://www.w3.org/2002/07/owl#Class"]["display"] = "prefLabel,synonym,definition"; batchData["http://www.w3.org/2002/07/owl#Class"]["collection"] = []; _.each(uris, function(uri) { var item = {}; item["class"] = uri; item["ontology"] = "http://data.bioontology.org/ontologies/ECSO"; batchData["http://www.w3.org/2002/07/owl#Class"]["collection"].push(item); }); var url = MetacatUI.appModel.get('bioportalBatchUrl'); var model = this; $.ajax(url, { method: "POST", //url: url, data: JSON.stringify(batchData), contentType: "application/json", headers: { "Authorization": "apikey token="+ MetacatUI.appModel.get("bioportalAPIKey") }, error: function(e) { console.log(e); }, success: function(data, textStatus, xhr) { _.each(data["http://www.w3.org/2002/07/owl#Class"], function(obj) { var concept = {}; concept.label = obj['prefLabel']; concept.value = obj['@id']; if (obj['definition']) { concept.desc = obj['definition'][0]; } // add the synonyms var synonyms = obj['synonym']; if (synonyms) { concept.synonyms = []; _.each(synonyms, function(synonym) { concept.synonyms.push(synonym); }); } var conceptList = []; conceptList.push(concept); model.get('concepts')[concept.value] = conceptList; }); callback.apply(); } }); }, orcidGetConcepts: function(uri, callback) { var people = this.get('concepts')[uri]; if (people) { callback(people); return; } else { people = []; } var query = MetacatUI.appModel.get('orcidBaseUrl') + uri.substring(uri.lastIndexOf("/")); var model = this; $.get(query, function(data, status, xhr) { // get the orcid info var profile = $(data).find("orcid-profile"); _.each(profile, function(obj) { var choice = {}; choice.label = $(obj).find("orcid-bio > personal-details > given-names").text() + " " + $(obj).find("orcid-bio > personal-details > family-name").text(); choice.value = $(obj).find("orcid-identifier > uri").text(); choice.desc = $(obj).find("orcid-bio > personal-details").text(); people.push(choice); }); model.get('concepts')[uri] = people; // callback with answers callback(people); }) }, /* * Supplies search results for ORCiDs to autocomplete UI elements */ orcidSearch: function(request, response, more, ignore) { var people = []; if(!ignore) var ignore = []; var query = MetacatUI.appModel.get('orcidSearchUrl') + request.term; $.get(query, function(data, status, xhr) { // get the orcid info var profile = $(data).find("orcid-profile"); _.each(profile, function(obj) { var choice = {}; choice.value = $(obj).find("orcid-identifier > uri").text(); if(_.contains(ignore, choice.value.toLowerCase())) return; choice.label = $(obj).find("orcid-bio > personal-details > given-names").text() + " " + $(obj).find("orcid-bio > personal-details > family-name").text(); choice.desc = $(obj).find("orcid-bio > personal-details").text(); people.push(choice); }); // add more if called that way if (more) { people = more.concat(people); } // callback with answers response(people); }); }, /* * Gets the bio of a person given an ORCID * Updates the given user model with the bio info from ORCID */ orcidGetBio: function(options){ if(!options || !options.userModel) return; var orcid = options.userModel.get("username"), onSuccess = options.success || function(){}, onError = options.error || function(){}; $.ajax({ url: MetacatUI.appModel.get("orcidSearchUrl") + orcid, type: "GET", //accepts: "application/orcid+json", success: function(data, textStatus, xhr){ // get the orcid info var orcidNode = $(data).find("path:contains(" + orcid + ")"), profile = orcidNode.length? $(orcidNode).parents("orcid-profile") : []; if(!profile.length) return; var fullName = $(profile).find("orcid-bio > personal-details > given-names").text() + " " + $(profile).find("orcid-bio > personal-details > family-name").text(); options.userModel.set("fullName", fullName); onSuccess(data, textStatus, xhr); }, error: function(xhr, textStatus, error){ onError(xhr, textStatus, error); } }); }, getGrantAutocomplete: function(request, response){ var term = $.ui.autocomplete.escapeRegex(request.term), filterBy = ""; //Only search after 3 characters or more if(term.length < 3) return; else if(term.match(/\d/)) return; //Don't search for digit only since it's most likely a user just entering the grant number directy else filterBy = "keyword"; var url = MetacatUI.appModel.get("grantsUrl") + "?" + filterBy + "=" + term + "&printFields=title,id"; // Send the AJAX request as a JSONP data type since it will be cross-origin var requestSettings = { url: url, dataType: "jsonp", success: function(data, textStatus, xhr) { // Handle the response from the NSF Award Search API and //transform each award query result into a jQueryUI autocomplete item if(!data || !data.response || !data.response.award) return []; var list = []; _.each(data.response.award, function(award, i){ list.push({ value: award.id, label: award.title }); }); var term = $.ui.autocomplete.escapeRegex(request.term) , startsWithMatcher = new RegExp("^" + term, "i") , startsWith = $.grep(list, function(value) { return startsWithMatcher.test(value.label || value.value || value); }) , containsMatcher = new RegExp(term, "i") , contains = $.grep(list, function (value) { return $.inArray(value, startsWith) < 0 && containsMatcher.test(value.label || value.value || value); }); response(startsWith.concat(contains)); } } //Send the query $.ajax(requestSettings); }, getGrant: function(id, onSuccess, onError){ if(!id || !onSuccess || !MetacatUI.appModel.get("useNSFAwardAPI") || !MetacatUI.appModel.get("grantsUrl")) return; var requestSettings = { url: MetacatUI.appModel.get("grantsUrl") + "?id=" + id, success: function(data, textStatus, xhr){ if(!data || !data.response || !data.response.award || !data.response.award.length){ if(onError) onError(); return; } onSuccess(data.response.award[0]); }, error: function(){ if(onError) onError(); } } //Send the query $.ajax(requestSettings); }, getAccountsAutocomplete: function(request, response){ var searchTerm = $.ui.autocomplete.escapeRegex(request.term); //Only search after 2 characters or more if(searchTerm.length < 2) return; var url = MetacatUI.appModel.get("accountsUrl") + "?query=" + searchTerm; // Send the AJAX request as a JSONP data type since it will be cross-origin var requestSettings = { url: url, success: function(data, textStatus, xhr) { if(!data) return []; //If an XML doc was not returned from the server, then try to parse the response as XML if( !XMLDocument.prototype.isPrototypeOf(data) ){ try{ data = $.parseXML(data); } catch(e){ //If the parsing XML failed, exit now console.error("The accounts service did not return valid XML.", e); return; } } var list = []; _.each($(data).children(/.+subjectInfo/).children(), function(accountNode, i){ var name = ""; if( $(accountNode).children("givenName").length ){ name = $(accountNode).children("givenName").text() + " " + $(accountNode).children("familyName").text() } else{ name = $(accountNode).children("groupName").text(); } if( !name ){ name = $(accountNode).children("subject").text(); } list.push({ value: $(accountNode).children("subject").text(), label: name + " (" + $(accountNode).children("subject").text() + ")" }); }); var term = $.ui.autocomplete.escapeRegex(request.term) , startsWithMatcher = new RegExp("^" + term, "i") , startsWith = $.grep(list, function(value) { return startsWithMatcher.test(value.label || value.value || value); }) , containsMatcher = new RegExp(term, "i") , contains = $.grep(list, function (value) { return $.inArray(value, startsWith) < 0 && containsMatcher.test(value.label || value.value || value); }); response(startsWith.concat(contains)); } } //Send the query $.ajax(requestSettings); }, /** * Calls the monitor/status DataONE MN API and gets the size of the index queue. * @param {function} [onSuccess] * @param {function} [onError] */ getSizeOfIndexQueue: function(onSuccess, onError){ try{ if( !MetacatUI.appModel.get("monitorStatusUrl") ){ if( typeof onSuccess == "function" ){ onSuccess(); } else{ //Trigger a custom event for the size of the index queue. this.trigger("sizeOfQueue", -1); } return false; } var model = this; //Check if there is an indexing queue, because this model may still be indexing var requestSettings = { url: MetacatUI.appModel.get("monitorStatusUrl"), type: "GET", error: function(){ if( typeof onError == "function" ){ onError(); } }, success: function(data){ var sizeOfQueue = parseInt($(data).find("status > index > sizeOfQueue").text()); if(sizeOfQueue > 0 || sizeOfQueue == 0){ //Trigger a custom event for the size of the index queue. model.trigger("sizeOfQueue", sizeOfQueue); if( typeof onSuccess == "function" ){ onSuccess(sizeOfQueue); } } else{ if( typeof onError == "function" ){ onError(); } } } } $.ajax(_.extend(requestSettings, MetacatUI.appUserModel.createAjaxSettings())); } catch(e){ console.error(e); if( typeof onError == "function" ){ onError(); } } } }); return LookupModel; });