Jump to content
  • Add an autocomplete search bar to Spotfire® using Text Areas


    Introduction

    While listbox and other text filters are quick and easy ways to add the ability to apply text-based filters for users, an user-friendly method that is more familiar for users is to have an autocomplete search box. This is a common technique used on most websites such as Google and Amazon allowing suggestions to appear as the user types in search terms. This is especially useful if you have a large number of text options for the user to filter by. This can be achieved in Spotfire also by following this guide. 

    Important Note: this example does have a dependency on an external library (jQueryUI). In Spotfire versions 7 to 11.4 this is included in Spotfire so does not need any extra work. However, in Spotfire 11.5 and beyond you are required to include or reference your own jQueryUI library: Should you wish to include your own jQueryUI version please follow this guide.

    autocomplete.gif.bf153b1b3e1e6605805721643a56fed4.gif

     

    Define your Text Area

    The steps to implement the autocomplete are shown below:

    1) Add a Text Area to your page which will hold the autocomplete search box

     

        2) Right click, selected Edit HTML on your Text Area and add a DIV tag with the id 'search-div'. As with the other examples, we are also adding a div to hold our stylesheet code:

    <div id="style-container">
      <!-- This element serves as a container for style elements added by the jQuery script. -->
    </div>
    
    <div id="search-div" style="padding-top: 6px; padding-left: 4px; font-size: 14px;"></div>
     

    3) Now insert a new Javascript script (from the Edit Text Area top right icon) with the following code:

    $( function() {
         
        // Inject the HTML to be HTML sanitation compliant
        var searchHTML = `<INPUT id='autocomplete-input' style='FONT-SIZE: 14px; HEIGHT: 24px; BORDER: #d2d2d2 1px solid; WIDTH: 320px;' placeholder=' Type in your search term here... '>
                           <INPUT id='search-button' type='button' value='Search'>`;
        $( "#search-div" ).html(searchHTML);
    
        // Autocomplete function for when a user types in the box
        $( "#autocomplete-input" ).click(function(){
                
            $( "#autocomplete-input" ).autocomplete({
            delay: 0,
            //minLength: 2,
            // read the calculated value into the source of the autocomplete
            source: JSON.parse($('#search-values').text().trim())
            })        
        });
        
        // react to clicking on search button
        $("#search-button").click(function(){
            var search = $("#autocomplete-input").val();
            if (search != "") {
                $("#hidden-search input").val(search).blur(); 
            } else if (search == "") {
                search = 'Reset';
                $("#hidden-search input").val(search).blur(); 
            } 
        });
     });
     
    var css = `
        .ui-autocomplete {
          max-height: 600px;
          overflow-y: auto;
          /* prevent horizontal scrollbar */
          overflow-x: hidden;
        }
    
        .ui-autocomplete-category {
            font-weight: normal;
            padding: .2em .4em;
            margin: .8em 0 .2em;
            line-height: 1.5;
        }
    
        #search-button {
          border: 1px solid #efefef;
          background: #4c9ece;
          color: white;
          padding: 4px 12px;
          margin: 0px 0px 0px 4px;
          cursor: pointer;
          -moz-border-radius: 6px;
          -webkit-border-radius: 6px;
          height: 30px; 
          font-weight: 600;
        }
        #search-button:hover{
          background: #00AAFF;
        }
        #search-button:active {
            position:relative;
            top:1px;
        }
    `;
    
    $("<style/>").text(css).appendTo($("#style-container"));
    
     

    This Javascript does multiple things:

    Firstly, it injects the HTML for an input text box that users will type their search terms into. This is where the autocomplete suggestions will appear. Second, it adds a search button to perform the search once a user selects one of the autocomplete examples. Note that this method is HTML sanitation friendly. If you have this option turned off you could simply add the HTML tags in the search HTML variable above into your Text Area HTML directly. 

    Adding data for your autocomplete

    Continuing on from the steps from above:

    3) Now we need to add the data we want to be searched when users type into this search box. To do this we add a calculated value onto our Text Area. We will then use Javascript to read and parse this into the autocomplete search options:

    4) Add another div tag to your HTML with the id: 'search-values'. In the example below we have added a style of display:none. This hides the contents of this div. However, for testing you may not want to add this so you can view the contents of this div. 

    5) Now add a calculated value inside this div: 

    Define your Calculated Value to be the unique concatenation of the text column you wish to use as your search for the autocomplete. In my example, I am using the 'Neighbourhood Cleaned' column. Use the expression as shown below:

     Substitute(Concatenate('["',UniqueConcatenate([Neighbourhood Cleaned]),'"]'),', ','","')
     

    Why do we need these substitutions in the expression above? First we take the unique values of the column. This produces a comma separated list of values from our data column. We then want to convert this into a Javascript array. So we add [] around the text using the Concatenate expression. Finally, we need to ensure each unque value in our column is surrounded by quotes so they are treated as separate strings by Javascript. We do this with the Substitute command.

    You can now test the autocomplete by typing some text into your search box and you should see suggestions appear which you can select. If you do not, go back and check the ids etc. are all correct and matching.

    Applying the autocomplete selection to a Spotfire filter

    Continuing on from the steps from above:

    6) Now we have the autocomplete ready, we need a way to send the search term someone selects to a Spotfire filter to apply the filter required. We do this using a common Javascript technique used in many of the examples above of creating a Spotfire input control inside a Div and then populating this using Javascript. So we add a new div tag to our Text Area with the id: hidden-search. Again we have added a style to hide this for this example below but you may not want to include this during testing so you can see the search term from the autocomplete appears here after clicking the search button:

     <div id="hidden-search" style="display: none;"> </div>
     

    Now add your Spotfire Property Control input field and assign a Document Property to it:

    7) The final aspect is to have an IronPython script attached to this Document Property so that the script runs and applies a filter based upon the search term chosen in the autocomplete box. To do this edit the input field and click the Script option beside the Document Property. 

    😎 Select to create a new script and add the following code. NOTE: you will need to change the filter line where the columnToFilter variable is created to match your own column name:

    from Spotfire.Dxp.Application import Filters as filters
    from Spotfire.Dxp.Application.Filters import *
    from System.Collections.Generic import Dictionary
    from Spotfire.Dxp.Data import *
    
    ## Set the column name to apply the autocomplete text filter to
    ## In your example - change this to be your column name to apply the filter to
    columnToFilter = "Neighbourhood Cleaned"
    
    ## perform search if text supplied
    if searchText != "Reset":
        filter = Document.ActivePageReference.FilterPanel.TableGroups[0].GetFilter(columnToFilter);
        filter.FilterReference.TypeId = FilterTypeIdentifiers.ListBoxFilter;
        locCodeFilterReal = filter.FilterReference.As[filters.ListBoxFilter]();
        locCodeFilterReal.IncludeAllValues = False;
        locCodeFilterReal.SetSelection(searchText);
    else: ## clear search
        filter = Document.ActivePageReference.FilterPanel.TableGroups[0].GetFilter(columnToFilter);
        filter.FilterReference.TypeId = FilterTypeIdentifiers.ListBoxFilter;
        locCodeFilterReal = filter.FilterReference.As[filters.ListBoxFilter]();
        locCodeFilterReal.IncludeAllValues = True;
        locCodeFilterReal.SetSelection();    
    
     

    Now add a parameter to your script called searchText and assign it the document property you created in step 6) above:

    Now, the autocomplete should be ready to use. 

     

    Additional Notes

    A few important notes on this example:

    • If you search with no text in the search box it will reset the filter and go back to all data. You may want to actually add a 'reset search' button. This can easily be achieved by adding an action control calling the same IronPython script created above and just passing the value 'Reset' in as the searchText   
    • This example only works on exact search terms. So the user must choose one of the search options from the autocomplete suggestions. However, this example could be altered to allow for partial text searching also by editing the IronPython script which applies the filter.
    • There are many nice ways to make the autocomplete work and look such as including categories, having minimum text searches etc. You can find out more at the jQueryUI autocomplete examples page.
    • If you have a very large amount of data you wish to expose to the autocomplete, it may be better to automate writing out the Javascript array to a file instead for the autocomplete to read, or even use a web service called from the jQuery to perform the autocomplete live. See methods from the jQueryUI autocomplete site on this.

    User Feedback

    Recommended Comments

    There are no comments to display.


×
×
  • Create New...