PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/index.html

https://bitbucket.org/nracovita/tek-ria-backone
HTML | 483 lines | 389 code | 88 blank | 6 comment | 0 complexity | e9d707b7ea94a9709ccf0354362c3666 MD5 | raw file
  1. <!doctype html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8">
  5. <title>Backbone &mdash; overview</title>
  6. <meta name="description" content="A framework for easily creating beautiful presentations using HTML">
  7. <meta name="author" content="Hakim El Hattab">
  8. <meta name="apple-mobile-web-app-capable" content="yes" />
  9. <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
  10. <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
  11. <link rel="stylesheet" href="css/reveal.css">
  12. <link rel="stylesheet" href="css/theme/default.css" id="theme">
  13. <!-- For syntax highlighting -->
  14. <link rel="stylesheet" href="lib/css/zenburn.css">
  15. <!-- If the query includes 'print-pdf', use the PDF print sheet -->
  16. <script>
  17. document.write( '<link rel="stylesheet" href="css/print/' + ( window.location.search.match( /print-pdf/gi ) ? 'pdf' : 'paper' ) + '.css" type="text/css" media="print">' );
  18. </script>
  19. <!--[if lt IE 9]>
  20. <script src="lib/js/html5shiv.js"></script>
  21. <![endif]-->
  22. </head>
  23. <body>
  24. <div class="reveal">
  25. <!-- Any section element inside of this container is displayed as a slide -->
  26. <div class="slides">
  27. <section>
  28. <h1>Backbone</h1>
  29. <h3>Building SPA. Overview.</h3>
  30. <p>
  31. <small>April 2013. Created for RIA (d) Competency Center</small>
  32. </p>
  33. </section>
  34. <section>
  35. <h2>What is Backbone</h2>
  36. <p>
  37. Gives structure to web applications with key-value binding and custom events, collections, views and connects to existing API over a RESTful JSON interface.
  38. </p>
  39. <aside class="notes">
  40. Oh hey, these are some notes. They'll be hidden in your presentation, but you can see them if you open the speaker notes window (hit 's' on your keyboard).
  41. </aside>
  42. </section>
  43. <section>
  44. <h2>Rest API server</h2>
  45. <img src="/img/resource-url-graph-1.0.png" alt="">
  46. </section>
  47. <section>
  48. <section>
  49. <h2>Events</h2>
  50. <pre><code>var object = {};
  51. _.extend(object, Backbone.Events);
  52. object.on("alert", function(msg) {
  53. alert("Triggered " + msg);
  54. });
  55. object.trigger("alert", "an event");</code></pre>
  56. </section>
  57. <section>
  58. <h2>Events</h2>
  59. <pre><code>book.on({
  60. "change:title": titleView.update,
  61. "change:author": authorPane.update,
  62. "destroy": bookView.remove
  63. });</code></pre>
  64. </section>
  65. </section>
  66. <section>
  67. <section>
  68. <h2>Models</h2>
  69. <p>
  70. <ul>
  71. <li>Data container</li>
  72. <li>Validation of data</li>
  73. <li>Conversion</li>
  74. <li>Computed properties</li>
  75. <li>Access control</li>
  76. </ul>
  77. </p>
  78. </section>
  79. <section>
  80. <h2>Models</h2>
  81. <pre><code contenteditable>
  82. app.Todo = Backbone.Model.extend({
  83. // Default attributes for the todo
  84. // and ensure that each todo created has `title` and `completed` keys.
  85. defaults: {
  86. title: '',
  87. completed: false
  88. },
  89. // Toggle the `completed` state of this todo item.
  90. toggle: function () {
  91. this.save({
  92. completed: !this.get('completed')
  93. });
  94. }
  95. });
  96. </code></pre>
  97. </section>
  98. <section>
  99. <h2>Model methods</h2>
  100. <ul>
  101. <li>get/ set &mdash; <small><code>note.get("title")</code></small> </li>
  102. <li>fetch / save / validate / destroy</li>
  103. <li>url &mdash; <small><code>/documents/7/notes/101</code></small></li>
  104. <li>parse</li>
  105. <li>clone</li>
  106. </ul>
  107. </section>
  108. <section>
  109. <h2>Model validation</h2>
  110. <pre><code>
  111. var Chapter = Backbone.Model.extend({
  112. validate: function(attrs, options) {
  113. if (attrs.end < attrs.start) {
  114. return "can't end before it starts";
  115. }
  116. }
  117. });
  118. var one = new Chapter({
  119. title : "Chapter One: The Beginning"
  120. });
  121. one.on("invalid", function(model, error) {
  122. alert(model.get("title") + " " + error);
  123. });
  124. one.save({
  125. start: 15,
  126. end: 10
  127. });
  128. </code></pre>
  129. </section>
  130. </section>
  131. <section>
  132. <section>
  133. <h2>Collections</h2>
  134. <p>Ordered sets of models
  135. </p>
  136. <p>An event that is triggered on a model in a collection will also be triggered on the collection</p>
  137. </section>
  138. <section>
  139. <h2>Collections</h2>
  140. <pre><code>var TodoList = Backbone.Collection.extend({
  141. model: app.Todo,
  142. // Save all of the todo items under the `"todos"` namespace.
  143. localStorage: new Backbone.LocalStorage('todos-backbone'),
  144. // Filter down the list of all todo items that are finished.
  145. completed: function () {
  146. return this.filter(function (todo) {
  147. return todo.get('completed');
  148. });
  149. },
  150. // Filter down the list to only todo items that are still not finished.
  151. remaining: function () {
  152. return this.without.apply(this, this.completed());
  153. },
  154. // We keep the Todos in sequential order, despite being saved by unordered
  155. // GUID in the database. This generates the next order number for new items.
  156. nextOrder: function () {
  157. if (!this.length) {
  158. return 1;
  159. }
  160. return this.last().get('order') + 1;
  161. },
  162. // Todos are sorted by their original insertion order.
  163. comparator: function (todo) {
  164. return todo.get('order');
  165. }
  166. });</code></pre>
  167. </section>
  168. <section>
  169. <h2>Collection methods</h2>
  170. <ul>
  171. <li>Underscore Methods: forEach/ map/ reduce ...</li>
  172. <li>add/ shift / pop / push / pluck / find...</li>
  173. <li>comparator</li>
  174. <li>fetch</li>
  175. </ul>
  176. </section>
  177. </section>
  178. <section>
  179. <section>
  180. <h2>Backbone.sync</h2>
  181. <p>Function called to read or save a model to the server.</p>
  182. <p>By default uses jQuery.ajax. Can be configured to use Web Sockets, XML transport or Local Storage.</p>
  183. </section>
  184. <section>
  185. <h2>Backbone.sync</h2>
  186. <pre><code>Backbone.sync(method, model, [options])</code></pre>
  187. <ul>
  188. <li><b>create POST &nbsp; </b><tt>/collection</tt></li>
  189. <li><b>read GET &nbsp; </b><tt>/collection[/id]</tt></li>
  190. <li><b>update PUT &nbsp; </b><tt>/collection/id</tt></li>
  191. <li><b>delete DELETE &nbsp; </b><tt>/collection/id</tt></li>
  192. </ul>
  193. </section>
  194. </section>
  195. <section>
  196. <section>
  197. <h2>Views</h2>
  198. <pre><code>// The DOM element for a todo item...
  199. app.TodoView = Backbone.View.extend({
  200. //... is a list tag.
  201. tagName: 'li',
  202. // Cache the template function for a single item.
  203. template: _.template($('#item-template').html()),
  204. // The DOM events specific to an item.
  205. events: {
  206. 'click .toggle': 'toggleCompleted',
  207. 'dblclick label': 'edit'
  208. },
  209. // The TodoView listens for changes to its model, re-rendering.
  210. initialize: function () {
  211. this.listenTo(this.model, 'change', this.render);
  212. },
  213. // Re-render the titles of the todo item.
  214. render: function () {
  215. this.$el.html(this.template(this.model.toJSON()));
  216. return this;
  217. },
  218. completeTodo: function(){
  219. this.model.save({
  220. 'completed': true
  221. });
  222. },
  223. editList: function() {
  224. return this.listForm(new EditListView({ model: bTask.views.activeListMenuItem.model }));
  225. },,...</code></pre>
  226. </section>
  227. </section>
  228. <section>
  229. <h2>Routes</h2>
  230. <pre><code>var Workspace = Backbone.Router.extend({
  231. routes: {
  232. '*filter': 'setFilter'
  233. },
  234. setFilter: function (param) {
  235. // Set the current filter to be used
  236. app.TodoFilter = param || '';
  237. // Trigger a collection filter event, causing hiding/unhiding
  238. // of Todo view items
  239. app.Todos.trigger('filter');
  240. }
  241. });
  242. app.TodoRouter = new Workspace();
  243. Backbone.history.start();</code></pre>
  244. </section>
  245. <section>
  246. <section>
  247. <h2>Testing </h2>
  248. <pre><code>suite('Lists', function() {
  249. var spyCreate = sinon.spy(gapi.client.tasks.tasklists, 'insert');
  250. setup(function() {
  251. spyCreate.reset();
  252. });
  253. test('Creating a list', function() {
  254. var $el = bTask.views.app.$el
  255. , listName = 'Example list';
  256. // Show the add list form
  257. $el.find('#add-list-button').click();
  258. // Fill out a value for the new list's title
  259. $el.find('#list_title').val(listName);
  260. $el.find('#list_title').parents('form').first().submit();
  261. // Make sure the spy has seen a call for a list being created
  262. assert.equal(1, spyCreate.callCount);
  263. // Ensure the expected UI element has been added
  264. assert.equal(listName, $('.list-menu-item:last').text().trim());
  265. });
  266. });</code></pre>
  267. </section>
  268. </section>
  269. <section>
  270. <section>
  271. <h2>Backbone common pitfalls: memory leaks</h2>
  272. <pre><code>var SomeModelView = Backbone.View.extend({
  273. initialize: function() {
  274. this.model.on('change', this.render, this);
  275. },
  276. render: function() {
  277. // render a template
  278. }
  279. });</code></pre>
  280. <p>Use</p>
  281. <pre><code>initialize: function() {
  282. this.listenTo(this.model, 'change', this.render);
  283. }</code></pre>
  284. </section>
  285. <section>
  286. <h2>Backbone common pitfalls: multiple DOM reflows</h2>
  287. <pre><code>render: function() {
  288. var self = this;
  289. this.$el.empty();
  290. // render each subview, appending to our root element
  291. _.each(this._views, function(subview) {
  292. self.$el.append(subview.render().el);
  293. });
  294. }</code></pre>
  295. <p>Use</p>
  296. <pre><code>render: function() {
  297. this.$el.empty();
  298. var container = document.createDocumentFragment();
  299. // render each subview, appending to our root element
  300. _.each(this._views, function(subview) {
  301. container.appendChild(subview.render().el)
  302. });
  303. this.$el.append(container);
  304. }</code></pre>
  305. </section>
  306. <section>
  307. <h2>Backbone common pitfalls: unnecessary XHR requests on page load</h2>
  308. <pre><code>
  309. initialize: function () {
  310. app.Todos.fetch();
  311. }
  312. </code></pre>
  313. <p>Use</p>
  314. <pre><code>
  315. var appInitialData = 'server_generated_json';
  316. ...
  317. initialize: function () {
  318. app.Todos.set(appInitialData);
  319. }
  320. </code></pre>
  321. </section>
  322. <section>
  323. <h2>Backbone common pitfalls: Non-optimistic AJAX</h2>
  324. <pre><code>saveName: function(e) {
  325. e.preventDefault();
  326. // get the new name from the input field
  327. var changedName = this.$('.name-input').val();
  328. // save it on the model
  329. this.model.save({name: changedName}, {
  330. success: function(model, response, options) {
  331. // render changes to the model
  332. },
  333. error: function(model, xhr, options) {
  334. // render an error message
  335. }
  336. });
  337. }</code></pre>
  338. <p>Use</p>
  339. <pre><code>saveName: function(e) {
  340. e.preventDefault();
  341. // get the new name from the input field
  342. var changedName = this.$('.name-input').val();
  343. // render changes to the model
  344. ...
  345. // save it on the model
  346. this.model.save({name: changedName}, {
  347. success: function(model, response, options) {
  348. },
  349. error: function(model, xhr, options) {
  350. // Notify of an error
  351. }
  352. });
  353. }</code></pre>
  354. </section>
  355. </section>
  356. <section>
  357. <h2>Articles and books</h2>
  358. <ul>
  359. <li><a href="http://info.apigee.com/Portals/62317/docs/web%20api.pdf">Rest API best practices</a></li>
  360. <li><a href="http://ozkatz.github.com/avoiding-common-backbonejs-pitfalls.html?tagref=js#gsc.tab=0">Avoiding Common Backbone.js Pitfalls</a></li>
  361. <li><a href="http://dailyjs.com/2013/02/07/backbone-tutorial-11/">Backbone tutorial from DailyJS</a></li>
  362. </ul>
  363. </section>
  364. <section>
  365. <h1>THE END</h1>
  366. </section>
  367. </div>
  368. </div>
  369. <script src="lib/js/head.min.js"></script>
  370. <script src="js/reveal.js"></script>
  371. <script>
  372. // Full list of configuration options available here:
  373. // https://github.com/hakimel/reveal.js#configuration
  374. Reveal.initialize({
  375. controls: true,
  376. progress: true,
  377. history: true,
  378. center: true,
  379. theme: Reveal.getQueryHash().theme , // available themes are in /css/theme
  380. transition: Reveal.getQueryHash().transition || 'linear', // default/cube/page/concave/zoom/linear/fade/none
  381. // Optional libraries used to extend on reveal.js
  382. dependencies: [
  383. { src: 'lib/js/classList.js', condition: function() { return !document.body.classList; } },
  384. { src: 'plugin/markdown/showdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
  385. { src: 'plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
  386. { src: 'plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
  387. { src: 'plugin/zoom-js/zoom.js', async: true, condition: function() { return !!document.body.classList; } },
  388. { src: 'plugin/notes/notes.js', async: true, condition: function() { return !!document.body.classList; } }
  389. // { src: 'plugin/search/search.js', async: true, condition: function() { return !!document.body.classList; } }
  390. // { src: 'plugin/remotes/remotes.js', async: true, condition: function() { return !!document.body.classList; } }
  391. ]
  392. });
  393. </script>
  394. </body>
  395. </html>