How to Autocomplete Email Addresses in Apps Script

When composing Gmail conversations, the auto-complete feature allows us to see our matching personal contacts as we type and quickly make our contact selections. This time-saving feature can be duplicated when creating Google Apps Script applications. For instance, if you design an application that requires sending emails, you can leverage this auto-complete feature by using a personal contact list.

Defining the Requirements

By observing the behavior while composing Gmail conversations, we can define the requirements of our application.

1. As the user begins typing, a list of matches based on first and last name and email address need to appear under the text box. In other words, the user can begin typing the contacts first name, last name, or their email address.

2. If the desired contact email is listed at the top of the matching list, the user can simply press the Enter key to select it.

3. Another option is to click on any of the contacts in the list.

4. Just in case the user would like to enter an email that is not in their contact list, they may enter the email and press the Enter key.

As an added feature if the email is not formatted correctly, then the invalid email is ignored and not selected. For our application when emails are selected, they will be compiled in a separate list on the right where only the email address is stored. If an email is selected by accident, the user can remove the email by clicking on it.

Designing the Application

The application was designed to mimic the behavior of composing Gmail messages. By doing so, the application avoided the use of buttons, providing an improved user experience.

1. Apps Script Services

The Apps Script’s Spreadsheet Service was used to store a user’s contact data. The Ui Service provided the application interaction with the user, and the Contacts Service was leveraged to gather all the user’s contacts. You may apply a Google Apps domain only filter for the contacts by changing the global variable to “true” in the script.

2. Visualize the Layout

Before writing code, the layout was sketched out to include a text box, some space beneath to list matches, and an area to the right to display the selected emails.

3. Choose your widgets

A text box widget was chosen to allow email entry, and two open list boxes were leveraged to display contact matches and selected emails. List boxes provided the use of click handlers to process email selections.

4. Challenges

To mimic the Gmail auto-complete behavior, the text box needed the ability to handle both keystrokes and a pressed Enter key. To accomplish this, a KeyUpHandler calls a function to identify contact matches via a search. The same function used an e.parameter.keyCode == 13 condition to determine when the enter key is pressed.

[php]<span>//create text box for auto-complete during email lookup in left grid</span>
var textBox = app.createTextBox().setName(<span>’textBox'</span>)
var tBoxHandler = app.createServerKeyHandler(<span>’search_'</span>);
tBoxHandler.addCallbackElement(textBox); textBox.addKeyUpHandler(tBoxHandler);
…function search_(e){ var app = UiApp.getActiveApplication(); app.getElementById(<span>’list'</span>).clear();
var searchKey = new RegExp(e.parameter.textBox,<span>"gi"</span>); 
<span>if</span> (searchKey == "") app.getElementById(<span>’textBox'</span>).setValue(<span>”</span>);
var range = sheetOwner.getRange(1, 1, sheetOwner.getLastRow(), 2).getValues(); var listBoxCount = 0;
var firstOne = <span>true</span>; <span>for</span> (var i in range){  
// if first/last name available, display name and email address <span>if</span>
(range[i][0].search(searchKey) != -1 || range[i][1].search(searchKey) != -1){ <span>if</span>
(range[i][0].toString()){ app.getElementById(<span>’list'</span>).addItem(range[i][0].toString()+ 
‘ .. ‘+range[i][1].toString(), range[i][1].toString()); 
var listBoxCount = listBoxCount + 1; } <span>else</span> { // else just display the email address 
(<span>’list'</span>).addItem(range[i][1].toString()); var listBoxCount = listBoxCount + 1; }  
<span>if</span> (firstOne) var firstItem = range[i][1].toString(); var firstOne = <span>false</span>;
} }  
// set the top listbox item as the default <span>if</span> (listBoxCount &gt; 0) app.getElementById(<span>’list’
.setItemSelected(0, true);
// if enter key is pressed in text box, assume they want to add</span> <span>// the email that’s not in the list</span> <span>if</span>
(e.parameter.keyCode==13 &amp;&amp; listBoxCount &lt; 1 &amp;&amp; searchKey !== <span>""</span>) { …[/php]

As this application shows, Apps Script is very powerful. Apps Script has the ability to create applications which allow you to integrate various Google services while building complex user interfaces.


You can find Dito’s Email Auto-Complete Script here. To view a video demonstration click here. You can also find Dito Directory on the Google Apps Marketplace.

Samsung Bada and BlackBerry 6 platforms now supported by the Maps API v3

From the day the Maps API v3 was first announced we placed a special focus on it’s suitability for use on mobile browsers. Being able to develop a single maps application that works across all major desktop browsers and also on mobile devices is a key benefit of the Maps API. We are keen to make Maps API applications as accessible as possible, which is why we’re always excited to test new devices to determine if they meet our requirements for support.

Today we are therefore happy to welcome Samsung Bada and BlackBerry 6 touchscreen devices such as the Samsung Wave family and BlackBerry Torch 9800 to the fold. The full feature set of Maps API v3 is now available to users of these devices. We hope that as mobile browsers continue to improve across platforms we can continue to add new devices to our list of those we support.

Generalising geographic data

It often happens that the dataset you have is very detailed and hence very large. Displaying such volume of data in online mapping applications (eg. as KML on Google Map) is out of the question. The only alternative is to reduce the number of vertices to reduce the overall size of the file (ie. generalise the data). There is an excellent free online tool to do just that and surprisingly it works much better than commercial software that costs a fortune. It is called MapShaper.

It accepts spatial data in shapefile format only. It is an online service and you can upload files up to 80MB in size for processing. There are 3 generalisation algorithms to choose from. Activation of generalisation process itself is as simple as moving a slider “left to right” (from 0% reduction to 99%) – the result is visible on the screen instantaneously. Another great feature of the tool is that you can view original file underneath the generalised version to assess the quality of the process but also to pick the right generalisation level for your requirements.

Processed files can be downloaded back in either shp or EPS format (so it’s is also a great tool for straight conversion of files from shp format into EPS format, for use with vector graphics software!). There is simple edit functionality as well so you can add/delete vertices manually, if required. Generalisation process preserves topology so boundaries of adjoining polygons are generalised in an identical fashion – that is, they still “fit” perfectly. All in all, MapShaper is very straightforward to use.

File size still counts when performance of online mapping tool is the objective. For example, it will not be possible to display electoral boundaries as a single, full resolution file in Google Map application. But original 25MB shapefile can be reduced to just a few hundred KB using MapShaper tool, and then even further by converting shp to gzipped KMZ format. Here is an example of a Google Map application that uses both, full resolution data for close-ups and generalised version for whole of the country view: Australian elections map (work in progress!).