/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This Source Code Form is "Incompatible With Secondary Licenses", as
* defined by the Mozilla Public License, v. 2.0. */
$(function() {
'use strict';
// comment collapse/expand
$('.comment-spinner')
.click(function(event) {
event.preventDefault();
var spinner = $(event.target);
var id = spinner.attr('id').match(/\d+$/)[0];
// switch to full header for initially collapsed comments
if (spinner.attr('id').match(/^ccs-/)) {
$('#cc-' + id).hide();
$('#ch-' + id).show();
}
$('#ct-' + id + ', #ctag-' + id).slideToggle('fast', function() {
$('#c' + id).find('.activity').toggle();
spinner.text($('#ct-' + id + ':visible').length ? '-' : '+');
});
});
//
// anything after this point is only executed for logged in users
//
if (BUGZILLA.user.id === 0) return;
// comment tagging
function taggingError(commentNo, message) {
$('#ctag-' + commentNo + ' .comment-tags').append($('#ctag-error'));
$('#ctag-error-message').text(message);
$('#ctag-error').show();
}
function deleteTag(event) {
event.preventDefault();
$('#ctag-error').hide();
var that = $(this);
var comment = that.parents('.comment');
var commentNo = comment.data('no');
var commentID = comment.data('id');
var tag = that.parent('.comment-tag').contents().filter(function() {
return this.nodeType === 3;
}).text();
var container = that.parents('.comment-tags');
// update ui
that.parent('.comment-tag').remove();
renderTags(commentNo, tagsFromDom(container));
// update bugzilla
bugzilla_ajax(
{
url: 'rest/bug/comment/' + commentID + '/tags',
type: 'PUT',
data: { remove: [ tag ] },
hideError: true
},
function(data) {
renderTags(commentNo, data);
},
function(message) {
taggingError(commentNo, message);
}
);
}
$('.comment-tag a').click(deleteTag);
function tagsFromDom(commentTagsDiv) {
return commentTagsDiv
.find('.comment-tag')
.contents()
.filter(function() { return this.nodeType === 3; })
.map(function() { return $(this).text(); })
.toArray();
}
function renderTags(commentNo, tags) {
cancelRefresh();
var root = $('#ctag-' + commentNo + ' .comment-tags');
root.find('.comment-tag').remove();
$.each(tags, function() {
var span = $('').addClass('comment-tag').text(this);
if (BUGZILLA.user.can_tag) {
span.prepend($('x').click(deleteTag));
}
root.append(span);
});
$('#ctag-' + commentNo + ' .comment-tags').append($('#ctag-error'));
}
var refreshXHR;
function refreshTags(commentNo, commentID) {
cancelRefresh();
refreshXHR = bugzilla_ajax(
{
url: 'rest/bug/comment/' + commentID + '?include_fields=tags',
hideError: true
},
function(data) {
refreshXHR = false;
renderTags(commentNo, data.comments[commentID].tags);
},
function(message) {
refreshXHR = false;
taggingError(commentNo, message);
}
);
}
function cancelRefresh() {
if (refreshXHR) {
refreshXHR.abort();
refreshXHR = false;
}
}
$('#ctag-add')
.devbridgeAutocomplete({
serviceUrl: function(query) {
return 'rest/bug/comment/tags/' + encodeURIComponent(query);
},
params: {
Bugzilla_api_token: (BUGZILLA.api_token ? BUGZILLA.api_token : '')
},
deferRequestBy: 250,
minChars: 3,
tabDisabled: true,
autoSelectFirst: true,
triggerSelectOnValidInput: false,
transformResult: function(response) {
response = $.parseJSON(response);
return {
suggestions: $.map(response, function(tag) {
return { value: tag };
})
};
},
formatResult: function(suggestion, currentValue) {
// disable wrapping of matched substring
return suggestion.value.htmlEncode();
}
})
.keydown(function(event) {
if (event.which === 27) {
event.preventDefault();
$('#ctag-close').click();
}
else if (event.which === 13) {
event.preventDefault();
$('#ctag-error').hide();
var ctag = $('#ctag');
var newTags = $('#ctag-add').val().trim().split(/[ ,]/);
var commentNo = ctag.data('commentNo');
var commentID = ctag.data('commentID');
$('#ctag-close').click();
// update ui
var tags = tagsFromDom($(this).parents('.comment-tags'));
var dirty = false;
var addTags = [];
$.each(newTags, function(index, value) {
if ($.inArrayIn(value, tags) == -1)
addTags.push(value);
});
if (addTags.length === 0)
return;
// validate
try {
$.each(addTags, function(index, value) {
if (value.length < BUGZILLA.constant.min_comment_tag_length) {
throw 'Comment tags must be at least ' +
BUGZILLA.constant.min_comment_tag_length + ' characters.';
}
if (value.length > BUGZILLA.constant.max_comment_tag_length) {
throw 'Comment tags cannot be longer than ' +
BUGZILLA.constant.min_comment_tag_length + ' characters.';
}
});
} catch(ex) {
taggingError(commentNo, ex);
return;
}
Array.prototype.push.apply(tags, addTags);
tags.sort();
renderTags(commentNo, tags);
// update bugzilla
bugzilla_ajax(
{
url: 'rest/bug/comment/' + commentID + '/tags',
type: 'PUT',
data: { add: addTags },
hideError: true
},
function(data) {
renderTags(commentNo, data);
},
function(message) {
taggingError(commentNo, message);
refreshTags(commentNo, commentID);
}
);
}
});
$('#ctag-close')
.click(function(event) {
event.preventDefault();
$('#ctag').hide().data('commentNo', '');
});
$('.tag-btn')
.click(function(event) {
event.preventDefault();
var that = $(this);
var commentNo = that.data('no');
var commentID = that.data('id');
var ctag = $('#ctag');
$('#ctag-error').hide();
// toggle -> hide
if (ctag.data('commentNo') === commentNo) {
ctag.hide().data('commentNo', '');
window.focus();
return;
}
ctag.data('commentNo', commentNo);
ctag.data('commentID', commentID);
// kick off a refresh of the tags
refreshTags(commentNo, commentID);
// expand collapsed comments
if ($('#ct-' + commentNo + ':visible').length === 0) {
$('#cs-' + commentNo + ', #ccs-' + commentNo).click();
}
// move, show, and focus tagging ui
ctag.prependTo('#ctag-' + commentNo + ' .comment-tags').show();
$('#ctag-add').val('').focus();
});
$('.close-btn')
.click(function(event) {
event.preventDefault();
$('#' + $(this).data('for')).hide();
});
});