// Generated by CoffeeScript 1.8.0 (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __slice = [].slice; Backbone.TypeaheadCollection = (function(_super) { __extends(TypeaheadCollection, _super); function TypeaheadCollection() { return TypeaheadCollection.__super__.constructor.apply(this, arguments); } TypeaheadCollection.prototype._tokenize = function(s) { s = $.trim(s); if (s.length === 0) { return null; } return s.toLowerCase().split(/[\s\-_]+/); }; /* Recursive method for walking an object as defined by an array. Returns the value of the last key in the array sequence. @private @method _deepObjectMap @param {Object} Object to walk @param {Array} Keys to walk the object with @return {Value} Last value from the object by array walk @example _deepObjectMap key: key2: key3: "val" , ['key', 'key2', 'key3'] * Returns "val" */ TypeaheadCollection.prototype._deepObjectMap = function(obj, attrs) { if (!(attrs.length > 0 && _.isObject(obj))) { return obj; } if (attrs.length === 1) { return obj[attrs[0]]; } return this._deepObjectMap(obj[attrs[0]], attrs.slice(1, attrs.length)); }; /* Split each typeaheadAttribute into an array of nested methods and return an array map the returned values from deepObjectMap. @private @method _getAttributeValues @param {Backbone.Model} Model to fetch and map values from @return {Array} Values from model retrieved by _deepObjectMap */ TypeaheadCollection.prototype._getAttributeValues = function(model) { return _.map(this.typeaheadAttributes, (function(_this) { return function(att) { var attArray; attArray = att.split('.'); return _this._deepObjectMap(model.get(attArray[0]), attArray.slice(1)); }; })(this)); }; TypeaheadCollection.prototype._extractValues = function(model) { if (this.typeaheadAttributes != null) { return this._getAttributeValues(model); } else { return _.values(model.attributes); } }; TypeaheadCollection.prototype._tokenizeModel = function(model) { return _.uniq(this._tokenize(_.flatten(this._extractValues(model)).join(' '))); }; TypeaheadCollection.prototype._addToIndex = function(models) { var adjacency, character, id, model, t, tokens, _i, _len, _results; if (!_.isArray(models)) { models = [models]; } _results = []; for (_i = 0, _len = models.length; _i < _len; _i++) { model = models[_i]; tokens = this._tokenizeModel(model); id = model.id != null ? model.id : model.cid; this._tokens[id] = tokens; _results.push((function() { var _base, _j, _len1, _results1; _results1 = []; for (_j = 0, _len1 = tokens.length; _j < _len1; _j++) { t = tokens[_j]; character = t.charAt(0); adjacency = (_base = this._adjacency)[character] || (_base[character] = [id]); if (!~_.indexOf(adjacency, id)) { _results1.push(adjacency.push(id)); } else { _results1.push(void 0); } } return _results1; }).call(this)); } return _results; }; TypeaheadCollection.prototype._removeFromIndex = function(models) { var id, ids, k, v, _i, _len, _ref, _results; if (!_.isArray(models)) { models = [models]; } ids = _.map(models, function(m) { if (m.id != null) { return m.id; } else { return m.cid; } }); for (_i = 0, _len = ids.length; _i < _len; _i++) { id = ids[_i]; delete this._tokens[id]; } _ref = this._adjacency; _results = []; for (k in _ref) { v = _ref[k]; _results.push(this._adjacency[k] = _.without.apply(_, [v].concat(__slice.call(ids)))); } return _results; }; TypeaheadCollection.prototype._rebuildIndex = function() { this._adjacency = {}; this._tokens = {}; return this._addToIndex(this.models); }; TypeaheadCollection.prototype.typeaheadIndexer = function(facets) { if (!((facets != null) && _.keys(facets).length > 0)) { return null; } return _.map(this.where(facets), function(m) { if (m.id != null) { return m.id; } else { return m.cid; } }); }; TypeaheadCollection.prototype.typeahead = function(query, facets) { var checkIfShortestList, facetList, firstChars, id, isCandidate, isMatch, item, lists, queryTokens, shortestList, suggestions, _i, _len; if (this._adjacency == null) { throw new Error('Index is not built'); } queryTokens = this._tokenize(query); lists = []; shortestList = null; firstChars = _(queryTokens).chain().map(function(t) { return t.charAt(0); }).uniq().value(); checkIfShortestList = (function(_this) { return function(list) { if (list.length < ((shortestList != null ? shortestList.length : void 0) || _this.length)) { return shortestList = list; } }; })(this); _.all(firstChars, (function(_this) { return function(firstChar) { var list; list = _this._adjacency[firstChar]; if (list == null) { return false; } lists.push(list); checkIfShortestList(list); return true; }; })(this)); if (lists.length < firstChars.length) { return []; } facetList = this.typeaheadIndexer(facets); if (facetList != null) { lists.push(facetList); checkIfShortestList(facetList); } if (shortestList == null) { return this.models; } if (shortestList.length === 0) { return []; } suggestions = []; for (_i = 0, _len = shortestList.length; _i < _len; _i++) { id = shortestList[_i]; isCandidate = _.every(lists, function(list) { return ~_.indexOf(list, id); }); isMatch = isCandidate && _.every(queryTokens, (function(_this) { return function(qt) { return _.some(_this._tokens[id], function(t) { return t.indexOf(qt) === 0; }); }; })(this)); if (isMatch) { item = this.get(id); if (this.typeaheadPreserveOrder) { suggestions[this.indexOf(item)] = item; } else { suggestions.push(item); } } } if (this.typeaheadPreserveOrder) { return _.compact(suggestions); } else { return suggestions; } }; TypeaheadCollection.prototype._reset = function() { this._tokens = {}; this._adjacency = {}; return TypeaheadCollection.__super__._reset.apply(this, arguments); }; TypeaheadCollection.prototype.set = function() { var models; models = TypeaheadCollection.__super__.set.apply(this, arguments); if (!_.isArray(models)) { models = [models]; } this._rebuildIndex(models); return models; }; TypeaheadCollection.prototype.remove = function() { var models; models = TypeaheadCollection.__super__.remove.apply(this, arguments); if (!_.isArray(models)) { models = [models]; } this._removeFromIndex(models); return models; }; TypeaheadCollection.prototype._onModelEvent = function(event, model, collection, options) { var add; add = false; if (event === ("change:" + model.idAttribute)) { add = true; this._removeFromIndex({ id: model.previous(model.idAttribute) }); } else if (event.indexOf('change:') === 0) { if ((this.typeaheadAttributes == null) || _.indexOf(_.map(this.typeaheadAttributes, function(att) { return 'change:' + att; }), event) >= 0) { add = true; this._removeFromIndex(model); } } if (add) { this._addToIndex(model); } return TypeaheadCollection.__super__._onModelEvent.apply(this, arguments); }; return TypeaheadCollection; })(Backbone.Collection); }).call(this); //# sourceMappingURL=backbone.typeahead.js.map