Backbone extends a lot of the underscore methods into the Collection class so you can get rid of some of that stuff. Really you probably want to impliment this on the collection itself as a method, then I would probably look at those keys using a good old fashioned 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);
});
That said, this would only ever return the first match from the collection. You may prefer an implementation that returns an array of results as [model, attribute] pairs.
// 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 wanted an array of models which matched but don't care which attribute matched 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');
});
});