In my previous blogpost, I presented our solution to a JIRA Quicksearch. We used the CUTE Addon to get this running. Now, this blogpost dives a little deeper into the development process with CUTE. As an example, I will use the JIRA Quicksearch feature.
Preparation
Install the CUTE addon in your JIRA system. The addon is available in the Atlassian Marketplace. With this, a CUTE administration interface is available in JIRA. You can create a new extension using the “Create Extension” button. You are now ready for using CUTE.
Step 1 – Create HTML
For our Quicksearch, we need a box which is used to hold our search results. So, we create a new velocity resource using the “Add a resource” button and select “Template (Velocity)”. We now enter our HTML code. Our result box also gets a unique name (“rich search-dropdown”) to address it later.
<!-- Dropdown --> <div id="richsearch-dropdown" class="aui-style-default aui-dropdown2"> <ul> </ul> </div>
This HTML will now be rendered hidden on each JIRA page. We need step 2 to use it.
Step 2 – Move and interact
In step 2, we now move our HTML to a visible area in the page by using Javascript. In our case, the container should be displayed directly below the global search box. So, we create a new resource of type “Javascript” and use the following code to perform the move.
// Execute after the page was fully loaded jQuery(function(jQuery){ jQuery("#quickSearchInput").after(jQuery("#richsearch-dropdown")); });
We use the Javascript Framework JQuery which is available by default in JIRA. This basic Javascript will now be extended to cover the requirements of searching after a user types in some characters. So, here is the code … it contains comments to give a better understanding what happens:
// Execute after the page was fully loaded jQuery(function(jQuery){ //register the quicksearch execution to the global search field jQuery("#quickSearchInput").keyup(getFilterInvoker()).attr("autocomplete", "off").after(jQuery("#richsearch-dropdown")); jQuery("#quickSearchInput").focus(doRichSearch); //if the user clicks outside the quicksearchresult the result box should disappear jQuery(document).mouseup(function (e) { var container = jQuery("#quicksearch"); if (!container.is(e.target) && container.has(e.target).length === 0) { jQuery("#richsearch-dropdown").hide(); } }); //this is a timer for the delayed search execution function getFilterInvoker() { var filterTimer = 0; return function(event){ clearTimeout(filterTimer); filterTimer = setTimeout(function() { doRichSearch(event) }, 300); } } //the search itself function doRichSearch() { var inputVal = jQuery("#quickSearchInput").val(); //if at least 3 characters inserted if(inputVal.length > 2) { jQuery("#richsearch-dropdown").show(); //build the query query = 'summary ~ "'+inputVal+'*"'; //if someone iserts an issuekey we have to search in the key instead of the summary var res = inputVal.match(/^.*-\d+$/); if(res) { query = 'key = "'+inputVal+'"'; } //we only want 10 results var maxResult = 10; jQuery("#richsearch-dropdown li").remove(); //if the search is runnig we need to show a little spinner gizmo to show the process var spinnerListEntry = jQuery('<li><a href="#"><div class="button-spinner"></div></a></li>'); spinnerListEntry.find("a").click(function(){ jQuery(this).closest("form").submit(); }); jQuery("#richsearch-dropdown ul").append(spinnerListEntry); jQuery(spinnerListEntry).find('.button-spinner').spin(); //here is the actual search. We use the same request confluence is using in the jiraissues macro jQuery.get(contextPath+"/sr/jira.issueviews:searchrequest-xml/temp/SearchRequest.xml",{tempMax: maxResult, jqlQuery: query, returnMax: true, field: ["summary", "type", "link"]} ,function(xml) { jQuery("#richsearch-dropdown li").remove(); //if no result was found we simply show it if(jQuery(xml).find("item").length == 0) { var elementToAddHtml = jQuery("<li><a href='#'>No results found for \""+inputVal+"\"</a></li>"); elementToAddHtml.find("a").click(function(){ jQuery(this).closest("form").submit(); }); jQuery("#richsearch-dropdown ul").append(jQuery(elementToAddHtml)); } //rendering the results to list items and append them to the quicksearchbox jQuery(xml).find("item").each(function(){ var elementToAddHtml = "<li><a href='"+jQuery(this).find("link").text()+"'><img src='"+jQuery(this).find("type").attr("iconUrl")+"'> <span>"+jQuery(this).find("key").text()+" "+jQuery(this).find("summary").text()+"</span></a></li>"; jQuery("#richsearch-dropdown ul").append(jQuery(elementToAddHtml)); }); }); } else { jQuery("#richsearch-dropdown").hide(); } } });
Step 3 – Styling
Finally, we can style the container and its content. Create a new resource of type “StyleSheet” for that. Here is the style code for our result box:
#richsearch-dropdown { z-index: 101; width: 300px; } #richsearch-dropdown img { vertical-align: middle; } #richsearch-dropdown a { line-height: 25px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } #richsearch-dropdown .button-spinner { height: 25px; }
Conclusion
The CUTE extension is now complete and ready to use. You can find the complete Extension in the Communardo Support Portal. Now, it is your turn. Create your own little CUTE extensions by doing the 3 steps “create”, “move” and “style”. If you want, you can start right now!