Writing HTML5 Mobile Web Apps using Backbone.js
-
Upload
ron-reiter -
Category
Technology
-
view
40.006 -
download
4
description
Transcript of Writing HTML5 Mobile Web Apps using Backbone.js
Writing HTML5 Mobile Web Apps
A complete development stackRon Reiter (Any.DO)
Agenda
HTML5 or native?
HTML5 Mobile Development FrameworksPhoneGap
Trigger.IO
UI FrameworksjQuery Mobile
Sencha Touch
jqMobi
MVC with Backbone.js
Client Side Templating with Mustache
Modular Javascript with RequireJS
Go web or native?
Web Native
Cross-platform code. Smoother user interface.
CSS3 is very powerful, easy and flexible compared to Android and iPhone UI libraries.
More control and flexibility (for example, PhoneGap does not export all native abilities).
Easy to patch / update because only web assets need to be replaced.
You will need to write Javascript to native interfaces if your back-end / business logic is already programmed using native code
All you need to know is Javascript for all platforms.
Static elements and transitions are still laggy.
My suggestion
Use WebViews when you need to have a complicated, good looking user interface, and if you need it fast
User native UI when you need very CPU intensive, sleek interface, and you are willing to invest a lot of work on it
Use a combination of both to gain both advantages! Use native static elements (header, footer, page frames and page transitions), and program the actual user interface in WebViews
Mobile Development Frameworks
PhoneGap, Trigger.IO
PhoneGap
Cross platform open source framework for writing mobile apps
Write your program once, and compile an app for Android, iPhone, BlackBerry, Windows Phone, and more…
Exports Javascript APIs for native phone control (camera, GPS, filesystem, etc.) and has plugins
PhoneGap APIs
Accelerometer
Camera
Capture
Compass
Connection
Contacts
Device
Events
File
Geolocation
Media
Notification
Storage
Trigger.IO
Similar to PhoneGap, but commercial
Has a utility called forge which does the app building for you, instead of opening 3 completely different IDEs to do it yourself
Claims to outperform PhoneGap native bridge by x5
You should choose it if you can write your program in Javascript only (no plugins)
Good for web, too!
Trigger.IO
UI FrameworksjQuery Mobile, Sencha Touch, jqMobi
UI Frameworks
If you decide to build all of your mobile UI using a web framework, you should use a UI framework which saves time with mobile-looking components
jQuery Mobile – Free, heavily backed by the communityhttp://jquerymobile.com/
Sencha Touch – Commercial, robusthttp://www.sencha.com/products/touch
jqMobi – Haven’t tried it, but it looks promising in terms of performance, which is the Achilles heel of mobile web UI
http://www.jqmobi.com/
http://www.youtube.com/watch?v=MwNdWZsRXgk
The Fixed Toolbar Nightmare
Either you have a new device which supports real fixed toolbars, or you simulate the scroll
jQuery goes with real toolbars & fallback support. Fallbacks to statically positioned toolbars
Sencha Touch goes for compatibility and simulates the scroll by moving the body up instead of letting the page scroll down
If you really want both performance and compatibility - the best solution would probably be… to use native toolbars
jQuery Mobile
jQuery Mobile does not use jQuery – you can use whatever you want for DOM manipulation
Evolved a lot in the past year and is ready for real world development
Although performance has improved a lot, it’s still not amazing. You might want to do a little more research
jQuery Mobile Features
Pages and sliding page transitions, toolbars (header, footer, fixed), navigation pane, forms, themes and more
Codiqa – Rapid jQuery Mobile Prototyping
MVC Frameworks
Comparison
Backbone.js, Spine.js – very similar libraries
Ember.js – has automatic updating templates, which are voodooish, and bindings work a bit different
Ember should be nicer to program with, but Backbone gives more control and performance
Backbone.js
Backbone.js
Backbone.js is a minimal, popular, generic MVC framework for writing heavy HTML5 web & mobile applications
Who uses Backbone.js?LinedIn, Soundcloud, Basecamp, Codiqa, and more
Backbone.js
Backbone.js makes you program user interface the right way
An object model with inheritance
REST Sync
Can be used with jQuery/Zepto, MooTools, etc. for DOM manipulation
Code with Backbone
Code without Backbone Code with Backbonefunction createListView(id) {
var listView = $(“<div>”).addClass(“list”) .click(function(e) { if ($(e).is(“li”)) $(e.target).addClass(“selected”); $(this).data(“selected”, $(e.target) .text());}).keypress(function(e) { if (e.keyCode == 8) { $(this).find(“.selected”).remove(); });
return listView;}
var listView = createListView();
Var ListView = Backbone.View.extend({ tagName: “div”, className: “list”, events: { “click li” : “clickItem”, “keypress” : “deleteOnKeypress” }, clickItem: function(e) { $(e.target).addClass(“selected”); this.selected = $(e.target).text(); }, deleteOnKeypress: function(e) { if (e.keyCode == 8) { $(this.el).find(“.selected”).remove(); } }}
var listView = new ListView();
Quick REST Tutorial
REST = REpresentational State Transfer
It is a protocol which servers implement to give control of the state of a data set (a collection of data items)
REST maps CRUD operations to HTTP operationsCollection Operations
HTTP GET = Read
HTTP POST = Create
Model OperationsHTTP PUT = Update
HTTP DELETE = Delete
Backbone MVC Architecture
ViewHTML + CSS
ControllerBackbone.View
ModelBackbone.Model
DOM ManipulationWith jQuery andtemplating
DOM View Events
Backbone REST Sync
Server Model Database
Model Events
Model updatedaccording touser interaction
Backbone Model
Model Viewchange/delete
The Backbone.js Model represents a single data entity
It is usually bound to a view in such a way that every time it changes, the view is updated accordingly (MVC)
Backbone.js Model
Backbone fires “change” and “destroy” events when specific models are updated or deleted.
Without regarding views, Backbone also automatically synchronizes models back to the server on every change
Model
Server
Backbone Model
Model
task.save({ title: “Get Rich”, done: false});
Viewchange:title
Server
HTTP PUT /tasks/1
Backbone Model
Model
task.destroy()
Viewdestroy
remove
Server
HTTP DELETE /tasks/1
Backbone Collection
A Backbone Collection object stores a set of models of the same type
It configures the REST endpoint in the server for the data set
Model
Model
Model
Collection Server
Backbone Collection
Backbone collections can fetch a collection from the server
A “reset” event is fired when results from the server return
Collection Server
tasks.fetch();tasks.bind(“reset”, this.addTaskViews);
HTTP GET /tasks
Model
Model
Model
Backbone Collection
Backbone collections have the “create” method, which creates a new model
Model
Model
Model
Collection Server
New Model
tasks.create({ title: “Hello, world!”, done: false});tasks.bind(“add”, this.addTaskView)
HTTP POST /tasks
New task ID: 3
New Model
Summary - Backbone REST Architecture
ModelView
ModelView
ModelView
ModelView
Collection
PUT /tasks/41DELETE /tasks/41
PUT /tasks/39DELETE /tasks/39
PUT /tasks/40DELETE /tasks/40
PUT /tasks/38DELETE /tasks/38
GET /tasksPOST /tasks
Collection OperationsModel Operations
Backbone View
Views represent a model or a collection of models, and are responsible for managing their child views
Backbone creates a DOM element with a specific class for every new view, using the tagName and className tags
Or, Backbone can use a view which already exists in the DOM, if el is defined
Backbone.View.extend({ tagName : “div”, className: “section”})
Backbone.View.extend({ el: $(“#main-view”);})…<div id=“main-view”></div>
Backbone View
The View is the most important class of Backbone, since it’s actually an MVC controller. (Bad choice of words. Check out spine.js for a better choice)
It translates the user actions into model changes
It updates the view when a model is changed
Backbone View
Let’s create a todo item view, which represents a single todo item in a todo list
View
var todoItemView = Backbone.View.extend({ tagName: “div”, className: “todo”});
Backbone View
Now let’s add the model it is bound to
var todoItemView = Backbone.View.extend({ tagName: “div”, className: “todo”, model: todoModel});
View
Model
Backbone View
Get notified when the model is changed by binding on model change events, so we’ll know we need to update itvar todoItemView = Backbone.View.extend({
tagName: “div”, className: “todo”, model: todoModel, initialize: function() { _.bindAll(this, “update”); this.model.bind(“change”, this.update); }});
View
Model
Backbone View
When checking off the task, we want to know about it. So let’s add a checkbox change handler
var todoItemView = Backbone.View.extend({ tagName: “div”, className: “todo”, model: todoModel, initialize: function() { _.bindAll(this, “update”, “check”); this.model.bind(“change”, this.update); }, events: { “change .done-checkbox” : this.check }});
View
Model
X
Backbone View
Now, let’s toggle the task’s “done” status in the function “check”
var todoItemView = Backbone.View.extend({ tagName: “div”, className: “todo”, model: todoModel, initialize: function() { _.bindAll(this, “update”, “check”); this.model.bind(“change”, this.update); }, events: { “change .done-checkbox” : this.check }, check: function() { this.model.save({ done: !this.model.get(“done”); }); }});
View
Model
X
Backbone View
Let’s update the view when we receive the “update” eventvar todoItemView = Backbone.View.extend({
tagName: “div”, className: “todo”, model: todoModel, initialize: function() { _.bindAll(this, “update”, “check”); this.model.bind(“change”, this.update); }, events: { “change .done-checkbox” : this.check }, check: function() { this.model.save({ done: !this.model.get(“done”); }); }, update: function() { this.title.text(this.model.get(“title”)); if (this.checkbox.val()) { $(this.el).addClass(“checked”); } else { $(this.el).removeClass(“checked”); }}});
View
Model
X
Rendering a View
When creating a new view, you must implement and call its render function to build its inner elements
You can implement the render function in 3 ways1. Don’t implement it – if you are using an existing
element
2. Use jQuery or another DOM library to build the inner elements using code – results in ugly and unreadable code
3. Use a template to render the view – preferred method
{{ Mustache }} Templating
Mustache is a common logic-less templating library
Supports a wide range of languages
Simple syntax, yet powerful
Supports loops
You can use underscore.js templates, but they are not as strong
Rendering using Mustache
Let’s use jQuery’s .html() function to fill our element with the rendered template
Use Mustache.render with the view template text , along with the models’ data (we use toJSON to serialize the model data so the template engine can use it).
Backbone.View.extend({ render: function() { $(this.el).html( Mustache.render(todoItemTemplate, this.model.toJSON())); });
View
Template
Model
Mustache
Updating a View
When updating a view, you may use two methods:
1. If you are using a template, you may use the render function with the updated attributes again
2. Acquire handles to the DOM elements you created in the render function and update each of them according to the change.
The first method is a lot easier to implement, but when you need performance, you should later on move to option #2.
Optimistic Mode
Optimistic mode (Default)Creates/updates views before confirmation from server
Gives better user experience
Wait mode Creates/updates views after confirmation from server
Safer method
If you have business logic related to how your entities are created which implicates on the views, you cannot use optimistic mode
RequireJS
RequireJS
Modular Javascript library
Important when writing big projects
Loads modules asynchronously – allows the page to load efficiently
Allows minification of the whole project into one file
How to use RequireJS
Boilerplate code examplehttps://github.com/ronreiter/webapp-boilerplate
RequireJS loads “AMD” modules (Asynchronous Module Definition” as opposed to the company )
Normal modules add a global variable (jQuery adds $ for example), or add method over a global variable (like jQuery plugins).
This means that you CANNOT use normal libraries, without wrapping them first.
I‘ve wrapped them for you, so just download my boilerplate and use it.
Code with RequireJS
Code without Require.JS Code with Require.JS<script src=“foo1.js”></script><script src=“foo2.js”></script><script src=“foo3.js”></script><script src=“foo4.js”></script><script> foo1.do(); foo2.do(); foo3.do(); foo4.do();</script>
<script src=“require.js”></script><script>require([“foo1”, “foo2”, “foo3”, “foo4”],function(foo1, foo2, foo3, foo4) { foo1.do(); foo2.do(); foo3.do(); foo4.do();});</script>
foo4.js:// hmmm. Can I use foo1, foo2, and foo3?// let’s put foo4 as a global variable.window.foo4 = …
foo4.js:define([“foo1”, “foo2”, “foo3”], function(foo1, foo2, foo3) { var foo4 = … return foo4;});
RequireJS + Templating
Another awesome advantage of RequireJS is that it knows how to load text files along with the modules, so you can simply write your client side template files separately, and load them when you need them
define([“backbone”, “underscore”, “jquery”, “text!listview.html”], function(Backbone, _, $, listViewTemplate) {
… Mustache.render(listViewTemplate, this.model.toJSON()) …
Optimization
Once you finish writing your project, simply run a utility called r.js (part of RequireJS) on your main script
r.js is a node executable script
It will turn all of your modules into one single, minified file
Creating an application manifest is required
JSJS
JSJS
minJS
node r.js
Thank You!
Questions?