PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/Automattic-trac-code-comments-plugin-b260714/code_comments/htdocs/code-comments.js

#
JavaScript | 215 lines | 197 code | 17 blank | 1 comment | 9 complexity | 1b359591d984c4d30137e77a227fa4f4 MD5 | raw file
  1. jQuery(function($) {
  2. var _ = window.underscore;
  3. $(document).ajaxError( function(e, xhr, options){
  4. var errorText = xhr.statusText;
  5. if (-1 == xhr.responseText.indexOf('<html')) {
  6. errorText += ': ' + xhr.responseText;
  7. } else {
  8. var traceback = $('#traceback pre', xhr.responseText).text();
  9. if (traceback) {
  10. errorText += '\n\nSee more in the console log.';
  11. console.log(traceback);
  12. }
  13. }
  14. alert(errorText);
  15. });
  16. window.Comment = Backbone.Model.extend({
  17. });
  18. window.CommentsList = Backbone.Collection.extend({
  19. model: Comment,
  20. url: CodeComments.comments_rest_url,
  21. comparator: function(comment) {
  22. return comment.get('time');
  23. }
  24. });
  25. window.CommentView = Backbone.View.extend({
  26. tagName: 'li',
  27. template: _.template(CodeComments.templates.comment),
  28. initialize: function() {
  29. this.model.bind('change', this.render, this);
  30. },
  31. render: function() {
  32. $(this.el).html(this.template(_.extend(this.model.toJSON(), {
  33. delete_url: CodeComments.delete_url,
  34. active: this.model.id == CodeComments.active_comment_id,
  35. can_delete: CodeComments.is_admin,
  36. })));
  37. return this;
  38. }
  39. });
  40. window.TopCommentsView = Backbone.View.extend({
  41. id: 'top-comments',
  42. template: _.template(CodeComments.templates.top_comments_block),
  43. events: {
  44. 'click button': 'showAddCommentDialog'
  45. },
  46. initialize: function() {
  47. TopComments.bind('add', this.addOne, this);
  48. TopComments.bind('reset', this.addAll, this);
  49. },
  50. render: function() {
  51. $(this.el).html(this.template());
  52. this.$('button').button();
  53. TopComments.fetch({data: {path: CodeComments.path, revision: CodeComments.revision, line: 0}});
  54. return this;
  55. },
  56. addOne: function(comment) {
  57. var view = new CommentView({model: comment});
  58. this.$("ul.comments").append(view.render().el);
  59. },
  60. addAll: function() {
  61. var view = this;
  62. TopComments.each(function(comment) {
  63. view.addOne.call(view, comment);
  64. });
  65. },
  66. showAddCommentDialog: function(e) {
  67. AddCommentDialog.open(TopComments);
  68. }
  69. });
  70. window.LineCommentsView = Backbone.View.extend({
  71. id: 'preview',
  72. initialize: function() {
  73. LineComments.bind('add', this.addOne, this);
  74. LineComments.bind('reset', this.addAll, this);
  75. this.viewPerLine = {};
  76. },
  77. render: function() {
  78. LineComments.fetch({data: {path: CodeComments.path, revision: CodeComments.revision, line__gt: 0}});
  79. //TODO: + links
  80. },
  81. addOne: function(comment) {
  82. var line = comment.get('line');
  83. if (!this.viewPerLine[line]) {
  84. this.viewPerLine[line] = new CommentsForALineView();
  85. var $tr = $("th#L"+line).parent();
  86. $tr.after(this.viewPerLine[line].render().el).addClass('with-comments');
  87. }
  88. this.viewPerLine[line].addOne(comment);
  89. },
  90. addAll: function() {
  91. var view = this;
  92. LineComments.each(function(comment) {
  93. view.addOne.call(view, comment);
  94. });
  95. },
  96. });
  97. window.CommentsForALineView = Backbone.View.extend({
  98. tagName: 'tr',
  99. className: 'comments',
  100. template: _.template(CodeComments.templates.comments_for_a_line),
  101. events: {
  102. 'click button': 'showAddCommentDialog'
  103. },
  104. render: function() {
  105. $(this.el).html(this.template());
  106. this.$('button').button();
  107. return this;
  108. },
  109. addOne: function(comment) {
  110. var view = new CommentView({model: comment});
  111. this.line = comment.get('line');
  112. this.$("ul.comments").append(view.render().el);
  113. },
  114. showAddCommentDialog: function() {
  115. AddCommentDialog.open(LineComments, this.line);
  116. }
  117. });
  118. window.AddCommentDialogView = Backbone.View.extend({
  119. id: 'add-comment-dialog',
  120. template: _.template(CodeComments.templates.add_comment_dialog),
  121. events: {
  122. 'click button.add-comment': 'createComment',
  123. 'keyup textarea': 'previewThrottled'
  124. },
  125. initialize: function(options) {
  126. this.$el = $(this.el);
  127. },
  128. render: function() {
  129. this.$el.html(this.template({formatting_help_url: CodeComments.formatting_help_url}))
  130. .dialog({autoOpen: false, title: 'Add Comment'});
  131. this.$('button.add-comment').button();
  132. return this;
  133. },
  134. open: function(collection, line) {
  135. this.line = line;
  136. this.collection = collection;
  137. var title = 'Add comment for ' + (this.line? 'line '+this.line + ' of ' : '') + CodeComments.path + '@' + CodeComments.revision;
  138. this.$el.dialog('open').dialog({title: title});
  139. },
  140. close: function() {
  141. this.$el.dialog('close');
  142. },
  143. createComment: function(e) {
  144. var self = this;
  145. var text = this.$('textarea').val();
  146. var line = this.line? this.line : 0;
  147. if (!text) return;
  148. var options = {
  149. success: function() {
  150. self.$('textarea').val('');
  151. self.$el.dialog('close');
  152. }
  153. }
  154. this.collection.create({text: text, author: CodeComments.username, path: CodeComments.path, revision: CodeComments.revision, line: line}, options);
  155. },
  156. previewThrottled: $.throttle(1500, function(e) { return this.preview(e); }),
  157. preview: function(e) {
  158. var view = this;
  159. $.get(CodeComments.preview_url, {text: this.$('textarea').val()}, function(data) {
  160. view.$('div.preview').html(data);
  161. view.$('h3').toggle(data != '');
  162. });
  163. }
  164. });
  165. window.LineCommentBubblesView = Backbone.View.extend({
  166. render: function() {
  167. this.$('tr').not('.comments').hover(
  168. function() {
  169. var $th = $('th', this);
  170. var line = $('a', $th).attr('href').replace('#L', '');
  171. $('a', $th).css('display', 'none');
  172. $th.prepend('<a style="" href="#L'+line+'" class="bubble"><span class="ui-icon ui-icon-comment"></span></a>');
  173. $('a.bubble').click(function(e) {
  174. e.preventDefault();
  175. AddCommentDialog.open(LineComments, line);
  176. })
  177. .css({width: $th.width(), height: $th.height(), 'text-align': 'center'})
  178. .find('span').css('margin-left', ($th.width() - 16) / 2);
  179. },
  180. function() {
  181. var $th = $('th', this);
  182. $('a.bubble', $th).remove();
  183. $('a', $th).show();
  184. }
  185. );
  186. }
  187. });
  188. window.TopComments = new CommentsList;
  189. window.LineComments = new CommentsList;
  190. window.TopCommentsBlock = new TopCommentsView;
  191. window.LineCommentsBlock = new LineCommentsView;
  192. window.AddCommentDialog = new AddCommentDialogView;
  193. window.LineCommentBubbles = new LineCommentBubblesView({el: $('table.code')});
  194. $(CodeComments.selectorToInsertBefore).before(TopCommentsBlock.render().el);
  195. LineCommentsBlock.render();
  196. AddCommentDialog.render();
  197. LineCommentBubbles.render();
  198. });