<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title>madhatted.com - Code</title>
  <id>tag:madhatted.com,2016:mephisto/</id>
  <generator uri="http://mephistoblog.com" version="0.8.0">Mephisto Drax</generator>
  <link href="http://madhatted.com/feed" rel="self" type="application/atom+xml"/>
  <link href="http://madhatted.com/" rel="alternate" type="text/html"/>
  <updated>2015-11-16T21:53:41Z</updated>
  <entry xml:base="http://madhatted.com/">
    <author>
      <name>mixonic</name>
    </author>
    <id>tag:madhatted.com,2015-11-16:3716</id>
    <published>2015-11-16T17:38:00Z</published>
    <updated>2015-11-16T21:53:41Z</updated>
    <link href="http://madhatted.com/2015/11/16/content-kit-is-now-mobiledoc-kit" rel="alternate" type="text/html"/>
    <title>Content-Kit is now Mobiledoc Kit</title>
<summary type="html">&lt;p&gt;&lt;strong&gt;Today we&#8217;re releasing &lt;a href=&quot;https://www.npmjs.com/package/mobiledoc-kit&quot;&gt;Mobiledoc Kit&lt;/a&gt; 0.6.0.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Previously, we&#8217;ve used the name Content-Kit Editor to describe this package. As we implemented the goals laid out in the post &lt;a href=&quot;http://madhatted.com/2015/8/25/content-kit-programmatic-editing&quot;&gt;Content-Kit: Programmatic Editing&lt;/a&gt;, it became clear the codebase was diverging from being an editor in the sense that most users would expect it to be. For example, it no longer sports a toolbar or much UI.&lt;/p&gt;

&lt;p&gt;Renaming the editor project &#8220;Mobiledoc Kit&#8221; achieves two goals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The new name ties this package closer to the Mobiledoc format, which we think is the most significant differentiator of our efforts.&lt;/li&gt;
&lt;li&gt;By naming the project a &#8220;kit&#8221;, we open the door to editors being implemented on top of Mobiledoc Kit. For example, &lt;strong&gt;we&#8217;re also releasing &lt;a href=&quot;https://github.com/bustlelabs/ember-mobiledoc-editor&quot;&gt;Ember Mobiledoc Editor&lt;/a&gt; 0.2.0 today&lt;/strong&gt;. This editor has the toolbar and UX features you would expect from something calling itself an editor.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This release also coincides with the first large-scale rollout of Mobiledoc at Bustle&#8217;s new website &lt;a href=&quot;https://www.romper.com/&quot;&gt;Romper&lt;/a&gt;. Over 750 articles have been published, and dozens more a day are being written with a CMS based on Ember Mobiledoc Editor.&lt;/p&gt;

&lt;p&gt;Since 0.4.0 in August, Mobiledoc and the kit have introduced several notable improvements. Let&#8217;s take a look.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;&lt;strong&gt;Today we&#8217;re releasing &lt;a href=&quot;https://www.npmjs.com/package/mobiledoc-kit&quot;&gt;Mobiledoc Kit&lt;/a&gt; 0.6.0.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Previously, we&#8217;ve used the name Content-Kit Editor to describe this package. As we implemented the goals laid out in the post &lt;a href=&quot;http://madhatted.com/2015/8/25/content-kit-programmatic-editing&quot;&gt;Content-Kit: Programmatic Editing&lt;/a&gt;, it became clear the codebase was diverging from being an editor in the sense that most users would expect it to be. For example, it no longer sports a toolbar or much UI.&lt;/p&gt;

&lt;p&gt;Renaming the editor project &#8220;Mobiledoc Kit&#8221; achieves two goals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The new name ties this package closer to the Mobiledoc format, which we think is the most significant differentiator of our efforts.&lt;/li&gt;
&lt;li&gt;By naming the project a &#8220;kit&#8221;, we open the door to editors being implemented on top of Mobiledoc Kit. For example, &lt;strong&gt;we&#8217;re also releasing &lt;a href=&quot;https://github.com/bustlelabs/ember-mobiledoc-editor&quot;&gt;Ember Mobiledoc Editor&lt;/a&gt; 0.2.0 today&lt;/strong&gt;. This editor has the toolbar and UX features you would expect from something calling itself an editor.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This release also coincides with the first large-scale rollout of Mobiledoc at Bustle&#8217;s new website &lt;a href=&quot;https://www.romper.com/&quot;&gt;Romper&lt;/a&gt;. Over 750 articles have been published, and dozens more a day are being written with a CMS based on Ember Mobiledoc Editor.&lt;/p&gt;

&lt;p&gt;Since 0.4.0 in August, Mobiledoc and the kit have introduced several notable improvements. Let&#8217;s take a look.&lt;/p&gt;
&lt;h2&gt;Programmatic Editing&lt;/h2&gt;

&lt;p&gt;As proposed in the &lt;a href=&quot;http://madhatted.com/2015/8/25/content-kit-programmatic-editing&quot;&gt;last blog post on Mobiledoc&lt;/a&gt;, we&#8217;ve implemented several editing APIs that allow consumers to modify posts and build custom user interfaces. We&#8217;ve also dropped nearly all UI from the Mobiledoc Kit project, and re-implemented most of it in the Ember Mobiledoc Editor&lt;/p&gt;

&lt;p&gt;Several &lt;a href=&quot;https://github.com/bustlelabs/mobiledoc-kit#editor-lifecycle-hooks&quot;&gt;lifecycle hooks&lt;/a&gt; have been added to the editor, which allows toolbars and other custom UX to be implemented.&lt;/p&gt;

&lt;h2&gt;Ember Mobiledoc Editor&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/bustlelabs/ember-mobiledoc-editor&quot;&gt;Ember Mobiledoc Editor&lt;/a&gt; includes components for rendering an editor and customizing the UI. For example, this template would render an editor and toolbar:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;{{#mobiledoc-editor mobiledoc=someDoc cards=(myCards) as |editor|}}&lt;tt&gt;
&lt;/tt&gt;  {{#mobiledoc-section-button editor=editor for=&amp;quot;h2&amp;quot;}}&lt;tt&gt;
&lt;/tt&gt;    Headline&lt;tt&gt;
&lt;/tt&gt;  {{/mobiledoc-section-button}}&lt;tt&gt;
&lt;/tt&gt;  {{#mobiledoc-markup-button editor=editor for=&amp;quot;strong&amp;quot;}}&lt;tt&gt;
&lt;/tt&gt;    Bold&lt;tt&gt;
&lt;/tt&gt;  {{/mobiledoc-markup-button}}&lt;tt&gt;
&lt;/tt&gt;{{/mobiledoc-editor}}&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Additionally, the Ember editor includes support for card display and editor modes being written as Ember components. This makes building new cards trivial, requiring very little knowledge of Mobiledoc Kit and zero knowledge of its internals.&lt;/p&gt;

&lt;h2&gt;Cut, Copy, Paste&lt;/h2&gt;

&lt;p&gt;Earlier versions of Mobiledoc Kit had limited or no support for pasting content. 0.6.0 adds battle-tested support for several scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pasting between any two Mobiledoc Kit instances is supported for text and card content. For example given the &#8220;Selfie Card&#8221; demo at &lt;a href=&quot;http://bustlelabs.github.io/mobiledoc-kit/demo/&quot;&gt;bustle.github.io/mobiledoc-kit/demo&lt;/a&gt;, you could snap a selfie, copy that part of the post, then paste it into any other kit instance supporting that card. The copying of a card payload is lossless, and the card is still editable.&lt;/li&gt;
&lt;li&gt;Using the HTML output of Google Docs as a baseline, we&#8217;ve implemented support for pasting copied webpages into Mobiledoc Kit. Among the challenges for a complete pasting solution is how to handle non-text items. We&#8217;ve added hooks to the HTML parser that allow images to be converted into cards, and will work on making a public API for parser hooks in the next release. For now you can see the &lt;a href=&quot;https://github.com/bustlelabs/mobiledoc-kit/blob/fb16ec0bcb55ef5b2810fc89bcd3b632ce6f4822/src/js/parsers/section.js#L58&quot;&gt;&lt;code&gt;cardParsers&lt;/code&gt;&lt;/a&gt; option and &lt;a href=&quot;https://github.com/bustlelabs/mobiledoc-kit/blob/fb16ec0bcb55ef5b2810fc89bcd3b632ce6f4822/src/js/parsers/section.js#L114&quot;&gt;calling code&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Copying from Mobiledoc Kit and pasting into any HTML parsing editor is also supported. The copied content is rendered specifically for that copy attempt, and, for example, will contain the display version of a card even if that card is in edit mode.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Better Card Cursors&lt;/h2&gt;

&lt;p&gt;In August, cursors in Mobiledoc Kit would skip over cards. Cards themselves had no before or after cursors. Amongst other limitations, this meant there was no way to have a cursor after a card that was the last section in a post.&lt;/p&gt;

&lt;p&gt;0.6.0 improved cursor interaction with cards, making them behave much more like you would expect from any other editor. For example:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The &#8220;Image Card&#8221; demo at at &lt;a href=&quot;http://bustlelabs.github.io/mobiledoc-kit/demo/&quot;&gt;bustle.github.io/mobiledoc-kit/demo&lt;/a&gt; is a good place to experiment with these changes.&lt;/p&gt;

&lt;h2&gt;Improved Webpack Support&lt;/h2&gt;

&lt;p&gt;We&#8217;ve seen some interest in Mobiledoc from &lt;a href=&quot;https://webpack.github.io/&quot;&gt;webpack&lt;/a&gt; and &lt;a href=&quot;https://facebook.github.io/react/&quot;&gt;React&lt;/a&gt; users. These tools expect our packaging to be slightly different than how we&#8217;ve been doing it so far.&lt;/p&gt;

&lt;p&gt;Webpack is a build tool that supports modules imported via CommonJS. Mobiledoc Kit and the various renderers did not originally have CommonJS builds enabled, but they do now.&lt;/p&gt;

&lt;p&gt;Webpack treats dependencies in NPM&#8217;s &lt;code&gt;package.json&lt;/code&gt; file as dependencies for the browser. This means we cannot have any build-time dependencies listed in &lt;code&gt;package.json&lt;/code&gt;, a strategy that is unfortunately incompatible with these packages being Ember addons. Consequently, we&#8217;ve spun out a separate addon for each of our renderers.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/bustlelabs/mobiledoc-dom-renderer&quot;&gt;mobiledoc-dom-renderer&lt;/a&gt; and &lt;a href=&quot;https://github.com/bustlelabs/ember-mobiledoc-dom-renderer&quot;&gt;ember-mobiledoc-dom-renderer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/bustlelabs/mobiledoc-html-renderer&quot;&gt;mobiledoc-html-renderer&lt;/a&gt; and &lt;a href=&quot;https://github.com/bustlelabs/ember-mobiledoc-html-renderer&quot;&gt;ember-mobiledoc-html-renderer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Finally we&#8217;ve introduced the &lt;a href=&quot;https://github.com/bustlelabs/mobiledoc-text-renderer&quot;&gt;mobiledoc-text-renderer&lt;/a&gt; and &lt;a href=&quot;https://github.com/bustlelabs/ember-mobiledoc-text-renderer&quot;&gt;ember-mobiledoc-text-renderer&lt;/a&gt;, which we&#8217;re using for creating searchable versions of Mobiledoc posts for &lt;a href=&quot;https://aws.amazon.com/elasticsearch-service/&quot;&gt;AWS ElasticSearch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More interest from webpack users is exciting, and we&#8217;re happy to better support their tooling.&lt;/p&gt;

&lt;h2&gt;Other Changes&lt;/h2&gt;

&lt;p&gt;Options for what kinds of markup can be created have been expanded to include underline, subscript, superscript, and strikethrough. Thanks to &lt;a href=&quot;https://github.com/vitosamson&quot;&gt;@vitosamson&lt;/a&gt; for this addition!&lt;/p&gt;

&lt;p&gt;Card payloads can now be saved without toggling the card back to display mode. See &lt;a href=&quot;https://github.com/bustlelabs/mobiledoc-kit/blob/master/CARDS.md#available-hooks&quot;&gt;Available hooks&lt;/a&gt; in the card documentation for more details.&lt;/p&gt;

&lt;p&gt;For a more detailed summary of changes in the recent few releases, see the Mobiledoc Kit &lt;a href=&quot;https://github.com/bustlelabs/mobiledoc-kit/blob/master/CHANGELOG.md&quot;&gt;CHANGELOG.md&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;What&#8217;s Coming&lt;/h2&gt;

&lt;p&gt;We have several projects underway today that are expected to land soon:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rlivsey&quot;&gt;@rlivsey&lt;/a&gt; is working on support for &#8220;Atoms&#8221; in Mobiledoc and Mobiledoc Kit. This may be a breaking change in the Mobiledoc format, and necessitate a version bump and migration script for current Mobiledocs. You can follow his work on &lt;a href=&quot;https://github.com/bustlelabs/mobiledoc-kit/pull/226&quot;&gt;PR #226&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Parsing hooks must be formalized into a public API. We&#8217;re tracking this on &lt;a href=&quot;https://github.com/bustlelabs/mobiledoc-kit/issues/229&quot;&gt;Issue #229&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;To mature and encourage a card ecosystem, we&#8217;ve begun an exploration of how to improve card packaging and card APIs. See &lt;a href=&quot;https://github.com/bustlelabs/mobiledoc-kit/issues/228&quot;&gt;Issue #228&lt;/a&gt; for an in-depth discussion and some proposed changes.&lt;/li&gt;
&lt;li&gt;We&#8217;ve regressed on support for IE, and are tracking progress to improve it in &lt;a href=&quot;https://github.com/bustlelabs/mobiledoc-kit/issues/212&quot;&gt;Issue #212&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Big thanks to &lt;a href=&quot;http://www.bustle.com/labs&quot;&gt;Bustle Labs&lt;/a&gt; for continued sponsorship of our work on Mobiledoc. We&#8217;re having a great time with their smart and fun team here in NYC. Bustle is looking for senior software engineers and senior UX designers to join their crew.&lt;/em&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://madhatted.com/">
    <author>
      <name>mixonic</name>
    </author>
    <id>tag:madhatted.com,2015-09-25:3649</id>
    <published>2015-09-25T14:59:00Z</published>
    <updated>2015-09-25T15:26:54Z</updated>
    <link href="http://madhatted.com/2015/9/25/announcing-torii-0-6-0" rel="alternate" type="text/html"/>
    <title>Announcing Torii 0.6.0</title>
<summary type="html">&lt;p&gt;&lt;a href=&quot;https://github.com/vestorly/torii&quot;&gt;Torii&lt;/a&gt; is an authentication library for Ember.js. Much of the motivation behind Torii is introduced in &lt;a href=&quot;http://madhatted.com/2014/6/17/authentication-for-single-page-apps&quot;&gt;this blog post from last summer&lt;/a&gt;. Unlike the popular Devise gem for Rails, Torii attempts to do little by default. Instead, it focuses on providing useful primitives and a conventional authentication lifecycle.&lt;/p&gt;

&lt;p&gt;Over the past year Torii has grown popular. We&#8217;ve started to learn what patterns work across many apps and which ones should be avoided.&lt;/p&gt;

&lt;p&gt;Torii 0.6.0, with amazing help from many contributors, formalizes several of these best practices into features. These include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OAuth 2.0 state support, securing applications from CSRF attack&lt;/li&gt;
&lt;li&gt;Exposing &lt;code&gt;torii&lt;/code&gt; and the opt-in &lt;code&gt;session&lt;/code&gt; support as Ember services&lt;/li&gt;
&lt;li&gt;Adding a test helper for stubbing session state&lt;/li&gt;
&lt;li&gt;Introducing support for flagging routes as &#8220;authenticated&#8221; in Ember&#8217;s router DSL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lastly we&#8217;ve worked quite hard to ensure &lt;strong&gt;Torii 0.6.0 is still compatible with Ember.js 1.12, and supports all versions up to the current 2.1 betas without raising deprecations&lt;/strong&gt;. This makes Torii 0.6.x a good version to use when migrating to Ember 2.x.&lt;/p&gt;

&lt;p&gt;In Torii 0.7.0 we&#8217;re aiming to ship two big changes: Porting Torii into a traditional Ember-CLI addon (this will likely mean the removal of Torii&#8217;s &#8220;globals&#8221; mode support), and &lt;a href=&quot;https://github.com/Vestorly/torii/pull/206&quot;&gt;an iframe flow&lt;/a&gt; the provides an alternative to the popups we use for OAuth today.&lt;/p&gt;

&lt;p&gt;But let&#8217;s take a look at these 0.6.0 features in detail.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;&lt;a href=&quot;https://github.com/vestorly/torii&quot;&gt;Torii&lt;/a&gt; is an authentication library for Ember.js. Much of the motivation behind Torii is introduced in &lt;a href=&quot;http://madhatted.com/2014/6/17/authentication-for-single-page-apps&quot;&gt;this blog post from last summer&lt;/a&gt;. Unlike the popular Devise gem for Rails, Torii attempts to do little by default. Instead, it focuses on providing useful primitives and a conventional authentication lifecycle.&lt;/p&gt;

&lt;p&gt;Over the past year Torii has grown popular. We&#8217;ve started to learn what patterns work across many apps and which ones should be avoided.&lt;/p&gt;

&lt;p&gt;Torii 0.6.0, with amazing help from many contributors, formalizes several of these best practices into features. These include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OAuth 2.0 state support, securing applications from CSRF attack&lt;/li&gt;
&lt;li&gt;Exposing &lt;code&gt;torii&lt;/code&gt; and the opt-in &lt;code&gt;session&lt;/code&gt; support as Ember services&lt;/li&gt;
&lt;li&gt;Adding a test helper for stubbing session state&lt;/li&gt;
&lt;li&gt;Introducing support for flagging routes as &#8220;authenticated&#8221; in Ember&#8217;s router DSL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lastly we&#8217;ve worked quite hard to ensure &lt;strong&gt;Torii 0.6.0 is still compatible with Ember.js 1.12, and supports all versions up to the current 2.1 betas without raising deprecations&lt;/strong&gt;. This makes Torii 0.6.x a good version to use when migrating to Ember 2.x.&lt;/p&gt;

&lt;p&gt;In Torii 0.7.0 we&#8217;re aiming to ship two big changes: Porting Torii into a traditional Ember-CLI addon (this will likely mean the removal of Torii&#8217;s &#8220;globals&#8221; mode support), and &lt;a href=&quot;https://github.com/Vestorly/torii/pull/206&quot;&gt;an iframe flow&lt;/a&gt; the provides an alternative to the popups we use for OAuth today.&lt;/p&gt;

&lt;p&gt;But let&#8217;s take a look at these 0.6.0 features in detail.&lt;/p&gt;
&lt;h2&gt;OAuth 2.0 &#8220;state&#8221;&lt;/h2&gt;

&lt;p&gt;OAuth 2.0 &lt;a href=&quot;https://tools.ietf.org/html/rfc6749#section-10.12&quot;&gt;recommends &#8220;state&#8221; to protect against CSRF attacks&lt;/a&gt;. Support for clients is optional, and the impact of CSRF varies from workflow to workflow in OAuth2. Some support from the provider is required, however many providers already support state.&lt;/p&gt;

&lt;p&gt;The delightful &lt;a href=&quot;https://twitter.com/alisdair&quot;&gt;@alisdair&lt;/a&gt; added transparent support for OAuth2 state to Torii in 0.6.0. This grants existing users improved protection against CSRF attacks on their authentication system. Current users of Torii only need to upgrade to 0.6.0, everything else is done by the library. See &lt;a href=&quot;https://github.com/Vestorly/torii/pull/217&quot;&gt;#217&lt;/a&gt; for more details.&lt;/p&gt;

&lt;h2&gt;Using Ember Services&lt;/h2&gt;

&lt;p&gt;Torii is fairly &#8220;mature&#8221;, and by that I mean it predates some APIs we take for granted in Ember today. One of these is Ember&#8217;s excellent service and lazy dependency injection system. Before 0.6.0, accessing Torii or the &lt;a href=&quot;https://github.com/vestorly/torii#session-management&quot;&gt;opt-in session service&lt;/a&gt; from a component was clumsy at best.&lt;/p&gt;

&lt;p&gt;In 0.6.0, simply use &lt;code&gt;Ember.inject.service&lt;/code&gt;:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;// app/components/open-facebook-auth.js&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;import&lt;/span&gt; Ember from &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ember&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;default&lt;/span&gt; Ember.Component.extend({&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;ke&quot;&gt;torii&lt;/span&gt;: Ember.inject.service(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;torii&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;),&lt;tt&gt;
&lt;/tt&gt;  click() {&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;.get(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;torii&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;).open(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;facebook-oauth2&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;).then((result) =&amp;gt; {&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;.sendAction(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;didOpenAuth&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, result);&lt;tt&gt;
&lt;/tt&gt;    });&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;});&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;To opt-in to Torii&#8217;s session management, you must configure a service name via &lt;code&gt;sessionServiceName&lt;/code&gt; in &lt;code&gt;config/environment.js&lt;/code&gt;. That configured name, say &#8220;session&#8221;, is also available as a service name.&lt;/p&gt;

&lt;p&gt;Please note that this change introduces a small breaking change in Torii: &lt;strong&gt;The &lt;code&gt;torii:main&lt;/code&gt; factory has been renamed &lt;code&gt;service:torii&lt;/code&gt;, and the configured session service name will also be prefixed by &lt;code&gt;service:&lt;/code&gt;, for example &lt;code&gt;service:session&lt;/code&gt;.&lt;/strong&gt; Both services are still injected on routes and controllers, as in previous versions of Torii.&lt;/p&gt;

&lt;p&gt;Thanks to &lt;a href=&quot;https://twitter.com/pzuraq&quot;&gt;@pzuraq&lt;/a&gt; for implementing this change.&lt;/p&gt;

&lt;h2&gt;New Testing Helper&lt;/h2&gt;

&lt;p&gt;Users of Torii&#8217;s opt-in session management need a way to stub authenticated states for testing. We still recommend mocking AJAX responses for testing sign-in and session restoration, however for testing unrelated features this is a slow and cumbersome method to mock signed-in state.&lt;/p&gt;

&lt;p&gt;0.6.0 introduces &lt;a href=&quot;https://github.com/vestorly/torii#test-helpers&quot;&gt;test helpers for Torii&lt;/a&gt;, specifically &lt;code&gt;stubValidSession&lt;/code&gt;. Thanks to our friend &lt;a href=&quot;https://twitter.com/jagthedrummer&quot;&gt;@jagthedrummer&lt;/a&gt; for implementing this.&lt;/p&gt;

&lt;h2&gt;Authenticated Route DSL&lt;/h2&gt;

&lt;p&gt;Ember&#8217;s nested routes present an ideal platform for flagging part of an app as requiring authentication. Usually this is done with a mixin, and toggling a flag on the route class. We&#8217;ve found that a difficult to use API. When first getting into a codebase, this important detail is buried.&lt;/p&gt;

&lt;p&gt;Torii 0.6.0 features a powerful new way to require authentication for a route. For example, given a codebase opted-in to Torii&#8217;s session management:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;// app/router.js&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;import&lt;/span&gt; Ember from &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ember&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;Router.map(&lt;span class=&quot;kw&quot;&gt;function&lt;/span&gt;(){&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;.route(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;about&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;.route(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sign-in&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;.authenticatedRoute(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;dashboard&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, {}, &lt;span class=&quot;kw&quot;&gt;function&lt;/span&gt;(){&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;.route(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;  });&lt;tt&gt;
&lt;/tt&gt;});&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;When any route in this application is visited, &lt;a href=&quot;https://github.com/Vestorly/torii/blob/2cadf8e2389e900430ac8da4aabf61f7c0d0bf64/lib/torii/routing/application-route-mixin.js#L15&quot;&gt;&lt;code&gt;checkLogin&lt;/code&gt;&lt;/a&gt; will be called on the application route with a default behavior of silently checking for a session named &lt;code&gt;application&lt;/code&gt;. Attempts to access the &lt;code&gt;dashboard&lt;/code&gt; without a session will trigger an &lt;code&gt;accessDenied&lt;/code&gt; action on the route. Implementing &lt;code&gt;accessDenied&lt;/code&gt; with an appropriate redirect is left to the developer. &lt;/p&gt;

&lt;p&gt;Read more about this API in &lt;a href=&quot;https://github.com/Vestorly/torii#router-dsl&quot;&gt;the Torii readme&lt;/a&gt;, and thanks to &lt;a href=&quot;https://twitter.com/tarasm&quot;&gt;@tarasm&lt;/a&gt; for completing a tricky implementation process! &lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://madhatted.com/">
    <author>
      <name>mixonic</name>
    </author>
    <id>tag:madhatted.com,2015-08-25:3638</id>
    <published>2015-08-25T14:03:00Z</published>
    <updated>2015-08-25T14:18:27Z</updated>
    <link href="http://madhatted.com/2015/8/25/content-kit-programmatic-editing" rel="alternate" type="text/html"/>
    <title>Content-Kit: Programmatic Editing</title>
<summary type="html">&lt;p&gt;Last month, I &lt;a href=&quot;http://madhatted.com/2015/7/31/announcing-content-kit-and-mobiledoc&quot;&gt;blogged about the initial release of Content-Kit&lt;/a&gt;. &lt;a href=&quot;https://github.com/bustlelabs/content-kit-editor&quot;&gt;Content-Kit&lt;/a&gt; is a WYSIWYG editing library for the web, built with &lt;a href=&quot;http://www.bustle.com/labs&quot;&gt;Bustle Labs&lt;/a&gt;. Instead of saving edited posts as HTML, Content-Kit saves posts as an easy-to-render &lt;a href=&quot;https://github.com/bustlelabs/content-kit-editor/blob/master/MOBILEDOC.md&quot;&gt;Mobiledoc&lt;/a&gt; format. Since that post, we&#8217;ve been talking to some other parties interested in our early alpha-quality work.&lt;/p&gt;

&lt;p&gt;Some of the feedback we got from developers looking into Content-Kit is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The content they publish includes rich fragments that can take advantage of Mobiledoc&#8217;s &lt;a href=&quot;https://github.com/bustlelabs/content-kit-editor/blob/master/CARDS.md&quot;&gt;cards API&lt;/a&gt;. This is often more important to them than real-time editing, for instance.&lt;/li&gt;
&lt;li&gt;Their previous experiences with the quirks of Content Editable have made them eager to explore other alternatives.&lt;/li&gt;
&lt;li&gt;They demand customization of the UI. Not only of button style and placement, but of inline experiences. One use-case was to allow Markdown-ish content entry (using &lt;code&gt;**&lt;/code&gt; to start bold markup), another was to display a drop-down of user handles when &lt;code&gt;@&lt;/code&gt; is entered.&lt;/li&gt;
&lt;li&gt;At times, they want to limit how and what a user can edit in a post.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our original suspicion was that Content-Kit needed to ship with an out-of-the-box ready-to-use UI in order to gain adoption. After these discussions it is clear no users are particularly excited about a stock user-interface, and most are very excited about increased programmatic control over the editor.&lt;/p&gt;

&lt;p&gt;This marks a slight change in direction for Content-Kit. &lt;strong&gt;We plan to port much of the existing Content-Kit interface to an Ember Addon&lt;/strong&gt;. Content-Kit itself should slowly lose UI features, and gain APIs for programmatic editing of a post.&lt;/p&gt;

&lt;p&gt;Last week we started working with these new assumptions, and began fleshing out APIs. Let&#8217;s take a look.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Last month, I &lt;a href=&quot;http://madhatted.com/2015/7/31/announcing-content-kit-and-mobiledoc&quot;&gt;blogged about the initial release of Content-Kit&lt;/a&gt;. &lt;a href=&quot;https://github.com/bustlelabs/content-kit-editor&quot;&gt;Content-Kit&lt;/a&gt; is a WYSIWYG editing library for the web, built with &lt;a href=&quot;http://www.bustle.com/labs&quot;&gt;Bustle Labs&lt;/a&gt;. Instead of saving edited posts as HTML, Content-Kit saves posts as an easy-to-render &lt;a href=&quot;https://github.com/bustlelabs/content-kit-editor/blob/master/MOBILEDOC.md&quot;&gt;Mobiledoc&lt;/a&gt; format. Since that post, we&#8217;ve been talking to some other parties interested in our early alpha-quality work.&lt;/p&gt;

&lt;p&gt;Some of the feedback we got from developers looking into Content-Kit is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The content they publish includes rich fragments that can take advantage of Mobiledoc&#8217;s &lt;a href=&quot;https://github.com/bustlelabs/content-kit-editor/blob/master/CARDS.md&quot;&gt;cards API&lt;/a&gt;. This is often more important to them than real-time editing, for instance.&lt;/li&gt;
&lt;li&gt;Their previous experiences with the quirks of Content Editable have made them eager to explore other alternatives.&lt;/li&gt;
&lt;li&gt;They demand customization of the UI. Not only of button style and placement, but of inline experiences. One use-case was to allow Markdown-ish content entry (using &lt;code&gt;**&lt;/code&gt; to start bold markup), another was to display a drop-down of user handles when &lt;code&gt;@&lt;/code&gt; is entered.&lt;/li&gt;
&lt;li&gt;At times, they want to limit how and what a user can edit in a post.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our original suspicion was that Content-Kit needed to ship with an out-of-the-box ready-to-use UI in order to gain adoption. After these discussions it is clear no users are particularly excited about a stock user-interface, and most are very excited about increased programmatic control over the editor.&lt;/p&gt;

&lt;p&gt;This marks a slight change in direction for Content-Kit. &lt;strong&gt;We plan to port much of the existing Content-Kit interface to an Ember Addon&lt;/strong&gt;. Content-Kit itself should slowly lose UI features, and gain APIs for programmatic editing of a post.&lt;/p&gt;

&lt;p&gt;Last week we started working with these new assumptions, and began fleshing out APIs. Let&#8217;s take a look.&lt;/p&gt;
&lt;h2&gt;Post Editing API&lt;/h2&gt;

&lt;p&gt;Content-Kit maintains a representation of the current post in what we call the &#8220;post abstract&#8221;. When a post changes, we need to re-render the editing surface and position the cursor correctly. For example, when a user hits &#8220;enter&#8221;, several operations to the post may take place. A few markers may be split, possibly some may be deleted, and a new section may be created.&lt;/p&gt;

&lt;p&gt;Rendering speed is extremely important for an editing surface. We want to update the UI as quickly as the user taps a key. Fast typists &lt;a href=&quot;http://smallbusiness.chron.com/good-typing-speed-per-minute-71789.html&quot;&gt;hit about 325 characters per minute&lt;/a&gt;, which means a max render budget of 184ms to update the screen before rendering falls behind. To make the UX feel smooth, &lt;a href=&quot;http://www.nngroup.com/articles/response-times-3-important-limits/&quot;&gt;100ms is a good target budget&lt;/a&gt; for most UI responsiveness. With editing and typing interfaces, we should likely be even faster.&lt;/p&gt;

&lt;p&gt;Content-Kit must provide an editing API that allows flexibility, but flush the changed post abstract to DOM only once.&lt;/p&gt;

&lt;p&gt;To do this, we have the user batch all editing operations in a &lt;code&gt;run&lt;/code&gt; method. This in turn flushes work queues after any methods are called. For example, this code removes the section under the cursor and replaces it with a card section:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;let {&lt;span class=&quot;ke&quot;&gt;headSection&lt;/span&gt;: sectionWithCursor} = editor.cursor.offsets;&lt;tt&gt;
&lt;/tt&gt;editor.run(postEditor =&amp;gt; {&lt;tt&gt;
&lt;/tt&gt;  let cardSection = editor.builder.createCardSection(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fancy-card&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt; {&lt;span class=&quot;ke&quot;&gt;payload&lt;/span&gt;: &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;});&lt;tt&gt;
&lt;/tt&gt;  postEditor.insertSectionBefore(cardSection, sectionWithCursor.next);&lt;tt&gt;
&lt;/tt&gt;  postEditor.removeSection(sectionWithCursor);&lt;tt&gt;
&lt;/tt&gt;});&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Note that only code mutating the post must use the &lt;code&gt;postEditor&lt;/code&gt; and &lt;code&gt;run&lt;/code&gt; method. Fetching cursor position, for example, is not a mutating call and thus can happen at any time.&lt;/p&gt;

&lt;p&gt;Further initial documentation on the post editing API can be found in the &lt;a href=&quot;https://github.com/bustlelabs/content-kit-editor#programmatic-post-editing&quot;&gt;README&lt;/a&gt; and &lt;a href=&quot;https://github.com/bustlelabs/content-kit-editor/blob/master/src/js/editor/post.js&quot;&gt;editor/post.js&lt;/a&gt; file.&lt;/p&gt;

&lt;h2&gt;Content-Kit Lifecycle Hooks&lt;/h2&gt;

&lt;p&gt;Some kinds of UI require notification when the post abstract is changed, or when the editing surface is re-rendered. For example, to display a list of usernames after &lt;code&gt;@&lt;/code&gt; is typed the
input to Content-Kit must be observed.&lt;/p&gt;

&lt;p&gt;One strategy we considered was to punt this responsibility to native browser event handling. Force developers to respond to key and mouse events themselves when wrapping Content-Kit. However we think this approach would be error prone and likely cause poor performance if the resulting handler needed to call &lt;code&gt;run&lt;/code&gt; to make its own updates.&lt;/p&gt;

&lt;p&gt;In &lt;a href=&quot;https://github.com/bustlelabs/content-kit-editor/issues/84&quot;&gt;#84&lt;/a&gt; we propose three lifecycle hooks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;didUpdatePost&lt;/code&gt; is called before post changes are rendered. This allows it to make changes with the &lt;code&gt;postEditor&lt;/code&gt;, which it is passed, before rendering. You could use this hook to implement text commands, for example converting &lt;code&gt;**&lt;/code&gt; into a bold marker to emulate Markdown syntax.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;willRender&lt;/code&gt; is called at the start of rendering, when the post is guaranteed updated but the DOM has not been changed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;didRender&lt;/code&gt; is called after rendering, when the post and DOM are synchronized.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, &lt;code&gt;didRender&lt;/code&gt; could be used to silently save the post after each successful change:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;editor.didRender(() =&amp;gt; {&lt;tt&gt;
&lt;/tt&gt;  let mobiledoc = editor.serialize();&lt;tt&gt;
&lt;/tt&gt;  savePostDebounced(mobiledoc);&lt;tt&gt;
&lt;/tt&gt;});&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;These hooks will ship with Content-Kit this week. To accompany them, we also plan iteration APIs for sections and markers (and possibly the tree of the post abstract). These combined will provide a rich API to build features like validation on top of.&lt;/p&gt;

&lt;h2&gt;Disabling Input&lt;/h2&gt;

&lt;p&gt;Limiting what users may input into a post (what cards, what markup) can be achieved by limiting their UI options. Content-Kit will continue to push that concern to UI implementations, like the Ember Addon, and to API consumers.&lt;/p&gt;

&lt;p&gt;However, Content-Kit must offer a way to suspend text editing capability itself to enable the strictest limitations on content. At Bustle, we&#8217;re using non-user-editable Content-Kit instances to organize content based entirely on cards.&lt;/p&gt;

&lt;p&gt;In &lt;a href=&quot;https://github.com/bustlelabs/content-kit-editor/pull/82&quot;&gt;#82&lt;/a&gt;, two methods on the editor were introduced:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;editor.disableInput()&lt;/code&gt; - disallow edits via the cursor&lt;/li&gt;
&lt;li&gt;&lt;code&gt;editor.enableInput()&lt;/code&gt; - resume standard text editing behaviors&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Extracting the UI&lt;/h2&gt;

&lt;p&gt;Content-Kit currently offers a rough user interface largely modeled on the excellent work of &lt;a href=&quot;http://medium.com&quot;&gt;medium&lt;/a&gt;. We&#8217;ve found that many developers are not interested in using the provided interface. Even with customization APIs, there was not enough flexibility to cover all use-cases.&lt;/p&gt;

&lt;p&gt;The above APIs are intended to power external UI libraries wrapping Content-Kit.&lt;/p&gt;

&lt;p&gt;With Bustle, we will be prototyping a new UI implementation based on Ember components.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A UI library based on Ember will be more customizable and flexible than what we could reasonably build in plain JavaScript&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;An Ember library will also allow cards to be implemented as Ember components&lt;/strong&gt;, making new content experiences easier and faster to implement, as well as easily tested.&lt;/li&gt;
&lt;li&gt;Building this library forces us to &#8220;dogfood&#8221; the public API for Content-Kit, making it more robust and well-considered.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An Ember Addon will be released in early September. We already have an internal prototype, and are using it to shape the public APIs in Content-Kit as we flesh it out.&lt;/p&gt;

&lt;p&gt;Despite the selection of Ember for our improved Content-Kit UI, &lt;strong&gt;we encourage the use of Content-Kit with other interface frameworks&lt;/strong&gt;. You can find us in the &lt;a href=&quot;https://gitter.im/bustlelabs/content-kit-editor&quot;&gt;Gitter chat&lt;/a&gt; if you want to kick around ideas.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Big thanks to &lt;a href=&quot;http://www.bustle.com/labs&quot;&gt;Bustle Labs&lt;/a&gt; for continued sponsorship of our work on Content-Kit. We&#8217;re having a great summer working with their smart and fun team here in NYC. Bustle is looking for senior software engineers and senior UX designers to join their crew.&lt;/em&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://madhatted.com/">
    <author>
      <name>mixonic</name>
    </author>
    <id>tag:madhatted.com,2015-07-31:3627</id>
    <published>2015-07-31T15:53:00Z</published>
    <updated>2015-07-31T16:28:11Z</updated>
    <link href="http://madhatted.com/2015/7/31/announcing-content-kit-and-mobiledoc" rel="alternate" type="text/html"/>
    <title>Announcing Content-Kit and Mobiledoc</title>
<summary type="html">&lt;p&gt;&lt;a href=&quot;http://www.bustle.com/labs&quot;&gt;Bustle Labs&lt;/a&gt; is the tech team behind the editorial staff at &lt;a href=&quot;http://www.bustle.com/&quot;&gt;Bustle&lt;/a&gt;, a fantastic feminist and women&#8217;s interest site. Early last year they started work on a WYSIWYG editing surface called &lt;strong&gt;Content-Kit&lt;/strong&gt;. &lt;a href=&quot;http://www.201-created.com&quot;&gt;201 Created&lt;/a&gt; has been helping to bring Content-Kit to completion this summer.&lt;/p&gt;

&lt;p&gt;Content-Kit is a completely new approach to post and article editing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It makes limited use of Content Editable, the siren-song of doomed web editor technologies.&lt;/li&gt;
&lt;li&gt;Content-Kit is designed for &lt;em&gt;rich&lt;/em&gt; content. We call these sections of an article &#8220;cards,&#8221; and implementing a new one doesn&#8217;t require an understanding of Content-Kit internals. Adding a new card take an afternoon, not several days. &lt;/li&gt;
&lt;li&gt;Posts are serialized to a JSON payload called &lt;strong&gt;Mobiledoc&lt;/strong&gt; instead of to HTML. Mobiledoc can be rendered for the web, mobile web, or, in theory, on any platform. Mobiledoc is portable and fast.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can &lt;a href=&quot;http://content-kit.herokuapp.com/&quot;&gt;try pre-1.0 Content-Kit right now&lt;/a&gt;, or check out the 100% MIT licensed &lt;a href=&quot;https://github.com/bustlelabs/content-kit-editor&quot;&gt;Content-Kit source code&lt;/a&gt;. The &lt;a href=&quot;https://github.com/bustlelabs/mobiledoc-dom-renderer&quot;&gt;Mobiledoc DOM renderer&lt;/a&gt; and &lt;a href=&quot;https://github.com/bustlelabs/mobiledoc-html-renderer&quot;&gt;Mobiledoc HTML renderer&lt;/a&gt; are available.&lt;/p&gt;

&lt;p&gt;Let&#8217;s talk about Content-Kit and Mobiledoc, and what remains for them to hit 1.0.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;&lt;a href=&quot;http://www.bustle.com/labs&quot;&gt;Bustle Labs&lt;/a&gt; is the tech team behind the editorial staff at &lt;a href=&quot;http://www.bustle.com/&quot;&gt;Bustle&lt;/a&gt;, a fantastic feminist and women&#8217;s interest site. Early last year they started work on a WYSIWYG editing surface called &lt;strong&gt;Content-Kit&lt;/strong&gt;. &lt;a href=&quot;http://www.201-created.com&quot;&gt;201 Created&lt;/a&gt; has been helping to bring Content-Kit to completion this summer.&lt;/p&gt;

&lt;p&gt;Content-Kit is a completely new approach to post and article editing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It makes limited use of Content Editable, the siren-song of doomed web editor technologies.&lt;/li&gt;
&lt;li&gt;Content-Kit is designed for &lt;em&gt;rich&lt;/em&gt; content. We call these sections of an article &#8220;cards,&#8221; and implementing a new one doesn&#8217;t require an understanding of Content-Kit internals. Adding a new card take an afternoon, not several days. &lt;/li&gt;
&lt;li&gt;Posts are serialized to a JSON payload called &lt;strong&gt;Mobiledoc&lt;/strong&gt; instead of to HTML. Mobiledoc can be rendered for the web, mobile web, or, in theory, on any platform. Mobiledoc is portable and fast.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can &lt;a href=&quot;http://content-kit.herokuapp.com/&quot;&gt;try pre-1.0 Content-Kit right now&lt;/a&gt;, or check out the 100% MIT licensed &lt;a href=&quot;https://github.com/bustlelabs/content-kit-editor&quot;&gt;Content-Kit source code&lt;/a&gt;. The &lt;a href=&quot;https://github.com/bustlelabs/mobiledoc-dom-renderer&quot;&gt;Mobiledoc DOM renderer&lt;/a&gt; and &lt;a href=&quot;https://github.com/bustlelabs/mobiledoc-html-renderer&quot;&gt;Mobiledoc HTML renderer&lt;/a&gt; are available.&lt;/p&gt;

&lt;p&gt;Let&#8217;s talk about Content-Kit and Mobiledoc, and what remains for them to hit 1.0.&lt;/p&gt;
&lt;h2&gt;Cards&lt;/h2&gt;

&lt;p&gt;The implementation details of Content-Kit, or any WYSIWYG editor, are incredibly interesting. But before diving into that discussion, I want to talk about the most important feature of Content-Kit and Mobiledoc.&lt;/p&gt;

&lt;p&gt;Modern article or post content has moved beyond text. &lt;a href=&quot;http://madhatted.com&quot;&gt;madhatted.com&lt;/a&gt; is pretty simple, but a post on Bustle, Verge, or the NYTimes could easily contain several different kinds of sections. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A full-bleed image and title.&lt;/li&gt;
&lt;li&gt;An introductory paragraph of text.&lt;/li&gt;
&lt;li&gt;A chart providing context for the article.&lt;/li&gt;
&lt;li&gt;Several paragraphs of text.&lt;/li&gt;
&lt;li&gt;A slideshow of a few photographs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Many web editors render the final version of this content into HTML when persisting. Consequently, adding new kinds of sections means wrestling with complex editor internals. Content-Kit&#8217;s cards API is designed to alleviate this burden.&lt;/p&gt;

&lt;p&gt;Persisting a rendered version of an article also limits the post from being improved or rendered differently in another environment. For Bustle, there are three main rendering targets to consider. On each, we can support a different level of interactivity.&lt;/p&gt;

&lt;table&gt;

&lt;tr&gt;
Desktop Web
Mobile Web
Mobile iOS
&lt;/tr&gt;


&lt;tr&gt;
&lt;td&gt;Full bleed image&lt;/td&gt;
&lt;td&gt;Full bleed image&lt;/td&gt;
&lt;td&gt;Full bleed image&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Text as HTML&lt;/td&gt;
&lt;td&gt;Text as HTML&lt;/td&gt;
&lt;td&gt;Text as HTML (rendered in web view)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Interactive SVG Chart&lt;/td&gt;
&lt;td&gt;Static SVG Chart&lt;/td&gt;
&lt;td&gt;Image linking to full-screen native interactive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inline slideshow&lt;/td&gt;
&lt;td&gt;Image with a click opening a full-screen slideshow&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;

&lt;p&gt;Additionally, the implementation of a slideshow will change over time. Coupling the DOM to any particular version means painful data-migrations are needed for old content.&lt;/p&gt;

&lt;p&gt;Content presentation that varies at runtime demands a new persistence format. We&#8217;ve created one named Mobiledoc.&lt;/p&gt;

&lt;p&gt;Mobiledoc stores post or article content as data, not DOM. For example this Mobiledoc has a headline, chart, and body of text:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;{&lt;tt&gt;
&lt;/tt&gt;  version: &amp;quot;0.1&amp;quot;,                          ---- Versioning information&lt;tt&gt;
&lt;/tt&gt;  sections: [[],[&lt;tt&gt;
&lt;/tt&gt;    [1, &amp;quot;h2&amp;quot;, [                            ----&lt;tt&gt;
&lt;/tt&gt;      [[], 0, &amp;quot;Understanding Content-Kit&amp;quot;]    | Text section wrapped in an h2&lt;tt&gt;
&lt;/tt&gt;    ]],                                    ----&lt;tt&gt;
&lt;/tt&gt;    [10, &amp;quot;slideshow&amp;quot;, [                    ----&lt;tt&gt;
&lt;/tt&gt;      &amp;quot;pic2.jpg&amp;quot;,                             | Slideshow card, with an array&lt;tt&gt;
&lt;/tt&gt;      &amp;quot;pic3.jpg&amp;quot;                              | payload of images&lt;tt&gt;
&lt;/tt&gt;    ]],                                    ----&lt;tt&gt;
&lt;/tt&gt;    [1, &amp;quot;p&amp;quot;, [                             ----&lt;tt&gt;
&lt;/tt&gt;      [[], 0, &amp;quot;What a nice, short post&amp;quot;]      | Text section wrapped in a p&lt;tt&gt;
&lt;/tt&gt;    ]]                                     ----&lt;tt&gt;
&lt;/tt&gt;  ]]&lt;tt&gt;
&lt;/tt&gt;}&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Importantly, Mobiledoc says nothing about how cards are edited or rendered. Instead, the editor or rendering runtime must be passed a handler conforming to the card API. For example, passing a slideshow display to the DOM renderer:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kw&quot;&gt;var&lt;/span&gt; SlideshowCard = {&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;ke&quot;&gt;name&lt;/span&gt;: &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;slideshow&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;ke&quot;&gt;display&lt;/span&gt;: {&lt;tt&gt;
&lt;/tt&gt;    setup(element, options, env, payload) {&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;kw&quot;&gt;var&lt;/span&gt; img = &lt;span class=&quot;pd&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;lt;img style=&amp;quot;cursor:pointer&amp;quot;&amp;gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;kw&quot;&gt;var&lt;/span&gt; index = &lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;      img.&lt;tt&gt;
&lt;/tt&gt;        attr(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, payload[index]).&lt;tt&gt;
&lt;/tt&gt;        appendTo(element).&lt;tt&gt;
&lt;/tt&gt;        click(&lt;span class=&quot;kw&quot;&gt;function&lt;/span&gt;(){&lt;tt&gt;
&lt;/tt&gt;          index++;&lt;tt&gt;
&lt;/tt&gt;          &lt;span class=&quot;kw&quot;&gt;if&lt;/span&gt; (!payload[index]) {&lt;tt&gt;
&lt;/tt&gt;            index = &lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;          }&lt;tt&gt;
&lt;/tt&gt;          img.attr(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, payload[index]);&lt;tt&gt;
&lt;/tt&gt;        });&lt;tt&gt;
&lt;/tt&gt;    }&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;};&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;kw&quot;&gt;var&lt;/span&gt; renderer = &lt;span class=&quot;kw&quot;&gt;new&lt;/span&gt; MobiledocDOMRenderer();&lt;tt&gt;
&lt;/tt&gt;renderer.render(mobiledoc, &lt;span class=&quot;pd&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;.post&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)[&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;], &lt;span class=&quot;ke&quot;&gt;cards&lt;/span&gt;: {&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;ke&quot;&gt;slideshow&lt;/span&gt;: slideshow&lt;tt&gt;
&lt;/tt&gt;});&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Mobiledoc renderers require cards to expose a setup hook for display cases. Additionally, when a card is passed to an editor instance an &lt;code&gt;edit&lt;/code&gt; hook must be fulfilled. There is an optional teardown hook, and the &lt;code&gt;env&lt;/code&gt; object will
include triggers to moving between edit and preview. One of these, &lt;code&gt;save&lt;/code&gt;, accepts the argument of a data payload to be stored in the Mobiledoc. In our example above, this was the URLs array.&lt;/p&gt;

&lt;p&gt;By allowing cards to be implemented at runtime, they can adapt or be swapped out to meet the needs of a given environment. By delegating only the editing and display logic to cards (not core parsing and rendering), Bustle developers can focus on building or enhancing the rich content tools they want to provide to the content team. They are liberated to create rich content experiences with Ember, React, or any other UI library that suits their needs.&lt;/p&gt;

&lt;p&gt;We&#8217;re excited by the potential of cards and Mobiledoc. Combined with something like Ember or React components, adding new editing and rich display experiences is a snap.&lt;/p&gt;

&lt;p&gt;Feel free to follow up by reading &lt;a href=&quot;https://github.com/bustlelabs/content-kit-editor/blob/d6f9ca85159b1aecc2a79c4e3b4b6ed146f7cc6e/demo/demo.js#L12&quot;&gt;some example cards in our demo&lt;/a&gt;, the &lt;a href=&quot;https://github.com/bustlelabs/content-kit-editor/blob/master/CARDS.md&quot;&gt;documentation on cards&lt;/a&gt; and &lt;a href=&quot;https://github.com/bustlelabs/content-kit-editor/blob/master/MOBILEDOC.md&quot;&gt;mobiledoc specs&lt;/a&gt;, or continue on to learn about the design decisions behind Content-Kit and Mobiledoc.&lt;/p&gt;

&lt;h2&gt;Moving away from Content Editable&lt;/h2&gt;

&lt;p&gt;The pains and limits of using HTML5 Content Editable are well understood by developers building text editing interfaces. The best editing experiences (we love &lt;a href=&quot;https://atom.io/&quot;&gt;Atom&lt;/a&gt; from Github, and &lt;a href=&quot;https://www.google.com/docs/about/&quot;&gt;Google Docs&lt;/a&gt;) avoid Content Editable APIs entirely.&lt;/p&gt;

&lt;p&gt;The difficult nature of Content Editable is that it conflates the previewed display of a document with its serialized and persisted form, using DOM for both. Often additional capability (runtime-defined behavior) is awkwardly embedded into DOM, or the natural flexibility of using the DOM to store content (including browser quirks and security issues) must be reined in.&lt;/p&gt;

&lt;p&gt;To build a great editing experience, it is clear we need to limit how much Content Editable is used or, ideally, avoid it entirely. By capturing events before they reach the default Content Editable behaviors, Content-Kit currently takes a hybrid approach. In the upcoming weeks, we plan to migrate further away from reliance on Content Editable.&lt;/p&gt;

&lt;p&gt;Content-Kit has an internal tree representing a document. The tree looks roughly like:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Posts&lt;/strong&gt; correspond to an entire article or document. &lt;strong&gt;Sections&lt;/strong&gt; represent top level data. For example, a headline tag would be a section, as would a paragraph tag. A card is also a section. Sections are ordered peers. Content-Kit has additional special section types that could likely become cards, but they also seem common enough to include as built-ins.&lt;/p&gt;

&lt;p&gt;In the Content-Kit editing surface, each section has a matching DOM node. &lt;strong&gt;Markers&lt;/strong&gt; do not map to single DOM node, but to a text node with opened and closed tags at its boundaries. Regardless of the depth of DOM nodes being represented by markers, they remain a shallow list.&lt;/p&gt;

&lt;p&gt;Content-Kit maintains the mapping of text nodes to markers. When an event happens inside a given DOM node, we can trace which marker is being referenced (if any) by checking that map. With markers and DOM, a simplified graph of Content-Kit&#8217;s internal post looks like (white-space added for sanity):&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;There are three markers in the text section:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first marker opens no tags, closes no tags, and has the text content of &#8220;A fantastic, &#8220;.&lt;/li&gt;
&lt;li&gt;The second marker opens a bold and italic tag, closes the italic tag, and has the text of &#8220;reliable&#8221;.&lt;/li&gt;
&lt;li&gt;The third marker opens no tags, closes the bold tag, and has the text &#8220;editor.&#8221;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This structuring of markup is wonderfully efficient to render, and takes less space than the corresponding HTML for an article payload. For example, here is the same article as above persisted into Mobiledoc:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;{&lt;tt&gt;
&lt;/tt&gt;  version: &amp;quot;0.1&amp;quot;,              ---- Versioning information&lt;tt&gt;
&lt;/tt&gt;  sections: [[                 ----&lt;tt&gt;
&lt;/tt&gt;    [&amp;quot;b&amp;quot;],                        |&lt;tt&gt;
&lt;/tt&gt;    [&amp;quot;i&amp;quot;]                         | Markup types. Referenced by markers.&lt;tt&gt;
&lt;/tt&gt;  ],[                          ----&lt;tt&gt;
&lt;/tt&gt;    [1, &amp;quot;p&amp;quot;, [                 ----&lt;tt&gt;
&lt;/tt&gt;      [[], 0, &amp;quot;A fantastic, &amp;quot;]    | Markup section with a p tag. Markers&lt;tt&gt;
&lt;/tt&gt;      [[0,1], 1, &amp;quot;reliable&amp;quot;],     | consist of a three markers.&lt;tt&gt;
&lt;/tt&gt;      [[], 1, &amp;quot; editor.&amp;quot;]         |&lt;tt&gt;
&lt;/tt&gt;    ]]                         ----&lt;tt&gt;
&lt;/tt&gt;  ]]&lt;tt&gt;
&lt;/tt&gt;}&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Content-Kit stills allows most text editing events to change the Content Editable DOM. During the &lt;code&gt;input&lt;/code&gt; event, targeted subsets of the post content are re-parsed into the abstract post. In the future, keystrokes will be captured and the post can be updated directly, then rerendered. For some kinds of event data, like pressing the enter key, we already do this.&lt;/p&gt;

&lt;p&gt;Content-Kit&#8217;s rendering system is directly inspired by the architecture of Ember&#8217;s Glimmer rendering engine. Render nodes are created during rendering, and manage the relationship of post content to the DOM. They track dirty state, allowing us to quickly render only the part of a post that has changed.&lt;/p&gt;

&lt;h2&gt;Getting to Content-Kit 1.0&lt;/h2&gt;

&lt;p&gt;We plan to bring Content-Kit to a 1.0 release in the next few weeks. This will mean the API for cards is stable, the UI is fairly polished and feature complete, and that we&#8217;ve integrated the editor into some internal Bustle tools.&lt;/p&gt;

&lt;p&gt;The most painful parts of Content Editable will be avoided by 1.0, though we may retain it for very narrow functionality (entering text). Using event capture, making changes directly to the abstract tree and rerendering the post will replace most formatting commands.&lt;/p&gt;

&lt;p&gt;Content-Kit is a flexible and powerful editor, and Mobiledoc paired with a generic cards API makes a great publishing tool. If you&#8217;re publishing for the web and interested in working with us to advance rich content, please say hello.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Big thanks to &lt;a href=&quot;http://www.bustle.com/labs&quot;&gt;Bustle Labs&lt;/a&gt; for making Content-Kit and the related libraries open source. We&#8217;re having a great summer working with their smart and fun team here in NYC. Bustle is looking for senior software engineers and senior UX designers to join their crew.&lt;/em&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://madhatted.com/">
    <author>
      <name>mixonic</name>
    </author>
    <id>tag:madhatted.com,2015-05-14:3581</id>
    <published>2015-05-14T00:17:00Z</published>
    <updated>2015-08-23T16:44:47Z</updated>
    <link href="http://madhatted.com/2015/5/14/ember-js-2-0-preview-with-canary" rel="alternate" type="text/html"/>
    <title>Previewing Ember 2.0 on Canary</title>
<content type="html">
            

&lt;p&gt;Ember.js 2.0 is right around the corner. Lots of the discussion around 2.0 has
focused rather narrowly on specific features, but there has been little reflection
(since the &lt;a href=&quot;https://github.com/emberjs/rfcs/pull/15&quot;&gt;RFC&lt;/a&gt;) on what 2.0 apps will
look like as a whole. I definitely recommend you read &lt;a href=&quot;http://emberjs.com/blog/2015/05/10/run-up-to-two-oh.html&quot;&gt;Yehuda&#8217;s transition
blog post&lt;/a&gt; though,
as it really lays out the nitty gritty.&lt;/p&gt;

&lt;p&gt;Meanwhile, Angular 2.0 is entering alpha this summer. You may have noticed several
talks on how to write an Angular 2.0 app from scratch. Many of the active
members of the Ember community maintain large 1.x applications, and thus
we tend to focus less on &#8220;from scratch&#8221; and more on how to manage the migration
forward.&lt;/p&gt;

&lt;p&gt;Thinking about apps &#8220;from scratch&#8221; is still useful for existing users though.
It reminds us where the framework is going, and why we invest time in
upgrades and learning new APIs. It also helps us be better teachers to new
users of the framework at work and in the community.&lt;/p&gt;

&lt;p&gt;Ember.js Canary is not Ember 2.0, but it is already a significant departure from what
an earlier 1.x app might have looked like. Let&#8217;s use it to get a preview of the Ember to
come.&lt;/p&gt;

&lt;h2&gt;Using Ember-CLI with Canary&lt;/h2&gt;

&lt;p&gt;I&#8217;m going to quickly show you how to build an idiomatic app with Ember.js Canary.
Canary is the cutting edge of Ember.js, and though it is not the &#8220;2.0&#8221;
release it definitely a close approximation.&lt;/p&gt;

&lt;p&gt;Ember-CLI is a fantastic tool, and has revolutionized how Ember applications
are developed. Using Ember-CLI is, at this point, required for a modern Ember app.
To install Ember-CLI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You will need to install Node.js 0.12. I often use a tool called &lt;a href=&quot;https://github.com/creationix/nvm&quot;&gt;nvm&lt;/a&gt; on a new
computer.&lt;/li&gt;
&lt;li&gt;You will need to install &lt;a href=&quot;https://www.npmjs.com/&quot;&gt;NPM&lt;/a&gt;, the Node Package Manager. This should come with your
Node.js installation. I&#8217;ve found that old versions of NPM can be
problematic, and encourage you to make sure you are on a recent release
by running &lt;code&gt;npm install -g npm&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;You should install or update your bower installation: &lt;code&gt;npm install -g bower&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you already have these tools, then you&#8217;re all set. Just run:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;npm install -g ember-cli@0.2.5&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Now we can create a new application with the command:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;ember new todo-list&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;To approximate Ember 2.0, we need to install Ember.js Canary and enable a few
feature flags. These are not steps a new developer would usually take, but bear with
me. &lt;code&gt;cd&lt;/code&gt; into the application directory, then install Ember.js and Ember-Data Canary:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;bower install components/ember#canary components/ember-data#canary --save&lt;tt&gt;
&lt;/tt&gt;# You may be prompted to resolve the version of Ember and/or Ember-Data.&lt;tt&gt;
&lt;/tt&gt;# If so choose the one labelled &amp;quot;canary&amp;quot; and use &amp;quot;!&amp;quot;. Usually you type&lt;tt&gt;
&lt;/tt&gt;# &amp;quot;!1&amp;quot; and hit enter.&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Feature flags are only available when using Ember Canary builds. Flags enable
certain code-paths in the framework, often at load time. To approximate 2.0,
we want to add these lines to &lt;code&gt;config/environment.js&lt;/code&gt;:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;// config/environment.js&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;module.exports = &lt;span class=&quot;kw&quot;&gt;function&lt;/span&gt;(environment) {&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;kw&quot;&gt;var&lt;/span&gt; ENV = {&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;c&quot;&gt;// ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;ke&quot;&gt;EmberENV&lt;/span&gt;: {&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;ke&quot;&gt;FEATURES&lt;/span&gt;: { &lt;span class=&quot;c&quot;&gt;// Here we enable some experimental features:&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ember-routing-htmlbars-improved-actions&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;: &lt;span class=&quot;kw&quot;&gt;true&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ember-views-component-block-info&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;: &lt;span class=&quot;kw&quot;&gt;true&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ember-htmlbars-component-generation&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;: &lt;span class=&quot;kw&quot;&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      }&lt;tt&gt;
&lt;/tt&gt;    },&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;c&quot;&gt;// ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  };&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;kw&quot;&gt;return&lt;/span&gt; ENV;&lt;tt&gt;
&lt;/tt&gt;};&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;The full list of available experimental features can be found in the
&lt;a href=&quot;https://github.com/emberjs/ember.js/blob/master/FEATURES.md&quot;&gt;FEATURES.md&lt;/a&gt; and
&lt;a href=&quot;https://github.com/emberjs/ember.js/blob/master/features.json&quot;&gt;features.json&lt;/a&gt;
file. You can read more about feature flags
&lt;a href=&quot;http://guides.emberjs.com/v1.11.0/configuring-ember/feature-flags/&quot;&gt;in the guides&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Lastly, we want to use the new &#8220;pods&#8221; directory layout for Ember apps. Edit
the &lt;code&gt;.ember-cli&lt;/code&gt; file and add the &lt;code&gt;&quot;usePods&quot;: true&lt;/code&gt; option:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;// .ember-cli&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;{&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;disableAnalytics&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span class=&quot;kw&quot;&gt;false&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;usePods&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span class=&quot;kw&quot;&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;}&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;And with that, we&#8217;re ready to start coding. Boot up the Ember-CLI server with
the following command:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;ember serve&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;And visit &lt;a href=&quot;http://localhost:4200&quot;&gt;http://localhost:4200&lt;/a&gt;. You should see
&#8220;Welcome to Ember.js&#8221; in your browser.&lt;/p&gt;

&lt;h2&gt;Creating Routes and Links&lt;/h2&gt;

&lt;p&gt;We&#8217;re going to build the most boring app we could write. I&#8217;ll guide you through writing
a very simple todos application, but if you&#8217;ve used Ember a simple app will let you focus
on what the idiomatic style is for a new codebase. If you&#8217;re new to Ember, there is
plenty to learn.&lt;/p&gt;

&lt;p&gt;First we need a URL for our items (&lt;code&gt;/items&lt;/code&gt;). Easy enough, Ember-CLI will generate the
needed files for us:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;ember generate route items&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;And we want to add a link to &lt;code&gt;/items&lt;/code&gt; from the &lt;code&gt;/&lt;/code&gt; page. To start, generate an index template:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;ember generate template index&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Index templates behave much like &lt;code&gt;index.html&lt;/code&gt; files on a webserver: They
are the default route (and template) served if you are not visiting a
specific sub-route.&lt;/p&gt;

&lt;p&gt;Edit the index template and add a link:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;{{! app/index/template.hbs }}&lt;tt&gt;
&lt;/tt&gt;{{link-to 'Items' 'items'}}&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;If you reload the &lt;code&gt;/&lt;/code&gt; URL in the browser, you will see a link to the &#8220;Items&#8221;.
If you click the link, you will be taken to &lt;code&gt;/items&lt;/code&gt; and the link will
disappear. Ember pages are nested inside outlets, and if you open the
&lt;code&gt;app/templates/application.hbs&lt;/code&gt; file you will find an outlet helper there.&lt;/p&gt;

&lt;p&gt;Changing the URL of an Ember application changes which route is mounted
on an outlet. The index route is the default route for &lt;code&gt;/&lt;/code&gt;, and thus is a
sibling of the &lt;code&gt;/items&lt;/code&gt; route. If you change the url from &lt;code&gt;/items&lt;/code&gt;
back to &lt;code&gt;/&lt;/code&gt;, the &lt;code&gt;app/index/template.hbs&lt;/code&gt; file will be loaded back into the
outlet. As sibling routes, &lt;code&gt;index&lt;/code&gt; and &lt;code&gt;items&lt;/code&gt; will share the outlet. Only one
can be rendered at a time.&lt;/p&gt;

&lt;p&gt;Install the Ember Inspector (&lt;a href=&quot;https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi&quot;&gt;Chrome&lt;/a&gt;, &lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/&quot;&gt;Firefox&lt;/a&gt;). After installation, open the developer tools (command-option i) and
click the &#8220;Ember&#8221; tab. Under &#8220;Routes&#8221; you can see the available routes and note
that the bold one changes as you navigate.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The inspector is a fantastic debugging tool. If you click &#8220;$E&#8221; near any object, that object
will be send to the console (as &lt;code&gt;$E&lt;/code&gt;) where you can investigate its state.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Note: The &#8220;View Tree&#8221; section in the inspector is likely broken due to updates
with Ember&#8217;s new Glimmer rendering engine. It should be fixed in the next
release.&lt;/i&gt;&lt;/p&gt;

&lt;h2&gt;Using an Ember.js Addon and Defining an Ember-Data Model&lt;/h2&gt;

&lt;p&gt;To keep our todo list across page refreshes, we will need to store it
somewhere. Ember-Data provides ways to save data to a server out of the box,
but not to save data to IndexDB (or the alternatives). Thankfully, there
is an addon that makes using Mozilla&#8217;s &lt;a href=&quot;http://mozilla.github.io/localForage/&quot;&gt;localForage&lt;/a&gt;
library a breeze.&lt;/p&gt;

&lt;p&gt;Addons are a little more than simply a library for your Ember application to
use. They can add code to the application runtime, but can also add or change
the build pipeline itself. For example, the compiler that turns Ember templates
into JavaScript objects before sending them to the browser is itself an addon.&lt;/p&gt;

&lt;p&gt;The addon we want is the &lt;a href=&quot;https://github.com/genkgo/ember-localforage-adapter&quot;&gt;ember-localforage-adapter&lt;/a&gt;. Installing it is easy:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;ember install ember-localforage-adapter&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;After installation you must restart the &lt;code&gt;ember serve&lt;/code&gt; server.&lt;/p&gt;

&lt;p&gt;Next we will need to configure an adapter for the application. Adapters tell
Ember-Data how to save model data after serialization (the process of converting
a record into a payload for persistence). The &#8220;application&#8221;
adapter is a special default adapter- it applies to any and all models we define.&lt;/p&gt;

&lt;p&gt;Create an application adapter and export the localforage adapter:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;ember generate adapter application&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;// app/application/adapter.js&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;import&lt;/span&gt; LFAdapter from &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ember-localforage-adapter/adapters/localforage&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;default&lt;/span&gt; LFAdapter;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;And next define the model for &#8220;item&#8221;:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;ember generate model item&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;// app/item/model.js&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;import&lt;/span&gt; DS from &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ember-data&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;default&lt;/span&gt; DS.Model.extend({&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;ke&quot;&gt;task&lt;/span&gt;: DS.attr(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;),&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;ke&quot;&gt;isDone&lt;/span&gt;: DS.attr(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;});&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;At this point, return to the inspector and click the &#8220;Data&#8221; section. Note that
there is a model type of &#8220;item&#8221; now, although there are no records to be
found. Later you can return to this section and see changes to the data.&lt;/p&gt;

&lt;h2&gt;Using Components and Actions&lt;/h2&gt;

&lt;p&gt;Most routes in an Ember application can be thought of as having a &#8220;subject&#8221;.
This object represents the focus of the user&#8217;s interaction for that route. We
call this subject the &#8220;model&#8221; of that route.&lt;/p&gt;

&lt;p&gt;For the items page, our subject is a list of items.
Edit the items route to return the items in our Ember-Data store:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;// app/items/route.js&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;import&lt;/span&gt; Ember from &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ember&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;default&lt;/span&gt; Ember.Route.extend({&lt;tt&gt;
&lt;/tt&gt;  model() {&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;kw&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;.get(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;).find(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;});&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;However we need to display the list. Additionally, we will want to input new
tasks. To do this edit the items template:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;{{! app/items/template.hbs }}&lt;tt&gt;
&lt;/tt&gt;&amp;lt;div&amp;gt;&lt;tt&gt;
&lt;/tt&gt;  &amp;lt;input-task on-enter={{action 'createTask'}} /&amp;gt;&lt;tt&gt;
&lt;/tt&gt;&amp;lt;/div&amp;gt;&lt;tt&gt;
&lt;/tt&gt;&amp;lt;ul&amp;gt;&lt;tt&gt;
&lt;/tt&gt;  {{#each model as |item|}}&lt;tt&gt;
&lt;/tt&gt;    &amp;lt;li&amp;gt;&lt;tt&gt;
&lt;/tt&gt;      &amp;lt;input type=&amp;quot;checkbox&amp;quot; checked={{item.isDone}} {{action 'toggleIsDone' item on=&amp;quot;change&amp;quot;}}&amp;gt;&lt;tt&gt;
&lt;/tt&gt;      &amp;lt;span&amp;gt;{{item.task}}&amp;lt;/span&amp;gt;&lt;tt&gt;
&lt;/tt&gt;    &amp;lt;/li&amp;gt;&lt;tt&gt;
&lt;/tt&gt;  {{/each}}&lt;tt&gt;
&lt;/tt&gt;&amp;lt;/ul&amp;gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;There are three interesting bits to this template:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&amp;lt;input-task on-enter={{action 'createTask'}}&amp;gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;This code calls an Ember component responsible for where new tasks are entered. When the user hits enter,
the action &#8220;createTask&#8221; will be called. The code calling the action (the input task component) decides what arguments will be passed.&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;{{#each model as |item|}}&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;The each helper iterates over an array of entries. In this case, it iterates over the items returned
from the model hook and yields the inner block of with the variable &lt;code&gt;item&lt;/code&gt;. In Ember we call &lt;code&gt;item&lt;/code&gt; or any other
value between the &lt;code&gt;|&lt;/code&gt; characters a block param.&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&amp;lt;input checked={{item.isDone}} {{action 'toggleIsDone' item on=&amp;quot;change&amp;quot;}}&amp;gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;There are two curly sections on this this line. First, the property &#8220;checked&#8221; is bound to whatever &lt;code&gt;item.isDone&lt;/code&gt;
is. Second, the &lt;code&gt;{{action&lt;/code&gt; helper attaches an event listener for change events on the &lt;code&gt;input&lt;/code&gt; tag. For each event triggered,
the &lt;code&gt;toggleIsDone&lt;/code&gt; action will be called with the item passed as an argument.&lt;/p&gt;

&lt;p&gt;In total, there are two actions used in this template. Lets
write the handlers for these actions: &lt;code&gt;createTask&lt;/code&gt; and &lt;code&gt;toggleIsDone&lt;/code&gt;.&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;ember generate controller items&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;// app/items/controller.js&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;import&lt;/span&gt; Ember from &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ember&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;default&lt;/span&gt; Ember.Controller.extend({&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;ke&quot;&gt;actions&lt;/span&gt;: {&lt;tt&gt;
&lt;/tt&gt;    createTask(task) {&lt;tt&gt;
&lt;/tt&gt;      const item = &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;.get(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;).createRecord(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, {&lt;tt&gt;
&lt;/tt&gt;        task,&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;ke&quot;&gt;isDone&lt;/span&gt;: &lt;span class=&quot;kw&quot;&gt;false&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      });&lt;tt&gt;
&lt;/tt&gt;      item.save();&lt;tt&gt;
&lt;/tt&gt;    },&lt;tt&gt;
&lt;/tt&gt;    toggleIsDone(item) {&lt;tt&gt;
&lt;/tt&gt;      item.toggleProperty(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;isDone&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;      item.save();&lt;tt&gt;
&lt;/tt&gt;    }&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;});&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Next lets implement the &lt;code&gt;input-task&lt;/code&gt; component. Ember components
are heavily inspired by the web component standards, but differ where we feel
the specs are lacking. A great example of this is block params (the &lt;code&gt;as |item|&lt;/code&gt;
syntax). Nothing like block params exists for web components, but we find them
supremely useful in real-world applications.&lt;/p&gt;

&lt;p&gt;To create a component, start with the generator:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;ember generate component input-task&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;We want to create an input tag, and when the user hits enter submit the task.
Like most new parts of an Ember app, we should start with the template:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;{{! app/components/input-task/template.hbs }}&lt;tt&gt;
&lt;/tt&gt;{{input value=value insert-newline=(action 'submit')}}&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;The component&#8217;s JavaScript must manage the &lt;code&gt;value&lt;/code&gt; value, the &lt;code&gt;submit&lt;/code&gt; action,
and call the passed in &lt;code&gt;createTask&lt;/code&gt; action when appropriate. Here is the
implementation:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;// app/components/input-task/component.js&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;import&lt;/span&gt; Ember from &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ember&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;default&lt;/span&gt; Ember.Component.extend({&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;ke&quot;&gt;tagName&lt;/span&gt;: &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;c&quot;&gt;// don't create a tag for this component&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;ke&quot;&gt;actions&lt;/span&gt;: {&lt;tt&gt;
&lt;/tt&gt;    submit(value) { &lt;span class=&quot;c&quot;&gt;// insert-newline is called with the input's value&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;.attrs[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;on-enter&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;](value); &lt;span class=&quot;c&quot;&gt;// call the on-enter action&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;.set(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;); &lt;span class=&quot;c&quot;&gt;// reset the input value&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    }&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;});&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;That should be everything wired up. Load up your browser and take a look. Note
the changes to the data in the inspector, and that the records persist across
page reloads.&lt;/p&gt;

&lt;h2&gt;Writing an Acceptance Test&lt;/h2&gt;

&lt;p&gt;The Ember community takes testing pretty seriously. As we&#8217;ve been generating different parts
of the todo application, we&#8217;ve also generated tests. To run these tests with Chrome run this
command:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;ember test --launch Chrome&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;There is also a server option, and by default the test runner will try to use &lt;a href=&quot;http://phantomjs.org/&quot;&gt;PhantomJS&lt;/a&gt;
to run the suite without a browser booting. See &lt;code&gt;ember test --help&lt;/code&gt; for details on those
options.&lt;/p&gt;

&lt;p&gt;The tests generated so far are all unit tests. Ember also supports acceptance tests. These
allow you to test an application as driven by the user. To generate an acceptance test run:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;ember generate acceptance-test items&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;And add our test to the generated file:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;31&lt;tt&gt;
&lt;/tt&gt;32&lt;tt&gt;
&lt;/tt&gt;33&lt;tt&gt;
&lt;/tt&gt;34&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;35&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;36&lt;tt&gt;
&lt;/tt&gt;37&lt;tt&gt;
&lt;/tt&gt;38&lt;tt&gt;
&lt;/tt&gt;39&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;// tests/acceptance/items-test.js&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;import&lt;/span&gt; Ember from &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ember&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;import&lt;/span&gt; {&lt;tt&gt;
&lt;/tt&gt;  module,&lt;tt&gt;
&lt;/tt&gt;  test&lt;tt&gt;
&lt;/tt&gt;} from &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;qunit&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;import&lt;/span&gt; startApp from &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;todo-list/tests/helpers/start-app&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;const ENTER_KEYCODE = &lt;span class=&quot;i&quot;&gt;13&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;kw&quot;&gt;var&lt;/span&gt; application;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;module(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Acceptance: Todos&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, {&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;ke&quot;&gt;beforeEach&lt;/span&gt;: &lt;span class=&quot;kw&quot;&gt;function&lt;/span&gt;() {&lt;tt&gt;
&lt;/tt&gt;    application = startApp();&lt;tt&gt;
&lt;/tt&gt;  },&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;ke&quot;&gt;afterEach&lt;/span&gt;: &lt;span class=&quot;kw&quot;&gt;function&lt;/span&gt;() {&lt;tt&gt;
&lt;/tt&gt;    Ember.run(application, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;destroy&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;});&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;test(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;visits /, navigates to items, adds an item&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;kw&quot;&gt;function&lt;/span&gt;(assert) {&lt;tt&gt;
&lt;/tt&gt;  visit(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;  click(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;a:contains(Items)&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  andThen(&lt;span class=&quot;kw&quot;&gt;function&lt;/span&gt;() {&lt;tt&gt;
&lt;/tt&gt;    assert.equal(currentURL(), &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/items&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;url is correct&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;  });&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  fillIn(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;input[type=text]&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;New Task&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;  keyEvent(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;input[type=text]&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;keyup&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, ENTER_KEYCODE);&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  andThen(&lt;span class=&quot;kw&quot;&gt;function&lt;/span&gt;() {&lt;tt&gt;
&lt;/tt&gt;    const input = find(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;input[type=text]&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;    assert.equal(input.val(), &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;input has been reset&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;    const task = find(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;span:contains(New Task)&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;    assert.equal(task.length, &lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;task is on the page&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;  });&lt;tt&gt;
&lt;/tt&gt;});&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Ember&#8217;s acceptance test harness provides several &#8220;async helpers&#8221; such as &lt;code&gt;visit&lt;/code&gt;, &lt;code&gt;click&lt;/code&gt;
and the form manipulations. The &lt;code&gt;andThen&lt;/code&gt; helper allows us to ensure any asynchronous
behavior such as fetching records from a persistence layer or animating the UI are complete
before making assertions.&lt;/p&gt;

&lt;h2&gt;Where to Go Next&lt;/h2&gt;

&lt;p&gt;This small app touched a pretty wide expanse of Ember&#8217;s API. Some of the features we
touched were cutting edge, but most are part of Ember.js 1.12. Here are some further resources
on the topics covered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ember-CLI
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.ember-cli.com/#getting-started&quot;&gt;Getting Started&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Ember Addons
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.emberaddons.com/&quot;&gt;directory of addons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://emberobserver.com/&quot;&gt;curated/ranked list of addons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.ember-cli.com/#developing-addons-and-blueprints&quot;&gt;docs on developing an addon&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Ember-CLI w/ pods
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://cball.me/organize-your-ember-app-with-pods/&quot;&gt;Organize Your Ember App with Pods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.ember-cli.com/#pods&quot;&gt;ember-cli docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;ES6 Modules
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.ember-cli.com/#using-modules&quot;&gt;in Ember-CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.2ality.com/2014/09/es6-modules-final.html&quot;&gt;detailed into to ES6 modules&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Ember-Data
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://guides.emberjs.com/v1.11.0/models/&quot;&gt;guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/genkgo/ember-localforage-adapter&quot;&gt;ember-localforage-adapter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Routing
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://guides.emberjs.com/v1.10.0/routing/&quot;&gt;guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;link-to helper
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://guides.emberjs.com/v1.11.0/templates/links/&quot;&gt;guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://emberjs.com/api/classes/Ember.Handlebars.helpers.html#method_link-to&quot;&gt;docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Ember Inspector
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/emberjs/ember-inspector&quot;&gt;source&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi&quot;&gt;Chrome extension&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/&quot;&gt;Firefox add-on&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Actions
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://guides.emberjs.com/v1.11.0/templates/actions/&quot;&gt;guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://emberjs.com/api/classes/Ember.Handlebars.helpers.html#method_action&quot;&gt;docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/emberjs/rfcs/pull/50&quot;&gt;RFC w/ recent improvements&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Components
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://emberjs.com/api/classes/Ember.Component.html&quot;&gt;docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://guides.emberjs.com/v1.11.0/components/&quot;&gt;guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Input helper
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://guides.emberjs.com/v1.10.0/templates/input-helpers/&quot;&gt;guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://emberjs.com/api/classes/Ember.TextField.html&quot;&gt;docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Async Test Helpers
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://emberjs.com/api/classes/Ember.Test.html&quot;&gt;docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://guides.emberjs.com/v1.11.0/testing/acceptance/&quot;&gt;guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://coryforsyth.com/2014/07/10/demystifing-ember-async-testing/&quot;&gt;Demystifying Ember Async Testing&lt;/a&gt; blog post&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We&#8217;ve also been able to build a pretty neat interaction in under 60 lines
of code (+ under 40 in the test), and the result is a codebase no Ember
developer should have trouble working with.&lt;/p&gt;

&lt;p&gt;There are still a lot of details to work out for Ember 2.0, and you&#8217;re bound
to hear lots of discussion about those topics in the next few weeks. Even short
of landing those details, the ecosystem as a whole is incredibly improved. All
these pieces working in harmony speaks to the diligence and continued effort
from the community.&lt;/p&gt;

&lt;p&gt;Whether you use Ember already or are looking at it for the first time, I hope
this gave you some fresh perspective. Getting started with the framework
has never been easier.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://madhatted.com/">
    <author>
      <name>mixonic</name>
    </author>
    <id>tag:madhatted.com,2015-03-06:3572</id>
    <published>2015-03-06T20:34:00Z</published>
    <updated>2015-03-06T20:35:14Z</updated>
    <link href="http://madhatted.com/2015/3/6/ember-community-survey-results-2015" rel="alternate" type="text/html"/>
    <title>Ember Community Survey Results, 2015</title>
<content type="html">
            &lt;p&gt;With over 900 responses, I&#8217;m very pleased to announce the results of the unofficial Ember.js Community Survey are now available:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.201-created.com/ember-community-survey-2015&quot;&gt;201-created.com/ember-community-survey-2015&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We&#8217;ve summarized the responses in about ten headlines, but I encourage readers to follow their curiosity with the full data-set linked at the bottom of the results page.&lt;/p&gt;

&lt;p&gt;I would like to thank Brian Runnells (&lt;a href=&quot;https://twitter.com/climbingnarc&quot;&gt;@ClimbingNarc&lt;/a&gt;) for his effort running this survey and engaging the community. It would not have been possible without his dedication and hard work.&lt;/p&gt;

&lt;p&gt;Take a look! And thank you for participating!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://madhatted.com/">
    <author>
      <name>mixonic</name>
    </author>
    <id>tag:madhatted.com,2015-03-06:3571</id>
    <published>2015-03-06T20:06:00Z</published>
    <updated>2015-03-09T18:49:20Z</updated>
    <link href="http://madhatted.com/2015/3/6/aligning-ember-js-with-web-standards-emberconf-2015" rel="alternate" type="text/html"/>
    <title>Aligning Ember.js with Web Standards</title>
<content type="html">
            &lt;p&gt;This March I was delighted to present at &lt;a href=&quot;http://emberconf.com/&quot;&gt;EmberConf&lt;/a&gt; 2015, after a great data-layer talk by Dan Gebhardt (&lt;a href=&quot;https://twitter.com/dgeb&quot;&gt;@dgeb&lt;/a&gt;) and before a heartwarming community talk by Jamie White (&lt;a href=&quot;https://twitter.com/jgwhite&quot;&gt;@jgwhite&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;My own presentation was on web standards- How they are changing, and what it means for Ember.js and Ember applications.&lt;/p&gt;





&lt;p&gt;While researching for this talk, I used several excellent resources written and organized by other developers. If you are interested in learning more about ES2015 (ES6) features, the standards process, or JavaScript in general I highly suggest these links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Alex Rauschmayer&#8217;s blog &lt;a href=&quot;http://www.2ality.com/&quot;&gt;2ality&lt;/a&gt;, especially:
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.2ality.com/2015/02/es6-classes-final.html&quot;&gt;Classes in ECMAScript 6 (final semantics)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.2ality.com/2014/12/es6-proxies.html&quot;&gt;Meta programming with ECMAScript 6 proxies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.2ality.com/2014/12/es6-oop.html&quot;&gt;ECMAScript 6: new OOP features besides classes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;http://people.mozilla.org/~jorendorff/es6-draft.html&quot;&gt;unofficial HTML version of the ECMAScript Language Specification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Rick Waldron&#8217;s (&lt;a href=&quot;http://twitter.com/rwaldron&quot;&gt;@rwaldron&lt;/a&gt;) &lt;a href=&quot;https://github.com/rwaldron/tc39-notes&quot;&gt;notes from TC39 meetings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://github.com/tc39/ecma262&quot;&gt;TC39 Ecma262 repo&lt;/a&gt;, which contains a list of current ES proposals under discussion&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://docs.google.com/document/d/1QbEE0BsO4lvl7NFTn5WXWeiEIBfaVUF7Dk0hpPpPDzU/edit&quot;&gt;TC39 Process document&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://babeljs.io/blog/2015/02/15/not-born-to-die/&quot;&gt;Not born to die&lt;/a&gt;, a blog post about &lt;a href=&quot;http://babeljs.io/&quot;&gt;Babel&lt;/a&gt; (formerly 6to5) by James Kyle (&lt;a href=&quot;https://twitter.com/thejameskyle&quot;&gt;@thejameskyle&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://remysharp.com/2010/10/08/what-is-a-polyfill&quot;&gt;What is a Polyfill?&lt;/a&gt; by Remy Sharp (&lt;a href=&quot;https://twitter.com/rem&quot;&gt;@rem&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;http://kangax.github.io/compat-table/es6/&quot;&gt;ECMAScript compatibility table&lt;/a&gt;, including browser and transpiler implementations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As with any talk about the current state of the world, parts of it quickly start becoming out of date.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I draw a pretty simplistic line between working groups and standards committees in my talk. For the point of narrative and understanding how we (the web) got here it is illustrative, but these are very rapidly changing organizations with intertwined and political relationships. I encourage you to review the meeting notes, charters, and process documents of a group if you want a good understanding of exactly what they bring to our complex, modern web.&lt;/li&gt;
&lt;li&gt;As of ng-conf, it looks like several decorator/annotation proposals being discussed by TC39 may have been resolved. The syntax would be:&lt;/li&gt;
&lt;/ul&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;er&quot;&gt;@&lt;/span&gt;attr(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;gearsCount&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;er&quot;&gt;@&lt;/span&gt;attr(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;wheelsCount&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; Car {&lt;tt&gt;
&lt;/tt&gt;  constructor(gearsCount) {&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;.gearsCount = gearsCount;&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;er&quot;&gt;@&lt;/span&gt;dependsOn(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;gearsCount&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  get isModern() {&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;kw&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;.gearsCount &amp;gt; &lt;span class=&quot;i&quot;&gt;3&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;}&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;kw&quot;&gt;var&lt;/span&gt; car = &lt;span class=&quot;kw&quot;&gt;new&lt;/span&gt; Car(&lt;span class=&quot;i&quot;&gt;3&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;car.isModern; &lt;span class=&quot;c&quot;&gt;// false&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Decorators before the class apply to the class, and before descriptors (properties) apply to the following property.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://madhatted.com/">
    <author>
      <name>mixonic</name>
    </author>
    <id>tag:madhatted.com,2015-02-27:3569</id>
    <published>2015-02-27T23:46:00Z</published>
    <updated>2015-03-10T23:18:16Z</updated>
    <link href="http://madhatted.com/2015/2/27/emblem-0-5-0" rel="alternate" type="text/html"/>
    <title>Emblem 0.5.0</title>
<content type="html">
            &lt;p&gt;&lt;a href=&quot;http://emblemjs.com/&quot;&gt;Emblem&lt;/a&gt; is an alternative Ember.js template syntax created by Alex Matchneer &lt;a href=&quot;https://twitter.com/machty&quot;&gt;@machty&lt;/a&gt;. Due to some internal compiling to the Handlebars AST (abstract syntax tree), keeping Emblem up to date and backward compatible has been difficult. When Emblem was initially authored, the Handlebars AST was pitched as a stable API to write other applications against. This has not held up over time.&lt;/p&gt;

&lt;p&gt;There is another path. With sponsorship from our friends at &lt;a href=&quot;http://www.vestorly.com/&quot;&gt;Vestorly&lt;/a&gt; and guidance from Alex, &lt;a href=&quot;http://www.201-created.com/&quot;&gt;201 Created&lt;/a&gt; set aside a few days to rewrite Emblem as a template printer. As a &#8220;printer&#8221;, Emblem no longer outputs compiled and executable templates. Instead, it generates Ember template strings. Since Ember template syntax is protected by semantic versioning, Emblem is now compatible with many versions of Ember regardless of the template engine (Handlebars 1.3, Handlebars 2.0, HTMLBars).&lt;/p&gt;

&lt;p&gt;For example, an Emblem template used with Ember 1.10 will be built in these steps. First, the template:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;/ app/templates/index.emblem&lt;tt&gt;
&lt;/tt&gt;h1 Howdy Friend!&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;div&lt;tt&gt;
&lt;/tt&gt;  marquee-banner | Emblem makes life easy!&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Is compiled into an Ember template:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;{{! app/templates/index.hbs }}&lt;tt&gt;
&lt;/tt&gt;&amp;lt;h1&amp;gt;Howdy Friend!&amp;lt;/h1&amp;gt;&amp;lt;div&amp;gt;{{#marquee-banner}}Emblem makes life easy!{{/marquee-banner}}&amp;lt;/div&amp;gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;This raw template is compiled by the build pipeline into an executable template. The printing step isolates Emblem from the Ember template compile step, allowing that to be based on whatever version of Ember the application uses.&lt;/p&gt;

&lt;p&gt;We also gain a great new feature from this conversion: Developers considering Emblem, but intimidated by the risk of &#8220;lock-in&#8221; can rest easy. With a little bit of additional work into pretty-printing Emblem should soon have an easy off ramp for those wanting to return to a more traditional syntax: Just save the Ember templates!&lt;/p&gt;

&lt;p&gt;Several issues remain open after this spike. We&#8217;ve opened a &lt;a href=&quot;https://github.com/machty/emblem.js/milestones/0.5.1&quot;&gt;0.5.1 Milestone&lt;/a&gt; to track them.&lt;/p&gt;

&lt;p&gt;We&#8217;ve had a fascinating time implementing the new printer and we&#8217;re looking forward to sharing more details in a forthcoming blog post.&lt;/p&gt;

&lt;h2&gt;Upgrading to Emblem 0.5.0 with Ember-CLI&lt;/h2&gt;

&lt;p&gt;If you currently use Emblem and want to upgrade (say, for 1.10 support and HTMLBars? ;-), follow these steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uninstall the &lt;a href=&quot;https://github.com/antramm/broccoli-emblem-compiler&quot;&gt;broccoli-emblem-compiler&lt;/a&gt; or any other Emblem compiler you may be using.&lt;/li&gt;
&lt;li&gt;Install the &lt;a href=&quot;https://github.com/Vestorly/ember-cli-emblem-hbs-printer&quot;&gt;ember-cli-emblem-hbs-printer&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can quickly install the printer with:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;ember install:addon ember-cli-emblem-hbs-printer&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;That&#8217;s it! Your Emblem templates will be compiled like any other &lt;code&gt;.hbs&lt;/code&gt; file in your codebase.&lt;/p&gt;

&lt;p&gt;A demo application can be found at &lt;a href=&quot;https://github.com/201-created/ember-cli-emblem-example&quot;&gt;201-created/ember-cli-emblem-example&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Many thanks to &lt;a href=&quot;http://www.vestorly.com/&quot;&gt;Vestorly&lt;/a&gt; for their sponsorship of &lt;a href=&quot;http://www.201-created.com/&quot;&gt;201 Created&lt;/a&gt;&#8217;s time on Emblem. If you&#8217;re a frontend developer looking for a new opportunity, Vestorly is tackling new and interesting Ember.js challenges every day. Check them out.&lt;/em&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://madhatted.com/">
    <author>
      <name>mixonic</name>
    </author>
    <id>tag:madhatted.com,2015-02-04:3565</id>
    <published>2015-02-04T19:33:00Z</published>
    <updated>2015-03-06T20:53:56Z</updated>
    <link href="http://madhatted.com/2015/2/4/ember-community-survey-2015" rel="alternate" type="text/html"/>
    <title>Ember Community Survey, 2015</title>
<content type="html">
            &lt;p&gt;&lt;em&gt;Update: We&#8217;re happy to announce that &lt;a href=&quot;http://madhatted.com/2015/3/6/ember-community-survey-results-2015&quot;&gt;results of the 2015 survey are available&lt;/a&gt;&lt;/em&gt;!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The 2015 Community Survey closed on February 20th. Thank you for participating!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&#8211;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Calling all Ember users!&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In 2014 Ember.js was a rapidly changing framework. The community and Ember Core Team tackled hard problems, many of which felt self-evident. We struck out in a new direction with Ember-CLI, created a bustling addon ecosystem, completed most of the grunt work on HTMLBars, and made huge strides in Ember-Data and API standardization.&lt;/p&gt;

&lt;p&gt;As Ember gains adoption, we should take a moment to check our assumptions about who is using the framework and how. A little reflection on what happens in the wild can keep us honest and focused.&lt;/p&gt;

&lt;p&gt;With this aim, I&#8217;m pleased to announce the unofficial Ember Community Survey!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;http://201-created.com/ember-community-survey-2015&quot;&gt;Submit your Ember Community Survey answers here&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Completing the survey should take about ten minutes. We will be accepting submissions until February 20th.&lt;/p&gt;

&lt;p&gt;Please help us spread the word by sharing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://201-created.com/ember-community-survey-2015&quot;&gt;201-created.com/ember-community-survey-2015&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;on your social network feeds, at meetups, and around your office and other communities.&lt;/p&gt;

&lt;p&gt;With your answers (all anonymous), we will create some visuals and write up our insights before EmberConf 2015 (March 3-4th). If you have any immediate questions, feel free to email us at &lt;a href=&quot;mailto:survey@201-created.com&quot;&gt;survey@201-created.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks to &lt;a href=&quot;https://twitter.com/climbingnarc&quot;&gt;@climbingnarc&lt;/a&gt; for his continued help organizing this project with &lt;a href=&quot;http://201-created.com&quot;&gt;201-created.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://madhatted.com/">
    <author>
      <name>brian.runnells</name>
    </author>
    <id>tag:madhatted.com,2015-01-28:3542</id>
    <published>2015-01-28T16:06:00Z</published>
    <updated>2015-03-06T20:53:41Z</updated>
    <link href="http://madhatted.com/2015/1/28/ember-community-survey-2015-preview" rel="alternate" type="text/html"/>
    <title>Ember Community Survey - 2015 Preview</title>
<content type="html">
            &lt;p&gt;&lt;em&gt;Update: We&#8217;re happy to announce that &lt;a href=&quot;http://madhatted.com/2015/3/6/ember-community-survey-results-2015&quot;&gt;results of the 2015 survey are available&lt;/a&gt;!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Say hello to Brian Runnells (&lt;a href=&quot;https://twitter.com/climbingnarc&quot;&gt;@climbingnarc&lt;/a&gt;). Brian is an Ember developer working with my consulting company &lt;a href=&quot;http://www.201-created.com/&quot;&gt;201 Created&lt;/a&gt; on a new project over February and March. He leads a double life as developer and rock climbing blogger. We&#8217;re lucky to be working with him, and happy to have him introduce the Ember Community Survey. -Matt&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who is currently developing applications with Ember.js?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What tools are those developers using to build their apps?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What kind of apps are they building?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;2015 is an incredible time to be an Ember.js developer.  Not only does the framework continue to gain momentum, but there are many features on the horizon. With this, however, comes many questions, like those above.  So, when 201 Created began seeking people to help construct a survey for Ember developers, I was excited to take advantage of that opportunity. &lt;/p&gt;

&lt;p&gt;Together, we have created a number of questions related to both your personal use of and professional work with Ember.  Our goal is to ask the necessary questions about how and why developers are using Ember in order to better inform both the the community at large and the Ember Core Team.  These responses will allow us to identify what is going well, where more work needs to be done, and what directions our community is moving in.&lt;/p&gt;

&lt;p&gt;As the goal is to have results compiled by March’s EmberConf (tickets are sold out, but hope to see you there!), this survey will be finalized and put out for responses in early February.  At this time, we are looking for any feedback you may have regarding the topics and questions we have produced thus far. &lt;/p&gt;

&lt;p&gt;Find the survey questions &lt;a href=&quot;https://docs.google.com/document/d/1J7nLuOPVzdagTzxhOLlhGCcF2gLRA1YQl033Doy2vJY/edit?usp=sharing]&quot;&gt;here&lt;/a&gt; and share your feedback as a comment. Google provides some &lt;a href=&quot;https://support.google.com/docs/answer/65129?hl=en&quot;&gt;documentation about commenting&lt;/a&gt; that is good to review if you haven&#8217;t used the feature before. You can also contact us directly via &lt;a href=&quot;mailto:survey@201-created.com&quot;&gt;survey@201-created.com&lt;/a&gt;.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://madhatted.com/">
    <author>
      <name>mixonic</name>
    </author>
    <id>tag:madhatted.com,2014-11-24:3445</id>
    <published>2014-11-24T16:23:00Z</published>
    <updated>2014-12-10T21:45:55Z</updated>
    <link href="http://madhatted.com/2014/11/24/scalable-vector-ember" rel="alternate" type="text/html"/>
    <title>Scalable Vector Ember</title>
<content type="html">
            &lt;p&gt;Fresh from &lt;a href=&quot;https://unspace.ca/embergarten/&quot;&gt;emberGarten&lt;/a&gt; in Toronto I bring you the latest on SVG in Ember.js, metal-views, and HTMLBars:&lt;/p&gt;



 

&lt;p&gt;In Ember.js 1.8, we&#8217;ve added full support for SVG. This means you can author templates of SVG and make SVG-element components. &lt;a href=&quot;http://emberjs.jsbin.com/woxes/10&quot;&gt;Demo here&lt;/a&gt;, and &lt;a href=&quot;http://emberjs.jsbin.com/woxes/10/edit?html,css,js&quot;&gt;code here&lt;/a&gt;. Zero graphic design skills were involved in the making of this demo, but you get the point!&lt;/p&gt;

&lt;p&gt;SVG is slowly rising in usage as IE8 finally drops from the list of commonly supported browsers. To fully support SVG in Ember templates, 1.8 tackled a few tough challenges:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Switching namespaces and element creation methods. Ember transparently swaps into the SVG namespace, and even swaps back out to HTML for &lt;code&gt;foreignObject&lt;/code&gt; tags.&lt;/li&gt;
&lt;li&gt;Track contextual elements. In 1.8, each executed template is a string which must be converted into DOM with &lt;code&gt;innerHTML&lt;/code&gt;. To properly support components and nested templates inside an SVG inline document, we&#8217;ve created a system to track the contextual (parent) element of a given template. This also helps us implement fixes for broken DOM APIs, and handle complex edge cases in the spec such as optionally omitted start tags (like &lt;code&gt;tbody&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the big story of metal views, and HTMLBars, is the slow migration of Ember from a string based rendering pipeline to a DOM based one.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pre-1.8 Ember templates returned strings, and the rendering pipeline assembled strings. This is akin to how a server-side framework would generate HTML.&lt;/li&gt;
&lt;li&gt;In 1.8-1.9, Ember templates are strings individually converted to DOM, then folded into a DOM based rendering tree.&lt;/li&gt;
&lt;li&gt;In 1.10+, Ember will introduce the DOM based HTMLBars templating engine. This completes our migration from string composition to DOM.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The nominal goals of this transition are to introduce new syntaxes (&lt;code&gt;&amp;lt;li class=&quot;{{someClass}}&quot;&amp;gt;&lt;/code&gt;) and improve performance (less strings means less GC pressure).&lt;/p&gt;

&lt;p&gt;DOM based rendering opens up an additional and less discussed frontier- That of interoperability with other DOM based rendering engines such as those in Angular, React, Mithril, and Polymer. None of these tools output strings, all expect to be attached to a DOM node and yield to a DOM node. By kicking HTML strings to the curb and embracing the DOM, we&#8217;ve created the possibility of using the best rendering strategy for a given part of an app.&lt;/p&gt;

&lt;p&gt;SVG support is nothing more than a proving ground for how this kind of integration can work. Our next steps are to ship HTMLBars, then work on making Ember&#8217;s conventional path a competitively performing one for all common cases.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;My &lt;a href=&quot;http://www.201-created.com/&quot;&gt;Ember.js consulting firm 201 Created&lt;/a&gt; has helped 15+ companies get up to speed. We&#8217;re eager to work on SVG projects, and available for hire in January.&lt;/em&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://madhatted.com/">
    <author>
      <name>mixonic</name>
    </author>
    <id>tag:madhatted.com,2014-11-05:3437</id>
    <published>2014-11-05T17:54:00Z</published>
    <updated>2015-08-23T16:54:38Z</updated>
    <link href="http://madhatted.com/2014/11/5/contribute-to-ember-js-2-0-no-coding-required" rel="alternate" type="text/html"/>
    <title>Contribute to Ember.js 2.0. No coding required.</title>
<summary type="html">


&lt;p&gt;Ember&#8217;s path to a 2.0 release has been announced in &lt;a href=&quot;https://github.com/emberjs/rfcs/pull/15&quot;&gt;an RFC&lt;/a&gt;. Our ambition is not simply to have 2.0 be a great framework, but for every 1.x codebase to make the transition forward with us.&lt;/p&gt;

&lt;p&gt;There is a lot of code to be written. Contributing code to Ember.js, especially if you are new to open source development, is a rewarding and skills-building experience. The project maintains a high bar for technical contribution, and fixing a bug often involves a healthy dose of new knowledge. Additionally, there is a &lt;a href=&quot;http://emberjs.com/guides/contributing/adding-new-features/&quot;&gt;mature process&lt;/a&gt; for adding new features and bug fixes that should serve as an inspiration to your development process elsewhere.&lt;/p&gt;

&lt;p&gt;If you have the time and will, adding code to Ember.js is an opportunity to collaborate with wonderful and extremely smart people.&lt;/p&gt;

&lt;p&gt;&#8220;&lt;em&gt;the time&lt;/em&gt;&#8221; is what keeps most developers from contributing to open source. There are businesses to build, families to raise, and always another Tolkien movie coming out.&lt;/p&gt;

&lt;p&gt;But you don&#8217;t need to contribute code to help Ember.js reach its 2.0 goals. Here are five great ways to be a part of the process.&lt;/p&gt;</summary><content type="html">
            


&lt;p&gt;Ember&#8217;s path to a 2.0 release has been announced in &lt;a href=&quot;https://github.com/emberjs/rfcs/pull/15&quot;&gt;an RFC&lt;/a&gt;. Our ambition is not simply to have 2.0 be a great framework, but for every 1.x codebase to make the transition forward with us.&lt;/p&gt;

&lt;p&gt;There is a lot of code to be written. Contributing code to Ember.js, especially if you are new to open source development, is a rewarding and skills-building experience. The project maintains a high bar for technical contribution, and fixing a bug often involves a healthy dose of new knowledge. Additionally, there is a &lt;a href=&quot;http://emberjs.com/guides/contributing/adding-new-features/&quot;&gt;mature process&lt;/a&gt; for adding new features and bug fixes that should serve as an inspiration to your development process elsewhere.&lt;/p&gt;

&lt;p&gt;If you have the time and will, adding code to Ember.js is an opportunity to collaborate with wonderful and extremely smart people.&lt;/p&gt;

&lt;p&gt;&#8220;&lt;em&gt;the time&lt;/em&gt;&#8221; is what keeps most developers from contributing to open source. There are businesses to build, families to raise, and always another Tolkien movie coming out.&lt;/p&gt;

&lt;p&gt;But you don&#8217;t need to contribute code to help Ember.js reach its 2.0 goals. Here are five great ways to be a part of the process.&lt;/p&gt;
&lt;h2&gt;Test your app on beta releases&lt;/h2&gt;

&lt;p&gt;When opening a Github issue for a bug, it is important to note which channel of Ember.js the bug is in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&#8220;canary&#8221; is the master branch of Ember.js. Every six weeks it forks to create the new Beta.&lt;/li&gt;
&lt;li&gt;&#8220;beta&#8221; builds are released every week for six weeks, then graduate to release.&lt;/li&gt;
&lt;li&gt;&#8220;release&#8221; builds are released every six weeks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This cycle means that &lt;strong&gt;every six weeks, a release candidate of Ember.js is forked&lt;/strong&gt;. Between the first beta release and the graduation of that release to release, we need feedback from real-world applications to discover bugs. We think of this process as a train. Beta forks, bug fixes land, and after six weeks that branch is release worthy.&lt;/p&gt;

&lt;p&gt;While code is in beta, much of the coding community&#8217;s focus is there. If a bug is undiscovered in beta and graduates into release, fixing it takes time away from the new beta and canary branches. Bugs in release, and in point releases (like 1.7.1 or 1.8.1), make the train jerk around.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testing your application with beta builds ensures quality releases on a steady schedule&lt;/strong&gt;. Once or twice every six weeks, update to beta and report bad behavior on Github. With Ember-CLI this is as easy as:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;bower install --save ember#beta&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Or install a specific version:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;bower install --save ember#1.9.0-beta.1&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;As part of installation you may be prompted by Bower to manually pick a specific version of Ember. After installation, you may need to restart your server. Like any change to bower dependencies, stay a little suspicious. Deleting the &lt;code&gt;bower_components/&lt;/code&gt; folder and doing a fresh &lt;code&gt;bower install&lt;/code&gt; may be warranted.&lt;/p&gt;

&lt;p&gt;You can also &lt;a href=&quot;http://emberjs.com/builds/&quot;&gt;download builds&lt;/a&gt; from the website. &lt;strong&gt;Even ten minutes of beta review every six weeks is incredibly helpful&lt;/strong&gt;. You don&#8217;t need to ship beta builds to production to generate meaningful feedback.&lt;/p&gt;

&lt;h2&gt;Catch and update old patterns in the documentation&lt;/h2&gt;

&lt;p&gt;As Ember.js 2.0 comes closer, more documentation at &lt;a href=&quot;http://emberjs.com&quot;&gt;emberjs.com&lt;/a&gt; will be updated to match Ember-CLI&#8217;s conventions. Documentation has gone from a sore spot to a point of pride with Ember, but it is impossible for any single person to ensure all guides and API docs are up to date.&lt;/p&gt;

&lt;p&gt;If you see something, PR something. The source of Ember&#8217;s guides (and the rest of the website) is &lt;a href=&quot;https://github.com/emberjs/website/&quot;&gt;on github&lt;/a&gt;. The API documentation is part of Ember&#8217;s own code. Making and previewing changes to the website is easy. Click the fork button, then start the preview server:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;git clone git@github.com:my-github-account/website.git&lt;tt&gt;
&lt;/tt&gt;cd website/&lt;tt&gt;
&lt;/tt&gt;bundle&lt;tt&gt;
&lt;/tt&gt;bundle exec middleman&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;And you&#8217;re off! PRs for something as small as a grammar or spelling correction are welcome, but most valuable is catching old or non-idiomatic recommendations and updating them.&lt;/p&gt;

&lt;h2&gt;Talk about your own solutions&lt;/h2&gt;

&lt;p&gt;Each user of Ember solves unique challenges. Sharing your solution to an interesting problem is a valuable way to contribute to our community, be it through a blog post, meetup talk, or video. Getting your business or personal name out there is a bonus!&lt;/p&gt;

&lt;p&gt;When writing about a topic for the first time, consider sharing your content on IRC or elsewhere for feedback. I&#8217;m always happy to review a post myself!&lt;/p&gt;

&lt;p&gt;If you write or otherwise share something, make sure it gets out there for other developers to see. Consider submitting it to one of these Ember resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://emberweekly.com/&quot;&gt;Ember Weekly&lt;/a&gt; is the oldest Ember.js newsletter, and reaches many developers.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://emberwatch.com/&quot;&gt;Ember Watch&lt;/a&gt; maintains a Twitter account and webpage with many resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Or to any general JavaScript resource.&lt;/p&gt;

&lt;p&gt;If you don&#8217;t have a place to publish, you can always consider posting at &lt;a href=&quot;http://discuss.emberjs.com/&quot;&gt;Ember&#8217;s active discourse forum&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Help others&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://discuss.emberjs.com/&quot;&gt;Discourse&lt;/a&gt;, &lt;a href=&quot;http://stackoverflow.com/questions/tagged/ember.js&quot;&gt;StackOverflow&lt;/a&gt;, and the IRC chatrooms are where new developers go to ask questions. Walking someone though an new concept, or triaging what might be a bug is a good way to welcome new users to the community. Getting bugs to Github and clarifying concepts is incredibly helpful, and gives new users a great introduction.&lt;/p&gt;

&lt;p&gt;The community hangs in three chatrooms on IRC:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;#emberjs&lt;/code&gt; is for general guidance, and it linked to from the Ember webpage.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#emberjs-dev&lt;/code&gt; is for internals discussion and more advanced topics.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#ember-cli&lt;/code&gt; is where contributors and maintainers of &lt;a href=&quot;http://www.ember-cli.com/&quot;&gt;ember-cli&lt;/a&gt; tend to hang.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Share your thoughts on RFCs&lt;/h2&gt;

&lt;p&gt;Last but not least, and not for the rushed or faint of heart, is to review and comment on &lt;a href=&quot;https://github.com/emberjs/rfcs&quot;&gt;RFCs&lt;/a&gt;. Ember RFCs are documents prepared by the community and core team for discussion and feedback.&lt;/p&gt;

&lt;p&gt;Feedback on an RFC should be specific, ideally taking into account your experiences with the problem addressed by the RFC. It should be researched and considered. We hope that discussion on RFCs moves a proposal forward until it is evident that it should be rejected or implemented, so &#8220;+1&#8221; comments should be avoided.&lt;/p&gt;

&lt;p&gt;Understanding the issues raised by an RFC can be challenging and may not be a quick task, but it is important discussion that shapes the future of the framework.&lt;/p&gt;

&lt;p&gt;I&#8217;m excited to do my part in making Ember&#8217;s 2.0 goals a reality. See you at &lt;a href=&quot;http://emberconf.com/&quot;&gt;EmberConf&lt;/a&gt; to celebrate!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Want to ensure your team is ready for 2.0? Or sponsor development to land features sooner? My &lt;a href=&quot;http://www.201-created.com/&quot;&gt;consulting business 201 Created&lt;/a&gt; is looking for new projects this January!&lt;/em&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://madhatted.com/">
    <author>
      <name>mixonic</name>
    </author>
    <id>tag:madhatted.com,2014-08-29:3408</id>
    <published>2014-08-29T11:50:00Z</published>
    <updated>2014-08-29T12:02:54Z</updated>
    <link href="http://madhatted.com/2014/8/29/testing-ember-js-apps-managing-dependencies" rel="alternate" type="text/html"/>
    <title>Testing Ember.js Apps: Managing Dependencies</title>
<content type="html">
            &lt;p&gt;Fresh via &lt;a href=&quot;https://emberfest.eu/&quot;&gt;EmberFest&lt;/a&gt;:&lt;/p&gt;



&lt;p&gt;Ember has an amazing testing story built upon the fundamentals of encapsulation and OO programming central to the framework. Despite this, every web application will be dependent upon and need to interact with native and network APIs that are hostile: Unreliable, slow, under-documented, and not to be trusted. The challenge in testing Ember applications lies with how to handle these external entities.&lt;/p&gt;

&lt;p&gt;In this talk, we distinguish the domain of an application from its implementation dependencies. The dependency is contained such that it avoids leaking into application code, unit tests, and acceptance tests.&lt;/p&gt;

&lt;p&gt;As a addendum exercise, lets consider how to wrap animation frames in a service that can be mocked.&lt;/p&gt;

&lt;p&gt;First, consider a component that schedules the animation:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;// in ember-cli, app/components/animate-in.js&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;App.AnimateInComponent = Ember.Component.extend({&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;ke&quot;&gt;animateIn&lt;/span&gt;: &lt;span class=&quot;kw&quot;&gt;function&lt;/span&gt;(){&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;kw&quot;&gt;var&lt;/span&gt; element = &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;.&lt;span class=&quot;pd&quot;&gt;$&lt;/span&gt;();&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;kw&quot;&gt;var&lt;/span&gt; position = -&lt;span class=&quot;i&quot;&gt;100&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;    element.css({&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;: &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;+position+&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;px&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    });&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;kw&quot;&gt;function&lt;/span&gt; animate(){&lt;tt&gt;
&lt;/tt&gt;      position++;&lt;tt&gt;
&lt;/tt&gt;      element.css(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;+position+&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;px&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);  &lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;kw&quot;&gt;if&lt;/span&gt; (position !== &lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;) {&lt;tt&gt;
&lt;/tt&gt;        window.requestAnimationFrame(animate);&lt;tt&gt;
&lt;/tt&gt;      }&lt;tt&gt;
&lt;/tt&gt;    }&lt;tt&gt;
&lt;/tt&gt;    window.requestAnimationFrame(animate);&lt;tt&gt;
&lt;/tt&gt;  }.on(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;didInsertElement&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;click&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;});&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Though functional, this component is leaking knowledge about a browser API (&lt;code&gt;requestAnimationFrame&lt;/code&gt;) and is difficult to disable or isolate in tests. If in the animation a component property was modified, it might also require the addition of an explicit runloop.&lt;/p&gt;

&lt;p&gt;Lets create a service to contain the request animation API and make it easier to mock in tests. A service in Ember.js has two parts, the service itself:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;// in ember-cli, app/services/animation.js&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;App.AnimationService = Ember.Object.extend({&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;ke&quot;&gt;init&lt;/span&gt;: &lt;span class=&quot;kw&quot;&gt;function&lt;/span&gt;(){&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;.frames = [];&lt;tt&gt;
&lt;/tt&gt;  },&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;ke&quot;&gt;scheduleFrame&lt;/span&gt;: &lt;span class=&quot;kw&quot;&gt;function&lt;/span&gt;(frame){&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;.frames.push(frame);&lt;tt&gt;
&lt;/tt&gt;    Ember.run.scheduleOnce(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;afterRender&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;, &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;.scheduleAnimationFrame);&lt;tt&gt;
&lt;/tt&gt;  },&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;ke&quot;&gt;scheduleAnimationFrame&lt;/span&gt;: &lt;span class=&quot;kw&quot;&gt;function&lt;/span&gt;(){&lt;tt&gt;
&lt;/tt&gt;    window.requestAnimationFrame(Ember.run.bind(&lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;, &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;._animateFrame));&lt;tt&gt;
&lt;/tt&gt;  },&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;ke&quot;&gt;_animateFrame&lt;/span&gt;: &lt;span class=&quot;kw&quot;&gt;function&lt;/span&gt;(){&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;kw&quot;&gt;var&lt;/span&gt; framesLength = &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;.frames.length;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;kw&quot;&gt;while&lt;/span&gt; (framesLength--) {&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;kw&quot;&gt;var&lt;/span&gt; frame = &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;.frames.shift();&lt;tt&gt;
&lt;/tt&gt;      frame();&lt;tt&gt;
&lt;/tt&gt;    }&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;kw&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;.frames.length) {&lt;tt&gt;
&lt;/tt&gt;      Ember.run.scheduleOnce(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;afterRender&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;, &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;.scheduleAnimationFrame);&lt;tt&gt;
&lt;/tt&gt;    }&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;});&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;And an initializer. In this example, I&#8217;m using the globals style of Ember. In ember-cli this would look different (again, see the slides):&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;// in ember-cli, app/initializers/animation.js&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;App.register(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;service:animation&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, App.AnimationService);&lt;tt&gt;
&lt;/tt&gt;App.inject(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;animation&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;service:animation&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;And now the component itself can be refactored to use this service:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;// in ember-cli, app/components/animate-in.js&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;App.AnimateInComponent = Ember.Component.extend({&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;ke&quot;&gt;animateIn&lt;/span&gt;: &lt;span class=&quot;kw&quot;&gt;function&lt;/span&gt;(){&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;kw&quot;&gt;var&lt;/span&gt; element = &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;.&lt;span class=&quot;pd&quot;&gt;$&lt;/span&gt;();&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;kw&quot;&gt;var&lt;/span&gt; animation = &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;.animation;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;kw&quot;&gt;var&lt;/span&gt; position = -&lt;span class=&quot;i&quot;&gt;100&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;    element.css({&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;: &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;+position+&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;px&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    });&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;kw&quot;&gt;function&lt;/span&gt; animate(){&lt;tt&gt;
&lt;/tt&gt;      position++;&lt;tt&gt;
&lt;/tt&gt;      element.css(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;+position+&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;px&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);  &lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;kw&quot;&gt;if&lt;/span&gt; (position !== &lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;) {&lt;tt&gt;
&lt;/tt&gt;        animation.scheduleFrame(animate);&lt;tt&gt;
&lt;/tt&gt;      }&lt;tt&gt;
&lt;/tt&gt;    }&lt;tt&gt;
&lt;/tt&gt;    animation.scheduleFrame(animate);&lt;tt&gt;
&lt;/tt&gt;  }.on(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;didInsertElement&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;click&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;});&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;A unit test for this component could now easily assert that animation begins, without needing to reference the native &lt;code&gt;requestAnimationFrame&lt;/code&gt; itself.&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;// in ember-cli, tests/components/animate-in-test.js&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;moduleForComponent(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;component:animate-in&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;test(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;schedules an animation&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;kw&quot;&gt;function&lt;/span&gt;(){&lt;tt&gt;
&lt;/tt&gt;  expect(&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;kw&quot;&gt;var&lt;/span&gt; component = &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;.subject({&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;ke&quot;&gt;scheduleFrame&lt;/span&gt;: &lt;span class=&quot;kw&quot;&gt;function&lt;/span&gt;(){&lt;tt&gt;
&lt;/tt&gt;      ok(&lt;span class=&quot;kw&quot;&gt;true&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;animation was scheduled!&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;    }&lt;tt&gt;
&lt;/tt&gt;  });&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;lv&quot;&gt;this&lt;/span&gt;.append();&lt;tt&gt;
&lt;/tt&gt;});&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Additionally, other components can now push frames to our service, conserving how many animation frames the browser needs to manage. This is a great example of how striving to move our technology dependency into a module apart from our domain code can improve the architecture of an application.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://emberjs.jsbin.com/tuzeb/2/edit?html,js,output&quot;&gt;Try out the example codebase in this JSBin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you joined us in Barcelona, thank you for being part of a great Ember conference. Let me know if you have any thoughts or comments, and hope to see you again!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://madhatted.com/">
    <author>
      <name>mixonic</name>
    </author>
    <id>tag:madhatted.com,2014-06-17:3166</id>
    <published>2014-06-17T15:27:00Z</published>
    <updated>2014-06-18T01:50:58Z</updated>
    <link href="http://madhatted.com/2014/6/17/authentication-for-single-page-apps" rel="alternate" type="text/html"/>
    <title>Authentication for Single Page Apps</title>
<summary type="html">&lt;p&gt;This week &lt;a href=&quot;http://www.vestorly.com&quot;&gt;Vestorly&lt;/a&gt;, a client of my consulting partnership &lt;a href=&quot;http://www.201-created.com&quot;&gt;201 Created&lt;/a&gt;, is sharing &lt;a href=&quot;http://vestorly.github.io/torii/&quot;&gt;Torii&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Torii is a set of abstractions for handling authentication and session management in Ember.js applications. The name comes from a &lt;a href=&quot;http://en.wikipedia.org/wiki/Torii&quot;&gt;traditional Japanese gate&lt;/a&gt; whose design you likely recognize:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Let&#8217;s discuss how we build authentication for single page applications, and how we can build it better.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;This week &lt;a href=&quot;http://www.vestorly.com&quot;&gt;Vestorly&lt;/a&gt;, a client of my consulting partnership &lt;a href=&quot;http://www.201-created.com&quot;&gt;201 Created&lt;/a&gt;, is sharing &lt;a href=&quot;http://vestorly.github.io/torii/&quot;&gt;Torii&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Torii is a set of abstractions for handling authentication and session management in Ember.js applications. The name comes from a &lt;a href=&quot;http://en.wikipedia.org/wiki/Torii&quot;&gt;traditional Japanese gate&lt;/a&gt; whose design you likely recognize:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Let&#8217;s discuss how we build authentication for single page applications, and how we can build it better.&lt;/p&gt;
&lt;h2&gt;API based Authentication&lt;/h2&gt;

&lt;p&gt;People prefer the tools they know. Authentication can be a non-trivial challenge for any app, so most developers have tools and techniques they trust for building traditional (page-by-page) auth flows. When building a single page app, it is not surprising that they reach for those same server-side authentication solutions.&lt;/p&gt;

&lt;p&gt;But those solutions fit poorly.&lt;/p&gt;

&lt;p&gt;We want to see more applications expose authorization and authentication as first-class concepts via the API. In the case of authentication, especially when a user could sign in via any of several services, we&#8217;ve found &#8220;authorization objects&#8221; useful. These provide a first-class model that can be passed to other APIs, and simplify the client-side logic and error handling requirements.&lt;/p&gt;

&lt;p&gt;Javascript applications can implement a clean, simple user experience for OAuth2 in the browser, one without user redirects or acrobatics to keep track of state.&lt;/p&gt;

&lt;p&gt;Raise your hand if you&#8217;ve worked on a single page application (whatever the framework or anti-framework) that had an authentication flow like this:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;This authentication system lives outside the JavaScript application entirely. The user-experience is choppy and slow, and the code difficult to maintain.&lt;/p&gt;

&lt;p&gt;To improve this, make authentication a first-class part of your API and JavaScript application:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Pushing authorization and authentication concerns into the JavaScript app makes managing errors and state simpler. It makes refactoring code easier, results in a better user experience, and creates opportunities for composition.&lt;/p&gt;

&lt;p&gt;When your application needs to authenticate against 3rd party services (Facebook, LinkedIn, Salesforce.com, Twitter etc.), splitting authorization and authentication into distinct API concerns becomes the best next step.&lt;/p&gt;

&lt;h2&gt;An RPC auth API&lt;/h2&gt;

&lt;p&gt;&#8220;Its OK @mixonic,&#8221; you may tweet, &#8220;we have a /session endpoint that accepts POST to create a session. We&#8217;re way ahead of you!&#8221;&lt;/p&gt;

&lt;p&gt;Let&#8217;s take a look:&lt;/p&gt;

&lt;table&gt;

&lt;tr&gt;&lt;td&gt;Auth API v1&lt;/td&gt;&lt;/tr&gt;


&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;POST&amp;nbsp;/api/session&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
  &lt;p&gt;This API endpoint is responsible for creating a session. It accepts a username/password combination, and returns either a session object with an access token or an error that the credentials are incorrect.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;

&lt;p&gt;Simple. If your application only supports username/password access, this may be sufficient. Let&#8217;s add support for social login:&lt;/p&gt;

&lt;table&gt;

&lt;tr&gt;&lt;td&gt;Auth API v2&lt;/td&gt;&lt;/tr&gt;


&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;POST&amp;nbsp;/api/session&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
  &lt;p&gt;This API endpoint is responsible for creating a session. It accepts a username/password combination, and attempts to authenticate that user. It returns either a session object and a &lt;code&gt;Set-Cookie&lt;/code&gt; header, or returns an error that the credentials are incorrect.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GET&amp;nbsp;/oauth2/facebookHandler&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
  &lt;p&gt;This endpoint accepts the redirect from Facebook as completion of an OAuth2 exchange. It validates the authorization code from Facebook, then authenticates that account as a user. It either redirects back to the application with a `Set-Cookie` header or renders an error into the page for the JavaScript application to read. The error might be regarding the invalidity of the OAuth2 exchange, or the invalidity of these credentials for signing in a user.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;

&lt;p&gt;Uh oh. This has gotten messy.&lt;/p&gt;

&lt;p&gt;There is one endpoint, &lt;code&gt;/oauth2/facebookHandler&lt;/code&gt;, that is not part of the API proper. It is not in the &lt;code&gt;/api&lt;/code&gt; namespace, and it doesn&#8217;t response like an API endpoint. Instead it uses redirects and rendering data into the page to push state into the browser.&lt;/p&gt;

&lt;p&gt;The session logic has changed in two ways: First, we&#8217;re forced to use cookies for authentication, which adds overhead to all requests and is a less portable way to authorize requests. Second, the logic for creating a session is in two places.&lt;/p&gt;

&lt;p&gt;These complications are why authentication and session management are often implemented as middleware. Middleware are filters for an HTTP stack. They get to handle all requests made to an application. Rack is an example of a middleware stack in Ruby, and Devise is an example of an authentication implementation using middleware.&lt;/p&gt;

&lt;p&gt;The crafty developer might say &#8220;Ahha! I can create an API endpoint for handling the Facebook OAuth2 code, and signing in! It could be the same endpoint even! Thus I can avoid the overhead and complexity of middleware!&#8221;&lt;/p&gt;

&lt;p&gt;Most OAuth2 flows are flexible enough to have all their user-interactive portions implemented in JavaScript. Facebook Connect is a good example of this. The crafty developer is crafty indeed.&lt;/p&gt;

&lt;p&gt;Let&#8217;s see what she came up with:&lt;/p&gt;

&lt;table&gt;

&lt;tr&gt;&lt;td&gt;Auth API v3&lt;/td&gt;&lt;/tr&gt;


&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;POST&amp;nbsp;/api/session&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
  &lt;p&gt;This API endpoint is responsible for creating a session. It accepts a username/password combination, or an OAuth2 code and service name. If a username/password combination is submitted, it attempts to authenticat a user to match that account. If a code/service combination is submitted, it attempts to validate the code, then attempts to authenticate a user to match that account. It returns either a session object with an access token, or an error that the OAuth2 code is invalid, or an error that the user could not be authenticated.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;

&lt;p&gt;This is where most apps end up. They meander into building a session API that is more like an RPC request than RESTful action. The inputs are inconsistent, the endpoint has the responsibility to do a large number of things (OAuth2 verification, username/password verification), and the possible error states are numerous.&lt;/p&gt;

&lt;p&gt;But there is a way out.&lt;/p&gt;

&lt;h2&gt;A RESTful auth API&lt;/h2&gt;

&lt;p&gt;When an API endpoint becomes cluttered with too many responsibilities, it stops being expressive of a domain object. The URLs of an API (e.g., &lt;code&gt;/api/session&lt;/code&gt;) should be expressive of a domain object (e.g., the &#8220;session&#8221;). RESTful API design allows domain objects to be &lt;em&gt;composable&lt;/em&gt;. Composable objects can be combined to achieve the same ends as procedural API calls, and are flexible enough to meet other goals as well.&lt;/p&gt;

&lt;p&gt;If the concept of &#8220;session&#8221; is cluttered, then the API is lacking. It fails to express &#8220;session&#8221; in a composable manner. By extracting a new domain object from the API, &#8220;session&#8221; can be repaired.&lt;/p&gt;

&lt;p&gt;Let&#8217;s try an approach that separates authorization from session creation:&lt;/p&gt;

&lt;table&gt;

&lt;tr&gt;&lt;td&gt;Auth API v4&lt;/td&gt;&lt;/tr&gt;


&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;POST&amp;nbsp;/api/socialAuthorization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
  &lt;p&gt;This API endpoint is responsible for creating a social authorization. It accepts an OAuth2 code and service name. It validates the code, and either returns a social authorization object or returns an error.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;POST&amp;nbsp;/api/session&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
  &lt;p&gt;This endpoint is responsible for creating a session. It accepts a username/password combination, &lt;strong&gt;or a social authorization object&lt;/strong&gt;. It returns a session object, or an error that the credentials are incorrect.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;

&lt;p&gt;The concerns of OAuth2 authorization and session creation are isolated. As a bonus, we have a social authorization object that can be passed not only to the session API, but also to other APIs. Consider the common scenario where an existing user wants to link his or her account to social accounts in order to make logins easier, or to enable some integration with their social networks:&lt;/p&gt;

&lt;table&gt;

&lt;tr&gt;&lt;td&gt;Auth API v5&lt;/td&gt;&lt;/tr&gt;


&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;POST&amp;nbsp;/api/socialAuthorization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
  &lt;p&gt;This API endpoint is responsible for creating a social authorization. It accepts an OAuth2 code and service name. It validates the code, and either returns a social authorization object or returns an error.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;POST&amp;nbsp;/api/session&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
  &lt;p&gt;This endpoint is responsible for creating a session. It accepts a username/password combination or a social authorization object. It returns either a session object, or an error that the credentials are incorrect.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;POST&amp;nbsp;/api/me/connectedAccounts&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
  &lt;p&gt;This endpoint is responsible for connecting social accounts to an existing user account. It accepts a social authorization object, and returns either a connected account object or an error.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;

&lt;p&gt;Note that the new endpoint accepts the social authorization object. The JavaScript client can take advantage of composability to combine these endpoints in novel ways. Handling errors at any single step of a complex interaction is trivial.&lt;/p&gt;

&lt;p&gt;&#8220;But the crafty developer!&#8221; I hear you cry, &#8220;How was she handling OAuth2 without server-side redirects?!&#8221;&lt;/p&gt;

&lt;h2&gt;OAuth2 Without Redirects&lt;/h2&gt;

&lt;p&gt;A redirect endpoint (as in v2 of the API above) is not the ideal way to handle authorization for a couple of reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript applications need to restore a special state when loading after the redirect.&lt;/li&gt;
&lt;li&gt;A redirection-based interface isn&#8217;t portable to other API consumers.&lt;/li&gt;
&lt;li&gt;It is slow and provides poor UX.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thankfully, a popup can encapsulate OAuth exchanges without reloading the JavaScript application. OAuth2 can be consumed without a server-side redirect handler, and though OAuth 1.0 would requires a handler we can slim down its responsiblities and complexity.&lt;/p&gt;

&lt;p&gt;Let&#8217;s re-imagine how to create authorization from Facebook&#8217;s OAuth2 API, using the &#8220;code&#8221; flow&#8221;:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;After submitting credentials to Facebook, the browser is redirected to a page that loads the JavaScript application. The application stalls while loading, and submits the URL containing the authorization code back to the parent window.&lt;/p&gt;

&lt;p&gt;This is where Torii comes in. For Ember.js applications, we&#8217;ve given you a way to build and consume these flows easily.&lt;/p&gt;

&lt;h2&gt;Authorization Objects and Torii&lt;/h2&gt;

&lt;p&gt;Torii encourages you to work with composable, RESTful APIs by isolating authorization (through providers) from authentication (through adapters).&lt;/p&gt;

&lt;p&gt;Torii is composed of just three primitives, and just three possible actions.&lt;/p&gt;

&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Providers&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
  &lt;p&gt;In Torii, a provider is anything that can return authorization. For example, all of Facebook, Twitter, and my own API can be providers returning authorization. Furthermore, we talk about providers as specific authorization implementations. Both &#8220;Auth via Facebook Connect SDK&#8221; and &#8220;Auth via Facebook&#8217;s OAuth2 Authorization Code flow&#8221; are providers.&lt;/p&gt;
  &lt;p&gt;An idiomatic provider can execute only a single action:&lt;/p&gt;
  &lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;open&lt;/strong&gt; – create a new authorization&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p&gt;We&#8217;ve provided several ready-to-go providers, but writing your own should be easy. Additionally, though I don&#8217;t believe there are idiomatic usages for `fetch` and `close` on a provider, those actions are also supported.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;    
&lt;td&gt;&lt;strong&gt;Sessions&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
  &lt;p&gt;A session manager is responsible for maintaining the authentication state of a user. A session tracks if a user is authenticated or un-authenticated, and who the currently authenticated user is. The session knows nothing about how a user became authenticated, just whether or not they are currently authenticated.&lt;/p&gt;
  &lt;p&gt;The session manager can execute the following actions:&lt;/p&gt;
  &lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;open&lt;/strong&gt; – create a new session&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;fetch&lt;/strong&gt; – retrieve and validate an existing session&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;close&lt;/strong&gt; - destroy an existing session&lt;/li&gt;
  &lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Adapters&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
  &lt;p&gt;A Torii adapter maps the interface expected by the session manager onto your specific API.&lt;/p&gt;
  &lt;p&gt;We&#8217;ve chosen to leave the implementation of this to developers. Often Ember applications are built on existing APIs, and we believe the client-side code should be flexible enough to adapt to what exists.&lt;/p&gt;
  &lt;p&gt;Adapters can execute the following actions:&lt;/p&gt;
  &lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;open&lt;/strong&gt; – create a new session using an authorization&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;fetch&lt;/strong&gt; – retrieve and validate an existing session&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;close&lt;/strong&gt; – destroy an existing session&lt;/li&gt;
  &lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;Providers in Torii are composable. They return authorization objects (often OAuth2 codes). Those objects could be passed to a connected account creation API, or to a session creation API. If you use the Torii session manager, they are passed to the adapter for your app, which can manage the exchange of authorization for a session object and/or current user.&lt;/p&gt;

&lt;p&gt;Torii powers your JavaScript application&#8217;s session so that you only need to implement the exchange of an authorization object for a session object and current user. All the social authorization concerns stay out of your way.&lt;/p&gt;

&lt;h2&gt;Wrap up&lt;/h2&gt;

&lt;p&gt;Let me know how your API has solved the authentication challenge, and give &lt;a href=&quot;http://github.com/vestorly/torii&quot;&gt;Torii&lt;/a&gt; a look if your next project will be written in Ember.js.&lt;/p&gt;

&lt;p&gt;Much thanks to &lt;a href=&quot;https://twitter.com/solirvine&quot;&gt;@solirvine&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/joeyAghion&quot;&gt;@joeyAghion&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/denik&quot;&gt;@denik&lt;/a&gt;, and &lt;a href=&quot;https://twitter.com/fancyremarker&quot;&gt;@fancyremarker&lt;/a&gt; for their time reviewing this post.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update: Some &lt;a href=&quot;https://news.ycombinator.com/item?id=7905848&quot;&gt;discussion at Hacker News&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://madhatted.com/">
    <author>
      <name>mixonic</name>
    </author>
    <id>tag:madhatted.com,2014-03-28:3162</id>
    <published>2014-03-28T21:43:00Z</published>
    <updated>2014-04-24T21:32:36Z</updated>
    <category term="browsers"/>
    <category term="chrome"/>
    <category term="ember.js"/>
    <category term="Javascript"/>
    <category term="javascript"/>
    <category term="networks"/>
    <category term="performance"/>
    <link href="http://madhatted.com/2014/3/28/via-emberconf-performance-in-ember-apps" rel="alternate" type="text/html"/>
    <title>Via EmberConf: Performance in Ember Apps</title>
<content type="html">
            



&lt;blockquote&gt;
    &lt;p&gt;Ember is fast. Ember Core is working hard to make Ember even faster. So why does your app drag?&lt;/p&gt;
    
    &lt;p&gt;The performance of a single-page app is impacted by the performance characteristics of its foundational parts: Network, Rendering, and JavaScript. Ember provides tools to manage these cornerstones, but with the tradeoff of introducing its own characteristics.&lt;/p&gt;
    
    &lt;p&gt;In this talk, we will use the source of real, shipped Ember apps (and of Ember itself) to diagnose, understand, and improve slow interactions. The Chrome developer tools will help us understand slow code paths and identify opportunities for improvement. Along the way, we will learn how parts of Ember work at the macro and micro level and learn how the framework helps us manage performance challenges in a browser environment.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At EmberConf, I spoke on web application performance and Ember.js. The message of this talk is that &lt;strong&gt;application performance is bigger than Ember performance&lt;/strong&gt;. As authors of many of the more ambitious single-page web applications out there, we need to understand the tools and techniques used in analyzing and bettering the a user&#8217;s experience.&lt;/p&gt;

&lt;p&gt;The slides above are accompanied by two live-coding sessions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Debugging a janky animation, &lt;a href=&quot;http://screencast.com/t/TqtMmnvhiQg&quot;&gt;part #1&lt;/a&gt; and &lt;a href=&quot;http://screencast.com/t/Hl6krsx3lN&quot;&gt;part #2&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://uni.madhatted.com/emberconf/animation-initial/index.html&quot;&gt;Initial moving Tomster animation with jank&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://uni.madhatted.com/emberconf/animation-second/index.html&quot;&gt;Second moving Tomster animation with jank&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://uni.madhatted.com/emberconf/animation/index.html&quot;&gt;Optimized moving Tomster animation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Conserving property change notifications, &lt;a href=&quot;http://screencast.com/t/GMIHB4q4xyr&quot;&gt;part #1&lt;/a&gt; and &lt;a href=&quot;http://screencast.com/t/xEagiQzyz&quot;&gt;part #2&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://uni.madhatted.com/emberconf/push-into-array/index.html&quot;&gt;Initial implementation of populating and displaying an array&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://uni.madhatted.com/emberconf/push-into-array-optimized/index.html&quot;&gt;Optimized implementation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also mentioned several tools in the slides and videos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I used Google Chrome (stable, v33) on OSX for all my examples.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://gfx.io/&quot;&gt;gfxCardStatus&lt;/a&gt; for pinning a mac to a specific graphics card&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://slowyapp.com/&quot;&gt;Slowy&lt;/a&gt; for emulating high-latency networks (alternatively &lt;a href=&quot;http://www.charlesproxy.com/&quot;&gt;Charles Proxy&lt;/a&gt; or &lt;a href=&quot;developer.apple.com/downloads/index.action?name=for Xcode -#&quot;&gt;Network Link Conditioner&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally there are a few documentation resources I strongly encourage you to read:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;a href=&quot;https://developers.google.com/chrome-developer-tools/&quot;&gt;documentation for the Chrome developer tools&lt;/a&gt;, including:
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.google.com/chrome-developer-tools/docs/network&quot;&gt;Network tab documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.google.com/chrome-developer-tools/docs/timeline&quot;&gt;Timeline tab documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.google.com/chrome-developer-tools/docs/cpu-profiling&quot;&gt;JavaScript profiling documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;How to use &lt;a href=&quot;https://support.google.com/chrome/answer/2364824?hl=en&quot;&gt;multiple Chrome users&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ilya Grigorik&#8217;s excellent &lt;a href=&quot;http://www.amazon.com/High-Performance-Browser-Networking-performance/dp/1449344763&quot;&gt;Browser Networking&lt;/a&gt; book. I believe this can be read online, but if you are a professional developer the money will be well spent.&lt;/li&gt;
&lt;li&gt;Iilya&#8217;s recent talk on &lt;a href=&quot;https://www.youtube.com/watch?v=7ubJzEi3HuA&quot;&gt;Speed, Performance, and Human Perception&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let me know if you have feedback on the presentation, and thanks to those who attended. In such a short talk it would have been difficult to comprehensively cover all the possible performance hangups in an Ember application, so instead these slides focus on giving you a new and better understanding of the tools available for gathering data, analyzing issues, and asserting the success of a change. With some practice, you will be using them every day.&lt;/p&gt;

&lt;p&gt;Thanks to everyone at EmberConf for a fantastic week!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Correction: &lt;strong&gt;setProperties does not cause observers to coalesce&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In my presentation at EmberConf, I stated that setting multiple properties with setProperties would cause an observer to only fire once. This is incorrect. The observer will fire for each property changed. See an illustration of the behavior in &lt;a href=&quot;http://emberjs.jsbin.com/xacag/1/edit?html,js,output&quot;&gt;this jsbin&lt;/a&gt;. Thanks to &lt;a href=&quot;https://twitter.com/krisselden&quot;&gt;@krisselden&lt;/a&gt; for the catch.&lt;/em&gt;&lt;/p&gt;
          </content>  </entry>
</feed>
