files_comment_button.js 5.43 KB
Newer Older
Fatih Acet's avatar
Fatih Acet committed
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 139 140 141
(function() {
  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)));
      }
    });
  };

}).call(this);