Bootstrap3使用typeahead插件实现自动补全功能


Posted in Javascript onJuly 07, 2016

很酷的一个自动补全插件

http://twitter.github.io/typeahead.js

在bootstrap中使用typeahead插件,完成自动补全

相关的文档:https://github.com/twitter/typeahead.js/blob/master/doc/jquery_typeahead.md

数据源:

Local:数组

prefectch:json

remote等方式

--------------------------------------------------------------------------------

Bootstrap3使用typeahead插件实现自动补全功能

html:

<input id="orderNo" class="typeahead" placeholder="Countries" type="text" class="form-control" name="ordersn">

js:

var states = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.whitespace,
queryTokenizer: Bloodhound.tokenizers.whitespace,
// `states` is an array of state names defined in "The Basics"
local: states
});
var findOrderByIdVague = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
prefetch: '${ctx}/admin/order/preOrderByIdVague.json',
remote: {
url: '${ctx}/admin/order/findOrderByIdVague/%QUERY.json',
wildcard: '%QUERY'
},
afterSelect: function (item) {
//选择项之后的事件 ,item是当前选中的。
alert(iterm);
}
});
$(function(){
/**
$('#addCombo .typeahead').typeahead({
hint: true,
highlight: true,
minLength: 1
},
{
name: 'states',
source: states
});
**/
$('#addCombo .typeahead').typeahead(null, {
name: 'best-pictures',
display: 'value',
source: findOrderByIdVague
});
$('#addCombo .typeahead').bind('typeahead:select', function(ev, suggestion) {
console.log('Selection: ' + suggestion.value);
});
}); 
…findOrderByIdVague/D20150502.json:
[ {
"value" : "D20150502173435141299"
}, {
"value" : "D20150502172928109304"
} ]

preOrderByIdVague.json:

[{"value":"D201"}]

docs 相关的事件: 

Custom Events
The following events get triggered on the input element during the life-cycle of a typeahead.
typeahead:active ? Fired when the typeahead moves to active state.
typeahead:idle ? Fired when the typeahead moves to idle state.
typeahead:open ? Fired when the results container is opened.
typeahead:close ? Fired when the results container is closed.
typeahead:change ? Normalized version of the native change event. Fired when input loses focus and the value has changed since it originally received focus.
typeahead:render ? Fired when suggestions are rendered for a dataset. The event handler will be invoked with 4 arguments: the jQuery event object, the suggestions that were rendered, a flag indicating whether the suggestions were fetched asynchronously, and the name of the dataset the rendering occurred in.
typeahead:select ? Fired when a suggestion is selected. The event handler will be invoked with 2 arguments: the jQuery event object and the suggestion object that was selected.
typeahead:autocomplete ? Fired when a autocompletion occurs. The event handler will be invoked with 2 arguments: the jQuery event object and the suggestion object that was used for autocompletion.
typeahead:cursorchange ? Fired when the results container cursor moves. The event handler will be invoked with 2 arguments: the jQuery event object and the suggestion object that was moved to.
typeahead:asyncrequest ? Fired when an async request for suggestions is sent. The event handler will be invoked with 3 arguments: the jQuery event object, the current query, and the name of the dataset the async request belongs to.
typeahead:asynccancel ? Fired when an async request is cancelled. The event handler will be invoked with 3 arguments: the jQuery event object, the current query, and the name of the dataset the async request belonged to.
typeahead:asyncreceive ? Fired when an async request completes. The event handler will be invoked with 3 arguments: the jQuery event object, the current query, and the name of the dataset the async request belongs to.
Example usage:
$('.typeahead').bind('typeahead:select', function(ev, suggestion) {
console.log('Selection: ' + suggestion);
});

typeahead.bundle.js:

/*!
* typeahead.js 0.11.1
* https://github.com/twitter/typeahead.js
* Copyright 2013-2015 Twitter, Inc. and other contributors; Licensed MIT
*/
(function(root, factory) {
if (typeof define === "function" && define.amd) {
define("bloodhound", [ "jquery" ], function(a0) {
return root["Bloodhound"] = factory(a0);
});
} else if (typeof exports === "object") {
module.exports = factory(require("jquery"));
} else {
root["Bloodhound"] = factory(jQuery);
}
})(this, function($) {
var _ = function() {
"use strict";
return {
isMsie: function() {
return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false;
},
isBlankString: function(str) {
return !str || /^\s*$/.test(str);
},
escapeRegExChars: function(str) {
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
},
isString: function(obj) {
return typeof obj === "string";
},
isNumber: function(obj) {
return typeof obj === "number";
},
isArray: $.isArray,
isFunction: $.isFunction,
isObject: $.isPlainObject,
isUndefined: function(obj) {
return typeof obj === "undefined";
},
isElement: function(obj) {
return !!(obj && obj.nodeType === 1);
},
isJQuery: function(obj) {
return obj instanceof $;
},
toStr: function toStr(s) {
return _.isUndefined(s) || s === null ? "" : s + "";
},
bind: $.proxy,
each: function(collection, cb) {
$.each(collection, reverseArgs);
function reverseArgs(index, value) {
return cb(value, index);
}
},
map: $.map,
filter: $.grep,
every: function(obj, test) {
var result = true;
if (!obj) {
return result;
}
$.each(obj, function(key, val) {
if (!(result = test.call(null, val, key, obj))) {
return false;
}
});
return !!result;
},
some: function(obj, test) {
var result = false;
if (!obj) {
return result;
}
$.each(obj, function(key, val) {
if (result = test.call(null, val, key, obj)) {
return false;
}
});
return !!result;
},
mixin: $.extend,
identity: function(x) {
return x;
},
clone: function(obj) {
return $.extend(true, {}, obj);
},
getIdGenerator: function() {
var counter = 0;
return function() {
return counter++;
};
},
templatify: function templatify(obj) {
return $.isFunction(obj) ? obj : template;
function template() {
return String(obj);
}
},
defer: function(fn) {
setTimeout(fn, 0);
},
debounce: function(func, wait, immediate) {
var timeout, result;
return function() {
var context = this, args = arguments, later, callNow;
later = function() {
timeout = null;
if (!immediate) {
result = func.apply(context, args);
}
};
callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) {
result = func.apply(context, args);
}
return result;
};
},
throttle: function(func, wait) {
var context, args, timeout, result, previous, later;
previous = 0;
later = function() {
previous = new Date();
timeout = null;
result = func.apply(context, args);
};
return function() {
var now = new Date(), remaining = wait - (now - previous);
context = this;
args = arguments;
if (remaining <= 0) {
clearTimeout(timeout);
timeout = null;
previous = now;
result = func.apply(context, args);
} else if (!timeout) {
timeout = setTimeout(later, remaining);
}
return result;
};
},
stringify: function(val) {
return _.isString(val) ? val : JSON.stringify(val);
},
noop: function() {}
};
}();
var VERSION = "0.11.1";
var tokenizers = function() {
"use strict";
return {
nonword: nonword,
whitespace: whitespace,
obj: {
nonword: getObjTokenizer(nonword),
whitespace: getObjTokenizer(whitespace)
}
};
function whitespace(str) {
str = _.toStr(str);
return str ? str.split(/\s+/) : [];
}
function nonword(str) {
str = _.toStr(str);
return str ? str.split(/\W+/) : [];
}
function getObjTokenizer(tokenizer) {
return function setKey(keys) {
keys = _.isArray(keys) ? keys : [].slice.call(arguments, 0);
return function tokenize(o) {
var tokens = [];
_.each(keys, function(k) {
tokens = tokens.concat(tokenizer(_.toStr(o[k])));
});
return tokens;
};
};
}
}();
var LruCache = function() {
"use strict";
function LruCache(maxSize) {
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) {
var tailItem = this.list.tail, node;
if (this.size >= this.maxSize) {
this.list.remove(tailItem);
delete this.hash[tailItem.key];
this.size--;
}
if (node = this.hash[key]) {
node.val = val;
this.list.moveToFront(node);
} else {
node = new Node(key, val);
this.list.add(node);
this.hash[key] = node;
this.size++;
}
},
get: function get(key) {
var node = this.hash[key];
if (node) {
this.list.moveToFront(node);
return node.val;
}
},
reset: function reset() {
this.size = 0;
this.hash = {};
this.list = new List();
}
});
function List() {
this.head = this.tail = null;
}
_.mixin(List.prototype, {
add: function add(node) {
if (this.head) {
node.next = this.head;
this.head.prev = node;
}
this.head = node;
this.tail = this.tail || node;
},
remove: function remove(node) {
node.prev ? node.prev.next = node.next : this.head = node.next;
node.next ? node.next.prev = node.prev : this.tail = node.prev;
},
moveToFront: function(node) {
this.remove(node);
this.add(node);
}
});
function Node(key, val) {
this.key = key;
this.val = val;
this.prev = this.next = null;
}
return LruCache;
}();
var PersistentStorage = function() {
"use strict";
var LOCAL_STORAGE;
try {
LOCAL_STORAGE = window.localStorage;
LOCAL_STORAGE.setItem("~~~", "!");
LOCAL_STORAGE.removeItem("~~~");
} catch (err) {
LOCAL_STORAGE = null;
}
function PersistentStorage(namespace, override) {
this.prefix = [ "__", namespace, "__" ].join("");
this.ttlKey = "__ttl__";
this.keyMatcher = new RegExp("^" + _.escapeRegExChars(this.prefix));
this.ls = override || LOCAL_STORAGE;
!this.ls && this._noop();
}
_.mixin(PersistentStorage.prototype, {
_prefix: function(key) {
return this.prefix + key;
},
_ttlKey: function(key) {
return this._prefix(key) + this.ttlKey;
},
_noop: function() {
this.get = this.set = this.remove = this.clear = this.isExpired = _.noop;
},
_safeSet: function(key, val) {
try {
this.ls.setItem(key, val);
} catch (err) {
if (err.name === "QuotaExceededError") {
this.clear();
this._noop();
}
}
},
get: function(key) {
if (this.isExpired(key)) {
this.remove(key);
}
return decode(this.ls.getItem(this._prefix(key)));
},
set: function(key, val, ttl) {
if (_.isNumber(ttl)) {
this._safeSet(this._ttlKey(key), encode(now() + ttl));
} else {
this.ls.removeItem(this._ttlKey(key));
}
return this._safeSet(this._prefix(key), encode(val));
},
remove: function(key) {
this.ls.removeItem(this._ttlKey(key));
this.ls.removeItem(this._prefix(key));
return this;
},
clear: function() {
var i, keys = gatherMatchingKeys(this.keyMatcher);
for (i = keys.length; i--; ) {
this.remove(keys[i]);
}
return this;
},
isExpired: function(key) {
var ttl = decode(this.ls.getItem(this._ttlKey(key)));
return _.isNumber(ttl) && now() > ttl ? true : false;
}
});
return PersistentStorage;
function now() {
return new Date().getTime();
}
function encode(val) {
return JSON.stringify(_.isUndefined(val) ? null : val);
}
function decode(val) {
return $.parseJSON(val);
}
function gatherMatchingKeys(keyMatcher) {
var i, key, keys = [], len = LOCAL_STORAGE.length;
for (i = 0; i < len; i++) {
if ((key = LOCAL_STORAGE.key(i)).match(keyMatcher)) {
keys.push(key.replace(keyMatcher, ""));
}
}
return keys;
}
}();
var Transport = function() {
"use strict";
var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests = 6, sharedCache = new LruCache(10);
function Transport(o) {
o = o || {};
this.cancelled = false;
this.lastReq = null;
this._send = o.transport;
this._get = o.limiter ? o.limiter(this._get) : this._get;
this._cache = o.cache === false ? new LruCache(0) : sharedCache;
}
Transport.setMaxPendingRequests = function setMaxPendingRequests(num) {
maxPendingRequests = num;
};
Transport.resetCache = function resetCache() {
sharedCache.reset();
};
_.mixin(Transport.prototype, {
_fingerprint: function fingerprint(o) {
o = o || {};
return o.url + o.type + $.param(o.data || {});
},
_get: function(o, cb) {
var that = this, fingerprint, jqXhr;
fingerprint = this._fingerprint(o);
if (this.cancelled || fingerprint !== this.lastReq) {
return;
}
if (jqXhr = pendingRequests[fingerprint]) {
jqXhr.done(done).fail(fail);
} else if (pendingRequestsCount < maxPendingRequests) {
pendingRequestsCount++;
pendingRequests[fingerprint] = this._send(o).done(done).fail(fail).always(always);
} else {
this.onDeckRequestArgs = [].slice.call(arguments, 0);
}
function done(resp) {
cb(null, resp);
that._cache.set(fingerprint, resp);
}
function fail() {
cb(true);
}
function always() {
pendingRequestsCount--;
delete pendingRequests[fingerprint];
if (that.onDeckRequestArgs) {
that._get.apply(that, that.onDeckRequestArgs);
that.onDeckRequestArgs = null;
}
}
},
get: function(o, cb) {
var resp, fingerprint;
cb = cb || $.noop;
o = _.isString(o) ? {
url: o
} : o || {};
fingerprint = this._fingerprint(o);
this.cancelled = false;
this.lastReq = fingerprint;
if (resp = this._cache.get(fingerprint)) {
cb(null, resp);
} else {
this._get(o, cb);
}
},
cancel: function() {
this.cancelled = true;
}
});
return Transport;
}();
var SearchIndex = window.SearchIndex = function() {
"use strict";
var CHILDREN = "c", IDS = "i";
function SearchIndex(o) {
o = o || {};
if (!o.datumTokenizer || !o.queryTokenizer) {
$.error("datumTokenizer and queryTokenizer are both required");
}
this.identify = o.identify || _.stringify;
this.datumTokenizer = o.datumTokenizer;
this.queryTokenizer = o.queryTokenizer;
this.reset();
}
_.mixin(SearchIndex.prototype, {
bootstrap: function bootstrap(o) {
this.datums = o.datums;
this.trie = o.trie;
},
add: function(data) {
var that = this;
data = _.isArray(data) ? data : [ data ];
_.each(data, function(datum) {
var id, tokens;
that.datums[id = that.identify(datum)] = datum;
tokens = normalizeTokens(that.datumTokenizer(datum));
_.each(tokens, function(token) {
var node, chars, ch;
node = that.trie;
chars = token.split("");
while (ch = chars.shift()) {
node = node[CHILDREN][ch] || (node[CHILDREN][ch] = newNode());
node[IDS].push(id);
}
});
});
},
get: function get(ids) {
var that = this;
return _.map(ids, function(id) {
return that.datums[id];
});
},
search: function search(query) {
var that = this, tokens, matches;
tokens = normalizeTokens(this.queryTokenizer(query));
_.each(tokens, function(token) {
var node, chars, ch, ids;
if (matches && matches.length === 0) {
return false;
}
node = that.trie;
chars = token.split("");
while (node && (ch = chars.shift())) {
node = node[CHILDREN][ch];
}
if (node && chars.length === 0) {
ids = node[IDS].slice(0);
matches = matches ? getIntersection(matches, ids) : ids;
} else {
matches = [];
return false;
}
});
return matches ? _.map(unique(matches), function(id) {
return that.datums[id];
}) : [];
},
all: function all() {
var values = [];
for (var key in this.datums) {
values.push(this.datums[key]);
}
return values;
},
reset: function reset() {
this.datums = {};
this.trie = newNode();
},
serialize: function serialize() {
return {
datums: this.datums,
trie: this.trie
};
}
});
return SearchIndex;
function normalizeTokens(tokens) {
tokens = _.filter(tokens, function(token) {
return !!token;
});
tokens = _.map(tokens, function(token) {
return token.toLowerCase();
});
return tokens;
}
function newNode() {
var node = {};
node[IDS] = [];
node[CHILDREN] = {};
return node;
}
function unique(array) {
var seen = {}, uniques = [];
for (var i = 0, len = array.length; i < len; i++) {
if (!seen[array[i]]) {
seen[array[i]] = true;
uniques.push(array[i]);
}
}
return uniques;
}
function getIntersection(arrayA, arrayB) {
var ai = 0, bi = 0, intersection = [];
arrayA = arrayA.sort();
arrayB = arrayB.sort();
var lenArrayA = arrayA.length, lenArrayB = arrayB.length;
while (ai < lenArrayA && bi < lenArrayB) {
if (arrayA[ai] < arrayB[bi]) {
ai++;
} else if (arrayA[ai] > arrayB[bi]) {
bi++;
} else {
intersection.push(arrayA[ai]);
ai++;
bi++;
}
}
return intersection;
}
}();
var Prefetch = function() {
"use strict";
var keys;
keys = {
data: "data",
protocol: "protocol",
thumbprint: "thumbprint"
};
function Prefetch(o) {
this.url = o.url;
this.ttl = o.ttl;
this.cache = o.cache;
this.prepare = o.prepare;
this.transform = o.transform;
this.transport = o.transport;
this.thumbprint = o.thumbprint;
this.storage = new PersistentStorage(o.cacheKey);
}
_.mixin(Prefetch.prototype, {
_settings: function settings() {
return {
url: this.url,
type: "GET",
dataType: "json"
};
},
store: function store(data) {
if (!this.cache) {
return;
}
this.storage.set(keys.data, data, this.ttl);
this.storage.set(keys.protocol, location.protocol, this.ttl);
this.storage.set(keys.thumbprint, this.thumbprint, this.ttl);
},
fromCache: function fromCache() {
var stored = {}, isExpired;
if (!this.cache) {
return null;
}
stored.data = this.storage.get(keys.data);
stored.protocol = this.storage.get(keys.protocol);
stored.thumbprint = this.storage.get(keys.thumbprint);
isExpired = stored.thumbprint !== this.thumbprint || stored.protocol !== location.protocol;
return stored.data && !isExpired ? stored.data : null;
},
fromNetwork: function(cb) {
var that = this, settings;
if (!cb) {
return;
}
settings = this.prepare(this._settings());
this.transport(settings).fail(onError).done(onResponse);
function onError() {
cb(true);
}
function onResponse(resp) {
cb(null, that.transform(resp));
}
},
clear: function clear() {
this.storage.clear();
return this;
}
});
return Prefetch;
}();
var Remote = function() {
"use strict";
function Remote(o) {
this.url = o.url;
this.prepare = o.prepare;
this.transform = o.transform;
this.transport = new Transport({
cache: o.cache,
limiter: o.limiter,
transport: o.transport
});
}
_.mixin(Remote.prototype, {
_settings: function settings() {
return {
url: this.url,
type: "GET",
dataType: "json"
};
},
get: function get(query, cb) {
var that = this, settings;
if (!cb) {
return;
}
query = query || "";
settings = this.prepare(query, this._settings());
return this.transport.get(settings, onResponse);
function onResponse(err, resp) {
err ? cb([]) : cb(that.transform(resp));
}
},
cancelLastRequest: function cancelLastRequest() {
this.transport.cancel();
}
});
return Remote;
}();
var oParser = function() {
"use strict";
return function parse(o) {
var defaults, sorter;
defaults = {
initialize: true,
identify: _.stringify,
datumTokenizer: null,
queryTokenizer: null,
sufficient: 5,
sorter: null,
local: [],
prefetch: null,
remote: null
};
o = _.mixin(defaults, o || {});
!o.datumTokenizer && $.error("datumTokenizer is required");
!o.queryTokenizer && $.error("queryTokenizer is required");
sorter = o.sorter;
o.sorter = sorter ? function(x) {
return x.sort(sorter);
} : _.identity;
o.local = _.isFunction(o.local) ? o.local() : o.local;
o.prefetch = parsePrefetch(o.prefetch);
o.remote = parseRemote(o.remote);
return o;
};
function parsePrefetch(o) {
var defaults;
if (!o) {
return null;
}
defaults = {
url: null,
ttl: 24 * 60 * 60 * 1e3,
cache: true,
cacheKey: null,
thumbprint: "",
prepare: _.identity,
transform: _.identity,
transport: null
};
o = _.isString(o) ? {
url: o
} : o;
o = _.mixin(defaults, o);
!o.url && $.error("prefetch requires url to be set");
o.transform = o.filter || o.transform;
o.cacheKey = o.cacheKey || o.url;
o.thumbprint = VERSION + o.thumbprint;
o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax;
return o;
}
function parseRemote(o) {
var defaults;
if (!o) {
return;
}
defaults = {
url: null,
cache: true,
prepare: null,
replace: null,
wildcard: null,
limiter: null,
rateLimitBy: "debounce",
rateLimitWait: 300,
transform: _.identity,
transport: null
};
o = _.isString(o) ? {
url: o
} : o;
o = _.mixin(defaults, o);
!o.url && $.error("remote requires url to be set");
o.transform = o.filter || o.transform;
o.prepare = toRemotePrepare(o);
o.limiter = toLimiter(o);
o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax;
delete o.replace;
delete o.wildcard;
delete o.rateLimitBy;
delete o.rateLimitWait;
return o;
}
function toRemotePrepare(o) {
var prepare, replace, wildcard;
prepare = o.prepare;
replace = o.replace;
wildcard = o.wildcard;
if (prepare) {
return prepare;
}
if (replace) {
prepare = prepareByReplace;
} else if (o.wildcard) {
prepare = prepareByWildcard;
} else {
prepare = idenityPrepare;
}
return prepare;
function prepareByReplace(query, settings) {
settings.url = replace(settings.url, query);
return settings;
}
function prepareByWildcard(query, settings) {
settings.url = settings.url.replace(wildcard, encodeURIComponent(query));
return settings;
}
function idenityPrepare(query, settings) {
return settings;
}
}
function toLimiter(o) {
var limiter, method, wait;
limiter = o.limiter;
method = o.rateLimitBy;
wait = o.rateLimitWait;
if (!limiter) {
limiter = /^throttle$/i.test(method) ? throttle(wait) : debounce(wait);
}
return limiter;
function debounce(wait) {
return function debounce(fn) {
return _.debounce(fn, wait);
};
}
function throttle(wait) {
return function throttle(fn) {
return _.throttle(fn, wait);
};
}
}
function callbackToDeferred(fn) {
return function wrapper(o) {
var deferred = $.Deferred();
fn(o, onSuccess, onError);
return deferred;
function onSuccess(resp) {
_.defer(function() {
deferred.resolve(resp);
});
}
function onError(err) {
_.defer(function() {
deferred.reject(err);
});
}
};
}
}();
var Bloodhound = function() {
"use strict";
var old;
old = window && window.Bloodhound;
function Bloodhound(o) {
o = oParser(o);
this.sorter = o.sorter;
this.identify = o.identify;
this.sufficient = o.sufficient;
this.local = o.local;
this.remote = o.remote ? new Remote(o.remote) : null;
this.prefetch = o.prefetch ? new Prefetch(o.prefetch) : null;
this.index = new SearchIndex({
identify: this.identify,
datumTokenizer: o.datumTokenizer,
queryTokenizer: o.queryTokenizer
});
o.initialize !== false && this.initialize();
}
Bloodhound.noConflict = function noConflict() {
window && (window.Bloodhound = old);
return Bloodhound;
};
Bloodhound.tokenizers = tokenizers;
_.mixin(Bloodhound.prototype, {
__ttAdapter: function ttAdapter() {
var that = this;
return this.remote ? withAsync : withoutAsync;
function withAsync(query, sync, async) {
return that.search(query, sync, async);
}
function withoutAsync(query, sync) {
return that.search(query, sync);
}
},
_loadPrefetch: function loadPrefetch() {
var that = this, deferred, serialized;
deferred = $.Deferred();
if (!this.prefetch) {
deferred.resolve();
} else if (serialized = this.prefetch.fromCache()) {
this.index.bootstrap(serialized);
deferred.resolve();
} else {
this.prefetch.fromNetwork(done);
}
return deferred.promise();
function done(err, data) {
if (err) {
return deferred.reject();
}
that.add(data);
that.prefetch.store(that.index.serialize());
deferred.resolve();
}
},
_initialize: function initialize() {
var that = this, deferred;
this.clear();
(this.initPromise = this._loadPrefetch()).done(addLocalToIndex);
return this.initPromise;
function addLocalToIndex() {
that.add(that.local);
}
},
initialize: function initialize(force) {
return !this.initPromise || force ? this._initialize() : this.initPromise;
},
add: function add(data) {
this.index.add(data);
return this;
},
get: function get(ids) {
ids = _.isArray(ids) ? ids : [].slice.call(arguments);
return this.index.get(ids);
},
search: function search(query, sync, async) {
var that = this, local;
local = this.sorter(this.index.search(query));
sync(this.remote ? local.slice() : local);
if (this.remote && local.length < this.sufficient) {
this.remote.get(query, processRemote);
} else if (this.remote) {
this.remote.cancelLastRequest();
}
return this;
function processRemote(remote) {
var nonDuplicates = [];
_.each(remote, function(r) {
!_.some(local, function(l) {
return that.identify(r) === that.identify(l);
}) && nonDuplicates.push(r);
});
async && async(nonDuplicates);
}
},
all: function all() {
return this.index.all();
},
clear: function clear() {
this.index.reset();
return this;
},
clearPrefetchCache: function clearPrefetchCache() {
this.prefetch && this.prefetch.clear();
return this;
},
clearRemoteCache: function clearRemoteCache() {
Transport.resetCache();
return this;
},
ttAdapter: function ttAdapter() {
return this.__ttAdapter();
}
});
return Bloodhound;
}();
return Bloodhound;
});
(function(root, factory) {
if (typeof define === "function" && define.amd) {
define("typeahead.js", [ "jquery" ], function(a0) {
return factory(a0);
});
} else if (typeof exports === "object") {
module.exports = factory(require("jquery"));
} else {
factory(jQuery);
}
})(this, function($) {
var _ = function() {
"use strict";
return {
isMsie: function() {
return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false;
},
isBlankString: function(str) {
return !str || /^\s*$/.test(str);
},
escapeRegExChars: function(str) {
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
},
isString: function(obj) {
return typeof obj === "string";
},
isNumber: function(obj) {
return typeof obj === "number";
},
isArray: $.isArray,
isFunction: $.isFunction,
isObject: $.isPlainObject,
isUndefined: function(obj) {
return typeof obj === "undefined";
},
isElement: function(obj) {
return !!(obj && obj.nodeType === 1);
},
isJQuery: function(obj) {
return obj instanceof $;
},
toStr: function toStr(s) {
return _.isUndefined(s) || s === null ? "" : s + "";
},
bind: $.proxy,
each: function(collection, cb) {
$.each(collection, reverseArgs);
function reverseArgs(index, value) {
return cb(value, index);
}
},
map: $.map,
filter: $.grep,
every: function(obj, test) {
var result = true;
if (!obj) {
return result;
}
$.each(obj, function(key, val) {
if (!(result = test.call(null, val, key, obj))) {
return false;
}
});
return !!result;
},
some: function(obj, test) {
var result = false;
if (!obj) {
return result;
}
$.each(obj, function(key, val) {
if (result = test.call(null, val, key, obj)) {
return false;
}
});
return !!result;
},
mixin: $.extend,
identity: function(x) {
return x;
},
clone: function(obj) {
return $.extend(true, {}, obj);
},
getIdGenerator: function() {
var counter = 0;
return function() {
return counter++;
};
},
templatify: function templatify(obj) {
return $.isFunction(obj) ? obj : template;
function template() {
return String(obj);
}
},
defer: function(fn) {
setTimeout(fn, 0);
},
debounce: function(func, wait, immediate) {
var timeout, result;
return function() {
var context = this, args = arguments, later, callNow;
later = function() {
timeout = null;
if (!immediate) {
result = func.apply(context, args);
}
};
callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) {
result = func.apply(context, args);
}
return result;
};
},
throttle: function(func, wait) {
var context, args, timeout, result, previous, later;
previous = 0;
later = function() {
previous = new Date();
timeout = null;
result = func.apply(context, args);
};
return function() {
var now = new Date(), remaining = wait - (now - previous);
context = this;
args = arguments;
if (remaining <= 0) {
clearTimeout(timeout);
timeout = null;
previous = now;
result = func.apply(context, args);
} else if (!timeout) {
timeout = setTimeout(later, remaining);
}
return result;
};
},
stringify: function(val) {
return _.isString(val) ? val : JSON.stringify(val);
},
noop: function() {}
};
}();
var WWW = function() {
"use strict";
var defaultClassNames = {
wrapper: "twitter-typeahead",
input: "tt-input",
hint: "tt-hint",
menu: "tt-menu",
dataset: "tt-dataset",
suggestion: "tt-suggestion",
selectable: "tt-selectable",
empty: "tt-empty",
open: "tt-open",
cursor: "tt-cursor",
highlight: "tt-highlight"
};
return build;
function build(o) {
var www, classes;
classes = _.mixin({}, defaultClassNames, o);
www = {
css: buildCss(),
classes: classes,
html: buildHtml(classes),
selectors: buildSelectors(classes)
};
return {
css: www.css,
html: www.html,
classes: www.classes,
selectors: www.selectors,
mixin: function(o) {
_.mixin(o, www);
}
};
}
function buildHtml(c) {
return {
wrapper: '<span class="' + c.wrapper + '"></span>',
menu: '<div class="' + c.menu + '"></div>'
};
}
function buildSelectors(classes) {
var selectors = {};
_.each(classes, function(v, k) {
selectors[k] = "." + v;
});
return selectors;
}
function buildCss() {
var css = {
wrapper: {
position: "relative",
display: "inline-block"
},
hint: {
position: "absolute",
top: "0",
left: "0",
borderColor: "transparent",
boxShadow: "none",
opacity: "1"
},
input: {
position: "relative",
verticalAlign: "top",
backgroundColor: "transparent"
},
inputWithNoHint: {
position: "relative",
verticalAlign: "top"
},
menu: {
position: "absolute",
top: "100%",
left: "0",
zIndex: "100",
display: "none"
},
ltr: {
left: "0",
right: "auto"
},
rtl: {
left: "auto",
right: " 0"
}
};
if (_.isMsie()) {
_.mixin(css.input, {
backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"
});
}
return css;
}
}();
var EventBus = function() {
"use strict";
var namespace, deprecationMap;
namespace = "typeahead:";
deprecationMap = {
render: "rendered",
cursorchange: "cursorchanged",
select: "selected",
autocomplete: "autocompleted"
};
function EventBus(o) {
if (!o || !o.el) {
$.error("EventBus initialized without el");
}
this.$el = $(o.el);
}
_.mixin(EventBus.prototype, {
_trigger: function(type, args) {
var $e;
$e = $.Event(namespace + type);
(args = args || []).unshift($e);
this.$el.trigger.apply(this.$el, args);
return $e;
},
before: function(type) {
var args, $e;
args = [].slice.call(arguments, 1);
$e = this._trigger("before" + type, args);
return $e.isDefaultPrevented();
},
trigger: function(type) {
var deprecatedType;
this._trigger(type, [].slice.call(arguments, 1));
if (deprecatedType = deprecationMap[type]) {
this._trigger(deprecatedType, [].slice.call(arguments, 1));
}
}
});
return EventBus;
}();
var EventEmitter = function() {
"use strict";
var splitter = /\s+/, nextTick = getNextTick();
return {
onSync: onSync,
onAsync: onAsync,
off: off,
trigger: trigger
};
function on(method, types, cb, context) {
var type;
if (!cb) {
return this;
}
types = types.split(splitter);
cb = context ? bindContext(cb, context) : cb;
this._callbacks = this._callbacks || {};
while (type = types.shift()) {
this._callbacks[type] = this._callbacks[type] || {
sync: [],
async: []
};
this._callbacks[type][method].push(cb);
}
return this;
}
function onAsync(types, cb, context) {
return on.call(this, "async", types, cb, context);
}
function onSync(types, cb, context) {
return on.call(this, "sync", types, cb, context);
}
function off(types) {
var type;
if (!this._callbacks) {
return this;
}
types = types.split(splitter);
while (type = types.shift()) {
delete this._callbacks[type];
}
return this;
}
function trigger(types) {
var type, callbacks, args, syncFlush, asyncFlush;
if (!this._callbacks) {
return this;
}
types = types.split(splitter);
args = [].slice.call(arguments, 1);
while ((type = types.shift()) && (callbacks = this._callbacks[type])) {
syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args));
asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args));
syncFlush() && nextTick(asyncFlush);
}
return this;
}
function getFlush(callbacks, context, args) {
return flush;
function flush() {
var cancelled;
for (var i = 0, len = callbacks.length; !cancelled && i < len; i += 1) {
cancelled = callbacks[i].apply(context, args) === false;
}
return !cancelled;
}
}
function getNextTick() {
var nextTickFn;
if (window.setImmediate) {
nextTickFn = function nextTickSetImmediate(fn) {
setImmediate(function() {
fn();
});
};
} else {
nextTickFn = function nextTickSetTimeout(fn) {
setTimeout(function() {
fn();
}, 0);
};
}
return nextTickFn;
}
function bindContext(fn, context) {
return fn.bind ? fn.bind(context) : function() {
fn.apply(context, [].slice.call(arguments, 0));
};
}
}();
var highlight = function(doc) {
"use strict";
var defaults = {
node: null,
pattern: null,
tagName: "strong",
className: null,
wordsOnly: false,
caseSensitive: false
};
return function hightlight(o) {
var regex;
o = _.mixin({}, defaults, o);
if (!o.node || !o.pattern) {
return;
}
o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ];
regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly);
traverse(o.node, hightlightTextNode);
function hightlightTextNode(textNode) {
var match, patternNode, wrapperNode;
if (match = regex.exec(textNode.data)) {
wrapperNode = doc.createElement(o.tagName);
o.className && (wrapperNode.className = o.className);
patternNode = textNode.splitText(match.index);
patternNode.splitText(match[0].length);
wrapperNode.appendChild(patternNode.cloneNode(true));
textNode.parentNode.replaceChild(wrapperNode, patternNode);
}
return !!match;
}
function traverse(el, hightlightTextNode) {
var childNode, TEXT_NODE_TYPE = 3;
for (var i = 0; i < el.childNodes.length; i++) {
childNode = el.childNodes[i];
if (childNode.nodeType === TEXT_NODE_TYPE) {
i += hightlightTextNode(childNode) ? 1 : 0;
} else {
traverse(childNode, hightlightTextNode);
}
}
}
};
function getRegex(patterns, caseSensitive, wordsOnly) {
var escapedPatterns = [], regexStr;
for (var i = 0, len = patterns.length; i < len; i++) {
escapedPatterns.push(_.escapeRegExChars(patterns[i]));
}
regexStr = wordsOnly ? "\\b(" + escapedPatterns.join("|") + ")\\b" : "(" + escapedPatterns.join("|") + ")";
return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, "i");
}
}(window.document);
var Input = function() {
"use strict";
var specialKeyCodeMap;
specialKeyCodeMap = {
9: "tab",
27: "esc",
37: "left",
39: "right",
13: "enter",
38: "up",
40: "down"
};
function Input(o, www) {
o = o || {};
if (!o.input) {
$.error("input is missing");
}
www.mixin(this);
this.$hint = $(o.hint);
this.$input = $(o.input);
this.query = this.$input.val();
this.queryWhenFocused = this.hasFocus() ? this.query : null;
this.$overflowHelper = buildOverflowHelper(this.$input);
this._checkLanguageDirection();
if (this.$hint.length === 0) {
this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop;
}
}
Input.normalizeQuery = function(str) {
return _.toStr(str).replace(/^\s*/g, "").replace(/\s{2,}/g, " ");
};
_.mixin(Input.prototype, EventEmitter, {
_onBlur: function onBlur() {
this.resetInputValue();
this.trigger("blurred");
},
_onFocus: function onFocus() {
this.queryWhenFocused = this.query;
this.trigger("focused");
},
_onKeydown: function onKeydown($e) {
var keyName = specialKeyCodeMap[$e.which || $e.keyCode];
this._managePreventDefault(keyName, $e);
if (keyName && this._shouldTrigger(keyName, $e)) {
this.trigger(keyName + "Keyed", $e);
}
},
_onInput: function onInput() {
this._setQuery(this.getInputValue());
this.clearHintIfInvalid();
this._checkLanguageDirection();
},
_managePreventDefault: function managePreventDefault(keyName, $e) {
var preventDefault;
switch (keyName) {
case "up":
case "down":
preventDefault = !withModifier($e);
break;
default:
preventDefault = false;
}
preventDefault && $e.preventDefault();
},
_shouldTrigger: function shouldTrigger(keyName, $e) {
var trigger;
switch (keyName) {
case "tab":
trigger = !withModifier($e);
break;
default:
trigger = true;
}
return trigger;
},
_checkLanguageDirection: function checkLanguageDirection() {
var dir = (this.$input.css("direction") || "ltr").toLowerCase();
if (this.dir !== dir) {
this.dir = dir;
this.$hint.attr("dir", dir);
this.trigger("langDirChanged", dir);
}
},
_setQuery: function setQuery(val, silent) {
var areEquivalent, hasDifferentWhitespace;
areEquivalent = areQueriesEquivalent(val, this.query);
hasDifferentWhitespace = areEquivalent ? this.query.length !== val.length : false;
this.query = val;
if (!silent && !areEquivalent) {
this.trigger("queryChanged", this.query);
} else if (!silent && hasDifferentWhitespace) {
this.trigger("whitespaceChanged", this.query);
}
},
bind: function() {
var that = this, onBlur, onFocus, onKeydown, onInput;
onBlur = _.bind(this._onBlur, this);
onFocus = _.bind(this._onFocus, this);
onKeydown = _.bind(this._onKeydown, this);
onInput = _.bind(this._onInput, this);
this.$input.on("blur.tt", onBlur).on("focus.tt", onFocus).on("keydown.tt", onKeydown);
if (!_.isMsie() || _.isMsie() > 9) {
this.$input.on("input.tt", onInput);
} else {
this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function($e) {
if (specialKeyCodeMap[$e.which || $e.keyCode]) {
return;
}
_.defer(_.bind(that._onInput, that, $e));
});
}
return this;
},
focus: function focus() {
this.$input.focus();
},
blur: function blur() {
this.$input.blur();
},
getLangDir: function getLangDir() {
return this.dir;
},
getQuery: function getQuery() {
return this.query || "";
},
setQuery: function setQuery(val, silent) {
this.setInputValue(val);
this._setQuery(val, silent);
},
hasQueryChangedSinceLastFocus: function hasQueryChangedSinceLastFocus() {
return this.query !== this.queryWhenFocused;
},
getInputValue: function getInputValue() {
return this.$input.val();
},
setInputValue: function setInputValue(value) {
this.$input.val(value);
this.clearHintIfInvalid();
this._checkLanguageDirection();
},
resetInputValue: function resetInputValue() {
this.setInputValue(this.query);
},
getHint: function getHint() {
return this.$hint.val();
},
setHint: function setHint(value) {
this.$hint.val(value);
},
clearHint: function clearHint() {
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();
},
hasFocus: function hasFocus() {
return this.$input.is(":focus");
},
hasOverflow: function hasOverflow() {
var constraint = this.$input.width() - 2;
this.$overflowHelper.text(this.getInputValue());
return this.$overflowHelper.width() >= constraint;
},
isCursorAtEnd: function() {
var valueLength, selectionStart, range;
valueLength = this.$input.val().length;
selectionStart = this.$input[0].selectionStart;
if (_.isNumber(selectionStart)) {
return selectionStart === valueLength;
} else if (document.selection) {
range = document.selection.createRange();
range.moveStart("character", -valueLength);
return valueLength === range.text.length;
}
return true;
},
destroy: function destroy() {
this.$hint.off(".tt");
this.$input.off(".tt");
this.$overflowHelper.remove();
this.$hint = this.$input = this.$overflowHelper = $("<div>");
}
});
return Input;
function buildOverflowHelper($input) {
return $('<pre aria-hidden="true"></pre>').css({
position: "absolute",
visibility: "hidden",
whiteSpace: "pre",
fontFamily: $input.css("font-family"),
fontSize: $input.css("font-size"),
fontStyle: $input.css("font-style"),
fontVariant: $input.css("font-variant"),
fontWeight: $input.css("font-weight"),
wordSpacing: $input.css("word-spacing"),
letterSpacing: $input.css("letter-spacing"),
textIndent: $input.css("text-indent"),
textRendering: $input.css("text-rendering"),
textTransform: $input.css("text-transform")
}).insertAfter($input);
}
function areQueriesEquivalent(a, b) {
return Input.normalizeQuery(a) === Input.normalizeQuery(b);
}
function withModifier($e) {
return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey;
}
}();
var Dataset = function() {
"use strict";
var keys, nameGenerator;
keys = {
val: "tt-selectable-display",
obj: "tt-selectable-object"
};
nameGenerator = _.getIdGenerator();
function Dataset(o, www) {
o = o || {};
o.templates = o.templates || {};
o.templates.notFound = o.templates.notFound || o.templates.empty;
if (!o.source) {
$.error("missing source");
}
if (!o.node) {
$.error("missing node");
}
if (o.name && !isValidName(o.name)) {
$.error("invalid dataset name: " + o.name);
}
www.mixin(this);
this.highlight = !!o.highlight;
this.name = o.name || nameGenerator();
this.limit = o.limit || 5;
this.displayFn = getDisplayFn(o.display || o.displayKey);
this.templates = getTemplates(o.templates, this.displayFn);
this.source = o.source.__ttAdapter ? o.source.__ttAdapter() : o.source;
this.async = _.isUndefined(o.async) ? this.source.length > 2 : !!o.async;
this._resetLastSuggestion();
this.$el = $(o.node).addClass(this.classes.dataset).addClass(this.classes.dataset + "-" + this.name);
}
Dataset.extractData = function extractData(el) {
var $el = $(el);
if ($el.data(keys.obj)) {
return {
val: $el.data(keys.val) || "",
obj: $el.data(keys.obj) || null
};
}
return null;
};
_.mixin(Dataset.prototype, EventEmitter, {
_overwrite: function overwrite(query, suggestions) {
suggestions = suggestions || [];
if (suggestions.length) {
this._renderSuggestions(query, suggestions);
} else if (this.async && this.templates.pending) {
this._renderPending(query);
} else if (!this.async && this.templates.notFound) {
this._renderNotFound(query);
} else {
this._empty();
}
this.trigger("rendered", this.name, suggestions, false);
},
_append: function append(query, suggestions) {
suggestions = suggestions || [];
if (suggestions.length && this.$lastSuggestion.length) {
this._appendSuggestions(query, suggestions);
} else if (suggestions.length) {
this._renderSuggestions(query, suggestions);
} else if (!this.$lastSuggestion.length && this.templates.notFound) {
this._renderNotFound(query);
}
this.trigger("rendered", this.name, suggestions, true);
},
_renderSuggestions: function renderSuggestions(query, suggestions) {
var $fragment;
$fragment = this._getSuggestionsFragment(query, suggestions);
this.$lastSuggestion = $fragment.children().last();
this.$el.html($fragment).prepend(this._getHeader(query, suggestions)).append(this._getFooter(query, suggestions));
},
_appendSuggestions: function appendSuggestions(query, suggestions) {
var $fragment, $lastSuggestion;
$fragment = this._getSuggestionsFragment(query, suggestions);
$lastSuggestion = $fragment.children().last();
this.$lastSuggestion.after($fragment);
this.$lastSuggestion = $lastSuggestion;
},
_renderPending: function renderPending(query) {
var template = this.templates.pending;
this._resetLastSuggestion();
template && this.$el.html(template({
query: query,
dataset: this.name
}));
},
_renderNotFound: function renderNotFound(query) {
var template = this.templates.notFound;
this._resetLastSuggestion();
template && this.$el.html(template({
query: query,
dataset: this.name
}));
},
_empty: function empty() {
this.$el.empty();
this._resetLastSuggestion();
},
_getSuggestionsFragment: function getSuggestionsFragment(query, suggestions) {
var that = this, fragment;
fragment = document.createDocumentFragment();
_.each(suggestions, function getSuggestionNode(suggestion) {
var $el, context;
context = that._injectQuery(query, suggestion);
$el = $(that.templates.suggestion(context)).data(keys.obj, suggestion).data(keys.val, that.displayFn(suggestion)).addClass(that.classes.suggestion + " " + that.classes.selectable);
fragment.appendChild($el[0]);
});
this.highlight && highlight({
className: this.classes.highlight,
node: fragment,
pattern: query
});
return $(fragment);
},
_getFooter: function getFooter(query, suggestions) {
return this.templates.footer ? this.templates.footer({
query: query,
suggestions: suggestions,
dataset: this.name
}) : null;
},
_getHeader: function getHeader(query, suggestions) {
return this.templates.header ? this.templates.header({
query: query,
suggestions: suggestions,
dataset: this.name
}) : null;
},
_resetLastSuggestion: function resetLastSuggestion() {
this.$lastSuggestion = $();
},
_injectQuery: function injectQuery(query, obj) {
return _.isObject(obj) ? _.mixin({
_query: query
}, obj) : obj;
},
update: function update(query) {
var that = this, canceled = false, syncCalled = false, rendered = 0;
this.cancel();
this.cancel = function cancel() {
canceled = true;
that.cancel = $.noop;
that.async && that.trigger("asyncCanceled", query);
};
this.source(query, sync, async);
!syncCalled && sync([]);
function sync(suggestions) {
if (syncCalled) {
return;
}
syncCalled = true;
suggestions = (suggestions || []).slice(0, that.limit);
rendered = suggestions.length;
that._overwrite(query, suggestions);
if (rendered < that.limit && that.async) {
that.trigger("asyncRequested", query);
}
}
function async(suggestions) {
suggestions = suggestions || [];
if (!canceled && rendered < that.limit) {
that.cancel = $.noop;
rendered += suggestions.length;
that._append(query, suggestions.slice(0, that.limit - rendered));
that.async && that.trigger("asyncReceived", query);
}
}
},
cancel: $.noop,
clear: function clear() {
this._empty();
this.cancel();
this.trigger("cleared");
},
isEmpty: function isEmpty() {
return this.$el.is(":empty");
},
destroy: function destroy() {
this.$el = $("<div>");
}
});
return Dataset;
function getDisplayFn(display) {
display = display || _.stringify;
return _.isFunction(display) ? display : displayFn;
function displayFn(obj) {
return obj[display];
}
}
function getTemplates(templates, displayFn) {
return {
notFound: templates.notFound && _.templatify(templates.notFound),
pending: templates.pending && _.templatify(templates.pending),
header: templates.header && _.templatify(templates.header),
footer: templates.footer && _.templatify(templates.footer),
suggestion: templates.suggestion || suggestionTemplate
};
function suggestionTemplate(context) {
return $("<div>").text(displayFn(context));
}
}
function isValidName(str) {
return /^[_a-zA-Z0-9-]+$/.test(str);
}
}();
var Menu = function() {
"use strict";
function Menu(o, www) {
var that = this;
o = o || {};
if (!o.node) {
$.error("node is required");
}
www.mixin(this);
this.$node = $(o.node);
this.query = null;
this.datasets = _.map(o.datasets, initializeDataset);
function initializeDataset(oDataset) {
var node = that.$node.find(oDataset.node).first();
oDataset.node = node.length ? node : $("<div>").appendTo(that.$node);
return new Dataset(oDataset, www);
}
}
_.mixin(Menu.prototype, EventEmitter, {
_onSelectableClick: function onSelectableClick($e) {
this.trigger("selectableClicked", $($e.currentTarget));
},
_onRendered: function onRendered(type, dataset, suggestions, async) {
this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty());
this.trigger("datasetRendered", dataset, suggestions, async);
},
_onCleared: function onCleared() {
this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty());
this.trigger("datasetCleared");
},
_propagate: function propagate() {
this.trigger.apply(this, arguments);
},
_allDatasetsEmpty: function allDatasetsEmpty() {
return _.every(this.datasets, isDatasetEmpty);
function isDatasetEmpty(dataset) {
return dataset.isEmpty();
}
},
_getSelectables: function getSelectables() {
return this.$node.find(this.selectors.selectable);
},
_removeCursor: function _removeCursor() {
var $selectable = this.getActiveSelectable();
$selectable && $selectable.removeClass(this.classes.cursor);
},
_ensureVisible: function ensureVisible($el) {
var elTop, elBottom, nodeScrollTop, nodeHeight;
elTop = $el.position().top;
elBottom = elTop + $el.outerHeight(true);
nodeScrollTop = this.$node.scrollTop();
nodeHeight = this.$node.height() + parseInt(this.$node.css("paddingTop"), 10) + parseInt(this.$node.css("paddingBottom"), 10);
if (elTop < 0) {
this.$node.scrollTop(nodeScrollTop + elTop);
} else if (nodeHeight < elBottom) {
this.$node.scrollTop(nodeScrollTop + (elBottom - nodeHeight));
}
},
bind: function() {
var that = this, onSelectableClick;
onSelectableClick = _.bind(this._onSelectableClick, this);
this.$node.on("click.tt", this.selectors.selectable, onSelectableClick);
_.each(this.datasets, function(dataset) {
dataset.onSync("asyncRequested", that._propagate, that).onSync("asyncCanceled", that._propagate, that).onSync("asyncReceived", that._propagate, that).onSync("rendered", that._onRendered, that).onSync("cleared", that._onCleared, that);
});
return this;
},
isOpen: function isOpen() {
return this.$node.hasClass(this.classes.open);
},
open: function open() {
this.$node.addClass(this.classes.open);
},
close: function close() {
this.$node.removeClass(this.classes.open);
this._removeCursor();
},
setLanguageDirection: function setLanguageDirection(dir) {
this.$node.attr("dir", dir);
},
selectableRelativeToCursor: function selectableRelativeToCursor(delta) {
var $selectables, $oldCursor, oldIndex, newIndex;
$oldCursor = this.getActiveSelectable();
$selectables = this._getSelectables();
oldIndex = $oldCursor ? $selectables.index($oldCursor) : -1;
newIndex = oldIndex + delta;
newIndex = (newIndex + 1) % ($selectables.length + 1) - 1;
newIndex = newIndex < -1 ? $selectables.length - 1 : newIndex;
return newIndex === -1 ? null : $selectables.eq(newIndex);
},
setCursor: function setCursor($selectable) {
this._removeCursor();
if ($selectable = $selectable && $selectable.first()) {
$selectable.addClass(this.classes.cursor);
this._ensureVisible($selectable);
}
},
getSelectableData: function getSelectableData($el) {
return $el && $el.length ? Dataset.extractData($el) : null;
},
getActiveSelectable: function getActiveSelectable() {
var $selectable = this._getSelectables().filter(this.selectors.cursor).first();
return $selectable.length ? $selectable : null;
},
getTopSelectable: function getTopSelectable() {
var $selectable = this._getSelectables().first();
return $selectable.length ? $selectable : null;
},
update: function update(query) {
var isValidUpdate = query !== this.query;
if (isValidUpdate) {
this.query = query;
_.each(this.datasets, updateDataset);
}
return isValidUpdate;
function updateDataset(dataset) {
dataset.update(query);
}
},
empty: function empty() {
_.each(this.datasets, clearDataset);
this.query = null;
this.$node.addClass(this.classes.empty);
function clearDataset(dataset) {
dataset.clear();
}
},
destroy: function destroy() {
this.$node.off(".tt");
this.$node = $("<div>");
_.each(this.datasets, destroyDataset);
function destroyDataset(dataset) {
dataset.destroy();
}
}
});
return Menu;
}();
var DefaultMenu = function() {
"use strict";
var s = Menu.prototype;
function DefaultMenu() {
Menu.apply(this, [].slice.call(arguments, 0));
}
_.mixin(DefaultMenu.prototype, Menu.prototype, {
open: function open() {
!this._allDatasetsEmpty() && this._show();
return s.open.apply(this, [].slice.call(arguments, 0));
},
close: function close() {
this._hide();
return s.close.apply(this, [].slice.call(arguments, 0));
},
_onRendered: function onRendered() {
if (this._allDatasetsEmpty()) {
this._hide();
} else {
this.isOpen() && this._show();
}
return s._onRendered.apply(this, [].slice.call(arguments, 0));
},
_onCleared: function onCleared() {
if (this._allDatasetsEmpty()) {
this._hide();
} else {
this.isOpen() && this._show();
}
return s._onCleared.apply(this, [].slice.call(arguments, 0));
},
setLanguageDirection: function setLanguageDirection(dir) {
this.$node.css(dir === "ltr" ? this.css.ltr : this.css.rtl);
return s.setLanguageDirection.apply(this, [].slice.call(arguments, 0));
},
_hide: function hide() {
this.$node.hide();
},
_show: function show() {
this.$node.css("display", "block");
}
});
return DefaultMenu;
}();
var Typeahead = function() {
"use strict";
function Typeahead(o, www) {
var onFocused, onBlurred, onEnterKeyed, onTabKeyed, onEscKeyed, onUpKeyed, onDownKeyed, onLeftKeyed, onRightKeyed, onQueryChanged, onWhitespaceChanged;
o = o || {};
if (!o.input) {
$.error("missing input");
}
if (!o.menu) {
$.error("missing menu");
}
if (!o.eventBus) {
$.error("missing event bus");
}
www.mixin(this);
this.eventBus = o.eventBus;
this.minLength = _.isNumber(o.minLength) ? o.minLength : 1;
this.input = o.input;
this.menu = o.menu;
this.enabled = true;
this.active = false;
this.input.hasFocus() && this.activate();
this.dir = this.input.getLangDir();
this._hacks();
this.menu.bind().onSync("selectableClicked", this._onSelectableClicked, this).onSync("asyncRequested", this._onAsyncRequested, this).onSync("asyncCanceled", this._onAsyncCanceled, this).onSync("asyncReceived", this._onAsyncReceived, this).onSync("datasetRendered", this._onDatasetRendered, this).onSync("datasetCleared", this._onDatasetCleared, this);
onFocused = c(this, "activate", "open", "_onFocused");
onBlurred = c(this, "deactivate", "_onBlurred");
onEnterKeyed = c(this, "isActive", "isOpen", "_onEnterKeyed");
onTabKeyed = c(this, "isActive", "isOpen", "_onTabKeyed");
onEscKeyed = c(this, "isActive", "_onEscKeyed");
onUpKeyed = c(this, "isActive", "open", "_onUpKeyed");
onDownKeyed = c(this, "isActive", "open", "_onDownKeyed");
onLeftKeyed = c(this, "isActive", "isOpen", "_onLeftKeyed");
onRightKeyed = c(this, "isActive", "isOpen", "_onRightKeyed");
onQueryChanged = c(this, "_openIfActive", "_onQueryChanged");
onWhitespaceChanged = c(this, "_openIfActive", "_onWhitespaceChanged");
this.input.bind().onSync("focused", onFocused, this).onSync("blurred", onBlurred, this).onSync("enterKeyed", onEnterKeyed, this).onSync("tabKeyed", onTabKeyed, this).onSync("escKeyed", onEscKeyed, this).onSync("upKeyed", onUpKeyed, this).onSync("downKeyed", onDownKeyed, this).onSync("leftKeyed", onLeftKeyed, this).onSync("rightKeyed", onRightKeyed, this).onSync("queryChanged", onQueryChanged, this).onSync("whitespaceChanged", onWhitespaceChanged, this).onSync("langDirChanged", this._onLangDirChanged, this);
}
_.mixin(Typeahead.prototype, {
_hacks: function hacks() {
var $input, $menu;
$input = this.input.$input || $("<div>");
$menu = this.menu.$node || $("<div>");
$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();
});
},
_onSelectableClicked: function onSelectableClicked(type, $el) {
this.select($el);
},
_onDatasetCleared: function onDatasetCleared() {
this._updateHint();
},
_onDatasetRendered: function onDatasetRendered(type, dataset, suggestions, async) {
this._updateHint();
this.eventBus.trigger("render", suggestions, async, dataset);
},
_onAsyncRequested: function onAsyncRequested(type, dataset, query) {
this.eventBus.trigger("asyncrequest", query, dataset);
},
_onAsyncCanceled: function onAsyncCanceled(type, dataset, query) {
this.eventBus.trigger("asynccancel", query, dataset);
},
_onAsyncReceived: function onAsyncReceived(type, dataset, query) {
this.eventBus.trigger("asyncreceive", query, dataset);
},
_onFocused: function onFocused() {
this._minLengthMet() && this.menu.update(this.input.getQuery());
},
_onBlurred: function onBlurred() {
if (this.input.hasQueryChangedSinceLastFocus()) {
this.eventBus.trigger("change", this.input.getQuery());
}
},
_onEnterKeyed: function onEnterKeyed(type, $e) {
var $selectable;
if ($selectable = this.menu.getActiveSelectable()) {
this.select($selectable) && $e.preventDefault();
}
},
_onTabKeyed: function onTabKeyed(type, $e) {
var $selectable;
if ($selectable = this.menu.getActiveSelectable()) {
this.select($selectable) && $e.preventDefault();
} else if ($selectable = this.menu.getTopSelectable()) {
this.autocomplete($selectable) && $e.preventDefault();
}
},
_onEscKeyed: function onEscKeyed() {
this.close();
},
_onUpKeyed: function onUpKeyed() {
this.moveCursor(-1);
},
_onDownKeyed: function onDownKeyed() {
this.moveCursor(+1);
},
_onLeftKeyed: function onLeftKeyed() {
if (this.dir === "rtl" && this.input.isCursorAtEnd()) {
this.autocomplete(this.menu.getTopSelectable());
}
},
_onRightKeyed: function onRightKeyed() {
if (this.dir === "ltr" && this.input.isCursorAtEnd()) {
this.autocomplete(this.menu.getTopSelectable());
}
},
_onQueryChanged: function onQueryChanged(e, query) {
this._minLengthMet(query) ? this.menu.update(query) : this.menu.empty();
},
_onWhitespaceChanged: function onWhitespaceChanged() {
this._updateHint();
},
_onLangDirChanged: function onLangDirChanged(e, dir) {
if (this.dir !== dir) {
this.dir = dir;
this.menu.setLanguageDirection(dir);
}
},
_openIfActive: function openIfActive() {
this.isActive() && this.open();
},
_minLengthMet: function minLengthMet(query) {
query = _.isString(query) ? query : this.input.getQuery() || "";
return query.length >= this.minLength;
},
_updateHint: function updateHint() {
var $selectable, data, val, query, escapedQuery, frontMatchRegEx, match;
$selectable = this.menu.getTopSelectable();
data = this.menu.getSelectableData($selectable);
val = this.input.getInputValue();
if (data && !_.isBlankString(val) && !this.input.hasOverflow()) {
query = Input.normalizeQuery(val);
escapedQuery = _.escapeRegExChars(query);
frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i");
match = frontMatchRegEx.exec(data.val);
match && this.input.setHint(val + match[1]);
} else {
this.input.clearHint();
}
},
isEnabled: function isEnabled() {
return this.enabled;
},
enable: function enable() {
this.enabled = true;
},
disable: function disable() {
this.enabled = false;
},
isActive: function isActive() {
return this.active;
},
activate: function activate() {
if (this.isActive()) {
return true;
} else if (!this.isEnabled() || this.eventBus.before("active")) {
return false;
} else {
this.active = true;
this.eventBus.trigger("active");
return true;
}
},
deactivate: function deactivate() {
if (!this.isActive()) {
return true;
} else if (this.eventBus.before("idle")) {
return false;
} else {
this.active = false;
this.close();
this.eventBus.trigger("idle");
return true;
}
},
isOpen: function isOpen() {
return this.menu.isOpen();
},
open: function open() {
if (!this.isOpen() && !this.eventBus.before("open")) {
this.menu.open();
this._updateHint();
this.eventBus.trigger("open");
}
return this.isOpen();
},
close: function close() {
if (this.isOpen() && !this.eventBus.before("close")) {
this.menu.close();
this.input.clearHint();
this.input.resetInputValue();
this.eventBus.trigger("close");
}
return !this.isOpen();
},
setVal: function setVal(val) {
this.input.setQuery(_.toStr(val));
},
getVal: function getVal() {
return this.input.getQuery();
},
select: function select($selectable) {
var data = this.menu.getSelectableData($selectable);
if (data && !this.eventBus.before("select", data.obj)) {
this.input.setQuery(data.val, true);
this.eventBus.trigger("select", data.obj);
this.close();
return true;
}
return false;
},
autocomplete: function autocomplete($selectable) {
var query, data, isValid;
query = this.input.getQuery();
data = this.menu.getSelectableData($selectable);
isValid = data && query !== data.val;
if (isValid && !this.eventBus.before("autocomplete", data.obj)) {
this.input.setQuery(data.val);
this.eventBus.trigger("autocomplete", data.obj);
return true;
}
return false;
},
moveCursor: function moveCursor(delta) {
var query, $candidate, data, payload, cancelMove;
query = this.input.getQuery();
$candidate = this.menu.selectableRelativeToCursor(delta);
data = this.menu.getSelectableData($candidate);
payload = data ? data.obj : null;
cancelMove = this._minLengthMet() && this.menu.update(query);
if (!cancelMove && !this.eventBus.before("cursorchange", payload)) {
this.menu.setCursor($candidate);
if (data) {
this.input.setInputValue(data.val);
} else {
this.input.resetInputValue();
this._updateHint();
}
this.eventBus.trigger("cursorchange", payload);
return true;
}
return false;
},
destroy: function destroy() {
this.input.destroy();
this.menu.destroy();
}
});
return Typeahead;
function c(ctx) {
var methods = [].slice.call(arguments, 1);
return function() {
var args = [].slice.call(arguments);
_.each(methods, function(method) {
return ctx[method].apply(ctx, args);
});
};
}
}();
(function() {
"use strict";
var old, keys, methods;
old = $.fn.typeahead;
keys = {
www: "tt-www",
attrs: "tt-attrs",
typeahead: "tt-typeahead"
};
methods = {
initialize: function initialize(o, datasets) {
var www;
datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1);
o = o || {};
www = WWW(o.classNames);
return this.each(attach);
function attach() {
var $input, $wrapper, $hint, $menu, defaultHint, defaultMenu, eventBus, input, menu, typeahead, MenuConstructor;
_.each(datasets, function(d) {
d.highlight = !!o.highlight;
});
$input = $(this);
$wrapper = $(www.html.wrapper);
$hint = $elOrNull(o.hint);
$menu = $elOrNull(o.menu);
defaultHint = o.hint !== false && !$hint;
defaultMenu = o.menu !== false && !$menu;
defaultHint && ($hint = buildHintFromInput($input, www));
defaultMenu && ($menu = $(www.html.menu).css(www.css.menu));
$hint && $hint.val("");
$input = prepInput($input, www);
if (defaultHint || defaultMenu) {
$wrapper.css(www.css.wrapper);
$input.css(defaultHint ? www.css.input : www.css.inputWithNoHint);
$input.wrap($wrapper).parent().prepend(defaultHint ? $hint : null).append(defaultMenu ? $menu : null);
}
MenuConstructor = defaultMenu ? DefaultMenu : Menu;
eventBus = new EventBus({
el: $input
});
input = new Input({
hint: $hint,
input: $input
}, www);
menu = new MenuConstructor({
node: $menu,
datasets: datasets
}, www);
typeahead = new Typeahead({
input: input,
menu: menu,
eventBus: eventBus,
minLength: o.minLength
}, www);
$input.data(keys.www, www);
$input.data(keys.typeahead, typeahead);
}
},
isEnabled: function isEnabled() {
var enabled;
ttEach(this.first(), function(t) {
enabled = t.isEnabled();
});
return enabled;
},
enable: function enable() {
ttEach(this, function(t) {
t.enable();
});
return this;
},
disable: function disable() {
ttEach(this, function(t) {
t.disable();
});
return this;
},
isActive: function isActive() {
var active;
ttEach(this.first(), function(t) {
active = t.isActive();
});
return active;
},
activate: function activate() {
ttEach(this, function(t) {
t.activate();
});
return this;
},
deactivate: function deactivate() {
ttEach(this, function(t) {
t.deactivate();
});
return this;
},
isOpen: function isOpen() {
var open;
ttEach(this.first(), function(t) {
open = t.isOpen();
});
return open;
},
open: function open() {
ttEach(this, function(t) {
t.open();
});
return this;
},
close: function close() {
ttEach(this, function(t) {
t.close();
});
return this;
},
select: function select(el) {
var success = false, $el = $(el);
ttEach(this.first(), function(t) {
success = t.select($el);
});
return success;
},
autocomplete: function autocomplete(el) {
var success = false, $el = $(el);
ttEach(this.first(), function(t) {
success = t.autocomplete($el);
});
return success;
},
moveCursor: function moveCursoe(delta) {
var success = false;
ttEach(this.first(), function(t) {
success = t.moveCursor(delta);
});
return success;
},
val: function val(newVal) {
var query;
if (!arguments.length) {
ttEach(this.first(), function(t) {
query = t.getVal();
});
return query;
} else {
ttEach(this, function(t) {
t.setVal(newVal);
});
return this;
}
},
destroy: function destroy() {
ttEach(this, function(typeahead, $input) {
revert($input);
typeahead.destroy();
});
return this;
}
};
$.fn.typeahead = function(method) {
if (methods[method]) {
return methods[method].apply(this, [].slice.call(arguments, 1));
} else {
return methods.initialize.apply(this, arguments);
}
};
$.fn.typeahead.noConflict = function noConflict() {
$.fn.typeahead = old;
return this;
};
function ttEach($els, fn) {
$els.each(function() {
var $input = $(this), typeahead;
(typeahead = $input.data(keys.typeahead)) && fn(typeahead, $input);
});
}
function buildHintFromInput($input, www) {
return $input.clone().addClass(www.classes.hint).removeData().css(www.css.hint).css(getBackgroundStyles($input)).prop("readonly", true).removeAttr("id name placeholder required").attr({
autocomplete: "off",
spellcheck: "false",
tabindex: -1
});
}
function prepInput($input, www) {
$input.data(keys.attrs, {
dir: $input.attr("dir"),
autocomplete: $input.attr("autocomplete"),
spellcheck: $input.attr("spellcheck"),
style: $input.attr("style")
});
$input.addClass(www.classes.input).attr({
autocomplete: "off",
spellcheck: false
});
try {
!$input.attr("dir") && $input.attr("dir", "auto");
} catch (e) {}
return $input;
}
function getBackgroundStyles($el) {
return {
backgroundAttachment: $el.css("background-attachment"),
backgroundClip: $el.css("background-clip"),
backgroundColor: $el.css("background-color"),
backgroundImage: $el.css("background-image"),
backgroundOrigin: $el.css("background-origin"),
backgroundPosition: $el.css("background-position"),
backgroundRepeat: $el.css("background-repeat"),
backgroundSize: $el.css("background-size")
};
}
function revert($input) {
var www, $wrapper;
www = $input.data(keys.www);
$wrapper = $input.parent().filter(www.selectors.wrapper);
_.each($input.data(keys.attrs), function(val, key) {
_.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val);
});
$input.removeData(keys.typeahead).removeData(keys.www).removeData(keys.attr).removeClass(www.classes.input);
if ($wrapper.length) {
$input.detach().insertAfter($wrapper);
$wrapper.remove();
}
}
function $elOrNull(obj) {
var isValid, $el;
isValid = _.isJQuery(obj) || _.isElement(obj);
$el = isValid ? $(obj).first() : [];
return $el.length ? $el : null;
}
})();
});

typeahead.css:

.typeahead,.tt-query,.tt-hint {
width: 396px;
height: 30px;
padding: 8px 12px;
font-size: 24px;
line-height: 30px;
border: 2px solid #ccc;
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
outline: none;
}
.typeahead {
background-color: #fff;
}
.typeahead:focus {
border: 2px solid #0097cf;
}
.tt-query {
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
}
.tt-hint {
color: #999
}
.tt-menu {
width: 422px;
margin: 12px 0;
padding: 8px 0;
background-color: #fff;
border: 1px solid #ccc;
border: 1px solid rgba(0, 0, 0, 0.2);
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
-webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
-moz-box-shadow: 0 5px 10px rgba(0,0,0,.2);
box-shadow: 0 5px 10px rgba(0,0,0,.2);
}
.tt-suggestion {
padding: 3px 20px;
font-size: 18px;
line-height: 24px;
}
.tt-suggestion:hover {
cursor: pointer;
color: #fff;
background-color: #0097cf;
}
.tt-suggestion.tt-cursor {
color: #fff;
background-color: #0097cf;
}
.tt-suggestion p {
margin: 0;
}
.gist {
font-size: 14px;
}
/* example specific styles */
/* ----------------------- */
#custom-templates .empty-message {
padding: 5px 10px;
text-align: center;
}
#multiple-datasets .league-name {
margin: 0 20px 5px 20px;
padding: 3px 0;
border-bottom: 1px solid #ccc;
}
#scrollable-dropdown-menu .tt-menu {
max-height: 150px;
overflow-y: auto;
}
#rtl-support .tt-menu {
text-align: right;
}

以上所述是小编给大家介绍的Bootstrap3使用typeahead插件实现自动补全功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
用js生产批量批处理执行命令
Jul 28 Javascript
jQueryUI的Dialog的简单封装
Jun 07 Javascript
jQuery.extend 函数详解
Feb 03 Javascript
js/jquery获取文本框输入焦点的方法
Mar 04 Javascript
jQuery选择器源码解读(一):Sizzle方法
Mar 31 Javascript
jQuery平滑旋转幻灯片特效代码分享
Sep 07 Javascript
jQuery实现页面顶部显示的进度条效果完整实例
Dec 09 Javascript
基于javascript实现右下角浮动广告效果
Jan 08 Javascript
使用vue和datatables进行表格的服务器端分页实例代码
Jun 07 Javascript
vue项目添加多页面配置的步骤详解
May 22 Javascript
详解Vue template 如何支持多个根结点
Feb 10 Javascript
vue 在methods中调用mounted的实现操作
Aug 07 Javascript
Node.js DES加密的简单实现
Jul 07 #Javascript
使用bootstrap typeahead插件实现输入框自动补全之问题及解决办法
Jul 07 #Javascript
使用Bootstrap typeahead插件实现搜索框自动补全的方法
Jul 07 #Javascript
jQuery插件Flexslider实现图片轮播、图文结合滑动切换效果
Apr 16 #Javascript
内容滑动切换效果jquery.hwSlide.js插件封装
Jul 07 #Javascript
jQuery实现下拉菜单(内容为时间)的实时更新及图表的随动更新的方法
Jul 07 #Javascript
深入解析桶排序算法及Node.js上JavaScript的代码实现
Jul 06 #Javascript
You might like
文件上传的实现
2006/10/09 PHP
用PHP实现小型站点广告管理(修正版)
2006/10/09 PHP
[原创]解决wincache不支持64位PHP5.5/5.6的问题(提供64位wincache下载)
2016/06/22 PHP
PHP常用排序算法实例小结【基本排序,冒泡排序,快速排序,插入排序】
2017/02/07 PHP
用JQuery 实现的自定义对话框
2007/03/24 Javascript
JQuery获取浏览器窗口内容部分高度的代码
2012/02/24 Javascript
原生js实现模拟滚动条
2015/06/15 Javascript
jQuery+PHP星级评分实现方法
2015/10/02 Javascript
如何根据百度地图计算出两地之间的驾驶距离(两种语言js和C#)
2015/10/29 Javascript
JS中跨页面调用变量和函数的方法(例如a.js 和 b.js中互相调用)
2016/11/01 Javascript
axios基本入门用法教程
2017/03/25 Javascript
AngularJS通过ng-Img-Crop实现头像截取的示例
2017/08/17 Javascript
jQuery实现的弹幕效果完整实例
2017/09/06 jQuery
微信小程序实现全国机场索引列表
2018/01/31 Javascript
JavaScript中的E-mail 地址格式验证
2018/03/28 Javascript
小程序实现短信登录倒计时
2019/07/12 Javascript
Vue发布项目实例讲解
2019/07/17 Javascript
vue fetch中的.then()的正确使用方法
2020/04/17 Javascript
JS面向对象实现飞机大战
2020/08/26 Javascript
实例讲解Python中global语句下全局变量的值的修改
2016/06/16 Python
Python实现爬虫爬取NBA数据功能示例
2018/05/28 Python
Python实现对文件进行单词划分并去重排序操作示例
2018/07/10 Python
Django Rest framework频率原理与限制
2019/07/26 Python
使用Windows批处理和WMI设置Python的环境变量方法
2019/08/14 Python
使用Keras 实现查看model weights .h5 文件的内容
2020/06/09 Python
Python叠加矩形框图层2种方法及效果
2020/06/18 Python
CSS3制作ajax loader icon实现思路及代码
2013/08/25 HTML / CSS
css3高级选择器使用方法
2013/12/02 HTML / CSS
css3和jquery实现的可折叠导航菜单适合放在手机网页的导航菜单
2014/09/02 HTML / CSS
HTML5触摸事件演化tap事件介绍
2016/03/25 HTML / CSS
Carter’s官方旗舰店:美国受欢迎的婴童服装品牌
2018/01/21 全球购物
写一个函数,求一个字符串的长度。在main函数中输入字符串,并输出其长度
2015/11/18 面试题
市场总经理岗位职责
2014/04/11 职场文书
政法干警核心价值观心得体会
2014/09/11 职场文书
红十字会救护培训简讯
2015/07/20 职场文书
2016反腐倡廉警示教育心得体会
2016/01/13 职场文书