Code Monkey home page Code Monkey logo

backbone.augment's People

Contributors

jsoverson avatar

Stargazers

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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

backbone.augment's Issues

Mixing components with a facade / Making mixInto's methodNames argument optional

I was reading @derickbailey's blog post on mixins on los techies (http://lostechies.com/derickbailey/2012/10/07/javascript-mixins-beyond-simple-object-extension/) where he sugested a handy way of mixing a component into a target object: https://gist.github.com/3847156#file_5.js

While I liked the idea, I thought it might become tedious to have to define which properties should and should not be mixed into the target object.

I can imagine a scenario where you might design components specifically with the intention to mix them into other objects. An example of this might be Backbone.EventBinder. In this case, the designer of the component has a very clear idea of which methods and/or properties should be mixed into the target object, and which should not.

I think it would be easier to create a facade, containing only the methods and properties you want to mix into the target object, while keeping the internals of the component private.

This way @derickbailey's gist could still take a target, and a source, but you would no longer need to explicitly list the method names you want to mix into the target. Instead the source's facade already contains only the methods you want to mix in. It would then be desirable to make the methodNames argument(s) optional:

// build a mixin function to take a target that receives the mixin, 
// a source that is the mixin, and a list of methods / attributes to
// copy over to the target

function mixInto(target, source, methodNames){

  // ignore the actual args list and build from arguments so we can
  // be sure to get all of the method names
  var args = Array.prototype.slice.apply(arguments);
  target = args.shift();
  source = args.shift();
  methodNames = args;

  // builds a function with a closure around the source
  // and forwards the method call to the source, passing
  // along the method parameters and setting the context
  var mixMethod = function(target, source, method) {
    target[method] = function(){
      var args = Array.prototype.slice(arguments);
      source[method].apply(source, args);
    }
  }

  // if any method names are supplied, only those methods should be
  // mixed into the target
  if(methodNames.length) {
    var length = methodNames.length;
    for(var i = 0; i < length; i++){
      mixMethod(target, source, methodNames[i]);
    }
  }
  // if no method names are supplied, all properties of the source
  // should be mixed into the target (leaving it upto the source
  // to expose it's public api)
  else {
    for(var method in source) {
      if(source.hasOwnProperty(method) && typeof source[method] === 'function') {
        mixMethod(target, source, method);
      }
    }
  }
}

Augmenting With Object Instances / Lifecycle Augments

All of the examples I've built, and the ones I see in the docs, assume an object literal for the augmenting object. What about object instances? How would we get an object like Backbone.EventBinder to mix an instance of itself in to a Backbone.View?

I think if we look at the augmenting object as an adapter this might work:

eventBinderAug = {

  augment: function(target){
    _.wrap(target.constructor, function(original, options){

      var eventBinder = new Backbone.EventBinder();
      Backbone.Augment.mixInto(this, eventBinder, "bindTo", "unbindFrom", "unbindAll");

      original(options);
    });
  }

};

MyView = Backbone.View.extend({});
MyView.augment(eventBinderAug);

What I really want to do, is have a way to use an existing constructor function as an augmenter for each instance of the target... which this does... but is this the best way to make this happen? It seems like it might be a bit cumbersome to do it this way.

Is there something we can do to make this easier?

One idea I had was to provide a way to hook in to the lifecycle of a given object.

eventBinderAug = {

  augment: {

     // fires during the construction of the target
    constructor: function(target, options){

      target.eventBinder = new Backbone.EventBinder();
      Backbone.Augment.mixInto(target, target.eventBinder, "bindTo, "unbindFrom", "unbindAll");

    },

    // fires just before the `initialize` function of the target
    initialize: function(options){
      // ...
    }

  }

};

MyView = Backbone.View.extend({});
MyView.augment(eventBinderAug);

var v = new MyView();
v.bindTo( ... );

When the augment is set up, it would override the specified functions of the target object to run the augment's function as well as the original target's function. So the end result would look something like this:

for (var method in augment){
  if (augment.hasOwnProperty(method){

    _.wrap(target[method], function(original, options){
      augment[method].call(augment, target, options);
      original(options);
    }

  }
}

This hack wouldn't really work for all the types of objects we can augment, but it should get the idea across, I think.

The intent is that we should be able to augment Backbone types and provide methods like constructor, initialize, dispose and even render or other methods that we want, without forcing the person writing the augmentation to have to call the whole Backbone.Whatever.prototype.method chain.

This would solve the problem of augmenting instances with instances, and also give a lot of value in the ability to augment the lifecycle and existing methods of a backbone object type.

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.