Mode Set

Detangle your jQuery

lessons from CoffeeScript to create better design

@jedschneider | @modeset_

http://jquery-coffeescript.herokuapp.com/

As presented:

ConvergeSE | Refresh Savannah

11.20.2017 mode set

What does a train wreck look like in jQuery?

It doesn't fit on a single slide, but here's the gist:

$(document).ready(function(){
  $('.right li:first .tabs').tabs({
    beforeLoad: function (e, ui){ /*...*/ },
    options : { disabled : false, active : 1 }
  });
  $('#myModal').on('show', function(e){
    /* more mayham here */
  });
  /* infinite number of calls to other components here */
});

A highly coupled, procedural command sequence; on a collision course with your application.

What if we could do it differently?

Decoupled: independent actors, single responsibility

Composable and Extendable: build big things with little pieces

Testable

Inspiration

OOP

class Bar
  def baz
    "baz"
  end
end

b = Bar.new
b.baz #=> "baz"
class Foo < Bar
  def foo
    "foo"
  end
end

f = Foo.new
f.baz #=> "baz"
f.foo #=> "foo"

Function Objects

  c = new Cirle()
  c.radius()

basically, we can apply our mental model of oop to function objects

read "Javascript the good parts"

Backbone

Extension & Initialization

insight into coffeescript language structures

Backbone

an 'mvc' framwork for browser based web applications (but lets just talk about the 'view')

<ul class="list">
  <!-- each one of these could be a view -->
  <li class="list-item">
    <a/>
    <div></div>
  </li>
  <!-- another view -->
  <li></li>
</ul>

Backbone

http://jsfiddle.net/jedschneider/m5LST/
ItemView = Backbone.View.extend({
  tagName: 'li',
  doSomething: function(arg){ return console.log(arg); }
});

var item = new ItemView();

item.doSomething("foo");

backbone relies on extension of function objects

Backbone continued

Initialization

<ul><li class='list-item'></li></ul>
item = new ItemView({el: $('.list-item')})

item.el #=> $('.list-item')

using an options hash to provide defaults to the instance (accepts a small subset of commonly assigned items)

Implementation

OOP, Function Objects in Backbone

and, of course,

coffeescript

Backbone in CoffeeScript

http://jsfiddle.net/jedschneider/ENbN2/6/
class ItemView extends Backbone.View
  tagName: 'li'
  doSomething: (arg)-> console?.log(arg)

item = new ItemView()

item.doSomething("foo")

Native Features

existential operator, keywords : class & extend, whitespace significant, no var keyword

Backbone 'revisited'

class ItemView extends Backbone.View
  tagName: 'li'

  constructor: ({@el})->
    super()

  doSomething: (arg)->
    console?.log arg

item = new ItemView(el: $('.item-view'))
item.doSomething("foo")

Question do we really need Backbone?

Utensils

Our extremely opinionated component library for the Rails framework.

utensils.modeset.com

$ rails generate untensils:component foo

Utensils

app/assets/components/foo
├── _foo.sass
├── foo.coffee
└── spec
    ├── fixture.html.haml
    └── foo_spec.coffee

Each component takes care of its own styling.

Each component takes care of its own behavior.

Utensils: adding behavior

a 53 line piece of magic we call Bindable

Utensils: adding behavior

http://jsfiddle.net/jedschneider/n26r5/8/
<ul data-bindable='item-view'></ul>
class ItemView
  constructor: (@el)->
    #custom magic happens here

utensils.Bindable.register 'item-view', ItemView
$(document).ready ->
  @bindable = new utensils.Bindable().bindAll()

Utensils: adding behavior

lets take a look at Bindable and see some more coffeescript features

Why is this better design?

thank you