Skip to content

Commit

Permalink
Switch up source api for more flexibility.
Browse files Browse the repository at this point in the history
  • Loading branch information
Jake Harding committed Aug 23, 2014
1 parent 2260576 commit 27c765e
Show file tree
Hide file tree
Showing 6 changed files with 210 additions and 152 deletions.
39 changes: 24 additions & 15 deletions src/bloodhound/bloodhound.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ var Bloodhound = (function() {
// constructor
// -----------

function Bloodhound(o) {
function Bloodhound(o, initialize) {
if (!o || (!o.local && !o.prefetch && !o.remote)) {
$.error('one of local, prefetch, or remote is required');
}
Expand All @@ -39,6 +39,9 @@ var Bloodhound = (function() {
// only initialize storage if there's a cacheKey otherwise
// loading from storage on subsequent page loads is impossible
this.storage = this.cacheKey ? new PersistentStorage(this.cacheKey) : null;

// if the initialize argument is truthy, kick off initialization
o.initialize && this.initialize();
}

// static methods
Expand All @@ -61,13 +64,13 @@ var Bloodhound = (function() {
__ttAdapter: function ttAdapter() {
var that = this;

return this.transport ? withBackfill : withoutBackfill;
return this.transport ? withAsync : withoutAsync;

function withBackfill(query, backfill) {
return that.get(query, backfill);
function withAsync(query, sync, async) {
return that.get(query, sync, async);
}

function withoutBackfill(query) {
function withoutAsync(query) {
return that.get(query);
}
},
Expand Down Expand Up @@ -187,24 +190,27 @@ var Bloodhound = (function() {

add: function add(data) {
this.index.add(data);
return this;
},

get: function get(query, backfill) {
get: function get(query, sync, async) {
var that = this, local;

local = this.sorter(this.index.get(query));

if (this.remote) {
local.length < this.remote.sufficient ?
this._getFromRemote(query, processRemote) :
this._cancelLastRemoteRequest();
// return a copy to guarantee no changes within this scope
// as this array will get used when processing the remote results
sync(this.remote ? local.slice() : local);

if (this.remote && local.length < this.remote.sufficient) {
this._getFromRemote(query, processRemote);
}

// return a copy to guarantee no changes within this scope
// as this array will get used when processing the remote results
return local.slice();
else if (this.remote) {
this._cancelLastRemoteRequest();
}

return local;
return this;

function processRemote(remote) {
var nonDuplicates = [];
Expand All @@ -220,7 +226,7 @@ var Bloodhound = (function() {
!isDuplicate && nonDuplicates.push(r);
});

backfill && backfill(nonDuplicates);
async && async(nonDuplicates);
}
},

Expand All @@ -230,14 +236,17 @@ var Bloodhound = (function() {

clear: function clear() {
this.index.reset();
return this;
},

clearPrefetchCache: function clearPrefetchCache() {
this.storage && this.storage.clear();
return this;
},

clearRemoteCache: function clearRemoteCache() {
this.transport && Transport.resetCache();
return this;
},

// DEPRECATED: will be removed in v1
Expand Down
14 changes: 6 additions & 8 deletions src/bloodhound/transport.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ var Transport = (function() {
this._send = o.transport ? callbackToDeferred(o.transport) : $.ajax;
this._get = o.rateLimiter ? o.rateLimiter(this._get) : this._get;

// eh, should this even exist? relying on the browser's cache may be enough
this._cache = o.cache === false ? new LruCache(0) : sharedCache;
}

Expand Down Expand Up @@ -78,12 +77,12 @@ var Transport = (function() {
}

function done(resp) {
cb && cb(null, resp);
cb(null, resp);
that._cache.set(fingerprint, resp);
}

function fail() {
cb && cb(true);
cb(true);
}

function always() {
Expand All @@ -103,24 +102,23 @@ var Transport = (function() {
get: function(o, cb) {
var resp, fingerprint;

cb = cb || $.noop;
o = _.isString(o) ? { url: o } : (o || {});

fingerprint = this._fingerprint(o);

this.cancelled = false;
this.lastReq = fingerprint;

// in-memory cache hit
if (resp = this._cache.get(fingerprint)) {
// defer to stay consistent with behavior of ajax call
_.defer(function() { cb && cb(null, resp); });
cb(null, resp);
}

// go to network
else {
this._get(o, cb);
}

// return bool indicating whether or not a cache hit occurred
return !!resp;
},

cancel: function() {
Expand Down
27 changes: 20 additions & 7 deletions src/typeahead/dataset.js
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ var Dataset = (function() {
},

update: function update(query) {
var that = this, canceled = false, results, rendered;
var that = this, canceled = false, ignoreSync = false, rendered = 0;

// cancel possible pending update
this.cancel();
Expand All @@ -241,23 +241,36 @@ var Dataset = (function() {
that.async && that.trigger('asyncCanceled', query);
};

results = (this.source(query, append) || []).slice(0, this.limit);
rendered = results.length;
this.source(query, sync, async);

this._overwrite(query, results);
// any calls to the sync callback from here on out should be ignored
// as they would have been done asynchronously
ignoreSync = true;

if (rendered < this.limit && this.async) {
this.trigger('asyncRequested', query);
that.trigger('asyncRequested', query);
}

function append(results) {
function sync(results) {
if (ignoreSync) { return; }

ignoreSync = true;
results = (results || []).slice(0, that.limit);
rendered = results.length;

that._overwrite(query, results);
}

function async(results) {
results = results || [];

// if the update has been canceled or if the query has changed
// do not render the results as they've become outdated
if (!canceled && rendered < that.limit) {
that.cancel = $.noop;
that._append(query, results.slice(0, that.limit - rendered));
rendered += results.length;
that._append(query, results.slice(0, that.limit - rendered));

This comment has been minimized.

Copy link
@sqs

sqs Jan 4, 2015

I think that the change in this hunk introduces a bug.

To determine how many suggestions (results) to append, all that matters is the limit and the number of suggestions currently rendered. This commit changes it so that rendered equals the number of suggestions currently rendered PLUS the ones that were returned by the async query but have not yet been rendered. Therefore if the query yields a lot of results, none will be rendered because this calculation treats them as though they've all already been rendered.

The rendered += results.length; line used to be after the call to _append (which seems to be correct) but now it is before.

I came across this while testing 0.11.0. With a limit of 5, if 3 results were returned, only 2 would display (because that.limit == 5 and rendered == results.length == 3, so that.limit - rendered == 2). Changing it so that therendered += results.length;line is after the_append` call fixes it. And FWIW all tests pass with that change and without that change.

This comment has been minimized.

Copy link
@javiercejudo

javiercejudo May 6, 2015

I came across the same issue. Just saw it was fixed in #1200


that.async && that.trigger('asyncReceived', query);
}
}
Expand Down
Loading

0 comments on commit 27c765e

Please sign in to comment.