Skip to content

Instantly share code, notes, and snippets.

@lbrenman
Last active January 4, 2016 15:35
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save lbrenman/d2f0c618c7670e6435ed to your computer and use it in GitHub Desktop.
Save lbrenman/d2f0c618c7670e6435ed to your computer and use it in GitHub Desktop.
Appcelerator Titanium Search Autocomplete
Appcelerator Autocomplete Search
A server side search for customers, accounts, inventory, products, etc… in a mobile application is a very common operation. A typical UI for this operation is to allow the user to enter the search text and press a search button or the enter key on the on screen keyboard, as shown below. Then a search is performed, perhaps via a web service call to a server search API, and the retrieved results are displayed in a list for the user to select from the search results, as shown:
This is accomplished in Titanium by adding a event listener on the search TextField and listen for the return event as follows:
$.searchTF.addEventListener('return', function(e){
processInput();
});
In the above UI, you would also add an event listener on the search button to the right of the search TextField.
One way to make the mobile application more useful and responsive is to enhance this search operation by implementing autocomplete. As the user types, searches are performed using the entered text, instead of waiting for the user to finish entering the entire search text. You experience this every time you use Google or Bing to search the web, as shown below:
This is easily accomplished in Titanium by also listening for the change event on the TextField as follows:
$.searchTF.addEventListener(‘change’, function(e){
processInput();
});
Now, as the user enters text, search results are fetched on each key entered as shown below:
One down side of implementing autocomplete is that you are now making many more calls over the network and taxing your back end more. This must be weighed against the increased adoption of the application due its increased usefulness.
One tip to reduce the number of web service calls made while still providing the autocomplete feature is to only make the web service call when the user pauses typing. This prevents extra web service calls from being made if the user backs up or changes the input text. This can be accomplished using a JavaScript timer to implement a delay before making the web service call. If the user continues typing before the delay time is reached, then the timer can be reset as follows:
var waitForPause, pauseDelay = 1000;
$.wordTF.addEventListener('change', function(e){
clearTimeout(waitForPause);
waitForPause = setTimeout(processInput, pauseDelay);
});
Next time you implement a server search feature in your application try the autocomplete and see for yourself how your application will appear more responsive and you will find yourself using this feature more and more.
The code from this post can be downloaded here.
".container": {
backgroundColor:"white"
},
"Label": {
width: Ti.UI.SIZE,
height: Ti.UI.SIZE,
color: "#000"
},
"TextField": {
left: "10",
width: Ti.UI.FILL,
color: "black",
clearButtonMode:Titanium.UI.INPUT_BUTTONMODE_ONFOCUS,
//returnKeyType: Titanium.UI.RETURNKEY_DONE,
autocapitalization:Ti.UI.TEXT_AUTOCAPITALIZATION_NONE,
autocorrect: false
},
"TableViewRow": {
height: "40",
hasChild: true
},
"TableView": {
height: Ti.UI.FILL
}
var waitForPause, pauseDelay = 1000;
$.infoButton.addEventListener('click', function(e) {
alert("Autocomplete demo");
});
$.wordTV.addEventListener('click', function(e) {
Ti.API.info("index: $.wordTV.addEventListener(click)");
alert("row clicked, word = "+e.row.word);
});
function resetTable(table) {
Ti.API.info("index: resetTable()");
var rd = [];
table.data = rd;
}
function processInput(){
Ti.API.info("index: processInput()");
if($.wordTF.value=="" || $.wordTF.value==null) {
resetTable($.wordTV);
} else {
getWords($.wordTF.value, {
success: function(e) {
Ti.API.info('Recieved data = '+e);
loadTable(e, $.wordTV);
},
error: function(e) {
Ti.API.info('Error = '+e);
alert("No network or server not available. Please try again.");
}
});
}
}
$.wordTF.addEventListener('change', function(e){
Ti.API.info("index: $.wordTF.addEventListener(change)");
//processInput();
clearTimeout(waitForPause);
waitForPause = setTimeout(processInput, pauseDelay);
});
$.wordTF.addEventListener('return', function(e){
Ti.API.info("index: $.wordTF.addEventListener(change)");
processInput();
});
function loadTable(e, table) {
Ti.API.info("index: loadTable()");
var reply = JSON.parse(e);
var rows = [];
var i = 0;
Ti.API.info("index: reply = "+reply);
if(reply.searchResults.length>0){
_.each(reply.searchResults, function(item) {
rows.push(Alloy.createController('wordRow', {
word: item.word,
}).getView());
});
}
else {
alert("No words found.");
}
//$.wordTV.setData(rows);
table.setData(rows);
}
function getWords(text, o){
Ti.API.info("getWords() - text = "+text);
if(Titanium.Network.networkType == Titanium.Network.NETWORK_NONE){
Ti.API.info("markit: ondemand() - No Network");
if (o.error) { o.error("No Network"); };
return;
}
var xhr = Titanium.Network.createHTTPClient({
onload: function() {
if (o.success) { o.success(this.responseText); };
},
onerror: function(e) {
if (o.error) { o.error("Error with wordnik API"); };
},
timeout: 10000,
});
xhr.open("GET", "http://api.wordnik.com/v4/words.json/search/"+text+"?api_key=3fc30fd2caff363468b3a4c28675145127f8640f06715d94f");
xhr.send();
};
$.index.open();
<Alloy>
<Window class="container" layout="vertical">
<View height="40" backgroundColor="black">
<Label color="white">Autocomplete Demo</Label>
<Button id="infoButton" right="10" color="white">i</Button>
</View>
<View layout="vertical">
<TextField id="wordTF" hintText="Enter word" top="20" />
<TableView id="wordTV" top="20"/>
</View>
</Window>
</Alloy>
var args = arguments[0] || {};
//Ti.API.info("row created, args.name = "+args.name);
$.wordRow.word = args.word;
$.wordLbl.text = args.word;
<Alloy>
<TableViewRow class="wordTVR">
<Label id="wordLbl" width="80%" left="10"/>
</TableViewRow>
</Alloy>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment