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代码
Sep 17 Javascript
JavaScript 滚轮事件使用说明
Mar 07 Javascript
javascript阻止浏览器后退事件防止误操作清空表单
Nov 22 Javascript
AngularJS实现表单验证
Jan 28 Javascript
JavaScript基础知识之方法汇总结
Jan 24 Javascript
常用的js验证和数据处理总结
Aug 02 Javascript
轻松掌握JavaScript状态模式
Sep 07 Javascript
微信小程序(应用号)开发新闻客户端实例
Oct 24 Javascript
Vue实现textarea固定输入行数与添加下划线样式的思路详解
Jun 28 Javascript
JS实现点击下拉列表文本框中出现对应的网址,点击跳转按钮实现跳转
Nov 25 Javascript
javascript Number 与 Math对象的介绍
Nov 17 Javascript
ant design charts 获取后端接口数据展示
May 25 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
PHP用mysql数据库存储session的代码
2010/03/05 PHP
PHP用GD库生成高质量的缩略图片
2011/03/09 PHP
采用PHP函数memory_get_usage获取PHP内存清耗量的方法
2011/12/06 PHP
php文本转图片自动换行的方法
2013/03/13 PHP
WordPress中给文章添加自定义字段及后台编辑功能区域
2015/12/19 PHP
PHP提取字符串中的手机号正则表达式怎么写
2017/07/17 PHP
PHP Post获取不到非表单数据的问题解决办法
2018/02/27 PHP
PHP Swoole异步MySQL客户端实现方法示例
2019/10/24 PHP
某页码显示的helper 少量调整,另附js版
2010/09/12 Javascript
jQuery EasyUI API 中文文档 - Pagination分页
2011/09/29 Javascript
JQuery.get提交页面不跳转的解决方法
2015/01/13 Javascript
JQuery实现展开关闭层的方法
2015/02/17 Javascript
JavaScript之AOP编程实例
2015/07/17 Javascript
jQuery操作属性和样式详解
2016/04/13 Javascript
jquery dialog获取焦点的方法
2017/02/09 Javascript
NodeJS测试框架mocha入门教程
2017/03/28 NodeJs
基于JavaScript实现带数据验证和复选框的表单提交
2017/08/23 Javascript
JavaScript this指向相关原理及实例解析
2020/07/10 Javascript
在vue中使用回调函数,this调用无效的解决
2020/08/11 Javascript
vue内置组件keep-alive事件动态缓存实例
2020/10/30 Javascript
javascript实现点击产生随机图形
2021/01/25 Javascript
[01:29:31]VP VS VG Supermajor小组赛胜者组第二轮 BO3第一场 6.2
2018/06/03 DOTA
Django项目中用JS实现加载子页面并传值的方法
2018/05/28 Python
Python常用的json标准库
2019/02/19 Python
python3获取当前目录的实现方法
2019/07/29 Python
Python3离线安装Requests模块问题
2019/10/13 Python
python 怎样进行内存管理
2020/11/10 Python
2014年党员公开承诺践诺书
2014/03/25 职场文书
学生评语大全
2014/04/18 职场文书
升旗仪式演讲稿
2014/05/08 职场文书
学习张丽丽心得体会
2014/09/03 职场文书
学习群众路线的心得体会
2014/11/05 职场文书
司机岗位职责
2015/02/04 职场文书
如何避免mysql启动时错误及sock文件作用分析
2022/01/22 MySQL
threejs太阳光与阴影效果实例代码
2022/04/05 Javascript
联想win10摄像头打不开怎么办?win10笔记本摄像头打不开解决办法
2022/04/08 数码科技