","nodeType":"text"},{"data":{},"marks":[],"value":".","nodeType":"text"}],"nodeType":"paragraph"}],"nodeType":"document"},"links":{"entries":{"hyperlink":[],"block":[{"type":"ComponentCallout","sys":{"id":"36OwhiXPTJCFIF2Bp5fBmZ"},"heading":"Important supportability disclaimer!","appearance":"Warning/Caution (Yellow)","body":{"json":{"data":{},"content":[{"data":{},"content":[{"data":{},"marks":[],"value":"Customizations like these are ","nodeType":"text"},{"data":{},"marks":[{"type":"italic"}],"value":"not supported by Atlassian","nodeType":"text"},{"data":{},"marks":[],"value":" ","nodeType":"text"},{"data":{},"marks":[{"type":"italic"}],"value":"(","nodeType":"text"},{"data":{"uri":"https://confluence.atlassian.com/support/atlassian-support-offerings-193299636.html"},"content":[{"data":{},"marks":[{"type":"italic"}],"value":"in any support offer","nodeType":"text"}],"nodeType":"hyperlink"},{"data":{},"marks":[{"type":"italic"}],"value":")","nodeType":"text"},{"data":{},"marks":[],"value":" and should be used at the Jira Admins' own discretion and risk.","nodeType":"text"}],"nodeType":"paragraph"},{"data":{},"content":[{"data":{},"marks":[],"value":"You may find support from fellow users in the ","nodeType":"text"},{"data":{"uri":"https://community.atlassian.com/"},"content":[{"data":{},"marks":[{"type":"bold"}],"value":"Community","nodeType":"text"}],"nodeType":"hyperlink"},{"data":{},"marks":[],"value":" or through the services provided by ","nodeType":"text"},{"data":{"uri":"https://www.atlassian.com/partners/"},"content":[{"data":{},"marks":[{"type":"bold"}],"value":"Atlassian Solution Partners","nodeType":"text"}],"nodeType":"hyperlink"},{"data":{},"marks":[],"value":". This article only offers some ","nodeType":"text"},{"data":{},"marks":[{"type":"italic"}],"value":"best practices","nodeType":"text"},{"data":{},"marks":[],"value":" should you ","nodeType":"text"},{"data":{},"marks":[{"type":"italic"}],"value":"really need","nodeType":"text"},{"data":{},"marks":[],"value":" to implement something like this.","nodeType":"text"}],"nodeType":"paragraph"},{"data":{},"content":[{"data":{},"marks":[{"type":"bold"}],"value":"On version upgrades:","nodeType":"text"},{"data":{},"marks":[],"value":"\nAlso keep in mind there's no \"contract\" for the HTML elements in any of Atlassian products and ","nodeType":"text"},{"data":{},"marks":[{"type":"italic"}],"value":"they may change on any release without any public notice","nodeType":"text"},{"data":{},"marks":[],"value":" — unlike Jira's public Java API, REST API or AJS itself. This means you should include tests on your upgrade checklist to make sure the customizations you may have applied through custom Javascript ","nodeType":"text"},{"data":{},"marks":[{"type":"italic"}],"value":"still work in the new version you're upgrading to","nodeType":"text"},{"data":{},"marks":[],"value":".","nodeType":"text"}],"nodeType":"paragraph"}],"nodeType":"document"},"links":{"entries":{"hyperlink":[]}}}},{"type":"ComponentCallout","sys":{"id":"5qCquBkCdbZvItqOhJJ0PB"},"heading":"Troubleshooting","appearance":"Warning/Caution (Yellow)","body":{"json":{"data":{},"content":[{"data":{},"content":[{"data":{},"marks":[],"value":"Keep in mind a crucial step of troubleshooting is to ","nodeType":"text"},{"data":{},"marks":[{"type":"italic"}],"value":"disable or remove any JavaScript customization","nodeType":"text"},{"data":{},"marks":[],"value":" (even temporarily) and observe if the reported issue still persists. If you have implemented any such customizations, be advised Atlassian Support ","nodeType":"text"},{"data":{},"marks":[{"type":"italic"}],"value":"will ask you to remove or disable them","nodeType":"text"},{"data":{},"marks":[],"value":" to isolate any possible interference during troubleshooting — these customizations tamper with Jira in ways it was not designed to handle and may result in malfunctions on unrelated features or interfaces.","nodeType":"text"}],"nodeType":"paragraph"}],"nodeType":"document"},"links":{"entries":{"hyperlink":[]}}}},{"type":"ComponentCodeBlock","sys":{"id":"6NOo6yvztOw3HNmmGJ3l6s"},"code":"","language":"JavaScript"}]}}},"solution":{"json":{"nodeType":"document","data":{},"content":[{"nodeType":"embedded-entry-block","data":{"target":{"sys":{"id":"20xq11TQqh2A0ZSkZ6qgSi","type":"Link","linkType":"Entry"}}},"content":[]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"There are three places custom Javascript, CSS and HTML tags can be inserted in Jira:","marks":[],"data":{}}]},{"nodeType":"unordered-list","data":{},"content":[{"nodeType":"list-item","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"The Announcement Banner (see ","marks":[],"data":{}},{"nodeType":"hyperlink","data":{"uri":"https://confluence.atlassian.com/display/ADMINJIRASERVER/Configuring+an+announcement+banner"},"content":[{"nodeType":"text","value":"Configuring an announcement banner","marks":[],"data":{}}]},{"nodeType":"text","value":")","marks":[],"data":{}}]}]},{"nodeType":"list-item","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Project descriptions (work when the browsing the ","marks":[],"data":{}},{"nodeType":"text","value":"/PROJECT/summary ","marks":[{"type":"bold"}],"data":{}},{"nodeType":"text","value":"page)","marks":[],"data":{}}]}]},{"nodeType":"list-item","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Custom Field descriptions (work ","marks":[],"data":{}},{"nodeType":"text","value":"wherever ","marks":[{"type":"bold"}],"data":{}},{"nodeType":"text","value":"the field's present in the screen, like Issue view or edit screens, transition screens, bulk edit pages, etc)","marks":[],"data":{}}]}]}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"For the Project and Custom Field to work, these settings must be enabled in Jira's ","marks":[],"data":{}},{"nodeType":"text","value":"General Configuration","marks":[{"type":"italic"}],"data":{}},{"nodeType":"text","value":":","marks":[],"data":{}}]},{"nodeType":"embedded-entry-block","data":{"target":{"sys":{"id":"AapPl7Rfu1grRW7lsDO71","type":"Link","linkType":"Entry"}}},"content":[]},{"nodeType":"heading-3","data":{},"content":[{"nodeType":"text","value":"Best practice 1. Make use of comments","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Both for intelligibility and troubleshooting, make ","marks":[],"data":{}},{"nodeType":"text","value":"extensive use","marks":[{"type":"bold"}],"data":{}},{"nodeType":"text","value":" of Comments.","marks":[],"data":{}}]},{"nodeType":"unordered-list","data":{},"content":[{"nodeType":"list-item","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"HTML comments: ","marks":[],"data":{}},{"nodeType":"text","value":"","marks":[{"type":"code"}],"data":{}}]}]},{"nodeType":"list-item","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Javascript comments: ","marks":[],"data":{}},{"nodeType":"text","value":"// comment goes here","marks":[{"type":"code"}],"data":{}}]}]}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Comments allow for easier troubleshooting, given no expertise on Javascript is needed to suspect a code snippet's doing something to the UI.","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"\"","marks":[],"data":{}},{"nodeType":"text","value":"","marks":[{"type":"code"}],"data":{}},{"nodeType":"text","value":"\" is easier to understand than \"","marks":[],"data":{}},{"nodeType":"text","value":"document.getElementById(\"#sla-web-panel-react\").style.display = \"none\";","marks":[{"type":"code"}],"data":{}},{"nodeType":"text","value":"\", for example.","marks":[],"data":{}}]},{"nodeType":"heading-3","data":{},"content":[{"nodeType":"text","value":"Best practice 2. Make use of console log","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"When changing anything with a custom Javascript code, use the Browser native \"console.log()\" functions (","marks":[],"data":{}},{"nodeType":"text","value":"info()","marks":[{"type":"code"}],"data":{}},{"nodeType":"text","value":", ","marks":[],"data":{}},{"nodeType":"text","value":"warn()","marks":[{"type":"code"}],"data":{}},{"nodeType":"text","value":" and ","marks":[],"data":{}},{"nodeType":"text","value":"error()","marks":[{"type":"code"}],"data":{}},{"nodeType":"text","value":").","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"This prints a message in the Browser's console and can be visible through the Browser's \"Developer Tools\".","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"If you can standardize the logs to make it easier to troubleshoot and track down what may be interfering with Jira's default behavior, all the better — but always log!","marks":[],"data":{}}]},{"nodeType":"heading-3","data":{},"content":[{"nodeType":"text","value":"Best practice 3. Narrow the scope of the change as much as possible","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Unless you're working with some specific scenario of a global-system-wide change, it's good practice to limit the scope of the change as much as possible.","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"This can be achieved through — but not limited to:","marks":[],"data":{}}]},{"nodeType":"unordered-list","data":{},"content":[{"nodeType":"list-item","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Checking the current page URL","marks":[],"data":{}}]}]},{"nodeType":"list-item","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Checking if a certain element exists in the current page","marks":[],"data":{}}]}]}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"This will help you mitigate the risk of changing (and potentially breaking) a screen you didn't consider in your tests in a pre-Prod environment.","marks":[],"data":{}}]},{"nodeType":"heading-3","data":{},"content":[{"nodeType":"text","value":"Best practice 4. Try and Catch errors","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Even with a simple and cautiously-coded script, it's a good practice to surround the custom code with try/catch blocks. This allows handling (or silencing) errors that may arise from unexpected situations (like trying to hide a button that doesn't even exist in the screen yet) and potentially ","marks":[],"data":{}},{"nodeType":"text","value":"compromise the rest of the script","marks":[{"type":"italic"}],"data":{}},{"nodeType":"text","value":".","marks":[],"data":{}}]},{"nodeType":"heading-4","data":{},"content":[{"nodeType":"text","value":"Success and Error logging example","marks":[{"type":"bold"}],"data":{}}]},{"nodeType":"embedded-entry-block","data":{"target":{"sys":{"id":"1JdU0IqsljKdnBJPTnpiS4","type":"Link","linkType":"Entry"}}},"content":[]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Depending on what you're trying to achieve, it may not make sense to log the error. The example snippet below \"silences\" the error and prevents the error from stopping the rest of the script:","marks":[],"data":{}}]},{"nodeType":"heading-4","data":{},"content":[{"nodeType":"text","value":"No error logging","marks":[],"data":{}}]},{"nodeType":"embedded-entry-block","data":{"target":{"sys":{"id":"3GPgUozTsUQMldiqEpGlEe","type":"Link","linkType":"Entry"}}},"content":[]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"As these are customization on top of Jira, you may choose ","marks":[],"data":{}},{"nodeType":"text","value":"not to use","marks":[{"type":"italic"}],"data":{}},{"nodeType":"text","value":" console.warn() or console.error(), leaving those methods for the \"official\" JavaScript code from Jira and apps/plugins. No harm in using them, though, as long as you prefix your custom messages or somehow write them in a way to facilitate troubleshooting.","marks":[],"data":{}}]},{"nodeType":"heading-3","data":{},"content":[{"nodeType":"text","value":"5. Waiting for elements to render (optional, use with caution)","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Jira (and most web applications today) renders most of it's UI elements asynchronously, meaning the user's not held at a blank page until everything is fully loaded. This results in UI elements being rendered by the Browser at not always the same order, and each element potentially taking a different time to load each time.","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"If you need to interact with the UI elements, you may need to wait for them to be fully loaded — or at least defined in the document already — to find them and edit them.","marks":[],"data":{}}]},{"nodeType":"embedded-entry-block","data":{"target":{"sys":{"id":"32vAOeBUptSzSVekoOFzK4","type":"Link","linkType":"Entry"}}},"content":[]},{"nodeType":"heading-4","data":{},"content":[{"nodeType":"text","value":"5.1. setTimeout (try once)","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"The setTimeout Javascript function waits for a number of milliseconds and then executes what's inside the function:","marks":[],"data":{}}]},{"nodeType":"embedded-entry-block","data":{"target":{"sys":{"id":"2OB6XPCA4Ib4pwspTsuGra","type":"Link","linkType":"Entry"}}},"content":[]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"This waits for 1000ms (1 second) ","marks":[],"data":{}},{"nodeType":"text","value":"then","marks":[{"type":"bold"}],"data":{}},{"nodeType":"text","value":" tries to hide a button (","marks":[],"data":{}},{"nodeType":"text","value":".style.display = \"none\"","marks":[{"type":"italic"}],"data":{}},{"nodeType":"text","value":") named \"With unresolved tickets\" in the page if it matches \"/secure/insight/search\".","marks":[],"data":{}}]},{"nodeType":"heading-4","data":{},"content":[{"nodeType":"text","value":"5.2. setInterval (keep trying)","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"The setInterval is very handy but ","marks":[],"data":{}},{"nodeType":"text","value":"also much more dangerous","marks":[{"type":"bold"}],"data":{}},{"nodeType":"text","value":" than the setTimeout: it executes the function code again and again at every interval in milliseconds.","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"This is useful if you want to \"retry\" fetching the element in case it's not there yet, but ","marks":[],"data":{}},{"nodeType":"text","value":"can also lead to a continuous loop","marks":[{"type":"bold"}],"data":{}},{"nodeType":"text","value":" if not handled properly: the \"setInterval\" ","marks":[],"data":{}},{"nodeType":"text","value":"runs forever","marks":[{"type":"bold"}],"data":{}},{"nodeType":"text","value":" in the Browser until it's explicitly stopped (","marks":[],"data":{}},{"nodeType":"text","value":"clearInterval(myInterval)","marks":[{"type":"italic"}],"data":{}},{"nodeType":"text","value":") or an uncaught error happens or the user browses another page.","marks":[],"data":{}}]},{"nodeType":"embedded-entry-block","data":{"target":{"sys":{"id":"PLBuUVtckk1DtsUkfwWmg","type":"Link","linkType":"Entry"}}},"content":[]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"This example script tries to locate the \"With unresolved tickets\" button on the \"/secure/insight/search\" page ","marks":[],"data":{}},{"nodeType":"text","value":"every 500ms","marks":[{"type":"bold"}],"data":{}},{"nodeType":"text","value":" and removes it when it finds it. It also ","marks":[],"data":{}},{"nodeType":"text","value":"drops out after 10 attempts","marks":[{"type":"bold"}],"data":{}},{"nodeType":"text","value":" (to prevent an infinite loop in case somehow the button never shows up or had it's named changed).","marks":[],"data":{}}]},{"nodeType":"embedded-entry-block","data":{"target":{"sys":{"id":"1QDgAjoNvH40IGP05iA7kM","type":"Link","linkType":"Entry"}}},"content":[]},{"nodeType":"heading-3","data":{},"content":[{"nodeType":"text","value":"Examples","marks":[],"data":{}}]},{"nodeType":"heading-4","data":{},"content":[{"nodeType":"text","value":"Example 1. Removing the ","marks":[],"data":{}},{"nodeType":"text","value":"+ Create issue","marks":[{"type":"italic"}],"data":{}},{"nodeType":"text","value":" button from the ","marks":[],"data":{}},{"nodeType":"text","value":"Project Issues","marks":[{"type":"italic"}],"data":{}},{"nodeType":"text","value":" page","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"In this example we make use of a custom Javascript in the Announcement Banner:","marks":[],"data":{}}]},{"nodeType":"embedded-entry-block","data":{"target":{"sys":{"id":"4fyAVAFZhXDW6PVAmQsHcp","type":"Link","linkType":"Entry"}}},"content":[]},{"nodeType":"embedded-entry-block","data":{"target":{"sys":{"id":"1tF9I8qGz97LNSeo3RtlRq","type":"Link","linkType":"Entry"}}},"content":[]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Best practises checklist","marks":[{"type":"bold"}],"data":{}}]},{"nodeType":"table","data":{},"content":[{"nodeType":"table-row","data":{},"content":[{"nodeType":"table-cell","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Comments","marks":[],"data":{}}]}]},{"nodeType":"table-cell","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Yes","marks":[],"data":{}}]}]}]},{"nodeType":"table-row","data":{},"content":[{"nodeType":"table-cell","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Console Log","marks":[],"data":{}}]}]},{"nodeType":"table-cell","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Yes","marks":[],"data":{}}]}]}]},{"nodeType":"table-row","data":{},"content":[{"nodeType":"table-cell","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Limiting scope to the \"JIRA/issues\" page (JIRA is the Project's Key in the example)","marks":[],"data":{}}]}]},{"nodeType":"table-cell","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Yes","marks":[],"data":{}}]}]}]},{"nodeType":"table-row","data":{},"content":[{"nodeType":"table-cell","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Try / Catch","marks":[],"data":{}}]}]},{"nodeType":"table-cell","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Yes","marks":[],"data":{}}]}]}]}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Outcomes","marks":[{"type":"bold"}],"data":{}}]},{"nodeType":"embedded-entry-block","data":{"target":{"sys":{"id":"1D46DlQ0AzYY6rJ8dEU3Bt","type":"Link","linkType":"Entry"}}},"content":[]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"The ","marks":[],"data":{}},{"nodeType":"text","value":"+ Create issues","marks":[{"type":"italic"}],"data":{}},{"nodeType":"text","value":" button's gone for project JIRA.","marks":[],"data":{}}]},{"nodeType":"embedded-entry-block","data":{"target":{"sys":{"id":"NzMu3zOGCErvoLOKGVmBr","type":"Link","linkType":"Entry"}}},"content":[]},{"nodeType":"heading-4","data":{},"content":[{"nodeType":"text","value":"Example 2. Hiding a custom field on the Bulk Edit screen","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"In this example we use a custom field's Description attribute to inject the Javascript:","marks":[],"data":{}}]},{"nodeType":"embedded-entry-block","data":{"target":{"sys":{"id":"4qdanKoOjgIOZfG6VTKbNP","type":"Link","linkType":"Entry"}}},"content":[]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"In this example, the field's id is 10300.","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Best practises checklist","marks":[{"type":"bold"}],"data":{}}]},{"nodeType":"table","data":{},"content":[{"nodeType":"table-row","data":{},"content":[{"nodeType":"table-cell","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Comments","marks":[],"data":{}}]}]},{"nodeType":"table-cell","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Yes","marks":[],"data":{}}]}]}]},{"nodeType":"table-row","data":{},"content":[{"nodeType":"table-cell","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Console Log","marks":[],"data":{}}]}]},{"nodeType":"table-cell","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Yes","marks":[],"data":{}}]}]}]},{"nodeType":"table-row","data":{},"content":[{"nodeType":"table-cell","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Limiting scope to the \"JIRA/issues\" page (JIRA is the Project's Key in the example)","marks":[],"data":{}}]}]},{"nodeType":"table-cell","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Yes","marks":[],"data":{}}]}]}]},{"nodeType":"table-row","data":{},"content":[{"nodeType":"table-cell","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Try / Catch","marks":[],"data":{}}]}]},{"nodeType":"table-cell","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Yes","marks":[],"data":{}}]}]}]}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Outcomes","marks":[{"type":"bold"}],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Before the script the \"Order Id\" is present:","marks":[],"data":{}}]},{"nodeType":"embedded-entry-block","data":{"target":{"sys":{"id":"4VRUjFFXLtTpOj6f5RHuDE","type":"Link","linkType":"Entry"}}},"content":[]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"After the script the \"Order Id\" is gone and the console log helps identify a custom behavior:","marks":[],"data":{}}]},{"nodeType":"embedded-entry-block","data":{"target":{"sys":{"id":"392ABUaZjBhPHLRj1LXDxL","type":"Link","linkType":"Entry"}}},"content":[]},{"nodeType":"heading-3","data":{},"content":[{"nodeType":"text","value":"Example 3. Hiding the Clone Issue links","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"It's not uncommon for Admins to want to restrict the Clone Issue functionality. Jira unfortunately doesn't has this feature — yet:","marks":[],"data":{}}]},{"nodeType":"unordered-list","data":{},"content":[{"nodeType":"list-item","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"","marks":[],"data":{}},{"nodeType":"hyperlink","data":{"uri":"https://confluence.atlassian.com/display/JIRAKB/How+to+restrict+issue+cloning+in+Jira"},"content":[{"nodeType":"text","value":"How to restrict issue cloning in Jira","marks":[],"data":{}}]},{"nodeType":"text","value":"","marks":[],"data":{}}]}]}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Admins have been working with the Workflow Permission \"jira.permission.createclone\" but that's a coincidence it works — it actually removes the Create Permission, but Jira still allows the Issue creation through some UI paths ","marks":[],"data":{}},{"nodeType":"text","value":"(though it shouldn't, actually)","marks":[{"type":"italic"}],"data":{}},{"nodeType":"text","value":".","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"The example Javascript below adds a \"display: none !important;\" CSS rule to the \"issueaction-clone-issue\" class:","marks":[],"data":{}}]},{"nodeType":"embedded-entry-block","data":{"target":{"sys":{"id":"17uJLNZgYeVpmtJqAp5MbE","type":"Link","linkType":"Entry"}}},"content":[]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Best practises checklist","marks":[{"type":"bold"}],"data":{}}]},{"nodeType":"table","data":{},"content":[{"nodeType":"table-row","data":{},"content":[{"nodeType":"table-cell","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Comments","marks":[],"data":{}}]}]},{"nodeType":"table-cell","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Yes","marks":[],"data":{}}]}]}]},{"nodeType":"table-row","data":{},"content":[{"nodeType":"table-cell","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Console Log","marks":[],"data":{}}]}]},{"nodeType":"table-cell","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Yes","marks":[],"data":{}}]}]}]},{"nodeType":"table-row","data":{},"content":[{"nodeType":"table-cell","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Limiting scope to the \"JIRA/issues\" page (JIRA is the Project's Key in the example)","marks":[],"data":{}}]}]},{"nodeType":"table-cell","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"NO","marks":[],"data":{}}]}]}]},{"nodeType":"table-row","data":{},"content":[{"nodeType":"table-cell","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Try / Catch","marks":[],"data":{}}]}]},{"nodeType":"table-cell","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Yes","marks":[],"data":{}}]}]}]}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"As a bypass mechanism, it only overrides the CSS Stylesheet if the text \"my-company-custom-param-to-allow-issue-clone=true\" is not present in the URL. So if the Admin needs to actually bypass this and be able to clone the issue through the URL, just append this parameter to the URL and press enter on the Browser:","marks":[],"data":{}}]},{"nodeType":"embedded-entry-block","data":{"target":{"sys":{"id":"5AdTrSQu8w3hRGiav7hOcK","type":"Link","linkType":"Entry"}}},"content":[]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Or append other URLs with the ampersand if there are already other parameters:","marks":[],"data":{}}]},{"nodeType":"embedded-entry-block","data":{"target":{"sys":{"id":"4UbkOGdFbM4Pxwew40r6lp","type":"Link","linkType":"Entry"}}},"content":[]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"You can change this to whatever other bypass text you want or remove this bypass mechanism entirely.","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"REST API or direct Clone URL access will still work, though. This example only hides the elements with the \"issueaction-clone-issue\" class in the UI — it doesn't block the Clone feature in the server-side.","marks":[],"data":{}}]},{"nodeType":"heading-3","data":{},"content":[{"nodeType":"text","value":"Example 4. Hiding the Announcement Banner completely","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"When adding anything to the Announcement Banner, even if it's not visible, you'll notice a narrow gray stripe where the banner would be located.","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"To get rid of it completely, simply add this snippet at the beginning or the end of the Banner — careful not to nest it inside any other script, html or style tag:","marks":[],"data":{}}]},{"nodeType":"embedded-entry-block","data":{"target":{"sys":{"id":"4kvWNEyBZkN8YISRwqrk2X","type":"Link","linkType":"Entry"}}},"content":[]},{"nodeType":"heading-3","data":{},"content":[{"nodeType":"text","value":"Example 5. Adding a new stylesheet conditionally","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Hiding elements through stylesheet (CSS) is generally better than through Javascript (JS) as the style's calculated by the Browser when creating the element, whereas in Javascript it'd fail if the element's not rendered yet or may delay in some cases until the script's loaded and executed (the element may show up and disappear right next).","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"This code snippet is an example of how to append a stylesheet dynamically depending on some conditions — in this example, if \"/PROJKEY-\" is present in the URL:","marks":[],"data":{}}]},{"nodeType":"embedded-entry-block","data":{"target":{"sys":{"id":"4V6cuAbKZ3xpCWaI834w9r","type":"Link","linkType":"Entry"}}},"content":[]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"When adding new elements in the page it's also very important to ","marks":[],"data":{}},{"nodeType":"text","value":"give it suggestive Ids","marks":[{"type":"bold"}],"data":{}},{"nodeType":"text","value":" to make it easier to troubleshoot.","marks":[],"data":{}}]},{"nodeType":"heading-3","data":{},"content":[{"nodeType":"text","value":"Reverting changes","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"If things have gone wrong and with an Admin account you're not able to revert he changes trough the UI, you'll need to revert them directly on the database.","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"To clear out the Announcement Banner you can run this DB update and restart Jira:","marks":[],"data":{}}]},{"nodeType":"embedded-entry-block","data":{"target":{"sys":{"id":"1Y6icz1dmiS5wCoTvbHZyo","type":"Link","linkType":"Entry"}}},"content":[]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Refer to the article on ","marks":[],"data":{}},{"nodeType":"hyperlink","data":{"uri":"https://confluence.atlassian.com/pages/viewpage.action?pageId=1101934366"},"content":[{"nodeType":"text","value":"How to identify fields with custom Javascript in their description in Jira Data Center / Server","marks":[],"data":{}}]},{"nodeType":"text","value":" to identify in which tables the custom Javascript is present and update the respective ","marks":[],"data":{}},{"nodeType":"text","value":"records","marks":[{"type":"bold"}],"data":{}},{"nodeType":"text","value":" to remove the script. ","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"After updating the specific ","marks":[],"data":{}},{"nodeType":"text","value":"records","marks":[{"type":"bold"}],"data":{}},{"nodeType":"text","value":", a Jira restart is required.","marks":[],"data":{}}]}]},"links":{"entries":{"hyperlink":[],"block":[{"type":"ComponentCallout","sys":{"id":"20xq11TQqh2A0ZSkZ6qgSi"},"heading":"Always test in pre-Prod!","appearance":"Information (Blue)","body":{"json":{"nodeType":"document","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Never","marks":[{"type":"bold"}],"data":{}},{"nodeType":"text","value":" apply changes in Production without first applying them in a ","marks":[],"data":{}},{"nodeType":"text","value":"pre-Prod","marks":[{"type":"bold"}],"data":{}},{"nodeType":"text","value":" environment! (Dev, Stage, UAT, pre-Prod, etc)","marks":[],"data":{}}]},{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Even a silly copy & paste mistake or typo can ","marks":[],"data":{}},{"nodeType":"text","value":"render Jira unavailable even for Admins","marks":[{"type":"italic"}],"data":{}},{"nodeType":"text","value":" and require a database update and Jira restart in worst cases (see the ","marks":[],"data":{}},{"nodeType":"text","value":"Reverting changes","marks":[{"type":"bold"}],"data":{}},{"nodeType":"text","value":" section).","marks":[],"data":{}}]}]},"links":{"entries":{"hyperlink":[]}}}},{"type":"ComponentKbImage","sys":{"id":"AapPl7Rfu1grRW7lsDO71"},"altText":"Enable HTML in project description and field descriptions","image":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/6LoG06N4bRrOpTDa8heDBz/9b26398778e12a7e24295a498f6c1793/image2022-11-7_18-9-5.png"}},{"type":"ComponentCodeBlock","sys":{"id":"1JdU0IqsljKdnBJPTnpiS4"},"code":"\n","language":"JavaScript"},{"type":"ComponentCodeBlock","sys":{"id":"3GPgUozTsUQMldiqEpGlEe"},"code":"","language":"JavaScript"},{"type":"ComponentCallout","sys":{"id":"32vAOeBUptSzSVekoOFzK4"},"heading":null,"appearance":"Warning/Caution (Yellow)","body":{"json":{"nodeType":"document","data":{},"content":[{"nodeType":"paragraph","data":{},"content":[{"nodeType":"text","value":"Please note that these Javascript functions are examples only and should be used with caution. They add contention to Browser Threads (they hang for some time, waiting for the specified amount of time to pass).","marks":[],"data":{}}]}]},"links":{"entries":{"hyperlink":[]}}}},{"type":"ComponentCodeBlock","sys":{"id":"2OB6XPCA4Ib4pwspTsuGra"},"code":"\n\n","language":"JavaScript"},{"type":"ComponentCodeBlock","sys":{"id":"PLBuUVtckk1DtsUkfwWmg"},"code":"\n","language":"JavaScript"},{"type":"ComponentCallout","sys":{"id":"1QDgAjoNvH40IGP05iA7kM"},"heading":null,"appearance":"Warning/Caution (Yellow)","body":{"json":{"data":{},"content":[{"data":{},"content":[{"data":{},"marks":[],"value":"Remember that there's no \"contract\" on UI elements and elements names, labels, ids and even layout/tree may change from one version to another.","nodeType":"text"}],"nodeType":"paragraph"},{"data":{},"content":[{"data":{},"marks":[],"value":"It's best to implement these failsafe mechanisms (like a counter to stop the interval execution) at your scripts just in case.","nodeType":"text"}],"nodeType":"paragraph"}],"nodeType":"document"},"links":{"entries":{"hyperlink":[]}}}},{"type":"ComponentKbImage","sys":{"id":"4fyAVAFZhXDW6PVAmQsHcp"},"altText":"Announcement Banner containing code block","image":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/6p3F9spd9h3GL9shNkXdml/bf8f7872f80cdeab1b1f5907efc53bf3/image-2023-3-8_16-30-58.png"}},{"type":"ComponentCodeBlock","sys":{"id":"1tF9I8qGz97LNSeo3RtlRq"},"code":"\n","language":"JavaScript"},{"type":"ComponentKbImage","sys":{"id":"1D46DlQ0AzYY6rJ8dEU3Bt"},"altText":"Outcomes announcement banner: create issue button no longer visible","image":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/2hRhiQ74WJlz437VrltR5X/0d3ee00dc3264c946bbd898958927780/image2022-11-7_11-44-10.png"}},{"type":"ComponentKbImage","sys":{"id":"NzMu3zOGCErvoLOKGVmBr"},"altText":"console log excerpt suggesting this is due to a customization interference","image":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/2PQAwXS5NELsCfurWP9KF/663017fffab36f9a6392f787399eb28f/image2022-11-7_11-49-45.png"}},{"type":"ComponentCodeBlock","sys":{"id":"4qdanKoOjgIOZfG6VTKbNP"},"code":"\n","language":"JavaScript"},{"type":"ComponentKbImage","sys":{"id":"4VRUjFFXLtTpOj6f5RHuDE"},"altText":"Order ID present on Bulk Edit screen","image":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/2Kq4xAQv70ZMIzbwkrMRT7/39c24374c0df2d6df8c22ec492fe6962/image2022-11-8_10-59-28.png"}},{"type":"ComponentKbImage","sys":{"id":"392ABUaZjBhPHLRj1LXDxL"},"altText":"Order ID no longer present on bulk edit screen and console log identifying that this is custom behaviour","image":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/3OmlmysOP1qhGAhuFqY36d/832b975b33d94da45d4cef2b962eefcf/image2022-11-8_12-29-37.png"}},{"type":"ComponentCodeBlock","sys":{"id":"17uJLNZgYeVpmtJqAp5MbE"},"code":"\n\n","language":"JavaScript"},{"type":"ComponentCodeBlock","sys":{"id":"5AdTrSQu8w3hRGiav7hOcK"},"code":"https://jira-base-url/browse/ISSUE-12345?my-company-custom-param-to-allow-issue-clone=true","language":"Plain text"},{"type":"ComponentCodeBlock","sys":{"id":"4UbkOGdFbM4Pxwew40r6lp"},"code":"&my-company-custom-param-to-allow-issue-clone=true","language":"Plain text"},{"type":"ComponentCodeBlock","sys":{"id":"4kvWNEyBZkN8YISRwqrk2X"},"code":"\n","language":"XML"},{"type":"ComponentCodeBlock","sys":{"id":"4V6cuAbKZ3xpCWaI834w9r"},"code":"\n","language":"JavaScript"},{"type":"ComponentCodeBlock","sys":{"id":"1Y6icz1dmiS5wCoTvbHZyo"},"code":"update propertytext set propertyvalue = '' where id = (select id from propertyentry where property_key='jira.alertheader');","language":"SQL"}]}}}},"tableOfContents":[{"id":"summary","title":"Summary"},{"id":"solution","title":"Solution"}],"appVersions":[],"productVersions":[{"sys":{"id":"75MNIiyv9EahECDNxlGixU"},"versionName":"Jira Software Data Center","versionNumber":null,"versionModifier":"None","platform":"Data Center","product":{"productName":"Jira Software"}},{"sys":{"id":"i0zwMmzelZa1nJDPH2vaz"},"versionName":"Jira Service Management Data Center","versionNumber":null,"versionModifier":"None","platform":"Data Center","product":{"productName":"Jira Service Management"}},{"sys":{"id":"40euYcvjhePMIkuukI2PNg"},"versionName":"Jira Core Data Center","versionNumber":null,"versionModifier":"None","platform":"Data Center","product":{"productName":"Jira Core"}}],"publishTo":["support.atlassian.com (SAC)"],"metadata":{"id":"dyFjaGJmZa6WQ84OA84SU","type":"sitewideMetadata","publisher":"Atlassian","language":"en-US","license":"Except where otherwise noted, content in this space is licensed under a Creative Commons Attribution 2.5 Australia License.","logo":"https://images.ctfassets.net/zsv3d0ugroxu/4usk6GCfTOCSKCwCQykYIu/34d7ed0904d9a0274fb906f86f51e1e1/Atlassian-vertical-blue-onecolor-rgb.svg","brand":"Atlassian","legalName":"Atlassian Corporation Plc","owns":"Jira Software,Jira Service Management,Jira Work Management,Jira Align,Confluence,Hipchat,Bitbucket,Bamboo,Crucible,Crowd,Sourcetree,OpsGenie,Statuspage,Trello,Halp,Mindville","siteName":"Atlassian Support"},"header":{"id":"3wZXajO6t2W8mUgA486Wai","type":"globalHeader","cloudProducts":[{"sys":{"id":"3yydXRuQ88gGCKOyYsAGaU"},"version":"Not Applicable","deployment":"Cloud","productBlurb":"Project and issue tracking","url":"jira-software-cloud","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/3tdm6nuuJrPlizPLgkWqZ5/d0a7942804abf2f8f6737197be1fc7f4/logo-light_Jira_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"jirasoftware"},"productName":"Jira Software"},"deploymentUrls":{"cloud":"/jira-software-cloud/"},"id":"3yydXRuQ88gGCKOyYsAGaU"},{"sys":{"id":"1gXBh54v1sayA6w8yowM8u"},"version":"Not Applicable","deployment":"Cloud","productBlurb":"Service management and customer support","url":"jira-service-management-cloud","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/5DppKv8q5q206zQzIRDKQq/f31b8874021ee7d6dd54389f902b1421/logo-light_Jira-Service-Management_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"jiraservicedesk"},"productName":"Jira Service Management"},"deploymentUrls":{"cloud":"/jira-service-management-cloud/"},"id":"1gXBh54v1sayA6w8yowM8u"},{"sys":{"id":"4z1mIelYHYwE6ugCuqEg0y"},"version":"Not Applicable","deployment":"Cloud","productBlurb":"Document collaboration","url":"confluence-cloud","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/5VucmXIhBRYyBXA9ygFJ3Y/5082d769a81934af185dcf109b29f628/logo-light_Confluence_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"confluence"},"productName":"Confluence"},"deploymentUrls":{"cloud":"/confluence-cloud/"},"id":"4z1mIelYHYwE6ugCuqEg0y"},{"sys":{"id":"UhZk1Nq8UMkcuUsy6sI4C"},"version":"Not Applicable","deployment":"Cloud","productBlurb":"Git code management","url":"bitbucket-cloud","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/1g4197x84jic8a1P3b3IGT/1a752272b12824d3a3df4bc1e7dd2c53/logo-light_Bitbucket_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"bitbucket"},"productName":"Bitbucket"},"deploymentUrls":{"cloud":"/bitbucket-cloud/"},"id":"UhZk1Nq8UMkcuUsy6sI4C"},{"sys":{"id":"7aO3e0I67vVoQJXGXm2pjr"},"version":"Not Applicable","deployment":"Cloud","productBlurb":"Work more collaboratively and get more done","url":"trello","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/1j6nvsJ8txgcxgy3Vmk4aO/e3b6d56c299ae744c2f4b8109cf1a482/logo-light_Trello_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"3Pgvsvt3uylBV25qaoU8ui"},"productName":"Trello"},"deploymentUrls":{"cloud":"/trello/"},"id":"7aO3e0I67vVoQJXGXm2pjr"},{"sys":{"id":"OBPfqfSG24X1AQ74Oc9ob"},"version":"Not Applicable","deployment":"Cloud","productBlurb":"Rovo is helps your team find knowledge, learn from it and create action—through the power of AI.","url":"rovo","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/7GLXCkFtxe0MUSfmTNdrPL/1a042c58b850d16c6eb3339dc4532c0d/logo-light_Rovo_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"1wFXee3vB0OUMBK6dJ5ncZ"},"productName":"Rovo"},"deploymentUrls":{"cloud":"/rovo/"},"id":"OBPfqfSG24X1AQ74Oc9ob"},{"sys":{"id":"74UlBDi4bbCZFw5rNyxpjj"},"version":"Not Applicable","deployment":"Cloud","productBlurb":"Loom is the video communication platform for async work.","url":"loom","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/1WJwDTYFClxfJJUOrhlevh/ea49afae7832f279d4769d04b004217e/Loom_blue.svg"},"productNameReference":{"sys":{"id":"6TYrk1y0pRJilwiT69uMgM"},"productName":"Loom"},"deploymentUrls":{"cloud":"/loom/"},"id":"74UlBDi4bbCZFw5rNyxpjj"},{"sys":{"id":"1IrNp77C6KQk9FZ7y8V1f2"},"version":"Not Applicable","deployment":"Cloud","productBlurb":"Mission control for your distributed architecture","url":"compass","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/3UAMHJdzO6e6NhYGD07Ugg/bf460d12761faed44a807bf7eb8a8c45/logo-light_Compass_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"1ndBBFKwZNMEzDmJzMd6Wo"},"productName":"Compass"},"deploymentUrls":{"cloud":"/compass/"},"id":"1IrNp77C6KQk9FZ7y8V1f2"},{"sys":{"id":"10SbTAPoOxxVcyZMNH20Kf"},"version":"Not Applicable","deployment":"Cloud","productBlurb":"Your team’s home for product discovery","url":"jira-product-discovery","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/UoGuPi0Q5W6nxm8P76Zun/7ff53cd380f66b6fe1dc27b8a9fd645a/logo-light_Jira-Product-Discovery_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"22bKMdHH2crmVtvOW4gfGg"},"productName":"Jira Product Discovery"},"deploymentUrls":{"cloud":"/jira-product-discovery/"},"id":"10SbTAPoOxxVcyZMNH20Kf"},{"sys":{"id":"2QnaIiOyGAeI4aWeg4y8ms"},"version":"Not Applicable","deployment":"Cloud","productBlurb":"Manage any business project","url":"jira-work-management","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/3vfg7u3DhUSKK0pXuJ88hK/5619c55b3e05a43bee3af77f4e293824/JWM.svg"},"productNameReference":{"sys":{"id":"7kTpVjbv8bjQ67yVJiWQyh"},"productName":"Jira Work Management"},"deploymentUrls":{"cloud":"/jira-work-management/"},"id":"2QnaIiOyGAeI4aWeg4y8ms"},{"sys":{"id":"53Ep5GwhITPflhp1tT1Ale"},"version":"Not Applicable","deployment":"Cloud","productBlurb":"Unlock the agility of your enterprise","url":"jira-align","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/6eS3KCOum0OuJfHEBmhIy6/32785683c67d135aae596e6e66ec9646/logo-light_Jira-Align_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"jiraalign"},"productName":"Jira Align"},"deploymentUrls":{"cloud":"/jira-align/"},"id":"53Ep5GwhITPflhp1tT1Ale"},{"sys":{"id":"5t76PH9Mw7zagigkXzUa8H"},"version":"Not Applicable","deployment":"Cloud","productBlurb":"Modern incident management","url":"opsgenie","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/3Mgc7MIYvTJ3EQ3ghceiVk/76c6a20b69802c434b973cb8098d490a/logo-light_Opsgenie_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"opsgenie"},"productName":"Opsgenie"},"deploymentUrls":{"cloud":"/opsgenie/"},"id":"5t76PH9Mw7zagigkXzUa8H"},{"sys":{"id":"70RA5tkL23bUJmCn3bDjGy"},"version":"Not Applicable","deployment":"Cloud","productBlurb":"Build trust with every incident","url":"statuspage","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/39aRd69G7mmkTG6yY8H0EV/857285af871d13d1b6290d360a7cea67/logo-light_Statuspage_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"statuspage"},"productName":"Statuspage"},"deploymentUrls":{"cloud":"/statuspage/"},"id":"70RA5tkL23bUJmCn3bDjGy"},{"sys":{"id":"GRwdL69kctHpHtKJ7zcJ1"},"version":"Not Applicable","deployment":"Cloud","productBlurb":"A teamwork directory","url":"platform-experiences","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/1EJJvH8M9OzrklPFmjq3Cg/e476c435a1743db02b9c811ae7a6a0e8/logo-light_Atlassian_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"6kdRPGfYiLXS40s5lykYaS"},"productName":"Platform experiences"},"deploymentUrls":{"cloud":"/platform-experiences/"},"id":"GRwdL69kctHpHtKJ7zcJ1"},{"sys":{"id":"6wktSePjIQKs6KcqcCeyEO"},"version":"Not Applicable","deployment":"Cloud","productBlurb":null,"url":"team-calendars-cloud","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/5VucmXIhBRYyBXA9ygFJ3Y/5082d769a81934af185dcf109b29f628/logo-light_Confluence_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"teamcalendars"},"productName":"Team Calendars"},"deploymentUrls":{"cloud":"/team-calendars-cloud/"},"id":"6wktSePjIQKs6KcqcCeyEO"},{"sys":{"id":"1wFo6tw3l6OQYIoCoW04MW"},"version":"Not Applicable","deployment":"Cloud","productBlurb":null,"url":"questions-for-confluence-cloud","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/5VucmXIhBRYyBXA9ygFJ3Y/5082d769a81934af185dcf109b29f628/logo-light_Confluence_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"questionsforconfluence"},"productName":"Questions for Confluence"},"deploymentUrls":{"cloud":"/questions-for-confluence-cloud/"},"id":"1wFo6tw3l6OQYIoCoW04MW"},{"sys":{"id":"2z0gZxjenWQMWqIqUIqSWw"},"version":"Not Applicable","deployment":"Cloud","productBlurb":null,"url":"cloud","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/1EJJvH8M9OzrklPFmjq3Cg/e476c435a1743db02b9c811ae7a6a0e8/logo-light_Atlassian_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"atlassiancloud"},"productName":"Atlassian Cloud"},"deploymentUrls":{"cloud":"/cloud/"},"id":"2z0gZxjenWQMWqIqUIqSWw"},{"sys":{"id":"5H0E33RpbSIBhC4Rf3X6sK"},"version":"Not Applicable","deployment":"Cloud","productBlurb":"Data visualization and analytics","url":"analytics","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/1LlGSRpoyIRimE0F2CabNM/9c8a89a7196fe549fbb855c8597776fe/logo-light_Atlassian-Analytics_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"4114hkTUsuTHRSjjQUd8Dd"},"productName":"Atlassian Analytics"},"deploymentUrls":{"cloud":"/analytics/"},"id":"5H0E33RpbSIBhC4Rf3X6sK"}],"serverProducts":[{"sys":{"id":"kvr1LpMbeXQeqBF6BJG5S"},"version":"Latest","deployment":"Server","productBlurb":"Project and issue tracking","url":"jira-software-server","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/1Ba3KU2ckjAMmeYoL9DgjO/e6710a37425ab1695046803d32c2db70/Jira_Software.svg"},"productNameReference":{"sys":{"id":"jirasoftware"},"productName":"Jira Software"},"deploymentUrls":{"server":"/jira-software-server/"},"id":"kvr1LpMbeXQeqBF6BJG5S"},{"sys":{"id":"1XBrxhXDoqegKhDG1BLAvI"},"version":"Latest","deployment":"Server","productBlurb":"Service management and customer support","url":"jira-service-management-server","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/5DppKv8q5q206zQzIRDKQq/f31b8874021ee7d6dd54389f902b1421/logo-light_Jira-Service-Management_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"jiraservicedesk"},"productName":"Jira Service Management"},"deploymentUrls":{"server":"/jira-service-management-server/"},"id":"1XBrxhXDoqegKhDG1BLAvI"},{"sys":{"id":"1F1m8sxD1tMlsaORRYGD1f"},"version":"Latest","deployment":"Server","productBlurb":"Manage any business project","url":"jira-core-server","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/33jpVupw41aFgHx33pk79p/9fc5a1d056827ace938a74dd3a825f1e/jira_core_flat.svg"},"productNameReference":{"sys":{"id":"jiracore"},"productName":"Jira Core"},"deploymentUrls":{"server":"/jira-core-server/"},"id":"1F1m8sxD1tMlsaORRYGD1f"},{"sys":{"id":"zifyQJ8ZmqvAmcXgWIWSR"},"version":"Latest","deployment":"Server","productBlurb":"Document collaboration","url":"confluence-server","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/5VucmXIhBRYyBXA9ygFJ3Y/5082d769a81934af185dcf109b29f628/logo-light_Confluence_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"confluence"},"productName":"Confluence"},"deploymentUrls":{"server":"/confluence-server/"},"id":"zifyQJ8ZmqvAmcXgWIWSR"},{"sys":{"id":"5nDH84LjHRq8Opn1Tmt2an"},"version":"Latest","deployment":"Server","productBlurb":"Git code management","url":"bitbucket-server","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/1g4197x84jic8a1P3b3IGT/1a752272b12824d3a3df4bc1e7dd2c53/logo-light_Bitbucket_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"bitbucket"},"productName":"Bitbucket"},"deploymentUrls":{"server":"/bitbucket-server/"},"id":"5nDH84LjHRq8Opn1Tmt2an"},{"sys":{"id":"6aFX6UNeJUogMmuSW04uEO"},"version":"Latest","deployment":"Server","productBlurb":null,"url":"bamboo","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/3DpPNPOUpDyuOyzNTU0WhT/883c9475bbc82c16e9334e47d0c3cd81/logo-light_Bamboo_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"bamboo"},"productName":"Bamboo"},"deploymentUrls":{"server":"/bamboo/"},"id":"6aFX6UNeJUogMmuSW04uEO"},{"sys":{"id":"4pI1aZ1P4QW82KKcU2o2A2"},"version":"Latest","deployment":"Server","productBlurb":null,"url":"crowd","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/7C9qBlldQMCQQmZYW9cKST/d9b5609c85b500bb065c99e38cf1a80a/logo-light_Crowd_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"crowd"},"productName":"Crowd"},"deploymentUrls":{"server":"/crowd/"},"id":"4pI1aZ1P4QW82KKcU2o2A2"},{"sys":{"id":"5F7bce6w8w0eMqeqeGSa42"},"version":"Latest","deployment":"Server","productBlurb":null,"url":"crucible","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/Bmzjg8Jf9IjaKxJJRsdyg/18618a0ed9fb4c119be53772b6657197/logo-light_Crucible_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"crucible"},"productName":"Crucible"},"deploymentUrls":{"server":"/crucible/"},"id":"5F7bce6w8w0eMqeqeGSa42"},{"sys":{"id":"x5esi3PpaoAAaekGEGWqY"},"version":"Latest","deployment":"Server","productBlurb":null,"url":"fisheye","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/1JPhscmMbQTiP584fioarJ/68c65896f78db9c082c74f029dfe14ba/logo-light_Fisheye_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"fisheye"},"productName":"Fisheye"},"deploymentUrls":{"server":"/fisheye/"},"id":"x5esi3PpaoAAaekGEGWqY"},{"sys":{"id":"6DftT4SP0A6eiAkISKuu6Y"},"version":"Latest","deployment":"Server","productBlurb":null,"url":"sourcetree","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/7r8051IqGKLJPwloKRYSVB/1a9b1a101e4419823993cfe79ae8f023/logo-light_Sourcetree_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"sourcetree"},"productName":"Sourcetree"},"deploymentUrls":{"server":"/sourcetree/"},"id":"6DftT4SP0A6eiAkISKuu6Y"},{"sys":{"id":"6pcStE2pewRQyCtz7yHnm1"},"version":"Latest","deployment":"Server","productBlurb":null,"url":"advanced-roadmaps-for-jira-server","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/33jpVupw41aFgHx33pk79p/9fc5a1d056827ace938a74dd3a825f1e/jira_core_flat.svg"},"productNameReference":{"sys":{"id":"portfolioforjira"},"productName":"Advanced Roadmaps for Jira"},"deploymentUrls":{"server":"/advanced-roadmaps-for-jira-server/"},"id":"6pcStE2pewRQyCtz7yHnm1"},{"sys":{"id":"2oDTelIDk4LAM0Bxomfo7m"},"version":"Latest","deployment":"Server","productBlurb":null,"url":"team-calendars-server","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/5VucmXIhBRYyBXA9ygFJ3Y/5082d769a81934af185dcf109b29f628/logo-light_Confluence_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"teamcalendars"},"productName":"Team Calendars"},"deploymentUrls":{"server":"/team-calendars-server/"},"id":"2oDTelIDk4LAM0Bxomfo7m"},{"sys":{"id":"4FWxkzknncoyN31Gnft19o"},"version":"Latest","deployment":"Server","productBlurb":null,"url":"questions-for-confluence-server","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/5VucmXIhBRYyBXA9ygFJ3Y/5082d769a81934af185dcf109b29f628/logo-light_Confluence_mark_brand_RGB.svg"},"productNameReference":{"sys":{"id":"questionsforconfluence"},"productName":"Questions for Confluence"},"deploymentUrls":{"server":"/questions-for-confluence-server/"},"id":"4FWxkzknncoyN31Gnft19o"}],"additionalLinks":[{"linkLabel":"Contact support","linkUrl":"https://support.atlassian.com/contact/","linkIcon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/34aQizNVKUaasai48ASqg2/0ca6041940bcf6b5fd74e559b90eb9e9/question-circle.svg"}},{"linkLabel":"Training & Certification","linkUrl":"https://www.atlassian.com/university","linkIcon":null},{"linkLabel":"Atlassian Migration Program","linkUrl":"https://www.atlassian.com/cloud-migration","linkIcon":null},{"linkLabel":"GDPR guides","linkUrl":"https://confluence.atlassian.com/gdpr","linkIcon":null},{"linkLabel":"Enterprise services","linkUrl":"https://www.atlassian.com/enterprise/services","linkIcon":null},{"linkLabel":"Atlassian Partners","linkUrl":"https://www.atlassian.com/partners","linkIcon":null},{"linkLabel":"Developers","linkUrl":"https://developer.atlassian.com","linkIcon":null},{"linkLabel":"Success Central","linkUrl":"https://success.atlassian.com","linkIcon":null},{"linkLabel":"User groups","linkUrl":"http://aug.atlassian.com","linkIcon":null},{"linkLabel":"Automation for Jira","linkUrl":"https://support.atlassian.com/cloud-automation/docs/jira-cloud-automation/","linkIcon":null},{"linkLabel":"Atlassian.com","linkUrl":"http://www.atlassian.com","linkIcon":null}],"atlassianSupportLogo":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/2a2EqJ1z4IOCa4EKCSAi2s/3f934328cbeb68b72892e7f50b65e380/support-logo-atlassian.svg"},"atlassianLogo":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/2sOh4sF3DSm8Qy8GigKK0S/1c7619d9db378c5ee902d8eeb8fde65b/atlassian-logo-footer.svg"}},"resources":{"cards":[{"sys":{"id":"b3fTs5PrPymsKyewq2uee"},"title":"Documentation","buttonLink":"https://confluence.atlassian.com","buttonText":"View documentation","shortTitle":null,"shortDescription":"Usage and admin help","hideInHeader":true,"analytics":"${Product} Documentation","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/3zu24q81rSIszjUcYWS7rs/e203ecd5b877949db50052f2e2cc018a/rich_icon-Guidelines.svg"},"id":"b3fTs5PrPymsKyewq2uee"},{"sys":{"id":"1eb4CYi6GQecc4S0amoCGm"},"title":"Knowledge Base","buttonLink":"https://atlassian.com","buttonText":"View knowledge base","shortTitle":null,"shortDescription":null,"hideInHeader":true,"analytics":"KnowledgeBase","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/2bQqvQH3QFxNcjpOxCEQKD/cc250e1247072a531cf591444211da4a/rich_icon-Autofix.svg"},"id":"1eb4CYi6GQecc4S0amoCGm"},{"sys":{"id":"1jekufjl8YMw4eUKoI6kg6"},"title":"Community","buttonLink":"https://community.atlassian.com","buttonText":"Visit Atlassian Community","shortTitle":null,"shortDescription":"Answers, support and inspiration","hideInHeader":null,"analytics":"Community","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/199clY7qv6MQc2EasKkGim/2be1028a3452c791c46ebb4a4343a91b/rich_icon-Community.svg"},"id":"1jekufjl8YMw4eUKoI6kg6"},{"sys":{"id":"5buCUK1TCgS2q6KMGkIkSy"},"title":"System Status","buttonLink":"https://status.atlassian.com/","buttonText":"View system status","shortTitle":null,"shortDescription":"Cloud services health","hideInHeader":null,"analytics":"System Status","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/72Hws13erkU4jPlqQmD2SS/fd94e1b3f2b1b3e88315702c77b672cd/rich_icon-Announcement.svg"},"id":"5buCUK1TCgS2q6KMGkIkSy"},{"sys":{"id":"2nRNjDkbCcUwSOq422y66"},"title":"Suggestions and bug reports","buttonLink":"https://jira.atlassian.com/secure/Dashboard.jspa?selectPageId=10440","buttonText":"View suggestions and bugs","shortTitle":"Suggestions and bugs","shortDescription":"Feature suggestions and bug reports","hideInHeader":null,"analytics":"Suggestion bug","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/4LAr0Xsaq4gUk60Uy6eYwk/3914441924f9af9ae74908ad136c55b9/rich_icon-Lightbulb.svg"},"id":"2nRNjDkbCcUwSOq422y66"},{"sys":{"id":"77KyWObmQowc8oycAK6mo2"},"title":"Marketplace apps","buttonLink":"https://marketplace.atlassian.com/","buttonText":"View Marketplace","shortTitle":"Marketplace","shortDescription":"Product apps","hideInHeader":null,"analytics":"Marketplace","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/1ss3lke3aYcVp07USZwdMY/f90bbe91db3ae373ea6dc008ce617373/rich_icon-Integration.svg"},"id":"77KyWObmQowc8oycAK6mo2"},{"sys":{"id":"t7tq3EzI9qwcKMaES0i0y"},"title":"Billing and licensing","buttonLink":"https://www.atlassian.com/licensing/purchase-licensing","buttonText":"View FAQs","shortTitle":null,"shortDescription":"Frequently asked questions","hideInHeader":null,"analytics":"Billing","icon":{"url":"https://images.ctfassets.net/zsv3d0ugroxu/5Cb1EEBbNKkm8uK24mIeEs/4ffba62bbd992b75dc3b7f227c9cb3f3/rich_icon-Credit_cards.svg"},"id":"t7tq3EzI9qwcKMaES0i0y"}]},"preview":false,"contentType":"pageKbArticle"}, contentType: "pageKbArticle", contentAri: "ari:third-party:contentful::entry/zsv3d0ugroxu/master/5FmCk1Z0JNvLiH4yF8XqAc", featureFlags: {}, pageTree: [], featuredEntries: [], }/* */;

How to customize Jira with JavaScript and CSS

Platform Notice: Data Center Only - This article only applies to Atlassian products on the Data Center platform.

Note that this KB was created for the Data Center version of the product. Data Center KBs for non-Data-Center-specific features may also work for Server versions of the product, however they have not been tested. Support for Server* products ended on February 15th 2024. If you are running a Server product, you can visit the Atlassian Server end of support announcement to review your migration options.

*Except Fisheye and Crucible

Summary

Important supportability disclaimer!

Customizations like these are not supported by Atlassian (in any support offer) and should be used at the Jira Admins' own discretion and risk.

You may find support from fellow users in the Community or through the services provided by Atlassian Solution Partners. This article only offers some best practices should you really need to implement something like this.

On version upgrades: Also keep in mind there's no "contract" for the HTML elements in any of Atlassian products and they may change on any release without any public notice — unlike Jira's public Java API, REST API or AJS itself. This means you should include tests on your upgrade checklist to make sure the customizations you may have applied through custom Javascript still work in the new version you're upgrading to.

Troubleshooting

Keep in mind a crucial step of troubleshooting is to disable or remove any JavaScript customization (even temporarily) and observe if the reported issue still persists. If you have implemented any such customizations, be advised Atlassian Support will ask you to remove or disable them to isolate any possible interference during troubleshooting — these customizations tamper with Jira in ways it was not designed to handle and may result in malfunctions on unrelated features or interfaces.

It's possible to add punctual customizations in Jira to work on the users' Browser side and change the look & feel or even overwrite elements in the screens and their behaviors.

This article lists some best practices when implement such customizations to make them less elusive to troubleshoot:

  1. Make use of comments

  2. Make use of console log

  3. Narrow the scope of the change as much as possible

  4. Try and Catch errors

  5. Waiting for elements to render (optional, use with caution)

Jira 9+ "module" script attribute

Starting in Jira 9.4, depending on the resources you want to use (like AJS), you may need to add type="module" to your script tags, like:

1 2 3 <script type="module"> ... </script>

For Jira 8 you don't need the type="module", just <script>...</script>.

Solution

Always test in pre-Prod!

Never apply changes in Production without first applying them in a pre-Prod environment! (Dev, Stage, UAT, pre-Prod, etc)

Even a silly copy & paste mistake or typo can render Jira unavailable even for Admins and require a database update and Jira restart in worst cases (see the Reverting changes section).

There are three places custom Javascript, CSS and HTML tags can be inserted in Jira:

  • The Announcement Banner (see Configuring an announcement banner)

  • Project descriptions (work when the browsing the /PROJECT/summary page)

  • Custom Field descriptions (work wherever the field's present in the screen, like Issue view or edit screens, transition screens, bulk edit pages, etc)

For the Project and Custom Field to work, these settings must be enabled in Jira's General Configuration:

Enable HTML in project description and field descriptions

Best practice 1. Make use of comments

Both for intelligibility and troubleshooting, make extensive use of Comments.

  • HTML comments: <!-- comment goes here -->

  • Javascript comments: // comment goes here

Comments allow for easier troubleshooting, given no expertise on Javascript is needed to suspect a code snippet's doing something to the UI.

"<!-- Custom code to Hide the SLA panel -->" is easier to understand than "document.getElementById("#sla-web-panel-react").style.display = "none";", for example.

Best practice 2. Make use of console log

When changing anything with a custom Javascript code, use the Browser native "console.log()" functions (info(), warn() and error()).

This prints a message in the Browser's console and can be visible through the Browser's "Developer Tools".

If you can standardize the logs to make it easier to troubleshoot and track down what may be interfering with Jira's default behavior, all the better — but always log!

Best practice 3. Narrow the scope of the change as much as possible

Unless you're working with some specific scenario of a global-system-wide change, it's good practice to limit the scope of the change as much as possible.

This can be achieved through — but not limited to:

  • Checking the current page URL

  • Checking if a certain element exists in the current page

This will help you mitigate the risk of changing (and potentially breaking) a screen you didn't consider in your tests in a pre-Prod environment.

Best practice 4. Try and Catch errors

Even with a simple and cautiously-coded script, it's a good practice to surround the custom code with try/catch blocks. This allows handling (or silencing) errors that may arise from unexpected situations (like trying to hide a button that doesn't even exist in the screen yet) and potentially compromise the rest of the script.

Success and Error logging example

1 2 3 4 5 6 7 8 9 10 <script> try { document.querySelector('button[title="With unresolved tickets"]').style.display = "none"; console.info("[My-Company Custom JavaScript] Success message here."); } catch (error) { console.info("[My-Company Custom JavaScript] ERROR: Error message here."); } </script>

Depending on what you're trying to achieve, it may not make sense to log the error. The example snippet below "silences" the error and prevents the error from stopping the rest of the script:

No error logging

1 2 3 4 5 6 7 <script> try { document.querySelector('button[title="With unresolved tickets"]').style.display = "none"; console.info("[My-Company Custom JavaScript] Success message here."); } catch (error) {} </script>

As these are customization on top of Jira, you may choose not to use console.warn() or console.error(), leaving those methods for the "official" JavaScript code from Jira and apps/plugins. No harm in using them, though, as long as you prefix your custom messages or somehow write them in a way to facilitate troubleshooting.

5. Waiting for elements to render (optional, use with caution)

Jira (and most web applications today) renders most of it's UI elements asynchronously, meaning the user's not held at a blank page until everything is fully loaded. This results in UI elements being rendered by the Browser at not always the same order, and each element potentially taking a different time to load each time.

If you need to interact with the UI elements, you may need to wait for them to be fully loaded — or at least defined in the document already — to find them and edit them.

Please note that these Javascript functions are examples only and should be used with caution. They add contention to Browser Threads (they hang for some time, waiting for the specified amount of time to pass).

5.1. setTimeout (try once)

The setTimeout Javascript function waits for a number of milliseconds and then executes what's inside the function:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 <!-- Hiding the "With unresolved tickets" button on Assets/Insight --> <script type="module"> setTimeout(function () { AJS.toInit(function() { if (document.URL.indexOf("/secure/insight/search") >= 0) { try { document.querySelector('button[title="With unresolved tickets"]').style.display = "none"; console.info("[My-Company Custom Announcement Banner] Assets "With unresolved tickets" button removed from screen"); } catch (error) {} } }); }, 1000); </script>

This waits for 1000ms (1 second) then tries to hide a button (.style.display = "none") named "With unresolved tickets" in the page if it matches "/secure/insight/search".

5.2. setInterval (keep trying)

The setInterval is very handy but also much more dangerous than the setTimeout: it executes the function code again and again at every interval in milliseconds.

This is useful if you want to "retry" fetching the element in case it's not there yet, but can also lead to a continuous loop if not handled properly: the "setInterval" runs forever in the Browser until it's explicitly stopped (clearInterval(myInterval)) or an uncaught error happens or the user browses another page.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <!-- Hiding the "With unresolved tickets" button on Assets/Insight --> <script type="module"> let myCounter = 0; let myInterval = setInterval(function () { myCounter++; if (myCounter > 10) { console.info('[My-Company Custom Announcement Banner] Exhausted attempts to locate and remove the "With unresolved tickets" Assets button'); clearInterval(myInterval); } else { AJS.toInit(function() { if (document.URL.indexOf("/secure/insight/search") >= 0) { try { document.querySelector('button[title="With unresolved tickets"]').style.display = "none"; console.info("[My-Company Custom Announcement Banner] Assets "With unresolved tickets" button removed from screen"); clearInterval(myInterval); } catch (error) {} } }); } }, 500); </script>

This example script tries to locate the "With unresolved tickets" button on the "/secure/insight/search" page every 500ms and removes it when it finds it. It also drops out after 10 attempts (to prevent an infinite loop in case somehow the button never shows up or had it's named changed).

Remember that there's no "contract" on UI elements and elements names, labels, ids and even layout/tree may change from one version to another.

It's best to implement these failsafe mechanisms (like a counter to stop the interval execution) at your scripts just in case.

Examples

Example 1. Removing the + Create issue button from the Project Issues page

In this example we make use of a custom Javascript in the Announcement Banner:

Announcement Banner containing code block
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <!-- Hiding the Inline Create Issue Container from URL JIRA/issues --> <script type="module"> if (document.URL.indexOf("JIRA/issues") >= 0) { AJS.toInit(function() { try { document.getElementsByClassName('inline-issue-create-container')[0].style.display = "none"; console.info("[My-Company Custom JavaScript] Screen updated!"); } catch (error) { console.info("[My-Company Custom JavaScript] ERROR: Log an error here if it makes sense."); } }); } </script>

Best practises checklist

Comments

Yes

Console Log

Yes

Limiting scope to the "JIRA/issues" page (JIRA is the Project's Key in the example)

Yes

Try / Catch

Yes

Outcomes

Outcomes announcement banner: create issue button no longer visible

The + Create issues button's gone for project JIRA.

console log excerpt suggesting this is due to a customization interference

Example 2. Hiding a custom field on the Bulk Edit screen

In this example we use a custom field's Description attribute to inject the Javascript:

1 2 3 4 5 6 7 8 9 10 11 12 <!-- Hiding field "Order Id" from the Bulk Edit Screen --> <script type="module"> if (document.URL.indexOf("views/bulkedit") >= 0) { AJS.toInit(function() { try { document.getElementById("customfield_10300_container").parentNode.style.display = "none"; console.info("[My-Company Custom JavaScript] Custom field #10300 hidden from screen."); } catch (error) {} }); } </script>

In this example, the field's id is 10300.

Best practises checklist

Comments

Yes

Console Log

Yes

Limiting scope to the "JIRA/issues" page (JIRA is the Project's Key in the example)

Yes

Try / Catch

Yes

Outcomes

Before the script the "Order Id" is present:

Order ID present on Bulk Edit screen

After the script the "Order Id" is gone and the console log helps identify a custom behavior:

Order ID no longer present on bulk edit screen and console log identifying that this is custom behaviour

Example 3. Hiding the Clone Issue links

It's not uncommon for Admins to want to restrict the Clone Issue functionality. Jira unfortunately doesn't has this feature — yet:

Admins have been working with the Workflow Permission "jira.permission.createclone" but that's a coincidence it works — it actually removes the Create Permission, but Jira still allows the Issue creation through some UI paths (though it shouldn't, actually).

The example Javascript below adds a "display: none !important;" CSS rule to the "issueaction-clone-issue" class:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <!-- Hiding the Clone Issue in Jira CSS Stylesheet --> <script type="module"> if (document.URL.indexOf("my-company-custom-param-to-allow-issue-clone=true") < 0) { AJS.toInit(function() { try { for (let styleSheet of stylesheet = document.styleSheets) { styleSheet.insertRule(".issueaction-clone-issue { display: none !important; }"); } console.info("[My-Company Custom JavaScript] Clone Issue removed from the CSS Stylesheet"); } catch (error) { console.info("[My-Company Custom JavaScript] ERROR trying to remove the Clone Issue from the CSS Stylesheet"); } }); } </script>

Best practises checklist

Comments

Yes

Console Log

Yes

Limiting scope to the "JIRA/issues" page (JIRA is the Project's Key in the example)

NO

Try / Catch

Yes

As a bypass mechanism, it only overrides the CSS Stylesheet if the text "my-company-custom-param-to-allow-issue-clone=true" is not present in the URL. So if the Admin needs to actually bypass this and be able to clone the issue through the URL, just append this parameter to the URL and press enter on the Browser:

1 https://jira-base-url/browse/ISSUE-12345?my-company-custom-param-to-allow-issue-clone=true

Or append other URLs with the ampersand if there are already other parameters:

1 &my-company-custom-param-to-allow-issue-clone=true

You can change this to whatever other bypass text you want or remove this bypass mechanism entirely.

REST API or direct Clone URL access will still work, though. This example only hides the elements with the "issueaction-clone-issue" class in the UI — it doesn't block the Clone feature in the server-side.

Example 4. Hiding the Announcement Banner completely

When adding anything to the Announcement Banner, even if it's not visible, you'll notice a narrow gray stripe where the banner would be located.

To get rid of it completely, simply add this snippet at the beginning or the end of the Banner — careful not to nest it inside any other script, html or style tag:

1 2 3 4 <!-- Hiding the banner completely --> <style> #announcement-banner { display: none; } </style>

Example 5. Adding a new stylesheet conditionally

Hiding elements through stylesheet (CSS) is generally better than through Javascript (JS) as the style's calculated by the Browser when creating the element, whereas in Javascript it'd fail if the element's not rendered yet or may delay in some cases until the script's loaded and executed (the element may show up and disappear right next).

This code snippet is an example of how to append a stylesheet dynamically depending on some conditions — in this example, if "/PROJKEY-" is present in the URL:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <!-- COMPANY-NAME custom Javascript banner to hide the SLA panel for some Projects --> <script> try { if (window.location.href.indexOf("/PROJKEY-") > 0) { let sheetSLA = document.createElement("style"); sheetSLA.id = "COMPANY-NAME-custom-stylesheet-from-announcement-banner-001"; sheetSLA.innerHTML = '#sla-web-panel-react { display: none; }'; document.head.appendChild(sheetSLA); console.info("[COMPANY-NAME custom JS banner] [INFO] SLA panel hidden"); } } catch (error) { console.info("[COMPANY-NAME custom JS banner] [ERROR] " + error); } </script>

When adding new elements in the page it's also very important to give it suggestive Ids to make it easier to troubleshoot.

Reverting changes

If things have gone wrong and with an Admin account you're not able to revert he changes trough the UI, you'll need to revert them directly on the database.

To clear out the Announcement Banner you can run this DB update and restart Jira:

1 update propertytext set propertyvalue = '' where id = (select id from propertyentry where property_key='jira.alertheader');

Refer to the article on How to identify fields with custom Javascript in their description in Jira Data Center / Server to identify in which tables the custom Javascript is present and update the respective records to remove the script.

After updating the specific records, a Jira restart is required.

Updated on February 11, 2025

Still need help?

The Atlassian Community is here for you.