1 /** 2 * Comment controller and view 3 * DOM event and comment model event handlers should live here. 4 * This view handles comment edit, delete and the sample text reverse actions, also 5 * listens to model change and destroy events to update the view in DOM. 6 * 7 * @class CommentView 8 * @extends Backbone.View 9 * @author Bodnar Istvan <istvan@gawker.com> 10 */ 11 /*global Mustache, FormView */ 12 var CommentView = Backbone.View.extend( 13 /** @lends CommentView.prototype */ 14 { 15 /** 16 * Html tag name of the container element that'll be created when initializing new instance. 17 * This container is then accessible via the this.el (native DOM node) or this.$el (jQuery node) 18 * variables. 19 * @type String 20 */ 21 tagName: 'li', 22 23 /** 24 * CSS class name of the container element 25 * @type String 26 */ 27 className: 'comment', 28 29 /** 30 * The map of delegated event handlers 31 * @type Object 32 */ 33 events: { 34 'click .edit': 'edit', 35 'click .delete': 'delete', 36 'click .reverse': 'reverse' 37 }, 38 39 /** 40 * View init method, subscribing to model events 41 */ 42 initialize: function () { 43 this.model.on('change', this.render, this); 44 this.model.on('destroy', this.remove, this); 45 }, 46 47 /** 48 * Render the new comment DOM element from a template using Mustache 49 * @returns {CommentView} Returns the view instance itself, to allow chaining view commands. 50 */ 51 render: function () { 52 // template is rendered in the main html, inside a <script /> tag with the specified id 53 var template = $('#comment-template').text(); 54 55 // variables passed to the template for rendering 56 var template_vars = { 57 author: this.model.get('author'), 58 text: this.model.get('text') 59 }; 60 61 // set the inner html of the container element to the Mustache rendered output 62 this.$el.html(Mustache.to_html(template, template_vars)); 63 return this; 64 }, 65 66 /** 67 * Edit button click handler 68 * @returns {Boolean} Returns false to stop propagation 69 */ 70 edit: function () { 71 // create new FormView instance to edit the comment 72 var formview = new FormView({model: this.model}); 73 74 // insert FormView instance after the comment container 75 this.$el.after(formview.render().$el); 76 77 // listen to save success event to handle successful form submit event 78 formview.on('success', this.handleEditSuccess, this); 79 return false; 80 }, 81 82 /** 83 * Delete button click handler 84 * @returns {Boolean} Returns false to stop propagation 85 */ 86 delete: function () { 87 // delete model from memory 88 this.model.id = undefined; 89 this.model.destroy(); 90 91 // note: since the view is subscribed to the models 'destroy' event, view will be also removed 92 // automatically, no need to delete container form DOM 93 return false; 94 }, 95 96 /** 97 * "Reverse" button click handler 98 * @returns {Boolean} Returns false to stop propagation 99 */ 100 reverse: function () { 101 // run the models sample text reverse method 102 this.model.reverseText(); 103 return false; 104 }, 105 106 /** 107 * Handles form save success event 108 * @params {CommentModel} model Model returned by successful comment "save" action 109 */ 110 handleEditSuccess: function (model) { 111 // create a new notification that is removed after 5 seconds 112 var $notification = $('<div />') 113 .text('Comment by ' + model.get('author') + ' is saved.') 114 .addClass('notification'); 115 116 // append notification to edited comments container element 117 this.$el.append($notification); 118 119 // remove notification after 5 seconds 120 setTimeout(function () { 121 $notification.remove(); 122 }, 5000); 123 }, 124 125 /** 126 * Override the default view remove method with custom actions 127 */ 128 remove: function () { 129 // remove container element from DOM 130 this.$el.remove(); 131 } 132 } 133 );