web: update typeahead.js to 0.10.4
This commit is contained in:
parent
3ce34b145c
commit
50ef6d52dd
@ -1,11 +1,13 @@
|
||||
/*!
|
||||
* typeahead.js 0.10.2
|
||||
* typeahead.js 0.10.4
|
||||
* https://github.com/twitter/typeahead.js
|
||||
* Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
var _ = {
|
||||
var _ = function() {
|
||||
"use strict";
|
||||
return {
|
||||
isMsie: function() {
|
||||
return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false;
|
||||
},
|
||||
@ -27,6 +29,9 @@
|
||||
isUndefined: function(obj) {
|
||||
return typeof obj === "undefined";
|
||||
},
|
||||
toStr: function toStr(s) {
|
||||
return _.isUndefined(s) || s === null ? "" : s + "";
|
||||
},
|
||||
bind: $.proxy,
|
||||
each: function(collection, cb) {
|
||||
$.each(collection, reverseArgs);
|
||||
@ -120,8 +125,10 @@
|
||||
},
|
||||
noop: function() {}
|
||||
};
|
||||
var VERSION = "0.10.2";
|
||||
var tokenizers = function(root) {
|
||||
}();
|
||||
var VERSION = "0.10.4";
|
||||
var tokenizers = function() {
|
||||
"use strict";
|
||||
return {
|
||||
nonword: nonword,
|
||||
whitespace: whitespace,
|
||||
@ -130,26 +137,35 @@
|
||||
whitespace: getObjTokenizer(whitespace)
|
||||
}
|
||||
};
|
||||
function whitespace(s) {
|
||||
return s.split(/\s+/);
|
||||
function whitespace(str) {
|
||||
str = _.toStr(str);
|
||||
return str ? str.split(/\s+/) : [];
|
||||
}
|
||||
function nonword(s) {
|
||||
return s.split(/\W+/);
|
||||
function nonword(str) {
|
||||
str = _.toStr(str);
|
||||
return str ? str.split(/\W+/) : [];
|
||||
}
|
||||
function getObjTokenizer(tokenizer) {
|
||||
return function setKey(key) {
|
||||
return function setKey() {
|
||||
var args = [].slice.call(arguments, 0);
|
||||
return function tokenize(o) {
|
||||
return tokenizer(o[key]);
|
||||
var tokens = [];
|
||||
_.each(args, function(k) {
|
||||
tokens = tokens.concat(tokenizer(_.toStr(o[k])));
|
||||
});
|
||||
return tokens;
|
||||
};
|
||||
};
|
||||
}
|
||||
}();
|
||||
var LruCache = function() {
|
||||
"use strict";
|
||||
function LruCache(maxSize) {
|
||||
this.maxSize = maxSize || 100;
|
||||
this.size = 0;
|
||||
this.hash = {};
|
||||
this.list = new List();
|
||||
this.maxSize = _.isNumber(maxSize) ? maxSize : 100;
|
||||
this.reset();
|
||||
if (this.maxSize <= 0) {
|
||||
this.set = this.get = $.noop;
|
||||
}
|
||||
}
|
||||
_.mixin(LruCache.prototype, {
|
||||
set: function set(key, val) {
|
||||
@ -174,6 +190,11 @@
|
||||
this.list.moveToFront(node);
|
||||
return node.val;
|
||||
}
|
||||
},
|
||||
reset: function reset() {
|
||||
this.size = 0;
|
||||
this.hash = {};
|
||||
this.list = new List();
|
||||
}
|
||||
});
|
||||
function List() {
|
||||
@ -205,6 +226,7 @@
|
||||
return LruCache;
|
||||
}();
|
||||
var PersistentStorage = function() {
|
||||
"use strict";
|
||||
var ls, methods;
|
||||
try {
|
||||
ls = window.localStorage;
|
||||
@ -216,7 +238,7 @@
|
||||
function PersistentStorage(namespace) {
|
||||
this.prefix = [ "__", namespace, "__" ].join("");
|
||||
this.ttlKey = "__ttl__";
|
||||
this.keyMatcher = new RegExp("^" + this.prefix);
|
||||
this.keyMatcher = new RegExp("^" + _.escapeRegExChars(this.prefix));
|
||||
}
|
||||
if (ls && window.JSON) {
|
||||
methods = {
|
||||
@ -284,21 +306,28 @@
|
||||
}
|
||||
}();
|
||||
var Transport = function() {
|
||||
var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests = 6, requestCache = new LruCache(10);
|
||||
"use strict";
|
||||
var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests = 6, sharedCache = new LruCache(10);
|
||||
function Transport(o) {
|
||||
o = o || {};
|
||||
this.cancelled = false;
|
||||
this.lastUrl = null;
|
||||
this._send = o.transport ? callbackToDeferred(o.transport) : $.ajax;
|
||||
this._get = o.rateLimiter ? o.rateLimiter(this._get) : this._get;
|
||||
this._cache = o.cache === false ? new LruCache(0) : sharedCache;
|
||||
}
|
||||
Transport.setMaxPendingRequests = function setMaxPendingRequests(num) {
|
||||
maxPendingRequests = num;
|
||||
};
|
||||
Transport.resetCache = function clearCache() {
|
||||
requestCache = new LruCache(10);
|
||||
Transport.resetCache = function resetCache() {
|
||||
sharedCache.reset();
|
||||
};
|
||||
_.mixin(Transport.prototype, {
|
||||
_get: function(url, o, cb) {
|
||||
var that = this, jqXhr;
|
||||
if (this.cancelled || url !== this.lastUrl) {
|
||||
return;
|
||||
}
|
||||
if (jqXhr = pendingRequests[url]) {
|
||||
jqXhr.done(done).fail(fail);
|
||||
} else if (pendingRequestsCount < maxPendingRequests) {
|
||||
@ -309,7 +338,7 @@
|
||||
}
|
||||
function done(resp) {
|
||||
cb && cb(null, resp);
|
||||
requestCache.set(url, resp);
|
||||
that._cache.set(url, resp);
|
||||
}
|
||||
function fail() {
|
||||
cb && cb(true);
|
||||
@ -329,7 +358,9 @@
|
||||
cb = o;
|
||||
o = {};
|
||||
}
|
||||
if (resp = requestCache.get(url)) {
|
||||
this.cancelled = false;
|
||||
this.lastUrl = url;
|
||||
if (resp = this._cache.get(url)) {
|
||||
_.defer(function() {
|
||||
cb && cb(null, resp);
|
||||
});
|
||||
@ -337,6 +368,9 @@
|
||||
this._get(url, o, cb);
|
||||
}
|
||||
return !!resp;
|
||||
},
|
||||
cancel: function() {
|
||||
this.cancelled = true;
|
||||
}
|
||||
});
|
||||
return Transport;
|
||||
@ -359,6 +393,7 @@
|
||||
}
|
||||
}();
|
||||
var SearchIndex = function() {
|
||||
"use strict";
|
||||
function SearchIndex(o) {
|
||||
o = o || {};
|
||||
if (!o.datumTokenizer || !o.queryTokenizer) {
|
||||
@ -370,12 +405,10 @@
|
||||
}
|
||||
_.mixin(SearchIndex.prototype, {
|
||||
bootstrap: function bootstrap(o) {
|
||||
console.log('bootstrap',o);
|
||||
this.datums = o.datums;
|
||||
this.trie = o.trie;
|
||||
},
|
||||
add: function(data) {
|
||||
console.log('add',data);
|
||||
var that = this;
|
||||
data = _.isArray(data) ? data : [ data ];
|
||||
_.each(data, function(datum) {
|
||||
@ -394,32 +427,18 @@
|
||||
});
|
||||
},
|
||||
get: function get(query) {
|
||||
console.log('trie',this.trie);
|
||||
var that = this, tokens, matches;
|
||||
tokens = normalizeTokens(this.queryTokenizer(query));
|
||||
// console.log('query',query);
|
||||
// console.log('tokens',tokens);
|
||||
_.each(tokens, function(token) {
|
||||
var node, chars, ch, ids;
|
||||
if (matches && matches.length === 0) {
|
||||
return false;
|
||||
}
|
||||
node = that.trie;
|
||||
// console.log('token',token);
|
||||
// console.log('token split',token.split(""));
|
||||
//whatever variable is used in the following while loop is losing the first character sometimes
|
||||
chars = token.split("");
|
||||
// console.log('pre node',node);
|
||||
// console.log('pre chars',chars);
|
||||
// console.log('ch1',ch = chars.shift());
|
||||
// console.log('node1',node = node.children[ch]);
|
||||
// console.log('ch2',ch = chars.shift());
|
||||
// console.log('node2',node = node.children[ch]);
|
||||
while (node && (ch = chars.shift())) {
|
||||
node = node.children[ch];
|
||||
}
|
||||
// console.log('final node',node);
|
||||
// console.log('final chars',chars);
|
||||
if (node && chars.length === 0) {
|
||||
ids = node.ids.slice(0);
|
||||
matches = matches ? getIntersection(matches, ids) : ids;
|
||||
@ -428,7 +447,6 @@
|
||||
return false;
|
||||
}
|
||||
});
|
||||
// console.log('matches',matches);
|
||||
return matches ? _.map(unique(matches), function(id) {
|
||||
return that.datums[id];
|
||||
}) : [];
|
||||
@ -462,7 +480,7 @@
|
||||
}
|
||||
function unique(array) {
|
||||
var seen = {}, uniques = [];
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
for (var i = 0, len = array.length; i < len; i++) {
|
||||
if (!seen[array[i]]) {
|
||||
seen[array[i]] = true;
|
||||
uniques.push(array[i]);
|
||||
@ -474,7 +492,8 @@
|
||||
var ai = 0, bi = 0, intersection = [];
|
||||
arrayA = arrayA.sort(compare);
|
||||
arrayB = arrayB.sort(compare);
|
||||
while (ai < arrayA.length && bi < arrayB.length) {
|
||||
var lenArrayA = arrayA.length, lenArrayB = arrayB.length;
|
||||
while (ai < lenArrayA && bi < lenArrayB) {
|
||||
if (arrayA[ai] < arrayB[bi]) {
|
||||
ai++;
|
||||
} else if (arrayA[ai] > arrayB[bi]) {
|
||||
@ -492,6 +511,7 @@
|
||||
}
|
||||
}();
|
||||
var oParser = function() {
|
||||
"use strict";
|
||||
return {
|
||||
local: getLocal,
|
||||
prefetch: getPrefetch,
|
||||
@ -525,6 +545,7 @@
|
||||
var remote, defaults;
|
||||
defaults = {
|
||||
url: null,
|
||||
cache: true,
|
||||
wildcard: "%QUERY",
|
||||
replace: null,
|
||||
rateLimitBy: "debounce",
|
||||
@ -559,6 +580,7 @@
|
||||
}
|
||||
}();
|
||||
(function(root) {
|
||||
"use strict";
|
||||
var old, keys;
|
||||
old = root.Bloodhound;
|
||||
keys = {
|
||||
@ -607,6 +629,9 @@
|
||||
},
|
||||
_getFromRemote: function getFromRemote(query, cb) {
|
||||
var that = this, url, uriEncodedQuery;
|
||||
if (!this.transport) {
|
||||
return;
|
||||
}
|
||||
query = query || "";
|
||||
uriEncodedQuery = encodeURIComponent(query);
|
||||
url = this.remote.replace ? this.remote.replace(this.remote.url, query) : this.remote.url.replace(this.remote.wildcard, uriEncodedQuery);
|
||||
@ -615,6 +640,9 @@
|
||||
err ? cb([]) : cb(that.remote.filter ? that.remote.filter(resp) : resp);
|
||||
}
|
||||
},
|
||||
_cancelLastRemoteRequest: function cancelLastRemoteRequest() {
|
||||
this.transport && this.transport.cancel();
|
||||
},
|
||||
_saveToStorage: function saveToStorage(data, thumbprint, ttl) {
|
||||
if (this.storage) {
|
||||
this.storage.set(keys.data, data, ttl);
|
||||
@ -652,9 +680,7 @@
|
||||
var that = this, matches = [], cacheHit = false;
|
||||
matches = this.index.get(query);
|
||||
matches = this.sorter(matches).slice(0, this.limit);
|
||||
if (matches.length < this.limit && this.transport) {
|
||||
cacheHit = this._getFromRemote(query, returnRemoteMatches);
|
||||
}
|
||||
matches.length < this.limit ? cacheHit = this._getFromRemote(query, returnRemoteMatches) : this._cancelLastRemoteRequest();
|
||||
if (!cacheHit) {
|
||||
(matches.length > 0 || !this.transport) && cb && cb(matches);
|
||||
}
|
||||
@ -698,13 +724,17 @@
|
||||
return false;
|
||||
}
|
||||
})(this);
|
||||
var html = {
|
||||
var html = function() {
|
||||
return {
|
||||
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>'
|
||||
};
|
||||
}();
|
||||
var css = function() {
|
||||
"use strict";
|
||||
var css = {
|
||||
wrapper: {
|
||||
position: "relative",
|
||||
@ -715,7 +745,8 @@
|
||||
top: "0",
|
||||
left: "0",
|
||||
borderColor: "transparent",
|
||||
boxShadow: "none"
|
||||
boxShadow: "none",
|
||||
opacity: "1"
|
||||
},
|
||||
input: {
|
||||
position: "relative",
|
||||
@ -762,7 +793,10 @@
|
||||
marginTop: "-1px"
|
||||
});
|
||||
}
|
||||
return css;
|
||||
}();
|
||||
var EventBus = function() {
|
||||
"use strict";
|
||||
var namespace = "typeahead:";
|
||||
function EventBus(o) {
|
||||
if (!o || !o.el) {
|
||||
@ -779,6 +813,7 @@
|
||||
return EventBus;
|
||||
}();
|
||||
var EventEmitter = function() {
|
||||
"use strict";
|
||||
var splitter = /\s+/, nextTick = getNextTick();
|
||||
return {
|
||||
onSync: onSync,
|
||||
@ -838,7 +873,7 @@
|
||||
return flush;
|
||||
function flush() {
|
||||
var cancelled;
|
||||
for (var i = 0; !cancelled && i < callbacks.length; i += 1) {
|
||||
for (var i = 0, len = callbacks.length; !cancelled && i < len; i += 1) {
|
||||
cancelled = callbacks[i].apply(context, args) === false;
|
||||
}
|
||||
return !cancelled;
|
||||
@ -868,6 +903,7 @@
|
||||
}
|
||||
}();
|
||||
var highlight = function(doc) {
|
||||
"use strict";
|
||||
var defaults = {
|
||||
node: null,
|
||||
pattern: null,
|
||||
@ -886,7 +922,7 @@
|
||||
regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly);
|
||||
traverse(o.node, hightlightTextNode);
|
||||
function hightlightTextNode(textNode) {
|
||||
var match, patternNode;
|
||||
var match, patternNode, wrapperNode;
|
||||
if (match = regex.exec(textNode.data)) {
|
||||
wrapperNode = doc.createElement(o.tagName);
|
||||
o.className && (wrapperNode.className = o.className);
|
||||
@ -911,7 +947,7 @@
|
||||
};
|
||||
function getRegex(patterns, caseSensitive, wordsOnly) {
|
||||
var escapedPatterns = [], regexStr;
|
||||
for (var i = 0; i < patterns.length; i++) {
|
||||
for (var i = 0, len = patterns.length; i < len; i++) {
|
||||
escapedPatterns.push(_.escapeRegExChars(patterns[i]));
|
||||
}
|
||||
regexStr = wordsOnly ? "\\b(" + escapedPatterns.join("|") + ")\\b" : "(" + escapedPatterns.join("|") + ")";
|
||||
@ -919,6 +955,7 @@
|
||||
}
|
||||
}(window.document);
|
||||
var Input = function() {
|
||||
"use strict";
|
||||
var specialKeyCodeMap;
|
||||
specialKeyCodeMap = {
|
||||
9: "tab",
|
||||
@ -1014,8 +1051,9 @@
|
||||
inputValue = this.getInputValue();
|
||||
areEquivalent = areQueriesEquivalent(inputValue, this.query);
|
||||
hasDifferentWhitespace = areEquivalent ? this.query.length !== inputValue.length : false;
|
||||
this.query = inputValue;
|
||||
if (!areEquivalent) {
|
||||
this.trigger("queryChanged", this.query = inputValue);
|
||||
this.trigger("queryChanged", this.query);
|
||||
} else if (hasDifferentWhitespace) {
|
||||
this.trigger("whitespaceChanged", this.query);
|
||||
}
|
||||
@ -1112,6 +1150,7 @@
|
||||
}
|
||||
}();
|
||||
var Dataset = function() {
|
||||
"use strict";
|
||||
var datasetKey = "ttDataset", valueKey = "ttValue", datumKey = "ttDatum";
|
||||
function Dataset(o) {
|
||||
o = o || {};
|
||||
@ -1165,19 +1204,13 @@
|
||||
nodes = _.map(suggestions, getSuggestionNode);
|
||||
$suggestions.append.apply($suggestions, nodes);
|
||||
that.highlight && highlight({
|
||||
className: "tt-highlight",
|
||||
node: $suggestions[0],
|
||||
pattern: query
|
||||
});
|
||||
return $suggestions;
|
||||
function getSuggestionNode(suggestion) {
|
||||
var $el;
|
||||
// console.log(that.templates.suggestion(suggestion));
|
||||
// console.log(datasetKey);
|
||||
// console.log(that.name);
|
||||
// console.log(valueKey);
|
||||
// console.log(that.displayFn(suggestion));
|
||||
// console.log(datumKey);
|
||||
// console.log(suggestion);
|
||||
$el = $(html.suggestion).append(that.templates.suggestion(suggestion)).data(datasetKey, that.name).data(valueKey, that.displayFn(suggestion)).data(datumKey, suggestion);
|
||||
$el.children().each(function() {
|
||||
$(this).css(css.suggestionChild);
|
||||
@ -1251,6 +1284,7 @@
|
||||
}
|
||||
}();
|
||||
var Dropdown = function() {
|
||||
"use strict";
|
||||
function Dropdown(o) {
|
||||
var that = this, onSuggestionClick, onSuggestionMouseEnter, onSuggestionMouseLeave;
|
||||
o = o || {};
|
||||
@ -1410,6 +1444,7 @@
|
||||
}
|
||||
}();
|
||||
var Typeahead = function() {
|
||||
"use strict";
|
||||
var attrsKey = "ttAttrs";
|
||||
function Typeahead(o) {
|
||||
var $menu, $input, $hint;
|
||||
@ -1420,7 +1455,7 @@
|
||||
this.isActivated = false;
|
||||
this.autoselect = !!o.autoselect;
|
||||
this.minLength = _.isNumber(o.minLength) ? o.minLength : 1;
|
||||
this.$node = buildDomStructure(o.input, o.withHint);
|
||||
this.$node = buildDom(o.input, o.withHint);
|
||||
$menu = this.$node.find(".tt-dropdown-menu");
|
||||
$input = this.$node.find(".tt-input");
|
||||
$hint = this.$node.find(".tt-hint");
|
||||
@ -1588,6 +1623,7 @@
|
||||
this.dropdown.close();
|
||||
},
|
||||
setVal: function setVal(val) {
|
||||
val = _.toStr(val);
|
||||
if (this.isActivated) {
|
||||
this.input.setInputValue(val);
|
||||
} else {
|
||||
@ -1607,15 +1643,16 @@
|
||||
}
|
||||
});
|
||||
return Typeahead;
|
||||
function buildDomStructure(input, withHint) {
|
||||
function buildDom(input, withHint) {
|
||||
var $input, $wrapper, $dropdown, $hint;
|
||||
$input = $(input);
|
||||
$wrapper = $(html.wrapper).css(css.wrapper);
|
||||
$dropdown = $(html.dropdown).css(css.dropdown);
|
||||
$hint = $input.clone().css(css.hint).css(getBackgroundStyles($input));
|
||||
$hint.val("").removeData().addClass("tt-hint").removeAttr("id name placeholder").prop("disabled", true).attr({
|
||||
$hint.val("").removeData().addClass("tt-hint").removeAttr("id name placeholder required").prop("readonly", true).attr({
|
||||
autocomplete: "off",
|
||||
spellcheck: "false"
|
||||
spellcheck: "false",
|
||||
tabindex: -1
|
||||
});
|
||||
$input.data(attrsKey, {
|
||||
dir: $input.attr("dir"),
|
||||
@ -1654,6 +1691,7 @@
|
||||
}
|
||||
}();
|
||||
(function() {
|
||||
"use strict";
|
||||
var old, typeaheadKey, methods;
|
||||
old = $.fn.typeahead;
|
||||
typeaheadKey = "ttTypeahead";
|
||||
@ -1726,8 +1764,12 @@
|
||||
}
|
||||
};
|
||||
$.fn.typeahead = function(method) {
|
||||
if (methods[method]) {
|
||||
return methods[method].apply(this, [].slice.call(arguments, 1));
|
||||
var tts;
|
||||
if (methods[method] && method !== "initialize") {
|
||||
tts = this.filter(function() {
|
||||
return !!$(this).data(typeaheadKey);
|
||||
});
|
||||
return methods[method].apply(tts, [].slice.call(arguments, 1));
|
||||
} else {
|
||||
return methods.initialize.apply(this, arguments);
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user