*Thank you everyone for chiming in to help.*
Here is more background information of the plugin I am writing. The plugin is a web-item plugin in JIRA version 4.
=== *atlassian-plugin.xml* ===
I have added the following code segment into atlassian-plugin.xml. As a result, I successfully added a new link in the top navigation bar of JIRA.
(ie: Dashboards | Projects | Issues | Administration | *NewAction* )
{code}<web-item key="new_action_link" name="New Action Link" section="system.top.navigation.bar" weight="100">
<label key="item.newactionlink.label" />
<link linkId="groovy_runner">/secure/NewAction!default.jspa</link>
<condition class="com.atlassian.jira.plugin.webfragment.conditions.UserLoggedInCondition" />
</web-item>
{code}
In addition to the above fragment, I also have the following fragment in atlassian-plugin.xml, which hooks a webwork action to my *New Action* link in the top navigation bar.
{code}<webwork1 key="new_action" name="New Action">
<actions>
<action name="com.ams.jira.plugins.NewAction" alias="NewAction">
<view name="input">/templates/new_action.vm</view>
<view name="error">/templates/new_action.vm</view>
<view name="success">/templates/new_action.vm</view>
</action>
</actions>
</webwork1>
{code}
=== *new_action.vm* ===
{code}<html>
<head>
<title>New Action</title>
<meta name="decorator" content="general">
<script type="text/javascript">
var rowCount = 0;
var fieldCount = 0;
function moreFields() {
var newRow = document.getElementById('issueRows').insertRow(2);
newRow.id = rowCount++;
var newCell = newRow.insertCell(0);
newCell.innerHTML = getCellHTML();
attachEventHandlers();
}
function deleteElement(id){
var el = document.getElementById(id);
el.parentNode.removeChild(el);
}
function getUserPickerHTML() {
var fieldName = "assignee" + fieldCount++;
var userPickerHTML = "<fieldset class='hidden user-picker-params' rel='" + fieldName + "'> \
<input id='formName' type='hidden' value='jiraform'/> \
<input id='fieldName' type='hidden' value='" + fieldName + "'/> \
<input id='multiSelect' type='hidden' value='false'/> \
<input id='userPickerEnabled' type='hidden' value='true'/> \
</fieldset> \
<div id='" + fieldName + "_container' class='ajax_autocomplete'> \
<input id='" + fieldName + "' class='userpickerfield' type='text' style='width: 30%;' value='' name='" + fieldName + "'/> \
<a class='popup-trigger' href=''> \
<img width='16' hspace='0' height='16' border='0' align='absmiddle' src='/images/icons/filter_public.gif' name='assigneeImage' title='Select a user'/> \
</a> \
<div id='" + fieldName + "_results' class='ajax_results'/> \
<font size='1'>Start typing to get a list of possible matches.</font> \
</div>";
return userPickerHTML;
}
function attachEventHandlers() {
AJS.$(".user-picker-params").each(function(){
var params = {};
AJS.$(this).find("input").each(function(){
var $this = AJS.$(this);
params[$this.attr("id")] = $this.val();
});
AJS.$("#" + params.fieldName + "_container a.popup-trigger").click(function(e){
if (!params.formName)
{
params.formName = AJS.$(":input[name='" + params.fieldName +"']").parents("form").attr("name");
}
var url = contextPath;
if (params.actionToOpen){
url = url + params.actionToOpen;
}else {
url = url + '/secure/popups/UserPickerBrowser.jspa';
};
url += '?formName=' + params.formName + '&';
url += 'multiSelect=' + params.multiSelect + '&';
url += 'element=' + params.fieldName;
var vWinUsers = window.open(url, 'UserPicker', 'status=yes,resizable=yes,top=100,left=200,width=580,height=750,scrollbars=yes');
vWinUsers.opener = self;
vWinUsers.focus();
e.preventDefault();
});
if (params.userPickerEnabled === "true" ){
jira.widget.autocomplete.Users({
fieldID: params.fieldName,
delimChar: params.multiSelect === "false"? undefined : ",",
ajaxData: {
fieldName: params.fieldName
}
});
}
});
}
</script>
$!webResourceManager.requireResource("jira.webresources:autocomplete")
</head>
<body>
<table cellspacing="0" cellpadding="10" border="0" width="100%"><tr><td>
<form action="NewAction!default.jspa" method="post" name="jiraform" onsubmit="if (this.submitted) return false; this.submitted = true; return true" >
<table class="jiraform maxWidth" id="issueRows">
<tr>
<td colspan="2" class="jiraformheader"><h3 class="formtitle">New Action</h3></td>
</tr>
<tr>
<td colspan="2" class="jiraformheader">
<p>This tool is for New Action. <a href="javascript:;" onclick="moreFields();">Add Row</a></p>
</td>
</tr>
<tr id="pivot">
<td colspan="2" class="fullyCentered jiraformfooter" >
<input type="submit" name="copyProject" value="Create" accesskey="S" title="Press Ctrl+S to submit form" class="spaced"/>
</td>
</tr>
</table>
</form>
<script language="javascript">
window.onload = moreFields;
try { document.jiraform.elements[0].focus(); } catch (e) {}
</script>
</td></tr></table>
</body>
</html>
{code}
The original problem I had faced, was that I could not get the AJAX suggestions to work for the user-picker JIRA field that I have included. What I have failed to explain, is that I was adding in the user-picker field with javascript. That is, the page starts without any fields, and then the user-picker field is dynamically populated using javascript. In contrast, if I had rewritten the velocity template with a static user-picker field (no dynamic population with javascript), then the AJAX suggestions for the user-picker field works.
+The update to my problem statement, is that I faced great difficulty getting JIRA's user-picker field's AJAX suggestion to work, *when the user-picker fields have been populated dynamically with javascript*.+
Fortunately, I have figured out a solution. The code above isn't elegant by any means, it is a prototype I have used to resolve my problem. Please note that my background in javascript is less than a week's worth. Thus, any comments or suggestions with regards to re-factoring are greatly appreciated.
*_Key Observation_*: After much tracing and reverse engineering attempts in trying to figure out how JIRA's user-picker field works, I realized that no event handlers (ie: keyboard key-up event, mouse click event, etc...) are mapped to the new dynamically populate user-picker fields. After spending some time with *autocomplete.js*, I have identified the code segment containing the logic for assigning the event handlers to user-picker fields. I have copied the mentioned code segment from *autocomplete.js* into the *attachEventHandlers()* javascript function. I would much rather have called an existing function that exist in *autocomplete.js*, however, I believe the code segment I have pulled out is an inline javascript function? Thus, there I am under the assumption there is no function nam
e I can readily use within *autocomplete.js* to invoke this logic. As such, I have simply copied the logic into *attachEventHandlers()*, and is calling *attachEventHandlers()* each time a ne
w user-picker field is dynamically added to ensure proper mapping of event handlers are set. This in result, solved the problem.
Thank you to everyone who has pitched in comments and suggestions, and I hope this post will help someone in the community in attempt to achieve similar goals.
-David Lai
--
Post by david.lai - online at:
http://forums.atlassian.com/thread.jspa?forumID=100&threadID=40097