var Comments = (function() { 'use strict'; /** * Initializes the comments * */ function initializeComments(){ var comments; if ( $('.step-comment') && $('.step-comment').length > 0 ) { comments = $('.step-comment'); } else if ( $('.result-comment') && $('.result-comment').length > 0 ) { comments = $('.result-comment'); } if(!_.isUndefined(comments)) { $.each(comments, function(){ var that = $(this); var link = that.attr('data-href'); if(that.html().length === 0) { $.ajax({ method: 'GET', url: link, beforeSend: animateSpinner(that, true) }) .done(function(data) { that.html(data.html); }) .always(function() { animateSpinner(that, false); }); } initCommentForm(that); initCommentsLink(that); scrollBottom(that.find('.content-comments')); }); } } // scroll to the botttom function scrollBottom(id) { var list; if ( id.hasClass('content-comments') ) { list = id; } else { list = id.find('.content-comments'); } if ( list && list.length > 0) { list.scrollTop($(list)[0].scrollHeight); } } // Initialize show more comments link. function initCommentsLink($el) { $el.find('.btn-more-comments').off() .on('ajax:success', function (e, data) { if (data.html) { var list = $(this).parents('ul'); var moreBtn = list.find('.btn-more-comments'); var listItem = moreBtn.parents('li'); $(data.html).insertAfter(listItem); if (data.resultsNumber < data.perPage) { moreBtn.remove(); } else { moreBtn.attr('href', data.moreUrl); moreBtn.trigger('blur'); } var date; $.each(list.find('.comment-date-separator'), function() { if ( $(this).find('p').html() === date ) { $(this).remove(); } else { date = $(this).find('p').html(); } }); // Reposition dropdown comment options scrollCommentOptions(listItem .closest('.content-comments') .find('.dropdown-comment')); } else { $('.btn-more-comments').remove(); } }); } // Initialize comment form. function initCommentForm($el) { var $form = $el.find('ul form'); $('.help-block', $form).addClass('hide'); $form.off().on('ajax:send', function () { $('#comment_message', $form).attr('readonly', true); }) .on('ajax:success', function (e, data) { if (data.html) { var list = $form.parents('ul'); // Remove potential 'no comments' element list.parent().find('.content-comments') .find('li.no-comments').remove(); // Find previous date separator var dateSeparator = list.parent().find('.comment-date-separator:last'); if (dateSeparator.length > 0) { // Parse string with creation date var pr = dateSeparator.text().split('.'); var comm = data.date.split('.'); // Build Date objects and compare var sepDate = new Date(pr[2], pr[1] - 1, pr[0]); var commDate = new Date(comm[2], comm[1] - 1, comm[0]); if (commDate > sepDate) { // Add date separator list.parent().find('.content-comments') .append('
  • \

    ' + data.date + '

    \
  • '); } } else { // Comment is the first one so add date separator list.parent().find('.content-comments') .append('
  • \

    ' + data.date + '

    \
  • '); } CounterBadge.updateCounterBadge(data.counter, data.linked_id, 'comments'); list.parent().find('.content-comments') .append('
  • ' + data.html + '
  • ') .scrollTop(0); list.parents('ul').find('> li.comment:gt(8)').remove(); $('#comment_message', $form).val(''); $('.form-group', $form) .removeClass('has-error'); $('.help-block', $form) .html('') .addClass('hide'); scrollBottom($el); } }) .on('ajax:error', function (ev, xhr) { if (xhr.status === 400) { var messageError = xhr.responseJSON.errors.message; if (messageError) { $('.form-group', $form) .addClass('has-error'); $('.help-block', $form) .html(messageError[0]) .removeClass('hide'); } } }) .on('ajax:complete', function () { scrollBottom($('#comment_message', $form)); $('#comment_message', $form) .attr('readonly', false) .focus(); }); } function initCommentOptions(scrollableContainer, useParentOffset) { if ( ! _.isUndefined(useParentOffset) ) { useParentOffset = useParentOffset; } else { useParentOffset = true; } scrollCommentOptions($('.dropdown-comment'), useParentOffset); // Reposition dropdown to the left // (only do this when using parent offset) if (useParentOffset) { $(document).on('shown.bs.dropdown', '.dropdown-comment', function() { var $el = $(this); var menu = $el.find('.dropdown-menu'); var leftPos = $el.offset().left; var parentTopPos = $el.offset().top; if (leftPos + menu.width() > $(window).width()) { menu.offset({ left: leftPos - menu.width(), top: (parentTopPos + <%= Constants::DROPDOWN_TOP_OFFSET_PX %>)}); } }); } // Reposition dropdowns vertically on scroll events document.addEventListener('scroll', function (event) { var $target = $(event.target); var parent = $(scrollableContainer); if ($target.length) { scrollCommentOptions(parent.find('.dropdown-comment'), useParentOffset); } }, true); } function scrollCommentOptions(selector, useParentOffset) { if ( ! _.isUndefined(useParentOffset) ) { useParentOffset = useParentOffset; } else { useParentOffset = true; } _.each(selector, function(el) { var $el = $(el); var offset = useParentOffset ? $el.offset().top : $el.position().top; $el.find('.dropdown-menu-fixed') .offset({ top: (offset + <%= Constants::DROPDOWN_TOP_OFFSET_PX %>) }); }); } function initDeleteComments(parent) { $(parent).on('click', '[data-action=delete-comment]', function(ev) { ev.preventDefault(); var $this = $(this); if (confirm($this.attr('data-confirm-message'))) { $.ajax({ url: $this.attr('data-url'), type: 'DELETE', dataType: 'json', success: function(data) { // There are 3 possible actions: // - (A) comment is the last comment in project // - (B) comment is the last comment inside specific date // (remove the date separator) // - (C) comment is a usual comment var commentEl = $this.closest('.comment'); // Case A if (commentEl.prevAll('.comment').length === 0 && commentEl.next().length === 0) { commentEl.after('
  • ' + I18n.t('projects.index.no_comments') + '
  • '); } // Case B if (commentEl.prev('.comment-date-separator').length > 0 && commentEl.next('.comment').length === 0) { commentEl.prev('.comment-date-separator').remove(); } commentEl.remove(); CounterBadge.updateCounterBadge(data.counter, data.linked_id, 'comments'); scrollCommentOptions($(parent).find('.dropdown-comment')); }, error: function(data) { // Display alert alert(data.responseJSON.message); } }); } }); } function initEditComments(parent) { $(parent).unbind('click').on('click', '[data-action=edit-comment]', function() { var $this = $(this); // close dropdown on click var dropdown = $($this.parents(".dropdown-comment.open").get(0)); if(dropdown.length) { // safety first dropdown.removeClass('open'); } $.ajax({ url: $this.attr('data-url'), type: 'GET', dataType: 'json', success: function(data) { var commentEl = $this.closest('.comment'); var container = commentEl .find('[data-role=comment-message-container]'); var oldMessage = container.find('[data-role=comment-message]'); var optionsBtn = commentEl.find('[data-role=comment-options]'); // Hide old message, append new HTML oldMessage.hide(); optionsBtn.hide(); container.append(data.html); var form = container.find('[data-role=edit-comment-message-form]'); var input = form.find('[data-role=message-input]'); var submitBtn = form.find('[data-action=save]'); var cancelBtn = form.find('[data-action=cancel]'); input.focus(); form .on('ajax:send', function() { input.attr('readonly', true); }) .on('ajax:success', function(ev, data) { var newMessage = input.val(); if (!_.isUndefined(data.comment)) { newMessage = data.comment; } oldMessage.html(newMessage); form.off('ajax:send ajax:success ajax:error ajax:complete'); submitBtn.off('click'); cancelBtn.off('click'); form.remove(); oldMessage.show(); optionsBtn.show(); }) .on('ajax:error', function(ev, xhr) { if (xhr.status === 422) { var messageError = xhr.responseJSON.errors.message; if (messageError) { $('.form-group', form) .addClass('has-error'); $('.help-block', form) .html(messageError[0] + ' |') .removeClass('hide'); } } }) .on('ajax:complete', function() { input.attr('readonly', false).focus(); }); submitBtn.on('click', function() { form.submit(); }); cancelBtn.on('click', function() { form.off('ajax:send ajax:success ajax:error ajax:complete'); submitBtn.off('click'); cancelBtn.off('click'); form.remove(); oldMessage.show(); optionsBtn.show(); }); }, error: function() { // TODO } }); }); } return { initialize: initializeComments, scrollBottom: scrollBottom, moreComments: initCommentsLink, form: initCommentForm, initCommentOptions: initCommentOptions, initDeleteComments: initDeleteComments, initEditComments: initEditComments }; })();