summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/image_diff/helpers/utils_helper.js
blob: d0cd42df0736f4385a0cc91b011cb95b8ca40b14 (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
import ImageBadge from '../image_badge';
import ImageDiff from '../image_diff';
import ReplacedImageDiff from '../replaced_image_diff';

export function resizeCoordinatesToImageElement(imageEl, meta) {
  const { x, y, width, height } = meta;

  const imageWidth = imageEl.width;
  const imageHeight = imageEl.height;

  const widthRatio = imageWidth / width;
  const heightRatio = imageHeight / height;

  return {
    x: Math.round(x * widthRatio),
    y: Math.round(y * heightRatio),
    width: imageWidth,
    height: imageHeight,
  };
}

export function generateBadgeFromDiscussionDOM(imageFrameEl, discussionEl) {
  const position = JSON.parse(discussionEl.dataset.position);
  const firstNoteEl = discussionEl.querySelector('.note');
  const badge = new ImageBadge({
    actual: {
      x: position.x_axis,
      y: position.y_axis,
      width: position.width,
      height: position.height,
    },
    imageEl: imageFrameEl.querySelector('img'),
    noteId: firstNoteEl.id,
    discussionId: discussionEl.dataset.discussionId,
  });

  return badge;
}

export function getTargetSelection(event) {
  const containerEl = event.currentTarget;
  const imageEl = containerEl.querySelector('img');

  const x = event.offsetX;
  const y = event.offsetY;

  const width = imageEl.width;
  const height = imageEl.height;

  const actualWidth = imageEl.naturalWidth;
  const actualHeight = imageEl.naturalHeight;

  const widthRatio = actualWidth / width;
  const heightRatio = actualHeight / height;

  // Browser will include the frame as a clickable target,
  // which would result in potential 1px out of bounds value
  // This bound the coordinates to inside the frame
  const normalizedX = Math.max(0, x) && Math.min(x, width);
  const normalizedY = Math.max(0, y) && Math.min(y, height);

  return {
    browser: {
      x: normalizedX,
      y: normalizedY,
      width,
      height,
    },
    actual: {
      // Round x, y so that we don't need to deal with decimals
      x: Math.round(normalizedX * widthRatio),
      y: Math.round(normalizedY * heightRatio),
      width: actualWidth,
      height: actualHeight,
    },
  };
}

export function initImageDiff(file, canCreateNote, renderCommentBadge) {
  const options = {
    canCreateNote,
    renderCommentBadge,
  };

  // ImageFile needs to be invoked before initImageDiff so that badges
  // can mount to the correct location
  new gl.ImageFile(file); // eslint-disable-line no-new

  if (file.querySelector('.diff-file .js-single-image')) {
    const imageDiff = new ImageDiff(file, options);
    imageDiff.init();
  } else if (file.querySelector('.diff-file .js-replaced-image')) {
    const replacedImageDiff = new ReplacedImageDiff(file, options);
    replacedImageDiff.init();
  }
}