Communardo Software GmbH, Kleiststraße 10 a, D-01129 Dresden
0800 1 255 255

Working with CUTE - JIRA Quicksearch

A deeper dive into the development process with the CUTE for JIRA add-on.

In my pre­vious blog­post, I pre­sen­ted our solu­tion to a JIRA Quicksearch. We used the CUTE Addon to get this run­ning. Now, this blog­post dives a little deeper into the deve­lo­p­ment pro­cess with CUTE. As an example, I will use the JIRA Quicksearch feature.

demojira

Preparation

Install the CUTE addon in your JIRA sys­tem. The addon is avail­able in the Atlassian Marketplace. With this, a CUTE admi­nis­tra­tion inter­face is avail­able in JIRA. You can create a new exten­sion using the "Create Extension" but­ton. You are now ready for using CUTE.

cuteoverview

Step 1 – Create HTML

For our Quicksearch, we need a box which is used to hold our search results. So, we create a new velo­city resource using the "Add a resource" but­ton and select "Template (Velocity)". We now enter our HTML code. Our result box also gets a uni­que 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 ren­de­red hid­den on each JIRA page. We need step 2 to use it.

template

Step 2 – Move and interact

In step 2, we now move our HTML to a visi­ble area in the page by using Javascript. In our case, the con­tai­ner should be dis­played directly below the glo­bal search box. So, we create a new resource of type "Javascript" and use the fol­lowing code to per­form 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 avail­able by default in JIRA. This basic Javascript will now be exten­ded to cover the requi­re­ments of sear­ching after a user types in some cha­rac­ters. So, here is the code … it con­tains comments to give a bet­ter under­stan­ding 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 con­tai­ner and its con­tent. 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 exten­sion is now com­plete and ready to use. You can find the com­plete Extension in the Communardo Support Portal. Now, it is your turn. Create your own little CUTE exten­si­ons by doing the 3 steps "create", "move" and "style". If you want, you can start right now!

>> Find out more about Atlassian licen­ces here!

13. März 2015

Pin It on Pinterest