PageRenderTime 55ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/docs/todos.html

https://github.com/huangbaihua001/backbone
HTML | 765 lines | 516 code | 249 blank | 0 comment | 0 complexity | 638bd84ab05c45b2e66bf327bf8d3fb5 MD5 | raw file
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>todos.js</title>
  5. <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  6. <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
  7. <link rel="stylesheet" media="all" href="docco.css" />
  8. </head>
  9. <body>
  10. <div id="container">
  11. <div id="background"></div>
  12. <ul id="jump_to">
  13. <li>
  14. <a class="large" href="javascript:void(0);">Jump To &hellip;</a>
  15. <a class="small" href="javascript:void(0);">+</a>
  16. <div id="jump_wrapper">
  17. <div id="jump_page">
  18. <a class="source" href="backbone.localstorage.html">
  19. backbone.localstorage.js
  20. </a>
  21. <a class="source" href="todos.html">
  22. todos.js
  23. </a>
  24. </div>
  25. </li>
  26. </ul>
  27. <ul class="sections">
  28. <li id="title">
  29. <div class="annotation">
  30. <h1>todos.js</h1>
  31. </div>
  32. </li>
  33. <li id="section-1">
  34. <div class="annotation">
  35. <div class="pilwrap ">
  36. <a class="pilcrow" href="#section-1">&#182;</a>
  37. </div>
  38. <p>An example Backbone application contributed by
  39. <a href="http://jgn.me/">J茅r么me Gravel-Niquet</a>. This demo uses a simple
  40. <a href="backbone-localstorage.html">LocalStorage adapter</a>
  41. to persist Backbone models within your browser.
  42. </p>
  43. <p>Load the application once the DOM is ready, using <code>jQuery.ready</code>:
  44. </p>
  45. </div>
  46. <div class="content"><div class='highlight'><pre>$(<span class="keyword">function</span>(){</pre></div></div>
  47. </li>
  48. <li id="section-2">
  49. <div class="annotation">
  50. <div class="pilwrap for-h2">
  51. <a class="pilcrow" href="#section-2">&#182;</a>
  52. </div>
  53. <h2>Todo Model</h2>
  54. </div>
  55. </li>
  56. <li id="section-3">
  57. <div class="annotation">
  58. <div class="pilwrap ">
  59. <a class="pilcrow" href="#section-3">&#182;</a>
  60. </div>
  61. <p>Our basic <strong>Todo</strong> model has <code>title</code>, <code>order</code>, and <code>done</code> attributes.
  62. </p>
  63. </div>
  64. <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> Todo = Backbone.Model.extend({</pre></div></div>
  65. </li>
  66. <li id="section-4">
  67. <div class="annotation">
  68. <div class="pilwrap ">
  69. <a class="pilcrow" href="#section-4">&#182;</a>
  70. </div>
  71. <p>Default attributes for the todo item.
  72. </p>
  73. </div>
  74. <div class="content"><div class='highlight'><pre> defaults: <span class="keyword">function</span>() {
  75. <span class="keyword">return</span> {
  76. title: <span class="string">"empty todo..."</span>,
  77. order: Todos.nextOrder(),
  78. done: <span class="literal">false</span>
  79. };
  80. },</pre></div></div>
  81. </li>
  82. <li id="section-5">
  83. <div class="annotation">
  84. <div class="pilwrap ">
  85. <a class="pilcrow" href="#section-5">&#182;</a>
  86. </div>
  87. <p>Toggle the <code>done</code> state of this todo item.
  88. </p>
  89. </div>
  90. <div class="content"><div class='highlight'><pre> toggle: <span class="keyword">function</span>() {
  91. <span class="keyword">this</span>.save({done: !<span class="keyword">this</span>.get(<span class="string">"done"</span>)});
  92. }
  93. });</pre></div></div>
  94. </li>
  95. <li id="section-6">
  96. <div class="annotation">
  97. <div class="pilwrap for-h2">
  98. <a class="pilcrow" href="#section-6">&#182;</a>
  99. </div>
  100. <h2>Todo Collection</h2>
  101. </div>
  102. </li>
  103. <li id="section-7">
  104. <div class="annotation">
  105. <div class="pilwrap ">
  106. <a class="pilcrow" href="#section-7">&#182;</a>
  107. </div>
  108. <p>The collection of todos is backed by <em>localStorage</em> instead of a remote
  109. server.
  110. </p>
  111. </div>
  112. <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> TodoList = Backbone.Collection.extend({</pre></div></div>
  113. </li>
  114. <li id="section-8">
  115. <div class="annotation">
  116. <div class="pilwrap ">
  117. <a class="pilcrow" href="#section-8">&#182;</a>
  118. </div>
  119. <p>Reference to this collection&#39;s model.
  120. </p>
  121. </div>
  122. <div class="content"><div class='highlight'><pre> model: Todo,</pre></div></div>
  123. </li>
  124. <li id="section-9">
  125. <div class="annotation">
  126. <div class="pilwrap ">
  127. <a class="pilcrow" href="#section-9">&#182;</a>
  128. </div>
  129. <p>Save all of the todo items under the <code>&quot;todos-backbone&quot;</code> namespace.
  130. </p>
  131. </div>
  132. <div class="content"><div class='highlight'><pre> localStorage: <span class="keyword">new</span> Backbone.LocalStorage(<span class="string">"todos-backbone"</span>),</pre></div></div>
  133. </li>
  134. <li id="section-10">
  135. <div class="annotation">
  136. <div class="pilwrap ">
  137. <a class="pilcrow" href="#section-10">&#182;</a>
  138. </div>
  139. <p>Filter down the list of all todo items that are finished.
  140. </p>
  141. </div>
  142. <div class="content"><div class='highlight'><pre> done: <span class="keyword">function</span>() {
  143. <span class="keyword">return</span> <span class="keyword">this</span>.where({done: <span class="literal">true</span>});
  144. },</pre></div></div>
  145. </li>
  146. <li id="section-11">
  147. <div class="annotation">
  148. <div class="pilwrap ">
  149. <a class="pilcrow" href="#section-11">&#182;</a>
  150. </div>
  151. <p>Filter down the list to only todo items that are still not finished.
  152. </p>
  153. </div>
  154. <div class="content"><div class='highlight'><pre> remaining: <span class="keyword">function</span>() {
  155. <span class="keyword">return</span> <span class="keyword">this</span>.without.apply(<span class="keyword">this</span>, <span class="keyword">this</span>.done());
  156. },</pre></div></div>
  157. </li>
  158. <li id="section-12">
  159. <div class="annotation">
  160. <div class="pilwrap ">
  161. <a class="pilcrow" href="#section-12">&#182;</a>
  162. </div>
  163. <p>We keep the Todos in sequential order, despite being saved by unordered
  164. GUID in the database. This generates the next order number for new items.
  165. </p>
  166. </div>
  167. <div class="content"><div class='highlight'><pre> nextOrder: <span class="keyword">function</span>() {
  168. <span class="keyword">if</span> (!<span class="keyword">this</span>.length) <span class="keyword">return</span> <span class="number">1</span>;
  169. <span class="keyword">return</span> <span class="keyword">this</span>.last().get(<span class="string">'order'</span>) + <span class="number">1</span>;
  170. },</pre></div></div>
  171. </li>
  172. <li id="section-13">
  173. <div class="annotation">
  174. <div class="pilwrap ">
  175. <a class="pilcrow" href="#section-13">&#182;</a>
  176. </div>
  177. <p>Todos are sorted by their original insertion order.
  178. </p>
  179. </div>
  180. <div class="content"><div class='highlight'><pre> comparator: <span class="string">'order'</span>
  181. });</pre></div></div>
  182. </li>
  183. <li id="section-14">
  184. <div class="annotation">
  185. <div class="pilwrap ">
  186. <a class="pilcrow" href="#section-14">&#182;</a>
  187. </div>
  188. <p>Create our global collection of <strong>Todos</strong>.
  189. </p>
  190. </div>
  191. <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> Todos = <span class="keyword">new</span> TodoList;</pre></div></div>
  192. </li>
  193. <li id="section-15">
  194. <div class="annotation">
  195. <div class="pilwrap for-h2">
  196. <a class="pilcrow" href="#section-15">&#182;</a>
  197. </div>
  198. <h2>Todo Item View</h2>
  199. </div>
  200. </li>
  201. <li id="section-16">
  202. <div class="annotation">
  203. <div class="pilwrap ">
  204. <a class="pilcrow" href="#section-16">&#182;</a>
  205. </div>
  206. <p>The DOM element for a todo item...
  207. </p>
  208. </div>
  209. <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> TodoView = Backbone.View.extend({</pre></div></div>
  210. </li>
  211. <li id="section-17">
  212. <div class="annotation">
  213. <div class="pilwrap ">
  214. <a class="pilcrow" href="#section-17">&#182;</a>
  215. </div>
  216. <p>... is a list tag.
  217. </p>
  218. </div>
  219. <div class="content"><div class='highlight'><pre> tagName: <span class="string">"li"</span>,</pre></div></div>
  220. </li>
  221. <li id="section-18">
  222. <div class="annotation">
  223. <div class="pilwrap ">
  224. <a class="pilcrow" href="#section-18">&#182;</a>
  225. </div>
  226. <p>Cache the template function for a single item.
  227. </p>
  228. </div>
  229. <div class="content"><div class='highlight'><pre> template: _.template($(<span class="string">'#item-template'</span>).html()),</pre></div></div>
  230. </li>
  231. <li id="section-19">
  232. <div class="annotation">
  233. <div class="pilwrap ">
  234. <a class="pilcrow" href="#section-19">&#182;</a>
  235. </div>
  236. <p>The DOM events specific to an item.
  237. </p>
  238. </div>
  239. <div class="content"><div class='highlight'><pre> events: {
  240. <span class="string">"click .toggle"</span> : <span class="string">"toggleDone"</span>,
  241. <span class="string">"dblclick .view"</span> : <span class="string">"edit"</span>,
  242. <span class="string">"click a.destroy"</span> : <span class="string">"clear"</span>,
  243. <span class="string">"keypress .edit"</span> : <span class="string">"updateOnEnter"</span>,
  244. <span class="string">"blur .edit"</span> : <span class="string">"close"</span>
  245. },</pre></div></div>
  246. </li>
  247. <li id="section-20">
  248. <div class="annotation">
  249. <div class="pilwrap ">
  250. <a class="pilcrow" href="#section-20">&#182;</a>
  251. </div>
  252. <p>The TodoView listens for changes to its model, re-rendering. Since there&#39;s
  253. a one-to-one correspondence between a <strong>Todo</strong> and a <strong>TodoView</strong> in this
  254. app, we set a direct reference on the model for convenience.
  255. </p>
  256. </div>
  257. <div class="content"><div class='highlight'><pre> initialize: <span class="keyword">function</span>() {
  258. <span class="keyword">this</span>.listenTo(<span class="keyword">this</span>.model, <span class="string">'change'</span>, <span class="keyword">this</span>.render);
  259. <span class="keyword">this</span>.listenTo(<span class="keyword">this</span>.model, <span class="string">'destroy'</span>, <span class="keyword">this</span>.remove);
  260. },</pre></div></div>
  261. </li>
  262. <li id="section-21">
  263. <div class="annotation">
  264. <div class="pilwrap ">
  265. <a class="pilcrow" href="#section-21">&#182;</a>
  266. </div>
  267. <p>Re-render the titles of the todo item.
  268. </p>
  269. </div>
  270. <div class="content"><div class='highlight'><pre> render: <span class="keyword">function</span>() {
  271. <span class="keyword">this</span>.$el.html(<span class="keyword">this</span>.template(<span class="keyword">this</span>.model.toJSON()));
  272. <span class="keyword">this</span>.$el.toggleClass(<span class="string">'done'</span>, <span class="keyword">this</span>.model.get(<span class="string">'done'</span>));
  273. <span class="keyword">this</span>.input = <span class="keyword">this</span>.$(<span class="string">'.edit'</span>);
  274. <span class="keyword">return</span> <span class="keyword">this</span>;
  275. },</pre></div></div>
  276. </li>
  277. <li id="section-22">
  278. <div class="annotation">
  279. <div class="pilwrap ">
  280. <a class="pilcrow" href="#section-22">&#182;</a>
  281. </div>
  282. <p>Toggle the <code>&quot;done&quot;</code> state of the model.
  283. </p>
  284. </div>
  285. <div class="content"><div class='highlight'><pre> toggleDone: <span class="keyword">function</span>() {
  286. <span class="keyword">this</span>.model.toggle();
  287. },</pre></div></div>
  288. </li>
  289. <li id="section-23">
  290. <div class="annotation">
  291. <div class="pilwrap ">
  292. <a class="pilcrow" href="#section-23">&#182;</a>
  293. </div>
  294. <p>Switch this view into <code>&quot;editing&quot;</code> mode, displaying the input field.
  295. </p>
  296. </div>
  297. <div class="content"><div class='highlight'><pre> edit: <span class="keyword">function</span>() {
  298. <span class="keyword">this</span>.$el.addClass(<span class="string">"editing"</span>);
  299. <span class="keyword">this</span>.input.focus();
  300. },</pre></div></div>
  301. </li>
  302. <li id="section-24">
  303. <div class="annotation">
  304. <div class="pilwrap ">
  305. <a class="pilcrow" href="#section-24">&#182;</a>
  306. </div>
  307. <p>Close the <code>&quot;editing&quot;</code> mode, saving changes to the todo.
  308. </p>
  309. </div>
  310. <div class="content"><div class='highlight'><pre> close: <span class="keyword">function</span>() {
  311. <span class="keyword">var</span> value = <span class="keyword">this</span>.input.val();
  312. <span class="keyword">if</span> (!value) {
  313. <span class="keyword">this</span>.clear();
  314. } <span class="keyword">else</span> {
  315. <span class="keyword">this</span>.model.save({title: value});
  316. <span class="keyword">this</span>.$el.removeClass(<span class="string">"editing"</span>);
  317. }
  318. },</pre></div></div>
  319. </li>
  320. <li id="section-25">
  321. <div class="annotation">
  322. <div class="pilwrap ">
  323. <a class="pilcrow" href="#section-25">&#182;</a>
  324. </div>
  325. <p>If you hit <code>enter</code>, we&#39;re through editing the item.
  326. </p>
  327. </div>
  328. <div class="content"><div class='highlight'><pre> updateOnEnter: <span class="keyword">function</span>(e) {
  329. <span class="keyword">if</span> (e.keyCode == <span class="number">13</span>) <span class="keyword">this</span>.close();
  330. },</pre></div></div>
  331. </li>
  332. <li id="section-26">
  333. <div class="annotation">
  334. <div class="pilwrap ">
  335. <a class="pilcrow" href="#section-26">&#182;</a>
  336. </div>
  337. <p>Remove the item, destroy the model.
  338. </p>
  339. </div>
  340. <div class="content"><div class='highlight'><pre> clear: <span class="keyword">function</span>() {
  341. <span class="keyword">this</span>.model.destroy();
  342. }
  343. });</pre></div></div>
  344. </li>
  345. <li id="section-27">
  346. <div class="annotation">
  347. <div class="pilwrap for-h2">
  348. <a class="pilcrow" href="#section-27">&#182;</a>
  349. </div>
  350. <h2>The Application</h2>
  351. </div>
  352. </li>
  353. <li id="section-28">
  354. <div class="annotation">
  355. <div class="pilwrap ">
  356. <a class="pilcrow" href="#section-28">&#182;</a>
  357. </div>
  358. <p>Our overall <strong>AppView</strong> is the top-level piece of UI.
  359. </p>
  360. </div>
  361. <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> AppView = Backbone.View.extend({</pre></div></div>
  362. </li>
  363. <li id="section-29">
  364. <div class="annotation">
  365. <div class="pilwrap ">
  366. <a class="pilcrow" href="#section-29">&#182;</a>
  367. </div>
  368. <p>Instead of generating a new element, bind to the existing skeleton of
  369. the App already present in the HTML.
  370. </p>
  371. </div>
  372. <div class="content"><div class='highlight'><pre> el: $(<span class="string">"#todoapp"</span>),</pre></div></div>
  373. </li>
  374. <li id="section-30">
  375. <div class="annotation">
  376. <div class="pilwrap ">
  377. <a class="pilcrow" href="#section-30">&#182;</a>
  378. </div>
  379. <p>Our template for the line of statistics at the bottom of the app.
  380. </p>
  381. </div>
  382. <div class="content"><div class='highlight'><pre> statsTemplate: _.template($(<span class="string">'#stats-template'</span>).html()),</pre></div></div>
  383. </li>
  384. <li id="section-31">
  385. <div class="annotation">
  386. <div class="pilwrap ">
  387. <a class="pilcrow" href="#section-31">&#182;</a>
  388. </div>
  389. <p>Delegated events for creating new items, and clearing completed ones.
  390. </p>
  391. </div>
  392. <div class="content"><div class='highlight'><pre> events: {
  393. <span class="string">"keypress #new-todo"</span>: <span class="string">"createOnEnter"</span>,
  394. <span class="string">"click #clear-completed"</span>: <span class="string">"clearCompleted"</span>,
  395. <span class="string">"click #toggle-all"</span>: <span class="string">"toggleAllComplete"</span>
  396. },</pre></div></div>
  397. </li>
  398. <li id="section-32">
  399. <div class="annotation">
  400. <div class="pilwrap ">
  401. <a class="pilcrow" href="#section-32">&#182;</a>
  402. </div>
  403. <p>At initialization we bind to the relevant events on the <code>Todos</code>
  404. collection, when items are added or changed. Kick things off by
  405. loading any preexisting todos that might be saved in <em>localStorage</em>.
  406. </p>
  407. </div>
  408. <div class="content"><div class='highlight'><pre> initialize: <span class="keyword">function</span>() {
  409. <span class="keyword">this</span>.input = <span class="keyword">this</span>.$(<span class="string">"#new-todo"</span>);
  410. <span class="keyword">this</span>.allCheckbox = <span class="keyword">this</span>.$(<span class="string">"#toggle-all"</span>)[<span class="number">0</span>];
  411. <span class="keyword">this</span>.listenTo(Todos, <span class="string">'add'</span>, <span class="keyword">this</span>.addOne);
  412. <span class="keyword">this</span>.listenTo(Todos, <span class="string">'reset'</span>, <span class="keyword">this</span>.addAll);
  413. <span class="keyword">this</span>.listenTo(Todos, <span class="string">'all'</span>, <span class="keyword">this</span>.render);
  414. <span class="keyword">this</span>.footer = <span class="keyword">this</span>.$(<span class="string">'footer'</span>);
  415. <span class="keyword">this</span>.main = $(<span class="string">'#main'</span>);
  416. Todos.fetch();
  417. },</pre></div></div>
  418. </li>
  419. <li id="section-33">
  420. <div class="annotation">
  421. <div class="pilwrap ">
  422. <a class="pilcrow" href="#section-33">&#182;</a>
  423. </div>
  424. <p>Re-rendering the App just means refreshing the statistics -- the rest
  425. of the app doesn&#39;t change.
  426. </p>
  427. </div>
  428. <div class="content"><div class='highlight'><pre> render: <span class="keyword">function</span>() {
  429. <span class="keyword">var</span> done = Todos.done().length;
  430. <span class="keyword">var</span> remaining = Todos.remaining().length;
  431. <span class="keyword">if</span> (Todos.length) {
  432. <span class="keyword">this</span>.main.show();
  433. <span class="keyword">this</span>.footer.show();
  434. <span class="keyword">this</span>.footer.html(<span class="keyword">this</span>.statsTemplate({done: done, remaining: remaining}));
  435. } <span class="keyword">else</span> {
  436. <span class="keyword">this</span>.main.hide();
  437. <span class="keyword">this</span>.footer.hide();
  438. }
  439. <span class="keyword">this</span>.allCheckbox.checked = !remaining;
  440. },</pre></div></div>
  441. </li>
  442. <li id="section-34">
  443. <div class="annotation">
  444. <div class="pilwrap ">
  445. <a class="pilcrow" href="#section-34">&#182;</a>
  446. </div>
  447. <p>Add a single todo item to the list by creating a view for it, and
  448. appending its element to the <code>&lt;ul&gt;</code>.
  449. </p>
  450. </div>
  451. <div class="content"><div class='highlight'><pre> addOne: <span class="keyword">function</span>(todo) {
  452. <span class="keyword">var</span> view = <span class="keyword">new</span> TodoView({model: todo});
  453. <span class="keyword">this</span>.$(<span class="string">"#todo-list"</span>).append(view.render().el);
  454. },</pre></div></div>
  455. </li>
  456. <li id="section-35">
  457. <div class="annotation">
  458. <div class="pilwrap ">
  459. <a class="pilcrow" href="#section-35">&#182;</a>
  460. </div>
  461. <p>Add all items in the <strong>Todos</strong> collection at once.
  462. </p>
  463. </div>
  464. <div class="content"><div class='highlight'><pre> addAll: <span class="keyword">function</span>() {
  465. Todos.each(<span class="keyword">this</span>.addOne, <span class="keyword">this</span>);
  466. },</pre></div></div>
  467. </li>
  468. <li id="section-36">
  469. <div class="annotation">
  470. <div class="pilwrap ">
  471. <a class="pilcrow" href="#section-36">&#182;</a>
  472. </div>
  473. <p>If you hit return in the main input field, create new <strong>Todo</strong> model,
  474. persisting it to <em>localStorage</em>.
  475. </p>
  476. </div>
  477. <div class="content"><div class='highlight'><pre> createOnEnter: <span class="keyword">function</span>(e) {
  478. <span class="keyword">if</span> (e.keyCode != <span class="number">13</span>) <span class="keyword">return</span>;
  479. <span class="keyword">if</span> (!<span class="keyword">this</span>.input.val()) <span class="keyword">return</span>;
  480. Todos.create({title: <span class="keyword">this</span>.input.val()});
  481. <span class="keyword">this</span>.input.val(<span class="string">''</span>);
  482. },</pre></div></div>
  483. </li>
  484. <li id="section-37">
  485. <div class="annotation">
  486. <div class="pilwrap ">
  487. <a class="pilcrow" href="#section-37">&#182;</a>
  488. </div>
  489. <p>Clear all done todo items, destroying their models.
  490. </p>
  491. </div>
  492. <div class="content"><div class='highlight'><pre> clearCompleted: <span class="keyword">function</span>() {
  493. _.invoke(Todos.done(), <span class="string">'destroy'</span>);
  494. <span class="keyword">return</span> <span class="literal">false</span>;
  495. },
  496. toggleAllComplete: <span class="function"><span class="keyword">function</span> <span class="params">()</span> {</span>
  497. <span class="keyword">var</span> done = <span class="keyword">this</span>.allCheckbox.checked;
  498. Todos.each(<span class="function"><span class="keyword">function</span> <span class="params">(todo)</span> {</span> todo.save({<span class="string">'done'</span>: done}); });
  499. }
  500. });</pre></div></div>
  501. </li>
  502. <li id="section-38">
  503. <div class="annotation">
  504. <div class="pilwrap ">
  505. <a class="pilcrow" href="#section-38">&#182;</a>
  506. </div>
  507. <p>Finally, we kick things off by creating the <strong>App</strong>.
  508. </p>
  509. </div>
  510. <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> App = <span class="keyword">new</span> AppView;
  511. });</pre></div></div>
  512. </li>
  513. </ul>
  514. </div>
  515. </body>
  516. </html>