First off, thanks for this library, it's just great.
I wonder whether it's possible to catch an event to show a spinner or something or the screen in the meantime the browser is waiting for the server to reply.
Thanks!
Adding support for something like this has been brought up previously (see https://github.com/twitter/typeahead.js/issues/130#issuecomment-15446455). This is one of the next things I'll be working on.
@jharding thanks, that would be brilliant!
I was able to show the progress spinner with the following:
css:
.typeahead {
background-color: #fff;
background-repeat: no-repeat;
background-position: 98%;
}
javascript:
typeaheadCtrl = $('.typeahead').typeahead({ name: 'countries', prefetch: '../data/countries.json' });
typeaheadCtrl.on('typeahead:initialized', function (event, data) {
// After initializing, hide the progress icon.
$('.tt-hint').css('background-image', '');
});
// Show progress icon while loading.
$('.tt-hint').css('background-image', 'url("/images/ajax-loader.gif")');
I overcome this situation by making little changes,
add these lines inside var Transport = function() {
this.xhrSending = o.xhrSending || function () { };
this.xhrDone = o.xhrDone || function () { };
And i changed _sendRequest function of Transport object like this
_sendRequest: function (url) {
var that = this, jqXhr = pendingRequests[url];
if (!jqXhr) {
incrementPendingRequests();
that.xhrSending(); // modification 1
jqXhr = pendingRequests[url] = $.ajax(url, this.ajaxSettings)
.always(always);
}
return jqXhr;
function always() {
decrementPendingRequests();
pendingRequests[url] = null;
if (that.onDeckRequestArgs) {
that._get.apply(that, that.onDeckRequestArgs);
that.onDeckRequestArgs = null;
}
that.xhrDone(); // modification 2
}
}
And if we get to how you can implement it,
As you can see in remote object there are xhrSending and xhrDone functions
var $ttHint = $(".tt-hint");
$txtAc.typeahead([
{
minLength: 3,
remote: {
url: '/Search?q=%QUERY',
xhrSending: function () {
if (!$ttHint.length) {
$ttHint = $(".tt-hint");
}
//add loading class to tt-hint element when request sending.
$ttHint.addClass("loading");
},
xhrDone: function () {
if (!$ttHint.length) {
$ttHint = $(".tt-hint");
}
//remove loading class from tt-hint element when response arrived.
$ttHint.removeClass("loading");
}
},
name : 'searchResults'
header: '<h3 class="ac-header">Search Results</h3>',
template: document.getElementById("acTemplate").innerHTML,
valueKey: 'title',
engine: Handlebars,
allowDuplicates : true
}
]);
There is loading css class
// added ! important because typeahead adding some styles to tt-hint that overrides background property.
.tt-hint.loading {
background: transparent url('/images/ajaxloading.gif') no-repeat scroll right center content-box !important;
}
@umitakkaya :+1:
:+1:
I used
remote:{
url: 'yourjsonlocation',
beforeSend: function(xhr){
showSpinner();
},
filter: function(parsedResponse){
hideSpinner();
return parsedResponse;
}
}
Really solved my problem. _Phew_
Wouldn't it be cleaner to just fira a for example "typeahead:loading" event (and an event to indicate that it isn't loading anymore?) This way you can add an default implementation of a spinner but also use custom handling.
Has there been any progress regarding this? It's a requested feature for the project I'm working on, but before I hack something together, I wanted to check if this was going to be implemented in the near future anyway.
Thanks for the great plugin!
I'm not aware of anything.
:+1:
As we don't have events dispatching in Bloodhound for now, it's possible to monkey-patch its "transport" layer to be notified of Ajax requests:
var _transport = myBloodhoundInstance.transport, _transportGet = _transport.get;
myBloodhoundInstance.transport.get = function (url, ajax, handleRemoteResponse) {
displayLoadingProgress();
_transportGet.apply(_transport, arguments);
};
And we can hide the loading progress in the filter function, as described upper in this Issue comments.
Hopefuly 0.10.3 will include support for this. In the meantime I've incorporated the handler in Svakinn's fork of 0.9.3.
Works well enough for now, although some of his other updates look awesome too.
Has there been any updates on this? I use typeahead in a lot of areas, so a global solution would be awesome.
Just to elaborate on @b3ckstage 's solution, this is actually quite clean--no patching or forking of anything required:
Since the remote configuration object allows you to pass parameters through to the jQuery ajax object, all you have to do is pass a beforeSend and a complete callback, and you find out whenever the AJAX call begins and ends. I'm doing this, for example, which is slightly different from what he did:
var groupPrincipals = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: '/api/groupprincipals?search=%QUERY',
filter: function(parsedResponse){
return parsedResponse['groupPrincipals'];
},
ajax: {
beforeSend: function(){ Ember.Logger.info("beforeSend callback called!"); },
complete: function(){ Ember.Logger.info("complete callback called!"); }
}
}
});
And it works fine (so far) in stock 0.9! I agree it would be nice if bloodhound emitted its own events, but as right now it doesn't emit _any_ events, adding events just for this seems like overkill, if the above facility to hook into the jQuery ajax object's callbacks works fine. Or if there's something I'm missing with the above solution, do please mention it!
@SphtKr great solution. that worked, it would also be good though if the typeahead had a flag to enable a spinner on its own though.
This one worked for me:
var twitterAccounts = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: '/whatever/twitter/?q=',
replace: function(url, query){
Ember.$('.tt-hint').css('background-image', 'url("/res/AjaxLoader.gif")');
Ember.$('.tt-hint').css('background-repeat', 'no-repeat');
return url+encodeURIComponent(query);
},
filter: function(parsedResponse){
Ember.$('.tt-hint').css('background-image', '');
return parsedResponse;
}
},
limit: 10
});
In v0.11 (it's currently a WIP), I've added the follow events:
typeahead:asyncrequesttypeahead:asynccanceltypeahead:asyncreceiveThe goal of these events is to solve the issues brought up in this thread – basically add hooks for async data operations.
Great! Thank you very much!
Thank you very much for your hard work!
:+1:
Any news?
@SphtKr 's way is indeed a nice clean way to implement it at this point, thank you for that.
Any updates? I'm also interested in a clean way to implement a loading indicator.
hint wasn't a good solution in my situation, i set the background image of my typeahead input
in my css:
.loading {
background: transparent url('/img/loading.gif') no-repeat scroll right center content-box;
background-size: contain;
}
and in my js:
$('.typeahead').addClass('loading');
$('.typeahead').removeClass('loading');
at my specifically appropriate locations
where can I download v0.11, still in github showing 0.10.5 version only, can any one provide link
@pottabathini v0.11 is not yet released, see #1068
@pottabathini v0.11.1 is out now.
None of these (ajax prefilters, new 0.11.0 custom events) work during prefetch. Is there anyway to show loading while prefetch initializes?
For the all dropping here agian:
// Instantiate the Typeahead UI
$('.typeahead').typeahead(null, {
displayKey: 'value',
limit: 10,
source: creditors.ttAdapter()
})
.on('typeahead:asyncrequest', function() {
$('.Typeahead-spinner').show();
})
.on('typeahead:asynccancel typeahead:asyncreceive', function() {
$('.Typeahead-spinner').hide();
});
Arrived late to the party, but you can combine @rajanrawal solution with some CSS3 animations and glyphicons and come up with a nice little loader:
.glyphicon-refresh-animate {
-animation: spin .7s infinite linear;
-webkit-animation: spin2 .7s infinite linear;
}
@-webkit-keyframes spin2 {
from { -webkit-transform: rotate(0deg); }
to { -webkit-transform: rotate(360deg); }
}
@keyframes spin {
from { transform: scale(1) rotate(0deg);}
to { transform: scale(1) rotate(360deg); }
}
I notice that when the search returns nothing, or when you type something that returns nothing/something but then remove the text, the spinner doesn't disappear.
For input with loading icon placed on the right while typing. Can use the code below.
.input-loading {
background-color: #ffffff;
background-image: url("http://loadinggif.com/images/image-selection/3.gif");
background-size: 25px 25px;
background-position:right center;
background-repeat: no-repeat;
}
$('.typeahead').typeahead(null, {
displayKey: 'value',
limit: 10,
source: creditors.ttAdapter()
}).on('typeahead:asyncrequest', function() {
$('.typeahead').addClass('input-loading');
})
.on('typeahead:asynccancel typeahead:asyncreceive', function() {
$('.typeahead').removeClass('input-loading');
});
@DrBenton Your solution doesn't seem to work for me. Any ideas?
Hi everybody, if anybody nowaday have a same problem, I resolve with this:
Here an example.
$('.typeahead').typeahead(
{
hint: true,
highlight: true,
minLength: 1,
//maxItem: 5,
},
{
name: 'usuario',
displayKey: 'nombre',
source: listadoEstudiantes.ttAdapter(),
templates: {
empty: function() {
var string = '<p class="tt-suggestion-link tt-notfound"> Ninguna coincidencia<p>';
return string;
},
pending: function(data) {
console.log('cargando listado');
var string = '<p class="tt-suggestion-link tt-notfound"> Cargando listado... <img src="img/loading_2.gif"> <p>';
return string;
},
suggestion: function(data) {
var string = '<p class="tt-suggestion-link">' + data + '<p>';
return string;
}
},
}
);
Just change "img/loading_2.gif" for your own directory and loader image.
Most helpful comment
For the all dropping here agian: