How to add web item via scriptrunner so that link opens in new tab?

Clemens Luebbers June 14, 2018

Hi,

with script fragments scriptrunner can add web items to the UI of Jira.

Unfortunately the URL provided in the link attribute opens in the same browser tab as the current Jira screen.

How can I define the web item, so that the URL opens in a new browser tab?

Regards

Clemens

1 answer

1 accepted

1 vote
Answer accepted
Aidan Derossett [Adaptavist]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
June 14, 2018

Hey there Clemens!

We meet again :D

Would you mind sending me a screenshot of your web item's configuration so that I can test out the best way to go about this?

Unfortunately there isn't any simple way to do it. You'll likely need some JavaScript that adds an attribute to the web item that specifies it to be opened in a separate tab. I can help set this up, but I'll need that screenshot for reference :)

Thanks!
Aidan

Clemens Luebbers June 14, 2018

Hi Aidan,

I add a screen shot here. Looking forward to your solution approach.

Regards

Clemens

2018-06-15 08_54_24-Script Fragments.png

Aidan Derossett [Adaptavist]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
June 19, 2018

Hey again,

I've been working on this for a good long minute and have gone with the simplest, although not the prettiest, solution I could. What you'll need to do is create a new JavaScript file in your Script Roots and add it to your instance with an "Install web resource" Script Fragment

To set up the web resource, create a JavaScript file containing code similar to this:

AJS.$(document).ready(function() {
let checkExist = setInterval(function () {
if (AJS.$('#key-of-your-web-item').length) {
let customEl = AJS.$("#key-of-your-web-item");
customEl.attr("target", "_blank");
clearInterval(checkExist);
}
}, 100); // check every 100ms
});

The above code is designed to check every 100ms that the element you are searching for (in this case your web item) exists. If your element never exists, the above code will continue checking, so you may want to add a counter to it that limits the time it will check.

With that JS file created and added to your Script Roots, you'll want to navigate to the Script Fragments page in your instance and, as mentioned above, select the "Install web resource." For the context, select "atl.general" and "atl.admin;" this will ensure that the JS is ran almost everywhere in your instance (you can add more contexts if you find it necessary). Add a Key of your choosing and type the name of your JavaScript file into the Resources box. 

After adding the resource, do a hard reload in your browser (ctrl-r or cmd-r) to ensure that browser cache is updated with the JS file you've added.

Now test it out and see what happens :D (hopefully good things).

As I mentioned above, the above JS code isn't the absolute best solution. I often recommend that people use the MutationObserver to find out when elements have been added instead of using an interval checking system. The MutationObserver is much more robust when done correctly, but can be slow with large DOMs like JIRA's if done incorrectly. Still, I would investigate using the MutationObserver instead, as it is usually much safer and prettier. :)

Here is an example of the MutationObserver being used to add text to the bottom of the JIRA Service Desk customer portal:

AJS.$(document).ready(function()
{
    //Get the target element that you'd like to observe    let target = document.querySelector('#footer');

    //Define the observer and the function that you want to be called when a mutation is observed    let observer = new WebKitMutationObserver(function(mutations)
    {
        //Define a function that makes your modification to the DOM        let makeModification = function()
        {
            //Stop observing the target element            observer.disconnect(); //Failing to do this will cause an infinite loop!
            //Get that element with JQuery and add your new div to it            let footerBody = AJS.$(".footer-body");
            footerBody.append("<div>text</div>");

            //Start observing the target element once again to watch for page changes            observer.observe(target, { attributes: true, childList: true, characterData: true, subtree: true });
        }

        //Define a function to recursively traverse childnodes until the desired node is found        let traverseChild = function(parent, parentIndex)
        {
            if(parent.childNodes.length > 0)
            {
                //Make the NodeList of childNodes and Array and use the "some" loop to traverse them                Array.from(parent.childNodes).some(function(childItem, childIndex)
                {
                    if(childItem.className == "footer-body")
                    {
                        makeModification();

                        //Return true when the element is found and modified                        //This will essentially break out of the "some" loop                        return true;
                    }
                    //Continue traversing if the desired node isn't found                    else if(childItem.childNodes.length > 0)
                    {
                        //Recursive call                        traverseChild(childItem, childIndex);
                    }
                });
            }
        }

        //Loop through each mutation that was observed        mutations.some(function(mutation)
        {
            //Use this log to check the mutation if you'd like to see its structure            //console.log(mutation, mutation.type);
            if(mutation.addedNodes.length > 0)
            {
                //Make the NodeList of childNodes and Array and use the "some" loop to traverse them                Array.from(mutation.addedNodes).some(function(item, index)
                {
                    if(item.className == "footer-body")
                    {
                        makeModification();
                        return true;
                    }
                    else
                    {
                        traverseChild(item, index);
                    }
                });
            }
        });
    });

    //Start observing the target element    observer.observe(target, { attributes: true, childList: true, characterData: true, subtree: true });
});

Hopefully that doesn't make things ten times more confusing haha.

Let me know if you have any questions or run into any issue! 
Aidan

Like jira guy likes this
Clemens Luebbers June 25, 2018

Hi Aidan,

thanks for the proposed solution. Unfortunately I do not have the necessary access to the "script root directory". I involve our Jira system admins into this, but they are currently quite busy and I do not know, when they will be able to provide the script in test environment.

Basicly I understand the approach and I assume that the solution will work. Therefore I mark the answer already as accepted.

Thanks and regards

Clemens

Aidan Derossett [Adaptavist]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
June 26, 2018

Well thank you very much for your trust in me! :D

If, for whatever reason, it goes South when you begin implementing the solution, let me know and I'll get on it. :)

Best,
Aidan

jira guy
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 7, 2020

Hello @Aidan Derossett [Adaptavist] 

This worked for me. Thank you! 

Now that it's been more than an year, do you think there is a better way to do this?

Like # people like this

Suggest an answer

Log in or Sign up to answer