{"id":95,"date":"2009-11-16T15:32:16","date_gmt":"2009-11-16T23:32:16","guid":{"rendered":"http:\/\/www.dhtmlx.com\/blog\/?p=95"},"modified":"2023-05-09T12:29:57","modified_gmt":"2023-05-09T09:29:57","slug":"using-dhtmlxcombo-for-searching-locations-with-google-maps","status":"publish","type":"post","link":"https:\/\/dhtmlx.com\/blog\/using-dhtmlxcombo-for-searching-locations-with-google-maps\/","title":{"rendered":"Using dhtmlxCombo for Searching Locations with Google Maps"},"content":{"rendered":"<p>Recently I was faced with having to add a location search mechanism to our application. My given task was short and clear: &#8220;We need to enter a few chars here and see the list of matching locations there\u2026&#8221; I nodded, made myself a cup of coffee, and started thinking about how I was going to do it.<\/p>\n<p>It was easy to guess that the task itself could be split into two parts: to build a component with combo box behavior and to invent a geocoding service to search locations by the text entered in the combo box. Fortunately for me, we already have a flexible <a href=\"https:\/\/dhtmlx.com\/docs\/products\/dhtmlxCombo\/\">dhtmlxCombo<\/a> component, so the first part didn\u2019t require any work on my part. There is also a set of free online geocoding services on the internet, so I&#8217;ve chosen <a href=\"https:\/\/developers.google.com\/maps\/?csw=1\">Google Maps API<\/a> for the second part.<\/p>\n<p><!--more--><\/p>\n<h4>Step 1 &#8211; Prepare dhtmlxCombo<\/h4>\n<p>If by chance you aren\u2019t familiar with the dhtmlxCombo component, it is a select-like control that can automatically fetch items when a user types it in. What\u2019s more important, the standard behavior of finding items can be replaced with user-defined functions by attaching it to the onDynXLS event. The event handler receives text entered into the combo, and that\u2019s what we need. <\/p>\n<p>The &#8220;initCombo&#8221; function will be called after the page load.<\/p>\n<p>First we create the combo box in HTML element with id=&#8221;comboID&#8221; and set its width to 200px. The next line adds autocomplete features to the combo. The first parameter enables them, and the next one sets up the URL of the page where to look for the results. Since a geoservice will be used instead, I just entered &#8220;http:\/\/&#8221;. The last parameter enables or disables caching. Google geocoder has its own cache, that\u2019s why I disabled this one.<\/p>\n<p>Finally, we attach the onDynamicLoad function to the onDynXLS event. The handler returns &#8220;false&#8221; in order to stop default search functionality.<\/p>\n<h4>Step 2 &#8211; Google Geocoder<\/h4>\n<p>Geocoding itself is a mechanism of converting geographical data (in our case, address) into geographical coordinates. Google&#8217;s GClientGeocoder class makes it possible to search locations by address and receive a collection of location objects as a result. Each of them contains coordinates and a proper location address- i.e., all the information we need. It&#8217;s free with just a few limitations. You&#8217;ll be prompted to enter a site name for which API will be used. For test purposes, &#8220;http:\/\/localhost&#8221; is good enough.<\/p>\n<p>So briefly, here&#8217;s how it works. We create the GClientGeocoder class instance and call the getLocations method which needs only 2 parameters: the text to search location by and the reference to the function that receives the result.<\/p>\n<p>Seems easy. Now we just need to bring it all together.<\/p>\n<h4>Step 3 &#8211; Getting Things to Work<\/h4>\n<p>Well, here&#8217;s the strategy: After dhtmlxCombo tries to fetch items the first time, GClientGeocoder is created, and all data requests are done through it. The geocoder callback function that receives locations becomes responsible for putting them into the combo. That\u2019s it.<\/p>\n<p><strong>Some comments:<\/strong><\/p>\n<p>The &#8220;location&#8221;, returned by the geocoder, contains a collection of Placemark objects. Each of them represents one location. In the code above, coordinates of the location go to the combo item\u2019s value. The address info goes to the item\u2019s text. The black magicinvolves the section between and including the lines with &#8220;enableFilteringMode&#8221;. <\/p>\n<p>We need these lines for a reason that is not obvious. When filtering mode is ON, any action that opens the combo causes the onDynXLS event to be fired. We need to open the combo, but we are already in an onDynXLS event. The easiest way to prevent universal chaos in this case is to disable filtering before opening the combo and then enabling it again after the combo is open.<\/p>\n<h4>Instead of Conclusion<\/h4>\n<p>With approximately 20 lines of JavaScript code, we\u2019ve managed to create a tool that takes user input, asks Google the meaning of the input, and shows a list of locations with real coordinates that the user is probably interested in. Christopher Columbus would\u2019ve killed for that. I spent a bit over an hour and got it for free :) Sometimes I really love my job.<\/p>\n<p><small>Posted by Paul Smirnov<\/small><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Recently I was faced with having to add a location search mechanism to our application. My given task was short and clear: &#8220;We need to enter a few chars &#8230;<\/p>\n","protected":false},"author":4,"featured_media":3456,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[71,1],"tags":[33,14],"class_list":["post-95","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","category-uncategorized","tag-all-posts","tag-tips"],"_links":{"self":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/95","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/comments?post=95"}],"version-history":[{"count":2,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/95\/revisions"}],"predecessor-version":[{"id":8621,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/95\/revisions\/8621"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/media\/3456"}],"wp:attachment":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/media?parent=95"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/categories?post=95"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/tags?post=95"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}