Come for the products,
stay for the community

The Atlassian Community can help you and your team get more value out of Atlassian products and practices.

Atlassian Community about banner
4,298,772
Community Members
 
Community Events
165
Community Groups

Strange behavior with web fragment when using the option "Run code and display dialog"

I’m trying to implement a feature through ScriptRunner that involves extending the Jira “issue details” screen using a web fragment (a button), which in turn shows a dialog box with a form. For the purpose of demonstrating this issue, I have kept the implementation to a minimum (the form only contains a couple of Radio Buttons and a Submit button).

 To summarize:

  1. I have a new button (web fragment) on the issue details screen that is tied to a REST endpoint that I implemented in ScriptRunner
  2. The REST endpoint returns the dialog to be shown with two radio buttons and a Submit button. Upon hitting the Submit button, a JavaScript dialog pops-up displaying the number of radio buttons it found on the form (this should always be 2).

 image.png

 

image.png

However, when I execute the following sequence, my JavaScript somehow thinks bumps up the radio button count by 2 upon every single invocation of this sequence.

  1. Click on the button “Show my Little Form” to bring up the form (works as expected)
  2. Use the radio buttons to select from the two options (works as expected)
  3. Click on the Submit button (works as expected)
  4. You should see the JavaScript pop-up with the message “Number of radio buttons in the group: 2” (works as expected)
  5. Press ESC to exit out of the dialog (works as expected)
  6. Click on the button “Show my Little Form” again (this is where the problem starts)
  7. Try to select between the two options. You will notice that the second radio button is not selectable (problem #1)
  8. Now click on the Submit button. You will notice that the number of pop-ups is now 4 in the message (problem #2 – this should have been 2 and not 4)
  9. Repeat steps (5) through (8) and see the number go up by 2 every time.

 Interestingly, if you refresh the web page after exiting the dialog, the dialog shows the correct number again, and both radio buttons are selectable.

 image.png

 

import com.onresolve.scriptrunner.runner.rest.common.CustomEndpointDelegate
import groovy.transform.BaseScript
import javax.ws.rs.core.MediaType
import javax.ws.rs.core.MultivaluedMap
import javax.ws.rs.core.Response

@BaseScript CustomEndpointDelegate delegate

showForm_Debug { MultivaluedMap queryParams ->
def header =
"""
<!-- Dialog header -->
<header class="aui-dialog2-header">
<h2 class="aui-dialog2-header-main">Test Form</h2>
<a class="aui-dialog2-header-close">
<span class="aui-icon aui-icon-small aui-iconfont-close-dialog">Close</span>
</a>
</header>
"""

def formContent =
"""
<form class="aui" name="crb_main_form">
<div class="field-group" id="cal_fieldgroup_id1">
<label for="cal_fieldgroup_id1">Phase Found</label>
<div class="radio">
<input class="radio" type="radio" checked="checked" name="radiobuttons_phase_found" id="rbStaging">
<label for="rbStaging">Pre-Production</label>
</div>

<div class="radio">
<input class="radio" type="radio" name="radiobuttons_phase_found" id="rbProduction">
<label for="rbProduction">Production</label>
</div>
</div>
</form>
"""

def footer =
"""
<!-- Dialog footer -->
<footer class="aui-dialog2-footer">
<div class="aui-dialog2-footer-actions">
<form id="my-custom-sr-dialog-form" class="aui" action="javascript&colon;getSelectedPhase()">
<button id="submit-button" class="aui-button aui-button-primary">Submit</button>
</form>
</div>
</footer>
"""

def scripts =
"""
<script>
function getSelectedPhase()
{
var radios = document.getElementsByName('radiobuttons_phase_found');
var msg = "Number of radio buttons in the group: " + radios.length
alert(msg);
}
</script>
"""

def dialog =
"""
<section id="static-dialog" class="aui-dialog2 aui-dialog2-large" role="dialog">
${header}
${formContent}
${footer}
${scripts}
</section>

"""
Response.ok().type(MediaType.TEXT_HTML).entity(dialog.toString()).build()
}

I'm at a loss to understand this behavior, and I'm hoping someone from this community could shed some light and hopefully point to what I'm doing wrong here and/or offer suggestions on how to fix this.

Many thanks,

Kamran

1 answer

1 accepted

0 votes
Answer accepted

Hi Kamran

I've encountered this.

It turns out that every time you click the button, your dialog html is embedded into the DOM and when you close it, the html is still in there.

Every time you click the button, you get another copy in the DOM.

You can avoid this by adding the data-aui-remove-on-hide attribute to the section tag

<section id="static-dialog" class="aui-dialog2 aui-dialog2-large" role="dialog" data-aui-remove-on-hide="true">

I would encourage you to explore using the MarkupBuilder to create your dialog and saving your javascript in a separate file (which you can maintain in an IDE that is good for javascript)

Here is how I would implement your form:


def writer = new StringWriter()
def dialog = new MarkupBuilder(writer)
dialog.section(role: 'dialog', id: 'static-dialog', class: 'aui-layer aui-dialog2 aui-dialog2-large', 'aria-hidden': true, 'data-aui-remove-on-hide': true) {
header(class: 'aui-dialog2-header') {
h2(class: 'aui-dialog2-header-main') { dialog.mkp.yield("QAD Log Work Settings") }
}
div(class: 'aui-dialog2-content') {
form(
class: 'aui', name:'crb_main_form'){
fieldset(class: 'group',id:'cal_fieldgroup_id1'){
legend { span { dialog.mkp.yield('Phase Found') } }
div(class: 'radio') {
input(class: 'radio', type: 'radio', id: 'rbStaging', name: 'radiobuttons_phase_found', value: 'rbStaging')
label(for: 'rbStaging') { dialog.mkp.yield "Pre-Production" }
}
div(class: 'radio') {
input(class: 'radio', type: 'radio', id: 'rbProduction', name: 'radiobuttons_phase_found', value: 'rbProduction',)
label(for: 'rbProduction') { dialog.mkp.yield "Production" }
}
}
}
}
foooter(class: 'aui-dialog2-footer') {
div(class: 'aui-dialog2-footer-actions') {
button(id: 'cancel-button', class: 'aui-button aui-button-link cancel', onclick: 'closeDialog()') { dialog.mkp.yield "Cancel" }
button(id: 'submit-button', class: 'aui-button aui-button-primary', type: 'submit', accesskey: 's', value: 'Submit', onclick: 'getSelectedPhase()') { dialog.mkp.yield "Submit" }
}
}
script(type: 'text/javascript') {
def scriptFile = new File("$jiraHome/scripts/path/to/your/javascript/file.js")
dialog.mkp.yieldUnescaped(scriptFile.getText('UTF-8'))
}
}

Response.ok().type(MediaType.TEXT_HTML).entity(writer.toString()).build()

If you haven't already found this...  I find it invaluable: https://aui.atlassian.com/aui/7.9/docs/dialog2.html

Thank you so much, you're awesome! :) This took care of both problems I described in my post. I also appreciate the explanation of what's going on with the DOM every time the button is clicked - it makes a lot of sense now.

 I'm still very new to ScriptRunner and Groovy, and I sincerely appreciate your suggestions about using MarkupBuilder and an IDE for development. Wondering if you'd have a recommendation for any good IDE out there (I use Windows).

Thanks again!

Kamran

PS: I've always wondered what name you went by if I had to address you by name (Peter or Peter-Dave?) :) 

Glad I could help.

I use Intelij community edition as my IDE. There are some instructions on the adaptavist site on how to configure.

When you start with their sample project (even if you have no plans to create a plugin or anything like that) the IDE will download all the relevant dependencies so that you get the full autocomplete experience.

I don't use a local instance of Jira or use any debug configuration. I just have WINSCP set up to copy my local files to my DEV server. This way every time I change a line of code, it is immediately picked up by my DEV server and I can test the results there.

I encourage people to call me by both: "Peter-Dave". But I'll answer to either.

Suggest an answer

Log in or Sign up to answer
TAGS
Community showcase
Published in Confluence

An update on Confluence Cloud customer feedback – June 2022

Hi everyone, We’re always looking at how to improve Confluence and customer feedback plays an important role in making sure we're investing in the areas that will bring the most value to the most c...

233 views 1 4
Read article

Community Events

Connect with like-minded Atlassian users at free events near you!

Find an event

Connect with like-minded Atlassian users at free events near you!

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you