Building Bridges, Connecting Communities

58
Building Bridges, Connecting Communities VADIM MIRGOROD Front-end, 05/22/2013 Using Backbone.js with Drupal 7 and 8

description

Using Backbone.js with Drupal 7 and 8. VADIM MIRGOROD Front-end, 05/22/2013. Building Bridges, Connecting Communities. Vadim Mirgorod. Lead developer in Trellon Writing Backbone.js CookBook for PACKT Email: [email protected] Web: http://vmirgorod.name Twitter: @dealancer. # 2. - PowerPoint PPT Presentation

Transcript of Building Bridges, Connecting Communities

Page 1: Building Bridges, Connecting Communities

Building Bridges, Connecting Communities

VADIM MIRGORODFront-end, 05/22/2013

Using Backbone.js withDrupal 7 and 8

Page 2: Building Bridges, Connecting Communities

Vadim Mirgorod

• Lead developer in Trellon

• Writing Backbone.js CookBook for PACKT

• Email: [email protected]

• Web: http://vmirgorod.name

• Twitter: @dealancer#2

Page 3: Building Bridges, Connecting Communities

Remember the web development in 90s?

#3

Page 4: Building Bridges, Connecting Communities

1995: JavaScript

#4

Page 5: Building Bridges, Connecting Communities

2000: XMLHttpRequest

#5

Page 6: Building Bridges, Connecting Communities

2006: jQuery

#6

Page 7: Building Bridges, Connecting Communities

2013:

?#7

Page 8: Building Bridges, Connecting Communities

What's new in JS?

• HTML5:– Local Storage– pushState

• JS templating engines:– Mustache.js– Twig.js

• Representative State Transfer (REST)

#8

Page 9: Building Bridges, Connecting Communities

JavaScript client evolution

#9

Page 10: Building Bridges, Connecting Communities

Complexity

#10

Page 11: Building Bridges, Connecting Communities

Thin to thick transition

#11

Page 12: Building Bridges, Connecting Communities

Performance

#12

Page 13: Building Bridges, Connecting Communities

Problems!

Page 14: Building Bridges, Connecting Communities

Right now typical AJAX code looks like this$(document).ready(function() {

$("#getData").click( function() {

$.getJSON("artistsRemote.cfc?method=getArtists&returnformat=json",

function(data) {

$("#artistsContent").empty();

$("#artistsTemplate").tmpl( data ).appendTo("#artistsContent");

var nowIs = new Date().toLocaleString();

$('#lastLoad').html( nowIs );

});

});

});

#14

Page 15: Building Bridges, Connecting Communities

AJAX in Drupal

Have you seen any JS?

#15

Page 16: Building Bridges, Connecting Communities

#16

Page 17: Building Bridges, Connecting Communities

Let's do things properly!

#17

Page 18: Building Bridges, Connecting Communities

Meet...

#18

Page 19: Building Bridges, Connecting Communities

#19

Page 20: Building Bridges, Connecting Communities

Backbone.js

• URL: http://backbonejs.org/

• Created by Jeremy Ashkenas in 2010, an author of CoffeeScript

• Based on Underscore.js: http://backbonejs.org/

• Requires jQuery or Zepto

#20

Page 21: Building Bridges, Connecting Communities

Backbone.js features

• Minimalistic

• Modular

• Perfect OOP design

• Over 100 available extensions:

https://github.com/documentcloud/backbone/wiki/Extensions,-Plugins,-Resources

• Community

#21

Page 22: Building Bridges, Connecting Communities

Backbone vs...

• Knockout

• AngularJS

• CanJS

• Spine

• Ember.js

• many others

#22

Page 23: Building Bridges, Connecting Communities

Backbone vs...

#23

Page 24: Building Bridges, Connecting Communities

Who uses Backbone.js?• Groupon Now!

• Foursquare

• LinkedIn Mobile

• Airbnb

#24

Page 25: Building Bridges, Connecting Communities

Let's learn how to backbone!

#25

Page 26: Building Bridges, Connecting Communities

Main concepts

• Model

• Collection

• View

• Template

• Router

• History

• Events

#26

Page 27: Building Bridges, Connecting Communities

MVC: Backbone:

http://www.jboss.org/jdf/examples/ticket-monster/tutorial/UserFrontEnd/

#27

Page 28: Building Bridges, Connecting Communities

DEMO!TODO APP

#28

Page 29: Building Bridges, Connecting Communities

Easy example

Page 30: Building Bridges, Connecting Communities

Define the model and the collection // Define new model.

var InvoiceItemModel = Backbone.Model.extend({

calculateAmount: function() {

return this.get('price') * this.get('quantity');

}

});

// Define new collection object.

var InvoiceItemCollection = Backbone.Collection.extend({

model: InvoiceItemModel

});

#30

Page 31: Building Bridges, Connecting Communities

Define the view to render the model var InvoiceItemView = Backbone.View.extend({

// Define element tag name.

tagName: 'tr',

// Define template.

template: _.template($('#item-row-template').html()),

// Render the view.

render: function() {

var data = this.model.toJSON();

data.amount = this.model.calculateAmount();

$(this.el).html(this.template(data));

return this;

},

});#31

Page 32: Building Bridges, Connecting Communities

Define the view to render the collection

var InvoiceItemListView = Backbone.View.extend({

tagName: 'table',

template: _.template($('#item-table-template').html()),

// Render the view.

render: function() {

$(this.el).html(this.template());

_.each(this.collection.models, function(model, key) { this.append(model); }, this);

return this;

},

// Add an invoice item row to the table.

append: function(model) {

$(this.el).append(new InvoiceItemView({ model: model }).render().el);

}

});#32

Page 33: Building Bridges, Connecting Communities

Add templates into index.html <script type="text/html" class="template" id="item-table-

template">

<tr>

<th>Quantity</th>

<th>Description</th>

<th>Price</th>

<th>Amount</th>

</tr>

</script>

<script type="text/html" class="template" id="item-row-template">

<td><%= quantity %></td>

<td><%= description %></td>

<td><%= price %></td>

<td><%= amount %></td>

</script>#33

Page 34: Building Bridges, Connecting Communities

Create collection and show the view var invoiceItemCollection = new InvoiceItemCollection([

{ description: 'Wooden Toy House', price: 22, quantity: 3 },

{ description: 'Farm Animal Set', price: 17, quantity: 1 },

]);

$('body').html(new InvoiceItemListView({

collection: invoiceItemCollection }).render().el

);

#34

Page 35: Building Bridges, Connecting Communities

Some cool thingsTwo way binding

Model to view binding

LayoutsTemplatesRouter

Forms

Page 36: Building Bridges, Connecting Communities

Model to view binding

var InvoiceItemView = Backbone.View.extend({

// ...

initialize: function() {

this.listenTo(this.model, 'destroy', this.destroy, this);

this.listenTo(this.model, 'change', this.render, this);

},

destroy: function() { this.remove(); }

});

var InvoiceItemListView = Backbone.View.extend({

// ...

initialize: function() {

this.listenTo(this.collection, 'add', this.append, this);

}

});#36

Page 37: Building Bridges, Connecting Communities

Forms

// Backbone-forms extension.

var UserModel = Backbone.Model.extend({

schema: {

title: { type: 'Select', options: ['Mr', 'Mrs', 'Ms'] },

name: 'Text',

email: { validators: ['required', 'email'] },

password: 'Password',

birthday: 'Date',

}

});

userModel = new BuyerModel();

$('body').append(new Backbone.Form({ model: this.user }).form.render().el);#37

Page 38: Building Bridges, Connecting Communities

Two-way binding

// Backbone.stickit extension.

var InvoiceItemFormView = Backbone.View.extend({

className: 'invoice-item-form-view',

bindings: {

'#description': 'description',

'#price': 'price',

'#quantity': 'quantity'

},

render: function() {

var html = '<label>Description:</label><input type="text" id="description"></input><br>' +

'<label>Price:</label><input type="text" id="price"></input><br>' +

'<label>Quantity:</label><input type="text" id="quantity"></input><br>';

$(this.el).html(html);

// Here binding occurs.

this.stickit();

return this;

}#38

Page 39: Building Bridges, Connecting Communities

Forms

// Backbone-forms extension.

var UserModel = Backbone.Model.extend({

schema: {

title: { type: 'Select', options: ['Mr', 'Mrs', 'Ms'] },

name: 'Text',

email: { validators: ['required', 'email'] },

password: 'Password',

birthday: 'Date',

}

});

userModel = new BuyerModel();

$('body').append(new Backbone.Form({ model: this.user }).form.render().el);#39

Page 40: Building Bridges, Connecting Communities

Router

var Workspace = Backbone.Router.extend({

routes: {

// Default path.

'': 'invoiceList',

// Usage of static path.

'invoice': 'invoiceList',

// Usage of fragment parameter.

'invoice/:id': 'invoicePage',

// Usage of fragment parameters.

'help/:topic/page:page': 'helpPage',

// Usage of splat parameter.

'download/*path': 'downloadPage'

},

});

#40

Page 41: Building Bridges, Connecting Communities

Other cool things...

in Backbone.js Cookbook

Page 42: Building Bridges, Connecting Communities
Page 43: Building Bridges, Connecting Communities

• Bootstrapping:– Technique we saw above– Do it yourself

• Representational State Transfer:– Services module– RESTful webservices module

• Backbone.js module

Backbone and Drupal 7

#43

Page 44: Building Bridges, Connecting Communities

REST

#44

Page 45: Building Bridges, Connecting Communities

REST in Backbonevar PostModel = Backbone.Model.extend({

// Override id attribute.

idAttribute: '_id',

// Define URL root to access model resource. Otherwise use

// url() method to provide full path to the model resource.

urlRoot: function() { return 'http://example.com/posts/'; }

});

var PostCollection = Backbone.Collection.extend({

model: PostModel,

// Define path to the collection resource.

url: function() { return 'http://example.com/posts/'; }

});

#45

Page 46: Building Bridges, Connecting Communities

REST in Backbone.js// Fetches data into a model.

model.fetch();

// Saves a model.

model.save();

// Destroys a model.

model.destroy();

// Fetches data into a collection.

collection.fetch();

// Adds models to a collection.

collection.add(models);

// Removes specific models from collection.

collection.remove(models);

#46

Page 47: Building Bridges, Connecting Communities

Backbone module

• URL: http://drupal.org/project/backbone

• Provides models and collections for Drupal entities via REST:

– Node: Node model– All node: NodeIndex collection– Arbitrary view: NodeView collection

• Works with both Services and RESTful Web Services modules.

#47

Page 48: Building Bridges, Connecting Communities

Backbone module

// Create new NodeView collection.

var viewCollection = new Drupal.Backbone.Collections.NodeView();

// Set Drupal View name.

viewCollection.viewName = 'backbone_example';

// Fetch data from the collection.

viewCollection.fetch({success: function() {

console.log(viewCollection.toJSON());

});

#48

Page 49: Building Bridges, Connecting Communities

Backbone mdl roadmap• Support for bootstrapping

• Better views support

• In-place content editing

• Drag and Drop

• D8 version?

#49

Page 50: Building Bridges, Connecting Communities

http://www.flickr.com/photos/gabblebee/3977912731/

Page 51: Building Bridges, Connecting Communities

Backbone and Drupal 8• It is in core!

• Used for In-place editing issue:http://drupal.org/node/1824500

• Used for layouts issue:http://drupal.org/node/1841584

• Used for toolbar issue:http://drupal.org/node/1860434

• META issue: http://drupal.org/node/1858368

#51

Page 52: Building Bridges, Connecting Communities

DEMO!

Page 53: Building Bridges, Connecting Communities

One more thing!

• Web services initiative– REST in core– Storage controllers

• Twig– Templating engine– Twig in core (Twig sandbox)– Works both for PHP and JS

#53

Page 54: Building Bridges, Connecting Communities

One more thing!

#54

Twig templatesStorage controllersAccess controllers

Render controllersForm controllers

DBBrowser

Page 55: Building Bridges, Connecting Communities

One more thing!

#55

Backbone app

Twig templatesStorage controllersAccess controllers

Render controllersForm controllers

DB

REST

Browser

Page 56: Building Bridges, Connecting Communities

One more thing!

#56

Backbone app

Twig templatesStorage controllersAccess controllers

Render controllersForm controllers

DB

REST

Browser

Mobile

Page 57: Building Bridges, Connecting Communities

One more thing!

#57

Backbone app

Twig templates

Storage controllersAccess controllers

DB

REST

Mobile app built with PhoneGap or Trigger.io

Page 58: Building Bridges, Connecting Communities

Building Bridges, Connecting Communities

Evaluate this session at: portland2013.drupal.org/node/1578.

Thank you!

What did you think?