diff --git a/build.gradle b/build.gradle index 4398da6..9bbff5d 100644 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,6 @@ plugins { id 'jacoco' } - version "7.2-SNAPSHOT" group "org.grails.plugins" diff --git a/grails-app/assets/javascripts/knockout-utils.js b/grails-app/assets/javascripts/knockout-utils.js index d4f9397..77310f3 100644 --- a/grails-app/assets/javascripts/knockout-utils.js +++ b/grails-app/assets/javascripts/knockout-utils.js @@ -13,53 +13,90 @@ */ ko.bindingHandlers.popover = { - init: function (element, valueAccessor) { + init: function(element, valueAccessor) { ko.bindingHandlers.popover.initPopover(element, valueAccessor); }, - update: function (element, valueAccessor) { + update: function(element, valueAccessor) { + var $element = $(element), + instance = $element.data('bs.popover'), + popOptions = ko.bindingHandlers.popover.getOptions(valueAccessor), + combinedOptions = popOptions.combinedOptions, + options = popOptions.options; + + if (!instance) { + ko.bindingHandlers.popover.initPopover(element, valueAccessor); + instance = $element.data('bs.popover'); + } + + if (!instance) + return; + + // if view model has changed, update the popover + instance.config.title = combinedOptions.title || ""; + instance.config.content = combinedOptions.content || ""; - var $element = $(element); - $element.popover('dispose'); - var options = ko.bindingHandlers.popover.initPopover(element, valueAccessor); if (options.autoShow) { if ($element.data('firstPopover') === false) { - $element.popover('show'); - $('body').on('click', function (e) { - + instance.show(); + $('body').on('click', function(e) { if (e.target != element && $element.find(e.target).length == 0) { - $element.popover('dispose'); + instance.hide(); } }); } + $element.data('firstPopover', false); } + // refresh popover content + if(ko.bindingHandlers.popover.isPopoverShown(element)) { + instance.show(); + } }, defaultOptions: { placement: "right", animation: true, html: true, - trigger: "hover", - delay: { - show: 250 - } + trigger: "hover" }, - initPopover: function (element, valueAccessor) { + initPopover: function(element, valueAccessor) { + var popOptions = ko.bindingHandlers.popover.getOptions(valueAccessor), + options = popOptions.options, + combinedOptions = popOptions.combinedOptions; + $(element).popover(combinedOptions); + ko.utils.domNodeDisposal.addDisposeCallback(element, function() { + $(element).popover("dispose"); + }); + + return options; + }, + /** + * constructs the options object from valueAccessor + * @param valueAccessor + * @returns {{combinedOptions: any, options: any}} + */ + getOptions: function(valueAccessor) { var options = ko.utils.unwrapObservable(valueAccessor()); + if (typeof(options.content) === "undefined") { + options.content = "" + } var combinedOptions = ko.utils.extend({}, ko.bindingHandlers.popover.defaultOptions); var content = ko.utils.unwrapObservable(options.content); ko.utils.extend(combinedOptions, options); combinedOptions.description = content; - - $(element).popover(combinedOptions); - - ko.utils.domNodeDisposal.addDisposeCallback(element, function () { - $(element).popover("dispose"); - }); - return options; + return {combinedOptions: combinedOptions, options: options}; + }, + /** + * id of the popover is stored in the element's aria-describedby attribute + * @param element + * @returns {boolean} + */ + isPopoverShown: function isPopoverShown(element) { + const popoverId = $(element).attr("aria-describedby"); + return $("#" + popoverId).length > 0; } }; diff --git a/grails-app/assets/javascripts/speciesModel.js b/grails-app/assets/javascripts/speciesModel.js index c34ca66..463556d 100644 --- a/grails-app/assets/javascripts/speciesModel.js +++ b/grails-app/assets/javascripts/speciesModel.js @@ -222,7 +222,7 @@ var speciesSearchEngines = function() { * Allows species information to be searched for and displayed. */ var SpeciesViewModel = function(data, options, context) { - + var SPECIAL_GUIDS = ['A_GUID']; var self = this; ecodata.forms.DataModelItem.apply(self, [options.metadata || {}, context, options]); @@ -232,6 +232,7 @@ var SpeciesViewModel = function(data, options, context) { var output = options.output || ""; var dataFieldName = options.dataFieldName || ""; var surveyName = options.surveyName || ""; + var kvpInfo = ""; self.guid = ko.observable(); self.name = ko.observable(); @@ -252,7 +253,7 @@ var SpeciesViewModel = function(data, options, context) { self.transients.source = ko.observable(options.speciesSearchUrl + '&output=' + output+ '&dataFieldName=' + dataFieldName + '&surveyName=' + surveyName); self.transients.bieUrl = ko.observable(); - self.transients.speciesInformation = ko.observable(); + self.transients.speciesInformation = ko.observable(''); self.transients.speciesTitle = ko.observable(); self.transients.matched = ko.computed(function() { return self.guid() && self.guid() != "A_GUID" && self.listId != "unmatched"; @@ -328,7 +329,6 @@ var SpeciesViewModel = function(data, options, context) { self.transients.textFieldValue(self.name()); // Species Translation - var kvpInfo = ""; var languages = ["Waramungu", "Warlpiri name"]; var listsId = 'dr8016'; if(self.listId() == listsId || output == 'CLC 2Ha Track Plot') { @@ -350,38 +350,44 @@ var SpeciesViewModel = function(data, options, context) { } }); } + }; + self.fetchSpeciesImage = function() { if (self.guid() && !options.printable) { + if (SPECIAL_GUIDS.indexOf(self.guid()) >= 0) { + var profileInfo = "No profile available"; + self.transients.speciesInformation(profileInfo); + } + else { + var profileUrl = options.bieUrl + '/species/' + encodeURIComponent(self.guid()); + $.ajax({ + url: options.speciesProfileUrl + '?id=' + encodeURIComponent(self.guid()), + cache: true, + dataType: 'json', + success: function (data) { + var profileInfo = ''; + var imageUrl = data.thumbnail || (data.taxonConcept && data.taxonConcept.smallImageUrl); - var profileUrl = options.bieUrl + '/species/' + encodeURIComponent(self.guid()); - $.ajax({ - url: options.speciesProfileUrl+'?id=' + encodeURIComponent(self.guid()), - dataType: 'json', - success: function (data) { - var profileInfo = ''; - var imageUrl = data.thumbnail || (data.taxonConcept && data.taxonConcept.smallImageUrl); - - if (imageUrl) { - profileInfo += ""; - } - else { - profileInfo += "No profile image available"; + if (imageUrl) { + profileInfo += ""; + } else { + profileInfo += "No profile image available"; + } + profileInfo += ""; + profileInfo += kvpInfo; + self.transients.speciesInformation(profileInfo); + }, + error: function (request, status, error) { + self.transients.speciesInformation(""); + console.log(error); } - profileInfo += ""; - profileInfo += kvpInfo; - self.transients.speciesInformation(profileInfo); - }, - error: function(request, status, error) { - console.log(error); - } - }); - + }); + } } else { self.transients.speciesInformation("No profile information is available."); } - - }; + } self.focusLost = function(event) { self.transients.editing(false); diff --git a/grails-app/views/output/_imageDataTypeViewModelWithMetadataTemplate.gsp b/grails-app/views/output/_imageDataTypeViewModelWithMetadataTemplate.gsp index 4a07df4..095e9d8 100644 --- a/grails-app/views/output/_imageDataTypeViewModelWithMetadataTemplate.gsp +++ b/grails-app/views/output/_imageDataTypeViewModelWithMetadataTemplate.gsp @@ -5,7 +5,7 @@
  • -