Knockback-Inspector for Backbone.Models and Backbone.Collections

It has been a while since I last posted, but I have some news!

After releasing Knockback 0.15.1, I wanted to show how easy it is to generate and render Backbone.Model and Backbone.Collection graphs…just the sort of thing you need to render relationships when you use Backbone-Relational.

So after creating an inspector library and accompanying tutorial, I would like to announce Knockback-Inspector 0.1.0.

What it allows you to do is embed a tree view in your application to inspect and edit JSON data that you store in your models and collection…think of it as a light debugger. Here is an example of what it can do:

Download Knockback-Inspector now (Right-click, and use “Save As”):

Enjoy!

Response to UI Technology Paradigm Shift by Paul Hammant

Before writing his post, Paul and I briefly spoke about the “state of union” given the proliferation of MVC/MVVM client-side micro frameworks. He raises some important points in his post posting and it is a good read to complement this MVC frameworks comparison table.

When we spoke, Paul quite rightly raised the key risk today being that the number of frameworks is likely to continue to grow and each one may end up taking the best features from the others while reimplementing them in their own way causing further fragmentation. 
 
What this means to me is that:
  • we will end up with a too many frameworks with brilliant pieces and also not so brilliant pieces, but we will be forced to take the good with the bad rather than just take the good (if you’ve looked at Sproutcore 1.x, you know we are all fortunate that Yehuda Katz was involved with Ember/Sproutcore 2.0)
  • programmers will need to jump from framework to framework whenever they change projects that have chosen yet another, slightly different MVC/MVVM framework until things consolidate. As each framework grows, their communities will need to devote more time to not only help programmers up the learning curve, but also to explain common solutions and best practices given their specific framework (Knockout is amazing at this by the way!)
I believe we need to step back a little further and look at what is going on and what we need.
 
What’s going on? Well, innovation obviously! We are in the middle of a (client side) Javascript and Coffeescript Renaissance and we’re lucky enough to be standing on the shoulders of giants while applying new techniques to make even more interactive client side applications (and HTML5/CSS3 isn’t so bad either!).

But what do we need? I believe we need to have the flexibly to pick and choose. Some personal examples:
  • Backbone’s Models and Collections are really quick and intuitive to learn, but their View (or partial-Controller) implementation is quite limited. Combining Backbone with Knockout into Knockback allowed me to iterate quickly and make beautiful, dynamic Views (easily using multiple Backbone models per View) with a templating engine that I was comfortable with.
  • jQuery Mobile’s default approach is a page per screen so they implement history and screen transitions as part of their framework. I originally chose JQM hoping that their Themeroller would be great for a designer, but each new release required me to disable more of their code to quickly get a single page app working again

So how do we pick and choose? I like Rails 3 modularity and believe it should be used for inspiration. Do we need modules like Active Resource, Action Contoller, Rack middleware-compliance, etc? Do we use CommonJS/RequireJS/AMD, a nano-framework framework like Mixin, or just use conventions? 

Maybe we just need to agree on the components for a good client side app and allow for different configurable distributions like Brunch?

I believe development teams should be able to make choices like between Pathjs or Backbone Routers for history/routing, eco or Mustache for templates, Backbone or Spline models, Backbone Views or a binding library like Knockout, Sprockets or Brunch for asset packaging, Less or SCSS or CSS for stylesheets, etc.

And if something better comes along, taking a modular approach now should make it easier to replace a single component and its touch-points rather than being forced into an “all of nothing” decision down the line (which is almost never a good thing!).

Best of all, rather than make a huge upfront MVC framework decision you can incrementally and iteratively choose the best available modules for whatever will make your client side application standout and be incredible!

To put my money where my mouth is…I would welcome a larger community like from Backbone to reverse-takeover Knockback and make it into a standard (but separate!) Backbone Model adapter library for different binding libraries like Angular, Batman, or something new (but not in the Backbone Model/Collection core). 
Alternatively, split Backbone into 3 modules: 1) Routing (Routers/History), 2) ORM (Models/Collections), and 3) Controller (View). Then, request proposals from the community for a replacement for the Controller (View) module (or even consider deprecating it) because with all of the recent innovations in the MVC space, there are already much better ways to do it.
Tear down these walls!

Knockback website is live!

Knockback is starting to take off so it was about time to have a proper website and here it is: http://kmalakoff.github.com/knockback/

There is a great comparison table to explain how Backbone, Knockout, and Knockback shine together as a complete MVVM solution. A big thank you to  Pier Paolo Ramon for all his hard work to make this site so informative and slick!

Also, be sure to check out the documentation:

  1. Knockback repository
  2. Knockout-Todos repository

And the demos:

  1. Knockback-Todos
  2. jsfiddle

Download Knockback.js now (Right-click, and use “Save As”):

Knockback.js works with both Knockout1.2.1 and Knockout1.3

Enjoy!

Kevin

Knockback Todos Demo

I’ve put together a demo of Knockback using the obligatory todo app…with a twist!

I didn’t want to do just a simple technical display of coolness, but something a little more real world. Until we get a proper Knockback website up and running, check out the github page and the three demos:

  1. Todos Classic - a minimal version of the todo
  2. Todos - a version that shows off the power of Knockback: live changes synchronized across views, localization from day one, dynamic list sorting, etc
  3. Todos Mockup - this is where I started with the concept. It isn’t interactive, but is a good resource for understanding the architecture of a Knockback app without having to get into any framework implementation details.

Try it live: http://kmalakoff.github.com/knockback-todos

You can find this example and more here: https://github.com/kmalakoff/knockback and here: https://github.com/kmalakoff/knockback-todos

Download Knockback.js now (Right-click, and use “Save As”):

Knockback.js works with both Knockout1.2.1 and Knockout1.3

Backbone.ModelRef: A small library for lazy Backbone models

OK. This is a little smaller of a library than usual, but still useful! 

I’ve made a small Backbone.ModelRef class which stores a collection and model id, and notifies you when it is loaded and unloaded using bindable Backbone.Events: ‘loaded’ and ‘unloaded’.

Example: A view with states depending on the model being loaded or not

  class MyView extends Backbone.View
    constructor: (@model_ref) ->
      super; _.bindAll(this, 'render', 'renderWaiting')
      @model_ref.bind('loaded', @render); @model_ref.bind('unloaded', @renderWaiting)
      if @model_ref.isLoaded() then @render() else @renderWaiting()

    render: -> @is_waiting = false
    renderWaiting: -> @is_waiting = true

  collection = new MyCollection()
  view = new MyView(new Backbone.ModelRef(collection, 'dog'))
  # view is now rendering in waiting state

  collection.add(collection.parse([{id: 'dog'}]))
  # view is now rendering in loaded state

  collection.reset()
  # view is now rendering in waiting state

Personal Use: I use this often because my web site my have a URL like “{host}/models/2” and if you refresh the page, the model isn’t loaded yet (and it may never load if the model has been deleted). Rather than waiting or writing some custom code for each view, I have two states for my model views with loading messages while waiting and timeouts for when the load fails (using “Mixin.Timeouts” from: Mixin.js).  

Also, Backbone.ModelRef is supported by Knockback.js (Knockback.js and this blog post) so if you like, you can set default values in fields while you wait.

You can find this example and more here: https://github.com/kmalakoff/backbone-modelref

Download now (Right-click, and use “Save As”):

Knockback.js: You got your Knockout in my Backbone

I’m really excited about releasing this. Knockback.js provides Backbone model and collection bindings for Knockout.

This means you can now put different views of the same models on your web page and they can automatically update…one or two way, and localization is a breeze. Take a look at this jsFiddle: http://jsfiddle.net/kmalakoff/QSkpv/ and you can see:

  • it dynamically localizes all the labels and event the text inputs
  • it dynamically sorts the model views based on the sortedIndex function 
  • all changes in a model are updated in real time using Knockout bindings

Example: A simple model attributes binding

  The view model:

    ContactViewModel = (model) ->
      kb.observables(model, {
        name:     {key:'name'}
        email:    {key:'email', write: true, default: 'your.name@yourplace.com'}
        date:     {key:'date', write: true, localizer: LongDateLocalizer}
      }, this)

  The HTML:

    <label>Name: </label><input data-bind="value: name" />
    <label>Email: </label><input data-bind="value: email" />
    <label>Birthdate: </label><input data-bind="value: date" />

  And...engage:

    view_model = new ContactViewModel(collection.get('some_id'))
    ko.applyBindings(view_model)


You can find this example and more here: https://github.com/kmalakoff/knockback 

Download now (Right-click, and use “Save As”):

Knockback.js works with both Knockout1.2.1 and Knockout1.3

(Source: kmalakoff.github.com)

Mixin.js: Example for writing your own mixins

I realized that all the mixin examples were about how to use existing mixins…not write your own! There are a couple of things to know.

First, you use Mixin.registerMixin with an object providing your mixin name, the object to mixin, and optionally an initialize and/or destroy method. For example: Mixin.registerMixin({mixin_name: ‘MyMixin’, mixin_object: {myFunction: ->}})

Second, you can create and access instance data per mixed in instance using a dual-purpose function Mixin.instanceData. Set the data with Mixin.instanceData(instance, ‘MyMixin’, SOMETHING) and get the data with Mixin.instanceData(instance, ‘MyMixin’).

Example: Create Your Own Mixin

# define a new mixin for a superstar with fans
Mixin.registerMixin({
  mixin_name: 'Superstar'

  initialize: ->
    # create instance data with an array of fans
    Mixin.instanceData(this, 'Superstar', {fans: []})

  mixin_object: {
    addFan: (fan) ->
      # get the instance data, and add the fan to the fans array
      Mixin.instanceData(this, 'Superstar').fans.push(fan)
      return this # allow chaining
    getFans: ->
      return Mixin.instanceData(this, 'Superstar').fans
  }
})

# make rockstar1 a superstar
class Rockstar
rockstar1 = new Rockstar()
Mixin.in(rockstar1, 'Superstar')

# create new fans of rockstar1
class Fan
fan1 = new Fan(); fan2 = new Fan()
rockstar1.addFan(fan1).addFan(fan2)

# fan1 now becomes a superstar and rockstar1 loses his status
Mixin.in(fan1, 'Superstar'); Mixin.out(rockstar1, 'Superstar')

# now everyone becomes a fan of fan1 (even rockstar1!)
fan1.addFan(fan2).addFan(rockstar1)

# cleanup after the new 'Superstar' (he doesn't do anything for himself anymore)
Mixin.out(fan1)

You can find this example and more here: https://github.com/kmalakoff/examples-kmalakoff

If you try out Mixin.js, please share your stories and your mixins!

Download now (Right-click, and use “Save As”):

Underscore-Awesomer: _.parseJSON for CouchDB model

This is an example showing a recent modification to _.parseJSON. Besides introducing a convention for serializing plain-old-JSON (POJ) into live instances, what I wanted to do was 1) introduce some flexibility into which field is used to look up the parseJSON methods, and 2) provide a way to not pollute the global namespace with your parseJSON methods.

# set up for CouchDB 'type' convention 
_.PARSE_JSON_TYPE_FIELD = 'type'
# make a Constructors namespace known to Underscore
root = this; root.Constructors||root.Constructors={}
_.PARSE_JSON_CONSTRUCTOR_ROOTS.push(root.Constructors)

class SomeModel
  constructor: (@key, @value) ->
  toJSON = -> return { type:'some_model', key:this.key, value:this.value }
  @parseJSON = (json) ->
    throw new Error('unexpected type') if (json.type!='some_model')
    return new SomeModel(json.key, json.value)
root.Constructors.some_model = SomeModel # add constructor to Constructors namespace

# assume this comes back from the server
json = {type:'some_model', key:'abcdef', value: {x:1, y:2, z:3} }

# deserialize - _.parseJSON finds 'root.Constructors.some_model'
some_model_instance = _.parseJSON(json)

Personal uses: Using my Backbone-Articulation.js library (Backbone-Articulation.js), I now automatically serialize the JSON from the server into instances inside my model attributes on the client. It means I am able to combine data with functionality on the client behind-the-scenes and just start interacting with the attributes directly.

You can find this example and more here: https://github.com/kmalakoff/examples-kmalakoff

Enjoy!

Download now (Right-click, and use “Save As”):

Or check out the project here: https://github.com/kmalakoff/underscore-awesomer

Background.js: Multiple array iteration example

I realized that there weren’t any Background.js examples on the blog. That’s changing today!

queue = new Background.JobQueue(10) # create a queue that processes each 10 milliseconds
iterator = null  # declare the iterator here so it is available in the init and run loop
test_array1 = [3,7,11]; test_array2 = [3,5]; test_array3 = [13,3,23]
iteration_count = 0; result = 0

queue.push(
  (->
    # set up the iterator for the arrays in batches of 3
    iterator = new Background.ArrayIterator_xN([test_array1,test_array2,test_array3],3)
  ),
  (->
    iteration_count++
    return iterator.nextByItems((items)-> result += items[0]*items[1]*items[2])
  )
)

This example shows how you can iterate over the combinations of items in any number of arrays in equal-sized steps and when the job is done, it comes off the queue and if there is one, the next job runs (Note: you could just as easily use a Background.JobList and run multiple jobs in parallel if sequential processing isn’t important to you).

Personal uses: I used something similar to apply identical filters to a collection of models and then rendered the results in batches in a second job that was executed after the filtering job was complete. Also, any time a new filter arrived I used JobContainer.clear() to immediately clear the previous jobs and to start again rather than queuing more jobs since the original jobs were now out-of-date. 

You can find this example and more here: https://github.com/kmalakoff/examples-kmalakoff

Enjoy!

Download now (Right-click, and use “Save As”):

Or check out the project here: https://github.com/kmalakoff/background

Mixin.js - Subscriptions example

I’ve tried to come up with a simple example demonstrating the Mixin.Subscriptions mixin and also the dynamic nature of mixins. Hopefully this hits the nail on the head!

class DynamicBroadcasterListener
  constructor: ->
    Mixin.in(this, ['RefCount', => Mixin.out(this)])
    @sent = []; @unsent = []; @received = [];

  sendUpdate: ->
    args = Array.prototype.slice.call(arguments)
    if Mixin.hasMixin(this, 'Observable') and @hasSubscription('update')
      @notifySubscribers.apply(this, ['update'].concat(args))
      @sent.push(args)
    else
      @unsent.push(args)

  receiveUpdate: ->
    @received.push(Array.prototype.slice.call(arguments))

# create two dynamic/flexible instances and then make one Observable and the other both
dynamic1 = new DynamicBroadcasterListener()
Mixin.in(dynamic1, 'Observable', 'update')
dynamic2 = new DynamicBroadcasterListener()
Mixin.in(dynamic2, 'ObservableSubscriber')
dynamic1.addSubscriber(dynamic2, 'update', dynamic2.receiveUpdate)

# broadcast something and then unmix Observability, send something else (which is unsent)
dynamic1.sendUpdate('Hello')
Mixin.out(dynamic1, 'Observable') # remove Observable and clear all subscribers
dynamic1.sendUpdate('Insane') # not mixed in so will be unsent

# remix, reconfigure and send something new
Mixin.in(dynamic1, 'Observable', 'update')
dynamic1.sendUpdate('Strange and Crazy') # no one subscribed but still sent
dynamic1.addSubscriber(dynamic2, 'update', dynamic2.receiveUpdate)
dynamic1.sendUpdate('World!')

You can find this example and more here: https://github.com/kmalakoff/examples-kmalakoff

If you try out Mixin.js, please share your stories and your mixins!

Download now (Right-click, and use “Save As”):