0

I have developed some sample of Javascript that creates a JIRA tool tip (using the Tipsy AUI guide - https://docs.atlassian.com/aui/5.4.0/docs/tooltips.html) of the Ticket status, Summary, Assignee and fixVersion when you hover over an issue-link. Mainly to be used on the issue search page to prevent continuous Right Click -> Open in New Tab -> Check... which becomes extremely tedious, but can also be used for most other issue links.

It is meant to work on hover of a link however it doesn't always go to plan. When I first hover over ANY issue-link, it produces a tooltip 'undefined'. When I hover over ANY issue-link the second time, it then generates the accurate tooltip as expected. Copy it into your console and I'm pretty sure you will see the same behavior.

I'm not a Javascript Guru so it could be the mechanics of Javascript that I am not aware of so if anyone has any idea why this might be happening please let me know!

I have also packaged it into a JIRA plugin and see the same results.

AJS.toInit(function () {

var url,
issue_id,
offset,
x,
y,
jira_data,
html,
fixVersions,
assignee,
domain = document.location;

// build url whatever it might be
url = domain.protocol +'//'+ domain.hostname
if (domain.port !== "") {
    url += ':'+domain.port
}

AJS.$(".issue-link, td.issuelinks > a, #ghx-issues-in-epic-table > tbody > tr > td > a").tooltip({

    title: function () {

        // GETS THE ISSUE ID FROM THE HREF ELEMENT
        issue_id = (AJS.$(this).attr("href")).slice((AJS.$(this).attr("href")).lastIndexOf("/"), (AJS.$(this).attr("href")).length);
        // QUERIES JIRA API - ALREADY AUTHENTICATED WITH SESSION
        jira_data = AJS.$.getJSON(url+'/rest/api/2/issue' + issue_id, function (json) {

        })
            // AJAX COMPLETE FUNCTION
            jira_data.done(function (jira_data) {
            // CHECK FOR FixVersoin and Multiple FixVersions
            fixVersions = ""
            if (jira_data['fields']['fixVersions'] === undefined) {
                fixVersions = "None";
            } else {
            AJS.$.each(jira_data['fields']['fixVersions'], function(index, value) {
                fixVersions += value['name'] + " ";
            });};
            // CHECK FOR UNASSIGNED
            if (jira_data['fields']['assignee'] === undefined) {
                assignee = "Unassigned";
            } else {
                assignee = jira_data['fields']['assignee']['displayName'];
            };            
            // BUILD STRING OUTPUT
            html = "<span style='text-align:left'>";
            html += "<strong>Status: </strong>" + jira_data['fields']['status']['name'] + "</br>"
            html +="<strong>Assignee: </strong>" + assignee + "</br>";
            html += "<strong>Fix Version:  </strong>" +fixVersions+ "</br>";
            html += "<strong>Summary: </strong>" + jira_data['fields']['summary'];
            html += "</span>"

        });
        return html;
    }, live: true, gravity: AJS.$.fn.tipsy.autoWE, html:true, delayIn: 400, delayOut: 50});


        // REMOVE TITLE TAG TO PREVENT OBSTURCTION
AJS.$(".issue-link, td.issuelinks > a, #ghx-issues-in-epic-table > tbody > tr > td > a").removeAttr('title');    
AJS.$(".issue-link, td.issuelinks > a, #ghx-issues-in-epic-table > tbody > tr > td > a").parent().removeAttr('title');

});
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
cbarlow123
  • 217
  • 5
  • 18

2 Answers2

1

The problem (or at least "a" problem) is that you are not attaching the tooltip to the link until after you already receive the mouseover event. Once the tooltip is attached, the tooltip library then starts looking for mouseover events. It's unclear as to how well this will work if you are already hovering over the element when you add the tooltip, which makes me think it's related to the problem. In any case, you don't want to be reinitializing the tooltip handler every time the user mouses over a link.

You need to be using live-type events with tipsy. In that scenario, you don't attach your own mouseover handler and you let the tooltip library handle it. You want something along these lines:

Reading your question again, as well as your comments below, suggest that you want a different approach from what I first suggested. Since Tipsy doesn't seem to have native AJAX support, you need to go back to something closer to what you originally wrote.

The goal is to attach a live handler to each of the links, and to see if the link has already been annotated as a tipsy tooltip. If not, you want to perform an AJAX call to fetch the data. Once the AJAX call has returned, only then do you want to attach the tipsy tooltip.

This assumes that tipsy will handle the situation properly when you are already mousing over an element and you add a tooltip, and then cause it to render the tooltip immediately. From your original post, it sounded like this was happening because you were getting the 'undefined'.

In other words, something like this:

AJS.$(document).on("mouseover", ".issue-link, td.issuelinks > ...etc...")(function(e) {
    var $el = AJS.$(e.currentTarget);

    // Attach an attribute so that we only do this once per element:

    if ($el.attr('data-has-tipsy') === 'yes') {
         return; // already handled
    }

    $el.attr('data-has-tipsy', 'yes');

    // Now call your code to get the issue data here.
    // issue_id = ...
    // jira_data = ...

    jira_data.done(function (jira_data) {

        // calculate html here
        var html = 'Hello, Bob';

        // Finally, attach the tooltip within the done function!
        $el.tooltip({title: html, gravity: 'n', html: true, ...});
    }
}
Community
  • 1
  • 1
Scott Dudley
  • 3,256
  • 1
  • 18
  • 30
  • Thanks, I can now see where that part is wrong and have updated my code as you suggest. I now think I've got a timing issue where the var html isn't defined correctly before the tooltip is output and therefore displays undefined on first hover OR the previous tooltip from a link before currently hovered. Any tips on how to return the tooltip function only once getJSON query is complete and HTML is redefined? Thanks – cbarlow123 Feb 17 '15 at 10:19
  • Thanks for your time on this one. Helped a lot :) – cbarlow123 Feb 24 '15 at 10:01
1

I refactored your code and it works OK. The trick is to fill the tooltip inside the ajax callback function.

AJS.toInit(function () {

var url,
issue_id,
offset,
x,
y,
jira_data,
html,
fixVersions,
assignee,
domain = document.location;

// build url whatever it might be
url = domain.protocol +'//'+ domain.hostname
if (domain.port !== "") {
    url += ':'+domain.port
}

AJS.$(".issue-link, td.issuelinks > a, #ghx-issues-in-epic-table > tbody > tr > td > a").hover(function () {

         console.log('Entro')
        // GETS THE ISSUE ID FROM THE HREF ELEMENT
        issue_id = (AJS.$(this).attr("href")).slice((AJS.$(this).attr("href")).lastIndexOf("/"), (AJS.$(this).attr("href")).length);
        // QUERIES JIRA API - ALREADY AUTHENTICATED WITH SESSION

        jira_data = AJS.$.getJSON(url+'/rest/api/2/issue' + issue_id, function (json) {

        })
            // AJAX COMPLETE FUNCTION
            jira_data.done(function (jira_data) {
            // CHECK FOR UNASSIGNED
            if (jira_data['fields']['assignee'] === undefined) {
                assignee = "Unassigned";
            } else {
                assignee = jira_data['fields']['assignee']['displayName'];
            };            
            // BUILD STRING OUTPUT
            html = "<span style='text-align:left'>";
            html += "<strong>Summary: </strong>" + jira_data['fields']['summary'] + "</br>";
            html += "<strong>Status: </strong>" + jira_data['fields']['status']['name'] + "</br>";
            html +="<strong>Asignado: </strong>" + assignee + "</br>";
            html += "</span>";
            AJS.$(".issue-link, td.issuelinks > a, #ghx-issues-in-epic-table > tbody > tr > td > a").removeAttr('title');    
   AJS.$(".issue-link, td.issuelinks > a, #ghx-issues-in-epic-table > tbody > tr > td > a").parent().removeAttr('title');
            AJS.$(".issue-link, td.issuelinks > a, #ghx-issues-in-epic-table > tbody > tr > td > a").tooltip({title:function () {
        return html;
    },live: true, gravity: AJS.$.fn.tipsy.autoWE, html:true, delayIn: 400, delayOut: 50});
        });
});
});
  • @cbarlow123, I think the above will work OK in a page, but if I click on a link it shows wrong tooltip in the linked page's issue links... – Adolfo Casari Feb 24 '15 at 14:19