You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			286 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			JavaScript
		
	
			
		
		
	
	
			286 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			JavaScript
		
	
| // 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
 |