Virtual Keyboard + Bootstrap Typeahead

https://github.com/Mottie/Keyboard

by Mottie

HTML

<link rel="stylesheet" href="https://mottie.github.io/Keyboard/css/keyboard.css">
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/ui-lightness/jquery-ui.css">
<script src="https://mottie.github.io/Keyboard/js/jquery.keyboard.js"></script>
<script src="https://mottie.github.io/Keyboard/js/jquery.mousewheel.js"></script>
<script src="https://mottie.github.io/Keyboard/js/jquery.keyboard.extension-typing.js"></script>
<script src="https://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap-theme.css">
<script src="https://twitter.github.io/typeahead.js/releases/latest/typeahead.bundle.js"></script>
<div id="wrap">
  <input id="keyboard" type="text" />
</div>

CSS

/* typeahead tweaks to work with virtual keyboard */

div.ui-keyboard-preview-wrapper {
  overflow: visible
}

.twitter-typeahead {
  width: 100%;
}

div.tt-menu {
  margin-left: 435px; /* adjust to move typeahead popup */
  margin-top: -2em;
}

.twitter-typeahead pre,
.tt-hint {
  visibility: hidden;
}

/* typeahead css - reduced width for this demo */

.typeahead,
.tt-query,
.tt-hint {
  width: 150px;
  height: 30px;
  padding: 8px 12px;
  font-size: 24px;
  line-height: 30px;
  border: 2px solid #ccc;
  -webkit-border-radius: 8px;
  -moz-border-radius: 8px;
  border-radius: 8px;
  outline: none;
}

.typeahead {
  background-color: #fff;
}

.typeahead:focus {
  border: 2px solid #0097cf;
}

.tt-query {
  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
  -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
}

.tt-hint {
  color: #999
}

.tt-menu {
  width: 150px;
  margin: 12px 0;
  padding: 8px 0;
  background-color: #fff;
  border: 1px solid #ccc;
  border: 1px solid rgba(0, 0, 0, 0.2);
  -webkit-border-radius: 8px;
  -moz-border-radius: 8px;
  border-radius: 8px;
  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
  -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
  box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
}

.tt-suggestion {
  padding: 3px 20px;
  font-size: 18px;
  line-height: 24px;
}

.tt-suggestion:hover {
  cursor: pointer;
  color: #fff;
  background-color: #0097cf;
}

.tt-suggestion.tt-cursor {
  color: #fff;
  background-color: #0097cf;
}

.tt-suggestion p {
  margin: 0;
}


/* demo css - position input so it's not hugging the top of the demo frame */

body {
  margin-top: 100px;
  font-size: 10px;
}

#wrap {
  display: block;
  margin: 0 auto;
  width: 200px;
}

JavaScript

/* VIRTUAL KEYBOARD DEMO - https://github.com/Mottie/Keyboard */
$(function() {

  $('#keyboard').keyboard({
      visible: function(e, keyboard) {
        initTypeAhead(keyboard);
      },
      change: function(e, keyboard){
        // trigger "input" required for typeahead to recognize a change
        e.type = 'input';
      	keyboard.$preview.trigger(e);
      }
    })
    // activate the typing extension
    .addTyping({
      showTyping: true,
      delay: 250
    });

  var substringMatcher = function(strs) {
      return function findMatches(q, cb) {
        var matches, substringRegex;

        // an array that will be populated with substring matches
        matches = [];

        // regex used to determine if a string contains the substring `q`
        substrRegex = new RegExp(q, 'i');

        // iterate through the pool of strings and for any string that
        // contains the substring `q`, add it to the `matches` array
        $.each(strs, function(i, str) {
          if (substrRegex.test(str)) {
            matches.push(str);
          }
        });

        cb(matches);
      };
    },
    states = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California',
      'Colorado', 'Connecticut', 'Delaware', 'Florida', 'Georgia', 'Hawaii',
      'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana',
      'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota',
      'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire',
      'New Jersey', 'New Mexico', 'New York', 'North Carolina', 'North Dakota',
      'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island',
      'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont',
      'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming'
    ],
    initTypeAhead = function(keyboard) {
      keyboard.$preview.typeahead({
        hint: true,
        highlight: true,
        minLength: 1
      }, {
        name: 'states',
       ...