typeahead.js
Advanced tools
Comparing version 0.10.1 to 0.10.2
{ | ||
"name": "typeahead.js", | ||
"version": "0.10.1", | ||
"main": [ | ||
"bloodhound.js", | ||
"typeahead.jquery.js", | ||
"typeahead.bundle.js", | ||
"typeahead.bundle.min.js" | ||
], | ||
"version": "0.10.2", | ||
"main": "dist/typeahead.bundle.js", | ||
"dependencies": { | ||
"jquery": "~1.9" | ||
"jquery": ">=1.7" | ||
}, | ||
"devDependencies": { | ||
"jasmine-ajax": "~1.3.1", | ||
"jasmine-jquery": "~1.5.2" | ||
} | ||
} |
198
CHANGELOG.md
@@ -18,2 +18,16 @@ Changelog | ||
### 0.10.2 March 10, 2014 | ||
* Prevent flickering of dropdown menu when requesting remote suggestions. [#718] | ||
* Reduce hint flickering. [#754] | ||
* Added `Bloodhound#{clear, clearPrefetchCache, clearRemoteCache}` and made it | ||
possible to reinitialize Bloodhound instances. [#703] | ||
* Invoke `local` function during initialization. [#687] | ||
* In addition to HTML strings, templates can now return DOM nodes. [#742] | ||
* Prevent `jQuery#typeahead('val', val)` from opening dropdown menus of | ||
non-active typeaheads. [#646] | ||
* Fix bug in IE that resulted in dropdown menus with overflow being closed | ||
when clicking on the scrollbar. [#705] | ||
* Only show dropdown menu if `minLength` is satisfied. [#710] | ||
### 0.10.1 February 9, 2014 | ||
@@ -23,10 +37,10 @@ | ||
* Fixed bug that prevented some ajax configs from being respected. [#630][630] | ||
* Event delegation on suggestion clicks is no longer broken. [#118][118] | ||
* Ensure dataset names are valid class name suffixes. [#610][610] | ||
* Added support for `displayKey` to be a function. [#633][633] | ||
* `jQuery#typeahead('val')` now mirrors `jQuery#val()`. [#659][659] | ||
* Datasets can now be passed to jQuery plugin as an array. [#664][664] | ||
* Added a `noConflict` method to the jQuery plugin. [#612][612] | ||
* Bloodhound's `local` property can now be a function. [#485][485] | ||
* Fixed bug that prevented some ajax configs from being respected. [#630] | ||
* Event delegation on suggestion clicks is no longer broken. [#118] | ||
* Ensure dataset names are valid class name suffixes. [#610] | ||
* Added support for `displayKey` to be a function. [#633] | ||
* `jQuery#typeahead('val')` now mirrors `jQuery#val()`. [#659] | ||
* Datasets can now be passed to jQuery plugin as an array. [#664] | ||
* Added a `noConflict` method to the jQuery plugin. [#612] | ||
* Bloodhound's `local` property can now be a function. [#485] | ||
@@ -58,22 +72,22 @@ ### 0.10.0 February 2, 2014 | ||
* Ensure cursor visibility in menus with overflow. [#209][209] | ||
* Fixed bug that led to the menu staying open when it should have been closed. [#260][260] | ||
* Private browsing in Safari no longer breaks prefetch. [#270][270] | ||
* Pressing tab while a suggestion is highlighted now results in a selection. [#266][266] | ||
* Dataset name is now passed as an argument for typeahead:selected event. [#207][207] | ||
* Ensure cursor visibility in menus with overflow. [#209] | ||
* Fixed bug that led to the menu staying open when it should have been closed. [#260] | ||
* Private browsing in Safari no longer breaks prefetch. [#270] | ||
* Pressing tab while a suggestion is highlighted now results in a selection. [#266] | ||
* Dataset name is now passed as an argument for typeahead:selected event. [#207] | ||
### 0.9.2 April 14, 2013 | ||
* Prefetch usage no longer breaks when cookies are disabled. [#190][190] | ||
* Precompiled templates are now wrapped in the appropriate DOM element. [#172][172] | ||
* Prefetch usage no longer breaks when cookies are disabled. [#190] | ||
* Precompiled templates are now wrapped in the appropriate DOM element. [#172] | ||
### 0.9.1 April 1, 2013 | ||
* Multiple requests no longer get sent for a query when datasets share a remote source. [#152][152] | ||
* Datasets now support precompiled templates. [#137][137] | ||
* Cached remote suggestions now get rendered immediately. [#156][156] | ||
* Added typeahead:autocompleted event. [#132][132] | ||
* Added a plugin method for programmatically setting the query. Experimental. [#159][159] | ||
* Added minLength option for datasets. Experimental. [#131][131] | ||
* Prefetch objects now support thumbprint option. Experimental. [#157][157] | ||
* Multiple requests no longer get sent for a query when datasets share a remote source. [#152] | ||
* Datasets now support precompiled templates. [#137] | ||
* Cached remote suggestions now get rendered immediately. [#156] | ||
* Added typeahead:autocompleted event. [#132] | ||
* Added a plugin method for programmatically setting the query. Experimental. [#159] | ||
* Added minLength option for datasets. Experimental. [#131] | ||
* Prefetch objects now support thumbprint option. Experimental. [#157] | ||
@@ -84,30 +98,30 @@ ### 0.9.0 March 24, 2013 | ||
* Implemented the triggering of custom events. [#106][106] | ||
* Got rid of typeahead.css and now apply styling through JavaScript. [#15][15] | ||
* Made the API more flexible and addressed a handful of remote issues by rewriting the transport component. [#25][25] | ||
* Added support for dataset headers and footers. [#81][81] | ||
* No longer cache unnamed datasets. [#116][116] | ||
* Made the key name of the value property configurable. [#115][115] | ||
* Input values set before initialization of typeaheads are now respected. [#109][109] | ||
* Fixed an input value/hint casing bug. [#108][108] | ||
* Implemented the triggering of custom events. [#106] | ||
* Got rid of typeahead.css and now apply styling through JavaScript. [#15] | ||
* Made the API more flexible and addressed a handful of remote issues by rewriting the transport component. [#25] | ||
* Added support for dataset headers and footers. [#81] | ||
* No longer cache unnamed datasets. [#116] | ||
* Made the key name of the value property configurable. [#115] | ||
* Input values set before initialization of typeaheads are now respected. [#109] | ||
* Fixed an input value/hint casing bug. [#108] | ||
### 0.8.2 March 04, 2013 | ||
* Fixed bug causing error to be thrown when initializing a typeahead on multiple elements. [#51][51] | ||
* Tokens with falsy values are now filtered out – was causing wonky behavior. [#75][75] | ||
* No longer making remote requests for blank queries. [#74][74] | ||
* Datums with regex characters in their value no longer cause errors. [#77][77] | ||
* Now compatible with the Closure Compiler. [#48][48] | ||
* Reference to jQuery is now obtained through window.jQuery, not window.$. [#47][47] | ||
* Added a plugin method for destroying typeaheads. Won't be documented until v0.9 and might change before then. [#59][59] | ||
* Fixed bug causing error to be thrown when initializing a typeahead on multiple elements. [#51] | ||
* Tokens with falsy values are now filtered out – was causing wonky behavior. [#75] | ||
* No longer making remote requests for blank queries. [#74] | ||
* Datums with regex characters in their value no longer cause errors. [#77] | ||
* Now compatible with the Closure Compiler. [#48] | ||
* Reference to jQuery is now obtained through window.jQuery, not window.$. [#47] | ||
* Added a plugin method for destroying typeaheads. Won't be documented until v0.9 and might change before then. [#59] | ||
### 0.8.1 February 25, 2013 | ||
* Fixed bug preventing local and prefetch from being used together. [#39][39] | ||
* No longer prevent default browser behavior when up or down arrow is pressed with a modifier. [#6][6] | ||
* Hint is hidden when user entered query is wider than the input. [#26][26] | ||
* Data stored in localStorage now expires properly. [#34][34] | ||
* Normalized search tokens and fixed query tokenization. [#38][38] | ||
* Remote suggestions now are appended, not prepended to suggestions list. [#40][40] | ||
* Fixed some typos through the codebase. [#3][3] | ||
* Fixed bug preventing local and prefetch from being used together. [#39] | ||
* No longer prevent default browser behavior when up or down arrow is pressed with a modifier. [#6] | ||
* Hint is hidden when user entered query is wider than the input. [#26] | ||
* Data stored in localStorage now expires properly. [#34] | ||
* Normalized search tokens and fixed query tokenization. [#38] | ||
* Remote suggestions now are appended, not prepended to suggestions list. [#40] | ||
* Fixed some typos through the codebase. [#3] | ||
@@ -128,45 +142,53 @@ ### 0.8.0 February 19, 2013 | ||
[664]: https://github.com/twitter/typeahead.js/pull/664 | ||
[659]: https://github.com/twitter/typeahead.js/pull/659 | ||
[633]: https://github.com/twitter/typeahead.js/pull/633 | ||
[630]: https://github.com/twitter/typeahead.js/pull/630 | ||
[612]: https://github.com/twitter/typeahead.js/pull/612 | ||
[610]: https://github.com/twitter/typeahead.js/pull/610 | ||
[485]: https://github.com/twitter/typeahead.js/pull/485 | ||
[270]: https://github.com/twitter/typeahead.js/pull/270 | ||
[266]: https://github.com/twitter/typeahead.js/pull/266 | ||
[260]: https://github.com/twitter/typeahead.js/pull/260 | ||
[209]: https://github.com/twitter/typeahead.js/pull/209 | ||
[207]: https://github.com/twitter/typeahead.js/pull/207 | ||
[190]: https://github.com/twitter/typeahead.js/pull/190 | ||
[172]: https://github.com/twitter/typeahead.js/pull/172 | ||
[159]: https://github.com/twitter/typeahead.js/pull/159 | ||
[157]: https://github.com/twitter/typeahead.js/pull/157 | ||
[156]: https://github.com/twitter/typeahead.js/pull/156 | ||
[152]: https://github.com/twitter/typeahead.js/pull/152 | ||
[137]: https://github.com/twitter/typeahead.js/pull/137 | ||
[132]: https://github.com/twitter/typeahead.js/pull/132 | ||
[131]: https://github.com/twitter/typeahead.js/pull/131 | ||
[118]: https://github.com/twitter/typeahead.js/pull/118 | ||
[116]: https://github.com/twitter/typeahead.js/pull/116 | ||
[115]: https://github.com/twitter/typeahead.js/pull/115 | ||
[109]: https://github.com/twitter/typeahead.js/pull/109 | ||
[108]: https://github.com/twitter/typeahead.js/pull/108 | ||
[106]: https://github.com/twitter/typeahead.js/pull/106 | ||
[81]: https://github.com/twitter/typeahead.js/pull/81 | ||
[77]: https://github.com/twitter/typeahead.js/pull/77 | ||
[75]: https://github.com/twitter/typeahead.js/pull/75 | ||
[74]: https://github.com/twitter/typeahead.js/pull/74 | ||
[59]: https://github.com/twitter/typeahead.js/pull/59 | ||
[51]: https://github.com/twitter/typeahead.js/pull/51 | ||
[48]: https://github.com/twitter/typeahead.js/pull/48 | ||
[47]: https://github.com/twitter/typeahead.js/pull/47 | ||
[40]: https://github.com/twitter/typeahead.js/pull/40 | ||
[39]: https://github.com/twitter/typeahead.js/pull/39 | ||
[38]: https://github.com/twitter/typeahead.js/pull/38 | ||
[34]: https://github.com/twitter/typeahead.js/pull/34 | ||
[26]: https://github.com/twitter/typeahead.js/pull/26 | ||
[25]: https://github.com/twitter/typeahead.js/pull/25 | ||
[15]: https://github.com/twitter/typeahead.js/pull/15 | ||
[6]: https://github.com/twitter/typeahead.js/pull/6 | ||
[3]: https://github.com/twitter/typeahead.js/pull/3 | ||
[#754]: https://github.com/twitter/typeahead.js/pull/754 | ||
[#742]: https://github.com/twitter/typeahead.js/pull/742 | ||
[#718]: https://github.com/twitter/typeahead.js/pull/718 | ||
[#710]: https://github.com/twitter/typeahead.js/pull/710 | ||
[#705]: https://github.com/twitter/typeahead.js/pull/705 | ||
[#703]: https://github.com/twitter/typeahead.js/pull/703 | ||
[#687]: https://github.com/twitter/typeahead.js/pull/687 | ||
[#664]: https://github.com/twitter/typeahead.js/pull/664 | ||
[#659]: https://github.com/twitter/typeahead.js/pull/659 | ||
[#646]: https://github.com/twitter/typeahead.js/pull/646 | ||
[#633]: https://github.com/twitter/typeahead.js/pull/633 | ||
[#630]: https://github.com/twitter/typeahead.js/pull/630 | ||
[#612]: https://github.com/twitter/typeahead.js/pull/612 | ||
[#610]: https://github.com/twitter/typeahead.js/pull/610 | ||
[#485]: https://github.com/twitter/typeahead.js/pull/485 | ||
[#270]: https://github.com/twitter/typeahead.js/pull/270 | ||
[#266]: https://github.com/twitter/typeahead.js/pull/266 | ||
[#260]: https://github.com/twitter/typeahead.js/pull/260 | ||
[#209]: https://github.com/twitter/typeahead.js/pull/209 | ||
[#207]: https://github.com/twitter/typeahead.js/pull/207 | ||
[#190]: https://github.com/twitter/typeahead.js/pull/190 | ||
[#172]: https://github.com/twitter/typeahead.js/pull/172 | ||
[#159]: https://github.com/twitter/typeahead.js/pull/159 | ||
[#157]: https://github.com/twitter/typeahead.js/pull/157 | ||
[#156]: https://github.com/twitter/typeahead.js/pull/156 | ||
[#152]: https://github.com/twitter/typeahead.js/pull/152 | ||
[#137]: https://github.com/twitter/typeahead.js/pull/137 | ||
[#132]: https://github.com/twitter/typeahead.js/pull/132 | ||
[#131]: https://github.com/twitter/typeahead.js/pull/131 | ||
[#118]: https://github.com/twitter/typeahead.js/pull/118 | ||
[#116]: https://github.com/twitter/typeahead.js/pull/116 | ||
[#115]: https://github.com/twitter/typeahead.js/pull/115 | ||
[#109]: https://github.com/twitter/typeahead.js/pull/109 | ||
[#108]: https://github.com/twitter/typeahead.js/pull/108 | ||
[#106]: https://github.com/twitter/typeahead.js/pull/106 | ||
[#81]: https://github.com/twitter/typeahead.js/pull/81 | ||
[#77]: https://github.com/twitter/typeahead.js/pull/77 | ||
[#75]: https://github.com/twitter/typeahead.js/pull/75 | ||
[#74]: https://github.com/twitter/typeahead.js/pull/74 | ||
[#59]: https://github.com/twitter/typeahead.js/pull/59 | ||
[#51]: https://github.com/twitter/typeahead.js/pull/51 | ||
[#48]: https://github.com/twitter/typeahead.js/pull/48 | ||
[#47]: https://github.com/twitter/typeahead.js/pull/47 | ||
[#40]: https://github.com/twitter/typeahead.js/pull/40 | ||
[#39]: https://github.com/twitter/typeahead.js/pull/39 | ||
[#38]: https://github.com/twitter/typeahead.js/pull/38 | ||
[#34]: https://github.com/twitter/typeahead.js/pull/34 | ||
[#26]: https://github.com/twitter/typeahead.js/pull/26 | ||
[#25]: https://github.com/twitter/typeahead.js/pull/25 | ||
[#15]: https://github.com/twitter/typeahead.js/pull/15 | ||
[#6]: https://github.com/twitter/typeahead.js/pull/6 | ||
[#3]: https://github.com/twitter/typeahead.js/pull/3 |
@@ -1,28 +0,114 @@ | ||
Contributing Guidelines | ||
======================= | ||
Contributing to typeahead.js | ||
============================ | ||
Setup | ||
----- | ||
*These contributing guidelines were proudly stolen from the | ||
[Flight](https://github.com/flightjs/flight) project* | ||
1. [Fork the project][how-to-fork] and clone the fork to your machine. | ||
2. Create a feature branch to work in. `$ git checkout -b name-of-feature` | ||
Looking to contribute something to typeahead.js? Here's how you can help. | ||
Writing Code | ||
Bugs Reports | ||
------------ | ||
* Use the project's coding style, not your own. If the code you write looks drastically different than the preexisting code, you're doing it wrong. | ||
* Include tests that fail without your code, and pass with it. | ||
* Commits should have meaningful messages. If you end up with a bunch of commits with garbage messages, squash your commits before submitting a pull request. | ||
A bug is a _demonstrable problem_ that is caused by the code in the | ||
repository. Good bug reports are extremely helpful – thank you! | ||
Guidelines for bug reports: | ||
1. **Use the GitHub issue search** — check if the issue has already been | ||
reported. | ||
2. **Check if the issue has been fixed** — try to reproduce it using the | ||
latest `master` or integration branch in the repository. | ||
3. **Isolate the problem** — ideally create a reduced test | ||
case and a live example. | ||
4. Please try to be as detailed as possible in your report. Include specific | ||
information about the environment – operating system and version, browser | ||
and version, version of typeahead.js – and steps required to reproduce the | ||
issue. | ||
Feature Requests & Contribution Enquiries | ||
----------------------------------------- | ||
Feature requests are welcome. But take a moment to find out whether your idea | ||
fits with the scope and aims of the project. It's up to *you* to make a strong | ||
case for the inclusion of your feature. Please provide as much detail and | ||
context as possible. | ||
Contribution enquiries should take place before any significant pull request, | ||
otherwise you risk spending a lot of time working on something that we might | ||
have good reasons for rejecting. | ||
Pull Requests | ||
------------- | ||
1. Push your feature branch to your remote repo on GitHub. `$ git push origin name-of-feature` | ||
2. [Create a pull request][create-pull-request] against master. | ||
3. Write a meaningful title and description. If you've added a new feature or break backwards compatibility, let us know so we can updated the docs accordingly. | ||
5. Submit the pull request! | ||
Good pull requests – patches, improvements, new features – are a fantastic | ||
help. They should remain focused in scope and avoid containing unrelated | ||
commits. | ||
[how-to-fork]: https://help.github.com/articles/fork-a-repo | ||
[create-pull-request]: https://help.github.com/articles/creating-a-pull-request | ||
Make sure to adhere to the coding conventions used throughout the codebase | ||
(indentation, accurate comments, etc.) and any other requirements (such as test | ||
coverage). | ||
Please follow this process; it's the best way to get your work included in the | ||
project: | ||
1. [Fork](http://help.github.com/fork-a-repo/) the project, clone your fork, | ||
and configure the remotes: | ||
```bash | ||
# Clone your fork of the repo into the current directory | ||
git clone https://github.com/<your-username>/typeahead.js | ||
# Navigate to the newly cloned directory | ||
cd <repo-name> | ||
# Assign the original repo to a remote called "upstream" | ||
git remote add upstream git://github.com/twitter/typeahead.js | ||
``` | ||
2. If you cloned a while ago, get the latest changes from upstream: | ||
```bash | ||
git checkout master | ||
git pull upstream master | ||
``` | ||
3. Install the dependencies (you must have Node.js and [Bower](http://bower.io) | ||
installed), and create a new topic branch (off the main project development | ||
branch) to contain your feature, change, or fix: | ||
```bash | ||
npm install | ||
bower install | ||
git checkout -b <topic-branch-name> | ||
``` | ||
4. Make sure to update, or add to the tests when appropriate. Patches and | ||
features will not be accepted without tests. Run `npm test` to check that | ||
all tests pass after you've made changes. | ||
5. Commit your changes in logical chunks. Provide clear and explanatory commit | ||
messages. Use Git's [interactive rebase](https://help.github.com/articles/interactive-rebase) feature to tidy up | ||
your commits before making them public. | ||
6. Locally merge (or rebase) the upstream development branch into your topic branch: | ||
```bash | ||
git pull [--rebase] upstream master | ||
``` | ||
7. Push your topic branch up to your fork: | ||
```bash | ||
git push origin <topic-branch-name> | ||
``` | ||
8. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/) | ||
with a clear title and description. | ||
9. If you are asked to amend your changes before they can be merged in, please | ||
use `git commit --amend` (or rebasing for multi-commit Pull Requests) and | ||
force push to your remote feature branch. You may also be asked to squash | ||
commits. | ||
License | ||
@@ -29,0 +115,0 @@ ------- |
/*! | ||
* typeahead.js 0.10.1 | ||
* typeahead.js 0.10.2 | ||
* https://github.com/twitter/typeahead.js | ||
* Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT | ||
* Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT | ||
*/ | ||
@@ -123,4 +123,27 @@ | ||
}; | ||
var VERSION = "0.10.1"; | ||
var LruCache = function(root, undefined) { | ||
var VERSION = "0.10.2"; | ||
var tokenizers = function(root) { | ||
return { | ||
nonword: nonword, | ||
whitespace: whitespace, | ||
obj: { | ||
nonword: getObjTokenizer(nonword), | ||
whitespace: getObjTokenizer(whitespace) | ||
} | ||
}; | ||
function whitespace(s) { | ||
return s.split(/\s+/); | ||
} | ||
function nonword(s) { | ||
return s.split(/\W+/); | ||
} | ||
function getObjTokenizer(tokenizer) { | ||
return function setKey(key) { | ||
return function tokenize(o) { | ||
return tokenizer(o[key]); | ||
}; | ||
}; | ||
} | ||
}(); | ||
var LruCache = function() { | ||
function LruCache(maxSize) { | ||
@@ -184,3 +207,3 @@ this.maxSize = maxSize || 100; | ||
return LruCache; | ||
}(this); | ||
}(); | ||
var PersistentStorage = function() { | ||
@@ -282,6 +305,6 @@ var ls, methods; | ||
if (jqXhr = pendingRequests[url]) { | ||
jqXhr.done(done); | ||
jqXhr.done(done).fail(fail); | ||
} else if (pendingRequestsCount < maxPendingRequests) { | ||
pendingRequestsCount++; | ||
pendingRequests[url] = this._send(url, o).done(done).always(always); | ||
pendingRequests[url] = this._send(url, o).done(done).fail(fail).always(always); | ||
} else { | ||
@@ -291,5 +314,8 @@ this.onDeckRequestArgs = [].slice.call(arguments, 0); | ||
function done(resp) { | ||
cb && cb(resp); | ||
cb && cb(null, resp); | ||
requestCache.set(url, resp); | ||
} | ||
function fail() { | ||
cb && cb(true); | ||
} | ||
function always() { | ||
@@ -305,3 +331,3 @@ pendingRequestsCount--; | ||
get: function(url, o, cb) { | ||
var that = this, resp; | ||
var resp; | ||
if (_.isFunction(o)) { | ||
@@ -313,3 +339,3 @@ cb = o; | ||
_.defer(function() { | ||
cb && cb(resp); | ||
cb && cb(null, resp); | ||
}); | ||
@@ -349,4 +375,3 @@ } else { | ||
this.queryTokenizer = o.queryTokenizer; | ||
this.datums = []; | ||
this.trie = newNode(); | ||
this.reset(); | ||
} | ||
@@ -366,3 +391,3 @@ _.mixin(SearchIndex.prototype, { | ||
_.each(tokens, function(token) { | ||
var node, chars, ch, ids; | ||
var node, chars, ch; | ||
node = that.trie; | ||
@@ -402,2 +427,6 @@ chars = token.split(""); | ||
}, | ||
reset: function reset() { | ||
this.datums = []; | ||
this.trie = newNode(); | ||
}, | ||
serialize: function serialize() { | ||
@@ -464,7 +493,3 @@ return { | ||
function getLocal(o) { | ||
var local = o.local || null; | ||
if (_.isFunction(local)) { | ||
local = local.call(null); | ||
} | ||
return local; | ||
return o.local || null; | ||
} | ||
@@ -529,4 +554,5 @@ function getPrefetch(o) { | ||
}(); | ||
var Bloodhound = window.Bloodhound = function() { | ||
var keys; | ||
(function(root) { | ||
var old, keys; | ||
old = root.Bloodhound; | ||
keys = { | ||
@@ -537,2 +563,3 @@ data: "data", | ||
}; | ||
root.Bloodhound = Bloodhound; | ||
function Bloodhound(o) { | ||
@@ -555,10 +582,7 @@ if (!o || !o.local && !o.prefetch && !o.remote) { | ||
} | ||
Bloodhound.tokenizers = { | ||
whitespace: function whitespaceTokenizer(s) { | ||
return s.split(/\s+/); | ||
}, | ||
nonword: function nonwordTokenizer(s) { | ||
return s.split(/\W+/); | ||
} | ||
Bloodhound.noConflict = function noConflict() { | ||
root.Bloodhound = old; | ||
return Bloodhound; | ||
}; | ||
Bloodhound.tokenizers = tokenizers; | ||
_.mixin(Bloodhound.prototype, { | ||
@@ -575,5 +599,4 @@ _loadPrefetch: function loadPrefetch(o) { | ||
function handlePrefetchResponse(resp) { | ||
var filtered; | ||
filtered = o.filter ? o.filter(resp) : resp; | ||
that.add(filtered); | ||
that.clear(); | ||
that.add(o.filter ? o.filter(resp) : resp); | ||
that._saveToStorage(that.index.serialize(), o.thumbprint, o.ttl); | ||
@@ -588,5 +611,4 @@ } | ||
return this.transport.get(url, this.remote.ajax, handleRemoteResponse); | ||
function handleRemoteResponse(resp) { | ||
var filtered = that.remote.filter ? that.remote.filter(resp) : resp; | ||
cb(filtered); | ||
function handleRemoteResponse(err, resp) { | ||
err ? cb([]) : cb(that.remote.filter ? that.remote.filter(resp) : resp); | ||
} | ||
@@ -611,15 +633,15 @@ }, | ||
}, | ||
initialize: function initialize() { | ||
var that = this, deferred; | ||
_initialize: function initialize() { | ||
var that = this, local = this.local, deferred; | ||
deferred = this.prefetch ? this._loadPrefetch(this.prefetch) : $.Deferred().resolve(); | ||
this.local && deferred.done(addLocalToIndex); | ||
local && deferred.done(addLocalToIndex); | ||
this.transport = this.remote ? new Transport(this.remote) : null; | ||
this.initialize = function initialize() { | ||
return deferred.promise(); | ||
}; | ||
return deferred.promise(); | ||
return this.initPromise = deferred.promise(); | ||
function addLocalToIndex() { | ||
that.add(that.local); | ||
that.add(_.isFunction(local) ? local() : local); | ||
} | ||
}, | ||
initialize: function initialize(force) { | ||
return !this.initPromise || force ? this._initialize() : this.initPromise; | ||
}, | ||
add: function add(data) { | ||
@@ -629,3 +651,3 @@ this.index.add(data); | ||
get: function get(query, cb) { | ||
var that = this, matches, cacheHit = false; | ||
var that = this, matches = [], cacheHit = false; | ||
matches = this.index.get(query); | ||
@@ -636,3 +658,5 @@ matches = this.sorter(matches).slice(0, this.limit); | ||
} | ||
!cacheHit && cb && cb(matches); | ||
if (!cacheHit) { | ||
(matches.length > 0 || !this.transport) && cb && cb(matches); | ||
} | ||
function returnRemoteMatches(remoteMatches) { | ||
@@ -651,2 +675,11 @@ var matchesWithBackfill = matches.slice(0); | ||
}, | ||
clear: function clear() { | ||
this.index.reset(); | ||
}, | ||
clearPrefetchCache: function clearPrefetchCache() { | ||
this.storage && this.storage.clear(); | ||
}, | ||
clearRemoteCache: function clearRemoteCache() { | ||
this.transport && Transport.resetCache(); | ||
}, | ||
ttAdapter: function ttAdapter() { | ||
@@ -669,3 +702,3 @@ return _.bind(this.get, this); | ||
} | ||
}(); | ||
})(this); | ||
})(window.jQuery); |
/*! | ||
* typeahead.js 0.10.1 | ||
* typeahead.js 0.10.2 | ||
* https://github.com/twitter/typeahead.js | ||
* Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT | ||
* Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT | ||
*/ | ||
!function(a){var b={isMsie:function(){return/(msie|trident)/i.test(navigator.userAgent)?navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2]:!1},isBlankString:function(a){return!a||/^\s*$/.test(a)},escapeRegExChars:function(a){return a.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")},isString:function(a){return"string"==typeof a},isNumber:function(a){return"number"==typeof a},isArray:a.isArray,isFunction:a.isFunction,isObject:a.isPlainObject,isUndefined:function(a){return"undefined"==typeof a},bind:a.proxy,each:function(b,c){function d(a,b){return c(b,a)}a.each(b,d)},map:a.map,filter:a.grep,every:function(b,c){var d=!0;return b?(a.each(b,function(a,e){return(d=c.call(null,e,a,b))?void 0:!1}),!!d):d},some:function(b,c){var d=!1;return b?(a.each(b,function(a,e){return(d=c.call(null,e,a,b))?!1:void 0}),!!d):d},mixin:a.extend,getUniqueId:function(){var a=0;return function(){return a++}}(),templatify:function(b){function c(){return String(b)}return a.isFunction(b)?b:c},defer:function(a){setTimeout(a,0)},debounce:function(a,b,c){var d,e;return function(){var f,g,h=this,i=arguments;return f=function(){d=null,c||(e=a.apply(h,i))},g=c&&!d,clearTimeout(d),d=setTimeout(f,b),g&&(e=a.apply(h,i)),e}},throttle:function(a,b){var c,d,e,f,g,h;return g=0,h=function(){g=new Date,e=null,f=a.apply(c,d)},function(){var i=new Date,j=b-(i-g);return c=this,d=arguments,0>=j?(clearTimeout(e),e=null,g=i,f=a.apply(c,d)):e||(e=setTimeout(h,j)),f}},noop:function(){}},c="0.10.1",d=function(){function a(a){this.maxSize=a||100,this.size=0,this.hash={},this.list=new c}function c(){this.head=this.tail=null}function d(a,b){this.key=a,this.val=b,this.prev=this.next=null}return b.mixin(a.prototype,{set:function(a,b){var c,e=this.list.tail;this.size>=this.maxSize&&(this.list.remove(e),delete this.hash[e.key]),(c=this.hash[a])?(c.val=b,this.list.moveToFront(c)):(c=new d(a,b),this.list.add(c),this.hash[a]=c,this.size++)},get:function(a){var b=this.hash[a];return b?(this.list.moveToFront(b),b.val):void 0}}),b.mixin(c.prototype,{add:function(a){this.head&&(a.next=this.head,this.head.prev=a),this.head=a,this.tail=this.tail||a},remove:function(a){a.prev?a.prev.next=a.next:this.head=a.next,a.next?a.next.prev=a.prev:this.tail=a.prev},moveToFront:function(a){this.remove(a),this.add(a)}}),a}(this),e=function(){function a(a){this.prefix=["__",a,"__"].join(""),this.ttlKey="__ttl__",this.keyMatcher=new RegExp("^"+this.prefix)}function c(){return(new Date).getTime()}function d(a){return JSON.stringify(b.isUndefined(a)?null:a)}function e(a){return JSON.parse(a)}var f,g;try{f=window.localStorage,f.setItem("~~~","!"),f.removeItem("~~~")}catch(h){f=null}return g=f&&window.JSON?{_prefix:function(a){return this.prefix+a},_ttlKey:function(a){return this._prefix(a)+this.ttlKey},get:function(a){return this.isExpired(a)&&this.remove(a),e(f.getItem(this._prefix(a)))},set:function(a,e,g){return b.isNumber(g)?f.setItem(this._ttlKey(a),d(c()+g)):f.removeItem(this._ttlKey(a)),f.setItem(this._prefix(a),d(e))},remove:function(a){return f.removeItem(this._ttlKey(a)),f.removeItem(this._prefix(a)),this},clear:function(){var a,b,c=[],d=f.length;for(a=0;d>a;a++)(b=f.key(a)).match(this.keyMatcher)&&c.push(b.replace(this.keyMatcher,""));for(a=c.length;a--;)this.remove(c[a]);return this},isExpired:function(a){var d=e(f.getItem(this._ttlKey(a)));return b.isNumber(d)&&c()>d?!0:!1}}:{get:b.noop,set:b.noop,remove:b.noop,clear:b.noop,isExpired:b.noop},b.mixin(a.prototype,g),a}(),f=function(){function c(b){b=b||{},this._send=b.transport?e(b.transport):a.ajax,this._get=b.rateLimiter?b.rateLimiter(this._get):this._get}function e(c){return function(d,e){function f(a){b.defer(function(){h.resolve(a)})}function g(a){b.defer(function(){h.reject(a)})}var h=a.Deferred();return c(d,e,f,g),h}}var f=0,g={},h=6,i=new d(10);return c.setMaxPendingRequests=function(a){h=a},c.resetCache=function(){i=new d(10)},b.mixin(c.prototype,{_get:function(a,b,c){function d(b){c&&c(b),i.set(a,b)}function e(){f--,delete g[a],k.onDeckRequestArgs&&(k._get.apply(k,k.onDeckRequestArgs),k.onDeckRequestArgs=null)}var j,k=this;(j=g[a])?j.done(d):h>f?(f++,g[a]=this._send(a,b).done(d).always(e)):this.onDeckRequestArgs=[].slice.call(arguments,0)},get:function(a,c,d){var e;return b.isFunction(c)&&(d=c,c={}),(e=i.get(a))?b.defer(function(){d&&d(e)}):this._get(a,c,d),!!e}}),c}(),g=function(){function c(b){b=b||{},b.datumTokenizer&&b.queryTokenizer||a.error("datumTokenizer and queryTokenizer are both required"),this.datumTokenizer=b.datumTokenizer,this.queryTokenizer=b.queryTokenizer,this.datums=[],this.trie=e()}function d(a){return a=b.filter(a,function(a){return!!a}),a=b.map(a,function(a){return a.toLowerCase()})}function e(){return{ids:[],children:{}}}function f(a){for(var b={},c=[],d=0;d<a.length;d++)b[a[d]]||(b[a[d]]=!0,c.push(a[d]));return c}function g(a,b){function c(a,b){return a-b}var d=0,e=0,f=[];for(a=a.sort(c),b=b.sort(c);d<a.length&&e<b.length;)a[d]<b[e]?d++:a[d]>b[e]?e++:(f.push(a[d]),d++,e++);return f}return b.mixin(c.prototype,{bootstrap:function(a){this.datums=a.datums,this.trie=a.trie},add:function(a){var c=this;a=b.isArray(a)?a:[a],b.each(a,function(a){var f,g;f=c.datums.push(a)-1,g=d(c.datumTokenizer(a)),b.each(g,function(a){var b,d,g;for(b=c.trie,d=a.split("");g=d.shift();)b=b.children[g]||(b.children[g]=e()),b.ids.push(f)})})},get:function(a){var c,e,h=this;return c=d(this.queryTokenizer(a)),b.each(c,function(a){var b,c,d,f;if(e&&0===e.length)return!1;for(b=h.trie,c=a.split("");b&&(d=c.shift());)b=b.children[d];return b&&0===c.length?(f=b.ids.slice(0),void(e=e?g(e,f):f)):(e=[],!1)}),e?b.map(f(e),function(a){return h.datums[a]}):[]},serialize:function(){return{datums:this.datums,trie:this.trie}}}),c}(),h=function(){function d(a){var c=a.local||null;return b.isFunction(c)&&(c=c.call(null)),c}function e(d){var e,f;return f={url:null,thumbprint:"",ttl:864e5,filter:null,ajax:{}},(e=d.prefetch||null)&&(e=b.isString(e)?{url:e}:e,e=b.mixin(f,e),e.thumbprint=c+e.thumbprint,e.ajax.type=e.ajax.type||"GET",e.ajax.dataType=e.ajax.dataType||"json",!e.url&&a.error("prefetch requires url to be set")),e}function f(c){function d(a){return function(c){return b.debounce(c,a)}}function e(a){return function(c){return b.throttle(c,a)}}var f,g;return g={url:null,wildcard:"%QUERY",replace:null,rateLimitBy:"debounce",rateLimitWait:300,send:null,filter:null,ajax:{}},(f=c.remote||null)&&(f=b.isString(f)?{url:f}:f,f=b.mixin(g,f),f.rateLimiter=/^throttle$/i.test(f.rateLimitBy)?e(f.rateLimitWait):d(f.rateLimitWait),f.ajax.type=f.ajax.type||"GET",f.ajax.dataType=f.ajax.dataType||"json",delete f.rateLimitBy,delete f.rateLimitWait,!f.url&&a.error("remote requires url to be set")),f}return{local:d,prefetch:e,remote:f}}(),i=(window.Bloodhound=function(){function c(b){b&&(b.local||b.prefetch||b.remote)||a.error("one of local, prefetch, or remote is required"),this.limit=b.limit||5,this.sorter=d(b.sorter),this.dupDetector=b.dupDetector||i,this.local=h.local(b),this.prefetch=h.prefetch(b),this.remote=h.remote(b),this.cacheKey=this.prefetch?this.prefetch.cacheKey||this.prefetch.url:null,this.index=new g({datumTokenizer:b.datumTokenizer,queryTokenizer:b.queryTokenizer}),this.storage=this.cacheKey?new e(this.cacheKey):null}function d(a){function c(b){return b.sort(a)}function d(a){return a}return b.isFunction(a)?c:d}function i(){return!1}var j;return j={data:"data",protocol:"protocol",thumbprint:"thumbprint"},c.tokenizers={whitespace:function(a){return a.split(/\s+/)},nonword:function(a){return a.split(/\W+/)}},b.mixin(c.prototype,{_loadPrefetch:function(b){function c(a){var c;c=b.filter?b.filter(a):a,f.add(c),f._saveToStorage(f.index.serialize(),b.thumbprint,b.ttl)}var d,e,f=this;return(d=this._readFromStorage(b.thumbprint))?(this.index.bootstrap(d),e=a.Deferred().resolve()):e=a.ajax(b.url,b.ajax).done(c),e},_getFromRemote:function(a,b){function c(a){var c=f.remote.filter?f.remote.filter(a):a;b(c)}var d,e,f=this;return a=a||"",e=encodeURIComponent(a),d=this.remote.replace?this.remote.replace(this.remote.url,a):this.remote.url.replace(this.remote.wildcard,e),this.transport.get(d,this.remote.ajax,c)},_saveToStorage:function(a,b,c){this.storage&&(this.storage.set(j.data,a,c),this.storage.set(j.protocol,location.protocol,c),this.storage.set(j.thumbprint,b,c))},_readFromStorage:function(a){var b,c={};return this.storage&&(c.data=this.storage.get(j.data),c.protocol=this.storage.get(j.protocol),c.thumbprint=this.storage.get(j.thumbprint)),b=c.thumbprint!==a||c.protocol!==location.protocol,c.data&&!b?c.data:null},initialize:function(){function b(){d.add(d.local)}var c,d=this;return c=this.prefetch?this._loadPrefetch(this.prefetch):a.Deferred().resolve(),this.local&&c.done(b),this.transport=this.remote?new f(this.remote):null,this.initialize=function(){return c.promise()},c.promise()},add:function(a){this.index.add(a)},get:function(a,c){function d(a){var d=e.slice(0);b.each(a,function(a){var c;return c=b.some(d,function(b){return f.dupDetector(a,b)}),!c&&d.push(a),d.length<f.limit}),c&&c(f.sorter(d))}var e,f=this,g=!1;e=this.index.get(a),e=this.sorter(e).slice(0,this.limit),e.length<this.limit&&this.transport&&(g=this._getFromRemote(a,d)),!g&&c&&c(e)},ttAdapter:function(){return b.bind(this.get,this)}}),c}(),{wrapper:'<span class="twitter-typeahead"></span>',dropdown:'<span class="tt-dropdown-menu"></span>',dataset:'<div class="tt-dataset-%CLASS%"></div>',suggestions:'<span class="tt-suggestions"></span>',suggestion:'<div class="tt-suggestion">%BODY%</div>'}),j={wrapper:{position:"relative",display:"inline-block"},hint:{position:"absolute",top:"0",left:"0",borderColor:"transparent",boxShadow:"none"},input:{position:"relative",verticalAlign:"top",backgroundColor:"transparent"},inputWithNoHint:{position:"relative",verticalAlign:"top"},dropdown:{position:"absolute",top:"100%",left:"0",zIndex:"100",display:"none"},suggestions:{display:"block"},suggestion:{whiteSpace:"nowrap",cursor:"pointer"},suggestionChild:{whiteSpace:"normal"},ltr:{left:"0",right:"auto"},rtl:{left:"auto",right:" 0"}};b.isMsie()&&b.mixin(j.input,{backgroundImage:"url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"}),b.isMsie()&&b.isMsie()<=7&&b.mixin(j.input,{marginTop:"-1px"});var k=function(){function c(b){b&&b.el||a.error("EventBus initialized without el"),this.$el=a(b.el)}var d="typeahead:";return b.mixin(c.prototype,{trigger:function(a){var b=[].slice.call(arguments,1);this.$el.trigger(d+a,b)}}),c}(),l=function(){function a(a,b,c,d){var e;if(!c)return this;for(b=b.split(i),c=d?h(c,d):c,this._callbacks=this._callbacks||{};e=b.shift();)this._callbacks[e]=this._callbacks[e]||{sync:[],async:[]},this._callbacks[e][a].push(c);return this}function b(b,c,d){return a.call(this,"async",b,c,d)}function c(b,c,d){return a.call(this,"sync",b,c,d)}function d(a){var b;if(!this._callbacks)return this;for(a=a.split(i);b=a.shift();)delete this._callbacks[b];return this}function e(a){var b,c,d,e,g;if(!this._callbacks)return this;for(a=a.split(i),d=[].slice.call(arguments,1);(b=a.shift())&&(c=this._callbacks[b]);)e=f(c.sync,this,[b].concat(d)),g=f(c.async,this,[b].concat(d)),e()&&j(g);return this}function f(a,b,c){function d(){for(var d,e=0;!d&&e<a.length;e+=1)d=a[e].apply(b,c)===!1;return!d}return d}function g(){var a;return a=window.setImmediate?function(a){setImmediate(function(){a()})}:function(a){setTimeout(function(){a()},0)}}function h(a,b){return a.bind?a.bind(b):function(){a.apply(b,[].slice.call(arguments,0))}}var i=/\s+/,j=g();return{onSync:c,onAsync:b,off:d,trigger:e}}(),m=function(a){function c(a,c,d){for(var e,f=[],g=0;g<a.length;g++)f.push(b.escapeRegExChars(a[g]));return e=d?"\\b("+f.join("|")+")\\b":"("+f.join("|")+")",c?new RegExp(e):new RegExp(e,"i")}var d={node:null,pattern:null,tagName:"strong",className:null,wordsOnly:!1,caseSensitive:!1};return function(e){function f(b){var c,d;return(c=h.exec(b.data))&&(wrapperNode=a.createElement(e.tagName),e.className&&(wrapperNode.className=e.className),d=b.splitText(c.index),d.splitText(c[0].length),wrapperNode.appendChild(d.cloneNode(!0)),b.parentNode.replaceChild(wrapperNode,d)),!!c}function g(a,b){for(var c,d=3,e=0;e<a.childNodes.length;e++)c=a.childNodes[e],c.nodeType===d?e+=b(c)?1:0:g(c,b)}var h;e=b.mixin({},d,e),e.node&&e.pattern&&(e.pattern=b.isArray(e.pattern)?e.pattern:[e.pattern],h=c(e.pattern,e.caseSensitive,e.wordsOnly),g(e.node,f))}}(window.document),n=function(){function c(c){var e,f,h,i,j=this;c=c||{},c.input||a.error("input is missing"),e=b.bind(this._onBlur,this),f=b.bind(this._onFocus,this),h=b.bind(this._onKeydown,this),i=b.bind(this._onInput,this),this.$hint=a(c.hint),this.$input=a(c.input).on("blur.tt",e).on("focus.tt",f).on("keydown.tt",h),0===this.$hint.length&&(this.setHintValue=this.getHintValue=this.clearHint=b.noop),b.isMsie()?this.$input.on("keydown.tt keypress.tt cut.tt paste.tt",function(a){g[a.which||a.keyCode]||b.defer(b.bind(j._onInput,j,a))}):this.$input.on("input.tt",i),this.query=this.$input.val(),this.$overflowHelper=d(this.$input)}function d(b){return a('<pre aria-hidden="true"></pre>').css({position:"absolute",visibility:"hidden",whiteSpace:"nowrap",fontFamily:b.css("font-family"),fontSize:b.css("font-size"),fontStyle:b.css("font-style"),fontVariant:b.css("font-variant"),fontWeight:b.css("font-weight"),wordSpacing:b.css("word-spacing"),letterSpacing:b.css("letter-spacing"),textIndent:b.css("text-indent"),textRendering:b.css("text-rendering"),textTransform:b.css("text-transform")}).insertAfter(b)}function e(a,b){return c.normalizeQuery(a)===c.normalizeQuery(b)}function f(a){return a.altKey||a.ctrlKey||a.metaKey||a.shiftKey}var g;return g={9:"tab",27:"esc",37:"left",39:"right",13:"enter",38:"up",40:"down"},c.normalizeQuery=function(a){return(a||"").replace(/^\s*/g,"").replace(/\s{2,}/g," ")},b.mixin(c.prototype,l,{_onBlur:function(){this.resetInputValue(),this.trigger("blurred")},_onFocus:function(){this.trigger("focused")},_onKeydown:function(a){var b=g[a.which||a.keyCode];this._managePreventDefault(b,a),b&&this._shouldTrigger(b,a)&&this.trigger(b+"Keyed",a)},_onInput:function(){this._checkInputValue()},_managePreventDefault:function(a,b){var c,d,e;switch(a){case"tab":d=this.getHintValue(),e=this.getInputValue(),c=d&&d!==e&&!f(b);break;case"up":case"down":c=!f(b);break;default:c=!1}c&&b.preventDefault()},_shouldTrigger:function(a,b){var c;switch(a){case"tab":c=!f(b);break;default:c=!0}return c},_checkInputValue:function(){var a,b,c;a=this.getInputValue(),b=e(a,this.query),c=b?this.query.length!==a.length:!1,b?c&&this.trigger("whitespaceChanged",this.query):this.trigger("queryChanged",this.query=a)},focus:function(){this.$input.focus()},blur:function(){this.$input.blur()},getQuery:function(){return this.query},setQuery:function(a){this.query=a},getInputValue:function(){return this.$input.val()},setInputValue:function(a,b){this.$input.val(a),!b&&this._checkInputValue()},getHintValue:function(){return this.$hint.val()},setHintValue:function(a){this.$hint.val(a)},resetInputValue:function(){this.$input.val(this.query)},clearHint:function(){this.$hint.val("")},getLanguageDirection:function(){return(this.$input.css("direction")||"ltr").toLowerCase()},hasOverflow:function(){var a=this.$input.width()-2;return this.$overflowHelper.text(this.getInputValue()),this.$overflowHelper.width()>=a},isCursorAtEnd:function(){var a,c,d;return a=this.$input.val().length,c=this.$input[0].selectionStart,b.isNumber(c)?c===a:document.selection?(d=document.selection.createRange(),d.moveStart("character",-a),a===d.text.length):!0},destroy:function(){this.$hint.off(".tt"),this.$input.off(".tt"),this.$hint=this.$input=this.$overflowHelper=null}}),c}(),o=function(){function c(c){c=c||{},c.templates=c.templates||{},c.source||a.error("missing source"),c.name&&!f(c.name)&&a.error("invalid dataset name: "+c.name),this.query=null,this.highlight=!!c.highlight,this.name=c.name||b.getUniqueId(),this.source=c.source,this.displayFn=d(c.display||c.displayKey),this.templates=e(c.templates,this.displayFn),this.$el=a(i.dataset.replace("%CLASS%",this.name))}function d(a){function c(b){return b[a]}return a=a||"value",b.isFunction(a)?a:c}function e(a,c){function d(a){return"<p>"+c(a)+"</p>"}return{empty:a.empty&&b.templatify(a.empty),header:a.header&&b.templatify(a.header),footer:a.footer&&b.templatify(a.footer),suggestion:a.suggestion||d}}function f(a){return/^[_a-zA-Z0-9-]+$/.test(a)}var g="ttDataset",h="ttValue",k="ttDatum";return c.extractDatasetName=function(b){return a(b).data(g)},c.extractValue=function(b){return a(b).data(h)},c.extractDatum=function(b){return a(b).data(k)},b.mixin(c.prototype,l,{_render:function(c,d){function e(){return p.templates.empty({query:c,isEmpty:!0})}function f(){function e(b){var c,d,e;return d=p.templates.suggestion(b),e=i.suggestion.replace("%BODY%",d),c=a(e).data(g,p.name).data(h,p.displayFn(b)).data(k,b),c.children().each(function(){a(this).css(j.suggestionChild)}),c}var f,l;return f=a(i.suggestions).css(j.suggestions),l=b.map(d,e),f.append.apply(f,l),p.highlight&&m({node:f[0],pattern:c}),f}function l(){return p.templates.header({query:c,isEmpty:!o})}function n(){return p.templates.footer({query:c,isEmpty:!o})}if(this.$el){var o,p=this;this.$el.empty(),o=d&&d.length,!o&&this.templates.empty?this.$el.html(e()).prepend(p.templates.header?l():null).append(p.templates.footer?n():null):o&&this.$el.html(f()).prepend(p.templates.header?l():null).append(p.templates.footer?n():null),this.trigger("rendered")}},getRoot:function(){return this.$el},update:function(a){function b(b){a===c.query&&c._render(a,b)}var c=this;this.query=a,this.source(a,b)},clear:function(){this._render(this.query||"")},isEmpty:function(){return this.$el.is(":empty")},destroy:function(){this.$el=null}}),c}(),p=function(){function c(c){var e,f,g,h=this;c=c||{},c.menu||a.error("menu is required"),this.isOpen=!1,this.isEmpty=!0,this.datasets=b.map(c.datasets,d),e=b.bind(this._onSuggestionClick,this),f=b.bind(this._onSuggestionMouseEnter,this),g=b.bind(this._onSuggestionMouseLeave,this),this.$menu=a(c.menu).on("click.tt",".tt-suggestion",e).on("mouseenter.tt",".tt-suggestion",f).on("mouseleave.tt",".tt-suggestion",g),b.each(this.datasets,function(a){h.$menu.append(a.getRoot()),a.onSync("rendered",h._onRendered,h)})}function d(a){return new o(a)}return b.mixin(c.prototype,l,{_onSuggestionClick:function(b){this.trigger("suggestionClicked",a(b.currentTarget))},_onSuggestionMouseEnter:function(b){this._removeCursor(),this._setCursor(a(b.currentTarget),!0)},_onSuggestionMouseLeave:function(){this._removeCursor()},_onRendered:function(){function a(a){return a.isEmpty()}this.isEmpty=b.every(this.datasets,a),this.isEmpty?this._hide():this.isOpen&&this._show(),this.trigger("datasetRendered")},_hide:function(){this.$menu.hide()},_show:function(){this.$menu.css("display","block")},_getSuggestions:function(){return this.$menu.find(".tt-suggestion")},_getCursor:function(){return this.$menu.find(".tt-cursor").first()},_setCursor:function(a,b){a.first().addClass("tt-cursor"),!b&&this.trigger("cursorMoved")},_removeCursor:function(){this._getCursor().removeClass("tt-cursor")},_moveCursor:function(a){var b,c,d,e;if(this.isOpen){if(c=this._getCursor(),b=this._getSuggestions(),this._removeCursor(),d=b.index(c)+a,d=(d+1)%(b.length+1)-1,-1===d)return void this.trigger("cursorRemoved");-1>d&&(d=b.length-1),this._setCursor(e=b.eq(d)),this._ensureVisible(e)}},_ensureVisible:function(a){var b,c,d,e;b=a.position().top,c=b+a.outerHeight(!0),d=this.$menu.scrollTop(),e=this.$menu.height()+parseInt(this.$menu.css("paddingTop"),10)+parseInt(this.$menu.css("paddingBottom"),10),0>b?this.$menu.scrollTop(d+b):c>e&&this.$menu.scrollTop(d+(c-e))},close:function(){this.isOpen&&(this.isOpen=!1,this._removeCursor(),this._hide(),this.trigger("closed"))},open:function(){this.isOpen||(this.isOpen=!0,!this.isEmpty&&this._show(),this.trigger("opened"))},setLanguageDirection:function(a){this.$menu.css("ltr"===a?j.ltr:j.rtl)},moveCursorUp:function(){this._moveCursor(-1)},moveCursorDown:function(){this._moveCursor(1)},getDatumForSuggestion:function(a){var b=null;return a.length&&(b={raw:o.extractDatum(a),value:o.extractValue(a),datasetName:o.extractDatasetName(a)}),b},getDatumForCursor:function(){return this.getDatumForSuggestion(this._getCursor().first())},getDatumForTopSuggestion:function(){return this.getDatumForSuggestion(this._getSuggestions().first())},update:function(a){function c(b){b.update(a)}b.each(this.datasets,c)},empty:function(){function a(a){a.clear()}b.each(this.datasets,a),this.isEmpty=!0},isVisible:function(){return this.isOpen&&!this.isEmpty},destroy:function(){function a(a){a.destroy()}this.$menu.off(".tt"),this.$menu=null,b.each(this.datasets,a)}}),c}(),q=function(){function c(c){var e,f,g;c=c||{},c.input||a.error("missing input"),this.autoselect=!!c.autoselect,this.minLength=b.isNumber(c.minLength)?c.minLength:1,this.$node=d(c.input,c.withHint),e=this.$node.find(".tt-dropdown-menu"),f=this.$node.find(".tt-input"),g=this.$node.find(".tt-hint"),this.eventBus=c.eventBus||new k({el:f}),this.dropdown=new p({menu:e,datasets:c.datasets}).onSync("suggestionClicked",this._onSuggestionClicked,this).onSync("cursorMoved",this._onCursorMoved,this).onSync("cursorRemoved",this._onCursorRemoved,this).onSync("opened",this._onOpened,this).onSync("closed",this._onClosed,this).onAsync("datasetRendered",this._onDatasetRendered,this),this.input=new n({input:f,hint:g}).onSync("focused",this._onFocused,this).onSync("blurred",this._onBlurred,this).onSync("enterKeyed",this._onEnterKeyed,this).onSync("tabKeyed",this._onTabKeyed,this).onSync("escKeyed",this._onEscKeyed,this).onSync("upKeyed",this._onUpKeyed,this).onSync("downKeyed",this._onDownKeyed,this).onSync("leftKeyed",this._onLeftKeyed,this).onSync("rightKeyed",this._onRightKeyed,this).onSync("queryChanged",this._onQueryChanged,this).onSync("whitespaceChanged",this._onWhitespaceChanged,this),e.on("mousedown.tt",function(a){b.isMsie()&&b.isMsie()<9&&(f[0].onbeforedeactivate=function(){window.event.returnValue=!1,f[0].onbeforedeactivate=null}),a.preventDefault()})}function d(b,c){var d,f,h,k;d=a(b),f=a(i.wrapper).css(j.wrapper),h=a(i.dropdown).css(j.dropdown),k=d.clone().css(j.hint).css(e(d)),k.val("").removeData().addClass("tt-hint").removeAttr("id name placeholder").prop("disabled",!0).attr({autocomplete:"off",spellcheck:"false"}),d.data(g,{dir:d.attr("dir"),autocomplete:d.attr("autocomplete"),spellcheck:d.attr("spellcheck"),style:d.attr("style")}),d.addClass("tt-input").attr({autocomplete:"off",spellcheck:!1}).css(c?j.input:j.inputWithNoHint);try{!d.attr("dir")&&d.attr("dir","auto")}catch(l){}return d.wrap(f).parent().prepend(c?k:null).append(h)}function e(a){return{backgroundAttachment:a.css("background-attachment"),backgroundClip:a.css("background-clip"),backgroundColor:a.css("background-color"),backgroundImage:a.css("background-image"),backgroundOrigin:a.css("background-origin"),backgroundPosition:a.css("background-position"),backgroundRepeat:a.css("background-repeat"),backgroundSize:a.css("background-size")}}function f(a){var c=a.find(".tt-input");b.each(c.data(g),function(a,d){b.isUndefined(a)?c.removeAttr(d):c.attr(d,a)}),c.detach().removeData(g).removeClass("tt-input").insertAfter(a),a.remove()}var g="ttAttrs";return b.mixin(c.prototype,{_onSuggestionClicked:function(a,b){var c;(c=this.dropdown.getDatumForSuggestion(b))&&this._select(c)},_onCursorMoved:function(){var a=this.dropdown.getDatumForCursor();this.input.clearHint(),this.input.setInputValue(a.value,!0),this.eventBus.trigger("cursorchanged",a.raw,a.datasetName)},_onCursorRemoved:function(){this.input.resetInputValue(),this._updateHint()},_onDatasetRendered:function(){this._updateHint()},_onOpened:function(){this._updateHint(),this.eventBus.trigger("opened")},_onClosed:function(){this.input.clearHint(),this.eventBus.trigger("closed")},_onFocused:function(){this.dropdown.empty(),this.dropdown.open()},_onBlurred:function(){this.dropdown.close()},_onEnterKeyed:function(a,b){var c,d;c=this.dropdown.getDatumForCursor(),d=this.dropdown.getDatumForTopSuggestion(),c?(this._select(c),b.preventDefault()):this.autoselect&&d&&(this._select(d),b.preventDefault())},_onTabKeyed:function(a,b){var c;(c=this.dropdown.getDatumForCursor())?(this._select(c),b.preventDefault()):this._autocomplete()},_onEscKeyed:function(){this.dropdown.close(),this.input.resetInputValue()},_onUpKeyed:function(){var a=this.input.getQuery();!this.dropdown.isOpen&&a.length>=this.minLength&&this.dropdown.update(a),this.dropdown.open(),this.dropdown.moveCursorUp()},_onDownKeyed:function(){var a=this.input.getQuery();!this.dropdown.isOpen&&a.length>=this.minLength&&this.dropdown.update(a),this.dropdown.open(),this.dropdown.moveCursorDown()},_onLeftKeyed:function(){"rtl"===this.dir&&this._autocomplete()},_onRightKeyed:function(){"ltr"===this.dir&&this._autocomplete()},_onQueryChanged:function(a,b){this.input.clearHint(),this.dropdown.empty(),b.length>=this.minLength&&this.dropdown.update(b),this.dropdown.open(),this._setLanguageDirection()},_onWhitespaceChanged:function(){this._updateHint(),this.dropdown.open()},_setLanguageDirection:function(){var a;this.dir!==(a=this.input.getLanguageDirection())&&(this.dir=a,this.$node.css("direction",a),this.dropdown.setLanguageDirection(a))},_updateHint:function(){var a,c,d,e,f,g;a=this.dropdown.getDatumForTopSuggestion(),a&&this.dropdown.isVisible()&&!this.input.hasOverflow()&&(c=this.input.getInputValue(),d=n.normalizeQuery(c),e=b.escapeRegExChars(d),f=new RegExp("^(?:"+e+")(.*$)","i"),g=f.exec(a.value),this.input.setHintValue(c+(g?g[1]:"")))},_autocomplete:function(){var a,b,c;a=this.input.getHintValue(),b=this.input.getQuery(),a&&b!==a&&this.input.isCursorAtEnd()&&(c=this.dropdown.getDatumForTopSuggestion(),c&&this.input.setInputValue(c.value),this.eventBus.trigger("autocompleted",c.raw,c.datasetName))},_select:function(a){this.input.clearHint(),this.input.setQuery(a.value),this.input.setInputValue(a.value,!0),this._setLanguageDirection(),this.eventBus.trigger("selected",a.raw,a.datasetName),this.dropdown.close(),b.defer(b.bind(this.dropdown.empty,this.dropdown))},open:function(){this.dropdown.open()},close:function(){this.dropdown.close()},getQuery:function(){return this.input.getQuery()},setQuery:function(a){this.input.setInputValue(a)},destroy:function(){this.input.destroy(),this.dropdown.destroy(),f(this.$node),this.$node=null}}),c}();!function(){var c,d,e;c=a.fn.typeahead,d="ttTypeahead",e={initialize:function(c,e){function f(){var f,g,h=a(this);b.each(e,function(a){a.highlight=!!c.highlight}),g=new q({input:h,eventBus:f=new k({el:h}),withHint:b.isUndefined(c.hint)?!0:!!c.hint,minLength:c.minLength,autoselect:c.autoselect,datasets:e}),h.data(d,g)}return e=b.isArray(e)?e:[].slice.call(arguments,1),c=c||{},this.each(f)},open:function(){function b(){var b,c=a(this);(b=c.data(d))&&b.open()}return this.each(b)},close:function(){function b(){var b,c=a(this);(b=c.data(d))&&b.close()}return this.each(b)},val:function(b){function c(){var c,e=a(this);(c=e.data(d))&&c.setQuery(b)}function e(a){var b,c;return(b=a.data(d))&&(c=b.getQuery()),c}return arguments.length?this.each(c):e(this.first())},destroy:function(){function b(){var b,c=a(this);(b=c.data(d))&&(b.destroy(),c.removeData(d))}return this.each(b)}},a.fn.typeahead=function(a){return e[a]?e[a].apply(this,[].slice.call(arguments,1)):e.initialize.apply(this,arguments)},a.fn.typeahead.noConflict=function(){return a.fn.typeahead=c,this}}()}(window.jQuery); | ||
!function(a){var b={isMsie:function(){return/(msie|trident)/i.test(navigator.userAgent)?navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2]:!1},isBlankString:function(a){return!a||/^\s*$/.test(a)},escapeRegExChars:function(a){return a.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")},isString:function(a){return"string"==typeof a},isNumber:function(a){return"number"==typeof a},isArray:a.isArray,isFunction:a.isFunction,isObject:a.isPlainObject,isUndefined:function(a){return"undefined"==typeof a},bind:a.proxy,each:function(b,c){function d(a,b){return c(b,a)}a.each(b,d)},map:a.map,filter:a.grep,every:function(b,c){var d=!0;return b?(a.each(b,function(a,e){return(d=c.call(null,e,a,b))?void 0:!1}),!!d):d},some:function(b,c){var d=!1;return b?(a.each(b,function(a,e){return(d=c.call(null,e,a,b))?!1:void 0}),!!d):d},mixin:a.extend,getUniqueId:function(){var a=0;return function(){return a++}}(),templatify:function(b){function c(){return String(b)}return a.isFunction(b)?b:c},defer:function(a){setTimeout(a,0)},debounce:function(a,b,c){var d,e;return function(){var f,g,h=this,i=arguments;return f=function(){d=null,c||(e=a.apply(h,i))},g=c&&!d,clearTimeout(d),d=setTimeout(f,b),g&&(e=a.apply(h,i)),e}},throttle:function(a,b){var c,d,e,f,g,h;return g=0,h=function(){g=new Date,e=null,f=a.apply(c,d)},function(){var i=new Date,j=b-(i-g);return c=this,d=arguments,0>=j?(clearTimeout(e),e=null,g=i,f=a.apply(c,d)):e||(e=setTimeout(h,j)),f}},noop:function(){}},c="0.10.2",d=function(){function a(a){return a.split(/\s+/)}function b(a){return a.split(/\W+/)}function c(a){return function(b){return function(c){return a(c[b])}}}return{nonword:b,whitespace:a,obj:{nonword:c(b),whitespace:c(a)}}}(),e=function(){function a(a){this.maxSize=a||100,this.size=0,this.hash={},this.list=new c}function c(){this.head=this.tail=null}function d(a,b){this.key=a,this.val=b,this.prev=this.next=null}return b.mixin(a.prototype,{set:function(a,b){var c,e=this.list.tail;this.size>=this.maxSize&&(this.list.remove(e),delete this.hash[e.key]),(c=this.hash[a])?(c.val=b,this.list.moveToFront(c)):(c=new d(a,b),this.list.add(c),this.hash[a]=c,this.size++)},get:function(a){var b=this.hash[a];return b?(this.list.moveToFront(b),b.val):void 0}}),b.mixin(c.prototype,{add:function(a){this.head&&(a.next=this.head,this.head.prev=a),this.head=a,this.tail=this.tail||a},remove:function(a){a.prev?a.prev.next=a.next:this.head=a.next,a.next?a.next.prev=a.prev:this.tail=a.prev},moveToFront:function(a){this.remove(a),this.add(a)}}),a}(),f=function(){function a(a){this.prefix=["__",a,"__"].join(""),this.ttlKey="__ttl__",this.keyMatcher=new RegExp("^"+this.prefix)}function c(){return(new Date).getTime()}function d(a){return JSON.stringify(b.isUndefined(a)?null:a)}function e(a){return JSON.parse(a)}var f,g;try{f=window.localStorage,f.setItem("~~~","!"),f.removeItem("~~~")}catch(h){f=null}return g=f&&window.JSON?{_prefix:function(a){return this.prefix+a},_ttlKey:function(a){return this._prefix(a)+this.ttlKey},get:function(a){return this.isExpired(a)&&this.remove(a),e(f.getItem(this._prefix(a)))},set:function(a,e,g){return b.isNumber(g)?f.setItem(this._ttlKey(a),d(c()+g)):f.removeItem(this._ttlKey(a)),f.setItem(this._prefix(a),d(e))},remove:function(a){return f.removeItem(this._ttlKey(a)),f.removeItem(this._prefix(a)),this},clear:function(){var a,b,c=[],d=f.length;for(a=0;d>a;a++)(b=f.key(a)).match(this.keyMatcher)&&c.push(b.replace(this.keyMatcher,""));for(a=c.length;a--;)this.remove(c[a]);return this},isExpired:function(a){var d=e(f.getItem(this._ttlKey(a)));return b.isNumber(d)&&c()>d?!0:!1}}:{get:b.noop,set:b.noop,remove:b.noop,clear:b.noop,isExpired:b.noop},b.mixin(a.prototype,g),a}(),g=function(){function c(b){b=b||{},this._send=b.transport?d(b.transport):a.ajax,this._get=b.rateLimiter?b.rateLimiter(this._get):this._get}function d(c){return function(d,e){function f(a){b.defer(function(){h.resolve(a)})}function g(a){b.defer(function(){h.reject(a)})}var h=a.Deferred();return c(d,e,f,g),h}}var f=0,g={},h=6,i=new e(10);return c.setMaxPendingRequests=function(a){h=a},c.resetCache=function(){i=new e(10)},b.mixin(c.prototype,{_get:function(a,b,c){function d(b){c&&c(null,b),i.set(a,b)}function e(){c&&c(!0)}function j(){f--,delete g[a],l.onDeckRequestArgs&&(l._get.apply(l,l.onDeckRequestArgs),l.onDeckRequestArgs=null)}var k,l=this;(k=g[a])?k.done(d).fail(e):h>f?(f++,g[a]=this._send(a,b).done(d).fail(e).always(j)):this.onDeckRequestArgs=[].slice.call(arguments,0)},get:function(a,c,d){var e;return b.isFunction(c)&&(d=c,c={}),(e=i.get(a))?b.defer(function(){d&&d(null,e)}):this._get(a,c,d),!!e}}),c}(),h=function(){function c(b){b=b||{},b.datumTokenizer&&b.queryTokenizer||a.error("datumTokenizer and queryTokenizer are both required"),this.datumTokenizer=b.datumTokenizer,this.queryTokenizer=b.queryTokenizer,this.reset()}function d(a){return a=b.filter(a,function(a){return!!a}),a=b.map(a,function(a){return a.toLowerCase()})}function e(){return{ids:[],children:{}}}function f(a){for(var b={},c=[],d=0;d<a.length;d++)b[a[d]]||(b[a[d]]=!0,c.push(a[d]));return c}function g(a,b){function c(a,b){return a-b}var d=0,e=0,f=[];for(a=a.sort(c),b=b.sort(c);d<a.length&&e<b.length;)a[d]<b[e]?d++:a[d]>b[e]?e++:(f.push(a[d]),d++,e++);return f}return b.mixin(c.prototype,{bootstrap:function(a){this.datums=a.datums,this.trie=a.trie},add:function(a){var c=this;a=b.isArray(a)?a:[a],b.each(a,function(a){var f,g;f=c.datums.push(a)-1,g=d(c.datumTokenizer(a)),b.each(g,function(a){var b,d,g;for(b=c.trie,d=a.split("");g=d.shift();)b=b.children[g]||(b.children[g]=e()),b.ids.push(f)})})},get:function(a){var c,e,h=this;return c=d(this.queryTokenizer(a)),b.each(c,function(a){var b,c,d,f;if(e&&0===e.length)return!1;for(b=h.trie,c=a.split("");b&&(d=c.shift());)b=b.children[d];return b&&0===c.length?(f=b.ids.slice(0),void(e=e?g(e,f):f)):(e=[],!1)}),e?b.map(f(e),function(a){return h.datums[a]}):[]},reset:function(){this.datums=[],this.trie=e()},serialize:function(){return{datums:this.datums,trie:this.trie}}}),c}(),i=function(){function d(a){return a.local||null}function e(d){var e,f;return f={url:null,thumbprint:"",ttl:864e5,filter:null,ajax:{}},(e=d.prefetch||null)&&(e=b.isString(e)?{url:e}:e,e=b.mixin(f,e),e.thumbprint=c+e.thumbprint,e.ajax.type=e.ajax.type||"GET",e.ajax.dataType=e.ajax.dataType||"json",!e.url&&a.error("prefetch requires url to be set")),e}function f(c){function d(a){return function(c){return b.debounce(c,a)}}function e(a){return function(c){return b.throttle(c,a)}}var f,g;return g={url:null,wildcard:"%QUERY",replace:null,rateLimitBy:"debounce",rateLimitWait:300,send:null,filter:null,ajax:{}},(f=c.remote||null)&&(f=b.isString(f)?{url:f}:f,f=b.mixin(g,f),f.rateLimiter=/^throttle$/i.test(f.rateLimitBy)?e(f.rateLimitWait):d(f.rateLimitWait),f.ajax.type=f.ajax.type||"GET",f.ajax.dataType=f.ajax.dataType||"json",delete f.rateLimitBy,delete f.rateLimitWait,!f.url&&a.error("remote requires url to be set")),f}return{local:d,prefetch:e,remote:f}}();!function(c){function e(b){b&&(b.local||b.prefetch||b.remote)||a.error("one of local, prefetch, or remote is required"),this.limit=b.limit||5,this.sorter=j(b.sorter),this.dupDetector=b.dupDetector||k,this.local=i.local(b),this.prefetch=i.prefetch(b),this.remote=i.remote(b),this.cacheKey=this.prefetch?this.prefetch.cacheKey||this.prefetch.url:null,this.index=new h({datumTokenizer:b.datumTokenizer,queryTokenizer:b.queryTokenizer}),this.storage=this.cacheKey?new f(this.cacheKey):null}function j(a){function c(b){return b.sort(a)}function d(a){return a}return b.isFunction(a)?c:d}function k(){return!1}var l,m;return l=c.Bloodhound,m={data:"data",protocol:"protocol",thumbprint:"thumbprint"},c.Bloodhound=e,e.noConflict=function(){return c.Bloodhound=l,e},e.tokenizers=d,b.mixin(e.prototype,{_loadPrefetch:function(b){function c(a){f.clear(),f.add(b.filter?b.filter(a):a),f._saveToStorage(f.index.serialize(),b.thumbprint,b.ttl)}var d,e,f=this;return(d=this._readFromStorage(b.thumbprint))?(this.index.bootstrap(d),e=a.Deferred().resolve()):e=a.ajax(b.url,b.ajax).done(c),e},_getFromRemote:function(a,b){function c(a,c){b(a?[]:f.remote.filter?f.remote.filter(c):c)}var d,e,f=this;return a=a||"",e=encodeURIComponent(a),d=this.remote.replace?this.remote.replace(this.remote.url,a):this.remote.url.replace(this.remote.wildcard,e),this.transport.get(d,this.remote.ajax,c)},_saveToStorage:function(a,b,c){this.storage&&(this.storage.set(m.data,a,c),this.storage.set(m.protocol,location.protocol,c),this.storage.set(m.thumbprint,b,c))},_readFromStorage:function(a){var b,c={};return this.storage&&(c.data=this.storage.get(m.data),c.protocol=this.storage.get(m.protocol),c.thumbprint=this.storage.get(m.thumbprint)),b=c.thumbprint!==a||c.protocol!==location.protocol,c.data&&!b?c.data:null},_initialize:function(){function c(){e.add(b.isFunction(f)?f():f)}var d,e=this,f=this.local;return d=this.prefetch?this._loadPrefetch(this.prefetch):a.Deferred().resolve(),f&&d.done(c),this.transport=this.remote?new g(this.remote):null,this.initPromise=d.promise()},initialize:function(a){return!this.initPromise||a?this._initialize():this.initPromise},add:function(a){this.index.add(a)},get:function(a,c){function d(a){var d=f.slice(0);b.each(a,function(a){var c;return c=b.some(d,function(b){return e.dupDetector(a,b)}),!c&&d.push(a),d.length<e.limit}),c&&c(e.sorter(d))}var e=this,f=[],g=!1;f=this.index.get(a),f=this.sorter(f).slice(0,this.limit),f.length<this.limit&&this.transport&&(g=this._getFromRemote(a,d)),g||(f.length>0||!this.transport)&&c&&c(f)},clear:function(){this.index.reset()},clearPrefetchCache:function(){this.storage&&this.storage.clear()},clearRemoteCache:function(){this.transport&&g.resetCache()},ttAdapter:function(){return b.bind(this.get,this)}}),e}(this);var j={wrapper:'<span class="twitter-typeahead"></span>',dropdown:'<span class="tt-dropdown-menu"></span>',dataset:'<div class="tt-dataset-%CLASS%"></div>',suggestions:'<span class="tt-suggestions"></span>',suggestion:'<div class="tt-suggestion"></div>'},k={wrapper:{position:"relative",display:"inline-block"},hint:{position:"absolute",top:"0",left:"0",borderColor:"transparent",boxShadow:"none"},input:{position:"relative",verticalAlign:"top",backgroundColor:"transparent"},inputWithNoHint:{position:"relative",verticalAlign:"top"},dropdown:{position:"absolute",top:"100%",left:"0",zIndex:"100",display:"none"},suggestions:{display:"block"},suggestion:{whiteSpace:"nowrap",cursor:"pointer"},suggestionChild:{whiteSpace:"normal"},ltr:{left:"0",right:"auto"},rtl:{left:"auto",right:" 0"}};b.isMsie()&&b.mixin(k.input,{backgroundImage:"url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"}),b.isMsie()&&b.isMsie()<=7&&b.mixin(k.input,{marginTop:"-1px"});var l=function(){function c(b){b&&b.el||a.error("EventBus initialized without el"),this.$el=a(b.el)}var d="typeahead:";return b.mixin(c.prototype,{trigger:function(a){var b=[].slice.call(arguments,1);this.$el.trigger(d+a,b)}}),c}(),m=function(){function a(a,b,c,d){var e;if(!c)return this;for(b=b.split(i),c=d?h(c,d):c,this._callbacks=this._callbacks||{};e=b.shift();)this._callbacks[e]=this._callbacks[e]||{sync:[],async:[]},this._callbacks[e][a].push(c);return this}function b(b,c,d){return a.call(this,"async",b,c,d)}function c(b,c,d){return a.call(this,"sync",b,c,d)}function d(a){var b;if(!this._callbacks)return this;for(a=a.split(i);b=a.shift();)delete this._callbacks[b];return this}function e(a){var b,c,d,e,g;if(!this._callbacks)return this;for(a=a.split(i),d=[].slice.call(arguments,1);(b=a.shift())&&(c=this._callbacks[b]);)e=f(c.sync,this,[b].concat(d)),g=f(c.async,this,[b].concat(d)),e()&&j(g);return this}function f(a,b,c){function d(){for(var d,e=0;!d&&e<a.length;e+=1)d=a[e].apply(b,c)===!1;return!d}return d}function g(){var a;return a=window.setImmediate?function(a){setImmediate(function(){a()})}:function(a){setTimeout(function(){a()},0)}}function h(a,b){return a.bind?a.bind(b):function(){a.apply(b,[].slice.call(arguments,0))}}var i=/\s+/,j=g();return{onSync:c,onAsync:b,off:d,trigger:e}}(),n=function(a){function c(a,c,d){for(var e,f=[],g=0;g<a.length;g++)f.push(b.escapeRegExChars(a[g]));return e=d?"\\b("+f.join("|")+")\\b":"("+f.join("|")+")",c?new RegExp(e):new RegExp(e,"i")}var d={node:null,pattern:null,tagName:"strong",className:null,wordsOnly:!1,caseSensitive:!1};return function(e){function f(b){var c,d;return(c=h.exec(b.data))&&(wrapperNode=a.createElement(e.tagName),e.className&&(wrapperNode.className=e.className),d=b.splitText(c.index),d.splitText(c[0].length),wrapperNode.appendChild(d.cloneNode(!0)),b.parentNode.replaceChild(wrapperNode,d)),!!c}function g(a,b){for(var c,d=3,e=0;e<a.childNodes.length;e++)c=a.childNodes[e],c.nodeType===d?e+=b(c)?1:0:g(c,b)}var h;e=b.mixin({},d,e),e.node&&e.pattern&&(e.pattern=b.isArray(e.pattern)?e.pattern:[e.pattern],h=c(e.pattern,e.caseSensitive,e.wordsOnly),g(e.node,f))}}(window.document),o=function(){function c(c){var e,f,h,i,j=this;c=c||{},c.input||a.error("input is missing"),e=b.bind(this._onBlur,this),f=b.bind(this._onFocus,this),h=b.bind(this._onKeydown,this),i=b.bind(this._onInput,this),this.$hint=a(c.hint),this.$input=a(c.input).on("blur.tt",e).on("focus.tt",f).on("keydown.tt",h),0===this.$hint.length&&(this.setHint=this.getHint=this.clearHint=this.clearHintIfInvalid=b.noop),b.isMsie()?this.$input.on("keydown.tt keypress.tt cut.tt paste.tt",function(a){g[a.which||a.keyCode]||b.defer(b.bind(j._onInput,j,a))}):this.$input.on("input.tt",i),this.query=this.$input.val(),this.$overflowHelper=d(this.$input)}function d(b){return a('<pre aria-hidden="true"></pre>').css({position:"absolute",visibility:"hidden",whiteSpace:"pre",fontFamily:b.css("font-family"),fontSize:b.css("font-size"),fontStyle:b.css("font-style"),fontVariant:b.css("font-variant"),fontWeight:b.css("font-weight"),wordSpacing:b.css("word-spacing"),letterSpacing:b.css("letter-spacing"),textIndent:b.css("text-indent"),textRendering:b.css("text-rendering"),textTransform:b.css("text-transform")}).insertAfter(b)}function e(a,b){return c.normalizeQuery(a)===c.normalizeQuery(b)}function f(a){return a.altKey||a.ctrlKey||a.metaKey||a.shiftKey}var g;return g={9:"tab",27:"esc",37:"left",39:"right",13:"enter",38:"up",40:"down"},c.normalizeQuery=function(a){return(a||"").replace(/^\s*/g,"").replace(/\s{2,}/g," ")},b.mixin(c.prototype,m,{_onBlur:function(){this.resetInputValue(),this.trigger("blurred")},_onFocus:function(){this.trigger("focused")},_onKeydown:function(a){var b=g[a.which||a.keyCode];this._managePreventDefault(b,a),b&&this._shouldTrigger(b,a)&&this.trigger(b+"Keyed",a)},_onInput:function(){this._checkInputValue()},_managePreventDefault:function(a,b){var c,d,e;switch(a){case"tab":d=this.getHint(),e=this.getInputValue(),c=d&&d!==e&&!f(b);break;case"up":case"down":c=!f(b);break;default:c=!1}c&&b.preventDefault()},_shouldTrigger:function(a,b){var c;switch(a){case"tab":c=!f(b);break;default:c=!0}return c},_checkInputValue:function(){var a,b,c;a=this.getInputValue(),b=e(a,this.query),c=b?this.query.length!==a.length:!1,b?c&&this.trigger("whitespaceChanged",this.query):this.trigger("queryChanged",this.query=a)},focus:function(){this.$input.focus()},blur:function(){this.$input.blur()},getQuery:function(){return this.query},setQuery:function(a){this.query=a},getInputValue:function(){return this.$input.val()},setInputValue:function(a,b){this.$input.val(a),b?this.clearHint():this._checkInputValue()},resetInputValue:function(){this.setInputValue(this.query,!0)},getHint:function(){return this.$hint.val()},setHint:function(a){this.$hint.val(a)},clearHint:function(){this.setHint("")},clearHintIfInvalid:function(){var a,b,c,d;a=this.getInputValue(),b=this.getHint(),c=a!==b&&0===b.indexOf(a),d=""!==a&&c&&!this.hasOverflow(),!d&&this.clearHint()},getLanguageDirection:function(){return(this.$input.css("direction")||"ltr").toLowerCase()},hasOverflow:function(){var a=this.$input.width()-2;return this.$overflowHelper.text(this.getInputValue()),this.$overflowHelper.width()>=a},isCursorAtEnd:function(){var a,c,d;return a=this.$input.val().length,c=this.$input[0].selectionStart,b.isNumber(c)?c===a:document.selection?(d=document.selection.createRange(),d.moveStart("character",-a),a===d.text.length):!0},destroy:function(){this.$hint.off(".tt"),this.$input.off(".tt"),this.$hint=this.$input=this.$overflowHelper=null}}),c}(),p=function(){function c(c){c=c||{},c.templates=c.templates||{},c.source||a.error("missing source"),c.name&&!f(c.name)&&a.error("invalid dataset name: "+c.name),this.query=null,this.highlight=!!c.highlight,this.name=c.name||b.getUniqueId(),this.source=c.source,this.displayFn=d(c.display||c.displayKey),this.templates=e(c.templates,this.displayFn),this.$el=a(j.dataset.replace("%CLASS%",this.name))}function d(a){function c(b){return b[a]}return a=a||"value",b.isFunction(a)?a:c}function e(a,c){function d(a){return"<p>"+c(a)+"</p>"}return{empty:a.empty&&b.templatify(a.empty),header:a.header&&b.templatify(a.header),footer:a.footer&&b.templatify(a.footer),suggestion:a.suggestion||d}}function f(a){return/^[_a-zA-Z0-9-]+$/.test(a)}var g="ttDataset",h="ttValue",i="ttDatum";return c.extractDatasetName=function(b){return a(b).data(g)},c.extractValue=function(b){return a(b).data(h)},c.extractDatum=function(b){return a(b).data(i)},b.mixin(c.prototype,m,{_render:function(c,d){function e(){return p.templates.empty({query:c,isEmpty:!0})}function f(){function e(b){var c;return c=a(j.suggestion).append(p.templates.suggestion(b)).data(g,p.name).data(h,p.displayFn(b)).data(i,b),c.children().each(function(){a(this).css(k.suggestionChild)}),c}var f,l;return f=a(j.suggestions).css(k.suggestions),l=b.map(d,e),f.append.apply(f,l),p.highlight&&n({node:f[0],pattern:c}),f}function l(){return p.templates.header({query:c,isEmpty:!o})}function m(){return p.templates.footer({query:c,isEmpty:!o})}if(this.$el){var o,p=this;this.$el.empty(),o=d&&d.length,!o&&this.templates.empty?this.$el.html(e()).prepend(p.templates.header?l():null).append(p.templates.footer?m():null):o&&this.$el.html(f()).prepend(p.templates.header?l():null).append(p.templates.footer?m():null),this.trigger("rendered")}},getRoot:function(){return this.$el},update:function(a){function b(b){c.canceled||a!==c.query||c._render(a,b)}var c=this;this.query=a,this.canceled=!1,this.source(a,b)},cancel:function(){this.canceled=!0},clear:function(){this.cancel(),this.$el.empty(),this.trigger("rendered")},isEmpty:function(){return this.$el.is(":empty")},destroy:function(){this.$el=null}}),c}(),q=function(){function c(c){var e,f,g,h=this;c=c||{},c.menu||a.error("menu is required"),this.isOpen=!1,this.isEmpty=!0,this.datasets=b.map(c.datasets,d),e=b.bind(this._onSuggestionClick,this),f=b.bind(this._onSuggestionMouseEnter,this),g=b.bind(this._onSuggestionMouseLeave,this),this.$menu=a(c.menu).on("click.tt",".tt-suggestion",e).on("mouseenter.tt",".tt-suggestion",f).on("mouseleave.tt",".tt-suggestion",g),b.each(this.datasets,function(a){h.$menu.append(a.getRoot()),a.onSync("rendered",h._onRendered,h)})}function d(a){return new p(a)}return b.mixin(c.prototype,m,{_onSuggestionClick:function(b){this.trigger("suggestionClicked",a(b.currentTarget))},_onSuggestionMouseEnter:function(b){this._removeCursor(),this._setCursor(a(b.currentTarget),!0)},_onSuggestionMouseLeave:function(){this._removeCursor()},_onRendered:function(){function a(a){return a.isEmpty()}this.isEmpty=b.every(this.datasets,a),this.isEmpty?this._hide():this.isOpen&&this._show(),this.trigger("datasetRendered")},_hide:function(){this.$menu.hide()},_show:function(){this.$menu.css("display","block")},_getSuggestions:function(){return this.$menu.find(".tt-suggestion")},_getCursor:function(){return this.$menu.find(".tt-cursor").first()},_setCursor:function(a,b){a.first().addClass("tt-cursor"),!b&&this.trigger("cursorMoved")},_removeCursor:function(){this._getCursor().removeClass("tt-cursor")},_moveCursor:function(a){var b,c,d,e;if(this.isOpen){if(c=this._getCursor(),b=this._getSuggestions(),this._removeCursor(),d=b.index(c)+a,d=(d+1)%(b.length+1)-1,-1===d)return void this.trigger("cursorRemoved");-1>d&&(d=b.length-1),this._setCursor(e=b.eq(d)),this._ensureVisible(e)}},_ensureVisible:function(a){var b,c,d,e;b=a.position().top,c=b+a.outerHeight(!0),d=this.$menu.scrollTop(),e=this.$menu.height()+parseInt(this.$menu.css("paddingTop"),10)+parseInt(this.$menu.css("paddingBottom"),10),0>b?this.$menu.scrollTop(d+b):c>e&&this.$menu.scrollTop(d+(c-e))},close:function(){this.isOpen&&(this.isOpen=!1,this._removeCursor(),this._hide(),this.trigger("closed"))},open:function(){this.isOpen||(this.isOpen=!0,!this.isEmpty&&this._show(),this.trigger("opened"))},setLanguageDirection:function(a){this.$menu.css("ltr"===a?k.ltr:k.rtl)},moveCursorUp:function(){this._moveCursor(-1)},moveCursorDown:function(){this._moveCursor(1)},getDatumForSuggestion:function(a){var b=null;return a.length&&(b={raw:p.extractDatum(a),value:p.extractValue(a),datasetName:p.extractDatasetName(a)}),b},getDatumForCursor:function(){return this.getDatumForSuggestion(this._getCursor().first())},getDatumForTopSuggestion:function(){return this.getDatumForSuggestion(this._getSuggestions().first())},update:function(a){function c(b){b.update(a)}b.each(this.datasets,c)},empty:function(){function a(a){a.clear()}b.each(this.datasets,a),this.isEmpty=!0},isVisible:function(){return this.isOpen&&!this.isEmpty},destroy:function(){function a(a){a.destroy()}this.$menu.off(".tt"),this.$menu=null,b.each(this.datasets,a)}}),c}(),r=function(){function c(c){var e,f,g;c=c||{},c.input||a.error("missing input"),this.isActivated=!1,this.autoselect=!!c.autoselect,this.minLength=b.isNumber(c.minLength)?c.minLength:1,this.$node=d(c.input,c.withHint),e=this.$node.find(".tt-dropdown-menu"),f=this.$node.find(".tt-input"),g=this.$node.find(".tt-hint"),f.on("blur.tt",function(a){var c,d,g;c=document.activeElement,d=e.is(c),g=e.has(c).length>0,b.isMsie()&&(d||g)&&(a.preventDefault(),a.stopImmediatePropagation(),b.defer(function(){f.focus()}))}),e.on("mousedown.tt",function(a){a.preventDefault()}),this.eventBus=c.eventBus||new l({el:f}),this.dropdown=new q({menu:e,datasets:c.datasets}).onSync("suggestionClicked",this._onSuggestionClicked,this).onSync("cursorMoved",this._onCursorMoved,this).onSync("cursorRemoved",this._onCursorRemoved,this).onSync("opened",this._onOpened,this).onSync("closed",this._onClosed,this).onAsync("datasetRendered",this._onDatasetRendered,this),this.input=new o({input:f,hint:g}).onSync("focused",this._onFocused,this).onSync("blurred",this._onBlurred,this).onSync("enterKeyed",this._onEnterKeyed,this).onSync("tabKeyed",this._onTabKeyed,this).onSync("escKeyed",this._onEscKeyed,this).onSync("upKeyed",this._onUpKeyed,this).onSync("downKeyed",this._onDownKeyed,this).onSync("leftKeyed",this._onLeftKeyed,this).onSync("rightKeyed",this._onRightKeyed,this).onSync("queryChanged",this._onQueryChanged,this).onSync("whitespaceChanged",this._onWhitespaceChanged,this),this._setLanguageDirection()}function d(b,c){var d,f,h,i;d=a(b),f=a(j.wrapper).css(k.wrapper),h=a(j.dropdown).css(k.dropdown),i=d.clone().css(k.hint).css(e(d)),i.val("").removeData().addClass("tt-hint").removeAttr("id name placeholder").prop("disabled",!0).attr({autocomplete:"off",spellcheck:"false"}),d.data(g,{dir:d.attr("dir"),autocomplete:d.attr("autocomplete"),spellcheck:d.attr("spellcheck"),style:d.attr("style")}),d.addClass("tt-input").attr({autocomplete:"off",spellcheck:!1}).css(c?k.input:k.inputWithNoHint);try{!d.attr("dir")&&d.attr("dir","auto")}catch(l){}return d.wrap(f).parent().prepend(c?i:null).append(h)}function e(a){return{backgroundAttachment:a.css("background-attachment"),backgroundClip:a.css("background-clip"),backgroundColor:a.css("background-color"),backgroundImage:a.css("background-image"),backgroundOrigin:a.css("background-origin"),backgroundPosition:a.css("background-position"),backgroundRepeat:a.css("background-repeat"),backgroundSize:a.css("background-size")}}function f(a){var c=a.find(".tt-input");b.each(c.data(g),function(a,d){b.isUndefined(a)?c.removeAttr(d):c.attr(d,a)}),c.detach().removeData(g).removeClass("tt-input").insertAfter(a),a.remove()}var g="ttAttrs";return b.mixin(c.prototype,{_onSuggestionClicked:function(a,b){var c;(c=this.dropdown.getDatumForSuggestion(b))&&this._select(c)},_onCursorMoved:function(){var a=this.dropdown.getDatumForCursor();this.input.setInputValue(a.value,!0),this.eventBus.trigger("cursorchanged",a.raw,a.datasetName)},_onCursorRemoved:function(){this.input.resetInputValue(),this._updateHint()},_onDatasetRendered:function(){this._updateHint()},_onOpened:function(){this._updateHint(),this.eventBus.trigger("opened")},_onClosed:function(){this.input.clearHint(),this.eventBus.trigger("closed")},_onFocused:function(){this.isActivated=!0,this.dropdown.open()},_onBlurred:function(){this.isActivated=!1,this.dropdown.empty(),this.dropdown.close()},_onEnterKeyed:function(a,b){var c,d;c=this.dropdown.getDatumForCursor(),d=this.dropdown.getDatumForTopSuggestion(),c?(this._select(c),b.preventDefault()):this.autoselect&&d&&(this._select(d),b.preventDefault())},_onTabKeyed:function(a,b){var c;(c=this.dropdown.getDatumForCursor())?(this._select(c),b.preventDefault()):this._autocomplete(!0)},_onEscKeyed:function(){this.dropdown.close(),this.input.resetInputValue()},_onUpKeyed:function(){var a=this.input.getQuery();this.dropdown.isEmpty&&a.length>=this.minLength?this.dropdown.update(a):this.dropdown.moveCursorUp(),this.dropdown.open()},_onDownKeyed:function(){var a=this.input.getQuery();this.dropdown.isEmpty&&a.length>=this.minLength?this.dropdown.update(a):this.dropdown.moveCursorDown(),this.dropdown.open()},_onLeftKeyed:function(){"rtl"===this.dir&&this._autocomplete()},_onRightKeyed:function(){"ltr"===this.dir&&this._autocomplete()},_onQueryChanged:function(a,b){this.input.clearHintIfInvalid(),b.length>=this.minLength?this.dropdown.update(b):this.dropdown.empty(),this.dropdown.open(),this._setLanguageDirection()},_onWhitespaceChanged:function(){this._updateHint(),this.dropdown.open()},_setLanguageDirection:function(){var a;this.dir!==(a=this.input.getLanguageDirection())&&(this.dir=a,this.$node.css("direction",a),this.dropdown.setLanguageDirection(a))},_updateHint:function(){var a,c,d,e,f,g;a=this.dropdown.getDatumForTopSuggestion(),a&&this.dropdown.isVisible()&&!this.input.hasOverflow()?(c=this.input.getInputValue(),d=o.normalizeQuery(c),e=b.escapeRegExChars(d),f=new RegExp("^(?:"+e+")(.+$)","i"),g=f.exec(a.value),g?this.input.setHint(c+g[1]):this.input.clearHint()):this.input.clearHint()},_autocomplete:function(a){var b,c,d,e;b=this.input.getHint(),c=this.input.getQuery(),d=a||this.input.isCursorAtEnd(),b&&c!==b&&d&&(e=this.dropdown.getDatumForTopSuggestion(),e&&this.input.setInputValue(e.value),this.eventBus.trigger("autocompleted",e.raw,e.datasetName))},_select:function(a){this.input.setQuery(a.value),this.input.setInputValue(a.value,!0),this._setLanguageDirection(),this.eventBus.trigger("selected",a.raw,a.datasetName),this.dropdown.close(),b.defer(b.bind(this.dropdown.empty,this.dropdown))},open:function(){this.dropdown.open()},close:function(){this.dropdown.close()},setVal:function(a){this.isActivated?this.input.setInputValue(a):(this.input.setQuery(a),this.input.setInputValue(a,!0)),this._setLanguageDirection()},getVal:function(){return this.input.getQuery()},destroy:function(){this.input.destroy(),this.dropdown.destroy(),f(this.$node),this.$node=null}}),c}();!function(){var c,d,e;c=a.fn.typeahead,d="ttTypeahead",e={initialize:function(c,e){function f(){var f,g,h=a(this);b.each(e,function(a){a.highlight=!!c.highlight}),g=new r({input:h,eventBus:f=new l({el:h}),withHint:b.isUndefined(c.hint)?!0:!!c.hint,minLength:c.minLength,autoselect:c.autoselect,datasets:e}),h.data(d,g)}return e=b.isArray(e)?e:[].slice.call(arguments,1),c=c||{},this.each(f)},open:function(){function b(){var b,c=a(this);(b=c.data(d))&&b.open()}return this.each(b)},close:function(){function b(){var b,c=a(this);(b=c.data(d))&&b.close()}return this.each(b)},val:function(b){function c(){var c,e=a(this);(c=e.data(d))&&c.setVal(b)}function e(a){var b,c;return(b=a.data(d))&&(c=b.getVal()),c}return arguments.length?this.each(c):e(this.first())},destroy:function(){function b(){var b,c=a(this);(b=c.data(d))&&(b.destroy(),c.removeData(d))}return this.each(b)}},a.fn.typeahead=function(a){return e[a]?e[a].apply(this,[].slice.call(arguments,1)):e.initialize.apply(this,arguments)},a.fn.typeahead.noConflict=function(){return a.fn.typeahead=c,this}}()}(window.jQuery); |
/*! | ||
* typeahead.js 0.10.1 | ||
* typeahead.js 0.10.2 | ||
* https://github.com/twitter/typeahead.js | ||
* Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT | ||
* Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT | ||
*/ | ||
@@ -128,3 +128,3 @@ | ||
suggestions: '<span class="tt-suggestions"></span>', | ||
suggestion: '<div class="tt-suggestion">%BODY%</div>' | ||
suggestion: '<div class="tt-suggestion"></div>' | ||
}; | ||
@@ -247,3 +247,3 @@ var css = { | ||
function trigger(types) { | ||
var that = this, type, callbacks, args, syncFlush, asyncFlush; | ||
var type, callbacks, args, syncFlush, asyncFlush; | ||
if (!this._callbacks) { | ||
@@ -272,3 +272,3 @@ return this; | ||
function getNextTick() { | ||
var nextTickFn, messageChannel; | ||
var nextTickFn; | ||
if (window.setImmediate) { | ||
@@ -370,3 +370,3 @@ nextTickFn = function nextTickSetImmediate(fn) { | ||
if (this.$hint.length === 0) { | ||
this.setHintValue = this.getHintValue = this.clearHint = _.noop; | ||
this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop; | ||
} | ||
@@ -390,7 +390,7 @@ if (!_.isMsie()) { | ||
_.mixin(Input.prototype, EventEmitter, { | ||
_onBlur: function onBlur($e) { | ||
_onBlur: function onBlur() { | ||
this.resetInputValue(); | ||
this.trigger("blurred"); | ||
}, | ||
_onFocus: function onFocus($e) { | ||
_onFocus: function onFocus() { | ||
this.trigger("focused"); | ||
@@ -405,3 +405,3 @@ }, | ||
}, | ||
_onInput: function onInput($e) { | ||
_onInput: function onInput() { | ||
this._checkInputValue(); | ||
@@ -413,3 +413,3 @@ }, | ||
case "tab": | ||
hintValue = this.getHintValue(); | ||
hintValue = this.getHint(); | ||
inputValue = this.getInputValue(); | ||
@@ -469,16 +469,24 @@ preventDefault = hintValue && hintValue !== inputValue && !withModifier($e); | ||
this.$input.val(value); | ||
!silent && this._checkInputValue(); | ||
silent ? this.clearHint() : this._checkInputValue(); | ||
}, | ||
getHintValue: function getHintValue() { | ||
resetInputValue: function resetInputValue() { | ||
this.setInputValue(this.query, true); | ||
}, | ||
getHint: function getHint() { | ||
return this.$hint.val(); | ||
}, | ||
setHintValue: function setHintValue(value) { | ||
setHint: function setHint(value) { | ||
this.$hint.val(value); | ||
}, | ||
resetInputValue: function resetInputValue() { | ||
this.$input.val(this.query); | ||
}, | ||
clearHint: function clearHint() { | ||
this.$hint.val(""); | ||
this.setHint(""); | ||
}, | ||
clearHintIfInvalid: function clearHintIfInvalid() { | ||
var val, hint, valIsPrefixOfHint, isValid; | ||
val = this.getInputValue(); | ||
hint = this.getHint(); | ||
valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0; | ||
isValid = val !== "" && valIsPrefixOfHint && !this.hasOverflow(); | ||
!isValid && this.clearHint(); | ||
}, | ||
getLanguageDirection: function getLanguageDirection() { | ||
@@ -516,3 +524,3 @@ return (this.$input.css("direction") || "ltr").toLowerCase(); | ||
visibility: "hidden", | ||
whiteSpace: "nowrap", | ||
whiteSpace: "pre", | ||
fontFamily: $input.css("font-family"), | ||
@@ -596,6 +604,4 @@ fontSize: $input.css("font-size"), | ||
function getSuggestionNode(suggestion) { | ||
var $el, innerHtml, outerHtml; | ||
innerHtml = that.templates.suggestion(suggestion); | ||
outerHtml = html.suggestion.replace("%BODY%", innerHtml); | ||
$el = $(outerHtml).data(datasetKey, that.name).data(valueKey, that.displayFn(suggestion)).data(datumKey, suggestion); | ||
var $el; | ||
$el = $(html.suggestion).append(that.templates.suggestion(suggestion)).data(datasetKey, that.name).data(valueKey, that.displayFn(suggestion)).data(datumKey, suggestion); | ||
$el.children().each(function() { | ||
@@ -626,9 +632,17 @@ $(this).css(css.suggestionChild); | ||
this.query = query; | ||
this.source(query, renderIfQueryIsSame); | ||
function renderIfQueryIsSame(suggestions) { | ||
query === that.query && that._render(query, suggestions); | ||
this.canceled = false; | ||
this.source(query, render); | ||
function render(suggestions) { | ||
if (!that.canceled && query === that.query) { | ||
that._render(query, suggestions); | ||
} | ||
} | ||
}, | ||
cancel: function cancel() { | ||
this.canceled = true; | ||
}, | ||
clear: function clear() { | ||
this._render(this.query || ""); | ||
this.cancel(); | ||
this.$el.empty(); | ||
this.trigger("rendered"); | ||
}, | ||
@@ -692,3 +706,3 @@ isEmpty: function isEmpty() { | ||
}, | ||
_onSuggestionMouseLeave: function onSuggestionMouseLeave($e) { | ||
_onSuggestionMouseLeave: function onSuggestionMouseLeave() { | ||
this._removeCursor(); | ||
@@ -828,3 +842,3 @@ }, | ||
function Typeahead(o) { | ||
var $menu, $input, $hint, datasets; | ||
var $menu, $input, $hint; | ||
o = o || {}; | ||
@@ -834,2 +848,3 @@ if (!o.input) { | ||
} | ||
this.isActivated = false; | ||
this.autoselect = !!o.autoselect; | ||
@@ -841,2 +856,18 @@ this.minLength = _.isNumber(o.minLength) ? o.minLength : 1; | ||
$hint = this.$node.find(".tt-hint"); | ||
$input.on("blur.tt", function($e) { | ||
var active, isActive, hasActive; | ||
active = document.activeElement; | ||
isActive = $menu.is(active); | ||
hasActive = $menu.has(active).length > 0; | ||
if (_.isMsie() && (isActive || hasActive)) { | ||
$e.preventDefault(); | ||
$e.stopImmediatePropagation(); | ||
_.defer(function() { | ||
$input.focus(); | ||
}); | ||
} | ||
}); | ||
$menu.on("mousedown.tt", function($e) { | ||
$e.preventDefault(); | ||
}); | ||
this.eventBus = o.eventBus || new EventBus({ | ||
@@ -853,11 +884,3 @@ el: $input | ||
}).onSync("focused", this._onFocused, this).onSync("blurred", this._onBlurred, this).onSync("enterKeyed", this._onEnterKeyed, this).onSync("tabKeyed", this._onTabKeyed, this).onSync("escKeyed", this._onEscKeyed, this).onSync("upKeyed", this._onUpKeyed, this).onSync("downKeyed", this._onDownKeyed, this).onSync("leftKeyed", this._onLeftKeyed, this).onSync("rightKeyed", this._onRightKeyed, this).onSync("queryChanged", this._onQueryChanged, this).onSync("whitespaceChanged", this._onWhitespaceChanged, this); | ||
$menu.on("mousedown.tt", function($e) { | ||
if (_.isMsie() && _.isMsie() < 9) { | ||
$input[0].onbeforedeactivate = function() { | ||
window.event.returnValue = false; | ||
$input[0].onbeforedeactivate = null; | ||
}; | ||
} | ||
$e.preventDefault(); | ||
}); | ||
this._setLanguageDirection(); | ||
} | ||
@@ -873,3 +896,2 @@ _.mixin(Typeahead.prototype, { | ||
var datum = this.dropdown.getDatumForCursor(); | ||
this.input.clearHint(); | ||
this.input.setInputValue(datum.value, true); | ||
@@ -894,6 +916,8 @@ this.eventBus.trigger("cursorchanged", datum.raw, datum.datasetName); | ||
_onFocused: function onFocused() { | ||
this.dropdown.empty(); | ||
this.isActivated = true; | ||
this.dropdown.open(); | ||
}, | ||
_onBlurred: function onBlurred() { | ||
this.isActivated = false; | ||
this.dropdown.empty(); | ||
this.dropdown.close(); | ||
@@ -919,3 +943,3 @@ }, | ||
} else { | ||
this._autocomplete(); | ||
this._autocomplete(true); | ||
} | ||
@@ -929,15 +953,9 @@ }, | ||
var query = this.input.getQuery(); | ||
if (!this.dropdown.isOpen && query.length >= this.minLength) { | ||
this.dropdown.update(query); | ||
} | ||
this.dropdown.isEmpty && query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.moveCursorUp(); | ||
this.dropdown.open(); | ||
this.dropdown.moveCursorUp(); | ||
}, | ||
_onDownKeyed: function onDownKeyed() { | ||
var query = this.input.getQuery(); | ||
if (!this.dropdown.isOpen && query.length >= this.minLength) { | ||
this.dropdown.update(query); | ||
} | ||
this.dropdown.isEmpty && query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.moveCursorDown(); | ||
this.dropdown.open(); | ||
this.dropdown.moveCursorDown(); | ||
}, | ||
@@ -951,5 +969,4 @@ _onLeftKeyed: function onLeftKeyed() { | ||
_onQueryChanged: function onQueryChanged(e, query) { | ||
this.input.clearHint(); | ||
this.dropdown.empty(); | ||
query.length >= this.minLength && this.dropdown.update(query); | ||
this.input.clearHintIfInvalid(); | ||
query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.empty(); | ||
this.dropdown.open(); | ||
@@ -971,18 +988,21 @@ this._setLanguageDirection(); | ||
_updateHint: function updateHint() { | ||
var datum, inputValue, query, escapedQuery, frontMatchRegEx, match; | ||
var datum, val, query, escapedQuery, frontMatchRegEx, match; | ||
datum = this.dropdown.getDatumForTopSuggestion(); | ||
if (datum && this.dropdown.isVisible() && !this.input.hasOverflow()) { | ||
inputValue = this.input.getInputValue(); | ||
query = Input.normalizeQuery(inputValue); | ||
val = this.input.getInputValue(); | ||
query = Input.normalizeQuery(val); | ||
escapedQuery = _.escapeRegExChars(query); | ||
frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.*$)", "i"); | ||
frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i"); | ||
match = frontMatchRegEx.exec(datum.value); | ||
this.input.setHintValue(inputValue + (match ? match[1] : "")); | ||
match ? this.input.setHint(val + match[1]) : this.input.clearHint(); | ||
} else { | ||
this.input.clearHint(); | ||
} | ||
}, | ||
_autocomplete: function autocomplete() { | ||
var hint, query, datum; | ||
hint = this.input.getHintValue(); | ||
_autocomplete: function autocomplete(laxCursor) { | ||
var hint, query, isCursorAtEnd, datum; | ||
hint = this.input.getHint(); | ||
query = this.input.getQuery(); | ||
if (hint && query !== hint && this.input.isCursorAtEnd()) { | ||
isCursorAtEnd = laxCursor || this.input.isCursorAtEnd(); | ||
if (hint && query !== hint && isCursorAtEnd) { | ||
datum = this.dropdown.getDatumForTopSuggestion(); | ||
@@ -994,3 +1014,2 @@ datum && this.input.setInputValue(datum.value); | ||
_select: function select(datum) { | ||
this.input.clearHint(); | ||
this.input.setQuery(datum.value); | ||
@@ -1009,8 +1028,14 @@ this.input.setInputValue(datum.value, true); | ||
}, | ||
getQuery: function getQuery() { | ||
setVal: function setVal(val) { | ||
if (this.isActivated) { | ||
this.input.setInputValue(val); | ||
} else { | ||
this.input.setQuery(val); | ||
this.input.setInputValue(val, true); | ||
} | ||
this._setLanguageDirection(); | ||
}, | ||
getVal: function getVal() { | ||
return this.input.getQuery(); | ||
}, | ||
setQuery: function setQuery(val) { | ||
this.input.setInputValue(val); | ||
}, | ||
destroy: function destroy() { | ||
@@ -1116,13 +1141,13 @@ this.input.destroy(); | ||
val: function val(newVal) { | ||
return !arguments.length ? getQuery(this.first()) : this.each(setQuery); | ||
function setQuery() { | ||
return !arguments.length ? getVal(this.first()) : this.each(setVal); | ||
function setVal() { | ||
var $input = $(this), typeahead; | ||
if (typeahead = $input.data(typeaheadKey)) { | ||
typeahead.setQuery(newVal); | ||
typeahead.setVal(newVal); | ||
} | ||
} | ||
function getQuery($input) { | ||
function getVal($input) { | ||
var typeahead, query; | ||
if (typeahead = $input.data(typeaheadKey)) { | ||
query = typeahead.getQuery(); | ||
query = typeahead.getVal(); | ||
} | ||
@@ -1129,0 +1154,0 @@ return query; |
@@ -43,7 +43,11 @@ Bloodhound | ||
local: [{ val: 'dog' }, { val: 'pig' }, { val: 'moose' }], | ||
remote: 'http://example.com/animals?q=%QUERY' | ||
remote: 'http://example.com/animals?q=%QUERY', | ||
datumTokenizer: function(d) { | ||
return Bloodhound.tokenizers.whitespace(d.val); | ||
}, | ||
queryTokenizer: Bloodhound.tokenizers.whitespace | ||
}); | ||
``` | ||
#### Bloodhound#initialize() | ||
#### Bloodhound#initialize(reinitialize) | ||
@@ -63,2 +67,66 @@ Kicks off the initialization of the suggestion engine. This includes processing | ||
After the initial call of `initialize`, how subsequent invocations of the method | ||
behave depends on the `reinitialize` argument. If `reinitialize` is falsy, the | ||
method will not execute the initialization logic and will just return the same | ||
jQuery promise returned by the initial invocation. If `reinitialize` is truthy, | ||
the method will behave as if it were being called for the first time. | ||
```javascript | ||
var promise1 = engine.initialize(); | ||
var promise2 = engine.initialize(); | ||
var promise3 = engine.initialize(true); | ||
promise1 === promise2; | ||
promise3 !== promise1 && promise3 !== promise2; | ||
``` | ||
#### Bloodhound#add(datums) | ||
Takes one argument, `datums`, which is expected to be an array of | ||
[datums](#datums). The passed in datums will get added to the search index that | ||
powers the suggestion engine. | ||
```javascript | ||
engine.add([{ val: 'one' }, { val: 'two' }]); | ||
``` | ||
#### Bloodhound#clear() | ||
Removes all suggestions from the search index. | ||
```javascript | ||
engine.clear(); | ||
``` | ||
#### Bloodhound#clearPrefetchCache() | ||
If you're using `prefetch`, data gets cached in local storage in an effort to | ||
cut down on unnecessary network requests. `clearPrefetchCache` offers a way to | ||
programmatically clear said cache. | ||
```javascript | ||
engine.clearPrefetchCache(); | ||
``` | ||
#### Bloodhound#clearRemoteCache() | ||
If you're using `remote`, Bloodhound will cache the 10 most recent responses | ||
in an effort to provide a better user experience. `clearRemoteCache` offers a | ||
way to programmatically clear said cache. | ||
```javascript | ||
engine.clearRemoteCache(); | ||
``` | ||
#### Bloodhound.noConflict() | ||
Returns a reference to the Bloodhound constructor and reverts | ||
`window.Bloodhound` to its previous value. Can be used to avoid naming | ||
collisions. | ||
```javascript | ||
var Dachshund = Bloodhound.noConflict(); | ||
``` | ||
<!-- section links --> | ||
@@ -65,0 +133,0 @@ |
@@ -11,2 +11,3 @@ jQuery#typeahead | ||
* [Features](#features) | ||
* [Specification](#specification) | ||
* [Usage](#usage) | ||
@@ -30,2 +31,140 @@ * [API](#api) | ||
Specification | ||
------------- | ||
In an effort to take advantage of the pre-existing knowledge of typeahead.js | ||
users, the behavior of the typeahead.js UI is modeled after google.com's search | ||
box. Below is pseudocode that details how the UI reacts to pertinent events. | ||
**Input Control Gains Focus** | ||
``` | ||
activate typeahead | ||
``` | ||
**Input Control Loses Focus** | ||
``` | ||
deactivate typeahead | ||
close dropdown menu | ||
remove hint | ||
clear suggestions from dropdown menu | ||
``` | ||
**Value of the Input Control Changes** | ||
``` | ||
IF query satisfies minLength requirement THEN | ||
request suggestions for new query | ||
IF suggestions are available THEN | ||
render suggestions in dropdown menu | ||
open dropdown menu | ||
update hint | ||
ELSE | ||
close dropdown menu | ||
clear suggestions from dropdown menu | ||
remove hint | ||
ENDIF | ||
ELSE | ||
close dropdown menu | ||
clear suggestions from dropdown menu | ||
remove hint | ||
ENDIF | ||
``` | ||
**Up Arrow is Keyed** | ||
``` | ||
IF dropdown menu is open THEN | ||
move dropdown menu cursor up 1 suggestion | ||
ELSE | ||
request suggestions for current query | ||
IF suggestions are available THEN | ||
render suggestions in dropdown menu | ||
open dropdown menu | ||
update hint | ||
ENDIF | ||
ENDIF | ||
``` | ||
**Down Arrow is Keyed** | ||
``` | ||
IF dropdown menu is open THEN | ||
move dropdown menu cursor down 1 suggestion | ||
ELSE | ||
request suggestions for current query | ||
IF suggestions are available THEN | ||
render suggestions in dropdown menu | ||
open dropdown menu | ||
update hint | ||
ENDIF | ||
ENDIF | ||
``` | ||
**Left Arrow is Keyed** | ||
``` | ||
IF detected query language direction is right-to-left THEN | ||
IF hint is being shown THEN | ||
IF text cursor is at end of query THEN | ||
autocomplete query to hint | ||
ENDIF | ||
ENDIF | ||
ENDIF | ||
``` | ||
**Right Arrow is Keyed** | ||
``` | ||
IF detected query language direction is left-to-right THEN | ||
IF hint is being shown THEN | ||
IF text cursor is at the end of the query THEN | ||
autocomplete query to hint | ||
ENDIF | ||
ENDIF | ||
ENDIF | ||
``` | ||
**Tab is Keyed** | ||
``` | ||
IF dropdown menu cursor is on suggestion THEN | ||
close dropdown menu | ||
update query to display key of suggestion | ||
remove hint | ||
ELSIF hint is being shown THEN | ||
autocomplete query to hint | ||
ENDIF | ||
``` | ||
**Enter is Keyed** | ||
``` | ||
IF dropdown menu cursor is on suggestion THEN | ||
close dropdown menu | ||
update query to display key of suggestion | ||
remove hint | ||
prevent default browser action e.g. form submit | ||
ENDIF | ||
``` | ||
**Esc is Keyed** | ||
``` | ||
close dropdown menu | ||
remove hint | ||
``` | ||
**Suggestion is Clicked** | ||
``` | ||
update query to display key of suggestion | ||
close dropdown menu | ||
remove hint | ||
``` | ||
Usage | ||
@@ -112,6 +251,2 @@ ----- | ||
* `autoselect` – If `true`, defaults the suggestion selection to the top | ||
suggestion when the user keys enter while the dropdown menu is open. Defaults | ||
to `false`. | ||
* `highlight` – If `true`, when suggestions are rendered, pattern matches | ||
@@ -118,0 +253,0 @@ for the current query in text nodes will be wrapped in a `strong` element. |
@@ -13,3 +13,3 @@ Migrating to typeahead.js v0.10.0 | ||
Noteable Changes | ||
Notable Changes | ||
---------------- | ||
@@ -68,7 +68,6 @@ | ||
dataset level. Instead, all you set in a dataset config is `source`. `source` is | ||
expected to be a function with the signature `function(query, cb)`. When a | ||
typeahead's query changes, suggestions wil be requested from `source`. It's | ||
expected `source` will compute the suggestion set and invoke `cb` with an array | ||
of suggestion objects. The typeahead will then go on to render those | ||
suggestions. | ||
expected to be a function with the signature `function(query, callback)`. When a | ||
typeahead's query changes, suggestions will be requested from `source`. It's | ||
expected `source` will compute the suggestion set and invoke `callback` with an array | ||
of suggestion objects. The typeahead will then go on to render those suggestions. | ||
@@ -93,3 +92,3 @@ If you're wondering if you can still configure `local`, `prefetch`, and | ||
// the suggestion engine will be useless until it is initialized | ||
mySource.initialze(); | ||
mySource.initialize(); | ||
``` | ||
@@ -121,3 +120,3 @@ | ||
mySource.initialze(); | ||
mySource.initialize(); | ||
@@ -184,3 +183,3 @@ $('.typeahead').typeahead(null, { | ||
funciton customTokenizer(datum) { return datum.tokens; } | ||
function customTokenizer(datum) { return datum.tokens; } | ||
``` | ||
@@ -231,8 +230,8 @@ | ||
### The Cursor Class Name Has Changed | ||
### CSS Class Changes | ||
This is a minor change, but one that could potentially trip you up. The class | ||
added the suggestion that typeahead cursor is over has changed from | ||
`tt-is-under-cursor` to `tt-cursor`. | ||
`tt-is-under-cursor` is now `tt-cursor` - Applied to a hovered-on suggestion (either via cursor or arrow key). | ||
`tt-query` is now `tt-input` - Applied to the typeahead input field. | ||
Something Missing? | ||
@@ -239,0 +238,0 @@ ------------------ |
@@ -9,2 +9,3 @@ var semver = require('semver'), | ||
'src/bloodhound/version.js', | ||
'src/bloodhound/tokenizers.js', | ||
'src/bloodhound/lru_cache.js', | ||
@@ -41,3 +42,3 @@ 'src/bloodhound/persistent_storage.js', | ||
' * https://github.com/twitter/typeahead.js', | ||
' * Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT', | ||
' * Copyright 2013-<%= grunt.template.today("yyyy") %> Twitter, Inc. and other contributors; Licensed MIT', | ||
' */\n\n' | ||
@@ -60,2 +61,10 @@ ].join('\n'), | ||
}, | ||
bloodhoundMin: { | ||
options: { | ||
mangle: true, | ||
compress: true | ||
}, | ||
src: files.common.concat(files.bloodhound), | ||
dest: '<%= buildDir %>/bloodhound.min.js' | ||
}, | ||
typeahead: { | ||
@@ -71,2 +80,11 @@ options: { | ||
}, | ||
typeaheadMin: { | ||
options: { | ||
mangle: true, | ||
compress: true | ||
}, | ||
src: files.common.concat(files.typeahead), | ||
dest: '<%= buildDir %>/typeahead.jquery.min.js' | ||
}, | ||
bundle: { | ||
@@ -118,11 +136,7 @@ options: { | ||
exec: { | ||
git_is_clean: { | ||
cmd: 'test -z "$(git status --porcelain)"' | ||
}, | ||
git_on_master: { | ||
cmd: 'test $(git symbolic-ref --short -q HEAD) = master' | ||
}, | ||
git_add: { | ||
cmd: 'git add .' | ||
}, | ||
npm_publish: 'npm publish', | ||
git_is_clean: 'test -z "$(git status --porcelain)"', | ||
git_on_master: 'test $(git symbolic-ref --short -q HEAD) = master', | ||
git_add: 'git add .', | ||
git_push: 'git push && git push --tags', | ||
git_commit: { | ||
@@ -134,22 +148,17 @@ cmd: function(m) { return f('git commit -m "%s"', m); } | ||
}, | ||
git_push: { | ||
cmd: 'git push && git push --tags' | ||
}, | ||
publish_assets: { | ||
cmd: [ | ||
'cp -r <%= buildDir %> typeahead.js', | ||
'zip -r typeahead.js/typeahead.js.zip typeahead.js', | ||
'git checkout gh-pages', | ||
'rm -rf releases/latest', | ||
'cp -r typeahead.js releases/<%= version %>', | ||
'cp -r typeahead.js releases/latest', | ||
'git add releases/<%= version %> releases/latest', | ||
'sed -E -i "" \'s/v[0-9]+\\.[0-9]+\\.[0-9]+/v<%= version %>/\' index.html', | ||
'git add index.html', | ||
'git commit -m "Add assets for <%= version %>."', | ||
//'git push', | ||
'git checkout -', | ||
'rm -rf typeahead.js' | ||
].join(' && ') | ||
} | ||
publish_assets: [ | ||
'cp -r <%= buildDir %> typeahead.js', | ||
'zip -r typeahead.js/typeahead.js.zip typeahead.js', | ||
'git checkout gh-pages', | ||
'rm -rf releases/latest', | ||
'cp -r typeahead.js releases/<%= version %>', | ||
'cp -r typeahead.js releases/latest', | ||
'git add releases/<%= version %> releases/latest', | ||
'sed -E -i "" \'s/v[0-9]+\\.[0-9]+\\.[0-9]+/v<%= version %>/\' index.html', | ||
'git add index.html', | ||
'git commit -m "Add assets for <%= version %>."', | ||
'git push', | ||
'git checkout -', | ||
'rm -rf typeahead.js' | ||
].join(' && ') | ||
}, | ||
@@ -174,6 +183,12 @@ | ||
] | ||
}, | ||
step: { | ||
options: { | ||
option: false | ||
} | ||
} | ||
}); | ||
grunt.registerTask('release', 'Ship it.', function(version) { | ||
grunt.registerTask('release', '#shipit', function(version) { | ||
var curVersion = grunt.config.get('version'); | ||
@@ -184,3 +199,3 @@ | ||
if (!semver.valid(version) || semver.lte(version, curVersion)) { | ||
grunt.fatal('invalid version dummy'); | ||
grunt.fatal('hey dummy, that version is no good!'); | ||
} | ||
@@ -193,8 +208,13 @@ | ||
'exec:git_is_clean', | ||
'manifests:' + version, | ||
f('step:Update to version %s?', version), | ||
f('manifests:%s', version), | ||
'build', | ||
'exec:git_add', | ||
'exec:git_commit:' + version, | ||
'exec:git_tag:' + version, | ||
//'exec:git_push', | ||
f('exec:git_commit:%s', version), | ||
f('exec:git_tag:%s', version), | ||
'step:Push changes?', | ||
'exec:git_push', | ||
'step:Publish to npm?', | ||
'exec:npm_publish', | ||
'step:Publish assets?', | ||
'exec:publish_assets' | ||
@@ -250,2 +270,3 @@ ]); | ||
grunt.loadNpmTasks('grunt-exec'); | ||
grunt.loadNpmTasks('grunt-step'); | ||
grunt.loadNpmTasks('grunt-parallel'); | ||
@@ -252,0 +273,0 @@ grunt.loadNpmTasks('grunt-contrib-watch'); |
@@ -14,5 +14,6 @@ // Karma configuration | ||
files = [ | ||
'test/vendor/**/*', | ||
'bower_components/jquery/dist/jquery.js', | ||
'src/common/utils.js', | ||
'src/bloodhound/version.js', | ||
'src/bloodhound/tokenizers.js', | ||
'src/bloodhound/lru_cache.js', | ||
@@ -37,2 +38,4 @@ 'src/bloodhound/persistent_storage.js', | ||
'test/fixtures/**/*', | ||
'bower_components/jasmine-jquery/lib/jasmine-jquery.js', | ||
'bower_components/jasmine-ajax/lib/mock-ajax.js', | ||
'test/helpers/**/*', | ||
@@ -39,0 +42,0 @@ 'test/*_spec.js' |
@@ -10,2 +10,6 @@ { | ||
"bugs": "https://github.com/twitter/typeahead.js/issues", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/twitter/typeahead.js.git" | ||
}, | ||
"author": { | ||
@@ -34,3 +38,3 @@ "name": "Twitter, Inc.", | ||
"grunt-sed": "~0.1", | ||
"grunt-exec": "~0.4", | ||
"grunt-exec": "~0.4.5", | ||
"grunt-contrib-watch": "~0.2", | ||
@@ -42,3 +46,4 @@ "grunt-contrib-jshint": "~0.8", | ||
"grunt-contrib-clean": "~0.4.0", | ||
"grunt-parallel": "0.0.2" | ||
"grunt-parallel": "0.0.2", | ||
"grunt-step": "~0.2.0" | ||
}, | ||
@@ -48,3 +53,4 @@ "scripts": { | ||
}, | ||
"version": "0.10.1" | ||
} | ||
"version": "0.10.2", | ||
"main": "dist/typeahead.bundle.js" | ||
} |
@@ -159,2 +159,11 @@ [![build status](https://secure.travis-ci.org/twitter/typeahead.js.png?branch=master)](http://travis-ci.org/twitter/typeahead.js) | ||
Maintainers | ||
----------- | ||
* **Jake Harding** | ||
* [@JakeHarding](https://twitter.com/JakeHarding) | ||
* [GitHub](https://github.com/jharding) | ||
* **You?** | ||
Authors | ||
@@ -161,0 +170,0 @@ ------- |
/* | ||
* typeahead.js | ||
* https://github.com/twitter/typeahead.js | ||
* Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT | ||
* Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT | ||
*/ | ||
var Bloodhound = window.Bloodhound = (function() { | ||
var keys; | ||
(function(root) { | ||
var old, keys; | ||
old = root.Bloodhound; | ||
keys = { data: 'data', protocol: 'protocol', thumbprint: 'thumbprint' }; | ||
// add Bloodhoud to global context | ||
root.Bloodhound = Bloodhound; | ||
// constructor | ||
@@ -45,12 +49,9 @@ // ----------- | ||
Bloodhound.tokenizers = { | ||
whitespace: function whitespaceTokenizer(s) { | ||
return s.split(/\s+/); | ||
}, | ||
nonword: function nonwordTokenizer(s) { | ||
return s.split(/\W+/); | ||
} | ||
Bloodhound.noConflict = function noConflict() { | ||
root.Bloodhound = old; | ||
return Bloodhound; | ||
}; | ||
Bloodhound.tokenizers = tokenizers; | ||
// instance methods | ||
@@ -78,7 +79,6 @@ // ---------------- | ||
function handlePrefetchResponse(resp) { | ||
var filtered; | ||
// clear to mirror the behavior of bootstrapping | ||
that.clear(); | ||
that.add(o.filter ? o.filter(resp) : resp); | ||
filtered = o.filter ? o.filter(resp) : resp; | ||
that.add(filtered); | ||
that._saveToStorage(that.index.serialize(), o.thumbprint, o.ttl); | ||
@@ -100,6 +100,4 @@ } | ||
function handleRemoteResponse(resp) { | ||
var filtered = that.remote.filter ? that.remote.filter(resp) : resp; | ||
cb(filtered); | ||
function handleRemoteResponse(err, resp) { | ||
err ? cb([]) : cb(that.remote.filter ? that.remote.filter(resp) : resp); | ||
} | ||
@@ -133,9 +131,5 @@ }, | ||
// ### public | ||
_initialize: function initialize() { | ||
var that = this, local = this.local, deferred; | ||
// the contents of this function are broken out of the constructor | ||
// to help improve the testability of bloodhounds | ||
initialize: function initialize() { | ||
var that = this, deferred; | ||
deferred = this.prefetch ? | ||
@@ -145,12 +139,20 @@ this._loadPrefetch(this.prefetch) : $.Deferred().resolve(); | ||
// make sure local is added to the index after prefetch | ||
this.local && deferred.done(addLocalToIndex); | ||
local && deferred.done(addLocalToIndex); | ||
this.transport = this.remote ? new Transport(this.remote) : null; | ||
this.initialize = function initialize() { return deferred.promise(); }; | ||
return deferred.promise(); | ||
return (this.initPromise = deferred.promise()); | ||
function addLocalToIndex() { that.add(that.local); } | ||
function addLocalToIndex() { | ||
// local can be a function that returns an array of datums | ||
that.add(_.isFunction(local) ? local() : local); | ||
} | ||
}, | ||
// ### public | ||
initialize: function initialize(force) { | ||
return !this.initPromise || force ? this._initialize() : this.initPromise; | ||
}, | ||
add: function add(data) { | ||
@@ -161,3 +163,3 @@ this.index.add(data); | ||
get: function get(query, cb) { | ||
var that = this, matches, cacheHit = false; | ||
var that = this, matches = [], cacheHit = false; | ||
@@ -174,3 +176,7 @@ matches = this.index.get(query); | ||
// in the event loop | ||
!cacheHit && cb && cb(matches); | ||
if (!cacheHit) { | ||
// only render if there are some local suggestions or we're | ||
// going to the network to backfill | ||
(matches.length > 0 || !this.transport) && cb && cb(matches); | ||
} | ||
@@ -194,3 +200,2 @@ function returnRemoteMatches(remoteMatches) { | ||
}); | ||
cb && cb(that.sorter(matchesWithBackfill)); | ||
@@ -200,2 +205,14 @@ } | ||
clear: function clear() { | ||
this.index.reset(); | ||
}, | ||
clearPrefetchCache: function clearPrefetchCache() { | ||
this.storage && this.storage.clear(); | ||
}, | ||
clearRemoteCache: function clearRemoteCache() { | ||
this.transport && Transport.resetCache(); | ||
}, | ||
ttAdapter: function ttAdapter() { return _.bind(this.get, this); } | ||
@@ -217,2 +234,2 @@ }); | ||
function ignoreDuplicates() { return false; } | ||
})(); | ||
})(this); |
/* | ||
* typeahead.js | ||
* https://github.com/twitter/typeahead.js | ||
* Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT | ||
* Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT | ||
*/ | ||
@@ -9,3 +9,3 @@ | ||
var LruCache = (function(root, undefined) { | ||
var LruCache = (function() { | ||
@@ -90,2 +90,2 @@ function LruCache(maxSize) { | ||
})(this); | ||
})(); |
/* | ||
* typeahead.js | ||
* https://github.com/twitter/typeahead.js | ||
* Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT | ||
* Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT | ||
*/ | ||
@@ -16,9 +16,3 @@ | ||
function getLocal(o) { | ||
var local = o.local || null; | ||
if (_.isFunction(local)) { | ||
local = local.call(null); | ||
} | ||
return local; | ||
return o.local || null; | ||
} | ||
@@ -25,0 +19,0 @@ |
/* | ||
* typeahead.js | ||
* https://github.com/twitter/typeahead.js | ||
* Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT | ||
* Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT | ||
*/ | ||
@@ -6,0 +6,0 @@ |
/* | ||
* typeahead.js | ||
* https://github.com/twitter/typeahead.js | ||
* Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT | ||
* Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT | ||
*/ | ||
@@ -22,4 +22,3 @@ | ||
this.datums = []; | ||
this.trie = newNode(); | ||
this.reset(); | ||
} | ||
@@ -51,3 +50,3 @@ | ||
_.each(tokens, function(token) { | ||
var node, chars, ch, ids; | ||
var node, chars, ch; | ||
@@ -101,2 +100,7 @@ node = that.trie; | ||
reset: function reset() { | ||
this.datums = []; | ||
this.trie = newNode(); | ||
}, | ||
serialize: function serialize() { | ||
@@ -103,0 +107,0 @@ return { datums: this.datums, trie: this.trie }; |
/* | ||
* typeahead.js | ||
* https://github.com/twitter/typeahead.js | ||
* Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT | ||
* Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT | ||
*/ | ||
@@ -46,3 +46,3 @@ | ||
if (jqXhr = pendingRequests[url]) { | ||
jqXhr.done(done); | ||
jqXhr.done(done).fail(fail); | ||
} | ||
@@ -53,3 +53,4 @@ | ||
pendingRequestsCount++; | ||
pendingRequests[url] = this._send(url, o).done(done).always(always); | ||
pendingRequests[url] = | ||
this._send(url, o).done(done).fail(fail).always(always); | ||
} | ||
@@ -62,8 +63,11 @@ | ||
// success callback | ||
function done(resp) { | ||
cb && cb(resp); | ||
cb && cb(null, resp); | ||
requestCache.set(url, resp); | ||
} | ||
function fail() { | ||
cb && cb(true); | ||
} | ||
function always() { | ||
@@ -84,3 +88,3 @@ pendingRequestsCount--; | ||
get: function(url, o, cb) { | ||
var that = this, resp; | ||
var resp; | ||
@@ -95,3 +99,3 @@ if (_.isFunction(o)) { | ||
// defer to stay consistent with behavior of ajax call | ||
_.defer(function() { cb && cb(resp); }); | ||
_.defer(function() { cb && cb(null, resp); }); | ||
} | ||
@@ -98,0 +102,0 @@ |
/* | ||
* typeahead.js | ||
* https://github.com/twitter/typeahead.js | ||
* Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT | ||
* Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT | ||
*/ | ||
var VERSION = '%VERSION%'; |
/* | ||
* typeahead.js | ||
* https://github.com/twitter/typeahead.js | ||
* Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT | ||
* Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT | ||
*/ | ||
@@ -6,0 +6,0 @@ |
/* | ||
* typeahead.js | ||
* https://github.com/twitter/typeahead.js | ||
* Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT | ||
* Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT | ||
*/ | ||
@@ -6,0 +6,0 @@ |
/* | ||
* typeahead.js | ||
* https://github.com/twitter/typeahead.js | ||
* Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT | ||
* Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT | ||
*/ | ||
@@ -104,7 +104,6 @@ | ||
function getSuggestionNode(suggestion) { | ||
var $el, innerHtml, outerHtml; | ||
var $el; | ||
innerHtml = that.templates.suggestion(suggestion); | ||
outerHtml = html.suggestion.replace('%BODY%', innerHtml); | ||
$el = $(outerHtml) | ||
$el = $(html.suggestion) | ||
.append(that.templates.suggestion(suggestion)) | ||
.data(datasetKey, that.name) | ||
@@ -145,11 +144,22 @@ .data(valueKey, that.displayFn(suggestion)) | ||
this.query = query; | ||
this.source(query, renderIfQueryIsSame); | ||
this.canceled = false; | ||
this.source(query, render); | ||
function renderIfQueryIsSame(suggestions) { | ||
query === that.query && that._render(query, suggestions); | ||
function render(suggestions) { | ||
// if the update has been canceled or if the query has changed | ||
// do not render the suggestions as they've become outdated | ||
if (!that.canceled && query === that.query) { | ||
that._render(query, suggestions); | ||
} | ||
} | ||
}, | ||
cancel: function cancel() { | ||
this.canceled = true; | ||
}, | ||
clear: function clear() { | ||
this._render(this.query || ''); | ||
this.cancel(); | ||
this.$el.empty(); | ||
this.trigger('rendered'); | ||
}, | ||
@@ -156,0 +166,0 @@ |
/* | ||
* typeahead.js | ||
* https://github.com/twitter/typeahead.js | ||
* Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT | ||
* Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT | ||
*/ | ||
@@ -59,3 +59,3 @@ | ||
_onSuggestionMouseLeave: function onSuggestionMouseLeave($e) { | ||
_onSuggestionMouseLeave: function onSuggestionMouseLeave() { | ||
this._removeCursor(); | ||
@@ -62,0 +62,0 @@ }, |
/* | ||
* typeahead.js | ||
* https://github.com/twitter/typeahead.js | ||
* Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT | ||
* Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT | ||
*/ | ||
@@ -6,0 +6,0 @@ |
/* | ||
* typeahead.js | ||
* https://github.com/twitter/typeahead.js | ||
* Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT | ||
* Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT | ||
*/ | ||
@@ -60,3 +60,3 @@ | ||
function trigger(types) { | ||
var that = this, type, callbacks, args, syncFlush, asyncFlush; | ||
var type, callbacks, args, syncFlush, asyncFlush; | ||
@@ -94,3 +94,3 @@ if (!this._callbacks) { return this; } | ||
function getNextTick() { | ||
var nextTickFn, messageChannel; | ||
var nextTickFn; | ||
@@ -97,0 +97,0 @@ // IE10+ |
/* | ||
* typeahead.js | ||
* https://github.com/twitter/typeahead.js | ||
* Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT | ||
* Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT | ||
*/ | ||
@@ -6,0 +6,0 @@ |
/* | ||
* typeahead.js | ||
* https://github.com/twitter/typeahead.js | ||
* Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT | ||
* Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT | ||
*/ | ||
@@ -12,3 +12,3 @@ | ||
suggestions: '<span class="tt-suggestions"></span>', | ||
suggestion: '<div class="tt-suggestion">%BODY%</div>' | ||
suggestion: '<div class="tt-suggestion"></div>' | ||
}; |
/* | ||
* typeahead.js | ||
* https://github.com/twitter/typeahead.js | ||
* Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT | ||
* Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT | ||
*/ | ||
@@ -46,3 +46,6 @@ | ||
if (this.$hint.length === 0) { | ||
this.setHintValue = this.getHintValue = this.clearHint = _.noop; | ||
this.setHint = | ||
this.getHint = | ||
this.clearHint = | ||
this.clearHintIfInvalid = _.noop; | ||
} | ||
@@ -91,3 +94,3 @@ | ||
_onBlur: function onBlur($e) { | ||
_onBlur: function onBlur() { | ||
this.resetInputValue(); | ||
@@ -97,3 +100,3 @@ this.trigger('blurred'); | ||
_onFocus: function onFocus($e) { | ||
_onFocus: function onFocus() { | ||
this.trigger('focused'); | ||
@@ -112,3 +115,3 @@ }, | ||
_onInput: function onInput($e) { | ||
_onInput: function onInput() { | ||
this._checkInputValue(); | ||
@@ -122,3 +125,3 @@ }, | ||
case 'tab': | ||
hintValue = this.getHintValue(); | ||
hintValue = this.getHint(); | ||
inputValue = this.getInputValue(); | ||
@@ -200,19 +203,31 @@ | ||
!silent && this._checkInputValue(); | ||
// silent prevents any additional events from being triggered | ||
silent ? this.clearHint() : this._checkInputValue(); | ||
}, | ||
getHintValue: function getHintValue() { | ||
resetInputValue: function resetInputValue() { | ||
this.setInputValue(this.query, true); | ||
}, | ||
getHint: function getHint() { | ||
return this.$hint.val(); | ||
}, | ||
setHintValue: function setHintValue(value) { | ||
setHint: function setHint(value) { | ||
this.$hint.val(value); | ||
}, | ||
resetInputValue: function resetInputValue() { | ||
this.$input.val(this.query); | ||
clearHint: function clearHint() { | ||
this.setHint(''); | ||
}, | ||
clearHint: function clearHint() { | ||
this.$hint.val(''); | ||
clearHintIfInvalid: function clearHintIfInvalid() { | ||
var val, hint, valIsPrefixOfHint, isValid; | ||
val = this.getInputValue(); | ||
hint = this.getHint(); | ||
valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0; | ||
isValid = val !== '' && valIsPrefixOfHint && !this.hasOverflow(); | ||
!isValid && this.clearHint(); | ||
}, | ||
@@ -274,4 +289,4 @@ | ||
visibility: 'hidden', | ||
// avoid line breaks | ||
whiteSpace: 'nowrap', | ||
// avoid line breaks and whitespace collapsing | ||
whiteSpace: 'pre', | ||
// use same font css as input to calculate accurate width | ||
@@ -278,0 +293,0 @@ fontFamily: $input.css('font-family'), |
/* | ||
* typeahead.js | ||
* https://github.com/twitter/typeahead.js | ||
* Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT | ||
* Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT | ||
*/ | ||
@@ -73,17 +73,17 @@ | ||
// write operates on all matches | ||
return !arguments.length ? getQuery(this.first()) : this.each(setQuery); | ||
return !arguments.length ? getVal(this.first()) : this.each(setVal); | ||
function setQuery() { | ||
function setVal() { | ||
var $input = $(this), typeahead; | ||
if (typeahead = $input.data(typeaheadKey)) { | ||
typeahead.setQuery(newVal); | ||
typeahead.setVal(newVal); | ||
} | ||
} | ||
function getQuery($input) { | ||
function getVal($input) { | ||
var typeahead, query; | ||
if (typeahead = $input.data(typeaheadKey)) { | ||
query = typeahead.getQuery(); | ||
query = typeahead.getVal(); | ||
} | ||
@@ -90,0 +90,0 @@ |
/* | ||
* typeahead.js | ||
* https://github.com/twitter/typeahead.js | ||
* Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT | ||
* Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT | ||
*/ | ||
@@ -15,3 +15,3 @@ | ||
function Typeahead(o) { | ||
var $menu, $input, $hint, datasets; | ||
var $menu, $input, $hint; | ||
@@ -24,2 +24,3 @@ o = o || {}; | ||
this.isActivated = false; | ||
this.autoselect = !!o.autoselect; | ||
@@ -33,2 +34,25 @@ this.minLength = _.isNumber(o.minLength) ? o.minLength : 1; | ||
// #705: if there's scrollable overflow, ie doesn't support | ||
// blur cancellations when the scrollbar is clicked | ||
// | ||
// #351: preventDefault won't cancel blurs in ie <= 8 | ||
$input.on('blur.tt', function($e) { | ||
var active, isActive, hasActive; | ||
active = document.activeElement; | ||
isActive = $menu.is(active); | ||
hasActive = $menu.has(active).length > 0; | ||
if (_.isMsie() && (isActive || hasActive)) { | ||
$e.preventDefault(); | ||
// stop immediate in order to prevent Input#_onBlur from | ||
// getting exectued | ||
$e.stopImmediatePropagation(); | ||
_.defer(function() { $input.focus(); }); | ||
} | ||
}); | ||
// #351: prevents input blur due to clicks within dropdown menu | ||
$menu.on('mousedown.tt', function($e) { $e.preventDefault(); }); | ||
this.eventBus = o.eventBus || new EventBus({ el: $input }); | ||
@@ -57,14 +81,3 @@ | ||
// #351: prevents input blur on menu click | ||
$menu.on('mousedown.tt', function($e) { | ||
if (_.isMsie() && _.isMsie() < 9) { | ||
$input[0].onbeforedeactivate = function() { | ||
window.event.returnValue = false; | ||
$input[0].onbeforedeactivate = null; | ||
}; | ||
} | ||
// ie 9+ and other browsers | ||
$e.preventDefault(); | ||
}); | ||
this._setLanguageDirection(); | ||
} | ||
@@ -90,3 +103,2 @@ | ||
this.input.clearHint(); | ||
this.input.setInputValue(datum.value, true); | ||
@@ -119,3 +131,3 @@ | ||
_onFocused: function onFocused() { | ||
this.dropdown.empty(); | ||
this.isActivated = true; | ||
this.dropdown.open(); | ||
@@ -125,2 +137,4 @@ }, | ||
_onBlurred: function onBlurred() { | ||
this.isActivated = false; | ||
this.dropdown.empty(); | ||
this.dropdown.close(); | ||
@@ -155,3 +169,3 @@ }, | ||
else { | ||
this._autocomplete(); | ||
this._autocomplete(true); | ||
} | ||
@@ -168,8 +182,7 @@ }, | ||
if(!this.dropdown.isOpen && query.length >= this.minLength) { | ||
this.dropdown.update(query); | ||
} | ||
this.dropdown.isEmpty && query.length >= this.minLength ? | ||
this.dropdown.update(query) : | ||
this.dropdown.moveCursorUp(); | ||
this.dropdown.open(); | ||
this.dropdown.moveCursorUp(); | ||
}, | ||
@@ -180,8 +193,7 @@ | ||
if( !this.dropdown.isOpen && query.length >= this.minLength) { | ||
this.dropdown.update(query); | ||
} | ||
this.dropdown.isEmpty && query.length >= this.minLength ? | ||
this.dropdown.update(query) : | ||
this.dropdown.moveCursorDown(); | ||
this.dropdown.open(); | ||
this.dropdown.moveCursorDown(); | ||
}, | ||
@@ -198,5 +210,8 @@ | ||
_onQueryChanged: function onQueryChanged(e, query) { | ||
this.input.clearHint(); | ||
this.dropdown.empty(); | ||
query.length >= this.minLength && this.dropdown.update(query); | ||
this.input.clearHintIfInvalid(); | ||
query.length >= this.minLength ? | ||
this.dropdown.update(query) : | ||
this.dropdown.empty(); | ||
this.dropdown.open(); | ||
@@ -222,3 +237,3 @@ this._setLanguageDirection(); | ||
_updateHint: function updateHint() { | ||
var datum, inputValue, query, escapedQuery, frontMatchRegEx, match; | ||
var datum, val, query, escapedQuery, frontMatchRegEx, match; | ||
@@ -228,20 +243,27 @@ datum = this.dropdown.getDatumForTopSuggestion(); | ||
if (datum && this.dropdown.isVisible() && !this.input.hasOverflow()) { | ||
inputValue = this.input.getInputValue(); | ||
query = Input.normalizeQuery(inputValue); | ||
val = this.input.getInputValue(); | ||
query = Input.normalizeQuery(val); | ||
escapedQuery = _.escapeRegExChars(query); | ||
frontMatchRegEx = new RegExp('^(?:' + escapedQuery + ')(.*$)', 'i'); | ||
// match input value, then capture trailing text | ||
frontMatchRegEx = new RegExp('^(?:' + escapedQuery + ')(.+$)', 'i'); | ||
match = frontMatchRegEx.exec(datum.value); | ||
this.input.setHintValue(inputValue + (match ? match[1] : '')); | ||
// clear hint if there's no trailing text | ||
match ? this.input.setHint(val + match[1]) : this.input.clearHint(); | ||
} | ||
else { | ||
this.input.clearHint(); | ||
} | ||
}, | ||
_autocomplete: function autocomplete() { | ||
var hint, query, datum; | ||
_autocomplete: function autocomplete(laxCursor) { | ||
var hint, query, isCursorAtEnd, datum; | ||
hint = this.input.getHintValue(); | ||
hint = this.input.getHint(); | ||
query = this.input.getQuery(); | ||
isCursorAtEnd = laxCursor || this.input.isCursorAtEnd(); | ||
if (hint && query !== hint && this.input.isCursorAtEnd()) { | ||
if (hint && query !== hint && isCursorAtEnd) { | ||
datum = this.dropdown.getDatumForTopSuggestion(); | ||
@@ -255,3 +277,2 @@ datum && this.input.setInputValue(datum.value); | ||
_select: function select(datum) { | ||
this.input.clearHint(); | ||
this.input.setQuery(datum.value); | ||
@@ -280,8 +301,17 @@ this.input.setInputValue(datum.value, true); | ||
getQuery: function getQuery() { | ||
return this.input.getQuery(); | ||
setVal: function setVal(val) { | ||
if (this.isActivated) { | ||
this.input.setInputValue(val); | ||
} | ||
else { | ||
this.input.setQuery(val); | ||
this.input.setInputValue(val, true); | ||
} | ||
this._setLanguageDirection(); | ||
}, | ||
setQuery: function setQuery(val) { | ||
this.input.setInputValue(val); | ||
getVal: function getVal() { | ||
return this.input.getQuery(); | ||
}, | ||
@@ -288,0 +318,0 @@ |
@@ -13,2 +13,104 @@ describe('Bloodhound', function() { | ||
describe('#initialize', function() { | ||
beforeEach(function() { | ||
this.bloodhound = new Bloodhound({ | ||
datumTokenizer: datumTokenizer, | ||
queryTokenizer: queryTokenizer, | ||
local: fixtures.data.simple | ||
}); | ||
spyOn(this.bloodhound, '_initialize').andCallThrough(); | ||
}); | ||
it('should not support reinitialization by default', function() { | ||
var p1, p2; | ||
p1 = this.bloodhound.initialize(); | ||
p2 = this.bloodhound.initialize(); | ||
expect(p1).toBe(p2); | ||
expect(this.bloodhound._initialize.callCount).toBe(1); | ||
}); | ||
it('should reinitialize if reintialize flag is true', function() { | ||
var p1, p2; | ||
p1 = this.bloodhound.initialize(); | ||
p2 = this.bloodhound.initialize(true); | ||
expect(p1).not.toBe(p2); | ||
expect(this.bloodhound._initialize.callCount).toBe(2); | ||
}); | ||
}); | ||
describe('#add', function() { | ||
it('should add datums to search index', function() { | ||
var spy = jasmine.createSpy(); | ||
this.bloodhound = new Bloodhound({ | ||
datumTokenizer: datumTokenizer, | ||
queryTokenizer: queryTokenizer, | ||
local: [] | ||
}); | ||
this.bloodhound.initialize(); | ||
this.bloodhound.add(fixtures.data.simple); | ||
this.bloodhound.get('big', spy); | ||
expect(spy).toHaveBeenCalledWith([ | ||
{ value: 'big' }, | ||
{ value: 'bigger' }, | ||
{ value: 'biggest' } | ||
]); | ||
}); | ||
}); | ||
describe('#clear', function() { | ||
it('should remove all datums to search index', function() { | ||
var spy = jasmine.createSpy(); | ||
this.bloodhound = new Bloodhound({ | ||
datumTokenizer: datumTokenizer, | ||
queryTokenizer: queryTokenizer, | ||
local: fixtures.data.simple | ||
}); | ||
this.bloodhound.initialize(); | ||
this.bloodhound.clear(); | ||
this.bloodhound.get('big', spy); | ||
expect(spy).toHaveBeenCalledWith([]); | ||
}); | ||
}); | ||
describe('#clearPrefetchCache', function() { | ||
it('should clear persistent storage', function() { | ||
this.bloodhound = new Bloodhound({ | ||
datumTokenizer: datumTokenizer, | ||
queryTokenizer: queryTokenizer, | ||
prefetch: '/test' | ||
}); | ||
this.bloodhound.initialize(); | ||
this.bloodhound.clearPrefetchCache(); | ||
expect(this.bloodhound.storage.clear).toHaveBeenCalled(); | ||
}); | ||
}); | ||
describe('#clearRemoteCache', function() { | ||
it('should clear remote request cache', function() { | ||
spyOn(Transport, 'resetCache'); | ||
this.bloodhound = new Bloodhound({ | ||
datumTokenizer: datumTokenizer, | ||
queryTokenizer: queryTokenizer, | ||
remote: '/test' | ||
}); | ||
this.bloodhound.initialize(); | ||
this.bloodhound.clearRemoteCache(); | ||
expect(Transport.resetCache).toHaveBeenCalled(); | ||
}); | ||
}); | ||
describe('local', function() { | ||
@@ -144,2 +246,16 @@ describe('when local is an array', function() { | ||
it('should clear preexisting data', function() { | ||
this.bloodhound = new Bloodhound({ | ||
datumTokenizer: datumTokenizer, | ||
queryTokenizer: queryTokenizer, | ||
prefetch: '/test' | ||
}); | ||
spyOn(this.bloodhound, 'clear'); | ||
this.bloodhound.initialize(); | ||
mostRecentAjaxRequest().response(fixtures.ajaxResps.ok); | ||
expect(this.bloodhound.clear).toHaveBeenCalled(); | ||
}); | ||
it('should filter data if filter is provided', function() { | ||
@@ -284,7 +400,90 @@ var filterSpy, spy; | ||
function fakeGet(url, o, cb) { | ||
cb(fixtures.data.simple); | ||
cb(null, fixtures.data.simple); | ||
} | ||
}); | ||
it('should call #get callback once if cache hit', function() { | ||
describe('when there is not matching data in the search index', function() { | ||
beforeEach(function() { | ||
this.bloodhound = new Bloodhound({ | ||
datumTokenizer: datumTokenizer, | ||
queryTokenizer: queryTokenizer, | ||
remote: '/test?q=%QUERY', | ||
local: { value: 'not an animal' } | ||
}); | ||
this.bloodhound.initialize(); | ||
}); | ||
it('should call #get callback once if there is a cache hit', function() { | ||
var spy = jasmine.createSpy(); | ||
this.bloodhound.transport.get.andCallFake(fakeGetWithCacheHit); | ||
this.bloodhound.get('dog', spy); | ||
expect(spy.callCount).toBe(1); | ||
function fakeGetWithCacheHit(url, o, cb) { | ||
cb(null, fixtures.data.animals); | ||
return true; | ||
} | ||
}); | ||
it('should call #get callback once if there is a cache miss', function() { | ||
var spy = jasmine.createSpy(); | ||
this.bloodhound.transport.get.andCallFake(fakeGetWithCacheMiss); | ||
this.bloodhound.get('dog', spy); | ||
expect(spy.callCount).toBe(1); | ||
function fakeGetWithCacheMiss(url, o, cb) { | ||
cb(null, fixtures.data.animals); | ||
return false; | ||
} | ||
}); | ||
}); | ||
describe('when there is matching data in the search index', function() { | ||
beforeEach(function() { | ||
this.bloodhound = new Bloodhound({ | ||
datumTokenizer: datumTokenizer, | ||
queryTokenizer: queryTokenizer, | ||
remote: '/test?q=%QUERY', | ||
local: { value: 'dog' } | ||
}); | ||
this.bloodhound.initialize(); | ||
}); | ||
it('should call the #get callback twice if there is a cache miss', function() { | ||
var spy = jasmine.createSpy(); | ||
this.bloodhound.transport.get.andCallFake(fakeGetWithCacheMiss); | ||
this.bloodhound.get('dog', spy); | ||
expect(spy.callCount).toBe(2); | ||
function fakeGetWithCacheMiss(url, o, cb) { | ||
cb(null, fixtures.data.animals); | ||
return false; | ||
} | ||
}); | ||
it('should call the #get callback once if there is a cache hit', function() { | ||
var spy = jasmine.createSpy(); | ||
this.bloodhound.transport.get.andCallFake(fakeGetWithCacheHit); | ||
this.bloodhound.get('dog', spy); | ||
expect(spy.callCount).toBe(1); | ||
function fakeGetWithCacheHit(url, o, cb) { | ||
cb(null, fixtures.data.animals); | ||
return true; | ||
} | ||
}); | ||
}); | ||
it('should should treat failures as empty suggestion sets', function() { | ||
var spy = jasmine.createSpy(); | ||
@@ -302,8 +501,5 @@ | ||
expect(spy.callCount).toBe(1); | ||
expect(spy).toHaveBeenCalledWith([]); | ||
function fakeGet(url, o, cb) { | ||
cb(fixtures.data.animals); | ||
return true; | ||
} | ||
function fakeGet(url, o, cb) { cb(true); } | ||
}); | ||
@@ -342,3 +538,3 @@ }); | ||
function fakeGet(url, o, cb) { | ||
setTimeout(function() { cb(fixtures.data.animals); }, 0); | ||
setTimeout(function() { cb(null, fixtures.data.animals); }, 0); | ||
} | ||
@@ -391,3 +587,3 @@ }); | ||
function fakeGet(url, o, cb) { | ||
setTimeout(function() { cb(fixtures.data.animals); }, 0); | ||
setTimeout(function() { cb(null, fixtures.data.animals); }, 0); | ||
} | ||
@@ -394,0 +590,0 @@ }); |
@@ -131,2 +131,12 @@ describe('Dataset', function() { | ||
it('should not render suggestions if update was canceled', function() { | ||
this.source.andCallFake(fakeGetWithAsyncResults); | ||
this.dataset.update('woah'); | ||
this.dataset.cancel(); | ||
waits(100); | ||
runs(function() { expect(this.dataset.getRoot()).toBeEmpty(); }); | ||
}); | ||
it('should trigger rendered after suggestions are rendered', function() { | ||
@@ -152,2 +162,13 @@ var spy; | ||
}); | ||
it('should cancel pending updates', function() { | ||
var spy = spyOn(this.dataset, 'cancel'); | ||
this.source.andCallFake(fakeGetWithSyncResults); | ||
this.dataset.update('woah'); | ||
expect(this.dataset.canceled).toBe(false); | ||
this.dataset.clear(); | ||
expect(spy).toHaveBeenCalled(); | ||
}); | ||
}); | ||
@@ -154,0 +175,0 @@ |
@@ -86,3 +86,3 @@ describe('Input', function() { | ||
this.view.setHintValue('good'); | ||
this.view.setHint('good'); | ||
this.view.setInputValue('goo'); | ||
@@ -277,6 +277,6 @@ | ||
describe('#getHintValue/#setHintValue', function() { | ||
describe('#getHint/#setHint', function() { | ||
it('should act as getter/setter to value of hint', function() { | ||
this.view.setHintValue('mountain'); | ||
expect(this.view.getHintValue()).toBe('mountain'); | ||
this.view.setHint('mountain'); | ||
expect(this.view.getHint()).toBe('mountain'); | ||
}); | ||
@@ -297,9 +297,44 @@ }); | ||
it('should set the hint value to the empty string', function() { | ||
this.view.setHintValue('cheese'); | ||
this.view.setHint('cheese'); | ||
this.view.clearHint(); | ||
expect(this.view.getHintValue()).toBe(''); | ||
expect(this.view.getHint()).toBe(''); | ||
}); | ||
}); | ||
describe('#clearHintIfInvalid', function() { | ||
it('should clear hint if input value is empty string', function() { | ||
this.view.setInputValue('', true); | ||
this.view.setHint('cheese'); | ||
this.view.clearHintIfInvalid(); | ||
expect(this.view.getHint()).toBe(''); | ||
}); | ||
it('should clear hint if input value is not prefix of input', function() { | ||
this.view.setInputValue('milk', true); | ||
this.view.setHint('cheese'); | ||
this.view.clearHintIfInvalid(); | ||
expect(this.view.getHint()).toBe(''); | ||
}); | ||
it('should clear hint if overflow exists', function() { | ||
spyOn(this.view, 'hasOverflow').andReturn(true); | ||
this.view.setInputValue('che', true); | ||
this.view.setHint('cheese'); | ||
this.view.clearHintIfInvalid(); | ||
expect(this.view.getHint()).toBe(''); | ||
}); | ||
it('should not clear hint if input value is prefix of input', function() { | ||
this.view.setInputValue('che', true); | ||
this.view.setHint('cheese'); | ||
this.view.clearHintIfInvalid(); | ||
expect(this.view.getHint()).toBe('cheese'); | ||
}); | ||
}); | ||
describe('#getLanguageDirection', function() { | ||
@@ -306,0 +341,0 @@ it('should return the language direction of the input', function() { |
@@ -48,2 +48,9 @@ describe('SearchIndex', function() { | ||
it('#reset should empty the search index', function() { | ||
this.searchIndex.reset(); | ||
expect(this.searchIndex.datums).toEqual([]); | ||
expect(this.searchIndex.trie.ids).toEqual([]); | ||
expect(this.searchIndex.trie.children).toEqual({}); | ||
}); | ||
// helper functions | ||
@@ -50,0 +57,0 @@ // ---------------- |
@@ -31,3 +31,3 @@ describe('Transport', function() { | ||
expect(req.url).toBe('/test'); | ||
expect(spy).toHaveBeenCalledWith(resp.parsed); | ||
expect(spy).toHaveBeenCalledWith(null, resp.parsed); | ||
}); | ||
@@ -46,3 +46,3 @@ | ||
runs(function() { | ||
expect(cbSpy).toHaveBeenCalledWith(resp.parsed); | ||
expect(cbSpy).toHaveBeenCalledWith(null, resp.parsed); | ||
expect(sendSpy).toHaveBeenCalledWith( | ||
@@ -101,4 +101,4 @@ '/test', | ||
expect(spy1).toHaveBeenCalledWith(fixtures.ajaxResps.ok.parsed); | ||
expect(spy2).toHaveBeenCalledWith(fixtures.ajaxResps.ok1.parsed); | ||
expect(spy1).toHaveBeenCalledWith(null, fixtures.ajaxResps.ok.parsed); | ||
expect(spy2).toHaveBeenCalledWith(null, fixtures.ajaxResps.ok1.parsed); | ||
}); | ||
@@ -120,4 +120,4 @@ }); | ||
runs(function() { | ||
expect(spy1).toHaveBeenCalledWith(fixtures.ajaxResps.ok.parsed); | ||
expect(spy2).toHaveBeenCalledWith(fixtures.ajaxResps.ok.parsed); | ||
expect(spy1).toHaveBeenCalledWith(null, fixtures.ajaxResps.ok.parsed); | ||
expect(spy2).toHaveBeenCalledWith(null, fixtures.ajaxResps.ok.parsed); | ||
}); | ||
@@ -146,3 +146,3 @@ }); | ||
it('should not invoke the callback on failure', function() { | ||
it('should invoke the callback with err set to true on failure', function() { | ||
var req, resp = fixtures.ajaxResps.err, spy = jasmine.createSpy(); | ||
@@ -156,4 +156,4 @@ | ||
expect(req.url).toBe('/test'); | ||
expect(spy).not.toHaveBeenCalledWith(resp.parsed); | ||
expect(spy).toHaveBeenCalledWith(true); | ||
}); | ||
}); |
@@ -40,3 +40,2 @@ describe('Typeahead', function() { | ||
expect(spy).toHaveBeenCalled(); | ||
expect(this.input.clearHint).toHaveBeenCalled(); | ||
expect(this.input.setQuery).toHaveBeenCalledWith(testDatum.value); | ||
@@ -55,8 +54,2 @@ expect(this.input.setInputValue) | ||
it('should clear the hint', function() { | ||
this.dropdown.trigger('cursorMoved'); | ||
expect(this.input.clearHint).toHaveBeenCalled(); | ||
}); | ||
it('should update the input value', function() { | ||
@@ -95,3 +88,3 @@ this.dropdown.trigger('cursorMoved'); | ||
expect(this.input.setHintValue).toHaveBeenCalledWith(testDatum.value); | ||
expect(this.input.setHint).toHaveBeenCalledWith(testDatum.value); | ||
}); | ||
@@ -109,8 +102,11 @@ }); | ||
// ensure it wasn't called synchronously | ||
expect(this.input.setHint).not.toHaveBeenCalled(); | ||
waitsFor(function() { | ||
return !!this.input.setHintValue.callCount; | ||
return !!this.input.setHint.callCount; | ||
}); | ||
runs(function() { | ||
expect(this.input.setHintValue).toHaveBeenCalledWith(testDatum.value); | ||
expect(this.input.setHint).toHaveBeenCalledWith(testDatum.value); | ||
}); | ||
@@ -129,3 +125,3 @@ }); | ||
expect(this.input.setHintValue).toHaveBeenCalledWith(testDatum.value); | ||
expect(this.input.setHint).toHaveBeenCalledWith(testDatum.value); | ||
}); | ||
@@ -163,6 +159,6 @@ | ||
describe('when input triggers focused', function() { | ||
it('should empty the dropdown', function() { | ||
it('should activate the typeahead', function() { | ||
this.input.trigger('focused'); | ||
expect(this.dropdown.empty).toHaveBeenCalled(); | ||
expect(this.view.isActivated).toBe(true); | ||
}); | ||
@@ -178,2 +174,14 @@ | ||
describe('when input triggers blurred', function() { | ||
it('should deactivate the typeahead', function() { | ||
this.input.trigger('blurred'); | ||
expect(this.view.isActivated).toBe(false); | ||
}); | ||
it('should empty the dropdown', function() { | ||
this.input.trigger('blurred'); | ||
expect(this.dropdown.empty).toHaveBeenCalled(); | ||
}); | ||
it('should close the dropdown', function() { | ||
@@ -199,3 +207,2 @@ this.input.trigger('blurred'); | ||
expect(spy).toHaveBeenCalled(); | ||
expect(this.input.clearHint).toHaveBeenCalled(); | ||
expect(this.input.setQuery).toHaveBeenCalledWith(testDatum.value); | ||
@@ -232,3 +239,2 @@ expect(this.input.setInputValue) | ||
expect(spy).toHaveBeenCalled(); | ||
expect(this.input.clearHint).toHaveBeenCalled(); | ||
expect(this.input.setQuery).toHaveBeenCalledWith(testDatum.value); | ||
@@ -256,3 +262,3 @@ expect(this.input.setInputValue) | ||
this.input.getQuery.andReturn('bi'); | ||
this.input.getHintValue.andReturn(testDatum.value); | ||
this.input.getHint.andReturn(testDatum.value); | ||
this.input.isCursorAtEnd.andReturn(true); | ||
@@ -289,25 +295,57 @@ this.dropdown.getDatumForTopSuggestion.andReturn(testDatum); | ||
describe('when dropdown is closed and minLength is satisfied', function() { | ||
describe('when dropdown is empty and minLength is satisfied', function() { | ||
beforeEach(function() { | ||
this.dropdown.isOpen = false; | ||
this.dropdown.isEmpty = true; | ||
this.view.minLength = 2; | ||
this.input.trigger('upKeyed'); | ||
}); | ||
it('should update dropdown', function() { | ||
expect(this.dropdown.update).toHaveBeenCalledWith('ghost'); | ||
}); | ||
it('should not move cursor up', function() { | ||
expect(this.dropdown.moveCursorUp).not.toHaveBeenCalled(); | ||
}); | ||
}); | ||
describe('when dropdown is not empty', function() { | ||
beforeEach(function() { | ||
this.dropdown.isEmpty = false; | ||
this.view.minLength = 2; | ||
this.input.trigger('upKeyed'); | ||
}); | ||
expect(this.dropdown.update).toHaveBeenCalledWith('ghost'); | ||
it('should not update dropdown', function() { | ||
expect(this.dropdown.update).not.toHaveBeenCalled(); | ||
}); | ||
it('should move cursor up', function() { | ||
expect(this.dropdown.moveCursorUp).toHaveBeenCalled(); | ||
}); | ||
}); | ||
it('should open the dropdown', function() { | ||
this.input.trigger('upKeyed'); | ||
describe('when minLength is not satisfied', function() { | ||
beforeEach(function() { | ||
this.dropdown.isEmpty = true; | ||
this.view.minLength = 10; | ||
expect(this.dropdown.open).toHaveBeenCalled(); | ||
this.input.trigger('upKeyed'); | ||
}); | ||
it('should not update dropdown', function() { | ||
expect(this.dropdown.update).not.toHaveBeenCalled(); | ||
}); | ||
it('should move cursor up', function() { | ||
expect(this.dropdown.moveCursorUp).toHaveBeenCalled(); | ||
}); | ||
}); | ||
it('should move the cursor up', function() { | ||
it('should open the dropdown', function() { | ||
this.input.trigger('upKeyed'); | ||
expect(this.dropdown.moveCursorUp).toHaveBeenCalled(); | ||
expect(this.dropdown.open).toHaveBeenCalled(); | ||
}); | ||
@@ -321,25 +359,57 @@ }); | ||
describe('when dropdown is closed and minLength is satisfied', function() { | ||
describe('when dropdown is empty and minLength is satisfied', function() { | ||
beforeEach(function() { | ||
this.dropdown.isOpen = false; | ||
this.dropdown.isEmpty = true; | ||
this.view.minLength = 2; | ||
this.input.trigger('downKeyed'); | ||
}); | ||
it('should update dropdown', function() { | ||
expect(this.dropdown.update).toHaveBeenCalledWith('ghost'); | ||
}); | ||
it('should not move cursor down', function() { | ||
expect(this.dropdown.moveCursorDown).not.toHaveBeenCalled(); | ||
}); | ||
}); | ||
describe('when dropdown is not empty', function() { | ||
beforeEach(function() { | ||
this.dropdown.isEmpty = false; | ||
this.view.minLength = 2; | ||
this.input.trigger('downKeyed'); | ||
}); | ||
expect(this.dropdown.update).toHaveBeenCalledWith('ghost'); | ||
it('should not update dropdown', function() { | ||
expect(this.dropdown.update).not.toHaveBeenCalled(); | ||
}); | ||
it('should move cursor down', function() { | ||
expect(this.dropdown.moveCursorDown).toHaveBeenCalled(); | ||
}); | ||
}); | ||
it('should open the dropdown', function() { | ||
this.input.trigger('downKeyed'); | ||
describe('when minLength is not satisfied', function() { | ||
beforeEach(function() { | ||
this.dropdown.isEmpty = true; | ||
this.view.minLength = 10; | ||
expect(this.dropdown.open).toHaveBeenCalled(); | ||
this.input.trigger('downKeyed'); | ||
}); | ||
it('should not update dropdown', function() { | ||
expect(this.dropdown.update).not.toHaveBeenCalled(); | ||
}); | ||
it('should move cursor down', function() { | ||
expect(this.dropdown.moveCursorDown).toHaveBeenCalled(); | ||
}); | ||
}); | ||
it('should move the cursor down', function() { | ||
it('should open the dropdown', function() { | ||
this.input.trigger('downKeyed'); | ||
expect(this.dropdown.moveCursorDown).toHaveBeenCalled(); | ||
expect(this.dropdown.open).toHaveBeenCalled(); | ||
}); | ||
@@ -354,3 +424,3 @@ }); | ||
this.input.getQuery.andReturn('bi'); | ||
this.input.getHintValue.andReturn(testDatum.value); | ||
this.input.getHint.andReturn(testDatum.value); | ||
this.input.isCursorAtEnd.andReturn(true); | ||
@@ -373,3 +443,3 @@ this.dropdown.getDatumForTopSuggestion.andReturn(testDatum); | ||
this.input.getQuery.andReturn('bi'); | ||
this.input.getHintValue.andReturn(testDatum.value); | ||
this.input.getHint.andReturn(testDatum.value); | ||
this.input.isCursorAtEnd.andReturn(true); | ||
@@ -387,10 +457,10 @@ this.dropdown.getDatumForTopSuggestion.andReturn(testDatum); | ||
describe('when input triggers queryChanged', function() { | ||
it('should clear the hint', function() { | ||
it('should clear the hint if it has become invalid', function() { | ||
this.input.trigger('queryChanged', testDatum.value); | ||
expect(this.input.clearHint).toHaveBeenCalled(); | ||
expect(this.input.clearHintIfInvalid).toHaveBeenCalled(); | ||
}); | ||
it('should empty dropdown', function() { | ||
this.input.trigger('queryChanged', testDatum.value); | ||
it('should empty dropdown if the query is empty', function() { | ||
this.input.trigger('queryChanged', ''); | ||
@@ -400,2 +470,8 @@ expect(this.dropdown.empty).toHaveBeenCalled(); | ||
it('should not empty dropdown if the query is non-empty', function() { | ||
this.input.trigger('queryChanged', testDatum.value); | ||
expect(this.dropdown.empty).not.toHaveBeenCalled(); | ||
}); | ||
it('should update dropdown', function() { | ||
@@ -433,3 +509,3 @@ this.input.trigger('queryChanged', testDatum.value); | ||
expect(this.input.setHintValue).toHaveBeenCalledWith(testDatum.value); | ||
expect(this.input.setHint).toHaveBeenCalledWith(testDatum.value); | ||
}); | ||
@@ -460,3 +536,3 @@ | ||
describe('#getQuery', function() { | ||
describe('#getVal', function() { | ||
it('should return the current query', function() { | ||
@@ -466,12 +542,20 @@ this.input.getQuery.andReturn('woah'); | ||
expect(this.view.getQuery()).toBe('woah'); | ||
expect(this.view.getVal()).toBe('woah'); | ||
}); | ||
}); | ||
describe('#getQuery', function() { | ||
it('should update the input value', function() { | ||
this.view.setQuery('woah'); | ||
describe('#setVal', function() { | ||
it('should update query', function() { | ||
this.view.isActivated = true; | ||
this.view.setVal('woah'); | ||
expect(this.input.setInputValue).toHaveBeenCalledWith('woah'); | ||
}); | ||
it('should update query silently if not activated', function() { | ||
this.view.setVal('woah'); | ||
expect(this.input.setQuery).toHaveBeenCalledWith('woah'); | ||
expect(this.input.setInputValue).toHaveBeenCalledWith('woah', true); | ||
}); | ||
}); | ||
@@ -478,0 +562,0 @@ |
@@ -8,3 +8,3 @@ { | ||
"dependencies": { | ||
"jquery": "~1.9" | ||
"jquery": ">=1.9" | ||
}, | ||
@@ -40,3 +40,3 @@ "docs": "https://github.com/twitter/typeahead.js", | ||
], | ||
"version": "0.10.1" | ||
"version": "0.10.2" | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
58
189
0
417846
13
8233