summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/files_comment_button.js
blob: f7ce9a7139cfa30f105738ac3ac15299354321ed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

this.FilesCommentButton = (function() {
  var COMMENT_BUTTON_CLASS, COMMENT_BUTTON_TEMPLATE, DEBOUNCE_TIMEOUT_DURATION, EMPTY_CELL_CLASS, LINE_COLUMN_CLASSES, LINE_CONTENT_CLASS, LINE_HOLDER_CLASS, LINE_NUMBER_CLASS, OLD_LINE_CLASS, TEXT_FILE_SELECTOR, UNFOLDABLE_LINE_CLASS;

  COMMENT_BUTTON_CLASS = '.add-diff-note';

  COMMENT_BUTTON_TEMPLATE = _.template('<button name="button" type="submit" class="btn <%- COMMENT_BUTTON_CLASS %> js-add-diff-note-button" title="Add a comment to this line"><i class="fa fa-comment-o"></i></button>');

  LINE_HOLDER_CLASS = '.line_holder';

  LINE_NUMBER_CLASS = 'diff-line-num';

  LINE_CONTENT_CLASS = 'line_content';

  UNFOLDABLE_LINE_CLASS = 'js-unfold';

  EMPTY_CELL_CLASS = 'empty-cell';

  OLD_LINE_CLASS = 'old_line';

  LINE_COLUMN_CLASSES = "." + LINE_NUMBER_CLASS + ", .line_content";

  TEXT_FILE_SELECTOR = '.text-file';

  DEBOUNCE_TIMEOUT_DURATION = 100;

  function FilesCommentButton(filesContainerElement) {
    var debounce;
    this.filesContainerElement = filesContainerElement;
    this.destroy = bind(this.destroy, this);
    this.render = bind(this.render, this);
    this.VIEW_TYPE = $('input#view[type=hidden]').val();
    debounce = _.debounce(this.render, DEBOUNCE_TIMEOUT_DURATION);
    $(document).off('mouseover', LINE_COLUMN_CLASSES).off('mouseleave', LINE_COLUMN_CLASSES).on('mouseover', LINE_COLUMN_CLASSES, debounce).on('mouseleave', LINE_COLUMN_CLASSES, this.destroy);
  }

  FilesCommentButton.prototype.render = function(e) {
    var $currentTarget, buttonParentElement, lineContentElement, textFileElement;
    $currentTarget = $(e.currentTarget);
    buttonParentElement = this.getButtonParent($currentTarget);
    if (!this.shouldRender(e, buttonParentElement)) {
      return;
    }
    textFileElement = this.getTextFileElement($currentTarget);
    lineContentElement = this.getLineContent($currentTarget);
    buttonParentElement.append(this.buildButton({
      noteableType: textFileElement.attr('data-noteable-type'),
      noteableID: textFileElement.attr('data-noteable-id'),
      commitID: textFileElement.attr('data-commit-id'),
      noteType: lineContentElement.attr('data-note-type'),
      position: lineContentElement.attr('data-position'),
      lineType: lineContentElement.attr('data-line-type'),
      discussionID: lineContentElement.attr('data-discussion-id'),
      lineCode: lineContentElement.attr('data-line-code')
    }));
  };

  FilesCommentButton.prototype.destroy = function(e) {
    if (this.isMovingToSameType(e)) {
      return;
    }
    $(COMMENT_BUTTON_CLASS, this.getButtonParent($(e.currentTarget))).remove();
  };

  FilesCommentButton.prototype.buildButton = function(buttonAttributes) {
    var initializedButtonTemplate;
    initializedButtonTemplate = COMMENT_BUTTON_TEMPLATE({
      COMMENT_BUTTON_CLASS: COMMENT_BUTTON_CLASS.substr(1)
    });
    return $(initializedButtonTemplate).attr({
      'data-noteable-type': buttonAttributes.noteableType,
      'data-noteable-id': buttonAttributes.noteableID,
      'data-commit-id': buttonAttributes.commitID,
      'data-note-type': buttonAttributes.noteType,
      'data-line-code': buttonAttributes.lineCode,
      'data-position': buttonAttributes.position,
      'data-discussion-id': buttonAttributes.discussionID,
      'data-line-type': buttonAttributes.lineType
    });
  };

  FilesCommentButton.prototype.getTextFileElement = function(hoveredElement) {
    return $(hoveredElement.closest(TEXT_FILE_SELECTOR));
  };

  FilesCommentButton.prototype.getLineContent = function(hoveredElement) {
    if (hoveredElement.hasClass(LINE_CONTENT_CLASS)) {
      return hoveredElement;
    }
    if (this.VIEW_TYPE === 'inline') {
      return $(hoveredElement).closest(LINE_HOLDER_CLASS).find("." + LINE_CONTENT_CLASS);
    } else {
      return $(hoveredElement).next("." + LINE_CONTENT_CLASS);
    }
  };

  FilesCommentButton.prototype.getButtonParent = function(hoveredElement) {
    if (this.VIEW_TYPE === 'inline') {
      if (hoveredElement.hasClass(OLD_LINE_CLASS)) {
        return hoveredElement;
      }
      return hoveredElement.parent().find("." + OLD_LINE_CLASS);
    } else {
      if (hoveredElement.hasClass(LINE_NUMBER_CLASS)) {
        return hoveredElement;
      }
      return $(hoveredElement).prev("." + LINE_NUMBER_CLASS);
    }
  };

  FilesCommentButton.prototype.isMovingToSameType = function(e) {
    var newButtonParent;
    newButtonParent = this.getButtonParent($(e.toElement));
    if (!newButtonParent) {
      return false;
    }
    return newButtonParent.is(this.getButtonParent($(e.currentTarget)));
  };

  FilesCommentButton.prototype.shouldRender = function(e, buttonParentElement) {
    return !buttonParentElement.hasClass(EMPTY_CELL_CLASS) && !buttonParentElement.hasClass(UNFOLDABLE_LINE_CLASS) && $(COMMENT_BUTTON_CLASS, buttonParentElement).length === 0;
  };

  return FilesCommentButton;

})();

$.fn.filesCommentButton = function() {
  if (!(this && (this.parent().data('can-create-note') != null))) {
    return;
  }
  return this.each(function() {
    if (!$.data(this, 'filesCommentButton')) {
      return $.data(this, 'filesCommentButton', new FilesCommentButton($(this)));
    }
  });
};