import $ from 'jquery'; import { isImageLoaded } from '../lib/utils/image_utility'; import imageDiffHelper from './helpers/index'; import ImageBadge from './image_badge'; export default class ImageDiff { constructor(el, options) { this.el = el; this.canCreateNote = Boolean(options && options.canCreateNote); this.renderCommentBadge = Boolean(options && options.renderCommentBadge); this.$noteContainer = $('.note-container', this.el); this.imageBadges = []; } init() { this.imageFrameEl = this.el.querySelector('.diff-file .js-image-frame'); this.imageEl = this.imageFrameEl.querySelector('img'); this.bindEvents(); } bindEvents() { this.imageClickedWrapper = this.imageClicked.bind(this); this.imageBlurredWrapper = imageDiffHelper.removeCommentIndicator.bind(null, this.imageFrameEl); this.addBadgeWrapper = this.addBadge.bind(this); this.removeBadgeWrapper = this.removeBadge.bind(this); this.renderBadgesWrapper = this.renderBadges.bind(this); // Render badges if (isImageLoaded(this.imageEl)) { this.renderBadges(); } else { this.imageEl.addEventListener('load', this.renderBadgesWrapper); } // jquery makes the event delegation here much simpler this.$noteContainer.on('click', '.js-diff-notes-toggle', imageDiffHelper.toggleCollapsed); $(this.el).on('click', '.comment-indicator', imageDiffHelper.commentIndicatorOnClick); if (this.canCreateNote) { this.el.addEventListener('click.imageDiff', this.imageClickedWrapper); this.el.addEventListener('blur.imageDiff', this.imageBlurredWrapper); this.el.addEventListener('addBadge.imageDiff', this.addBadgeWrapper); this.el.addEventListener('removeBadge.imageDiff', this.removeBadgeWrapper); } } imageClicked(event) { const customEvent = event.detail; const selection = imageDiffHelper.getTargetSelection(customEvent); const el = customEvent.currentTarget; imageDiffHelper.setPositionDataAttribute(el, selection.actual); imageDiffHelper.showCommentIndicator(this.imageFrameEl, selection.browser); } renderBadges() { const discussionsEls = this.el.querySelectorAll('.note-container .discussion-notes .notes'); [...discussionsEls].forEach(this.renderBadge.bind(this)); } renderBadge(discussionEl, index) { const imageBadge = imageDiffHelper.generateBadgeFromDiscussionDOM( this.imageFrameEl, discussionEl, ); this.imageBadges.push(imageBadge); const options = { coordinate: imageBadge.browser, noteId: imageBadge.noteId, }; if (this.renderCommentBadge) { imageDiffHelper.addImageCommentBadge(this.imageFrameEl, options); } else { const numberBadgeOptions = { ...options, badgeText: index + 1 }; imageDiffHelper.addImageBadge(this.imageFrameEl, numberBadgeOptions); } } addBadge(event) { const { x, y, width, height, noteId, discussionId } = event.detail; const badgeText = this.imageBadges.length + 1; const imageBadge = new ImageBadge({ actual: { x, y, width, height, }, imageEl: this.imageFrameEl.querySelector('img'), noteId, discussionId, }); this.imageBadges.push(imageBadge); imageDiffHelper.addImageBadge(this.imageFrameEl, { coordinate: imageBadge.browser, badgeText, noteId, }); imageDiffHelper.addAvatarBadge(this.el, { detail: { noteId, badgeNumber: badgeText, }, }); const discussionEl = this.el.querySelector(`#discussion_${discussionId}`); imageDiffHelper.updateDiscussionBadgeNumber(discussionEl, badgeText); } removeBadge(event) { const { badgeNumber } = event.detail; const indexToRemove = badgeNumber - 1; const imageBadgeEls = this.imageFrameEl.querySelectorAll('.design-note-pin'); if (this.imageBadges.length !== badgeNumber) { // Cascade badges count numbers for (avatar badges + image badges) this.imageBadges.forEach((badge, index) => { if (index > indexToRemove) { const { discussionId } = badge; const updatedBadgeNumber = index; const discussionEl = this.el.querySelector(`#discussion_${discussionId}`); imageBadgeEls[index].textContent = updatedBadgeNumber; imageDiffHelper.updateDiscussionBadgeNumber(discussionEl, updatedBadgeNumber); imageDiffHelper.updateDiscussionAvatarBadgeNumber(discussionEl, updatedBadgeNumber); } }); } this.imageBadges.splice(indexToRemove, 1); const imageBadgeEl = imageBadgeEls[indexToRemove]; imageBadgeEl.remove(); } }