|
|
@ -25,9 +25,11 @@ define([
|
|
|
|
u: id,
|
|
|
|
u: id,
|
|
|
|
m: "str", // comment
|
|
|
|
m: "str", // comment
|
|
|
|
t: +new Date,
|
|
|
|
t: +new Date,
|
|
|
|
v: "str" // value of the commented content
|
|
|
|
v: "str", // value of the commented content
|
|
|
|
|
|
|
|
e: undefined/1, // edited
|
|
|
|
|
|
|
|
d: undefined/1, // deleted
|
|
|
|
}],
|
|
|
|
}],
|
|
|
|
(deleted: undefined/true,)
|
|
|
|
d: undefined/1,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -66,14 +68,24 @@ define([
|
|
|
|
return uid || authorUid(existing);
|
|
|
|
return uid || authorUid(existing);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
var updateAuthorData = function (Env) {
|
|
|
|
// Return the author ID and add/update the data for registered users
|
|
|
|
|
|
|
|
// Return the username for unregistered users
|
|
|
|
|
|
|
|
var updateAuthorData = function (Env, onChange) {
|
|
|
|
var userData = Env.metadataMgr.getUserData();
|
|
|
|
var userData = Env.metadataMgr.getUserData();
|
|
|
|
|
|
|
|
if (!Env.common.isLoggedIn()) {
|
|
|
|
|
|
|
|
return userData.name;
|
|
|
|
|
|
|
|
}
|
|
|
|
var myAuthorId = getAuthorId(Env, userData.curvePublic);
|
|
|
|
var myAuthorId = getAuthorId(Env, userData.curvePublic);
|
|
|
|
var data = Env.comments.authors[myAuthorId] = Env.comments.authors[myAuthorId] || {};
|
|
|
|
var data = Env.comments.authors[myAuthorId] = Env.comments.authors[myAuthorId] || {};
|
|
|
|
|
|
|
|
var old = Sortify(data);
|
|
|
|
data.name = userData.name;
|
|
|
|
data.name = userData.name;
|
|
|
|
data.avatar = userData.avatar;
|
|
|
|
data.avatar = userData.avatar;
|
|
|
|
data.profile = userData.profile;
|
|
|
|
data.profile = userData.profile;
|
|
|
|
data.curvePublic = userData.curvePublic;
|
|
|
|
data.curvePublic = userData.curvePublic;
|
|
|
|
|
|
|
|
data.notifications = userData.notifications;
|
|
|
|
|
|
|
|
if (typeof(onChange) === "function" && Sortify(data) !== old) {
|
|
|
|
|
|
|
|
onChange();
|
|
|
|
|
|
|
|
}
|
|
|
|
return myAuthorId;
|
|
|
|
return myAuthorId;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
@ -83,17 +95,82 @@ define([
|
|
|
|
Env.metadataMgr.updateMetadata(md);
|
|
|
|
Env.metadataMgr.updateMetadata(md);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var sendReplyNotification = function (Env, uid) {
|
|
|
|
|
|
|
|
if (!Env.comments || !Env.comments.data || !Env.comments.authors) { return; }
|
|
|
|
|
|
|
|
if (!Env.common.isLoggedIn()) { return; }
|
|
|
|
|
|
|
|
var thread = Env.comments.data[uid];
|
|
|
|
|
|
|
|
if (!thread || !Array.isArray(thread.m)) { return; }
|
|
|
|
|
|
|
|
var userData = Env.metadataMgr.getUserData();
|
|
|
|
|
|
|
|
var privateData = Env.metadataMgr.getPrivateData();
|
|
|
|
|
|
|
|
var others = {};
|
|
|
|
|
|
|
|
// Get all the other registered users with a mailbox
|
|
|
|
|
|
|
|
thread.m.forEach(function (obj) {
|
|
|
|
|
|
|
|
var u = obj.u;
|
|
|
|
|
|
|
|
if (typeof(u) !== "number") { return; }
|
|
|
|
|
|
|
|
var author = Env.comments.authors[u];
|
|
|
|
|
|
|
|
if (!author || others[u] || !author.notifications || !author.curvePublic) { return; }
|
|
|
|
|
|
|
|
if (author.curvePublic === userData.curvePublic) { return; } // don't send to yourself
|
|
|
|
|
|
|
|
others[u] = {
|
|
|
|
|
|
|
|
curvePublic: author.curvePublic,
|
|
|
|
|
|
|
|
comment: obj.m,
|
|
|
|
|
|
|
|
content: obj.v,
|
|
|
|
|
|
|
|
notifications: author.notifications
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
// Send the notification
|
|
|
|
|
|
|
|
Object.keys(others).forEach(function (id) {
|
|
|
|
|
|
|
|
var data = others[id];
|
|
|
|
|
|
|
|
Env.common.mailbox.sendTo("COMMENT_REPLY", {
|
|
|
|
|
|
|
|
channel: privateData.channel,
|
|
|
|
|
|
|
|
comment: data.comment,
|
|
|
|
|
|
|
|
content: data.content
|
|
|
|
|
|
|
|
}, {
|
|
|
|
|
|
|
|
channel: data.notifications,
|
|
|
|
|
|
|
|
curvePublic: data.curvePublic
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var cleanMentions = function ($el) {
|
|
|
|
|
|
|
|
$el.html('');
|
|
|
|
|
|
|
|
var el = $el[0];
|
|
|
|
|
|
|
|
var allowed = ['data-profile', 'data-name', 'data-avatar', 'class'];
|
|
|
|
|
|
|
|
// Remove unnecessary/unsafe attributes
|
|
|
|
|
|
|
|
for (var i=el.attributes.length-1; i>0; i--) {
|
|
|
|
|
|
|
|
var name = el.attributes[i] && el.attributes[i].name;
|
|
|
|
|
|
|
|
if (allowed.indexOf(name) === -1) {
|
|
|
|
|
|
|
|
$el.removeAttr(name);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Seletc all text of a contenteditable element
|
|
|
|
|
|
|
|
var selectAll = function (element) {
|
|
|
|
|
|
|
|
var selection = window.getSelection();
|
|
|
|
|
|
|
|
var range = document.createRange();
|
|
|
|
|
|
|
|
range.selectNodeContents(element);
|
|
|
|
|
|
|
|
selection.removeAllRanges();
|
|
|
|
|
|
|
|
selection.addRange(range);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Messages.comments_deleted = "Comment deleted by its author"; // XXX
|
|
|
|
|
|
|
|
Messages.comments_edited = "Edited"; // XXX
|
|
|
|
Messages.comments_submit = "Submit"; // XXX
|
|
|
|
Messages.comments_submit = "Submit"; // XXX
|
|
|
|
Messages.comments_reply = "Reply"; // XXX
|
|
|
|
Messages.comments_reply = "Reply"; // XXX
|
|
|
|
Messages.comments_resolve = "Resolve"; // XXX
|
|
|
|
Messages.comments_resolve = "Resolve"; // XXX
|
|
|
|
|
|
|
|
var getCommentForm = function (Env, reply, _cb, editContent) {
|
|
|
|
var getCommentForm = function (Env, reply, _cb) {
|
|
|
|
|
|
|
|
var cb = Util.once(_cb);
|
|
|
|
var cb = Util.once(_cb);
|
|
|
|
var userData = Env.metadataMgr.getUserData();
|
|
|
|
var userData = Env.metadataMgr.getUserData();
|
|
|
|
var name = Util.fixHTML(userData.name || Messages.anonymous);
|
|
|
|
var name = Util.fixHTML(userData.name || Messages.anonymous);
|
|
|
|
var avatar = h('span.cp-avatar');
|
|
|
|
var avatar = h('span.cp-avatar');
|
|
|
|
var textarea = h('textarea', {
|
|
|
|
var textarea = h('div.cp-textarea', {
|
|
|
|
tabindex: 1
|
|
|
|
tabindex: 1,
|
|
|
|
|
|
|
|
role: 'textbox',
|
|
|
|
|
|
|
|
'aria-multiline': true,
|
|
|
|
|
|
|
|
'aria-labelledby': 'cp-comments-label',
|
|
|
|
|
|
|
|
'aria-required': true,
|
|
|
|
|
|
|
|
contenteditable: true,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
Env.common.displayAvatar($(avatar), userData.avatar, name);
|
|
|
|
Env.common.displayAvatar($(avatar), userData.avatar, name);
|
|
|
|
|
|
|
|
|
|
|
@ -110,31 +187,106 @@ define([
|
|
|
|
Messages.comments_submit
|
|
|
|
Messages.comments_submit
|
|
|
|
]);
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// List of allowed attributes in mentions
|
|
|
|
$(submit).click(function (e) {
|
|
|
|
$(submit).click(function (e) {
|
|
|
|
e.stopPropagation();
|
|
|
|
e.stopPropagation();
|
|
|
|
cb(textarea.value);
|
|
|
|
var clone = textarea.cloneNode(true);
|
|
|
|
|
|
|
|
var notify = {};
|
|
|
|
|
|
|
|
var $clone = $(clone);
|
|
|
|
|
|
|
|
$clone.find('span.cp-mentions').each(function (i, el) {
|
|
|
|
|
|
|
|
var $el = $(el);
|
|
|
|
|
|
|
|
var curve = $el.attr('data-curve');
|
|
|
|
|
|
|
|
var notif = $el.attr('data-notifications');
|
|
|
|
|
|
|
|
cleanMentions($el, true);
|
|
|
|
|
|
|
|
if (!curve || !notif) { return; }
|
|
|
|
|
|
|
|
notify[curve] = notif;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
$clone.find('br').replaceWith("\n");
|
|
|
|
|
|
|
|
$clone.find('> *:not(.cp-mentions)').remove();
|
|
|
|
|
|
|
|
var content = clone.innerHTML.trim();
|
|
|
|
|
|
|
|
if (!content) { return; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Send notification
|
|
|
|
|
|
|
|
var privateData = Env.metadataMgr.getPrivateData();
|
|
|
|
|
|
|
|
var userData = Env.metadataMgr.getUserData();
|
|
|
|
|
|
|
|
Object.keys(notify).forEach(function (curve) {
|
|
|
|
|
|
|
|
if (curve === userData.curvePublic) { return; }
|
|
|
|
|
|
|
|
Env.common.mailbox.sendTo("MENTION", {
|
|
|
|
|
|
|
|
channel: privateData.channel,
|
|
|
|
|
|
|
|
}, {
|
|
|
|
|
|
|
|
channel: notify[curve],
|
|
|
|
|
|
|
|
curvePublic: curve
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Push the content
|
|
|
|
|
|
|
|
cb(content);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
$(cancel).click(function (e) {
|
|
|
|
$(cancel).click(function (e) {
|
|
|
|
e.stopPropagation();
|
|
|
|
e.stopPropagation();
|
|
|
|
cb();
|
|
|
|
cb();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
$(textarea).keydown(function (e) {
|
|
|
|
var $text = $(textarea).keydown(function (e) {
|
|
|
|
|
|
|
|
e.stopPropagation();
|
|
|
|
if (e.which === 27) {
|
|
|
|
if (e.which === 27) {
|
|
|
|
$(cancel).click();
|
|
|
|
$(cancel).click();
|
|
|
|
|
|
|
|
e.stopImmediatePropagation();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (e.which === 13 && !e.shiftKey) {
|
|
|
|
if (e.which === 13 && !e.shiftKey) {
|
|
|
|
|
|
|
|
// Submit form on Enter is the autocompelte menu is not visible
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
var visible = $text.autocomplete("instance").menu.activeMenu.is(':visible');
|
|
|
|
|
|
|
|
if (visible) { return; }
|
|
|
|
|
|
|
|
} catch (err) {}
|
|
|
|
$(submit).click();
|
|
|
|
$(submit).click();
|
|
|
|
|
|
|
|
e.stopImmediatePropagation();
|
|
|
|
e.preventDefault();
|
|
|
|
e.preventDefault();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}).click(function (e) {
|
|
|
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (Env.common.isLoggedIn()) {
|
|
|
|
|
|
|
|
var authors = {};
|
|
|
|
|
|
|
|
Object.keys((Env.comments && Env.comments.authors) || {}).forEach(function (id) {
|
|
|
|
|
|
|
|
var obj = Util.clone(Env.comments.authors[id]);
|
|
|
|
|
|
|
|
authors[obj.curvePublic] = obj;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
Env.common.addMentions({
|
|
|
|
|
|
|
|
$input: $text,
|
|
|
|
|
|
|
|
contenteditable: true,
|
|
|
|
|
|
|
|
type: 'contacts',
|
|
|
|
|
|
|
|
sources: authors
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var deleteButton;
|
|
|
|
|
|
|
|
// Edit? start with the old content
|
|
|
|
|
|
|
|
// Add a space to make sure we won't end with a mention and a bad cursor
|
|
|
|
|
|
|
|
if (editContent) {
|
|
|
|
|
|
|
|
textarea.innerHTML = editContent + " ";
|
|
|
|
|
|
|
|
deleteButton = h('button.btn.btn-danger', {
|
|
|
|
|
|
|
|
tabindex: 1
|
|
|
|
|
|
|
|
}, [
|
|
|
|
|
|
|
|
h('i.fa.fa-times'),
|
|
|
|
|
|
|
|
Messages.kanban_delete
|
|
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
$(deleteButton).click(function (e) {
|
|
|
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
|
|
|
cb(false);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setTimeout(function () {
|
|
|
|
setTimeout(function () {
|
|
|
|
$(textarea).focus();
|
|
|
|
$(textarea).focus();
|
|
|
|
|
|
|
|
selectAll(textarea);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return h('div.cp-comment-form' + (reply ? '.cp-comment-reply' : ''), {
|
|
|
|
return h('div.cp-comment-form' + (reply ? '.cp-comment-reply' : ''), {
|
|
|
|
'data-uid': reply || undefined
|
|
|
|
'data-uid': reply || ''
|
|
|
|
}, [
|
|
|
|
}, [
|
|
|
|
h('div.cp-comment-form-input', [
|
|
|
|
h('div.cp-comment-form-input', [
|
|
|
|
avatar,
|
|
|
|
avatar,
|
|
|
@ -142,49 +294,90 @@ define([
|
|
|
|
]),
|
|
|
|
]),
|
|
|
|
h('div.cp-comment-form-actions', [
|
|
|
|
h('div.cp-comment-form-actions', [
|
|
|
|
cancel,
|
|
|
|
cancel,
|
|
|
|
|
|
|
|
deleteButton,
|
|
|
|
submit
|
|
|
|
submit
|
|
|
|
])
|
|
|
|
])
|
|
|
|
]);
|
|
|
|
]);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var isVisible = function (el, $container) {
|
|
|
|
|
|
|
|
var size = $container.outerHeight();
|
|
|
|
|
|
|
|
var pos = el.getBoundingClientRect();
|
|
|
|
|
|
|
|
return (pos.bottom < size) && (pos.y > 0);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
var redrawComments = function (Env) {
|
|
|
|
var redrawComments = function (Env) {
|
|
|
|
// Don't redraw if there were no change
|
|
|
|
// Don't redraw if there were no change
|
|
|
|
var str = Sortify((Env.comments || {}).data || {});
|
|
|
|
var str = Sortify(Env.comments || {});
|
|
|
|
|
|
|
|
|
|
|
|
if (str === Env.oldComments) { return; }
|
|
|
|
if (str === Env.oldComments) { return; }
|
|
|
|
Env.oldComments = str;
|
|
|
|
Env.oldComments = str;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Store the cursor position if it's located in this form
|
|
|
|
|
|
|
|
var oldSelection = window.getSelection();
|
|
|
|
|
|
|
|
var oldRangeObj;
|
|
|
|
|
|
|
|
if ($(oldSelection.anchorNode).closest('.cp-comment-form').length) {
|
|
|
|
|
|
|
|
var oldRange = oldSelection.getRangeAt && oldSelection.getRangeAt(0);
|
|
|
|
|
|
|
|
oldRangeObj = {
|
|
|
|
|
|
|
|
start: oldRange.startContainer,
|
|
|
|
|
|
|
|
startO: oldRange.startOffset,
|
|
|
|
|
|
|
|
end: oldRange.endContainer,
|
|
|
|
|
|
|
|
endO: oldRange.endOffset
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Store existing input form in memory
|
|
|
|
var $oldInput = Env.$container.find('.cp-comment-form').detach();
|
|
|
|
var $oldInput = Env.$container.find('.cp-comment-form').detach();
|
|
|
|
if ($oldInput.length !== 1) { $oldInput = undefined; }
|
|
|
|
if ($oldInput.length !== 1) { $oldInput = undefined; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Remove everything
|
|
|
|
Env.$container.html('');
|
|
|
|
Env.$container.html('');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// "show" tells us if we need to display the "comments" column or not
|
|
|
|
var show = false;
|
|
|
|
var show = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Add invisible label for accessibility tools
|
|
|
|
|
|
|
|
var label = h('label#cp-comments-label', Messages.comments_comment);
|
|
|
|
|
|
|
|
Env.$container.append(label);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// If we were adding a new comment, redraw our form
|
|
|
|
if ($oldInput && !$oldInput.attr('data-uid')) {
|
|
|
|
if ($oldInput && !$oldInput.attr('data-uid')) {
|
|
|
|
show = true;
|
|
|
|
show = true;
|
|
|
|
Env.$container.append($oldInput);
|
|
|
|
Env.$container.append($oldInput);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var order = Env.$inner.find('comment').map(function (i, el) {
|
|
|
|
var userData = Env.metadataMgr.getUserData();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Get all the comment threads in their order in the pad
|
|
|
|
|
|
|
|
var threads = Env.$inner.find('comment').map(function (i, el) {
|
|
|
|
return el.getAttribute('data-uid');
|
|
|
|
return el.getAttribute('data-uid');
|
|
|
|
}).toArray();
|
|
|
|
}).toArray();
|
|
|
|
var done = [];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
order.forEach(function (key) {
|
|
|
|
|
|
|
|
// Avoir duplicates
|
|
|
|
|
|
|
|
if (done.indexOf(key) !== -1) { return; }
|
|
|
|
|
|
|
|
done.push(key);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Draw all comment threads
|
|
|
|
|
|
|
|
Util.deduplicateString(threads).forEach(function (key) {
|
|
|
|
|
|
|
|
// Get thread data
|
|
|
|
var obj = Env.comments.data[key];
|
|
|
|
var obj = Env.comments.data[key];
|
|
|
|
if (!obj || obj.deleted || !Array.isArray(obj.m) || !obj.m.length) {
|
|
|
|
if (!obj || obj.d || !Array.isArray(obj.m) || !obj.m.length) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// If at least one thread is visible, display the "comments" column
|
|
|
|
show = true;
|
|
|
|
show = true;
|
|
|
|
|
|
|
|
|
|
|
|
var content = [];
|
|
|
|
var content = [];
|
|
|
|
obj.m.forEach(function (msg, i) {
|
|
|
|
var $div;
|
|
|
|
var author = (Env.comments.authors || {})[msg.u] || {};
|
|
|
|
var $actions;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Draw all messages for this thread
|
|
|
|
|
|
|
|
(obj.m || []).forEach(function (msg, i) {
|
|
|
|
|
|
|
|
var replyCls = i === 0 ? '' : '.cp-comment-reply';
|
|
|
|
|
|
|
|
if (msg.d) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
content.push(h('div.cp-comment.cp-comment-deleted'+replyCls,
|
|
|
|
|
|
|
|
Messages.comments_deleted));
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
var author = typeof(msg.u) === "number" ?
|
|
|
|
|
|
|
|
((Env.comments.authors || {})[msg.u] || {}) :
|
|
|
|
|
|
|
|
{ name: msg.u };
|
|
|
|
var name = Util.fixHTML(author.name || Messages.anonymous);
|
|
|
|
var name = Util.fixHTML(author.name || Messages.anonymous);
|
|
|
|
var date = new Date(msg.t);
|
|
|
|
var date = new Date(msg.t);
|
|
|
|
var avatar = h('span.cp-avatar');
|
|
|
|
var avatar = h('span.cp-avatar');
|
|
|
@ -196,17 +389,109 @@ define([
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
content.push(h('div.cp-comment'+(i === 0 ? '' : '.cp-comment-reply'), [
|
|
|
|
// Build sanitized html with mentions
|
|
|
|
|
|
|
|
var m = h('div.cp-comment-content');
|
|
|
|
|
|
|
|
m.innerHTML = msg.m;
|
|
|
|
|
|
|
|
var $m = $(m);
|
|
|
|
|
|
|
|
$m.find('> *:not(span.cp-mentions)').remove();
|
|
|
|
|
|
|
|
$m.find('span.cp-mentions').each(function (i, el) {
|
|
|
|
|
|
|
|
var $el = $(el);
|
|
|
|
|
|
|
|
var name = $el.attr('data-name');
|
|
|
|
|
|
|
|
var avatarUrl = $el.attr('data-avatar');
|
|
|
|
|
|
|
|
var profile = $el.attr('data-profile');
|
|
|
|
|
|
|
|
if (!name && !avatarUrl && !profile) {
|
|
|
|
|
|
|
|
$el.remove();
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanMentions($el);
|
|
|
|
|
|
|
|
var avatar = h('span.cp-avatar');
|
|
|
|
|
|
|
|
Env.common.displayAvatar($(avatar), avatarUrl, name);
|
|
|
|
|
|
|
|
$el.append([
|
|
|
|
|
|
|
|
avatar,
|
|
|
|
|
|
|
|
h('span.cp-mentions-name', name)
|
|
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
if (profile) {
|
|
|
|
|
|
|
|
$el.attr('tabindex', 1);
|
|
|
|
|
|
|
|
$el.addClass('cp-mentions-clickable').click(function (e) {
|
|
|
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
|
|
|
Env.common.openURL(Hash.hashToHref(profile, 'profile'));
|
|
|
|
|
|
|
|
}).focus(function (e) {
|
|
|
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// edited state
|
|
|
|
|
|
|
|
var edited;
|
|
|
|
|
|
|
|
if (msg.e) {
|
|
|
|
|
|
|
|
edited = h('div.cp-comment-edited', Messages.comments_edited);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var container;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Add edit button when applicable (last message of the thread, written by ourselves)
|
|
|
|
|
|
|
|
var edit;
|
|
|
|
|
|
|
|
if (i === (obj.m.length -1) && author.curvePublic === userData.curvePublic) {
|
|
|
|
|
|
|
|
edit = h('span.cp-comment-edit', {
|
|
|
|
|
|
|
|
tabindex:1,
|
|
|
|
|
|
|
|
title: Messages.clickToEdit
|
|
|
|
|
|
|
|
}, h('i.fa.fa-pencil'));
|
|
|
|
|
|
|
|
$(edit).click(function (e) {
|
|
|
|
|
|
|
|
Env.$container.find('.cp-comment-active').removeClass('cp-comment-active');
|
|
|
|
|
|
|
|
$div.addClass('cp-comment-active');
|
|
|
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
|
|
|
Env.$container.find('.cp-comment-form').remove();
|
|
|
|
|
|
|
|
if ($actions) { $actions.hide(); }
|
|
|
|
|
|
|
|
var form = getCommentForm(Env, key, function (val) {
|
|
|
|
|
|
|
|
// Show the "reply" and "resolve" buttons again
|
|
|
|
|
|
|
|
$(form).closest('.cp-comment-container')
|
|
|
|
|
|
|
|
.find('.cp-comment-actions').css('display', '');
|
|
|
|
|
|
|
|
$(form).remove();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (typeof(val) === "undefined") { return; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var obj = Env.comments.data[key];
|
|
|
|
|
|
|
|
if (!obj || !Array.isArray(obj.m)) { return; }
|
|
|
|
|
|
|
|
var msg = obj.m[i];
|
|
|
|
|
|
|
|
if (!msg) { return; }
|
|
|
|
|
|
|
|
// i is our index
|
|
|
|
|
|
|
|
if (val === false) {
|
|
|
|
|
|
|
|
msg.d = 1;
|
|
|
|
|
|
|
|
if (container) {
|
|
|
|
|
|
|
|
$(container).addClass('cp-comment-deleted')
|
|
|
|
|
|
|
|
.html(Messages.comments_deleted);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (obj.m.length === 1) {
|
|
|
|
|
|
|
|
delete Env.comments.data[key];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
msg.e = 1;
|
|
|
|
|
|
|
|
msg.m = val;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Send to chainpad
|
|
|
|
|
|
|
|
updateMetadata(Env);
|
|
|
|
|
|
|
|
Env.framework.localChange();
|
|
|
|
|
|
|
|
}, m.innerHTML);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!$div) { return; }
|
|
|
|
|
|
|
|
$div.append(form);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Add the comment
|
|
|
|
|
|
|
|
content.push(container = h('div.cp-comment'+replyCls, [
|
|
|
|
h('div.cp-comment-header', [
|
|
|
|
h('div.cp-comment-header', [
|
|
|
|
avatar,
|
|
|
|
avatar,
|
|
|
|
h('span.cp-comment-metadata', [
|
|
|
|
h('span.cp-comment-metadata', [
|
|
|
|
h('span.cp-comment-author', name),
|
|
|
|
h('span.cp-comment-author', name),
|
|
|
|
h('span.cp-comment-time', date.toLocaleString())
|
|
|
|
h('span.cp-comment-time', date.toLocaleString())
|
|
|
|
])
|
|
|
|
|
|
|
|
]),
|
|
|
|
]),
|
|
|
|
h('div.cp-comment-content', [
|
|
|
|
edit
|
|
|
|
msg.m
|
|
|
|
]),
|
|
|
|
])
|
|
|
|
m,
|
|
|
|
|
|
|
|
edited
|
|
|
|
]));
|
|
|
|
]));
|
|
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
});
|
|
|
@ -229,22 +514,23 @@ define([
|
|
|
|
reply,
|
|
|
|
reply,
|
|
|
|
resolve
|
|
|
|
resolve
|
|
|
|
]));
|
|
|
|
]));
|
|
|
|
var $actions = $(actions);
|
|
|
|
$actions = $(actions);
|
|
|
|
|
|
|
|
|
|
|
|
var div;
|
|
|
|
var div;
|
|
|
|
Env.$container.append(div = h('div.cp-comment-container', {
|
|
|
|
Env.$container.append(div = h('div.cp-comment-container', {
|
|
|
|
'data-uid': key,
|
|
|
|
'data-uid': key,
|
|
|
|
tabindex: 1
|
|
|
|
tabindex: 1
|
|
|
|
}, content));
|
|
|
|
}, content));
|
|
|
|
var $div = $(div);
|
|
|
|
$div = $(div);
|
|
|
|
|
|
|
|
|
|
|
|
$(reply).click(function (e) {
|
|
|
|
$(reply).click(function (e) {
|
|
|
|
e.stopPropagation();
|
|
|
|
e.stopPropagation();
|
|
|
|
$actions.hide();
|
|
|
|
$actions.hide();
|
|
|
|
var form = getCommentForm(Env, key, function (val) {
|
|
|
|
var form = getCommentForm(Env, key, function (val) {
|
|
|
|
$(form).remove();
|
|
|
|
// Show the "reply" and "resolve" buttons again
|
|
|
|
$(form).closest('.cp-comment-container')
|
|
|
|
$(form).closest('.cp-comment-container')
|
|
|
|
.find('.cp-comment-actions').css('display', '');
|
|
|
|
.find('.cp-comment-actions').css('display', '');
|
|
|
|
|
|
|
|
$(form).remove();
|
|
|
|
|
|
|
|
|
|
|
|
if (!val) { return; }
|
|
|
|
if (!val) { return; }
|
|
|
|
var obj = Env.comments.data[key];
|
|
|
|
var obj = Env.comments.data[key];
|
|
|
@ -257,23 +543,36 @@ define([
|
|
|
|
}).join('\n');
|
|
|
|
}).join('\n');
|
|
|
|
|
|
|
|
|
|
|
|
// Push the reply
|
|
|
|
// Push the reply
|
|
|
|
var myId = updateAuthorData(Env);
|
|
|
|
var user = updateAuthorData(Env);
|
|
|
|
obj.m.push({
|
|
|
|
obj.m.push({
|
|
|
|
u: myId,
|
|
|
|
u: user, // id (number) or name (string)
|
|
|
|
t: +new Date(),
|
|
|
|
t: +new Date(),
|
|
|
|
m: val,
|
|
|
|
m: val,
|
|
|
|
v: value
|
|
|
|
v: value
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Notify other users
|
|
|
|
|
|
|
|
sendReplyNotification(Env, key);
|
|
|
|
|
|
|
|
|
|
|
|
// Send to chainpad
|
|
|
|
// Send to chainpad
|
|
|
|
updateMetadata(Env);
|
|
|
|
updateMetadata(Env);
|
|
|
|
Env.framework.localChange();
|
|
|
|
Env.framework.localChange();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
$div.append(form);
|
|
|
|
$div.append(form);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Make sure the submit button is visible: scroll by the height of the form
|
|
|
|
|
|
|
|
setTimeout(function () {
|
|
|
|
|
|
|
|
var yContainer = Env.$container[0].getBoundingClientRect().bottom;
|
|
|
|
|
|
|
|
var yActions = form.getBoundingClientRect().bottom;
|
|
|
|
|
|
|
|
if (yActions > yContainer) {
|
|
|
|
|
|
|
|
Env.$container.scrollTop(Env.$container.scrollTop() + 55);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
UI.confirmButton(resolve, {
|
|
|
|
UI.confirmButton(resolve, {
|
|
|
|
classes: 'btn-danger-alt'
|
|
|
|
classes: 'btn-danger'
|
|
|
|
}, function () {
|
|
|
|
}, function () {
|
|
|
|
// Delete the comment
|
|
|
|
// Delete the comment
|
|
|
|
delete Env.comments.data[key];
|
|
|
|
delete Env.comments.data[key];
|
|
|
@ -291,21 +590,24 @@ define([
|
|
|
|
|
|
|
|
|
|
|
|
// Scroll into view
|
|
|
|
// Scroll into view
|
|
|
|
if (!$last.length) { return; }
|
|
|
|
if (!$last.length) { return; }
|
|
|
|
var size = Env.$inner.outerHeight();
|
|
|
|
var visible = isVisible($last[0], Env.$inner);
|
|
|
|
var pos = $last[0].getBoundingClientRect();
|
|
|
|
|
|
|
|
var visible = (pos.y + pos.height) < size;
|
|
|
|
|
|
|
|
if (!visible) { $last[0].scrollIntoView(); }
|
|
|
|
if (!visible) { $last[0].scrollIntoView(); }
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
$div.on('click focus', function () {
|
|
|
|
$div.on('click focus', function (e) {
|
|
|
|
|
|
|
|
// Prevent the click event to propagate if we're already selected
|
|
|
|
|
|
|
|
// The propagation to #cp-app-pad-inner would trigger the "unselect" handler
|
|
|
|
|
|
|
|
e.stopPropagation();
|
|
|
|
if ($div.hasClass('cp-comment-active')) { return; }
|
|
|
|
if ($div.hasClass('cp-comment-active')) { return; }
|
|
|
|
Env.$container.find('.cp-comment-active').removeClass('cp-comment-active');
|
|
|
|
Env.$container.find('.cp-comment-active').removeClass('cp-comment-active');
|
|
|
|
$div.addClass('cp-comment-active');
|
|
|
|
$div.addClass('cp-comment-active');
|
|
|
|
div.scrollIntoView();
|
|
|
|
|
|
|
|
$actions.css('display', '');
|
|
|
|
$actions.css('display', '');
|
|
|
|
Env.$container.find('.cp-comment-form').remove();
|
|
|
|
Env.$container.find('.cp-comment-form').remove();
|
|
|
|
|
|
|
|
|
|
|
|
focusContent();
|
|
|
|
focusContent();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var visible = isVisible(div, Env.$container);
|
|
|
|
|
|
|
|
if (!visible) { div.scrollIntoView(); }
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if ($oldInput && $oldInput.attr('data-uid') === key) {
|
|
|
|
if ($oldInput && $oldInput.attr('data-uid') === key) {
|
|
|
@ -317,6 +619,19 @@ define([
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Restore selection
|
|
|
|
|
|
|
|
if (oldRangeObj) {
|
|
|
|
|
|
|
|
setTimeout(function () {
|
|
|
|
|
|
|
|
if (!oldRangeObj) { return; }
|
|
|
|
|
|
|
|
var range = document.createRange();
|
|
|
|
|
|
|
|
range.setStart(oldRangeObj.start, oldRangeObj.startO);
|
|
|
|
|
|
|
|
range.setEnd(oldRangeObj.end, oldRangeObj.endO);
|
|
|
|
|
|
|
|
var sel = window.getSelection();
|
|
|
|
|
|
|
|
sel.removeAllRanges();
|
|
|
|
|
|
|
|
sel.addRange(range);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (show) {
|
|
|
|
if (show) {
|
|
|
|
Env.$container.show();
|
|
|
|
Env.$container.show();
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@ -334,10 +649,22 @@ define([
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (Env.ready === 0) {
|
|
|
|
if (Env.ready === 0) {
|
|
|
|
Env.ready = true;
|
|
|
|
Env.ready = true;
|
|
|
|
|
|
|
|
updateAuthorData(Env, function () {
|
|
|
|
|
|
|
|
changed = true;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
// On ready, if our user data have changed or if we've added the initial structure
|
|
|
|
|
|
|
|
// of the comments, push the changes
|
|
|
|
if (changed) {
|
|
|
|
if (changed) {
|
|
|
|
updateMetadata(Env);
|
|
|
|
updateMetadata(Env);
|
|
|
|
Env.framework.localChange();
|
|
|
|
Env.framework.localChange();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (Env.ready) {
|
|
|
|
|
|
|
|
// Everytime there is a metadata change, check if our user data have changed
|
|
|
|
|
|
|
|
// and push the updates if necessary
|
|
|
|
|
|
|
|
updateAuthorData(Env, function () {
|
|
|
|
|
|
|
|
updateMetadata(Env);
|
|
|
|
|
|
|
|
Env.framework.localChange();
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
redrawComments(Env);
|
|
|
|
redrawComments(Env);
|
|
|
|
};
|
|
|
|
};
|
|
|
@ -353,7 +680,7 @@ define([
|
|
|
|
|
|
|
|
|
|
|
|
// If there is no comment stored in the metadata, abort
|
|
|
|
// If there is no comment stored in the metadata, abort
|
|
|
|
var comments = Object.keys(Env.comments.data || {}).filter(function (id) {
|
|
|
|
var comments = Object.keys(Env.comments.data || {}).filter(function (id) {
|
|
|
|
return !Env.comments.data[id].deleted;
|
|
|
|
return !Env.comments.data[id].d;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
var changed = false;
|
|
|
|
var changed = false;
|
|
|
@ -378,8 +705,8 @@ define([
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// If this comment was deleted, we're probably using "undo" to restore it:
|
|
|
|
// If this comment was deleted, we're probably using "undo" to restore it:
|
|
|
|
// remove the "deleted" state and continue
|
|
|
|
// remove the "deleted" state and continue
|
|
|
|
if (obj.deleted) {
|
|
|
|
if (obj.d) {
|
|
|
|
delete obj.deleted;
|
|
|
|
delete obj.d;
|
|
|
|
changed = true;
|
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return id;
|
|
|
|
return id;
|
|
|
@ -397,7 +724,7 @@ define([
|
|
|
|
// comment has been deleted
|
|
|
|
// comment has been deleted
|
|
|
|
var data = Env.comments.data[uid];
|
|
|
|
var data = Env.comments.data[uid];
|
|
|
|
if (!data) { return; }
|
|
|
|
if (!data) { return; }
|
|
|
|
data.deleted = true;
|
|
|
|
data.d = 1;
|
|
|
|
//delete Env.comments.data[uid];
|
|
|
|
//delete Env.comments.data[uid];
|
|
|
|
changed = true;
|
|
|
|
changed = true;
|
|
|
|
});
|
|
|
|
});
|
|
|
@ -440,7 +767,8 @@ define([
|
|
|
|
node: node,
|
|
|
|
node: node,
|
|
|
|
button: button
|
|
|
|
button: button
|
|
|
|
};
|
|
|
|
};
|
|
|
|
$(button).click(function () {
|
|
|
|
$(button).click(function (e) {
|
|
|
|
|
|
|
|
e.stopPropagation();
|
|
|
|
Env.editor.execCommand('comment');
|
|
|
|
Env.editor.execCommand('comment');
|
|
|
|
Env.bubble = undefined;
|
|
|
|
Env.bubble = undefined;
|
|
|
|
});
|
|
|
|
});
|
|
|
@ -462,6 +790,8 @@ define([
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Remove active class on other comments
|
|
|
|
|
|
|
|
Env.$container.find('.cp-comment-active').removeClass('cp-comment-active');
|
|
|
|
Env.$container.find('.cp-comment-form').remove();
|
|
|
|
Env.$container.find('.cp-comment-form').remove();
|
|
|
|
var form = getCommentForm(Env, false, function (val) {
|
|
|
|
var form = getCommentForm(Env, false, function (val) {
|
|
|
|
$(form).remove();
|
|
|
|
$(form).remove();
|
|
|
@ -477,10 +807,10 @@ define([
|
|
|
|
// Don't override existing data
|
|
|
|
// Don't override existing data
|
|
|
|
if (Env.comments.data[uid]) { return; }
|
|
|
|
if (Env.comments.data[uid]) { return; }
|
|
|
|
|
|
|
|
|
|
|
|
var myId = updateAuthorData(Env);
|
|
|
|
var user = updateAuthorData(Env);
|
|
|
|
Env.comments.data[uid] = {
|
|
|
|
Env.comments.data[uid] = {
|
|
|
|
m: [{
|
|
|
|
m: [{
|
|
|
|
u: myId,
|
|
|
|
u: user, // Id or name
|
|
|
|
t: +new Date(),
|
|
|
|
t: +new Date(),
|
|
|
|
m: val,
|
|
|
|
m: val,
|
|
|
|
v: canonicalize(Env.editor.getSelection().getSelectedText())
|
|
|
|
v: canonicalize(Env.editor.getSelection().getSelectedText())
|
|
|
@ -533,7 +863,7 @@ define([
|
|
|
|
// Clear data
|
|
|
|
// Clear data
|
|
|
|
var data = (Env.comments && Env.comments.data) || {};
|
|
|
|
var data = (Env.comments && Env.comments.data) || {};
|
|
|
|
Object.keys(data).forEach(function (uid) {
|
|
|
|
Object.keys(data).forEach(function (uid) {
|
|
|
|
if (data[uid].deleted) { delete data[uid]; }
|
|
|
|
if (data[uid].d) { delete data[uid]; }
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// Commit
|
|
|
|
// Commit
|
|
|
@ -545,21 +875,39 @@ define([
|
|
|
|
var Env = cfg;
|
|
|
|
var Env = cfg;
|
|
|
|
Env.comments = Util.clone(COMMENTS);
|
|
|
|
Env.comments = Util.clone(COMMENTS);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var ro = cfg.framework.isReadOnly();
|
|
|
|
|
|
|
|
var onEditableChange = function (unlocked) {
|
|
|
|
|
|
|
|
Env.$container.removeClass('cp-comments-readonly');
|
|
|
|
|
|
|
|
if (ro || !unlocked) {
|
|
|
|
|
|
|
|
Env.$container.addClass('cp-comments-readonly');
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
cfg.framework.onEditableChange(onEditableChange);
|
|
|
|
|
|
|
|
onEditableChange();
|
|
|
|
|
|
|
|
|
|
|
|
addAddCommentHandler(Env);
|
|
|
|
addAddCommentHandler(Env);
|
|
|
|
|
|
|
|
|
|
|
|
// Unselect comment when clicking outside
|
|
|
|
// Unselect comment when clicking outside
|
|
|
|
$(window).click(function (e) {
|
|
|
|
$(window).click(function (e) {
|
|
|
|
if ($(e.target).closest('.cp-comment-container').length) {
|
|
|
|
var $target = $(e.target);
|
|
|
|
return;
|
|
|
|
if (!$target.length) { return; }
|
|
|
|
}
|
|
|
|
if ($target.is('.cp-comment-container')) { return; }
|
|
|
|
|
|
|
|
if ($target.closest('.cp-comment-container').length) { return; }
|
|
|
|
|
|
|
|
if ($target.closest('.ui-autocomplete').length) { return; }
|
|
|
|
|
|
|
|
// Add comment button? don't remove anything because this handler is called after
|
|
|
|
|
|
|
|
// the button action
|
|
|
|
|
|
|
|
if ($target.is('.cke_button__comment')) { return; }
|
|
|
|
|
|
|
|
if ($target.closest('.cke_button__comment').length) { return; }
|
|
|
|
Env.$container.find('.cp-comment-active').removeClass('cp-comment-active');
|
|
|
|
Env.$container.find('.cp-comment-active').removeClass('cp-comment-active');
|
|
|
|
Env.$inner.find('comment.active').removeClass('active');
|
|
|
|
Env.$inner.find('comment.active').removeClass('active');
|
|
|
|
|
|
|
|
Env.$container.find('.cp-comment-form').remove();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
// Unselect comment when clicking on another part of the doc
|
|
|
|
// Unselect comment when clicking on another part of the doc
|
|
|
|
Env.$inner.on('click', function (e) {
|
|
|
|
Env.$inner.on('click', function (e) {
|
|
|
|
if ($(e.target).closest('comment').length) { return; }
|
|
|
|
if ($(e.target).closest('comment').length) { return; }
|
|
|
|
Env.$container.find('.cp-comment-active').removeClass('cp-comment-active');
|
|
|
|
Env.$container.find('.cp-comment-active').removeClass('cp-comment-active');
|
|
|
|
Env.$inner.find('comment.active').removeClass('active');
|
|
|
|
Env.$inner.find('comment.active').removeClass('active');
|
|
|
|
|
|
|
|
Env.$container.find('.cp-comment-form').remove();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
Env.$inner.on('click', 'comment', function (e) {
|
|
|
|
Env.$inner.on('click', 'comment', function (e) {
|
|
|
|
var $comment = $(e.target);
|
|
|
|
var $comment = $(e.target);
|
|
|
|