View on GitHub

Autocomplete-lhc

An autocompleter package used by the NLM PHR and LHC-Forms projects

Download pre-built JavaScript and CSS as a .zip file

autocomplete-lhc

This is a package of JavaScript autocompleters that were developed to meet the requirements of the NLM PHR and LHC-Forms projects. The package includes an AngularJS directive, but can be used without Angular.

The package supports two basic types of autocompleters. Autocompleters whose lists are small enough to be fully specified at construction time are called "Prefetch", and are supported by autoCompPrefetch.js. Autocompleters whose lists are shown in small, AJAX-retrieved chunks that match the user's input are called "Search", and are supported by autoCompSearch.js.

Below are a few demos of the features and the code to use them.

A Few Demos

A prefetch autocompleter that allows entry of off-list items:
[Show source]
<input type="text" id="demo1">
<script>
var dessertArray = ['Chocolate bar', 'Chocolate ice cream',
  'Vanilla ice cream', 'Brownie', 'Fudge Brownie', 'Double Fudge Brownie',
  'Fudge'].sort();
new Def.Autocompleter.Prefetch('demo1', dessertArray);
</script>
    
[Hide source]
Autocompleters can also require the entered value to match:
[Show source]
<input type="text" id="demo2">
<script>
var opts = {'matchListValue': true}
new Def.Autocompleter.Prefetch('demo2', dessertArray, opts);
</script>
    
[Hide source]
Sequence numbers can be left out (but are useful for picking by number):
[Show source]
<input type="text" id="demo3">
<script>
var opts = {addSeqNum: false}
new Def.Autocompleter.Prefetch('demo3', dessertArray, opts);
</script>
    
[Hide source]
When a field is near the bottom of the window, the list will scroll into view and flow into two columns:
[Show source]
<input type="text" id="demo4">
<script>
var moreDesserts = ['Chocolate bar', 'Chocolate ice cream',
  'Vanilla ice cream', 'Brownie', 'Fudge brownie', 'Double fudge brownie',
  'Fudge', 'Chocolate cake', 'Chocolate mousse', 'Watermelon',
   'Chocolate chip cookies', 'Brownie-stuffed cookie'].sort();
new Def.Autocompleter.Prefetch('demo4', moreDesserts);
</script>
    
[Hide source]
Larger lists show a subset and have a "see more" link:
[Show source]
<input type="text" id="demo5">
<script>
var evenMoreDesserts = ['Chocolate bar', 'Chocolate ice cream',
  'Vanilla ice cream', 'Brownie', 'Fudge brownie', 'Double fudge brownie',
  'Fudge', 'Chocolate cake', 'Chocolate mousse', 'Watermelon',
  'Chocolate chip cookies', 'Brownie-stuffed cookie', 'Cannoli',
  'Baklava', 'Tiramisu', 'Ice cream cake', 'Pumpkin pie', 'Shortbread',
  'Samoas', 'Raisin cookies', 'Peanut butter cookies'].sort();
new Def.Autocompleter.Prefetch('demo5', evenMoreDesserts);
</script>
    
[Hide source]
List items can have associated codes:
Code:
[Show source]
<input type="text" id="demo6" name="demo6">  Code: <input id=demo6Code readonly>
<script>
var opts = {codes: ['R', 'G', 'B']}
new Def.Autocompleter.Prefetch('demo6', ['Red', 'Green', 'Blue'], opts);
Def.Autocompleter.Event.observeListSelections('demo6', function(data) {
  jQuery('#demo6Code')[0].value = data.item_code;
});
</script>
    
[Hide source]
List items can have headers (in prefetch lists):
[Show source]
<input type="text" id="demo7">
<script>
var colors = ['Primary', 'Red', 'Green', 'Blue',
              'Secondary', 'Magenta', 'Yellow', 'Cyan']
var opts = {codes: ['P', 'R', 'G', 'B', 'S', 'M', 'Y', 'C'],
            itemToHeading: {R: 'P', G: 'P', B: 'P',
                            M: 'S', Y: 'S', C: 'S'}}
new Def.Autocompleter.Prefetch('demo7', colors, opts);
</script>
    
[Hide source]
A search autocompleter searching medical conditions:
[Show source]
<input type="text" id="demo8">
<script>
new Def.Autocompleter.Search('demo8',
  'https://clinicaltables.nlm.nih.gov/api/conditions/v3/search');
</script>
    
[Hide source]
A prefetch autocompleter via an AngularJS directive:
[Show source]
<script>
  angular.module('demoApp', ['autocompleteLhcMod']).
    controller('demoController', ['$scope', function($scope) {
      // Set up the list items as data on the scope.  Base them
      // on the dessertArray declared in the first demo.
      var listItemData = [];
      for (var i=0, len=dessertArray.length; i<len; ++i) {
        // Each item's data is an object which will get stored on the
        // input field's model (demo9Val, in this case) when the item is
        // selected from the list.
        listItemData.push({
          text: dessertArray[i],  // the display string goes under "text"
          otherItemData:  'anything else you want can be included in the object'
        });
      }
      $scope.demo9ListOpts = {listItems: listItemData};
    }]);
</script>
<div ng-controller="demoController">
  <input type="text" id="demo9" ng-model="demo9Val"
   autocomplete-lhc="demo9ListOpts">
</div>
    
[Hide source]
A multi-select prefetch autocompleter:
[Show source]
<input type="text" id="demo10">
<script>
new Def.Autocompleter.Prefetch('demo10', dessertArray, {maxSelect: '*'});
</script>
    
[Hide source]
A table-format search autocompleter (having two columns, with only the first column being selected for the input field):
[Show source]
<input type="text" id="demo11">
<script>
new Def.Autocompleter.Search('demo11',
  'https://clinicaltables.nlm.nih.gov/api/genes/v3/search?df=symbol,name_mod',
  {tableFormat: true, valueCols: [0], colHeaders: ['Symbol', 'Name']});
</script>
    
[Hide source]

Some complete HTML page examples hosted on Plunker:

Features:

  1. Section 508-compliant (i.e., accessible to screen readers)
  2. Supports coded-value lists
  3. Supports headings for groups of items in lists
  4. Two-column lists when there is not enough space on the page to show the list in a single column.
  5. Numbered list items (optional).
  6. Can require that an entry in the field match the list.
  7. Multi-select lists
  8. Table-format for list items with multiple fields
  9. Event listeners for various things like "list selection".
  10. Provides a way to get extra information about the record associated with a list item. (See recordDataRequester.js.)
  11. Support for list suggestions in the search (AJAX) autocompleter, when the user does not pick an item in the list. (Currently this is for single-select lists only.)
  12. "autofill" option, which fills in the field automatically if there is just one list item
  13. Default value (optional), which gets placed in the field when the field gets focus (along with showing the list).
  14. A "see more" link on the search autocompleter which provides an expanded list of items.
  15. Search buttons (optional) for search autocompleters to make them show an expanded results list. (Without a button, the user can click on the "see more" link.)
  16. A results cache for the search autocompleter, so that repeats of AJAX calls for the same list items are not necessary.

Installation:

There are four ways to install and use autocomplete-lhc code:

Using the Hosted Browser-Ready Releases

Starting with version 17, this package does not bundle its jQuery depenendency, so you will need to include that separately, but that can be obtained from one of several CDNs (an example of which is below).

For the Javascript, include:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <!-- example CDN-- you may choose another source -->
<script src="https://lhcforms-static.nlm.nih.gov/autocomplete-lhc-versions/17.0.3/autocomplete-lhc.min.js"></script>

(Note that you can substitute for "17.0.3" one of the other prebuilt versions available at https://lhcforms-static.nlm.nih.gov/autocomplete-lhc-versions).

For the CSS, include:

<link href="https://lhcforms-static.nlm.nih.gov/autocomplete-lhc-versions/17.0.3/autocomplete-lhc.min.css" rel="stylesheet" />

License, etc.

This software, autocomplete-lhc, was developed by the National Library of Medicine (NLM) Lister Hill National Center for Biomedical Communications (LHNCBC), part of the National Institutes of Health (NIH).

Please cite as:

Lister Hill National Center for Biomedical Communications
National Library of Medicine
Bethesda, MD

This software is distributed under a BSD-style open-source license. See LICENSE.md.

No warranty or indemnification for damages resulting from claims brought by third parties whose proprietary rights may be infringed by your usage of this software are provided by any of the owners.