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”):

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”):

Mixin.js: View with model loading timeout

I’m still excited about finally releasing Mixin.js yesterday…and hope other people find it as exciting as me!

I’ve started a repository with examples from my various project (https://github.com/kmalakoff/examples-kmalakoff) and added the following first example for Mixin.js.

class ViewWithModelLoadingTimeout
  constructor: ->
    Mixin.in(this, ['RefCount', => Mixin.out(this)], 'AutoMemory', 'Timeouts')
    @id = _.uniqueId('model_view')
    @el = $("<div id='#{@id}' class='model_loading'></div>").appendTo($('body'))[0]
    @autoWrappedProperty('el', 'remove')
    @addTimeout('Waiting for Model', (=>@render(false)), 20)

  render: (successful_load) ->
    $(@el).remove()
    if successful_load
      @el = $("<div id='#{@id}' class='model_loaded'></div>").appendTo($('body'))[0]
    else
      @el = $("<div id='#{@id}' class='model_failed'></div>").appendTo($('body'))[0]

  callbackModelLoaded: ->
    @killTimeout('Waiting for Model'); @render(true)

# create a view and send tell is that it's model was loaded
view_successful_loading = new ViewWithModelLoadingTimeout()
view_successful_loading.callbackModelLoaded()

# create a view and let the timer get called triggering it to move into a failed state
view_failed_loading = new ViewWithModelLoadingTimeout()
# LATER...
# cleanup - elements removed, timers killed
view_successful_loading.release()
view_failed_loading.release()

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

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

Or check out the project here: https://github.com/kmalakoff/mixin and look at the tests folder for many more examples!

Mixin.js: the Javascript nano-framework

A few months ago, I was using Backbone.Views and many views (or categories of views) had slightly different needs. For example, if one view needed a timeout to check if model failed to load, did all of my views need the timeout functionality. 

I was faced with a fundamental architecture decision. Should I keep pushing functionality higher in my Backbone.View hierarchy to expose the functionality and cause bloat super class bloat, or was there a better way?

I think I found a better way…mixins! 

I started with just mixing in simple Javascript objects, but as I kept developing the idea, I realized that sometimes I needed initialization or cleanup code, and I needed to know which instances had been initialized with which mixins, etc. Plus, it was getting really exciting to try to push my code to the DRYest state possible….

After a few months, I’ve developed quite a sophisticated solution and I think it is mature enough to share publicly so i spent a few days packaging it, writing tests, etc.  I just had to release it because it is so fun and flexible to use!

Here’s a taster:

class StatusBar
  constructor: -> Mixin.in('Subscriber')
  updateProgress: (progress) -> # update bar
  workerDone: -> # clear bar

class HardWorker 
  constructor: ->
    Mixin.in(['Observable', 'progress_update'], 'AutoMemory', 'Backbone.Events')
    @list = new Background.List(100); @autoProperty('list', 'destroy')
    @list.append(null, (=>doWork()))
  doWork: ->
    # do something
    @notifySubscribers('progress_update', progress)

status_bar = app.getStatusBar()
worker = new HardWorker()
worker.addSubscriber(status_bar, 'progress_update', status_bar.updateProgress, 
	{destroy:status_bar.workerDone})

# later use a Backbone.Event to kill the worker and and the status bar 
# is notified (workerDone) and the background list (BGList) is cleaned up
worker.trigger('destroy')

I’ll write more examples over the coming days and weeks. Enjoy!

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

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

Background.js now with multi-dimensional arrays!

I had a need for combining arrays on a background thread and after a bit of thought, I came up with a simple way to iterate over any number of arrays in fixed sized batches.

For example, you may want to apply the same list of filters to some models and then based on the results, so some more heavy processing. Take a look at this gist for a code snippet.

Enjoy!

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

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

Background.js

I’ve been writing a single page CoffeeScript web app and needed to put some processing on a background thread so my GUI would remain responsive.

I found some articles referring to a good JavaScript WorkerQueue library so I gave it a shot.

After playing with it, I realized that I needed some extra functionality:

1) set up and clean up before and after the worker is run

2) the ability to destroy the worker queue (to support a single page app) 

3) Array iterator helpers to keep the code DRY

If you are interested in theses capabilities in an easy to use background queue and list library, download now (Right-click, and use “Save As”):

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

Enjoy!

Brain.new(“code”)

Hello and Welcome!

This is my first blog and so my first blog post. So why start now? Well, simply put, I want to share my recent experiences on my path to creating a cross-platform mobile application…I’m done yet!

Recently, I switched from Objective-C native to Rhodes and finally to PhoneGap + Couchbase for various reasons. Objective-C felt too heavy given all the memory management boilerplate code. Rhodes was very efficient, but RhoSync licensing was too expensive. So despite the pioneering efforts required to use Couchbase (http://www.couchbase.com), which provides mobile versions of CouchDB (http://couchdb.apache.org), I have decided to start blazing a trail and help the community make the Couchbase ecosystem fullfil its full potential.

I have released the following libraries and ruby gems, which, among other things, I will be providing tutorials and background on in the future:

In addition to the choice of base application technologies, in order to build something cross-platform that is easier to maintain, I have based the client on the following web technologies: brunch (http://brunchwithcoffee.com) which packages CoffeeScript, Backbone.js, Underscore.js, Eco, Stylus, and CommonJS into a really nice working environment; iScroll 4; and many great query libraries including JQuery Mobile and JQuery Global.

I look forward to hearing from you and I hope you find this useful on your own journey.

Cheers!

Kevin