todos.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /**
  2. * @see Model.url
  3. */
  4. $(function () {
  5. const onChange = (change, x) => {
  6. console.log('On change', change.changed);
  7. };
  8. // Create a model class.
  9. const TodoItem = Backbone.Model.extend({
  10. defaults: {
  11. description: "Empty todo",
  12. status: "incomplete",
  13. },
  14. // RESTful web service, RoR flavor.
  15. urlRoot: '/server/todos',
  16. toggleStatus(view) {
  17. if (this.get('status') === 'incomplete') {
  18. this.set('status', 'complete');
  19. }
  20. else {
  21. this.set('status', 'incomplete');
  22. }
  23. this.save();
  24. }
  25. }
  26. );
  27. // Create a model instance to load it by ID. Let it be global for console use.
  28. todoItem = new TodoItem({ id: 1 });
  29. // Listeners
  30. todoItem.on('change', onChange);
  31. // Skip listener during a change. Notice the value format.
  32. todoItem.set({ 'description': 'some other description' }, {silent: true});
  33. // Remove listener.
  34. //todoItem.off('change', onChange);
  35. /* Built-in events
  36. change - when any attribute is modified
  37. change:<attr> - when <attr> is modified
  38. destroy - when the model is destroyed
  39. sync - when the model successfully synced with the server
  40. error - when model save or validation fails
  41. all - on any event
  42. */
  43. // Check default attribute pre-fetch.
  44. const defaultDescription = todoItem.get('description');
  45. // Access the server at /server/todos/1 (urlRoot + '/' + item.id).
  46. const x = todoItem.fetch({ async: false });
  47. // Manipulate attributes.
  48. const description = todoItem.get('description');
  49. todoItem.set('status', 'complete');
  50. // Save on server.
  51. todoItem.save();
  52. // Destroy on server.
  53. // todoItem.destroy();
  54. // Create a view class.
  55. const TodoView = Backbone.View.extend({
  56. tagName: 'article',
  57. id: 'todo-view',
  58. className: 'todo',
  59. // Underscore templating.
  60. //language=HTML
  61. template: _.template(`
  62. <h3 class="<%= status %>">
  63. <input type="checkbox"
  64. <% if (status === "complete") print("checked") %> />
  65. <%= description %>
  66. </h3>
  67. `),
  68. events: {
  69. // Generates this.$el.('h3", 'click', alertStatus).
  70. 'click h3': 'alertStatus',
  71. 'change input': 'toggleStatus',
  72. },
  73. // Backbone.
  74. initialize() {
  75. // Backbone on() takes (event, callback, context)
  76. this.model.on('change', this.render, this);
  77. // Or without an explicit context, use a bound function.
  78. // this.model.on('change', this.render.bind(this));
  79. this.model.on('destroy', this.remove, this);
  80. },
  81. // Handle on destroy.
  82. remove() {
  83. this.$el.remove();
  84. },
  85. // Handle "click h3"
  86. alertStatus() {
  87. // Noisy.
  88. // alert('Hey, you clicked the H3');
  89. },
  90. // Handle "change input".
  91. toggleStatus() {
  92. this.model.toggleStatus();
  93. },
  94. render: function () {
  95. const attributes = this.model.toJSON();
  96. const html = this.template(attributes);
  97. // Since this.el is a DOMElement, we can just wrap it with jQuery instead
  98. // of using a jQuery selector like $('#todo-view') or $('.todo').
  99. // This is better because it is id- and class- independent.
  100. // $(this.el).html(html);
  101. // Backbone even gives a shortcut: the $el property.
  102. this.$el.html(html);
  103. },
  104. });
  105. // Create a view instance.
  106. const todoView = new TodoView({ model: todoItem });
  107. // Build view.
  108. todoView.render();
  109. // console.log(todoView.el);
  110. // Apply to the DOM.
  111. $('#app').html(todoView.el);
  112. });