I have a simple CFC returning username and Id number. The CFC works and has been tested with the browser to return the JavaScript results. No issues. This is the output:
{
"COLUMNS":["USERNAME","ID"]
,"DATA":[ ["jclark","001650472"]
,["jclark1","000086949"]
,["jclarke","002386440"]
]
}
When I try using it with Twitter Typeahead, I get no results back. in firebug I can see the successful response from the CFC/JS however I get an error JS error once that happens.
return this.name.toLowerCase();
This.name is undefined
Seems like my data isn't making it back from the CFC correctly.
Here is my js/html
<script>
$(document).ready(function () {
$('#add_user').typeahead({
source: function (query, process) {
var $url = "/glv/_includes/gl_data.cfc?method=search_accounts_by_username&returnformat=json&username=" + query;
var $datas = new Array;
$datas = [""];
$.ajax({
url: $url,
dataType: "json",
type: "GET",
success: function (data) {
$.map(data, function (data) {
var group;
group = {
id: data.ID,
name: data.USERNAME,
toString: function () {
return JSON.stringify(this);
//return this.variable;
},
toLowerCase: function () {
return this.name.toLowerCase();
},
indexOf: function (string) {
return String.prototype.indexOf.apply(this.name, arguments);
},
replace: function (string) {
var value = '';
value += this.name;
if (typeof (this.name) != 'undefined') {
value += ' <span class="pull-right muted">';
//value += this.name;
value += '</span>';
}
return String.prototype.replace.apply('<div style="padding: 10px; font-size: 1em;">' + value + '</div>', arguments);
}
};
$datas.push(group);
});
process($datas);
}
});
},
property: 'username',
items: 10,
minLength: 2,
updater: function (item) {
var item = JSON.parse(item);
$('#id').val(item.id);
$('#add_user').val(item.name);
return item.name;
}
});
});
</script>
<div class="span9">
<h1>Administration</h1>
<hr>
<h3>Add New User</h3>
<div class='search'>
<form class="form-search">
<input type="text" class="input-medium search-query" placeholder="Username" data-provide="typeahead" id="add_user" name="add_user" autocomplete="off">
<button type="submit" class="btn">Search</button>
</form>
</div>
</div>
Update - After some discussion in chat we were able to get a working prototype. Tony posted his working code in a separate answer. See chat for details.
Okay, here is a self-contained test script to hopefully show you what is going on. Browse to this using Google Chrome and open up the JavaScript console. It will allow you to expand and collapse the JavaScript objects so you can see their contents. This is not a complete solution, I am merely showing you how to breakdown the JSON data to hopefully allow you to migrate it into your code.
The first part of the code is copied from the tatiyants.com example. I needed to see the format of map
and states
. You will see these in the console.
Next I took your sample JSON and attempted to get it in the same format for map
and usernames
that you were using in your code. I renamed the variable in the $.each
loop stuff
to avoid confusion and hopefully shed some light on what is happening.
<html>
<head>
<title>Test</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>
/* Example from http://tatiyants.com/ */
var states = [];
var map = {};
var data = [
{"stateCode": "CA", "stateName": "California"},
{"stateCode": "AZ", "stateName": "Arizona"},
{"stateCode": "NY", "stateName": "New York"},
{"stateCode": "NV", "stateName": "Nevada"},
{"stateCode": "OH", "stateName": "Ohio"}
];
$.each(data, function (i, state) {
/* console.log(state); */
map[state.stateName] = state;
states.push(state.stateName);
});
console.log(map);
console.log(states);
/* Example from http://tatiyants.com/ */
console.log("\n--- end of tatiyants example ---\n");
/* My example from your code */
var usernames = [];
var map = {};
var sampleJSON = '{"COLUMNS":["USERNAME","ID"],"DATA":[ ["jclark","001650472"],["jclark1","000086949"],["jclarke","002386440"] ]}';
var parJSON = JSON.parse(sampleJSON);
$.each(parJSON.DATA, function (i, stuff) {
/* console.log(stuff); */
map[stuff[0]] = { "stuffid":stuff[1], "stuffname":stuff[0] };
usernames.push(stuff[0]);
});
console.log(map);
console.log(usernames);
/* My example from your code */
</script>
</head>
<body>
<h3>Test</h3>
<div>
</div>
</body>
</html>
When you browse to this file in Chrome the JavaScript console will show you first, the format from the example on tatiyants.com and then my example of your data. Obviously you can change the stuff
references to whatever you like once you understand it.
I would try taking my example and running it through the bootstrap typeahead and see if you can get it working with the static data. Once you do, then bring in your AJAX call and work on that data. I believe the key is to get the ColdFusion JSON format converted into the format that the typeahead is expecting.