{"id":389,"date":"2013-08-23T13:47:23","date_gmt":"2013-08-23T18:47:23","guid":{"rendered":"http:\/\/www.aibistin.com\/?p=389"},"modified":"2013-08-25T21:10:29","modified_gmt":"2013-08-26T02:10:29","slug":"city-state-county-selection-using-bootstrap-2-typeahead","status":"publish","type":"post","link":"https:\/\/www.aibistin.com\/?p=389","title":{"rendered":"City, State, County Selection With Bootstrap 2 Typeahead"},"content":{"rendered":"<p class=\"important\">\n This is a demonstration of how I implemented an Ajax call to a Perl Dancer2 Application using jQuery and the Bootstrap Typeahead function.\n<\/p>\n<p>\nAs part of my <a class=\"vital-link\" href=\"http:\/\/www.aibistin.com\/?p=290\" title=\"TravelTime\"> TravelTime App <\/a>, I wanted to create and easy way to select the start and end locations using the jQuery Autocomplete component. Bootstrap 2 has its own version of this which they call <a href=\"http:\/\/getbootstrap.com\/2.3.2\/javascript.html#typeahead\" title=\"Bootstrap 2 Typeahead\" target=\"_blank\">Typeahead<\/a>.<br \/>\n<em>I just found out that the latest version of Bootstrap will not include this Typeahead functionality. Instead it will be replaced with <a class=\"vital-link\"  href=\"https:\/\/github.com\/twitter\/typeahead.js\/\" title=\"typeahead.js\" target=\"_blank\">typeahead.js<\/a> I hope to check this out in the future.<\/em><br \/>\nAnyway, I will be using <a href=\"https:\/\/www.perl.org\" title=\"Perl\"  target=\"_blank\">Perl<\/a>, <a href=\"https:\/\/metacpan.org\/module\/Dancer2\" title=\"Dancer2\"  target=\"_blank\">Dancer2<\/a> with <a href=\"https:\/\/metacpan.org\/module\/Template\" title=\"Template Toolkit\"  target=\"_blank\">Template Toolkit<\/a> to render this form.<br \/>\nI also needed to customise the Typeahead to complete an Ajax call to my Perl Dancer2 application. The Dancer2 application will then provide the sorted list of City,States and Counties based on the search parameters passed to it.\n<\/p>\n<p class=\"code-heading\">The Template::Toolkit Form<\/p>\n<p><span class=\"code-description\">Exerpt from travel_time_quick.tt<\/span><\/p>\n<pre class=\"brush: css; auto-links: false; collapse: false; first-line: 1; gutter: true; highlight: [10,11,12,14,15,22,23,24]; light: false; pad-line-numbers: false; smart-tabs: false; tab-size: 4; title: Address selector form travel_time_quick.tt; toolbar: true; notranslate\" title=\"Address selector form travel_time_quick.tt\">\r\n&lt;div class=&quot;span11&quot;&gt;\r\n        &lt;span class=&quot;text-info&quot;&gt;\r\n            &lt;abbr title='Enter the starting location'&gt;Start Location&lt;\/abbr&gt;\r\n        &lt;\/span&gt;\r\n        &lt;div class=&quot;control-group&quot;&gt;\r\n        &lt;!-- Bootstrap Typeahead --&gt;\r\n            &lt;label class=&quot;control-label&quot; for=&quot;address-&#x5B;% loop.count %]&quot;&gt;&#x5B;% warning_message %]&lt;\/label&gt;\r\n            &lt;div class=&quot;controls&quot;&gt;\r\n                &lt;input type=&quot;text&quot;\r\n                    class=&quot;cityStatesTypeahead span9 input-append&quot;\r\n                    name=&quot;address-&#x5B;% loop.count %]&quot;\r\n                    id=&quot;address-&#x5B;% loop.count %]&quot; value=&quot;&#x5B;% address %]&quot;\r\n                    placeholder=&quot;City\/Town, State&quot; \r\n                    autocomplete=&quot;off&quot;\r\n                    data-provide=&quot;typeahead&quot;\r\n                    required=&quot;required&quot; \r\n                    autofocus\r\n                    \/&gt;\r\n                    &lt;span class=&quot;addQmark&quot;&gt;&lt;i class=&quot;iconic-question-mark&quot;&gt;&lt;\/i&gt;&lt;\/span&gt;\r\n            &lt;\/div&gt;\r\n            &lt;input type=&quot;hidden&quot;\r\n                name=&quot;h-address-&#x5B;% loop.count %]&quot;\r\n                id=&quot;h-address-&#x5B;% loop.count %]&quot;\r\n                value=&quot;&quot;\r\n                \/&gt;\r\n            &lt;\/div&gt;\r\n        &lt;\/div&gt; &lt;!-- \/span11 --&gt;\r\n<\/pre>\n<p>\nThe entire template can be seen here on <a class=\"vital-link\" href=\"https:\/\/github.com\/aibistin\/TravelTime\/blob\/master\/views\/travel_time_quick.tt\" title=\"Travel Time Quick Form Page\" target=\"_blank\">GitHub<\/a>.<br \/>\nThe highlighted fields are the ones that are pertinent to the activation of the <a href=\"http:\/\/getbootstrap.com\/2.3.2\/javascript.html#typeahead\" title=\"Bootstrap 2 Typeahead\" target=\"_blank\">Bootstrap Typeahead<\/a>.<br \/>\nIn order to customise the Bootstrap Typeahead, I found this very useful <a href=\"http:\/\/fusiongrokker.com\/post\/heavily-customizing-a-bootstrap-typeahead\" title=\"Fusion Grokker Typeahead\" target=\"_blank\">website<\/a> by FusionGrokker, for which I am thankful (You could also check out the <a href=\"http:\/\/jqueryui.com\/autocomplete\/\" title=\"jQuery Autocomplete\" target=\"_blank\">jQuery docs<\/a> for the original concept).\n<\/p>\n<p>\n<a class=\"vital-link\" href=\"https:\/\/github.com\/aibistin\/TravelTime\/blob\/master\/public\/javascripts\/city-states.js\" title=\"City States Typeahead JS\" target=\"_blank\">Here is my JavaScript<\/a> to implement the Typeahead Ajax call.\n<\/p>\n<p class=\"code-heading\">The jQuery<\/p>\n<p><span class=\"code-description\">Excerpt from city-states.js<\/span><\/p>\n<pre class=\"brush: css; auto-links: false; collapse: false; first-line: 1; gutter: true; highlight: [4,8,11,15,19,21,33,34]; light: false; pad-line-numbers: false; smart-tabs: false; tab-size: 4; title: City State County Typeahead  city-states.js; toolbar: true; notranslate\" title=\"City State County Typeahead  city-states.js\">\r\nvar hiddenId;\r\n\/\/ Get the hidden address field associated with the current\r\n\/\/ address field\r\n$('.cityStatesTypeahead').bind('focus',  function(){\r\n   hiddenId =  $(this).attr('id'); \r\n});\r\n\r\n$(&quot;.cityStatesTypeahead&quot;).typeahead({\r\n  items: 10, \r\n  minLength : 3, \r\n  source:  function(query, process) {\r\n      \/\/Call Perl App to find the sorted list of City, States and Counties\r\n      return searchForPlaces(query, process);\r\n },  \r\n  highlighter: function(item){\r\n    return highLightSelect(item);\r\n},  \r\n\r\nmatcher: function () { return true; }, \r\n \r\nupdater: function (item) {\r\n    return updateField(item);\r\n}, \r\n\r\n});\r\n\/\/ Ajax call to Perl Dancer Script, which returns an Array Ref\r\n\/\/ of sorted City, State and County data.\r\nvar debounceWait = 100;\r\n\/\/ Use Underscore JS function '_debounce' to ensure that the\r\n\/\/ search waits for specific number of milliseconds before running again.\r\nvar cityStates = {};\r\nvar cityNames = &#x5B;];\r\nvar searchForPlaces = _.debounce(function( query,  process ){\r\n    $.post(&quot;\/city_states&quot;,{ find : query}, function(data){\r\n    cityStates = {};\r\n    cityNames = &#x5B;];\r\n        var counter = 0;\r\n        _.each( data.city_states,  function( item,  ix,  list ){\r\n        item.label = item + '-' + (counter++);\r\n         \/\/ console.log('Got this item from AJAX : ' + item);\r\n        cityStates&#x5B;item.label] = {\r\n                city : item&#x5B;0],   \r\n                state : item&#x5B;1],  \r\n                county : item&#x5B;2]\r\n        };\r\n        \/\/add selected items to diaplay array\r\n        \/\/ console.log('Add this to the array ' + item.label);\r\n        cityNames.push(item.label);\r\n\r\n    });\r\n    \/\/ Let Bootstrap and jQuery process the list\r\n    \/\/ for display in the input box\r\n    process( cityNames );\r\n});\r\n},  debounceWait);\r\n\r\n\/\/Highlighter Function\r\nvar highLightSelect = function(item){\r\n    \/\/ console.log(&quot;      Item inside highlighter &quot; + item);\r\n   var c = cityStates&#x5B;item];\r\n   return ''\r\n       + &quot;&lt;div class='typeahead_wrapper'&gt;&quot;\r\n       + &quot;&lt;div class='typeahead_labels'&gt;&quot;\r\n       + &quot;&lt;div class='typeahead_primary'&gt;&quot; + c.city + ', ' + c.state + &quot;&lt;\/div&gt;&quot;\r\n       + &quot;&lt;div class='typeahead_secondary'&gt;&lt;strong&gt;County: &lt;\/strong&gt;&quot;  + c.county + &quot;&lt;\/div&gt;&quot;\r\n       + &quot;&lt;\/div&gt;&quot;\r\n       + &quot;&lt;\/div&gt;&quot;;\r\n};\r\n\r\n\/\/ Updater Function\r\n\/\/ Add the required data into the input field\r\nvar updateField = function(item){\r\n   var c = cityStates&#x5B;item];\r\n   \/\/Hidden field will contain all the valuable data\r\n    $( &quot;#h-&quot; + hiddenId ).val( c.city + ',' + c.state + ',' + c.county );\r\n   \/\/This is the data for display on input box\r\n   return c.city + ', ' + c.state + &quot;  County: &quot; + c.county ;\r\n};\r\n\r\n\/\/      END BOOTSTRAP TYPEAHEAD\r\n\r\n\r\n<\/pre>\n<p>\nHave a look at line 34 for the actual Ajax call to the Perl <a class=\"vital-link\" href=\"https:\/\/github.com\/aibistin\/TravelTime\/blob\/master\/lib\/TravelTime.pm\" title=\"Dancer2 TravelTime.pm\" target=\"_blank\">module<\/a>. It sends a request to TravelTime.pm&#8217;s &#8216;\/city_state&#8217; route. As the Typeahead attribute &#8216;minLength&#8217; is set to 3, it passes at least the first three letters of the requested City to the Dancer2 application. The city_states database is then searched for a city beginning with this search string. The Dancer2 application will return a sorted list of these cities with their corresponding state and county names. The application can also accept two search strings separated by a comma. This will search the database for cities beginning with the first string and corresponding states beginning with the second string.<br \/>\n&#8220;city-states.js&#8221; receives this sorted list of cities, states and counties.<br \/>\nThe Typeahead displays (items: 10) items in the dropdown list.The &#8220;highLightSelect&#8221; highlighter function formats this list into a more readable format.<br \/>\nWhen an item is selected &#8220;theupdateField&#8221; populates the hidden fields.\n<\/p>\n<pre class=\"brush: css; auto-links: false; collapse: false; first-line: 75; gutter: true; light: false; pad-line-numbers: false; smart-tabs: false; tab-size: 4; title: Update hidden field; toolbar: true; notranslate\" title=\"Update hidden field\">\r\n\r\n $( &quot;#h-&quot; + hiddenId ).val( c.city + ',' + c.state + ',' + c.county );\r\n\r\n<\/pre>\n<p class=\"important\">\nMore details of what is happening in TravelTime.pm will be left for another post.<br \/>\nHave a look at the <a class=\"vital-link\" href=\"http:\/\/www.carryonmoving.net\/quick\" title=\"CarryOnMoving.net\" target=\"_blank\">TravelTime App<\/a> in action.<br \/>\nI hope that this blog post may useful to some developer out there.\n<\/p>\n<p>\n<a href=\"https:\/\/twitter.com\/aibistin\" class=\"twitter-follow-button\" data-show-count=\"false\" >Follow @aibistin<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is a demonstration of how I implemented an Ajax call to a Perl Dancer2 Application using jQuery and the Bootstrap Typeahead function. As part of my TravelTime App , I wanted to create and easy way to select the start and end locations using the jQuery Autocomplete component. Bootstrap 2 has its own version [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[25,9,7,21,24,17,20,22,15],"class_list":["post-389","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-ajax","tag-bootstrap","tag-dancer","tag-dancer2","tag-javascript","tag-jquery","tag-perl","tag-templatetoolkit","tag-typeahead"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.aibistin.com\/index.php?rest_route=\/wp\/v2\/posts\/389","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.aibistin.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.aibistin.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.aibistin.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.aibistin.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=389"}],"version-history":[{"count":41,"href":"https:\/\/www.aibistin.com\/index.php?rest_route=\/wp\/v2\/posts\/389\/revisions"}],"predecessor-version":[{"id":562,"href":"https:\/\/www.aibistin.com\/index.php?rest_route=\/wp\/v2\/posts\/389\/revisions\/562"}],"wp:attachment":[{"href":"https:\/\/www.aibistin.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=389"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.aibistin.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=389"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.aibistin.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=389"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}