Skip to content

Commit

Permalink
Merge branch '68-trigger-custom-events' of git://github.com/jharding/…
Browse files Browse the repository at this point in the history
…typeahead.js into integration-0.9.0

Conflicts:
	src/dataset.js
	src/dropdown_view.js
	test/dropdown_view_spec.js
	test/playground.html
  • Loading branch information
Jake Harding committed Mar 14, 2013
2 parents 6fcd112 + d789c4b commit 2da2670
Show file tree
Hide file tree
Showing 10 changed files with 240 additions and 114 deletions.
1 change: 1 addition & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ var semver = require('semver'),
'src/version.js',
'src/utils.js',
'src/event_target.js',
'src/event_bus.js',
'src/persistent_storage.js',
'src/request_cache.js',
'src/transport.js',
Expand Down
35 changes: 26 additions & 9 deletions src/dataset.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,21 @@ var Dataset = (function() {
$.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.header = o.header;
this.footer = o.footer;
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 @@ -42,6 +51,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 @@ -57,12 +67,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 @@ -223,17 +237,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, cb) {
Expand Down
29 changes: 10 additions & 19 deletions src/dropdown_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ var DropdownView = (function() {

_handleSelection: function($e) {
var $suggestion = $($e.currentTarget);
this.trigger('suggestionSelected', formatDataForSuggestion($suggestion));
this.trigger('suggestionSelected', getSuggestionData($suggestion));
},

_show: function() {
Expand Down Expand Up @@ -94,7 +94,7 @@ var DropdownView = (function() {
}

$underCursor = $suggestions.eq(nextIndex).addClass('tt-is-under-cursor');
this.trigger('cursorMoved', { value: $underCursor.data('value') });
this.trigger('cursorMoved', getSuggestionData($underCursor));
},

_getSuggestions: function() {
Expand Down Expand Up @@ -166,15 +166,13 @@ var DropdownView = (function() {
.filter('.tt-is-under-cursor')
.first();

return $suggestion.length > 0 ?
formatDataForSuggestion($suggestion) : null;
return $suggestion.length > 0 ? getSuggestionData($suggestion) : null;
},

getFirstSuggestion: function() {
var $suggestion = this._getSuggestions().first();

return $suggestion.length > 0 ?
formatDataForSuggestion($suggestion) : null;
return $suggestion.length > 0 ? getSuggestionData($suggestion) : null;
},

renderSuggestions: function(query, dataset, suggestions) {
Expand Down Expand Up @@ -210,7 +208,7 @@ var DropdownView = (function() {

$el = $(elBuilder.firstChild)
.css(css.suggestion)
.data('value', suggestion.value);
.data('suggestion', suggestion);

$el.children().each(function() {
$(this).css(css.suggestionChild);
Expand All @@ -221,11 +219,7 @@ var DropdownView = (function() {

// show this dataset in case it was previously empty
// and render the new suggestions
$dataset
.show()
.find('.tt-suggestions')
.data({ query: query, dataset: dataset.name })
.html(fragment);
$dataset.show().find('.tt-suggestions').html(fragment);
}

// no suggestions to render
Expand Down Expand Up @@ -254,13 +248,10 @@ var DropdownView = (function() {

return DropdownView;

function formatDataForSuggestion($suggestion) {
var $suggestions = $suggestion.parents('.tt-suggestions').first();
// helper functions
// ----------------

return {
value: $suggestion.data('value'),
query: $suggestions.data('query'),
dataset: $suggestions.data('dataset')
};
function getSuggestionData($el) {
return $el.data('suggestion');
}
})();
30 changes: 30 additions & 0 deletions src/event_bus.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* typeahead.js
* https://github.com/twitter/typeahead
* Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT
*/

var EventBus = (function() {
var namespace = 'typeahead:';

function EventBus(o) {
if (!o || !o.el) {
$.error('EventBus initialized without el');
}

this.$el = $(o.el);
}

utils.mixin(EventBus.prototype, {
// public methods
// --------------

trigger: function(type) {
var args = [].slice.call(arguments, 1);

this.$el.trigger(namespace + type, args);
}
});

return EventBus;
})();
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
21 changes: 15 additions & 6 deletions src/typeahead_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ 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');
Expand All @@ -78,7 +80,8 @@ var TypeaheadView = (function() {
.on('cursorRemoved', this._updateHint)
.on('suggestionsRendered', this._updateHint)
.on('opened', this._updateHint)
.on('closed', this._clearHint);
.on('closed', this._clearHint)
.on('opened closed', this._propagateEvent);

this.inputView = new InputView({ input: $input, hint: $hint })
.on('focused', this._openDropdown)
Expand Down Expand Up @@ -136,8 +139,8 @@ var TypeaheadView = (function() {
},

_updateHint: function() {
var dataForFirstSuggestion = this.dropdownView.getFirstSuggestion(),
hint = dataForFirstSuggestion ? dataForFirstSuggestion.value : null,
var suggestion = this.dropdownView.getFirstSuggestion(),
hint = suggestion ? suggestion.value : null,
dropdownIsVisible = this.dropdownView.isVisible(),
inputHasOverflow = this.inputView.isOverflow(),
inputValue,
Expand Down Expand Up @@ -198,11 +201,11 @@ var TypeaheadView = (function() {

_handleSelection: function(e) {
var byClick = e.type === 'suggestionSelected',
suggestionData = byClick ?
suggestion = byClick ?
e.data : this.dropdownView.getSuggestionUnderCursor();

if (suggestionData) {
this.inputView.setInputValue(suggestionData.value);
if (suggestion) {
this.inputView.setInputValue(suggestion.value);

// if triggered by click, ensure the query input still has focus
// if triggered by keypress, prevent default browser behavior
Expand All @@ -213,6 +216,8 @@ var TypeaheadView = (function() {
// focus is not a synchronous event in ie, so we deal with it
byClick && utils.isMsie() ?
setTimeout(this.dropdownView.close, 0) : this.dropdownView.close();

this.eventBus.trigger('selected', suggestion);
}
},

Expand Down Expand Up @@ -258,6 +263,10 @@ var TypeaheadView = (function() {
}
},

_propagateEvent: function(e) {
this.eventBus.trigger(e.type);
},

// public methods
// --------------

Expand Down
Loading

0 comments on commit 2da2670

Please sign in to comment.