Giter VIP home page Giter VIP logo

filtered-collection's Introduction

Filtered Collection

Build Status

This is a simple filtered collection implemented using Backbone.Collection. The goal here is to create a collection which, given a filter function, will just contain elements of the original which pass the filter. Supports add/remove/reset events of the original to modify the filtered version.

Why not just extend backbone?

The main reason I did not just extend backbone is because by extending it, you shove all behaviors into one model, making it a jack-of-all-trades and potentially conflicting with behaviors of other extentions, not to mention making normal operaitons potentially slower. So the intention is to compose a filter chain pattern using these guys.

Installation to rails

With bundler

gem 'backbone-filtered-collection'

Inside your sprockets file:

//= require backbone-filtered-collection

Installation anywhere else

Download the source, minify as you see fit by your minification strategy.

Usage

var YourCollection = Backbone.Collection.extend({model: YourModel});
var YourFilteredCollection = Backbone.FilteredCollection.extend({model: YourModel});

var allItems = new YourCollection(...);

// note the null, backbone collections want the pre-populated model here
// we can't do that since this collection does not accept mutations, it
// only mutates as a proxy for the underlying collection
var filteredItems = new YourFilteredCollection(null, {collection: allItems});

var filteredItems.setFilter(function(item) { return item.get('included') == true;});

And now filteredItems contains only those items that pass the filter. You can still manipulate the original:

allItems.add(..., {at: 5}); // at is supported too...

However, if you invoke {silent: true} on the original model, then you must reset the filter by invoking:

filteredItems.setFilter(); // no args = just re-filter

Same goes for remove and reset.

To clear the filtering completely, pass the value false to setFilter.

Filters

  • setFilter(function() {}): Set the given function as the filter. Same api as _.each.
  • setFilter(false): Turn filtering off. This collection will have all elements of the original collection.
  • setFilter(): Re-filter. Don't change the filter function but execute it on all elements. Useful after the original collection was modified via silent: true

Events

The collection will create events much like a regular collection. There are a few to note:

  • add: An object was added to the collection (via filter OR via orig collection)
  • remove: An object was removed from the collection (via filter OR via orig collection)
  • reset: The original collection was reset, filtering happened
  • sort: The collection was sorted. No changes in models represented.
  • change: An object in the collection was changed. The object was already accepted by the filter, and is still.
  • filter-complete: Filtering was completed. If you are not listening to add/remove then just listen to filter-complete and reset your views.

Change Collection

You can change the underlying collection if you really need to by invoking #resetWith(newCollection), only one reset event will be triggered with the new data.

Testing

bundle install
rake jasmine

I also included a .rvmrc file incase you have rvm installed.

Contributing

Please, do not contribute without a spec. Being tested is critically important to this project, as it's a framework level component, and so its failure will be damn hard to detect.

Also, no tab characters, 2 spaces only. Minifiers can handle this stuff for you.

filtered-collection's People

Contributors

calamari avatar dlikhten avatar facundocabrera avatar jorgenfb avatar justinabrahms avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

filtered-collection's Issues

Possible issue with inherited _onModelEvent

Just started using this, and I've been seeing an exception thrown where if model.destroy() is called, the "destroy" event triggers _onModelEvent on both the original Collection and on the FilteredCollection. When it's called on the FilteredCollection, it attempts to call this.remove(...), which is made to throw "Do not invoke directly." By copying in the functionality of _onModelEvent, without the clause that calls this.remove(...), everything seems to work fine.

In essence, the FilteredCollection is getting told to remove each model twice: from the model itself via a "destroy" event, and from the original collection's "remove" event.

I'll need to isolate a test case first (I'm using the Parse.com version of Backbone, so I'm not 100% sure that this is a bug in FilteredCollection), but thought I'd submit the issue to track it.

#setFilter is a terrible API. Change it.

I was reading the readme, and realized how shitty of an API setFilter is.

Desired behavior:

#setFilter(filter) -- set the filter to the given function. Cannot be falsy.
#clearFilter() -- clear the filter
#refilter() -- execute the filter. Do not change the filter function

Since people are using this tool, please weigh in. I'd like to improve the API if possible.

Render my view collection before filter.

Hi, i have a problem with this great code, excuse me my ignorance, but when override setFilter with this
filteredItems.setFilter(function(item){
return item.get('nt') == 'Travesía' ? true : false;
});

and then call the filter and render
filteredItems.setFilter();
$("#content").html(new EventListView({model: filteredItems, page: 1}).el);

The execution flow is:
first render and then execute return item.get('nt') == 'Travesía' ? true : false;

I dont underenstand because happen this.

Convert to Gem

Converted into a gem, in addition to having a bit more structure, this would be easily importable into a rails app.

Better support for sort

A backbone sort event indicates no model changes occurred. This code could be more efficient at handling such an event without actually re-filtering, thus making overall app performance better (in theory)

newModels = [];
newMapping = [];
_.each(this.originalCollection.models, function(model, index) {
    if (this.models.indexOf(model) >= 0) { // did you pass the filter?
      newModels.push(model); // add the model in the exact order it is in the original model
      newMapping.push(index);
    }
});
this.models = newModels;
this.newMapping = newMappings;
this.trigger("sort", this);

Need an event which signifies that filtering is complete

This is really useful if there does not exist an ability to individually add or remove elements to/from the rendered view. Instead if the rendered view must re-render everything, it is a bad idea to bind to add/remove events. Instead we should have a single event indicating that all filtering is done (that we know of).

Note: add/remove events should not trigger this, they indicate an element was added/removed. However if the underlying collection is a filtered collection, it should propagate the event. This way even though many individual elements may be added/removed, a single filter-complete event can occur.

Adding version number

Is it possible that you could include a version number on your next update. I ran into some problems with the older version of the plugin and didn't realize that I wasn't working on the most current version until reading through the code to see the differences.

Filtering should be efficient with add and remove events

Filtering should pay attention to add/remove events closely.

  • Apply filtering to just the new element (on add) and insert it propperly.
  • A removed element should just be removed without any new filtering going on (if it is already filtered out).
  • A single Add/Remove should not reset the entire collection.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.