Get Up to Date with the SproutCore Meetups!

written by mdouglas

Have you been to a SproutCore Meetup yet? If you haven’t, now is the time!

Since February, we have grown from having 3 active meetups in the US to having 10 internationally- and several more in the works. We’re excited by the energetic response we’ve received from you, the SproutCore community, and hope many of you are able to come and share in the awesomeness (and swag!).

We’re always looking for ways to involve more community members in the user groups. If you’re interested in speaking at any of the existing meetups, or if you’re interested in starting a meetup in your neck of the woods, email us at community@sproutcore.com- we’d love to have you!

In the meantime, we want to share some talks that have been given at recent meetups: The Future of SproutCore, by Tom Dale at the Chicago meetup on May 24, and Structuring Teams to Build Large-Scale SproutCore Apps, given by Peter Bergstrom to the San Francisco meetup on June 14th.

On the 14th, the SF group was also lucky enough to hear a great talk by Colin Campbell on the ABCs of Building a SproutCore App. Unfortunately, we had a bit of a hiccup recording Colin’s talk, but stay tuned for a blog post next week where he’ll take you through the code examples he showed.

Until then, you can find the code from his presentation here.


In this talk, The Future of SproutCore, Tom Dale explains some of the changes that are coming in SproutCore 2.0, and hopefully answers a few questions you may have about where SproutCore is headed.

Bear with us on the audio for the first portion; the echo goes away quickly :)


Watch here as Peter Bergstrom expands on his blog post about structuring teams and division of labor on large-scale SproutCore projects.


We hope you found these recordings helpful- and next time, we hope to see you in person!

Dispatches From The Edge: Handlebars Without Spans

written by gmoeck

As more people have been using templates to map the state of their views into the DOM, a couple of questions have continually come up. In this week’s Dispatch, I want to focus on how SC.TextField solves one of the common questions and offer some advice on building similar custom views.

Let’s first specify the common question: How would one go about implementing something like a textarea tag? Just about everyone tries to do it like this:

<textarea>{{content}}</textarea>

You would like it to render something like this:

<textarea>Some Content</textarea>

But instead, SproutCore outputs something that looks like the following:

<textarea><span>Some Content</span></textarea>

Why would SproutCore wrap your content inside of the span tag? Because the Handlebars template isn’t only responsible for the initial rendering, it’s also keeping that rendered content in sync with the state of your view. Because of this, it needs to be able to target an element inside of the DOM to replace when the state of your view changes. So SproutCore inserts that span tag into the rendered DOM so that it can later change the DOM when content changes. So, then, how would we implement a textarea sort of view? Although you might not have known it, SproutCore 1.6 actually allows you to use a textarea instead of a text input within SC.TextField by changing the isMultiLine parameter.

A template using this might look something like this:

{{view SC.TextField isMultiLine="true" valueBinding="MyApp.someController.someValue"}}

Which would then output something like this:

<textarea>Some Content</textarea>

How did the core team create a view that does that? Since we don’t really have a way to handle this updating baked into the SproutCore extensions to Handlebars, we bypass the delegating to the template for the value of the text area, and handle that updating directly in our view. So if you were to build a custom TextArea view, it might look something like this:

SC.TextArea = SC.TemplateView.extend({
  value: '',
  template: SC.Handlebars.compile('<textarea></textarea>'),

  $input: function() {
    return this.$('textarea');
  },

  didCreateLayer: function() {
    this.$input().val(this.get('value'));
    SC.Event.add(this.$input(), 'keyup', this, this.domValueDidChange);
  },

  domValueDidChange: function() {
    var input = this.$input();
    if(input.val() !== this.get('value'))
      this.set('value', input.val());
  },

  viewValueDidChange: function() {
    var input = this.$input();
    if(this.get('value') !== input.val())
      input.val(this.get('value'));
  }.observes('value')
})

What is this code doing?

First, we’re specifying the basic render with the template method to be just a basic textarea tag without any handlebars tags. This way, when initially rendering the view it just renders a blank text area, and doesn’t insert the span tag that we saw earlier.

Second, we implement a didCreateLayer function which is called after the view is initially rendered. Within that, we set the initial value of the textarea DOM to be the value of our view. Then we register the input tag to call into an API called domValueDidChange when a keyup event is fired upon the textarea element. We need this so that we can manually keep our view state in sync when changes happen to the state in the DOM.

Third, in order to keep our view state in sync with the DOM, we need to actually implement the domValueDidChange function. In order to ensure we don’t enter an infinite loop, we double check that we don’t set the value if it is already identical to the value in the DOM. And if it is not identical, we update the value of our view with the current value of the textfield. Then we also need to implement a function that will update the DOM when the value of the view changes. This is what the viewValueDidChange function is. It observes the value of the view object and when it changes if the textarea is not in sync, it syncs it.

The basic idea behind the whole view is that instead of delegating to the template to keep the view in sync, we manually do that with observers in the DOM.

If you want to see how we do this directly, you should read the actual source for textfield view in both 1.6 and 2.0. And remember- however the core team builds views, you can too if you just look at the source and learn how it’s being done.


Announcements:

We’re excited to welcome our first Meetup group in Asia, SproutCore Kuala Lumpur, to the family of SproutCore meetup groups! More international meetups are in the pipeline, so keep your eyes peeled for announcements in the next few weeks!

There is also the San Francisco meetup tonight. If you can’t make it, watch for video posted here on the blog.

Hope to see you around! And, as always, let us know if there’s something you feel should be up here.

SproutCore 1.6 Released

written by pwagenet

We’re pleased to announce that SproutCore 1.6 is now out!

SproutCore 1.6 is largely a bug fix release aiming to help provide a more stable experience. If you’re using SproutCore 1.5 it should be a relatively straight-forward upgrade.

For more information on the changes, see the Abbot changelog and the framework changelog.

Upgrade now via package or, if you installed via RubyGems, run gem install sproutcore. Enjoy!

By the way, we’re still on a six week release schedule so that means we’re planning to release 1.7 in mid-to-late July. Keep an eye out for more news on 1.7 in the coming weeks.

Statecharts in SproutCore

written by jskeie

In their most simple form, statecharts are a way to structure your application into logical states. A statechart does not need to be implemented in your application’s code; but it is easier to adhere to the statechart you lay out if you are able to create or use a framework that defines:

  • what is possible to do within a state

  • how the application can transition from one state to another

  • and finally what needs to be set up and torn down upon state entry and state exit.

From SproutCore Version 1.5 and onwards, there is a fantastic Statechart framework built right into the library itself– conveniently called SC.Statechart.

To Statechart or Not to Statechart?

For me, there are a couple of main reasons to use statecharts. First, having to sit down and think about your application’s possible states makes you think long and hard about the actual design of your application. Second, splitting a large application into logical (and smaller) states makes it easier to break functional requirements down into manageable parts when it is time to plan and develop the application.

As a final bonus, you end up with a finished application that has one killer feature: separation of concerns between application domains. That last part alone should make you want to invest in using statecharts for your application: cleaner code and less spaghetti.

The State of the Game

There are many ways to structure a statechart application. The statechart needs to have one and only one root state, which you can think of as the initial state of your application.

There are a number of key factors that needs to be included in each state, so that the states can be combined into a statechart.

  • Each state needs to have exactly one clearly defined entry point

  • Each state needs to have at least one clearly defined exit point (the possible transitions available)

  • Each state needs to be able to set up everything required within that state upon state entry

  • Each state needs to be able to tear down anything that is state-specific upon state exit

Note that the above can be considered my guidelines. It’s most certainly possible to break any of the above requirements inside your statechart implementation– however, be prepared that the end result might be messy/spaghetti code, no clear separation of concerns, or worse, both.

An added bonus of using SC.statechart is that you will also be able to build an application where the routes that the user can travel through your application is made explicit in both design and code.

Statecharts and the MVC Model

Since Statecharts will make up a large portion of your application’s architecture, where does it fit into the SproutCore MVC model? Will a Statechart-built application really be something like an MVCS (Model-View-Controller-Statechart) model?

The answer to the first question is that Statecharts fits in beautifully with the SC MVC model. The answer to the MVCS question is: it depends on your viewpoint.

Without statecharts, the SproutCore MVC model looks like the diagram below.

In my opinion, a statechart belongs within the Controller portion of the MVC model, and might look something like the diagram below. Note that both the “Action” and the “Statechart” portions of the Controller layer in the diagram below are application-wide, while the “Controller” portion of the Controller layer refers to the controller that the view binds to (usually a SC.ListController, SC.ItemController, etc., or a custom made controller).

Implementing a Statechart Application

Now, lets looks at the actual implementation of a Statechart application. For this blog post, I will be looking at a portion of the EurekaJ Statechart implementation.

In EurekaJ the actual login and authentication of the application is handled outside of SproutCore (by Spring Security on the Java backend), and so we will make the assumption that the user already is pre-authenticated. Before we get started, though, there are a few key symbols that you need to get acquainted with.

To get started discussing the statechart implementation, let’s first describe how the Graphical User Interface works in the EurekaJ application. The application is split into four main parts. The top panel is responsible for displaying the application logo, as well as a toolbar. The toolbar currently only has a single item, a button that will activate the administration panel.

On the left hand side of the application, there is a sidebar responsible for showing a tree-structure consisting of all nodes that the application is able to display visual charts for.

On the right hand side, there is an information panel that currently has two responsibilities: letting the user select which time-period to display charts for, as well as listing any recent alerts triggered by the system. In the center, the main area of the application, the application will display any of the charts selected in the tree menu to the left, for the time period chosen in the time-period panel to the right.

Schematically the application looks like the diagram below.

We can immediately identify 6 states that concurrently need to be displayed on the screen, each of which needs to be active and ready for user input. For my application, I decided to make the four states “showingTopPanel”, “showingTreePanel”, “showingChartPanel” and “showingInformationPanel” direct concurrent states of the rootState.

The statechart implementation in the file core_statechart.js thus becomes:

<code><span class="cm">/*globals EurekaJView */</span>

<span class="nx">EurekaJView</span><span class="p">.</span><span class="nx">statechart</span> <span class="o">=</span> <span class="nx">SC</span><span class="p">.</span><span class="nx">Statechart</span><span class="p">.</span><span class="nx">create</span><span class="p">({</span>
    <span class="nx">rootState</span><span class="o">:</span> <span class="nx">SC</span><span class="p">.</span><span class="nx">State</span><span class="p">.</span><span class="nx">design</span><span class="p">({</span>
        <span class="nx">substatesAreConcurrent</span><span class="o">:</span> <span class="nx">YES</span><span class="p">,</span>

        <span class="nx">showingTreePanel</span><span class="o">:</span> <span class="nx">SC</span><span class="p">.</span><span class="nx">State</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="s1">'EurekaJView.showingTreePanel'</span><span class="p">),</span>

        <span class="nx">showingChartPanel</span><span class="o">:</span> <span class="nx">SC</span><span class="p">.</span><span class="nx">State</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="s1">'EurekaJView.showingChartPanel'</span><span class="p">),</span>

        <span class="nx">showingInformationPanel</span><span class="o">:</span> <span class="nx">SC</span><span class="p">.</span><span class="nx">State</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="s1">'EurekaJView.showingInformationPanel'</span><span class="p">),</span>

        <span class="nx">showingTopPanel</span><span class="o">:</span> <span class="nx">SC</span><span class="p">.</span><span class="nx">State</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="s1">'EurekaJView.showingTopPanel'</span><span class="p">)</span>
    <span class="p">})</span>
<span class="p">});</span>
</code>

The important things to notice in the above code are first that each of the four states are extracted into their own JavaScript files; and second, that all states that are defined as children of the rootState are defined as concurrent using the substatesAreConcurrent: YES flag.

Neither the showingTreePanel and the showingChartPanel states are complex, so we will instead have a look at the state “showingTopPanel” in more detail.

In the top panel there is a button on the far right that will allow the user to enter the applications administration panel. When the user clicks the “Administration panel” button, the administration panel is displayed inside a modal panel. Once inside the modal panel, the user is able to leave the panel by clicking on a “Hide Administration Panel” button.

In the above scenario, we have described two states, the top panel’s initial “ready” state, as well as the “showingAdministrationPanel” state. Each state therefore has one action each, as depicted in the diagram below.

To view the implementation details for the showingTopPanel state, we therefore have to look at the source for the showingTopPanel.js file.

<code><span class="nx">EurekaJView</span><span class="p">.</span><span class="nx">showingTopPanel</span> <span class="o">=</span> <span class="nx">SC</span><span class="p">.</span><span class="nx">State</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
	<span class="nx">initialSubstate</span><span class="o">:</span> <span class="s1">'ready'</span><span class="p">,</span>

    <span class="nx">enterState</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
        <span class="nx">EurekaJView</span><span class="p">.</span><span class="nx">mainPage</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">'topView'</span><span class="p">).</span><span class="nx">set</span><span class="p">(</span><span class="s1">'isVisible'</span><span class="p">,</span> <span class="nx">YES</span><span class="p">);</span>
    <span class="p">},</span>

    <span class="nx">exitState</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
        <span class="nx">EurekaJView</span><span class="p">.</span><span class="nx">mainPage</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">'topView'</span><span class="p">).</span><span class="nx">set</span><span class="p">(</span><span class="s1">'isVisible'</span><span class="p">,</span> <span class="nx">NO</span><span class="p">);</span>
    <span class="p">},</span>

    <span class="nx">ready</span><span class="o">:</span> <span class="nx">SC</span><span class="p">.</span><span class="nx">State</span><span class="p">.</span><span class="nx">design</span><span class="p">({</span>
    	<span class="nx">showAdministrationPaneAction</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
			<span class="nx">EurekaJView</span><span class="p">.</span><span class="nx">EurekaJStore</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">EurekaJView</span><span class="p">.</span><span class="nx">ALERTS_QUERY</span><span class="p">);</span>
			<span class="nx">EurekaJView</span><span class="p">.</span><span class="nx">EurekaJStore</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">EurekaJView</span><span class="p">.</span><span class="nx">ADMINISTRATION_TREE_QUERY</span><span class="p">);</span>
			<span class="nx">EurekaJView</span><span class="p">.</span><span class="nx">EurekaJStore</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">EurekaJView</span><span class="p">.</span><span class="nx">INSTRUMENTATION_GROUPS_QUERY</span><span class="p">);</span>
			<span class="nx">EurekaJView</span><span class="p">.</span><span class="nx">EurekaJStore</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">EurekaJView</span><span class="p">.</span><span class="nx">EMAIL_GROUPS_QUERY</span><span class="p">);</span>

			<span class="nx">EurekaJView</span><span class="p">.</span><span class="nx">updateAlertsAction</span><span class="p">();</span>
			<span class="nx">EurekaJView</span><span class="p">.</span><span class="nx">updateInstrumentationGroupsAction</span><span class="p">();</span>
			<span class="nx">EurekaJView</span><span class="p">.</span><span class="nx">updateEmailGroupsAction</span><span class="p">();</span>
			<span class="k">this</span><span class="p">.</span><span class="nx">gotoState</span><span class="p">(</span><span class="s1">'showingAdminPanel'</span><span class="p">);</span>
    	<span class="p">}</span>
    <span class="p">}),</span>

    <span class="nx">showingAdminPanel</span><span class="o">:</span> <span class="nx">SC</span><span class="p">.</span><span class="nx">State</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="s1">'EurekaJView.showingAdminPanel'</span><span class="p">)</span>
<span class="p">});</span>
</code>

Here, we see that the showingTopPanel state has an initial substate ready. showingTopPanel sets up the view for the state in the enter functions and tears down the state-specific views in the exit function, by toggling the visibility of the top panel itself. The ready state does not have any enter or exit logic, but it has a single action showAdiministrationPanelAction defined that will ensure that data required for the administration panel is fetched from the server before moving on to the showingAdminPanel state.

As the last line suggests, the showingAdminPanel state is defined in its own file showingAdminPanel.js.

<code><span class="nx">EurekaJView</span><span class="p">.</span><span class="nx">showingAdminPanel</span> <span class="o">=</span> <span class="nx">SC</span><span class="p">.</span><span class="nx">State</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
	<span class="nx">hideAdministrationPaneAction</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">this</span><span class="p">.</span><span class="nx">gotoState</span><span class="p">(</span><span class="s1">'ready'</span><span class="p">);</span>
    <span class="p">},</span>

    <span class="nx">enterState</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
        <span class="nx">EurekaJView</span><span class="p">.</span><span class="nx">mainPage</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">'adminPanelView'</span><span class="p">).</span><span class="nx">append</span><span class="p">();</span>
    <span class="p">},</span>

    <span class="nx">exitState</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
        <span class="nx">EurekaJView</span><span class="p">.</span><span class="nx">mainPage</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">'adminPanelView'</span><span class="p">).</span><span class="nx">remove</span><span class="p">();</span>
    <span class="p">}</span>
<span class="p">});</span>
</code>

Here we can see that the EurekaJView.showingAdminPanel state will append and remove the admin modal panel upon state entry and exit. It also has a single action defined that will return to the “ready” state.

Note that with this approach you never have to explicitly call code to either append or remove the adminPanelView from the application– this is done implicitly by letting the state take care of state setup and state teardown. If the administration panel gets additional requirements later on regarding state entry and exit it is easy to know just where to go inside the code to make the change.

By now, you are hopefully starting to see a pattern with the statechart approach to state specification and management within a RIA application, as well as starting to see the benefit of designing your GUI application around statecharts. I won’t bore you with the implementation details of the other states, as they are all structured in a similar manner. I will however, leave you with a diagram of the final statechart for the EurekaJ application. If you do want to have a look at the source code, though, EurekaJ is open sources with the GPLv2 license, and the source code is available from GitHub/joachimhs/EurekaJ. There is also an online demo of the EurekaJ application available at http://eurekaj-ec2.haagen.name/, where you can log in with the username ‘user’ and the password ‘user’.

The Run Loop: Part 1

written by tkeating

The following post cuts to the very core, pun intended, of SproutCore: the Run Loop.

What is a Run Loop?

In order to ensure that we’re all talking about the same thing, here’s the definition from Wikipedia:

In computer science, the event loop, message dispatcher, message loop, message pump, or run loop is a programming construct that waits for and dispatches events or messages in a program. It works by polling some internal or external "event provider", which generally blocks until an event has arrived, and then calls the relevant event handler ("dispatches the event").

That’s a bit of a high-level definition, but I’ll try to expose the “bare metal” of SproutCore’s Run Loop enough so that it makes sense not only theoretically, but practically too.

What is the Run Loop?

In the context of SproutCore, the Run Loop is a function that coordinates code, key-value notifications, and timers within your application. Typically, a new Run Loop will automatically be started by SproutCore in response to the browser firing certain events, but a new Run Loop can be manually started at any time by placing your code between a SC.RunLoop.begin() statement and a SC.RunLoop.end() statement.

At this point, you may be thinking, “All right, smart guy, it’s easy to make general statements like ‘firing certain events’, but what events exactly?”. All right, smart reader, heaven forbid we leave anything to ambiguity. Let us look at the events that SproutCore listens for.

What triggers a Run Loop?

If you delve into the RootResponder code, you’ll find that SproutCore registers itself to receive the following events from the browser’s document:

  • touchstart

  • touchmove

  • touchend

  • touchcancel

  • keydown

  • keyup

  • beforedeactivate

  • mousedown

  • mouseup

  • click

  • dblclick

  • mousemove

  • selectstart

  • contextmenu

  • focusinFor IE only

  • focusoutFor IE only

  • webkitAnimationStart

  • webkitAnimationIteration

  • webkitAnimationEnd

  • transitionendFor platforms that support CSS transitions only

and the following events from the browser’s window:

  • resize

  • focusFor non-IE browsers

  • blurFor non-IE browsers

If you look at the code in SC.device, you’ll also find these listeners on the window:

  • online

  • offline

  • orientationchange

and there are also listeners for devicemotion and deviceorientation in the experimental framework’s SC.device extension. Now, if you were to follow the code further, you will find that each of these events does some amount of set up, but invariably ends up creating a new Run Loop.

When should you manually trigger a Run Loop?

So, we know that SproutCore will start a new Run Loop in response to any of the many events previously listed– and I apologize if I’ve missed any– but the point is, if we better understand when SproutCore is creating Run Loops, we should also better understand when it is not creating them.

For instance, SproutCore does not listen for copy or paste events, so if you were to add your own listener, ex. $('my-input').on('copy', function() { ... }), you must also start your own Run Loop, ex. $('my-input').on('copy', function() { SC.RunLoop.begin(); ... SC.RunLoop.end()}).

However, this is a rare case, since SproutCore’s built-in libraries do trigger Run Loops properly. For example, using SC.Request ensures that a Run Loop is triggered when the browser receives a response from the server, and using SC.Timer ensures that a Run Loop is triggered when the timer expires.

So it is actually quite likely that you will never need to manually start a Run Loop, but hopefully you now understand better when you may need to.

What does the Run Loop do?

Earlier, I mentioned that the Run Loop “coordinates code, key-value notifications and timers within your application”. So, what does that mean exactly? Well, to explain it best, I’ll walk you through a flow diagram of the Run Loop.

You’ll notice the functions invokeOnce(), invokeLast() and invokeLater() in the flow diagram. These are important functions that you are most likely already using to coordinate your code execution. In order to understand exactly how they are and should be used, let’s follow very closely as the Run Loop executes.

Run Loop Walkthrough

1. Execute expired SC.Timers (invokeLater())

Any timers that have just expired will be run. This includes functions passed to invokeLater() or SC.Timers that were manually created.

2. Execute invokeOnce() functions

Your code may have added a number of functions to the invokeOnce() queue. Those functions will now be run in the order they were added, i.e. first-in-first-out.

3. Flush changes to bound properties

Now things start to get really interesting. Several observable properties may have been changed by your code using Key-Value Coding, i.e. set(), which means that these properties’ bound properties should be updated. So propagate the changes through to the bindings.

Note: properties that are observed using .observes() or addObserver(...) get updated immediately as they change, while bindings update asynchronously within the Run Loop. That is why bindings are less taxing on the application’s performance.

More changes?

At this point, steps 1., 2. and 3. may have caused new functions to be added to invokeOnce or more observable property changes. So the Run Loop will continue to repeat these steps until all the updates have propagated. When the application’s state has settled, the Run Loop will continue.

4. Execute invokeLast() functions

Now that all the changes have propagated through the app, the functions queued with invokeLast() will be run. This illustrates the common use for invokeLast(), to act upon the application when its state is guaranteed to be synchronized.

More changes?

Of course, the functions passed to invokeLast() may have again added code to invokeOnce() or changed observable properties.  If so, then go back and continue to flush changes until the application state is again completely in sync.

5. Schedule outstanding SC.Timers (invokeLater())

Finally, if there are still timers outstanding, the Run Loop simply schedules a new timeout to start a new Run Loop when the timer expires.

Conclusion

Hopefully you have now learned as much as you would care to know about what the Run Loop is and how it operates, but the outstanding question is “Why?”. The answer to that question is performance and synchronization, which I will delve into in part two of this series.