GithubHelp home page GithubHelp logo

cocktail's Introduction

Cocktail

Break out your shared Backbone.js model/collection/view behaviors into separate modules and mix them into your classes with Cocktail - an implementation of Backbone mixins.

Concocting Mixins

Mixins are simply bare-bones JavaScript objects that provide additional functionality to your Backbone objects. Think of them as bags of methods that will get added to all instances of your objects.

Here's an example mixin that implements selectability on a view based on a model's selection state:

window.MyMixins = {};

MyMixins.SelectMixin = {
  initialize: function() {
    this.model.on('change:selected', this.refreshSelect, this);
  },

  events: {
    click: 'toggleSelect'
  },

  render: function() {
    this.refreshSelect();
  },

  refreshSelect: function() {
    this.$el.toggleClass('selected', this.model.get('selected'));
  },

  toggleSelect: function() {
    this.model.set('selected', !this.model.get('selected'));
  }
}

As you can see: nothing special, just a bag of functions.

Obviously, the bit about window.MyMixins is just a suggested pattern for organizing your mixins!

And, yes, having models know about view state like selection is often an anti-pattern... but it makes for a simple intelligible example!

Mixing Mixins In

Once you have your mixins defin;;ed including them in your Backbone object definitions is a one-liner:

var MyView = Backbone.View.extend({

  mixins: [MyMixins.SelectMixin, MyMixins.SomeOtherMixin],

  events: {
    'click .myChild': 'myCustomHandler'
  }

  initialize: function() {
    ...
  },

  render: function() {
    ...
  },

  etc...
});

Now all instances of MyView will have the selection behavior defined in the SelectMixin:

var view = new MyView(...);
view.toggleSelect(); //works!

But What About Collisions?

In the example above, both MyView and SelectMixin both defined initialize, and render. What happens with these colliding methods?

Cocktail automatically ensures that methods defined in your mixins do not obliterate the corresponding methods in your classes. This is accomplished by wrapping all colliding methods into a new method that is then assigned to the final composite object.

How are colliding functions called?

Let's take a concrete example. Class X implements render and mixes in mixins A, B, and C (in that order). Of these only A and C implement render.

When render is called on instances of X the implementation of render in X is called first, followed by the implementation in A and then C. In this way the original implementation is always called first, followed by the mixins.

What are the return values from colliding functions?

The return value of the composite function is the last non-undefined return value from the chain of colliding functions.

To be clear: let's say X mixes in A and B. Say X implements a method foo that returns bar, A implements foo but returns nothing (i.e. undefined is implicitly returned) and B implements baz. Then instances of X will return baz -- the last non-undefined return value from foo's X โ†’ A โ†’ B collision chain.

And how about that events hash?

The events hash is special-cased by Cocktail. Mixins can define new events hashes. The set of event hashes (original implementation + each mixin) are merged together.

Note that key-collisions are still possible. If two mixins add a click handler to the events hash ({'click': ... }) then the last mixin in the mixins list's event handler will win.

And what about subclasses?

Subclass hierarchies with mixins should work just fine. If a super class mixes in a mixin, then all subclasses will inherit that mixin. If those subclasses mixin additional mixins, those mixins will be folded in to the subclasses and collisions will be handled correctly, even collisions with methods further up the class hierarchy.

However, if a subclass redefines a method that is provided by a mixin of the super class, the mixin's implementation will not be called. This shouldn't be surprising: the subclass's method is further up in the prototype chain and is the method that gets evaluated. In these circumstance you must remember to call SubClass.__super__.theMethod.apply(this) to ensure that the mixin's method gets called.

Testing Mixins

The example directory includes an example mixin and its usage, and the accompanying Jasmine test. It also includes a readme that walks through the testing pattern employed for testing mixins with Jasmine.

Dependencies and "Installation"

Cocktail requires:

To use Cocktail you must include Cocktail.js it after including Underscore and Backbone. Cocktail monkey-patches backbone's extend!

Future changes to backbone could break Cocktail or obviate its need. If the latter happens - great! If the former: let me know and I'll try to ensure compatibility going forward.

If you like Cocktail...

...check out Coccyx. Coccyx helps you plug up backbone leaks with two things: named constructors and tear-downable view hierarchies.

cocktail's People

Contributors

onsi avatar teleological avatar

Watchers

James Cloos avatar

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.