").appendTo(that.$node);
1872 | return new Dataset(oDataset, www);
1873 | }
1874 | }
1875 | _.mixin(Menu.prototype, EventEmitter, {
1876 | _onSelectableClick: function onSelectableClick($e) {
1877 | this.trigger("selectableClicked", $($e.currentTarget));
1878 | },
1879 | _onRendered: function onRendered(type, dataset, suggestions, async) {
1880 | this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty());
1881 | this.trigger("datasetRendered", dataset, suggestions, async);
1882 | },
1883 | _onCleared: function onCleared() {
1884 | this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty());
1885 | this.trigger("datasetCleared");
1886 | },
1887 | _propagate: function propagate() {
1888 | this.trigger.apply(this, arguments);
1889 | },
1890 | _allDatasetsEmpty: function allDatasetsEmpty() {
1891 | return _.every(this.datasets, _.bind(function isDatasetEmpty(dataset) {
1892 | var isEmpty = dataset.isEmpty();
1893 | this.$node.attr("aria-expanded", !isEmpty);
1894 | return isEmpty;
1895 | }, this));
1896 | },
1897 | _getSelectables: function getSelectables() {
1898 | return this.$node.find(this.selectors.selectable);
1899 | },
1900 | _removeCursor: function _removeCursor() {
1901 | var $selectable = this.getActiveSelectable();
1902 | $selectable && $selectable.removeClass(this.classes.cursor);
1903 | },
1904 | _ensureVisible: function ensureVisible($el) {
1905 | var elTop, elBottom, nodeScrollTop, nodeHeight;
1906 | elTop = $el.position().top;
1907 | elBottom = elTop + $el.outerHeight(true);
1908 | nodeScrollTop = this.$node.scrollTop();
1909 | nodeHeight = this.$node.height() + parseInt(this.$node.css("paddingTop"), 10) + parseInt(this.$node.css("paddingBottom"), 10);
1910 | if (elTop < 0) {
1911 | this.$node.scrollTop(nodeScrollTop + elTop);
1912 | } else if (nodeHeight < elBottom) {
1913 | this.$node.scrollTop(nodeScrollTop + (elBottom - nodeHeight));
1914 | }
1915 | },
1916 | bind: function() {
1917 | var that = this, onSelectableClick;
1918 | onSelectableClick = _.bind(this._onSelectableClick, this);
1919 | this.$node.on("click.tt", this.selectors.selectable, onSelectableClick);
1920 | this.$node.on("mouseover", this.selectors.selectable, function() {
1921 | that.setCursor($(this));
1922 | });
1923 | this.$node.on("mouseleave", function() {
1924 | that._removeCursor();
1925 | });
1926 | _.each(this.datasets, function(dataset) {
1927 | 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);
1928 | });
1929 | return this;
1930 | },
1931 | isOpen: function isOpen() {
1932 | return this.$node.hasClass(this.classes.open);
1933 | },
1934 | open: function open() {
1935 | this.$node.scrollTop(0);
1936 | this.$node.addClass(this.classes.open);
1937 | },
1938 | close: function close() {
1939 | this.$node.attr("aria-expanded", false);
1940 | this.$node.removeClass(this.classes.open);
1941 | this._removeCursor();
1942 | },
1943 | setLanguageDirection: function setLanguageDirection(dir) {
1944 | this.$node.attr("dir", dir);
1945 | },
1946 | selectableRelativeToCursor: function selectableRelativeToCursor(delta) {
1947 | var $selectables, $oldCursor, oldIndex, newIndex;
1948 | $oldCursor = this.getActiveSelectable();
1949 | $selectables = this._getSelectables();
1950 | oldIndex = $oldCursor ? $selectables.index($oldCursor) : -1;
1951 | newIndex = oldIndex + delta;
1952 | newIndex = (newIndex + 1) % ($selectables.length + 1) - 1;
1953 | newIndex = newIndex < -1 ? $selectables.length - 1 : newIndex;
1954 | return newIndex === -1 ? null : $selectables.eq(newIndex);
1955 | },
1956 | setCursor: function setCursor($selectable) {
1957 | this._removeCursor();
1958 | if ($selectable = $selectable && $selectable.first()) {
1959 | $selectable.addClass(this.classes.cursor);
1960 | this._ensureVisible($selectable);
1961 | }
1962 | },
1963 | getSelectableData: function getSelectableData($el) {
1964 | return $el && $el.length ? Dataset.extractData($el) : null;
1965 | },
1966 | getActiveSelectable: function getActiveSelectable() {
1967 | var $selectable = this._getSelectables().filter(this.selectors.cursor).first();
1968 | return $selectable.length ? $selectable : null;
1969 | },
1970 | getTopSelectable: function getTopSelectable() {
1971 | var $selectable = this._getSelectables().first();
1972 | return $selectable.length ? $selectable : null;
1973 | },
1974 | update: function update(query) {
1975 | var isValidUpdate = query !== this.query;
1976 | if (isValidUpdate) {
1977 | this.query = query;
1978 | _.each(this.datasets, updateDataset);
1979 | }
1980 | return isValidUpdate;
1981 | function updateDataset(dataset) {
1982 | dataset.update(query);
1983 | }
1984 | },
1985 | empty: function empty() {
1986 | _.each(this.datasets, clearDataset);
1987 | this.query = null;
1988 | this.$node.addClass(this.classes.empty);
1989 | function clearDataset(dataset) {
1990 | dataset.clear();
1991 | }
1992 | },
1993 | destroy: function destroy() {
1994 | this.$node.off(".tt");
1995 | this.$node = $("
");
1996 | _.each(this.datasets, destroyDataset);
1997 | function destroyDataset(dataset) {
1998 | dataset.destroy();
1999 | }
2000 | }
2001 | });
2002 | return Menu;
2003 | }();
2004 | var Status = function() {
2005 | "use strict";
2006 | function Status(options) {
2007 | this.$el = $("
", {
2008 | role: "status",
2009 | "aria-live": "polite"
2010 | }).css({
2011 | position: "absolute",
2012 | padding: "0",
2013 | border: "0",
2014 | height: "1px",
2015 | width: "1px",
2016 | "margin-bottom": "-1px",
2017 | "margin-right": "-1px",
2018 | overflow: "hidden",
2019 | clip: "rect(0 0 0 0)",
2020 | "white-space": "nowrap"
2021 | });
2022 | options.$input.after(this.$el);
2023 | _.each(options.menu.datasets, _.bind(function(dataset) {
2024 | if (dataset.onSync) {
2025 | dataset.onSync("rendered", _.bind(this.update, this));
2026 | dataset.onSync("cleared", _.bind(this.cleared, this));
2027 | }
2028 | }, this));
2029 | }
2030 | _.mixin(Status.prototype, {
2031 | update: function update(event, suggestions) {
2032 | var length = suggestions.length;
2033 | var words;
2034 | if (length === 1) {
2035 | words = {
2036 | result: "result",
2037 | is: "is"
2038 | };
2039 | } else {
2040 | words = {
2041 | result: "results",
2042 | is: "are"
2043 | };
2044 | }
2045 | this.$el.text(length + " " + words.result + " " + words.is + " available, use up and down arrow keys to navigate.");
2046 | },
2047 | cleared: function() {
2048 | this.$el.text("");
2049 | }
2050 | });
2051 | return Status;
2052 | }();
2053 | var DefaultMenu = function() {
2054 | "use strict";
2055 | var s = Menu.prototype;
2056 | function DefaultMenu() {
2057 | Menu.apply(this, [].slice.call(arguments, 0));
2058 | }
2059 | _.mixin(DefaultMenu.prototype, Menu.prototype, {
2060 | open: function open() {
2061 | !this._allDatasetsEmpty() && this._show();
2062 | return s.open.apply(this, [].slice.call(arguments, 0));
2063 | },
2064 | close: function close() {
2065 | this._hide();
2066 | return s.close.apply(this, [].slice.call(arguments, 0));
2067 | },
2068 | _onRendered: function onRendered() {
2069 | if (this._allDatasetsEmpty()) {
2070 | this._hide();
2071 | } else {
2072 | this.isOpen() && this._show();
2073 | }
2074 | return s._onRendered.apply(this, [].slice.call(arguments, 0));
2075 | },
2076 | _onCleared: function onCleared() {
2077 | if (this._allDatasetsEmpty()) {
2078 | this._hide();
2079 | } else {
2080 | this.isOpen() && this._show();
2081 | }
2082 | return s._onCleared.apply(this, [].slice.call(arguments, 0));
2083 | },
2084 | setLanguageDirection: function setLanguageDirection(dir) {
2085 | this.$node.css(dir === "ltr" ? this.css.ltr : this.css.rtl);
2086 | return s.setLanguageDirection.apply(this, [].slice.call(arguments, 0));
2087 | },
2088 | _hide: function hide() {
2089 | this.$node.hide();
2090 | },
2091 | _show: function show() {
2092 | this.$node.css("display", "block");
2093 | }
2094 | });
2095 | return DefaultMenu;
2096 | }();
2097 | var Typeahead = function() {
2098 | "use strict";
2099 | function Typeahead(o, www) {
2100 | var onFocused, onBlurred, onEnterKeyed, onTabKeyed, onEscKeyed, onUpKeyed, onDownKeyed, onLeftKeyed, onRightKeyed, onQueryChanged, onWhitespaceChanged;
2101 | o = o || {};
2102 | if (!o.input) {
2103 | $.error("missing input");
2104 | }
2105 | if (!o.menu) {
2106 | $.error("missing menu");
2107 | }
2108 | if (!o.eventBus) {
2109 | $.error("missing event bus");
2110 | }
2111 | www.mixin(this);
2112 | this.eventBus = o.eventBus;
2113 | this.minLength = _.isNumber(o.minLength) ? o.minLength : 1;
2114 | this.input = o.input;
2115 | this.menu = o.menu;
2116 | this.enabled = true;
2117 | this.active = false;
2118 | this.input.hasFocus() && this.activate();
2119 | this.dir = this.input.getLangDir();
2120 | this._hacks();
2121 | 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);
2122 | onFocused = c(this, "activate", "open", "_onFocused");
2123 | onBlurred = c(this, "deactivate", "_onBlurred");
2124 | onEnterKeyed = c(this, "isActive", "isOpen", "_onEnterKeyed");
2125 | onTabKeyed = c(this, "isActive", "isOpen", "_onTabKeyed");
2126 | onEscKeyed = c(this, "isActive", "_onEscKeyed");
2127 | onUpKeyed = c(this, "isActive", "open", "_onUpKeyed");
2128 | onDownKeyed = c(this, "isActive", "open", "_onDownKeyed");
2129 | onLeftKeyed = c(this, "isActive", "isOpen", "_onLeftKeyed");
2130 | onRightKeyed = c(this, "isActive", "isOpen", "_onRightKeyed");
2131 | onQueryChanged = c(this, "_openIfActive", "_onQueryChanged");
2132 | onWhitespaceChanged = c(this, "_openIfActive", "_onWhitespaceChanged");
2133 | 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);
2134 | }
2135 | _.mixin(Typeahead.prototype, {
2136 | _hacks: function hacks() {
2137 | var $input, $menu;
2138 | $input = this.input.$input || $("
");
2139 | $menu = this.menu.$node || $("
");
2140 | $input.on("blur.tt", function($e) {
2141 | var active, isActive, hasActive;
2142 | active = document.activeElement;
2143 | isActive = $menu.is(active);
2144 | hasActive = $menu.has(active).length > 0;
2145 | if (_.isMsie() && (isActive || hasActive)) {
2146 | $e.preventDefault();
2147 | $e.stopImmediatePropagation();
2148 | _.defer(function() {
2149 | $input.focus();
2150 | });
2151 | }
2152 | });
2153 | $menu.on("mousedown.tt", function($e) {
2154 | $e.preventDefault();
2155 | });
2156 | },
2157 | _onSelectableClicked: function onSelectableClicked(type, $el) {
2158 | this.select($el);
2159 | },
2160 | _onDatasetCleared: function onDatasetCleared() {
2161 | this._updateHint();
2162 | },
2163 | _onDatasetRendered: function onDatasetRendered(type, suggestions, async, dataset) {
2164 | this._updateHint();
2165 | this.eventBus.trigger("render", suggestions, async, dataset);
2166 | },
2167 | _onAsyncRequested: function onAsyncRequested(type, dataset, query) {
2168 | this.eventBus.trigger("asyncrequest", query, dataset);
2169 | },
2170 | _onAsyncCanceled: function onAsyncCanceled(type, dataset, query) {
2171 | this.eventBus.trigger("asynccancel", query, dataset);
2172 | },
2173 | _onAsyncReceived: function onAsyncReceived(type, dataset, query) {
2174 | this.eventBus.trigger("asyncreceive", query, dataset);
2175 | },
2176 | _onFocused: function onFocused() {
2177 | this._minLengthMet() && this.menu.update(this.input.getQuery());
2178 | },
2179 | _onBlurred: function onBlurred() {
2180 | if (this.input.hasQueryChangedSinceLastFocus()) {
2181 | this.eventBus.trigger("change", this.input.getQuery());
2182 | }
2183 | },
2184 | _onEnterKeyed: function onEnterKeyed(type, $e) {
2185 | var $selectable;
2186 | if ($selectable = this.menu.getActiveSelectable()) {
2187 | if (this.select($selectable)) {
2188 | $e.preventDefault();
2189 | $e.stopPropagation();
2190 | }
2191 | }
2192 | },
2193 | _onTabKeyed: function onTabKeyed(type, $e) {
2194 | var $selectable;
2195 | if ($selectable = this.menu.getActiveSelectable()) {
2196 | this.select($selectable) && $e.preventDefault();
2197 | } else if ($selectable = this.menu.getTopSelectable()) {
2198 | this.autocomplete($selectable) && $e.preventDefault();
2199 | }
2200 | },
2201 | _onEscKeyed: function onEscKeyed() {
2202 | this.close();
2203 | },
2204 | _onUpKeyed: function onUpKeyed() {
2205 | this.moveCursor(-1);
2206 | },
2207 | _onDownKeyed: function onDownKeyed() {
2208 | this.moveCursor(+1);
2209 | },
2210 | _onLeftKeyed: function onLeftKeyed() {
2211 | if (this.dir === "rtl" && this.input.isCursorAtEnd()) {
2212 | this.autocomplete(this.menu.getActiveSelectable() || this.menu.getTopSelectable());
2213 | }
2214 | },
2215 | _onRightKeyed: function onRightKeyed() {
2216 | if (this.dir === "ltr" && this.input.isCursorAtEnd()) {
2217 | this.autocomplete(this.menu.getActiveSelectable() || this.menu.getTopSelectable());
2218 | }
2219 | },
2220 | _onQueryChanged: function onQueryChanged(e, query) {
2221 | this._minLengthMet(query) ? this.menu.update(query) : this.menu.empty();
2222 | },
2223 | _onWhitespaceChanged: function onWhitespaceChanged() {
2224 | this._updateHint();
2225 | },
2226 | _onLangDirChanged: function onLangDirChanged(e, dir) {
2227 | if (this.dir !== dir) {
2228 | this.dir = dir;
2229 | this.menu.setLanguageDirection(dir);
2230 | }
2231 | },
2232 | _openIfActive: function openIfActive() {
2233 | this.isActive() && this.open();
2234 | },
2235 | _minLengthMet: function minLengthMet(query) {
2236 | query = _.isString(query) ? query : this.input.getQuery() || "";
2237 | return query.length >= this.minLength;
2238 | },
2239 | _updateHint: function updateHint() {
2240 | var $selectable, data, val, query, escapedQuery, frontMatchRegEx, match;
2241 | $selectable = this.menu.getTopSelectable();
2242 | data = this.menu.getSelectableData($selectable);
2243 | val = this.input.getInputValue();
2244 | if (data && !_.isBlankString(val) && !this.input.hasOverflow()) {
2245 | query = Input.normalizeQuery(val);
2246 | escapedQuery = _.escapeRegExChars(query);
2247 | frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i");
2248 | match = frontMatchRegEx.exec(data.val);
2249 | match && this.input.setHint(val + match[1]);
2250 | } else {
2251 | this.input.clearHint();
2252 | }
2253 | },
2254 | isEnabled: function isEnabled() {
2255 | return this.enabled;
2256 | },
2257 | enable: function enable() {
2258 | this.enabled = true;
2259 | },
2260 | disable: function disable() {
2261 | this.enabled = false;
2262 | },
2263 | isActive: function isActive() {
2264 | return this.active;
2265 | },
2266 | activate: function activate() {
2267 | if (this.isActive()) {
2268 | return true;
2269 | } else if (!this.isEnabled() || this.eventBus.before("active")) {
2270 | return false;
2271 | } else {
2272 | this.active = true;
2273 | this.eventBus.trigger("active");
2274 | return true;
2275 | }
2276 | },
2277 | deactivate: function deactivate() {
2278 | if (!this.isActive()) {
2279 | return true;
2280 | } else if (this.eventBus.before("idle")) {
2281 | return false;
2282 | } else {
2283 | this.active = false;
2284 | this.close();
2285 | this.eventBus.trigger("idle");
2286 | return true;
2287 | }
2288 | },
2289 | isOpen: function isOpen() {
2290 | return this.menu.isOpen();
2291 | },
2292 | open: function open() {
2293 | if (!this.isOpen() && !this.eventBus.before("open")) {
2294 | this.menu.open();
2295 | this._updateHint();
2296 | this.eventBus.trigger("open");
2297 | }
2298 | return this.isOpen();
2299 | },
2300 | close: function close() {
2301 | if (this.isOpen() && !this.eventBus.before("close")) {
2302 | this.menu.close();
2303 | this.input.clearHint();
2304 | this.input.resetInputValue();
2305 | this.eventBus.trigger("close");
2306 | }
2307 | return !this.isOpen();
2308 | },
2309 | setVal: function setVal(val) {
2310 | this.input.setQuery(_.toStr(val));
2311 | },
2312 | getVal: function getVal() {
2313 | return this.input.getQuery();
2314 | },
2315 | select: function select($selectable) {
2316 | var data = this.menu.getSelectableData($selectable);
2317 | if (data && !this.eventBus.before("select", data.obj, data.dataset)) {
2318 | this.input.setQuery(data.val, true);
2319 | this.eventBus.trigger("select", data.obj, data.dataset);
2320 | this.close();
2321 | return true;
2322 | }
2323 | return false;
2324 | },
2325 | autocomplete: function autocomplete($selectable) {
2326 | var query, data, isValid;
2327 | query = this.input.getQuery();
2328 | data = this.menu.getSelectableData($selectable);
2329 | isValid = data && query !== data.val;
2330 | if (isValid && !this.eventBus.before("autocomplete", data.obj, data.dataset)) {
2331 | this.input.setQuery(data.val);
2332 | this.eventBus.trigger("autocomplete", data.obj, data.dataset);
2333 | return true;
2334 | }
2335 | return false;
2336 | },
2337 | moveCursor: function moveCursor(delta) {
2338 | var query, $candidate, data, suggestion, datasetName, cancelMove, id;
2339 | query = this.input.getQuery();
2340 | $candidate = this.menu.selectableRelativeToCursor(delta);
2341 | data = this.menu.getSelectableData($candidate);
2342 | suggestion = data ? data.obj : null;
2343 | datasetName = data ? data.dataset : null;
2344 | id = $candidate ? $candidate.attr("id") : null;
2345 | this.input.trigger("cursorchange", id);
2346 | cancelMove = this._minLengthMet() && this.menu.update(query);
2347 | if (!cancelMove && !this.eventBus.before("cursorchange", suggestion, datasetName)) {
2348 | this.menu.setCursor($candidate);
2349 | if (data) {
2350 | this.input.setInputValue(data.val);
2351 | } else {
2352 | this.input.resetInputValue();
2353 | this._updateHint();
2354 | }
2355 | this.eventBus.trigger("cursorchange", suggestion, datasetName);
2356 | return true;
2357 | }
2358 | return false;
2359 | },
2360 | destroy: function destroy() {
2361 | this.input.destroy();
2362 | this.menu.destroy();
2363 | }
2364 | });
2365 | return Typeahead;
2366 | function c(ctx) {
2367 | var methods = [].slice.call(arguments, 1);
2368 | return function() {
2369 | var args = [].slice.call(arguments);
2370 | _.each(methods, function(method) {
2371 | return ctx[method].apply(ctx, args);
2372 | });
2373 | };
2374 | }
2375 | }();
2376 | (function() {
2377 | "use strict";
2378 | var old, keys, methods;
2379 | old = $.fn.typeahead;
2380 | keys = {
2381 | www: "tt-www",
2382 | attrs: "tt-attrs",
2383 | typeahead: "tt-typeahead"
2384 | };
2385 | methods = {
2386 | initialize: function initialize(o, datasets) {
2387 | var www;
2388 | datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1);
2389 | o = o || {};
2390 | www = WWW(o.classNames);
2391 | return this.each(attach);
2392 | function attach() {
2393 | var $input, $wrapper, $hint, $menu, defaultHint, defaultMenu, eventBus, input, menu, status, typeahead, MenuConstructor;
2394 | _.each(datasets, function(d) {
2395 | d.highlight = !!o.highlight;
2396 | });
2397 | $input = $(this);
2398 | $wrapper = $(www.html.wrapper);
2399 | $hint = $elOrNull(o.hint);
2400 | $menu = $elOrNull(o.menu);
2401 | defaultHint = o.hint !== false && !$hint;
2402 | defaultMenu = o.menu !== false && !$menu;
2403 | defaultHint && ($hint = buildHintFromInput($input, www));
2404 | defaultMenu && ($menu = $(www.html.menu).css(www.css.menu));
2405 | $hint && $hint.val("");
2406 | $input = prepInput($input, www);
2407 | if (defaultHint || defaultMenu) {
2408 | $wrapper.css(www.css.wrapper);
2409 | $input.css(defaultHint ? www.css.input : www.css.inputWithNoHint);
2410 | $input.wrap($wrapper).parent().prepend(defaultHint ? $hint : null).append(defaultMenu ? $menu : null);
2411 | }
2412 | MenuConstructor = defaultMenu ? DefaultMenu : Menu;
2413 | eventBus = new EventBus({
2414 | el: $input
2415 | });
2416 | input = new Input({
2417 | hint: $hint,
2418 | input: $input
2419 | }, www);
2420 | menu = new MenuConstructor({
2421 | node: $menu,
2422 | datasets: datasets
2423 | }, www);
2424 | status = new Status({
2425 | $input: $input,
2426 | menu: menu
2427 | });
2428 | typeahead = new Typeahead({
2429 | input: input,
2430 | menu: menu,
2431 | eventBus: eventBus,
2432 | minLength: o.minLength
2433 | }, www);
2434 | $input.data(keys.www, www);
2435 | $input.data(keys.typeahead, typeahead);
2436 | }
2437 | },
2438 | isEnabled: function isEnabled() {
2439 | var enabled;
2440 | ttEach(this.first(), function(t) {
2441 | enabled = t.isEnabled();
2442 | });
2443 | return enabled;
2444 | },
2445 | enable: function enable() {
2446 | ttEach(this, function(t) {
2447 | t.enable();
2448 | });
2449 | return this;
2450 | },
2451 | disable: function disable() {
2452 | ttEach(this, function(t) {
2453 | t.disable();
2454 | });
2455 | return this;
2456 | },
2457 | isActive: function isActive() {
2458 | var active;
2459 | ttEach(this.first(), function(t) {
2460 | active = t.isActive();
2461 | });
2462 | return active;
2463 | },
2464 | activate: function activate() {
2465 | ttEach(this, function(t) {
2466 | t.activate();
2467 | });
2468 | return this;
2469 | },
2470 | deactivate: function deactivate() {
2471 | ttEach(this, function(t) {
2472 | t.deactivate();
2473 | });
2474 | return this;
2475 | },
2476 | isOpen: function isOpen() {
2477 | var open;
2478 | ttEach(this.first(), function(t) {
2479 | open = t.isOpen();
2480 | });
2481 | return open;
2482 | },
2483 | open: function open() {
2484 | ttEach(this, function(t) {
2485 | t.open();
2486 | });
2487 | return this;
2488 | },
2489 | close: function close() {
2490 | ttEach(this, function(t) {
2491 | t.close();
2492 | });
2493 | return this;
2494 | },
2495 | select: function select(el) {
2496 | var success = false, $el = $(el);
2497 | ttEach(this.first(), function(t) {
2498 | success = t.select($el);
2499 | });
2500 | return success;
2501 | },
2502 | autocomplete: function autocomplete(el) {
2503 | var success = false, $el = $(el);
2504 | ttEach(this.first(), function(t) {
2505 | success = t.autocomplete($el);
2506 | });
2507 | return success;
2508 | },
2509 | moveCursor: function moveCursoe(delta) {
2510 | var success = false;
2511 | ttEach(this.first(), function(t) {
2512 | success = t.moveCursor(delta);
2513 | });
2514 | return success;
2515 | },
2516 | val: function val(newVal) {
2517 | var query;
2518 | if (!arguments.length) {
2519 | ttEach(this.first(), function(t) {
2520 | query = t.getVal();
2521 | });
2522 | return query;
2523 | } else {
2524 | ttEach(this, function(t) {
2525 | t.setVal(_.toStr(newVal));
2526 | });
2527 | return this;
2528 | }
2529 | },
2530 | destroy: function destroy() {
2531 | ttEach(this, function(typeahead, $input) {
2532 | revert($input);
2533 | typeahead.destroy();
2534 | });
2535 | return this;
2536 | }
2537 | };
2538 | $.fn.typeahead = function(method) {
2539 | if (methods[method]) {
2540 | return methods[method].apply(this, [].slice.call(arguments, 1));
2541 | } else {
2542 | return methods.initialize.apply(this, arguments);
2543 | }
2544 | };
2545 | $.fn.typeahead.noConflict = function noConflict() {
2546 | $.fn.typeahead = old;
2547 | return this;
2548 | };
2549 | function ttEach($els, fn) {
2550 | $els.each(function() {
2551 | var $input = $(this), typeahead;
2552 | (typeahead = $input.data(keys.typeahead)) && fn(typeahead, $input);
2553 | });
2554 | }
2555 | function buildHintFromInput($input, www) {
2556 | return $input.clone().addClass(www.classes.hint).removeData().css(www.css.hint).css(getBackgroundStyles($input)).prop("readonly", true).removeAttr("id name placeholder required").attr({
2557 | spellcheck: "false",
2558 | tabindex: -1
2559 | });
2560 | }
2561 | function prepInput($input, www) {
2562 | $input.data(keys.attrs, {
2563 | dir: $input.attr("dir"),
2564 | autocomplete: $input.attr("autocomplete"),
2565 | spellcheck: $input.attr("spellcheck"),
2566 | style: $input.attr("style")
2567 | });
2568 | $input.addClass(www.classes.input).attr({
2569 | spellcheck: false
2570 | });
2571 | try {
2572 | !$input.attr("dir") && $input.attr("dir", "auto");
2573 | } catch (e) {}
2574 | return $input;
2575 | }
2576 | function getBackgroundStyles($el) {
2577 | return {
2578 | backgroundAttachment: $el.css("background-attachment"),
2579 | backgroundClip: $el.css("background-clip"),
2580 | backgroundColor: $el.css("background-color"),
2581 | backgroundImage: $el.css("background-image"),
2582 | backgroundOrigin: $el.css("background-origin"),
2583 | backgroundPosition: $el.css("background-position"),
2584 | backgroundRepeat: $el.css("background-repeat"),
2585 | backgroundSize: $el.css("background-size")
2586 | };
2587 | }
2588 | function revert($input) {
2589 | var www, $wrapper;
2590 | www = $input.data(keys.www);
2591 | $wrapper = $input.parent().filter(www.selectors.wrapper);
2592 | _.each($input.data(keys.attrs), function(val, key) {
2593 | _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val);
2594 | });
2595 | $input.removeData(keys.typeahead).removeData(keys.www).removeData(keys.attr).removeClass(www.classes.input);
2596 | if ($wrapper.length) {
2597 | $input.detach().insertAfter($wrapper);
2598 | $wrapper.remove();
2599 | }
2600 | }
2601 | function $elOrNull(obj) {
2602 | var isValid, $el;
2603 | isValid = _.isJQuery(obj) || _.isElement(obj);
2604 | $el = isValid ? $(obj).first() : [];
2605 | return $el.length ? $el : null;
2606 | }
2607 | })();
2608 | });
--------------------------------------------------------------------------------