GithubHelp home page GithubHelp logo

andreypopp / backbone.projections Goto Github PK

View Code? Open in Web Editor NEW
108.0 7.0 9.0 188 KB

backbone.projections is a set of projections for Backbone.Collection

Home Page: http://andreypopp.com/posts/2013-05-15-projections-for-backbone-collections.html

License: MIT License

JavaScript 42.03% PHP 1.81% CoffeeScript 56.15%

backbone.projections's Introduction

Backbone.Projections

Backbone.Projections is a library of projections for Backbone.Collection.

Projection is a read-only collection which contains some subset of an other underlying collection and stays in sync with it. That means that projection will respond correspondingly to add, remove and other events from an underlying collection.

Currently there are four available projections โ€” Sorted, Reversed, Capped and Filtered.

See blog post for examples and demos.

Usage with Browserify

Install with npm, use with Browserify:

% npm install backbone.projections

and in your code

BackboneProjections = require 'backbone.projections'

Usage with "globals"

Grab a copy of backbone.projections.js which exports BackboneProjections as a global.

Sorted and Reversed

Sorted provides a projection which maintains its own order. You are required to provide a comparator:

{Sorted} = require 'backbone.projections'

collection = new Collection([...])
sorted = new Sorted(collection, comparator: (m) -> m.get('score'))

There's also a special case Reversed which maintains order reversed to an underlying collection order.

{Reversed} = require 'backbone.projections'

collection = new Collection([...])
sorted = new Reversed(collection)

Capped

Capped provides a projection of a limited number of elements from an underlying collection:

{Capped} = require 'backbone.projections'

collection = new Collection([...])
capped = new Capped(collection, cap: 5)

Using cap parameter you can restrict the number of models capped collection will contain. By default this projection tries to maintain the order of models induced by underlying collection but you can also pass custom comparator, for example

topPosts = new Capped(posts,
  cap: 10
  comparator: (post) -> - post.get('likes'))

will create a topPosts collection which will contain first 10 most "liked" posts from underlying posts collection.

Filtered

Filtered provides a projection which contains a subset of models from an underlying collection which match some predicate.

{Filtered} = require 'backbone.projections'

todaysPosts = new Filtered(posts,
  filter: (post) -> post.get('date').isToday())

The example above will create a todaysPosts projection which only contains "today's" posts from the underlying posts collection.

By default this projection tries to maintain the order of models induced by underlying collection but you can also pass custom comparator.

Complex predicates which depend on some changing data

Filtered can be a base for complex projection which includes more than a single collection, as an example we will implement a difference between two collections:

class Difference extends Filtered
  constructor: (underlying, subtrahend, options = {}) ->
    options.filter = (model) -> not subtrahend.contains(model)
    super(underlying, options)
    this.listenTo subtrahend, 'add remove reset', this.update.bind(this)


a = new Model()
b = new Model()
c = new Model()
d = new Model()

underlying = new Collection [a, b, c]
subtrahend = new Collection [b, c, d]

diff = new Difference(underlying, subtrahend)

This way diff will contain only models from underlying which are not members of subtrahend collection and what's more important diff will track changes in subtrahend and update itself accordingly.

But that's a quick'n'dirty way of implementing this because on each change to subtrahend the difference will reexamine entire underlying collection. Let's implement this in a more efficient way:

class EfficientDifference extends Filtered
  constructor: (underlying, subtrahend, options = {}) ->
    options.filter = (model) -> not subtrahend.contains(model)
    super(underlying, options)
    this.listenTo subtrahend,
      add: (model) =>
        this.remove(model) if this.contains(model)
      remove: (model) =>
        this.add(model) if this.underlying.contains(model)
      reset: this.update.bind(this)

Composing projections

You can compose different projection which each other, for example

todaysPosts = new Filtered(posts,
  filter: (post) -> post.get('date').isToday())
topTodaysPosts = new Capped(todaysPosts,
  cap: 5
  comparator: (post) -> - post.get('likes'))

will result in a topTodaysPosts projection which only contains "top 5 most liked posts from today".

backbone.projections's People

Contributors

andreypopp 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

backbone.projections's Issues

Add an Optional Offset to Capped Projections

It would be helpful if the capped projection could also take an additional option specifying how far to offset before returning items. This option would of course default to zero if not provided.

As an example, setting "cap" to 5 and not setting "skip" would have a projection that shows indices 0 - 4, inclusive. Setting "cap" to 5 and "skip" to 2 would show indices 2 - 6, inclusive.

It could be "skip", "offset", or whatever makes the most sense.

Thanks again.

Override underlying functions for CRUD

Hello, I'm sorry if this doesn't make sense for this project or I am asking for a stupidity.

In my use case, I have some views that use a FooCollection or a Filtered FooCollection, the views doesn't know if it is filtered or if it is not.

So since my collections are passed around and as I said they don't know if is FooCollection or the filtered one, when I try to add a model to the collection and the collection is the filtered one, the model will be added to the filtered but not in the underlying.

Could be possible to override "add" for example so when you add a model to the filtered it will just pass the message to the underlying?

Or maybe I'm using this project wrong and if so, is it possible to have a filtered collection but actually filtering nothing? So I can change all my CRUD relying in col.underlying.

On the other hand, thanks for "global" versions and thanks for amazing work.

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.