Skip to content

Commit

Permalink
Trigger typeahead:initialized.
Browse files Browse the repository at this point in the history
  • Loading branch information
Jake Harding committed Mar 13, 2013
1 parent 04d8f2a commit d789c4b
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 52 deletions.
37 changes: 27 additions & 10 deletions src/dataset.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,22 @@ var Dataset = (function() {
utils.bindAll(this);

if (o.template && !o.engine) {
throw new Error('no template engine specified');

This comment has been minimized.

Copy link
@BinRoot

BinRoot Mar 28, 2013

What was the reason to wrap the error through JQuery instead?

This comment has been minimized.

Copy link
@jharding

jharding Mar 28, 2013

Contributor

Did it mostly for aesthetics reasons. Also I was at one point considering doing something like:

function initialize(o) {
  // ...
  !o.requiredProp && $.error('required property missing');
  // ...
}

I decided against that though.

$.error('no template engine specified');
}

if (!o.local && !o.prefetch && !o.remote) {
$.error('one of local, prefetch, or remote is requried');
}

this.name = o.name;
this.limit = o.limit || 5;
this.template = compileTemplate(o.template, o.engine);

// used in #initialize
this.local = o.local;
this.prefetch = o.prefetch;
this.remote = o.remote;

this.keys = {
version: 'version',
protocol: 'protocol',
Expand All @@ -40,6 +49,7 @@ var Dataset = (function() {

_loadPrefetchData: function(o) {
var that = this,
deferred,
version = this.storage.get(this.keys.version),
protocol = this.storage.get(this.keys.protocol),
itemHash = this.storage.get(this.keys.itemHash),
Expand All @@ -55,12 +65,16 @@ var Dataset = (function() {
itemHash: itemHash,
adjacencyList: adjacencyList
});

deferred = $.Deferred().resolve();
}

else {
$.getJSON(o.url).done(processPrefetchData);
deferred = $.getJSON(o.url).done(processPrefetchData);
}

return deferred;

function processPrefetchData(data) {
var filteredData = o.filter ? o.filter(data) : data,
processedData = that._processData(filteredData),
Expand Down Expand Up @@ -256,17 +270,20 @@ var Dataset = (function() {

// the contents of this function are broken out of the constructor
// to help improve the testability of datasets
initialize: function(o) {
if (!o.local && !o.prefetch && !o.remote) {
throw new Error('one of local, prefetch, or remote is requried');
}
initialize: function() {
var deferred;

this.local && this._processLocalData(this.local);
this.transport = this.remote ? new Transport(this.remote) : null;

this.transport = o.remote ? new Transport(o.remote) : null;
deferred = this.prefetch ?
this._loadPrefetchData(this.prefetch) :
$.Deferred().resolve();

o.local && this._processLocalData(o.local);
o.prefetch && this._loadPrefetchData(o.prefetch);
this.local = this.prefetch = this.remote = null;
this.initialize = function() { return deferred; };

return this;
return deferred;
},

getSuggestions: function(query, callback) {
Expand Down
34 changes: 24 additions & 10 deletions src/typeahead.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

(function() {
var datasetCache = {}, methods;
var datasetCache = {}, viewKey = 'ttView', methods;

methods = {
initialize: function(datasetDefs) {
Expand All @@ -14,37 +14,51 @@
datasetDefs = utils.isArray(datasetDefs) ? datasetDefs : [datasetDefs];

if (this.length === 0) {
throw new Error('typeahead initialized without DOM element');
$.error('typeahead initialized without DOM element');
}

if (datasetDefs.length === 0) {
throw new Error('no datasets provided');
$.error('no datasets provided');
}

datasets = utils.map(datasetDefs, function(o) {
o.name = o.name || utils.getUniqueId();

return datasetCache[o.name] ?
datasetCache[o.name] :
datasetCache[o.name] = new Dataset(o).initialize(o);
datasetCache[o.name] = new Dataset(o);
});

return this.each(function() {
return this.each(initialize);

function initialize() {
var $input = $(this),
view = new TypeaheadView({ input: $input, datasets: datasets });
deferreds,
eventBus = new EventBus({ el: $input });

$input.data('ttView', view);
});
deferreds = utils.map(datasets, function(dataset) {
return dataset.initialize();
});

$input.data(viewKey, new TypeaheadView({
input: $input,
eventBus: eventBus = new EventBus({ el: $input }),
datasets: datasets
}));

$.when.apply($, deferreds)
.always(function() { eventBus.trigger('initialized'); });
}
},

destroy: function() {
this.each(function() {
var $this = $(this),
view = $this.data('ttView');
view = $this.data(viewKey);

if (view) {
view.destroy();
$this.removeData('ttView');
$this.removeData(viewKey);
}
});
}
Expand Down
4 changes: 2 additions & 2 deletions src/typeahead_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,12 @@ var TypeaheadView = (function() {
this.datasets = o.datasets;
this.dir = null;

this.eventBus = o.eventBus;

$menu = this.$node.find('.tt-dropdown-menu');
$input = this.$node.find('.tt-query');
$hint = this.$node.find('.tt-hint');

this.eventBus = new EventBus({ el: $input });

this.dropdownView = new DropdownView({ menu: $menu })
.on('suggestionSelected', this._handleSelection)
.on('cursorMoved', this._clearHint)
Expand Down
65 changes: 41 additions & 24 deletions test/dataset_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,16 @@ describe('Dataset', function() {
});
});

describe('when called without local, prefetch, or remote', function() {
beforeEach(function() {
this.fn = function() { this.dataset = new Dataset(); };
});

it('should throw an error', function() {
expect(this.fn).toThrow();
});
});

describe('when called with no template', function() {
beforeEach(function() {
this.dataset = new Dataset({ local: fixtureData });
Expand Down Expand Up @@ -100,23 +110,22 @@ describe('Dataset', function() {
});

describe('#initialize', function() {
beforeEach(function() {
this.dataset = new Dataset({ name: '#initialize' });
});
it('should return Deferred instance', function() {
var returnVal;

describe('when called without local, prefetch, or remote', function() {
beforeEach(function() {
this.fn = function() { this.dataset.initialize({}); };
});
this.dataset = new Dataset({ local: fixtureData });
returnVal = this.dataset.initialize();

it('should throw an error', function() {
expect(this.fn).toThrow();
});
// eh, have to rely on duck typing unfortunately
expect(returnVal.fail).toBeDefined();
expect(returnVal.done).toBeDefined();
expect(returnVal.always).toBeDefined();
});

describe('when called with local', function() {
beforeEach(function() {
this.dataset.initialize({ local: fixtureData });
this.dataset = new Dataset({ local: fixtureData });
this.dataset.initialize();
});

it('should process and merge the data', function() {
Expand All @@ -128,8 +137,9 @@ describe('Dataset', function() {
describe('when called with prefetch', function() {
describe('if data is available in storage', function() {
beforeEach(function() {
this.dataset = new Dataset({ prefetch: '/prefetch.json' });
this.dataset.storage.get.andCallFake(mockStorageFns.getHit);
this.dataset.initialize({ prefetch: '/prefetch.json' });
this.dataset.initialize();
});

it('should not make ajax request', function() {
Expand All @@ -146,24 +156,23 @@ describe('Dataset', function() {
// default ttl
var ttl = 24 * 60 * 60 * 1000;

beforeEach(function() {
this.dataset.storage.get.andCallFake(mockStorageFns.getMiss);
});

describe('if filter was passed in', function() {
var filteredAdjacencyList = { f: ['filter'] },
filteredItemHash = {
filter: { tokens: ['filter'], value: 'filter' }
};

beforeEach(function() {
this.dataset.initialize({
this.dataset = new Dataset({
prefetch: {
url: '/prefetch.json',
filter: function(data) { return ['filter']; }
}
});

this.dataset.storage.get.andCallFake(mockStorageFns.getMiss);
this.dataset.initialize();

this.request = mostRecentAjaxRequest();
this.request.response(prefetchResp);
});
Expand Down Expand Up @@ -194,7 +203,11 @@ describe('Dataset', function() {

describe('if filter was not passed in', function() {
beforeEach(function() {
this.dataset.initialize({ prefetch: '/prefetch.json' });
this.dataset = new Dataset({ prefetch: '/prefetch.json' });

this.dataset.storage.get.andCallFake(mockStorageFns.getMiss);

this.dataset.initialize();

this.request = mostRecentAjaxRequest();
this.request.response(prefetchResp);
Expand Down Expand Up @@ -228,7 +241,8 @@ describe('Dataset', function() {

describe('when called with remote', function() {
beforeEach(function() {
this.dataset.initialize({ remote: '/remote' });
this.dataset = new Dataset({ remote: '/remote' });
this.dataset.initialize();
});

it('should initialize the transport', function() {
Expand All @@ -239,7 +253,8 @@ describe('Dataset', function() {

describe('Datasource options', function() {
beforeEach(function() {
this.dataset = new Dataset({}).initialize({ local: fixtureData });
this.dataset = new Dataset({ local: fixtureData });
this.dataset.initialize();
});

it('allow for a custom matching function to be defined', function() {
Expand Down Expand Up @@ -272,8 +287,8 @@ describe('Dataset', function() {

describe('Matching, ranking, combining, returning results', function() {
beforeEach(function() {
this.dataset = new Dataset({})
.initialize({ local: fixtureData, remote: '/remote' });
this.dataset = new Dataset({ local: fixtureData, remote: '/remote' });
this.dataset.initialize();
});

it('network requests are not triggered with enough local results', function() {
Expand Down Expand Up @@ -362,7 +377,8 @@ describe('Dataset', function() {
var fixtureData = ['course-106', 'user_name', 'One-Two', 'two three'];

beforeEach(function() {
this.dataset = new Dataset({}).initialize({ local: fixtureData });
this.dataset = new Dataset({ local: fixtureData });
this.dataset.initialize();
});

it('normalizes capitalization to match items', function() {
Expand Down Expand Up @@ -407,7 +423,8 @@ describe('Dataset', function() {
var fixtureData = [{ value: 'course-106', tokens: ['course-106'] }];

beforeEach(function() {
this.dataset = new Dataset({}).initialize({ local: fixtureData });
this.dataset = new Dataset({ local: fixtureData });
this.dataset.initialize();
});

it('matches items with dashes', function() {
Expand Down
14 changes: 8 additions & 6 deletions test/playground.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@
</div>

<script>
$('input').on([
'typeahead:initialized',
'typeahead:selected',
'typeahead:opened',
'typeahead:closed'
].join(' '), logToTextarea);

$('.states').typeahead({
local: [
"Alabama",
Expand Down Expand Up @@ -100,12 +107,7 @@
"Wisconsin",
"Wyoming"
]
})
.on([
'typeahead:selected',
'typeahead:opened',
'typeahead:closed'
].join(' '), logToTextarea);
});

$('.bad-tokens').typeahead({
local: [
Expand Down
1 change: 1 addition & 0 deletions test/typeahead_view_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ describe('TypeaheadView', function() {

this.typeaheadView = new TypeaheadView({
input: this.$input,
eventBus: new EventBus({ el: this.$input }),
datasets: mockDatasets
});

Expand Down

0 comments on commit d789c4b

Please sign in to comment.