The trunk extends many underscores in the Collection
class, so you can get rid of some of these things. Actually, you probably want to inject this into the collection itself as a method, then I would probably look at these keys using the old vintage for
loop, especially if I wanted to break out of it.
// in Backbone.Collection.extend search: function( query, callback ){ var pattern = new RegExp( $.trim( query ).replace( / /gi, '|' ), "i"); var collection = this; collection.each(function(model) { for( k in model.attributes ){ if( model.attributes.hasOwnProperty(k) && pattern.test(model.attributes[k]) ){ callback.call( collection, model, k ); break; // ends the for loop. } } }); } // later collection.search('foo', function( model, attr ){ console.log('found foo in '+model.cid+' attribute '+attr); });
However, this will only return the first match from the collection. You may prefer an implementation that returns an array of results as pairs of [model, attribute].
// in Backbone.Collection.extend search: function( query, callback ){ var matches = []; var pattern = new RegExp( $.trim( query ).replace( / /gi, '|' ), "i"); this.each(function(model) { for( k in model.attributes ){ if( model.attributes.hasOwnProperty(k) && pattern.test(model.attributes[k]) ){ matches.push([model, k]); } } }); callback.call( this, matches ); } // later collection.search('foo', function( matches ){ _.each(matches, function(match){ console.log('found foo in '+match[0].cid+' attribute '+match[1]); }); });
Or, if you need an array of models that match, but don't care about which attribute matches, you can use filter
// in Backbone.Collection.extend search: function( query, callback ){ var pattern = new RegExp( $.trim( query ).replace( / /gi, '|' ), "i"); callback.call( this, this.filter(function( model ){ for( k in model.attributes ){ if( model.attributes.hasOwnProperty(k) && pattern.test(k) ) return true; } })); } // later collection.search('foo', function( matches ){ _.each(matches, function(match){ console.log('found foo in '+match[0].cid+' somewhere'); }); });