Slide 1

Slide 1 text

A Guided Tour Through the Jungle @floriankugler berlinjs.org/apps May 10th, 2012

Slide 2

Slide 2 text

What is SproutCore? Cocoa inspired web application framework Large-scale, Desktop-grade applications Strict MVC (+ statechart) architecture Well defined application structure Backend agnostic Ruby build tools

Slide 3

Slide 3 text

What’s comparable? Cappuccino Sencha ExtJS Ember.js

Slide 4

Slide 4 text

A SproutCore History * 2007 Charles Jolley  2008 2009 1.0 Release 2010 1.4 Release 2010 Strobe Corp. 2010 + @wycats 2011 1.5 Release ...

Slide 5

Slide 5 text

A SproutCore History 1.5 Release 1.6 Release 2.0 beta Strobe Corp.

Slide 6

Slide 6 text

A SproutCore History 1.5 Release 1.6 Release 2.0 beta amber.js ember.js 1.8 Release ( 1.7 )

Slide 7

Slide 7 text

Status Quo SproutCore 1.4 SproutCore 1.8 ember.js SproutCore “core” (Modularization) Core SproutCore concepts Clear mission statement (Auto updating template views) Lightweight Fast, complex, large-scale apps Render delegates Auto updating template views Window-based apps Improved build tools Page-based apps Desktop browsers No build tools required

Slide 8

Slide 8 text

Core Concepts Strict MVC architecture with well defined event/data flow KVC / KVO / Bindings Computed properties Build views with HTML & CSS, update with jQuery Statecharts

Slide 9

Slide 9 text

MVC Architecture DataStore Controllers Object | Array | Tree Views Panes | Collections | Label | Button | CheckBox | ... Statechart

Slide 10

Slide 10 text

MVC Architecture Model App Controller View

Slide 11

Slide 11 text

The “V” Property Model Controller View Runloop mouseDown mouseUp keyDown mouseMoved 1 2 3 4 5 KVO Bindings Call Call

Slide 12

Slide 12 text

KVC / KVO myObject.set(‘foo’, ‘bar’); fooDidChange: function() { console.log(‘foo changed to ‘ + this.get(‘foo’)); }.observes(‘foo’) enumerable = myObject.get(‘anArray’); enumerable.pushObject(‘foo’); anArrayDidChange: function() { console.log(‘anArray length: ‘ + this.getPath(‘anArray.length’); }.observes(‘*anArray.[]’)

Slide 13

Slide 13 text

Bindings contactsController = SC.ArrayController.create(); contactController = SC.ObjectController.create({ contentBinding: ‘App.contactsController.selection’ }); addressesController = SC.ArrayController.create({ contentBinding: ‘App.contactController.addresses’ }); addressController = SC.ObjectController.create({ contentBinding: ‘App.addressesController.selection’ }); ... street: SC.LabelView.design({ valueBinding: ‘App.addressController.streetName’ }) ...

Slide 14

Slide 14 text

Computed Properties addressController = SC.ObjectController.create({ contentBinding: ‘App.addressesController.selection‘ fullName: function() { return this.get(‘firstname’) + ‘ ‘ + this.get(‘lastName’); }.property(‘firstName’, ‘lastName’).cacheable() }); ... name: SC.LabelView.design({ valueBinding: ‘App.addressController.fullName’ }) ...

Slide 15

Slide 15 text

Custom Views App.AddressView = SC.View.extend({ displayProperties: [ ‘content’ ], render: function(ctx) { ctx.push( ‘
‘ + this.getPath(‘content.lastName’) + ‘
’ ); }, update: function($) { $.find(‘last-name’).text(this.getPath(‘content.lastName’)); } });

Slide 16

Slide 16 text

Custom Views App.AddressView = SC.View.extend(SC.ContentDisplay, { contentDisplayProperties: [ ‘lastName‘ ], render: function(ctx) { ctx.push( ‘
‘ + this.getPath(‘content.lastName’) + ‘
’ ); }, update: function($) { $.find(‘last-name’).text(this.getPath(‘content.lastName’)); } });

Slide 17

Slide 17 text

Custom Views App.AddressView = SC.View.extend(SC.ContentDisplay, { contentDisplayProperties: [ ‘lastName‘ ], displayProperties: [ ‘highlighted‘ ], ... update: function($) { $.find(‘last-name’).text(this.getPath(‘content.lastName’)); if (this.get(‘highlighted’)) { $.addClass(‘highlighted’); } else { $.removeClass(‘highlighted’); } }, mouseDown: function(evt) { this.set(‘highlighted’, YES); } });

Slide 18

Slide 18 text

Statecharts showContactsState editContactState editContactDefaultState editContactDeleteState editContact submit deleteContact confirm cancel

Slide 19

Slide 19 text

Statecharts editButton: SC.ButtonView.design({ ... action: ‘editContact’ }) showContactsState: SC.State.design({ editContact: function() { this.gotoState(‘editContactState’); } }) editContactState: SC.State.design({ enterState: function() { // setup view tree }, exitState: function() { // tear down view tree }, submit: function() { this.gotoState(‘showContactsState’); } })

Slide 20

Slide 20 text

editContactState: SC.State.design({ initialSubstate: ‘editContactDefaultState’, enterState: function() { /* setup view tree */ }, exitState: function() { /* tear down view tree */ }, editContactDefaultState: SC.State.design({ submit: function() { ... }, deleteContact: function({ this.gotoState(‘editContactDeleteState’); }) }), editContactDeleteState: SC.State.design({ enterState: function() { /* setup view tree */ }, exitState: function() { /* tear down view tree */ }, confirm: function() { this.gotoState(‘showContactsState’); }, cancel: function() { this.gotoState(‘editContactDefaultState’); } }) })

Slide 21

Slide 21 text

The Future The community is recovering from the disruptive changes during the last year SproutCore is actively maintained Roadmap discussions are ongoing... Interesting spin-off: Blossom (#blossom) Built off SproutCore 1.4 Canvas based view layer

Slide 22

Slide 22 text

SproutCore and Mobile I wouldn’t recommend it Try it: touch.ebay.com It’s a lot of JavaScript to be downloaded and parsed (~ 600-800 kB) Too DOM heavy Keep an eye on Blossom, Ember.js

Slide 23

Slide 23 text

For Whom is SproutCore? Complex, desktop-grade application? Rich user interaction? Handles a lot of data? Targets desktop browsers? ... Then SproutCore is a very well designed and mature application framework, check it out!

Slide 24

Slide 24 text

Resources sproutcore.com Guides & API docs Install SproutCore as Ruby Gem Highly recommended to clone SC repo into the frameworks folder of your app #sproutcore frozencanuck.wordpress.com

Slide 25

Slide 25 text

Questions? @floriankugler mail@floriankugler.de